1use crate::{
2 ast::{Expr, Value},
3 data_type::DataType,
4};
5use base64::{engine::general_purpose::URL_SAFE, Engine};
6use chrono::{DateTime, NaiveDate, NaiveDateTime, NaiveTime, Utc};
7use serde::{Deserialize, Serialize};
8use sqlparser::ast as sql;
9use std::fmt;
10use uuid::Uuid;
11
12#[derive(PartialEq, Debug, Clone, Serialize, Deserialize)]
15pub enum DataValue {
16 Nil,
17 Bool(bool),
18 S8(u8),
19 S16(u16),
20 S32(u32),
21 S64(u64),
22 F32(f32),
23 F64(f64),
24 U8(u8),
25 U16(u16),
26 U32(u32),
27 U64(u64),
28 I8(i8),
29 I16(i16),
30 I32(i32),
31 I64(i64),
32 Uuid(Uuid),
33 UuidRand(Uuid),
34 UuidSlug(String),
35 Utc(DateTime<Utc>),
36 Text(String),
37 Ident(String),
38 Bytes(Vec<u8>),
39}
40
41impl DataValue {
42 pub fn get_data_type(&self) -> Option<DataType> {
43 let dt = match self {
44 DataValue::Nil => {
45 return None;
46 }
47 DataValue::Bool(_) => DataType::Bool,
48 DataValue::S8(_) => DataType::S8,
49 DataValue::S16(_) => DataType::S16,
50 DataValue::S32(_) => DataType::S32,
51 DataValue::S64(_) => DataType::S64,
52 DataValue::F32(_) => DataType::F32,
53 DataValue::F64(_) => DataType::F64,
54 DataValue::U8(_) => DataType::U8,
55 DataValue::U16(_) => DataType::U16,
56 DataValue::U32(_) => DataType::U32,
57 DataValue::U64(_) => DataType::U64,
58 DataValue::I8(_) => DataType::I8,
59 DataValue::I16(_) => DataType::I16,
60 DataValue::I32(_) => DataType::I32,
61 DataValue::I64(_) => DataType::I64,
62 DataValue::Uuid(_) => DataType::Uuid,
63 DataValue::UuidRand(_) => DataType::UuidRand,
64 DataValue::UuidSlug(_) => DataType::UuidSlug,
65 DataValue::Utc(_) => DataType::Utc,
66 DataValue::Text(_) => DataType::Text,
67 DataValue::Ident(_) => DataType::Ident,
68 DataValue::Bytes(_) => DataType::Bytes,
69 };
70 Some(dt)
71 }
72}
73
74fn naive_date_parser(v: &str) -> NaiveDateTime {
75 if let Ok(dt) = DateTime::parse_from_rfc3339(v) {
76 dt.naive_local()
77 } else if let Ok(ts) =
78 NaiveDateTime::parse_from_str(&v, "%Y-%m-%dT%H:%M:%S%z")
79 {
80 ts
81 } else if let Ok(ts) =
82 NaiveDateTime::parse_from_str(&v, "%Y-%m-%d %H:%M:%S")
83 {
84 ts
85 } else if let Ok(ts) =
86 NaiveDateTime::parse_from_str(&v, "%Y-%m-%d %H:%M:%S.%f")
87 {
88 ts
89 } else if let Ok(nd) = NaiveDate::parse_from_str(&v, "%Y-%m-%d") {
90 NaiveDateTime::new(
91 nd,
92 NaiveTime::from_hms_milli_opt(0, 0, 0, 0).unwrap(),
93 )
94 } else {
95 panic!("unable to parse timestamp: {:?}", v);
96 }
97}
98
99impl Into<u32> for DataValue {
100 fn into(self) -> u32 {
101 match self {
102 DataValue::U8(v) => v as u32,
103 DataValue::U16(v) => v as u32,
104 DataValue::U32(v) => v,
105 DataValue::U64(v) => v as u32,
106 DataValue::I8(v) => v as u32,
107 DataValue::I16(v) => v as u32,
108 DataValue::I32(v) => v as u32,
109 DataValue::I64(v) => v as u32,
110 DataValue::S8(v) => v as u32,
111 DataValue::S16(v) => v as u32,
112 DataValue::S32(v) => v,
113 DataValue::S64(v) => v as u32,
114 _ => {
115 panic!(
116 "unsupported conversion: {:?} to u32",
117 self.get_data_type()
118 )
119 }
120 }
121 }
122}
123
124impl Into<u64> for DataValue {
125 fn into(self) -> u64 {
126 match self {
127 DataValue::U8(v) => v as u64,
128 DataValue::U16(v) => v as u64,
129 DataValue::U32(v) => v as u64,
130 DataValue::U64(v) => v,
131 DataValue::I8(v) => v as u64,
132 DataValue::I16(v) => v as u64,
133 DataValue::I32(v) => v as u64,
134 DataValue::I64(v) => v as u64,
135 DataValue::S8(v) => v as u64,
136 DataValue::S16(v) => v as u64,
137 DataValue::S32(v) => v as u64,
138 DataValue::S64(v) => v,
139 _ => {
140 panic!(
141 "unsupported conversion: {:?} to u64",
142 self.get_data_type()
143 )
144 }
145 }
146 }
147}
148
149impl Into<i64> for DataValue {
150 fn into(self) -> i64 {
151 match self {
152 DataValue::U8(v) => v as i64,
153 DataValue::U16(v) => v as i64,
154 DataValue::U32(v) => v as i64,
155 DataValue::U64(v) => v as i64,
156 DataValue::I8(v) => v as i64,
157 DataValue::I16(v) => v as i64,
158 DataValue::I32(v) => v as i64,
159 DataValue::I64(v) => v,
160 DataValue::S8(v) => v as i64,
161 DataValue::S16(v) => v as i64,
162 DataValue::S32(v) => v as i64,
163 DataValue::S64(v) => v as i64,
164 _ => {
165 panic!(
166 "unsupported conversion: {:?} to u64",
167 self.get_data_type()
168 )
169 }
170 }
171 }
172}
173
174impl Into<f32> for DataValue {
175 fn into(self) -> f32 {
176 match self {
177 DataValue::U8(v) => v as f32,
178 DataValue::U16(v) => v as f32,
179 DataValue::U32(v) => v as f32,
180 DataValue::U64(v) => v as f32,
181 DataValue::I8(v) => v as f32,
182 DataValue::I16(v) => v as f32,
183 DataValue::I32(v) => v as f32,
184 DataValue::I64(v) => v as f32,
185 DataValue::F32(v) => v,
186 DataValue::F64(v) => v as f32,
187 DataValue::S8(v) => v as f32,
188 DataValue::S16(v) => v as f32,
189 DataValue::S32(v) => v as f32,
190 DataValue::S64(v) => v as f32,
191 _ => {
192 panic!(
193 "unsupported conversion: {:?} to f32",
194 self.get_data_type()
195 )
196 }
197 }
198 }
199}
200
201impl Into<String> for DataValue {
202 fn into(self) -> String {
203 match self {
204 DataValue::Text(v) => v,
205 _ => {
206 panic!(
207 "unsupported conversion: {:?} to String",
208 self.get_data_type()
209 )
210 }
211 }
212 }
213}
214
215impl<'a> Into<&'a str> for &'a DataValue {
216 fn into(self) -> &'a str {
217 match self {
218 DataValue::Text(ref v) => v,
219 _ => {
220 panic!(
221 "unsupported conversion: {:?} to &str",
222 self.get_data_type()
223 )
224 }
225 }
226 }
227}
228
229impl Into<Expr> for Value {
230 fn into(self) -> Expr {
231 Expr::Value(self)
232 }
233}
234
235impl Into<sql::Expr> for &Value {
236 fn into(self) -> sql::Expr {
237 let expr: Expr = Into::into(self.clone());
238 Into::into(&expr)
239 }
240}
241
242impl Into<sql::Value> for &DataValue {
243 fn into(self) -> sql::Value {
244 match self {
245 DataValue::Bool(v) => sql::Value::Boolean(*v),
246 DataValue::U8(v) => sql::Value::Number(v.to_string(), false),
247 DataValue::U16(v) => sql::Value::Number(v.to_string(), false),
248 DataValue::U32(v) => sql::Value::Number(v.to_string(), false),
249 DataValue::U64(v) => sql::Value::Number(v.to_string(), false),
250 DataValue::F32(v) => sql::Value::Number(v.to_string(), false),
251 DataValue::F64(v) => sql::Value::Number(v.to_string(), false),
252 _ => todo!(),
253 }
254 }
255}
256
257impl Into<Value> for &DataValue {
258 fn into(self) -> Value {
259 match self {
260 DataValue::Bool(v) => Value::Bool(*v),
261 DataValue::U8(v) => Value::Number(*v as f64),
262 DataValue::U16(v) => Value::Number(*v as f64),
263 DataValue::U32(v) => Value::Number(*v as f64),
264 DataValue::U64(v) => Value::Number(*v as f64),
265 DataValue::I8(v) => Value::Number(*v as f64),
266 DataValue::I16(v) => Value::Number(*v as f64),
267 DataValue::I32(v) => Value::Number(*v as f64),
268 DataValue::I64(v) => Value::Number(*v as f64),
269 DataValue::F32(v) => Value::Number(*v as f64),
270 DataValue::F64(v) => Value::Number(*v as f64),
271 DataValue::Text(v) => Value::String(v.clone()),
272 _ => panic!("todo for: {:?}", self),
273 }
274 }
275}
276
277impl Into<sql::Expr> for &DataValue {
278 fn into(self) -> sql::Expr {
279 sql::Expr::Value(Into::into(self))
280 }
281}
282
283pub fn cast_data_value(value: &Value, required_type: &DataType) -> DataValue {
285 if *value == Value::Null {
286 DataValue::Nil
287 } else {
288 match *value {
289 Value::Bool(v) => match *required_type {
290 DataType::Bool => DataValue::Bool(v),
291 DataType::U8 => DataValue::U8(if v { 1 } else { 0 }),
292 DataType::U16 => DataValue::U16(if v { 1 } else { 0 }),
293 DataType::U32 => DataValue::U32(if v { 1 } else { 0 }),
294 DataType::U64 => DataValue::U64(if v { 1 } else { 0 }),
295 DataType::I8 => DataValue::I8(if v { 1 } else { 0 }),
296 DataType::I16 => DataValue::I16(if v { 1 } else { 0 }),
297 DataType::I32 => DataValue::I32(if v { 1 } else { 0 }),
298 DataType::I64 => DataValue::I64(if v { 1 } else { 0 }),
299 DataType::S8 => DataValue::S8(if v { 1 } else { 0 }),
300 DataType::S16 => DataValue::S16(if v { 1 } else { 0 }),
301 DataType::S32 => DataValue::S32(if v { 1 } else { 0 }),
302 DataType::S64 => DataValue::S64(if v { 1 } else { 0 }),
303 _ => {
304 panic!(
305 "unsupported conversion from {:?} to {:?}",
306 value, required_type
307 )
308 }
309 },
310 Value::Number(v) => match *required_type {
311 DataType::U8 => DataValue::U8(v as u8),
312 DataType::U16 => DataValue::U16(v as u16),
313 DataType::U32 => DataValue::U32(v as u32),
314 DataType::U64 => DataValue::U64(v as u64),
315 DataType::I8 => DataValue::I8(v as i8),
316 DataType::I16 => DataValue::I16(v as i16),
317 DataType::I32 => DataValue::I32(v as i32),
318 DataType::I64 => DataValue::I64(v as i64),
319 DataType::F32 => DataValue::F32(v as f32),
320 DataType::F64 => DataValue::F64(v as f64),
321 DataType::S8 => DataValue::S8(v as u8),
322 DataType::S16 => DataValue::S16(v as u16),
323 DataType::S32 => DataValue::S32(v as u32),
324 DataType::S64 => DataValue::S64(v as u64),
325 _ => {
326 panic!(
327 "unsupported conversion from {:?} to {:?}",
328 value, required_type
329 )
330 }
331 },
332 Value::String(ref v) => {
333 match *required_type {
334 DataType::Text => DataValue::Text(v.to_string()),
335 DataType::Bool => match v.as_ref() {
336 "true" => DataValue::Bool(true),
337 "false" => DataValue::Bool(false),
338 "1" => DataValue::Bool(true),
339 "0" => DataValue::Bool(false),
340 _ => DataValue::Bool(false),
341 },
342 DataType::S8 => {
343 if v.is_empty() {
344 DataValue::Nil
345 } else if let Ok(v) = v.parse::<u8>() {
346 DataValue::S8(v)
347 } else {
348 panic!(
349 "unsupported conversion from {:?} to {:?}",
350 value, required_type
351 );
352 }
353 }
354 DataType::S16 => {
355 if v.is_empty() {
356 DataValue::Nil
357 } else if let Ok(v) = v.parse::<u16>() {
358 DataValue::S16(v)
359 } else {
360 panic!(
361 "unsupported conversion from {:?} to {:?}",
362 value, required_type
363 );
364 }
365 }
366 DataType::S32 => {
367 if v.is_empty() {
368 DataValue::Nil
369 } else if let Ok(v) = v.parse::<u32>() {
370 DataValue::S32(v)
371 } else {
372 panic!(
373 "unsupported conversion from {:?} to {:?}",
374 value, required_type
375 );
376 }
377 }
378 DataType::S64 => {
379 if v.is_empty() {
380 DataValue::Nil
381 } else if let Ok(v) = v.parse::<u64>() {
382 DataValue::S64(v)
383 } else {
384 panic!(
385 "unsupported conversion from {:?} to {:?}",
386 value, required_type
387 );
388 }
389 }
390 DataType::U8 => {
391 if v.is_empty() {
392 DataValue::Nil
393 } else if v.is_empty() {
394 DataValue::Nil
395 } else if let Ok(v) = v.parse::<u8>() {
396 DataValue::U8(v)
397 } else {
398 panic!(
399 "unsupported conversion from {:?} to {:?}",
400 value, required_type
401 );
402 }
403 }
404 DataType::U16 => {
405 if v.is_empty() {
406 DataValue::Nil
407 } else if let Ok(v) = v.parse::<u16>() {
408 DataValue::U16(v)
409 } else {
410 panic!(
411 "unsupported conversion from {:?} to {:?}",
412 value, required_type
413 );
414 }
415 }
416 DataType::U32 => {
417 if v.is_empty() {
418 DataValue::Nil
419 } else if let Ok(v) = v.parse::<u32>() {
420 DataValue::U32(v)
421 } else {
422 panic!(
423 "unsupported conversion from {:?} to {:?}",
424 value, required_type
425 );
426 }
427 }
428 DataType::U64 => {
429 if v.is_empty() {
430 DataValue::Nil
431 } else if let Ok(v) = v.parse::<u64>() {
432 DataValue::U64(v)
433 } else {
434 panic!(
435 "unsupported conversion from {:?} to {:?}",
436 value, required_type
437 );
438 }
439 }
440 DataType::I8 => {
441 if v.is_empty() {
442 DataValue::Nil
443 } else if let Ok(v) = v.parse::<i8>() {
444 DataValue::I8(v)
445 } else {
446 panic!(
447 "unsupported conversion from {:?} to {:?}",
448 value, required_type
449 );
450 }
451 }
452 DataType::I16 => {
453 if v.is_empty() {
454 DataValue::Nil
455 } else if let Ok(v) = v.parse::<i16>() {
456 DataValue::I16(v)
457 } else {
458 panic!(
459 "unsupported conversion from {:?} to {:?}",
460 value, required_type
461 );
462 }
463 }
464 DataType::I32 => {
465 if v.is_empty() {
466 DataValue::Nil
467 } else if let Ok(v) = v.parse::<i32>() {
468 DataValue::I32(v)
469 } else {
470 panic!(
471 "unsupported conversion from {:?} to {:?}",
472 value, required_type
473 );
474 }
475 }
476 DataType::I64 => {
477 if v.is_empty() {
478 DataValue::Nil
479 } else if let Ok(v) = v.parse::<i64>() {
480 DataValue::I64(v)
481 } else {
482 panic!(
483 "unsupported conversion from {:?} to {:?}",
484 value, required_type
485 );
486 }
487 }
488 DataType::F32 => {
489 if v.is_empty() {
490 DataValue::Nil
491 } else if let Ok(v) = v.parse::<f32>() {
492 DataValue::F32(v)
493 } else {
494 panic!(
495 "unsupported conversion from {:?} to {:?}",
496 value, required_type
497 );
498 }
499 }
500 DataType::F64 => {
501 if v.is_empty() {
502 DataValue::Nil
503 } else if let Ok(v) = v.parse::<f64>() {
504 DataValue::F64(v)
505 } else {
506 panic!(
507 "unsupported conversion from {:?} to {:?}",
508 value, required_type
509 );
510 }
511 }
512 DataType::Utc => {
513 if v.is_empty() {
514 DataValue::Nil
515 } else {
516 let ts = naive_date_parser(&v);
517 if let Some(utc) =
518 DateTime::<Utc>::from_timestamp_millis(
519 ts.and_utc().timestamp_millis(),
520 )
521 {
522 DataValue::Utc(utc)
523 } else {
524 panic!("error converting datetime");
525 }
526 }
527 }
528 DataType::Uuid | DataType::UuidRand => {
529 match Uuid::parse_str(&v) {
530 Ok(v) => DataValue::Uuid(v),
531 Err(_e) => DataValue::Nil,
532 }
533 }
534 DataType::UuidSlug => DataValue::UuidSlug(v.to_string()),
535 DataType::Ident => DataValue::Ident(v.to_string()),
537 DataType::Bytes => {
538 let bytes = URL_SAFE
539 .decode(&v)
540 .expect("must be a valid base64 bytes");
541 DataValue::Bytes(bytes)
542 }
543 DataType::Json => DataValue::Text(v.to_string()),
544 _ => {
545 panic!(
546 "unsupported conversion from {:?} to {:?}",
547 value, required_type
548 )
549 }
550 }
551 }
552 _ => {
553 panic!(
554 "unsupported conversion from {:?} to {:?}",
555 value, required_type
556 )
557 }
558 }
559 }
560}
561
562impl fmt::Display for DataValue {
563 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
564 match self {
565 DataValue::Nil => write!(f, ""),
566 DataValue::Bool(v) => write!(f, "{}", v),
567 DataValue::S8(v) => write!(f, "{}", v),
568 DataValue::S16(v) => write!(f, "{}", v),
569 DataValue::S32(v) => write!(f, "{}", v),
570 DataValue::S64(v) => write!(f, "{}", v),
571 DataValue::F32(v) => write!(f, "{}", v),
572 DataValue::F64(v) => write!(f, "{}", v),
573 DataValue::U8(v) => write!(f, "{}", v),
574 DataValue::U16(v) => write!(f, "{}", v),
575 DataValue::U32(v) => write!(f, "{}", v),
576 DataValue::U64(v) => write!(f, "{}", v),
577 DataValue::I8(v) => write!(f, "{}", v),
578 DataValue::I16(v) => write!(f, "{}", v),
579 DataValue::I32(v) => write!(f, "{}", v),
580 DataValue::I64(v) => write!(f, "{}", v),
581 DataValue::Uuid(v) => write!(f, "{}", v),
582 DataValue::UuidRand(v) => write!(f, "{}", v),
583 DataValue::UuidSlug(v) => write!(f, "{}", v),
584 DataValue::Utc(v) => write!(f, "{}", v.to_rfc3339()),
585 DataValue::Text(v) => write!(f, "{}", v),
586 DataValue::Ident(v) => write!(f, "{}", v),
587 DataValue::Bytes(v) => {
588 let encoded = URL_SAFE.encode(&v);
589 write!(f, "{}", encoded)
590 }
591 }
592 }
593}
594
595#[cfg(test)]
596mod test {
597 use super::*;
598
599 #[test]
600 fn parse_simple_date() {
601 let date = "2006-02-14";
602
603 let parsed = NaiveDateTime::parse_from_str(date, "%Y-%m-%d");
604 println!("parsed: {:?}", parsed);
605
606 let res = naive_date_parser(date);
607 let naive_date = NaiveDate::from_ymd_opt(2006, 2, 14).unwrap();
608 let naive_time = NaiveTime::from_hms_milli_opt(0, 0, 0, 0).unwrap();
609 assert_eq!(res, NaiveDateTime::new(naive_date, naive_time));
610 }
611
612 #[test]
613 fn parse_dates() {
614 let date = "2006-02-15T09:34:33+00:00";
615 let res = naive_date_parser(date);
616 println!("res: {}", res);
617 let naive_date = NaiveDate::from_ymd_opt(2006, 2, 15).unwrap();
618 let naive_time = NaiveTime::from_hms_milli_opt(9, 34, 33, 0).unwrap();
619 assert_eq!(res, NaiveDateTime::new(naive_date, naive_time));
620 }
621}