clickhouse_srv/types/
value_ref.rs

1use std::convert;
2use std::fmt;
3use std::str;
4use std::sync::Arc;
5
6use chrono::prelude::*;
7use chrono_tz::Tz;
8use uuid::Uuid;
9
10use crate::errors::Error;
11use crate::errors::FromSqlError;
12use crate::errors::Result;
13use crate::types::column::datetime64::to_datetime;
14use crate::types::column::Either;
15use crate::types::decimal::Decimal;
16use crate::types::value::decode_ipv4;
17use crate::types::value::decode_ipv6;
18use crate::types::value::AppDate;
19use crate::types::value::AppDateTime;
20use crate::types::DateTimeType;
21use crate::types::Enum16;
22use crate::types::Enum8;
23use crate::types::SqlType;
24use crate::types::Value;
25
26#[derive(Clone, Debug)]
27pub enum ValueRef<'a> {
28    UInt8(u8),
29    UInt16(u16),
30    UInt32(u32),
31    UInt64(u64),
32    Int8(i8),
33    Int16(i16),
34    Int32(i32),
35    Int64(i64),
36    String(&'a [u8]),
37    Float32(f32),
38    Float64(f64),
39    Date(u16, Tz),
40    DateTime(u32, Tz),
41    DateTime64(i64, &'a (u32, Tz)),
42    Nullable(Either<&'static SqlType, Box<ValueRef<'a>>>),
43    Array(&'static SqlType, Arc<Vec<ValueRef<'a>>>),
44    Decimal(Decimal),
45    Ipv4([u8; 4]),
46    Ipv6([u8; 16]),
47    Uuid([u8; 16]),
48    Enum16(Vec<(String, i16)>, Enum16),
49    Enum8(Vec<(String, i8)>, Enum8)
50}
51
52impl<'a> PartialEq for ValueRef<'a> {
53    fn eq(&self, other: &Self) -> bool {
54        match (self, other) {
55            (ValueRef::UInt8(a), ValueRef::UInt8(b)) => *a == *b,
56            (ValueRef::UInt16(a), ValueRef::UInt16(b)) => *a == *b,
57            (ValueRef::UInt32(a), ValueRef::UInt32(b)) => *a == *b,
58            (ValueRef::UInt64(a), ValueRef::UInt64(b)) => *a == *b,
59            (ValueRef::Int8(a), ValueRef::Int8(b)) => *a == *b,
60            (ValueRef::Int16(a), ValueRef::Int16(b)) => *a == *b,
61            (ValueRef::Int32(a), ValueRef::Int32(b)) => *a == *b,
62            (ValueRef::Int64(a), ValueRef::Int64(b)) => *a == *b,
63            (ValueRef::String(a), ValueRef::String(b)) => *a == *b,
64            (ValueRef::Float32(a), ValueRef::Float32(b)) => *a == *b,
65            (ValueRef::Float64(a), ValueRef::Float64(b)) => *a == *b,
66            (ValueRef::Date(a, tz_a), ValueRef::Date(b, tz_b)) => {
67                let time_a = tz_a.timestamp(i64::from(*a) * 24 * 3600, 0);
68                let time_b = tz_b.timestamp(i64::from(*b) * 24 * 3600, 0);
69                time_a.date() == time_b.date()
70            }
71            (ValueRef::DateTime(a, tz_a), ValueRef::DateTime(b, tz_b)) => {
72                let time_a = tz_a.timestamp(i64::from(*a), 0);
73                let time_b = tz_b.timestamp(i64::from(*b), 0);
74                time_a == time_b
75            }
76            (ValueRef::Nullable(a), ValueRef::Nullable(b)) => *a == *b,
77            (ValueRef::Array(ta, a), ValueRef::Array(tb, b)) => *ta == *tb && *a == *b,
78            (ValueRef::Decimal(a), ValueRef::Decimal(b)) => *a == *b,
79            (ValueRef::Enum8(a0, a1), ValueRef::Enum8(b0, b1)) => *a1 == *b1 && *a0 == *b0,
80            (ValueRef::Enum16(a0, a1), ValueRef::Enum16(b0, b1)) => *a1 == *b1 && *a0 == *b0,
81            (ValueRef::DateTime64(this, this_params), ValueRef::DateTime64(that, that_params)) => {
82                let (this_precision, this_tz) = **this_params;
83                let (that_precision2, that_tz) = **that_params;
84
85                let this_time = to_datetime(*this, this_precision, this_tz);
86                let that_time = to_datetime(*that, that_precision2, that_tz);
87
88                this_time == that_time
89            }
90            _ => false
91        }
92    }
93}
94
95impl<'a> fmt::Display for ValueRef<'a> {
96    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
97        match self {
98            ValueRef::UInt8(v) => fmt::Display::fmt(v, f),
99            ValueRef::UInt16(v) => fmt::Display::fmt(v, f),
100            ValueRef::UInt32(v) => fmt::Display::fmt(v, f),
101            ValueRef::UInt64(v) => fmt::Display::fmt(v, f),
102            ValueRef::Int8(v) => fmt::Display::fmt(v, f),
103            ValueRef::Int16(v) => fmt::Display::fmt(v, f),
104            ValueRef::Int32(v) => fmt::Display::fmt(v, f),
105            ValueRef::Int64(v) => fmt::Display::fmt(v, f),
106            ValueRef::String(v) => match str::from_utf8(v) {
107                Ok(s) => fmt::Display::fmt(s, f),
108                Err(_) => write!(f, "{:?}", *v)
109            },
110            ValueRef::Float32(v) => fmt::Display::fmt(v, f),
111            ValueRef::Float64(v) => fmt::Display::fmt(v, f),
112            ValueRef::Date(v, tz) if f.alternate() => {
113                let time = tz.timestamp(i64::from(*v) * 24 * 3600, 0);
114                let date = time.date();
115                fmt::Display::fmt(&date, f)
116            }
117            ValueRef::Date(v, tz) => {
118                let time = tz.timestamp(i64::from(*v) * 24 * 3600, 0);
119                let date = time.date();
120                fmt::Display::fmt(&date.format("%Y-%m-%d"), f)
121            }
122            ValueRef::DateTime(u, tz) if f.alternate() => {
123                let time = tz.timestamp(i64::from(*u), 0);
124                write!(f, "{}", time.to_rfc2822())
125            }
126            ValueRef::DateTime(u, tz) => {
127                let time = tz.timestamp(i64::from(*u), 0);
128                fmt::Display::fmt(&time.format("%Y-%m-%d %H:%M:%S"), f)
129            }
130            ValueRef::DateTime64(u, params) => {
131                let (precision, tz) = **params;
132                let time = to_datetime(*u, precision, tz);
133                fmt::Display::fmt(&time.format("%Y-%m-%d %H:%M:%S"), f)
134            }
135            ValueRef::Nullable(v) => match v {
136                Either::Left(_) => write!(f, "NULL"),
137                Either::Right(inner) => write!(f, "{}", inner)
138            },
139            ValueRef::Array(_, vs) => {
140                let cells: Vec<String> = vs.iter().map(|v| format!("{}", v)).collect();
141                write!(f, "[{}]", cells.join(", "))
142            }
143            ValueRef::Decimal(v) => fmt::Display::fmt(v, f),
144            ValueRef::Ipv4(v) => {
145                write!(f, "{}", decode_ipv4(v))
146            }
147            ValueRef::Ipv6(v) => {
148                write!(f, "{}", decode_ipv6(v))
149            }
150            ValueRef::Uuid(v) => {
151                let mut buffer = *v;
152                buffer[..8].reverse();
153                buffer[8..].reverse();
154                match Uuid::from_slice(&buffer) {
155                    Ok(uuid) => write!(f, "{}", uuid),
156                    Err(e) => write!(f, "{}", e)
157                }
158            }
159            ValueRef::Enum8(_, v) => fmt::Display::fmt(v, f),
160            ValueRef::Enum16(_, v) => fmt::Display::fmt(v, f)
161        }
162    }
163}
164
165impl<'a> convert::From<ValueRef<'a>> for SqlType {
166    fn from(source: ValueRef<'a>) -> Self {
167        match source {
168            ValueRef::UInt8(_) => SqlType::UInt8,
169            ValueRef::UInt16(_) => SqlType::UInt16,
170            ValueRef::UInt32(_) => SqlType::UInt32,
171            ValueRef::UInt64(_) => SqlType::UInt64,
172            ValueRef::Int8(_) => SqlType::Int8,
173            ValueRef::Int16(_) => SqlType::Int16,
174            ValueRef::Int32(_) => SqlType::Int32,
175            ValueRef::Int64(_) => SqlType::Int64,
176            ValueRef::String(_) => SqlType::String,
177            ValueRef::Float32(_) => SqlType::Float32,
178            ValueRef::Float64(_) => SqlType::Float64,
179            ValueRef::Date(_, _) => SqlType::Date,
180            ValueRef::DateTime(_, _) => SqlType::DateTime(DateTimeType::DateTime32),
181            ValueRef::Nullable(u) => match u {
182                Either::Left(sql_type) => SqlType::Nullable(sql_type),
183                Either::Right(value_ref) => SqlType::Nullable(SqlType::from(*value_ref).into())
184            },
185            ValueRef::Array(t, _) => SqlType::Array(t),
186            ValueRef::Decimal(v) => SqlType::Decimal(v.precision, v.scale),
187            ValueRef::Enum8(values, _) => SqlType::Enum8(values),
188            ValueRef::Enum16(values, _) => SqlType::Enum16(values),
189            ValueRef::Ipv4(_) => SqlType::Ipv4,
190            ValueRef::Ipv6(_) => SqlType::Ipv6,
191            ValueRef::Uuid(_) => SqlType::Uuid,
192            ValueRef::DateTime64(_, params) => {
193                let (precision, tz) = params;
194                SqlType::DateTime(DateTimeType::DateTime64(*precision, *tz))
195            }
196        }
197    }
198}
199
200impl<'a> ValueRef<'a> {
201    pub fn as_str(&self) -> Result<&'a str> {
202        if let ValueRef::String(t) = self {
203            return Ok(str::from_utf8(t)?);
204        }
205        let from = SqlType::from(self.clone()).to_string();
206        Err(Error::FromSql(FromSqlError::InvalidType {
207            src: from,
208            dst: "&str".into()
209        }))
210    }
211
212    pub fn as_string(&self) -> Result<String> {
213        let tmp = self.as_str()?;
214        Ok(tmp.to_string())
215    }
216
217    pub fn as_bytes(&self) -> Result<&'a [u8]> {
218        if let ValueRef::String(t) = self {
219            return Ok(t);
220        }
221        let from = SqlType::from(self.clone()).to_string();
222        Err(Error::FromSql(FromSqlError::InvalidType {
223            src: from,
224            dst: "&[u8]".into()
225        }))
226    }
227}
228
229impl<'a> From<ValueRef<'a>> for Value {
230    fn from(borrowed: ValueRef<'a>) -> Self {
231        match borrowed {
232            ValueRef::UInt8(v) => Value::UInt8(v),
233            ValueRef::UInt16(v) => Value::UInt16(v),
234            ValueRef::UInt32(v) => Value::UInt32(v),
235            ValueRef::UInt64(v) => Value::UInt64(v),
236            ValueRef::Int8(v) => Value::Int8(v),
237            ValueRef::Int16(v) => Value::Int16(v),
238            ValueRef::Int32(v) => Value::Int32(v),
239            ValueRef::Int64(v) => Value::Int64(v),
240            ValueRef::String(v) => Value::String(Arc::new(v.into())),
241            ValueRef::Float32(v) => Value::Float32(v),
242            ValueRef::Float64(v) => Value::Float64(v),
243            ValueRef::Date(v, tz) => Value::Date(v, tz),
244            ValueRef::DateTime(v, tz) => Value::DateTime(v, tz),
245            ValueRef::Nullable(u) => match u {
246                Either::Left(sql_type) => Value::Nullable(Either::Left((sql_type.clone()).into())),
247                Either::Right(v) => {
248                    let value: Value = (*v).into();
249                    Value::Nullable(Either::Right(Box::new(value)))
250                }
251            },
252            ValueRef::Array(t, vs) => {
253                let mut value_list: Vec<Value> = Vec::with_capacity(vs.len());
254                for v in vs.iter() {
255                    let value: Value = v.clone().into();
256                    value_list.push(value);
257                }
258                Value::Array(t, Arc::new(value_list))
259            }
260            ValueRef::Decimal(v) => Value::Decimal(v),
261            ValueRef::Enum8(e_v, v) => Value::Enum8(e_v, v),
262            ValueRef::Enum16(e_v, v) => Value::Enum16(e_v, v),
263            ValueRef::Ipv4(v) => Value::Ipv4(v),
264            ValueRef::Ipv6(v) => Value::Ipv6(v),
265            ValueRef::Uuid(v) => Value::Uuid(v),
266            ValueRef::DateTime64(v, params) => Value::DateTime64(v, *params)
267        }
268    }
269}
270
271impl<'a> From<&'a str> for ValueRef<'a> {
272    fn from(s: &str) -> ValueRef {
273        ValueRef::String(s.as_bytes())
274    }
275}
276
277impl<'a> From<&'a [u8]> for ValueRef<'a> {
278    fn from(bs: &[u8]) -> ValueRef {
279        ValueRef::String(bs)
280    }
281}
282
283macro_rules! from_number {
284    ( $($t:ty: $k:ident),* ) => {
285        $(
286            impl<'a> From<$t> for ValueRef<'a> {
287                fn from(v: $t) -> ValueRef<'static> {
288                    ValueRef::$k(v)
289                }
290            }
291        )*
292    };
293}
294
295from_number! {
296    u8: UInt8,
297    u16: UInt16,
298    u32: UInt32,
299    u64: UInt64,
300
301    i8: Int8,
302    i16: Int16,
303    i32: Int32,
304    i64: Int64,
305
306    f32: Float32,
307    f64: Float64
308}
309
310impl<'a> From<&'a Value> for ValueRef<'a> {
311    fn from(value: &'a Value) -> ValueRef<'a> {
312        match value {
313            Value::UInt8(v) => ValueRef::UInt8(*v),
314            Value::UInt16(v) => ValueRef::UInt16(*v),
315            Value::UInt32(v) => ValueRef::UInt32(*v),
316            Value::UInt64(v) => ValueRef::UInt64(*v),
317            Value::Int8(v) => ValueRef::Int8(*v),
318            Value::Int16(v) => ValueRef::Int16(*v),
319            Value::Int32(v) => ValueRef::Int32(*v),
320            Value::Int64(v) => ValueRef::Int64(*v),
321            Value::String(v) => ValueRef::String(v),
322            Value::Float32(v) => ValueRef::Float32(*v),
323            Value::Float64(v) => ValueRef::Float64(*v),
324            Value::Date(v, tz) => ValueRef::Date(*v, *tz),
325            Value::DateTime(v, tz) => ValueRef::DateTime(*v, *tz),
326            Value::DateTime64(v, params) => ValueRef::DateTime64(*v, params),
327            Value::Nullable(u) => match u {
328                Either::Left(sql_type) => ValueRef::Nullable(Either::Left(sql_type.to_owned())),
329                Either::Right(v) => {
330                    let value_ref = v.as_ref().into();
331                    ValueRef::Nullable(Either::Right(Box::new(value_ref)))
332                }
333            },
334            Value::Array(t, vs) => {
335                let mut ref_vec = Vec::with_capacity(vs.len());
336                for v in vs.iter() {
337                    let value_ref: ValueRef<'a> = From::from(v);
338                    ref_vec.push(value_ref)
339                }
340                ValueRef::Array(*t, Arc::new(ref_vec))
341            }
342            Value::Decimal(v) => ValueRef::Decimal(v.clone()),
343            Value::Enum8(values, v) => ValueRef::Enum8(values.to_vec(), *v),
344            Value::Enum16(values, v) => ValueRef::Enum16(values.to_vec(), *v),
345            Value::Ipv4(v) => ValueRef::Ipv4(*v),
346            Value::Ipv6(v) => ValueRef::Ipv6(*v),
347            Value::Uuid(v) => ValueRef::Uuid(*v)
348        }
349    }
350}
351
352macro_rules! value_from {
353    ( $( $t:ty: $k:ident ),* ) => {
354        $(
355            impl<'a> From<ValueRef<'a>> for $t {
356                fn from(value: ValueRef<'a>) -> Self {
357                    if let ValueRef::$k(v) = value {
358                        return v
359                    }
360                    let from = format!("{}", SqlType::from(value.clone()));
361                    panic!("Can't convert ValueRef::{} into {}.",
362                            from, stringify!($t))
363                }
364            }
365        )*
366    };
367}
368
369impl<'a> From<ValueRef<'a>> for AppDate {
370    fn from(value: ValueRef<'a>) -> Self {
371        if let ValueRef::Date(v, tz) = value {
372            let time = tz.timestamp(i64::from(v) * 24 * 3600, 0);
373            return time.date();
374        }
375        let from = format!("{}", SqlType::from(value.clone()));
376        panic!("Can't convert ValueRef::{} into {}.", from, stringify!($t))
377    }
378}
379
380impl<'a> From<ValueRef<'a>> for AppDateTime {
381    fn from(value: ValueRef<'a>) -> Self {
382        match value {
383            ValueRef::DateTime(x, tz) => tz.timestamp(i64::from(x), 0),
384            ValueRef::DateTime64(x, params) => {
385                let (precision, tz) = *params;
386                to_datetime(x, precision, tz)
387            }
388            _ => {
389                let from = format!("{}", SqlType::from(value.clone()));
390                panic!("Can't convert ValueRef::{} into {}.", from, "DateTime<Tz>")
391            }
392        }
393    }
394}
395
396value_from! {
397    u8: UInt8,
398    u16: UInt16,
399    u32: UInt32,
400    u64: UInt64,
401
402    i8: Int8,
403    i16: Int16,
404    i32: Int32,
405    i64: Int64,
406
407    f32: Float32,
408    f64: Float64
409}
410
411#[cfg(test)]
412mod test {
413    use super::*;
414
415    #[test]
416    fn test_display() {
417        assert_eq!(
418            "[0, 159, 146, 150]".to_string(),
419            format!("{}", ValueRef::String(&[0, 159, 146, 150]))
420        );
421
422        assert_eq!("text".to_string(), format!("{}", ValueRef::String(b"text")));
423
424        assert_eq!("42".to_string(), format!("{}", ValueRef::UInt8(42)));
425        assert_eq!("42".to_string(), format!("{}", ValueRef::UInt16(42)));
426        assert_eq!("42".to_string(), format!("{}", ValueRef::UInt32(42)));
427        assert_eq!("42".to_string(), format!("{}", ValueRef::UInt64(42)));
428
429        assert_eq!("42".to_string(), format!("{}", ValueRef::Int8(42)));
430        assert_eq!("42".to_string(), format!("{}", ValueRef::Int16(42)));
431        assert_eq!("42".to_string(), format!("{}", ValueRef::Int32(42)));
432        assert_eq!("42".to_string(), format!("{}", ValueRef::Int64(42)));
433
434        assert_eq!("42".to_string(), format!("{}", ValueRef::Float32(42.0)));
435        assert_eq!("42".to_string(), format!("{}", ValueRef::Float64(42.0)));
436
437        assert_eq!(
438            "NULL".to_string(),
439            format!(
440                "{}",
441                ValueRef::Nullable(Either::Left(SqlType::UInt8.into()))
442            )
443        );
444
445        assert_eq!(
446            "42".to_string(),
447            format!(
448                "{}",
449                ValueRef::Nullable(Either::Right(Box::new(ValueRef::UInt8(42))))
450            )
451        );
452
453        assert_eq!(
454            "[1, 2, 3]".to_string(),
455            format!(
456                "{}",
457                ValueRef::Array(
458                    SqlType::Int32.into(),
459                    Arc::new(vec![
460                        ValueRef::Int32(1),
461                        ValueRef::Int32(2),
462                        ValueRef::Int32(3)
463                    ])
464                )
465            )
466        );
467
468        assert_eq!(
469            "1970-01-01".to_string(),
470            format!("{}", ValueRef::Date(0, Tz::Zulu))
471        );
472
473        assert_eq!(
474            "1970-01-01UTC".to_string(),
475            format!("{:#}", ValueRef::Date(0, Tz::Zulu))
476        );
477
478        assert_eq!(
479            "1970-01-01 00:00:00".to_string(),
480            format!("{}", ValueRef::DateTime(0, Tz::Zulu))
481        );
482
483        assert_eq!(
484            "Thu, 01 Jan 1970 00:00:00 +0000".to_string(),
485            format!("{:#}", ValueRef::DateTime(0, Tz::Zulu))
486        );
487
488        assert_eq!(
489            "2.00".to_string(),
490            format!("{}", ValueRef::Decimal(Decimal::of(2.0_f64, 2)))
491        )
492    }
493
494    #[test]
495    fn test_size_of() {
496        use std::mem;
497        assert_eq!(32, mem::size_of::<[ValueRef<'_>; 1]>());
498    }
499
500    #[test]
501    fn test_value_from_ref() {
502        assert_eq!(Value::from(ValueRef::UInt8(42)), Value::UInt8(42));
503        assert_eq!(Value::from(ValueRef::UInt16(42)), Value::UInt16(42));
504        assert_eq!(Value::from(ValueRef::UInt32(42)), Value::UInt32(42));
505        assert_eq!(Value::from(ValueRef::UInt64(42)), Value::UInt64(42));
506
507        assert_eq!(Value::from(ValueRef::Int8(42)), Value::Int8(42));
508        assert_eq!(Value::from(ValueRef::Int16(42)), Value::Int16(42));
509        assert_eq!(Value::from(ValueRef::Int32(42)), Value::Int32(42));
510        assert_eq!(Value::from(ValueRef::Int64(42)), Value::Int64(42));
511
512        assert_eq!(Value::from(ValueRef::Float32(42.0)), Value::Float32(42.0));
513        assert_eq!(Value::from(ValueRef::Float64(42.0)), Value::Float64(42.0));
514
515        assert_eq!(
516            Value::from(ValueRef::Date(42, Tz::Zulu)),
517            Value::Date(42, Tz::Zulu)
518        );
519        assert_eq!(
520            Value::from(ValueRef::DateTime(42, Tz::Zulu)),
521            Value::DateTime(42, Tz::Zulu)
522        );
523
524        assert_eq!(
525            Value::from(ValueRef::Decimal(Decimal::of(2.0_f64, 4))),
526            Value::Decimal(Decimal::of(2.0_f64, 4))
527        );
528
529        assert_eq!(
530            Value::from(ValueRef::Array(
531                SqlType::Int32.into(),
532                Arc::new(vec![
533                    ValueRef::Int32(1),
534                    ValueRef::Int32(2),
535                    ValueRef::Int32(3)
536                ])
537            )),
538            Value::Array(
539                SqlType::Int32.into(),
540                Arc::new(vec![Value::Int32(1), Value::Int32(2), Value::Int32(3)])
541            )
542        )
543    }
544
545    #[test]
546    fn test_uuid() {
547        let uuid = Uuid::parse_str("936da01f-9abd-4d9d-80c7-02af85c822a8").unwrap();
548        let mut buffer = *uuid.as_bytes();
549        buffer[..8].reverse();
550        buffer[8..].reverse();
551        let v = ValueRef::Uuid(buffer);
552        assert_eq!(v.to_string(), "936da01f-9abd-4d9d-80c7-02af85c822a8");
553    }
554
555    #[test]
556    fn test_get_sql_type() {
557        assert_eq!(SqlType::from(ValueRef::UInt8(42)), SqlType::UInt8);
558        assert_eq!(SqlType::from(ValueRef::UInt16(42)), SqlType::UInt16);
559        assert_eq!(SqlType::from(ValueRef::UInt32(42)), SqlType::UInt32);
560        assert_eq!(SqlType::from(ValueRef::UInt64(42)), SqlType::UInt64);
561
562        assert_eq!(SqlType::from(ValueRef::Int8(42)), SqlType::Int8);
563        assert_eq!(SqlType::from(ValueRef::Int16(42)), SqlType::Int16);
564        assert_eq!(SqlType::from(ValueRef::Int32(42)), SqlType::Int32);
565        assert_eq!(SqlType::from(ValueRef::Int64(42)), SqlType::Int64);
566
567        assert_eq!(SqlType::from(ValueRef::Float32(42.0)), SqlType::Float32);
568        assert_eq!(SqlType::from(ValueRef::Float64(42.0)), SqlType::Float64);
569
570        assert_eq!(SqlType::from(ValueRef::String(&[])), SqlType::String);
571
572        assert_eq!(SqlType::from(ValueRef::Date(42, Tz::Zulu)), SqlType::Date);
573        assert_eq!(
574            SqlType::from(ValueRef::DateTime(42, Tz::Zulu)),
575            SqlType::DateTime(DateTimeType::DateTime32)
576        );
577
578        assert_eq!(
579            SqlType::from(ValueRef::Decimal(Decimal::of(2.0_f64, 4))),
580            SqlType::Decimal(18, 4)
581        );
582
583        assert_eq!(
584            SqlType::from(ValueRef::Array(
585                SqlType::Int32.into(),
586                Arc::new(vec![
587                    ValueRef::Int32(1),
588                    ValueRef::Int32(2),
589                    ValueRef::Int32(3)
590                ])
591            )),
592            SqlType::Array(SqlType::Int32.into())
593        );
594
595        assert_eq!(
596            SqlType::from(ValueRef::Nullable(Either::Left(SqlType::UInt8.into()))),
597            SqlType::Nullable(SqlType::UInt8.into())
598        );
599
600        assert_eq!(
601            SqlType::from(ValueRef::Nullable(Either::Right(Box::new(ValueRef::Int8(
602                42
603            ))))),
604            SqlType::Nullable(SqlType::Int8.into())
605        );
606    }
607}