Skip to main content

sqlx_gen/typemap/
sqlite.rs

1use super::RustType;
2use crate::cli::TimeCrate;
3
4pub fn map_type(declared_type: &str, time_crate: TimeCrate) -> RustType {
5    let upper = declared_type.to_uppercase();
6
7    if upper.contains("INT") {
8        return RustType::simple("i64");
9    }
10    if upper.contains("CHAR") || upper.contains("TEXT") || upper.contains("CLOB") {
11        return RustType::simple("String");
12    }
13    if upper.contains("BLOB") || upper.is_empty() {
14        return RustType::simple("Vec<u8>");
15    }
16    if upper.contains("REAL") || upper.contains("FLOAT") || upper.contains("DOUBLE") {
17        return RustType::simple("f64");
18    }
19    if upper.contains("BOOL") {
20        return RustType::simple("bool");
21    }
22    if upper.contains("TIMESTAMP") || upper.contains("DATETIME") {
23        return match time_crate {
24            TimeCrate::Chrono => RustType::with_import("NaiveDateTime", "use chrono::NaiveDateTime;"),
25            TimeCrate::Time => RustType::with_import("PrimitiveDateTime", "use time::PrimitiveDateTime;"),
26        };
27    }
28    if upper.contains("DATE") {
29        return match time_crate {
30            TimeCrate::Chrono => RustType::with_import("NaiveDate", "use chrono::NaiveDate;"),
31            TimeCrate::Time => RustType::with_import("Date", "use time::Date;"),
32        };
33    }
34    if upper.contains("TIME") {
35        return match time_crate {
36            TimeCrate::Chrono => RustType::with_import("NaiveTime", "use chrono::NaiveTime;"),
37            TimeCrate::Time => RustType::with_import("Time", "use time::Time;"),
38        };
39    }
40    if upper.contains("NUMERIC") || upper.contains("DECIMAL") {
41        return RustType::simple("f64");
42    }
43
44    // Default: SQLite is loosely typed
45    RustType::simple("String")
46}
47
48#[cfg(test)]
49mod tests {
50    use super::*;
51    use crate::cli::TimeCrate;
52
53    #[test]
54    fn test_integer() {
55        assert_eq!(map_type("INTEGER", TimeCrate::Chrono).path, "i64");
56    }
57
58    #[test]
59    fn test_int() {
60        assert_eq!(map_type("INT", TimeCrate::Chrono).path, "i64");
61    }
62
63    #[test]
64    fn test_bigint() {
65        assert_eq!(map_type("BIGINT", TimeCrate::Chrono).path, "i64");
66    }
67
68    #[test]
69    fn test_smallint() {
70        assert_eq!(map_type("SMALLINT", TimeCrate::Chrono).path, "i64");
71    }
72
73    #[test]
74    fn test_tinyint() {
75        assert_eq!(map_type("TINYINT", TimeCrate::Chrono).path, "i64");
76    }
77
78    #[test]
79    fn test_mediumint() {
80        assert_eq!(map_type("MEDIUMINT", TimeCrate::Chrono).path, "i64");
81    }
82
83    #[test]
84    fn test_text() {
85        assert_eq!(map_type("TEXT", TimeCrate::Chrono).path, "String");
86    }
87
88    #[test]
89    fn test_varchar() {
90        assert_eq!(map_type("VARCHAR(255)", TimeCrate::Chrono).path, "String");
91    }
92
93    #[test]
94    fn test_character() {
95        assert_eq!(map_type("CHARACTER(20)", TimeCrate::Chrono).path, "String");
96    }
97
98    #[test]
99    fn test_clob() {
100        assert_eq!(map_type("CLOB", TimeCrate::Chrono).path, "String");
101    }
102
103    #[test]
104    fn test_blob() {
105        assert_eq!(map_type("BLOB", TimeCrate::Chrono).path, "Vec<u8>");
106    }
107
108    #[test]
109    fn test_empty_type() {
110        assert_eq!(map_type("", TimeCrate::Chrono).path, "Vec<u8>");
111    }
112
113    #[test]
114    fn test_real() {
115        assert_eq!(map_type("REAL", TimeCrate::Chrono).path, "f64");
116    }
117
118    #[test]
119    fn test_float() {
120        assert_eq!(map_type("FLOAT", TimeCrate::Chrono).path, "f64");
121    }
122
123    #[test]
124    fn test_double() {
125        assert_eq!(map_type("DOUBLE", TimeCrate::Chrono).path, "f64");
126    }
127
128    #[test]
129    fn test_double_precision() {
130        assert_eq!(map_type("DOUBLE PRECISION", TimeCrate::Chrono).path, "f64");
131    }
132
133    #[test]
134    fn test_boolean() {
135        assert_eq!(map_type("BOOLEAN", TimeCrate::Chrono).path, "bool");
136    }
137
138    #[test]
139    fn test_timestamp() {
140        let rt = map_type("TIMESTAMP", TimeCrate::Chrono);
141        assert_eq!(rt.path, "NaiveDateTime");
142        assert!(rt.needs_import.as_ref().unwrap().contains("chrono"));
143    }
144
145    #[test]
146    fn test_datetime() {
147        let rt = map_type("DATETIME", TimeCrate::Chrono);
148        assert_eq!(rt.path, "NaiveDateTime");
149        assert!(rt.needs_import.is_some());
150    }
151
152    #[test]
153    fn test_date() {
154        let rt = map_type("DATE", TimeCrate::Chrono);
155        assert_eq!(rt.path, "NaiveDate");
156        assert!(rt.needs_import.as_ref().unwrap().contains("chrono"));
157    }
158
159    #[test]
160    fn test_time() {
161        let rt = map_type("TIME", TimeCrate::Chrono);
162        assert_eq!(rt.path, "NaiveTime");
163        assert!(rt.needs_import.as_ref().unwrap().contains("chrono"));
164    }
165
166    #[test]
167    fn test_numeric() {
168        assert_eq!(map_type("NUMERIC", TimeCrate::Chrono).path, "f64");
169    }
170
171    #[test]
172    fn test_decimal() {
173        assert_eq!(map_type("DECIMAL", TimeCrate::Chrono).path, "f64");
174    }
175
176    #[test]
177    fn test_case_insensitive() {
178        assert_eq!(map_type("integer", TimeCrate::Chrono).path, "i64");
179    }
180
181    #[test]
182    fn test_fallback_unknown_type() {
183        assert_eq!(map_type("JSON", TimeCrate::Chrono).path, "String");
184    }
185
186    // --- time crate ---
187
188    #[test]
189    fn test_timestamp_time_crate() {
190        let rt = map_type("TIMESTAMP", TimeCrate::Time);
191        assert_eq!(rt.path, "PrimitiveDateTime");
192        assert!(rt.needs_import.as_ref().unwrap().contains("time::PrimitiveDateTime"));
193    }
194
195    #[test]
196    fn test_datetime_time_crate() {
197        let rt = map_type("DATETIME", TimeCrate::Time);
198        assert_eq!(rt.path, "PrimitiveDateTime");
199        assert!(rt.needs_import.as_ref().unwrap().contains("time::PrimitiveDateTime"));
200    }
201
202    #[test]
203    fn test_date_time_crate() {
204        let rt = map_type("DATE", TimeCrate::Time);
205        assert_eq!(rt.path, "Date");
206        assert!(rt.needs_import.as_ref().unwrap().contains("time::Date"));
207    }
208
209    #[test]
210    fn test_time_time_crate() {
211        let rt = map_type("TIME", TimeCrate::Time);
212        assert_eq!(rt.path, "Time");
213        assert!(rt.needs_import.as_ref().unwrap().contains("time::Time"));
214    }
215}