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