1use serde::{Deserialize, Serialize};
2use serde_json::Value;
3use std::str::FromStr;
4
5#[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize)]
6pub enum SqlSigned {
7 #[default]
8 Signed,
9 Unsigned,
10}
11
12#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
13#[serde(rename_all = "snake_case")]
14pub enum SqlDatatype {
16 Tinyint(u32, SqlSigned),
17 Smallint(u32, SqlSigned),
18 Mediumint(u32, SqlSigned),
19 Int(u32, SqlSigned),
20 Bigint(u32, SqlSigned),
21 Float(u32, u32, SqlSigned),
22 Double(u32, u32, SqlSigned),
23 Decimal(u32, u32, SqlSigned),
24
25 Date,
26 Time,
27 Datetime,
28 Timestamp,
29
30 Char(u32),
31 Varchar(u32),
32 Text(u32),
33
34 Binary(u32),
35 Varbinary(u32),
36
37 Enum(Vec<String>),
38 Set(Vec<String>),
39}
40
41#[derive(Debug, PartialEq, Eq)]
42pub struct ParseDatatypeError;
43
44impl SqlDatatype {
45 pub fn sign(&self) -> Option<SqlSigned> {
47 match self {
48 SqlDatatype::Tinyint(_, sign) => Some(sign.clone()),
49 SqlDatatype::Smallint(_, sign) => Some(sign.clone()),
50 SqlDatatype::Mediumint(_, sign) => Some(sign.clone()),
51 SqlDatatype::Int(_, sign) => Some(sign.clone()),
52 SqlDatatype::Bigint(_, sign) => Some(sign.clone()),
53 SqlDatatype::Float(_, _, sign) => Some(sign.clone()),
54 SqlDatatype::Double(_, _, sign) => Some(sign.clone()),
55 SqlDatatype::Decimal(_, _, sign) => Some(sign.clone()),
56 _ => None,
57 }
58 }
59
60 #[allow(clippy::len_without_is_empty)]
62 pub fn len(&self) -> Option<u32> {
63 match self {
64 SqlDatatype::Tinyint(len, _) => Some(*len),
65 SqlDatatype::Smallint(len, _) => Some(*len),
66 SqlDatatype::Mediumint(len, _) => Some(*len),
67 SqlDatatype::Int(len, _) => Some(*len),
68 SqlDatatype::Bigint(len, _) => Some(*len),
69 SqlDatatype::Float(len, _, _) => Some(*len),
70 SqlDatatype::Double(len, _, _) => Some(*len),
71 SqlDatatype::Decimal(len, _, _) => Some(*len),
72 SqlDatatype::Char(len) => Some(*len),
73 SqlDatatype::Varchar(len) => Some(*len),
74 SqlDatatype::Text(len) => Some(*len),
75 SqlDatatype::Binary(len) => Some(*len),
76 SqlDatatype::Varbinary(len) => Some(*len),
77 SqlDatatype::Enum(v) => Some(v.len() as u32),
78 SqlDatatype::Set(v) => Some(v.len() as u32),
79 _ => None,
80 }
81 }
82
83 pub fn is_text(&self) -> bool {
85 matches!(
86 self,
87 SqlDatatype::Text(_) | SqlDatatype::Varchar(_) | SqlDatatype::Char(_)
88 )
89 }
90}
91
92impl Default for SqlDatatype {
93 fn default() -> Self {
94 SqlDatatype::Varchar(45)
95 }
96}
97
98impl FromStr for SqlDatatype {
99 type Err = ParseDatatypeError;
100
101 fn from_str(s: &str) -> Result<Self, Self::Err> {
102 SqlDatatype::try_from(s)
103 }
104}
105
106impl TryFrom<&str> for SqlDatatype {
107 type Error = ParseDatatypeError;
108
109 fn try_from(value: &str) -> Result<Self, Self::Error> {
110 return if value.contains('(') && value.contains(')') {
111 let is_signed = if value.contains("unsigned") {
114 SqlSigned::Unsigned
115 } else {
116 SqlSigned::Signed
117 };
118
119 let (type_group, type_length) = value
120 .split_once('(')
121 .map(|s| (s.0, s.1.rsplit_once(')').unwrap_or(("", "")).0))
122 .ok_or(ParseDatatypeError)?;
123
124 match type_group {
125 "set" | "enum" => {
126 let trim_match: &[_] = &['"', '\''];
127 let options = type_length
128 .split(',')
129 .map(|s| s.trim_matches(trim_match).to_string())
130 .collect();
131
132 return if type_group == "set" {
133 Ok(SqlDatatype::Set(options))
134 } else {
135 Ok(SqlDatatype::Enum(options))
136 };
137 }
138 "float" | "double" | "decimal" => {
139 let (left, right) = {
140 let v = type_length
141 .splitn(2, ',')
142 .map(|s| s.parse::<u32>().unwrap_or_default())
143 .collect::<Vec<u32>>();
144
145 (
146 *v.first().ok_or(ParseDatatypeError)?,
147 *v.last().ok_or(ParseDatatypeError)?,
148 )
149 };
150
151 if type_group == "float" {
152 Ok(SqlDatatype::Float(left, right, is_signed))
153 } else if type_group == "double" {
154 Ok(SqlDatatype::Double(left, right, is_signed))
155 } else {
156 Ok(SqlDatatype::Decimal(left, right, is_signed))
157 }
158 }
159 _ => {
160 if let Ok(len_val) = type_length.parse::<u32>() {
161 match type_group {
162 "tinyint" => Ok(SqlDatatype::Tinyint(len_val, is_signed)),
163 "int" => Ok(SqlDatatype::Int(len_val, is_signed)),
164 "smallint" => Ok(SqlDatatype::Smallint(len_val, is_signed)),
165 "mediumint" => Ok(SqlDatatype::Mediumint(len_val, is_signed)),
166 "bigint" => Ok(SqlDatatype::Bigint(len_val, is_signed)),
167
168 "char" => Ok(SqlDatatype::Char(len_val)),
169 "varchar" => Ok(SqlDatatype::Varchar(len_val)),
170 "text" => Ok(SqlDatatype::Text(len_val)), "binary" => Ok(SqlDatatype::Binary(len_val)),
173 "varbinary" => Ok(SqlDatatype::Varbinary(len_val)),
174
175 _ => Err(ParseDatatypeError),
176 }
177 } else {
178 Err(ParseDatatypeError)
179 }
180 }
181 }
182 } else {
183 match value {
186 "text" => Ok(SqlDatatype::Text(65535)),
187 "date" => Ok(SqlDatatype::Date),
188 "time" => Ok(SqlDatatype::Time),
189 "datetime" => Ok(SqlDatatype::Datetime),
190 "timestamp" => Ok(SqlDatatype::Timestamp),
191 _ => Err(ParseDatatypeError),
192 }
193 };
194 }
195}
196
197#[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize)]
198#[serde(rename_all = "snake_case")]
199pub enum DefaultValue {
201 #[default]
202 Null,
203 Value(Value),
204}
205
206#[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize)]
207#[serde(rename_all = "snake_case")]
208pub enum JsonNumber {
210 #[default]
211 Number,
212 BigInt,
213 Int,
214 Float,
215}
216
217#[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize)]
218#[serde(rename_all = "snake_case")]
219pub enum JsonString {
221 #[default]
222 String,
223 Datetime,
224 Date,
225 Time,
226 Json,
227}
228
229#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
230#[serde(rename_all = "snake_case")]
231pub enum JsonDatatype {
233 Number(JsonNumber),
234 String(JsonString, Option<u32>),
235 Boolean,
236 Array(Vec<String>),
237 Object(Value),
238}
239
240impl Default for JsonDatatype {
241 fn default() -> Self {
242 JsonDatatype::String(JsonString::String, None)
243 }
244}
245
246impl From<&SqlDatatype> for JsonDatatype {
247 fn from(value: &SqlDatatype) -> Self {
248 match value {
249 SqlDatatype::Tinyint(1, SqlSigned::Unsigned) => JsonDatatype::Boolean,
250 SqlDatatype::Int(_, _)
251 | SqlDatatype::Smallint(_, _)
252 | SqlDatatype::Mediumint(_, _)
253 | SqlDatatype::Tinyint(_, _) => JsonDatatype::Number(JsonNumber::Int),
254 SqlDatatype::Float(_, _, _)
255 | SqlDatatype::Double(_, _, _)
256 | SqlDatatype::Decimal(_, _, _) => JsonDatatype::Number(JsonNumber::Float),
257 SqlDatatype::Bigint(_, _) => JsonDatatype::Number(JsonNumber::BigInt),
258 SqlDatatype::Date => JsonDatatype::String(JsonString::Date, Some(10)),
259 SqlDatatype::Time => JsonDatatype::String(JsonString::Time, Some(8)),
260 SqlDatatype::Datetime | SqlDatatype::Timestamp => {
261 JsonDatatype::String(JsonString::Datetime, Some(20))
262 }
263 SqlDatatype::Char(length)
264 | SqlDatatype::Varchar(length)
265 | SqlDatatype::Text(length) => JsonDatatype::String(JsonString::String, Some(*length)),
266 SqlDatatype::Binary(length) | SqlDatatype::Varbinary(length) => {
267 JsonDatatype::String(JsonString::String, Some(*length))
268 }
269 SqlDatatype::Enum(options) | SqlDatatype::Set(options) => {
270 JsonDatatype::Array(options.clone())
271 }
272 }
273 }
274}
275
276#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
277pub struct RustDatatype(pub String, pub Option<u32>);
279
280pub const RUST_TYPE_STRING: &str = "String";
281pub const RUST_TYPE_I32: &str = "i32";
284pub const RUST_TYPE_I64: &str = "i64";
285pub const RUST_TYPE_U32: &str = "u32";
286pub const RUST_TYPE_U64: &str = "u64";
287pub const RUST_TYPE_F32: &str = "f32";
288pub const RUST_TYPE_F64: &str = "f64";
289pub const RUST_TYPE_BOOL: &str = "bool";
290pub const RUST_TYPE_VEC: &str = "Vec<String>";
291
292impl Default for RustDatatype {
293 fn default() -> Self {
294 RustDatatype(RUST_TYPE_STRING.to_string(), None)
295 }
296}
297
298impl From<&SqlDatatype> for RustDatatype {
299 fn from(value: &SqlDatatype) -> Self {
300 match value {
301 SqlDatatype::Tinyint(1, _) => {
302 RustDatatype(RUST_TYPE_BOOL.to_string(), None)
304 }
305 SqlDatatype::Int(len, SqlSigned::Unsigned)
306 | SqlDatatype::Smallint(len, SqlSigned::Unsigned)
307 | SqlDatatype::Mediumint(len, SqlSigned::Unsigned)
308 | SqlDatatype::Tinyint(len, SqlSigned::Unsigned) => {
309 RustDatatype(RUST_TYPE_U32.to_string(), Some(*len))
310 }
311 SqlDatatype::Int(len, SqlSigned::Signed)
312 | SqlDatatype::Smallint(len, SqlSigned::Signed)
313 | SqlDatatype::Mediumint(len, SqlSigned::Signed)
314 | SqlDatatype::Tinyint(len, SqlSigned::Signed) => {
315 RustDatatype(RUST_TYPE_I32.to_string(), Some(*len))
316 }
317 SqlDatatype::Float(_, fp, _) => RustDatatype(RUST_TYPE_F32.to_string(), Some(*fp)),
318 SqlDatatype::Double(_, fp, _) | SqlDatatype::Decimal(_, fp, _) => {
319 RustDatatype(RUST_TYPE_F64.to_string(), Some(*fp))
320 }
321 SqlDatatype::Bigint(len, SqlSigned::Unsigned) => {
322 RustDatatype(RUST_TYPE_U64.to_string(), Some(*len))
323 }
324 SqlDatatype::Bigint(len, SqlSigned::Signed) => {
325 RustDatatype(RUST_TYPE_I64.to_string(), Some(*len))
326 }
327 SqlDatatype::Date => RustDatatype(RUST_TYPE_STRING.to_string(), Some(10)),
328 SqlDatatype::Time => RustDatatype(RUST_TYPE_STRING.to_string(), Some(8)),
329 SqlDatatype::Datetime | SqlDatatype::Timestamp => {
330 RustDatatype(RUST_TYPE_STRING.to_string(), Some(20))
331 }
332 SqlDatatype::Char(length)
333 | SqlDatatype::Varchar(length)
334 | SqlDatatype::Text(length) => {
335 RustDatatype(RUST_TYPE_STRING.to_string(), Some(*length))
336 }
337 SqlDatatype::Binary(length) | SqlDatatype::Varbinary(length) => {
338 RustDatatype(RUST_TYPE_STRING.to_string(), Some(*length))
339 }
340 SqlDatatype::Enum(options) => RustDatatype(
341 RUST_TYPE_STRING.to_string(),
342 Some(options.iter().fold(0u32, |ac, c| {
343 if c.len() as u32 > ac {
344 c.len() as u32
345 } else {
346 ac
347 }
348 })),
349 ),
350 SqlDatatype::Set(options) => {
351 RustDatatype(RUST_TYPE_VEC.to_string(), Some(options.len() as u32))
352 }
353 }
354 }
355}