Skip to main content

bsql_driver_postgres/
oid_map.rs

1//! Single-source OID mapping: Rust type string -> PostgreSQL OID.
2//!
3//! This is the canonical source of truth for the Rust type -> PG OID mapping.
4//! `bsql-core::types::default_pg_oid_for_rust_type` delegates to this function.
5
6/// Map a Rust type string to the default PostgreSQL OID for that type.
7///
8/// Returns the OID that a Rust type would naturally correspond to in PG.
9/// Returns 0 for unknown types (let PG infer from context).
10///
11/// Single source of truth for Rust type -> PostgreSQL OID mapping.
12///
13/// Used by:
14/// - `Encode::pg_type_oid()` and `Encode::type_oid()` (runtime delegation)
15/// - The proc macro's two-phase PREPARE (Phase 1 sends these OIDs, via bsql-core re-export)
16///
17/// Every OID value in the codebase should originate from this function.
18pub fn default_pg_oid_for_rust_type(rust_type: &str) -> u32 {
19    // Strip Option<> wrapper — Option<T> is nullable T, same PG type as T.
20    let ty = strip_option_wrapper(rust_type);
21    match ty {
22        // Scalars
23        "bool" => 16,
24        "i16" => 21,
25        "i32" => 23,
26        "i64" => 20,
27        "f32" => 700,
28        "f64" => 701,
29        "&str" | "String" => 25,
30        "u32" => 26,
31        "&[u8]" | "Vec<u8>" => 17,
32        // Arrays
33        "&[bool]" | "Vec<bool>" => 1000,
34        "&[i16]" | "Vec<i16>" => 1005,
35        "&[i32]" | "Vec<i32>" => 1007,
36        "&[i64]" | "Vec<i64>" => 1016,
37        "&[f32]" | "Vec<f32>" => 1021,
38        "&[f64]" | "Vec<f64>" => 1022,
39        "&[&str]" | "Vec<String>" | "&[String]" => 1009,
40        "&[&[u8]]" | "Vec<Vec<u8>>" => 1001,
41        // Feature-gated types
42        "uuid::Uuid" | "Uuid" => 2950,
43        "time::OffsetDateTime" | "OffsetDateTime" => 1184,
44        "time::Date" => 1082,
45        "time::Time" => 1083,
46        "time::PrimitiveDateTime" | "PrimitiveDateTime" => 1114,
47        "chrono::NaiveDateTime" | "NaiveDateTime" => 1114,
48        "chrono::DateTime<chrono::Utc>" | "DateTime<Utc>" => 1184,
49        "chrono::NaiveDate" | "NaiveDate" => 1082,
50        "chrono::NaiveTime" | "NaiveTime" => 1083,
51        "rust_decimal::Decimal" | "Decimal" => 1700,
52        _ => 0, // unknown → let PG infer
53    }
54}
55
56/// Strip `Option<...>` wrapper from a type string, returning the inner type.
57/// If the type is not `Option<T>`, returns it unchanged.
58fn strip_option_wrapper(ty: &str) -> &str {
59    if let Some(inner) = ty.strip_prefix("Option<") {
60        if let Some(inner) = inner.strip_suffix('>') {
61            return inner;
62        }
63    }
64    ty
65}
66
67#[cfg(test)]
68mod tests {
69    use super::*;
70
71    #[test]
72    fn default_pg_oid_scalars() {
73        assert_eq!(default_pg_oid_for_rust_type("bool"), 16);
74        assert_eq!(default_pg_oid_for_rust_type("i16"), 21);
75        assert_eq!(default_pg_oid_for_rust_type("i32"), 23);
76        assert_eq!(default_pg_oid_for_rust_type("i64"), 20);
77        assert_eq!(default_pg_oid_for_rust_type("f32"), 700);
78        assert_eq!(default_pg_oid_for_rust_type("f64"), 701);
79        assert_eq!(default_pg_oid_for_rust_type("&str"), 25);
80        assert_eq!(default_pg_oid_for_rust_type("String"), 25);
81        assert_eq!(default_pg_oid_for_rust_type("u32"), 26);
82        assert_eq!(default_pg_oid_for_rust_type("&[u8]"), 17);
83        assert_eq!(default_pg_oid_for_rust_type("Vec<u8>"), 17);
84    }
85
86    #[test]
87    fn default_pg_oid_arrays() {
88        assert_eq!(default_pg_oid_for_rust_type("&[bool]"), 1000);
89        assert_eq!(default_pg_oid_for_rust_type("Vec<bool>"), 1000);
90        assert_eq!(default_pg_oid_for_rust_type("&[i16]"), 1005);
91        assert_eq!(default_pg_oid_for_rust_type("Vec<i16>"), 1005);
92        assert_eq!(default_pg_oid_for_rust_type("&[i32]"), 1007);
93        assert_eq!(default_pg_oid_for_rust_type("Vec<i32>"), 1007);
94        assert_eq!(default_pg_oid_for_rust_type("&[i64]"), 1016);
95        assert_eq!(default_pg_oid_for_rust_type("Vec<i64>"), 1016);
96        assert_eq!(default_pg_oid_for_rust_type("&[f32]"), 1021);
97        assert_eq!(default_pg_oid_for_rust_type("Vec<f32>"), 1021);
98        assert_eq!(default_pg_oid_for_rust_type("&[f64]"), 1022);
99        assert_eq!(default_pg_oid_for_rust_type("Vec<f64>"), 1022);
100        assert_eq!(default_pg_oid_for_rust_type("&[&str]"), 1009);
101        assert_eq!(default_pg_oid_for_rust_type("Vec<String>"), 1009);
102        assert_eq!(default_pg_oid_for_rust_type("&[String]"), 1009);
103        assert_eq!(default_pg_oid_for_rust_type("&[&[u8]]"), 1001);
104        assert_eq!(default_pg_oid_for_rust_type("Vec<Vec<u8>>"), 1001);
105    }
106
107    #[test]
108    fn default_pg_oid_feature_gated() {
109        assert_eq!(default_pg_oid_for_rust_type("uuid::Uuid"), 2950);
110        assert_eq!(default_pg_oid_for_rust_type("Uuid"), 2950);
111        assert_eq!(default_pg_oid_for_rust_type("time::OffsetDateTime"), 1184);
112        assert_eq!(default_pg_oid_for_rust_type("time::Date"), 1082);
113        assert_eq!(default_pg_oid_for_rust_type("time::Time"), 1083);
114        assert_eq!(
115            default_pg_oid_for_rust_type("time::PrimitiveDateTime"),
116            1114
117        );
118        assert_eq!(default_pg_oid_for_rust_type("chrono::NaiveDateTime"), 1114);
119        assert_eq!(
120            default_pg_oid_for_rust_type("chrono::DateTime<chrono::Utc>"),
121            1184
122        );
123        assert_eq!(default_pg_oid_for_rust_type("chrono::NaiveDate"), 1082);
124        assert_eq!(default_pg_oid_for_rust_type("chrono::NaiveTime"), 1083);
125        assert_eq!(default_pg_oid_for_rust_type("rust_decimal::Decimal"), 1700);
126    }
127
128    #[test]
129    fn default_pg_oid_option_wrapper() {
130        assert_eq!(default_pg_oid_for_rust_type("Option<bool>"), 16);
131        assert_eq!(default_pg_oid_for_rust_type("Option<i32>"), 23);
132        assert_eq!(default_pg_oid_for_rust_type("Option<String>"), 25);
133    }
134
135    #[test]
136    fn default_pg_oid_unknown() {
137        assert_eq!(default_pg_oid_for_rust_type("unknown"), 0);
138        assert_eq!(default_pg_oid_for_rust_type(""), 0);
139    }
140}