drizzle_types/sqlite/
sql_type.rs1#[derive(Default, Debug, Clone, Copy, PartialEq, Eq, Hash)]
23#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
24#[cfg_attr(feature = "serde", serde(rename_all = "UPPERCASE"))]
25pub enum SQLiteType {
26 Integer,
32
33 Text,
39
40 Blob,
46
47 Real,
51
52 Numeric,
56
57 #[default]
63 Any,
64}
65
66#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
70#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
71#[cfg_attr(feature = "serde", serde(rename_all = "UPPERCASE"))]
72pub enum SQLiteAffinity {
73 Integer,
75 Text,
77 Blob,
79 Real,
81 Numeric,
83 Any,
85}
86
87impl SQLiteType {
88 #[must_use]
93 pub const fn from_attribute_name(name: &str) -> Option<Self> {
94 if name.eq_ignore_ascii_case("integer") {
95 Some(Self::Integer)
96 } else if name.eq_ignore_ascii_case("text") {
97 Some(Self::Text)
98 } else if name.eq_ignore_ascii_case("blob") {
99 Some(Self::Blob)
100 } else if name.eq_ignore_ascii_case("real") {
101 Some(Self::Real)
102 } else if name.eq_ignore_ascii_case("number") || name.eq_ignore_ascii_case("numeric") {
103 Some(Self::Numeric)
104 } else if name.eq_ignore_ascii_case("boolean") {
105 Some(Self::Integer) } else if name.eq_ignore_ascii_case("any") {
107 Some(Self::Any)
108 } else {
109 None
110 }
111 }
112
113 #[must_use]
115 pub const fn to_sql_type(&self) -> &'static str {
116 match self {
117 Self::Integer => "INTEGER",
118 Self::Text => "TEXT",
119 Self::Blob => "BLOB",
120 Self::Real => "REAL",
121 Self::Numeric => "NUMERIC",
122 Self::Any => "ANY",
123 }
124 }
125
126 #[must_use]
128 pub const fn affinity(&self) -> SQLiteAffinity {
129 match self {
130 Self::Integer => SQLiteAffinity::Integer,
131 Self::Text => SQLiteAffinity::Text,
132 Self::Blob => SQLiteAffinity::Blob,
133 Self::Real => SQLiteAffinity::Real,
134 Self::Numeric => SQLiteAffinity::Numeric,
135 Self::Any => SQLiteAffinity::Any,
136 }
137 }
138
139 #[must_use]
141 pub const fn is_strict_allowed(&self) -> bool {
142 matches!(
143 self,
144 Self::Integer | Self::Real | Self::Text | Self::Blob | Self::Any
145 )
146 }
147
148 #[must_use]
159 pub fn is_valid_flag(&self, flag: &str) -> bool {
160 matches!(flag, "primary" | "primary_key" | "unique")
161 || matches!(
162 (self, flag),
163 (Self::Integer, "autoincrement")
164 | (Self::Text, "json")
165 | (Self::Text | Self::Integer, "enum")
166 )
167 }
168}
169
170impl core::fmt::Display for SQLiteType {
171 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
172 f.write_str(self.to_sql_type())
173 }
174}
175
176#[cfg(test)]
177mod tests {
178 use super::*;
179
180 #[test]
181 fn test_from_attribute_name() {
182 assert_eq!(
183 SQLiteType::from_attribute_name("integer"),
184 Some(SQLiteType::Integer)
185 );
186 assert_eq!(
187 SQLiteType::from_attribute_name("INTEGER"),
188 Some(SQLiteType::Integer)
189 );
190 assert_eq!(
191 SQLiteType::from_attribute_name("text"),
192 Some(SQLiteType::Text)
193 );
194 assert_eq!(
195 SQLiteType::from_attribute_name("blob"),
196 Some(SQLiteType::Blob)
197 );
198 assert_eq!(
199 SQLiteType::from_attribute_name("boolean"),
200 Some(SQLiteType::Integer)
201 );
202 assert_eq!(SQLiteType::from_attribute_name("unknown"), None);
203 }
204
205 #[test]
206 fn test_to_sql_type() {
207 assert_eq!(SQLiteType::Integer.to_sql_type(), "INTEGER");
208 assert_eq!(SQLiteType::Text.to_sql_type(), "TEXT");
209 assert_eq!(SQLiteType::Blob.to_sql_type(), "BLOB");
210 assert_eq!(SQLiteType::Real.to_sql_type(), "REAL");
211 assert_eq!(SQLiteType::Numeric.to_sql_type(), "NUMERIC");
212 assert_eq!(SQLiteType::Any.to_sql_type(), "ANY");
213 }
214
215 #[test]
216 fn test_affinity_mapping() {
217 assert_eq!(SQLiteType::Integer.affinity(), SQLiteAffinity::Integer);
218 assert_eq!(SQLiteType::Text.affinity(), SQLiteAffinity::Text);
219 assert_eq!(SQLiteType::Blob.affinity(), SQLiteAffinity::Blob);
220 assert_eq!(SQLiteType::Real.affinity(), SQLiteAffinity::Real);
221 assert_eq!(SQLiteType::Numeric.affinity(), SQLiteAffinity::Numeric);
222 assert_eq!(SQLiteType::Any.affinity(), SQLiteAffinity::Any);
223 }
224
225 #[test]
226 fn test_strict_allowed_types() {
227 assert!(SQLiteType::Integer.is_strict_allowed());
228 assert!(SQLiteType::Text.is_strict_allowed());
229 assert!(SQLiteType::Blob.is_strict_allowed());
230 assert!(SQLiteType::Real.is_strict_allowed());
231 assert!(SQLiteType::Any.is_strict_allowed());
232 assert!(!SQLiteType::Numeric.is_strict_allowed());
233 }
234
235 #[test]
236 fn test_is_valid_flag() {
237 assert!(SQLiteType::Integer.is_valid_flag("autoincrement"));
239 assert!(!SQLiteType::Text.is_valid_flag("autoincrement"));
240 assert!(!SQLiteType::Blob.is_valid_flag("autoincrement"));
241
242 assert!(SQLiteType::Text.is_valid_flag("json"));
244 assert!(!SQLiteType::Blob.is_valid_flag("json"));
245 assert!(!SQLiteType::Integer.is_valid_flag("json"));
246
247 assert!(SQLiteType::Text.is_valid_flag("enum"));
249 assert!(SQLiteType::Integer.is_valid_flag("enum"));
250 assert!(!SQLiteType::Blob.is_valid_flag("enum"));
251
252 assert!(SQLiteType::Integer.is_valid_flag("primary"));
254 assert!(SQLiteType::Text.is_valid_flag("unique"));
255 assert!(SQLiteType::Blob.is_valid_flag("primary_key"));
256 }
257}