1use std::fmt;
4
5pub type Oid = u32;
7
8pub const BOOLOID: Oid = 16;
10pub const BYTEAOID: Oid = 17;
12pub const NAMEOID: Oid = 19;
14pub const INT8OID: Oid = 20;
16pub const INT2OID: Oid = 21;
18pub const INT4OID: Oid = 23;
20pub const TEXTOID: Oid = 25;
22pub const OIDOID: Oid = 26;
24pub const JSONOID: Oid = 114;
26pub const FLOAT4OID: Oid = 700;
28pub const FLOAT8OID: Oid = 701;
30pub const INETOID: Oid = 869;
32pub const CIDROID: Oid = 650;
34pub const VARCHAROID: Oid = 1043;
36pub const BPCHAROID: Oid = 1042;
38pub const DATEOID: Oid = 1082;
40pub const TIMEOID: Oid = 1083;
42pub const TIMESTAMPOID: Oid = 1114;
44pub const TIMESTAMPTZOID: Oid = 1184;
46pub const INTERVALOID: Oid = 1186;
48pub const TIMETZOID: Oid = 1266;
50pub const NUMERICOID: Oid = 1700;
52pub const UUIDOID: Oid = 2950;
54pub const JSONBOID: Oid = 3802;
56
57pub const NAME_ARRAY_OID: Oid = 1003;
59pub const BPCHAR_ARRAY_OID: Oid = 1014;
61pub const INT2_ARRAY_OID: Oid = 1005;
63pub const INT4_ARRAY_OID: Oid = 1007;
65pub const TEXT_ARRAY_OID: Oid = 1009;
67pub const INT8_ARRAY_OID: Oid = 1016;
69pub const FLOAT4_ARRAY_OID: Oid = 1021;
71pub const FLOAT8_ARRAY_OID: Oid = 1022;
73pub const BOOL_ARRAY_OID: Oid = 1000;
75pub const BYTEA_ARRAY_OID: Oid = 1001;
77pub const UUID_ARRAY_OID: Oid = 2951;
79pub const TIMESTAMPTZ_ARRAY_OID: Oid = 1185;
81pub const DATE_ARRAY_OID: Oid = 1182;
83pub const TIMESTAMP_ARRAY_OID: Oid = 1115;
85pub const VARCHAR_ARRAY_OID: Oid = 1015;
87pub const JSON_ARRAY_OID: Oid = 199;
89pub const INET_ARRAY_OID: Oid = 1041;
91pub const CIDR_ARRAY_OID: Oid = 651;
93pub const TIME_ARRAY_OID: Oid = 1183;
95pub const TIMETZ_ARRAY_OID: Oid = 1270;
97pub const INTERVAL_ARRAY_OID: Oid = 1187;
99pub const NUMERIC_ARRAY_OID: Oid = 1231;
101pub const JSONB_ARRAY_OID: Oid = 3807;
103
104#[derive(Debug, Clone, Copy, PartialEq, Eq)]
106pub enum Format {
107 Text,
109 Binary,
111}
112
113impl Format {
114 pub const fn code(self) -> i16 {
116 match self {
117 Format::Text => 0,
118 Format::Binary => 1,
119 }
120 }
121}
122
123pub const fn array_oid(elem: Oid) -> Option<Oid> {
129 Some(match elem {
130 INT2OID => INT2_ARRAY_OID,
131 INT4OID => INT4_ARRAY_OID,
132 INT8OID => INT8_ARRAY_OID,
133 FLOAT4OID => FLOAT4_ARRAY_OID,
134 FLOAT8OID => FLOAT8_ARRAY_OID,
135 BOOLOID => BOOL_ARRAY_OID,
136 TEXTOID => TEXT_ARRAY_OID,
137 NAMEOID => NAME_ARRAY_OID,
138 VARCHAROID => VARCHAR_ARRAY_OID,
139 BPCHAROID => BPCHAR_ARRAY_OID,
140 BYTEAOID => BYTEA_ARRAY_OID,
141 UUIDOID => UUID_ARRAY_OID,
142 JSONOID => JSON_ARRAY_OID,
143 JSONBOID => JSONB_ARRAY_OID,
144 INETOID => INET_ARRAY_OID,
145 CIDROID => CIDR_ARRAY_OID,
146 DATEOID => DATE_ARRAY_OID,
147 TIMEOID => TIME_ARRAY_OID,
148 TIMETZOID => TIMETZ_ARRAY_OID,
149 TIMESTAMPTZOID => TIMESTAMPTZ_ARRAY_OID,
150 TIMESTAMPOID => TIMESTAMP_ARRAY_OID,
151 INTERVALOID => INTERVAL_ARRAY_OID,
152 NUMERICOID => NUMERIC_ARRAY_OID,
153 _ => return None,
154 })
155}
156
157pub const fn array_oid_checked(elem: Oid) -> Oid {
164 match array_oid(elem) {
165 Some(oid) => oid,
166 None => panic!("this type has no PostgreSQL array type"),
167 }
168}
169
170#[derive(Debug, Clone, Copy, PartialEq, Eq)]
172pub struct PgType {
173 pub oid: Oid,
175 pub name: &'static str,
177}
178
179impl PgType {
180 pub const fn new(oid: Oid, name: &'static str) -> Self {
182 PgType {
183 oid,
184 name,
185 }
186 }
187
188 pub const fn array_of(self) -> PgType {
195 let Some(oid) = array_oid(self.oid) else {
196 panic!("this type has no array type")
197 };
198 PgType {
199 oid,
200 name: "",
201 }
202 }
203}
204
205impl fmt::Display for PgType {
206 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
207 write!(f, "{}", self.name)
208 }
209}
210
211pub static INT2: PgType = PgType::new(INT2OID, "int2");
213pub static INT4: PgType = PgType::new(INT4OID, "int4");
215pub static INT8: PgType = PgType::new(INT8OID, "int8");
217pub static FLOAT4: PgType = PgType::new(FLOAT4OID, "float4");
219pub static FLOAT8: PgType = PgType::new(FLOAT8OID, "float8");
221pub static BOOL: PgType = PgType::new(BOOLOID, "bool");
223pub static TEXT: PgType = PgType::new(TEXTOID, "text");
225pub static VARCHAR: PgType = PgType::new(VARCHAROID, "varchar");
227pub static BYTEA: PgType = PgType::new(BYTEAOID, "bytea");
229pub static UUID: PgType = PgType::new(UUIDOID, "uuid");
231pub static JSON: PgType = PgType::new(JSONOID, "json");
233pub static JSONB: PgType = PgType::new(JSONBOID, "jsonb");
235pub static INET: PgType = PgType::new(INETOID, "inet");
237pub static CIDR: PgType = PgType::new(CIDROID, "cidr");
239pub static DATE: PgType = PgType::new(DATEOID, "date");
241pub static TIME: PgType = PgType::new(TIMEOID, "time");
243pub static TIMETZ: PgType = PgType::new(TIMETZOID, "timetz");
245pub static TIMESTAMP: PgType = PgType::new(TIMESTAMPOID, "timestamp");
247pub static TIMESTAMPTZ: PgType = PgType::new(TIMESTAMPTZOID, "timestamptz");
249pub static INTERVAL: PgType = PgType::new(INTERVALOID, "interval");
251pub static NUMERIC: PgType = PgType::new(NUMERICOID, "numeric");
253
254pub const fn array_element(oid: Oid) -> Option<PgType> {
256 let elem = match oid {
257 INT2_ARRAY_OID => INT2OID,
258 INT4_ARRAY_OID => INT4OID,
259 INT8_ARRAY_OID => INT8OID,
260 FLOAT4_ARRAY_OID => FLOAT4OID,
261 FLOAT8_ARRAY_OID => FLOAT8OID,
262 BOOL_ARRAY_OID => BOOLOID,
263 TEXT_ARRAY_OID => TEXTOID,
264 NAME_ARRAY_OID => NAMEOID,
265 VARCHAR_ARRAY_OID => VARCHAROID,
266 BPCHAR_ARRAY_OID => BPCHAROID,
267 BYTEA_ARRAY_OID => BYTEAOID,
268 UUID_ARRAY_OID => UUIDOID,
269 JSON_ARRAY_OID => JSONOID,
270 JSONB_ARRAY_OID => JSONBOID,
271 INET_ARRAY_OID => INETOID,
272 CIDR_ARRAY_OID => CIDROID,
273 DATE_ARRAY_OID => DATEOID,
274 TIME_ARRAY_OID => TIMEOID,
275 TIMETZ_ARRAY_OID => TIMETZOID,
276 TIMESTAMPTZ_ARRAY_OID => TIMESTAMPTZOID,
277 TIMESTAMP_ARRAY_OID => TIMESTAMPOID,
278 INTERVAL_ARRAY_OID => INTERVALOID,
279 NUMERIC_ARRAY_OID => NUMERICOID,
280 _ => return None,
281 };
282 Some(PgType::new(elem, ""))
283}
284
285pub const fn is_array(oid: Oid) -> bool {
287 array_element(oid).is_some()
288}
289
290#[cfg(test)]
291mod tests {
292 use super::*;
293
294 #[test]
295 fn array_of_known() {
296 assert_eq!(INT2.array_of().oid, INT2_ARRAY_OID);
297 assert_eq!(INT4.array_of().oid, INT4_ARRAY_OID);
298 assert_eq!(TEXT.array_of().oid, TEXT_ARRAY_OID);
299 assert_eq!(VARCHAR.array_of().oid, VARCHAR_ARRAY_OID);
300 assert_eq!(UUID.array_of().oid, UUID_ARRAY_OID);
301 assert_eq!(TIMESTAMPTZ.array_of().oid, TIMESTAMPTZ_ARRAY_OID);
302 assert_eq!(array_oid(INTERVALOID), Some(INTERVAL_ARRAY_OID));
303 assert_eq!(array_oid(JSONBOID), Some(JSONB_ARRAY_OID));
304 assert_eq!(array_oid(NAMEOID), Some(NAME_ARRAY_OID));
305 }
306
307 #[test]
308 fn unknown_element_has_no_array_oid() {
309 assert_eq!(array_oid(4242), None);
310 }
311
312 #[test]
313 fn element_roundtrip() {
314 assert_eq!(array_element(INT2_ARRAY_OID).unwrap().oid, INT2OID);
315 assert!(array_element(TEXTOID).is_none());
316 assert!(is_array(UUID_ARRAY_OID));
317 assert!(!is_array(UUIDOID));
318 }
319}