clickhouse_rs_async/types/
value.rs

1use std::{
2    collections::HashMap,
3    convert, fmt,
4    hash::{Hash, Hasher},
5    mem,
6    net::{Ipv4Addr, Ipv6Addr},
7    str,
8    sync::Arc,
9};
10
11use chrono::{prelude::*, Duration};
12use chrono_tz::Tz;
13use either::Either;
14use uuid::Uuid;
15
16use crate::types::{
17    column::datetime64::{to_datetime, DEFAULT_TZ},
18    decimal::{Decimal, NoBits},
19    DateConverter, DateTimeType, Enum16, Enum8, HasSqlType, SqlType,
20};
21
22pub(crate) type AppDateTime = DateTime<Tz>;
23pub(crate) type AppDate = NaiveDate;
24
25/// Client side representation of a value of Clickhouse column.
26#[derive(Clone, Debug)]
27pub enum Value {
28    Bool(bool),
29    UInt8(u8),
30    UInt16(u16),
31    UInt32(u32),
32    UInt64(u64),
33    UInt128(u128),
34    Int8(i8),
35    Int16(i16),
36    Int32(i32),
37    Int64(i64),
38    Int128(i128),
39    String(Arc<Vec<u8>>),
40    Float32(f32),
41    Float64(f64),
42    Date(u16),
43    DateTime(u32, Tz),
44    DateTime64(i64, (u32, Tz)),
45    ChronoDateTime(DateTime<Tz>),
46    Ipv4([u8; 4]),
47    Ipv6([u8; 16]),
48    Uuid([u8; 16]),
49    Nullable(Either<&'static SqlType, Box<Value>>),
50    Array(&'static SqlType, Arc<Vec<Value>>),
51    Decimal(Decimal),
52    Enum8(Vec<(String, i8)>, Enum8),
53    Enum16(Vec<(String, i16)>, Enum16),
54    Map(
55        &'static SqlType,
56        &'static SqlType,
57        Arc<HashMap<Value, Value>>,
58    ),
59}
60
61impl Hash for Value {
62    fn hash<H: Hasher>(&self, state: &mut H) {
63        match self {
64            Self::String(s) => s.hash(state),
65            Self::Int8(i) => i.hash(state),
66            Self::Int16(i) => i.hash(state),
67            Self::Int32(i) => i.hash(state),
68            Self::Int64(i) => i.hash(state),
69            Self::Int128(i) => i.hash(state),
70            Self::UInt8(i) => i.hash(state),
71            Self::UInt16(i) => i.hash(state),
72            Self::UInt32(i) => i.hash(state),
73            Self::UInt64(i) => i.hash(state),
74            Self::UInt128(i) => i.hash(state),
75            Self::Date(d) => d.hash(state),
76            Self::DateTime(t, _) => t.hash(state),
77            Self::DateTime64(t, (prec_a, _)) => (*t, *prec_a).hash(state),
78            _ => unimplemented!(),
79        }
80    }
81}
82
83impl Eq for Value {}
84
85impl PartialEq for Value {
86    fn eq(&self, other: &Self) -> bool {
87        match (self, other) {
88            (Value::Bool(a), Value::Bool(b)) => *a == *b,
89            (Value::UInt8(a), Value::UInt8(b)) => *a == *b,
90            (Value::UInt16(a), Value::UInt16(b)) => *a == *b,
91            (Value::UInt32(a), Value::UInt32(b)) => *a == *b,
92            (Value::UInt64(a), Value::UInt64(b)) => *a == *b,
93            (Value::UInt128(a), Value::UInt128(b)) => *a == *b,
94            (Value::Int8(a), Value::Int8(b)) => *a == *b,
95            (Value::Int16(a), Value::Int16(b)) => *a == *b,
96            (Value::Int32(a), Value::Int32(b)) => *a == *b,
97            (Value::Int64(a), Value::Int64(b)) => *a == *b,
98            (Value::Int128(a), Value::Int128(b)) => *a == *b,
99            (Value::String(a), Value::String(b)) => *a == *b,
100            (Value::Float32(a), Value::Float32(b)) => *a == *b,
101            (Value::Float64(a), Value::Float64(b)) => *a == *b,
102            (Value::Date(a), Value::Date(b)) => *a == *b,
103            (Value::DateTime(a, tz_a), Value::DateTime(b, tz_b)) => {
104                let time_a = tz_a.timestamp_opt(i64::from(*a), 0).unwrap();
105                let time_b = tz_b.timestamp_opt(i64::from(*b), 0).unwrap();
106                time_a == time_b
107            }
108            (Value::ChronoDateTime(a), Value::ChronoDateTime(b)) => *a == *b,
109            (Value::Nullable(a), Value::Nullable(b)) => *a == *b,
110            (Value::Array(ta, a), Value::Array(tb, b)) => *ta == *tb && *a == *b,
111            (Value::Decimal(a), Value::Decimal(b)) => *a == *b,
112            (Value::Enum8(values_a, val_a), Value::Enum8(values_b, val_b)) => {
113                *values_a == *values_b && *val_a == *val_b
114            }
115            (Value::Enum16(values_a, val_a), Value::Enum16(values_b, val_b)) => {
116                *values_a == *values_b && *val_a == *val_b
117            }
118            (Value::Ipv4(a), Value::Ipv4(b)) => *a == *b,
119            (Value::Ipv6(a), Value::Ipv6(b)) => *a == *b,
120            (Value::Uuid(a), Value::Uuid(b)) => *a == *b,
121            (Value::DateTime64(a, (prec_a, tz_a)), Value::DateTime64(b, (prec_b, tz_b))) => {
122                // chrono has no "variable-precision" offset method. As a
123                // fallback, we always use `timestamp_nanos` and multiply by
124                // the correct value.
125                #[rustfmt::skip]
126                const MULTIPLIERS: [i64; 10] = [
127                    1_000_000_000, // 1 s  is 10^9 nanos
128                      100_000_000,
129                       10_000_000,
130                        1_000_000, // 1 ms is 10^6 nanos
131                          100_000,
132                           10_000,
133                            1_000, // 1 µs is 10^3 nanos
134                              100,
135                               10,
136                                1, // 1 ns is 1 nanos!
137                ];
138
139                // The precision must be in the [0 - 9] range. As such, the
140                // following indexing can not fail.
141                prec_a == prec_b
142                    && tz_a.timestamp_nanos(a * MULTIPLIERS[*prec_a as usize])
143                        == tz_b.timestamp_nanos(b * MULTIPLIERS[*prec_b as usize])
144            }
145
146            _ => false,
147        }
148    }
149}
150
151impl Value {
152    pub(crate) fn default(sql_type: SqlType) -> Value {
153        match sql_type {
154            SqlType::Bool => Value::Bool(false),
155            SqlType::UInt8 => Value::UInt8(0),
156            SqlType::UInt16 => Value::UInt16(0),
157            SqlType::UInt32 => Value::UInt32(0),
158            SqlType::UInt64 => Value::UInt64(0),
159            SqlType::UInt128 => Value::UInt128(0),
160            SqlType::Int8 => Value::Int8(0),
161            SqlType::Int16 => Value::Int16(0),
162            SqlType::Int32 => Value::Int32(0),
163            SqlType::Int64 => Value::Int64(0),
164            SqlType::Int128 => Value::Int128(0),
165            SqlType::String => Value::String(Arc::new(Vec::default())),
166            SqlType::LowCardinality(inner) => Value::default(inner.clone()),
167            SqlType::FixedString(str_len) => Value::String(Arc::new(vec![0_u8; str_len])),
168            SqlType::Float32 => Value::Float32(0.0),
169            SqlType::Float64 => Value::Float64(0.0),
170            SqlType::Date => 0_u16.to_date(*DEFAULT_TZ).into(),
171            SqlType::DateTime(DateTimeType::DateTime64(_, _)) => {
172                Value::DateTime64(0, (1, *DEFAULT_TZ))
173            }
174            SqlType::SimpleAggregateFunction(_, nested) => Value::default(nested.clone()),
175            SqlType::DateTime(_) => 0_u32.to_date(*DEFAULT_TZ).into(),
176            SqlType::Nullable(inner) => Value::Nullable(Either::Left(inner)),
177            SqlType::Array(inner) => Value::Array(inner, Arc::new(Vec::default())),
178            SqlType::Decimal(precision, scale) => Value::Decimal(Decimal {
179                underlying: 0,
180                precision,
181                scale,
182                nobits: NoBits::N64,
183            }),
184            SqlType::Ipv4 => Value::Ipv4([0_u8; 4]),
185            SqlType::Ipv6 => Value::Ipv6([0_u8; 16]),
186            SqlType::Uuid => Value::Uuid([0_u8; 16]),
187            SqlType::Enum8(values) => Value::Enum8(values, Enum8(0)),
188            SqlType::Enum16(values) => Value::Enum16(values, Enum16(0)),
189            SqlType::Map(k, v) => Value::Map(k, v, Arc::new(HashMap::default())),
190        }
191    }
192}
193
194impl fmt::Display for Value {
195    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
196        match self {
197            Value::Bool(ref v) => fmt::Display::fmt(v, f),
198            Value::UInt8(ref v) => fmt::Display::fmt(v, f),
199            Value::UInt16(ref v) => fmt::Display::fmt(v, f),
200            Value::UInt32(ref v) => fmt::Display::fmt(v, f),
201            Value::UInt64(ref v) => fmt::Display::fmt(v, f),
202            Value::UInt128(ref v) => fmt::Display::fmt(v, f),
203            Value::Int8(ref v) => fmt::Display::fmt(v, f),
204            Value::Int16(ref v) => fmt::Display::fmt(v, f),
205            Value::Int32(ref v) => fmt::Display::fmt(v, f),
206            Value::Int64(ref v) => fmt::Display::fmt(v, f),
207            Value::Int128(ref v) => fmt::Display::fmt(v, f),
208            Value::String(ref v) => match str::from_utf8(v) {
209                Ok(s) => fmt::Display::fmt(s, f),
210                Err(_) => write!(f, "{v:?}"),
211            },
212            Value::Float32(ref v) => fmt::Display::fmt(v, f),
213            Value::Float64(ref v) => fmt::Display::fmt(v, f),
214            Value::DateTime(u, tz) if f.alternate() => {
215                let time = tz.timestamp_opt(i64::from(*u), 0).unwrap();
216                fmt::Display::fmt(&time, f)
217            }
218            Value::DateTime(u, tz) => {
219                let time = tz.timestamp_opt(i64::from(*u), 0).unwrap();
220                write!(f, "{}", time.to_rfc2822())
221            }
222            Value::DateTime64(value, params) => {
223                let (precision, tz) = params;
224                let time = to_datetime(*value, *precision, *tz);
225                write!(f, "{}", time.to_rfc2822())
226            }
227            Value::ChronoDateTime(time) => {
228                write!(f, "{}", time.to_rfc2822())
229            }
230            Value::Date(v) if f.alternate() => {
231                let date = NaiveDate::from_ymd_opt(1970, 1, 1)
232                    .map(|unix_epoch| unix_epoch + Duration::days((*v).into()))
233                    .unwrap();
234                fmt::Display::fmt(&date, f)
235            }
236            Value::Date(v) => {
237                let date = NaiveDate::from_ymd_opt(1970, 1, 1)
238                    .map(|unix_epoch| unix_epoch + Duration::days((*v).into()))
239                    .unwrap();
240                fmt::Display::fmt(&date.format("%Y-%m-%d"), f)
241            }
242            Value::Nullable(v) => match v {
243                Either::Left(_) => write!(f, "NULL"),
244                Either::Right(data) => data.fmt(f),
245            },
246            Value::Array(_, vs) => {
247                let cells: Vec<String> = vs.iter().map(|v| format!("{v}")).collect();
248                write!(f, "[{}]", cells.join(", "))
249            }
250            Value::Decimal(v) => fmt::Display::fmt(v, f),
251            Value::Ipv4(v) => {
252                write!(f, "{}", decode_ipv4(v))
253            }
254            Value::Ipv6(v) => {
255                write!(f, "{}", decode_ipv6(v))
256            }
257            Value::Uuid(v) => {
258                let mut buffer = *v;
259                buffer[..8].reverse();
260                buffer[8..].reverse();
261                match Uuid::from_slice(&buffer) {
262                    Ok(uuid) => write!(f, "{uuid}"),
263                    Err(e) => write!(f, "{e}"),
264                }
265            }
266            Value::Enum8(ref _v1, ref v2) => write!(f, "Enum8, {v2}"),
267            Value::Enum16(ref _v1, ref v2) => write!(f, "Enum16, {v2}"),
268            Value::Map(_, _, hm) => {
269                let cells: Vec<String> = hm
270                    .iter()
271                    .map(|(k, v)| format!("key=>{k} value=>{v}"))
272                    .collect();
273                write!(f, "[{}]", cells.join(", "))
274            }
275        }
276    }
277}
278
279impl From<Value> for SqlType {
280    fn from(source: Value) -> Self {
281        match source {
282            Value::Bool(_) => SqlType::Bool,
283            Value::UInt8(_) => SqlType::UInt8,
284            Value::UInt16(_) => SqlType::UInt16,
285            Value::UInt32(_) => SqlType::UInt32,
286            Value::UInt64(_) => SqlType::UInt64,
287            Value::UInt128(_) => SqlType::UInt128,
288            Value::Int8(_) => SqlType::Int8,
289            Value::Int16(_) => SqlType::Int16,
290            Value::Int32(_) => SqlType::Int32,
291            Value::Int64(_) => SqlType::Int64,
292            Value::Int128(_) => SqlType::Int128,
293            Value::String(_) => SqlType::String,
294            Value::Float32(_) => SqlType::Float32,
295            Value::Float64(_) => SqlType::Float64,
296            Value::Date(_) => SqlType::Date,
297            Value::DateTime(_, _) => SqlType::DateTime(DateTimeType::DateTime32),
298            Value::ChronoDateTime(_) => SqlType::DateTime(DateTimeType::DateTime32),
299            Value::Nullable(d) => match d {
300                Either::Left(t) => SqlType::Nullable(t),
301                Either::Right(inner) => {
302                    let sql_type = SqlType::from(inner.as_ref().to_owned());
303                    SqlType::Nullable(sql_type.into())
304                }
305            },
306            Value::Array(t, _) => SqlType::Array(t),
307            Value::Decimal(v) => SqlType::Decimal(v.precision, v.scale),
308            Value::Ipv4(_) => SqlType::Ipv4,
309            Value::Ipv6(_) => SqlType::Ipv6,
310            Value::Uuid(_) => SqlType::Uuid,
311            Value::Enum8(values, _) => SqlType::Enum8(values),
312            Value::Enum16(values, _) => SqlType::Enum16(values),
313            Value::DateTime64(_, params) => {
314                let (precision, tz) = params;
315                SqlType::DateTime(DateTimeType::DateTime64(precision, tz))
316            }
317            Value::Map(k, v, _) => SqlType::Map(k, v),
318        }
319    }
320}
321
322impl<T> From<Option<T>> for Value
323where
324    Value: From<T>,
325    T: HasSqlType,
326{
327    fn from(value: Option<T>) -> Value {
328        match value {
329            None => {
330                let default_type: SqlType = T::get_sql_type();
331                Value::Nullable(Either::Left(default_type.into()))
332            }
333            Some(inner) => Value::Nullable(Either::Right(Box::new(inner.into()))),
334        }
335    }
336}
337
338macro_rules! value_from {
339    ( $( $t:ty : $k:ident ),* ) => {
340        $(
341            impl convert::From<$t> for Value {
342                fn from(v: $t) -> Value {
343                    Value::$k(v.into())
344                }
345            }
346        )*
347    };
348}
349
350macro_rules! value_array_from {
351    ( $( $t:ty : $k:ident ),* ) => {
352        $(
353            impl convert::From<Vec<$t>> for Value {
354                fn from(v: Vec<$t>) -> Self {
355                    Value::Array(
356                        SqlType::$k.into(),
357                        Arc::new(v.into_iter().map(|s| s.into()).collect())
358                    )
359                }
360            }
361        )*
362    };
363}
364
365impl From<AppDate> for Value {
366    fn from(v: AppDate) -> Value {
367        Value::Date(u16::get_days(v))
368    }
369}
370
371impl From<Enum8> for Value {
372    fn from(v: Enum8) -> Value {
373        Value::Enum8(Vec::new(), v)
374    }
375}
376
377impl From<Enum16> for Value {
378    fn from(v: Enum16) -> Value {
379        Value::Enum16(Vec::new(), v)
380    }
381}
382
383impl From<AppDateTime> for Value {
384    fn from(v: AppDateTime) -> Value {
385        Value::ChronoDateTime(v)
386    }
387}
388
389impl From<DateTime<Utc>> for Value {
390    fn from(v: DateTime<Utc>) -> Value {
391        Value::DateTime(v.timestamp() as u32, Tz::UTC)
392    }
393}
394
395impl From<String> for Value {
396    fn from(v: String) -> Value {
397        Value::String(Arc::new(v.into_bytes()))
398    }
399}
400
401impl From<Vec<u8>> for Value {
402    fn from(v: Vec<u8>) -> Value {
403        Value::String(Arc::new(v))
404    }
405}
406
407impl From<&[u8]> for Value {
408    fn from(v: &[u8]) -> Value {
409        Value::String(Arc::new(v.to_vec()))
410    }
411}
412
413impl From<Vec<String>> for Value {
414    fn from(v: Vec<String>) -> Self {
415        Value::Array(
416            SqlType::String.into(),
417            Arc::new(v.into_iter().map(|s| s.into()).collect()),
418        )
419    }
420}
421
422impl From<Uuid> for Value {
423    fn from(v: Uuid) -> Value {
424        let mut buffer = *v.as_bytes();
425        buffer[..8].reverse();
426        buffer[8..].reverse();
427        Value::Uuid(buffer)
428    }
429}
430
431impl<K, V> From<HashMap<K, V>> for Value
432where
433    K: Into<Value> + HasSqlType,
434    V: Into<Value> + HasSqlType,
435{
436    fn from(hm: HashMap<K, V>) -> Self {
437        let mut res = HashMap::with_capacity(hm.capacity());
438
439        for (k, v) in hm {
440            res.insert(k.into(), v.into());
441        }
442        Self::Map(
443            K::get_sql_type().into(),
444            V::get_sql_type().into(),
445            Arc::new(res),
446        )
447    }
448}
449
450value_from! {
451    bool: Bool,
452    u8: UInt8,
453    u16: UInt16,
454    u32: UInt32,
455    u64: UInt64,
456    u128: UInt128,
457
458    i8: Int8,
459    i16: Int16,
460    i32: Int32,
461    i64: Int64,
462    i128: Int128,
463
464    f32: Float32,
465    f64: Float64,
466
467    Decimal: Decimal,
468
469    [u8; 4]: Ipv4,
470    [u8; 16]: Ipv6
471}
472
473value_array_from! {
474    u16: UInt16,
475    u32: UInt32,
476    u64: UInt64,
477    u128: UInt128,
478
479    i8: Int8,
480    i16: Int16,
481    i32: Int32,
482    i64: Int64,
483    i128: Int128,
484
485    f32: Float32,
486    f64: Float64
487}
488
489impl<'a> From<&'a str> for Value {
490    fn from(v: &'a str) -> Self {
491        let bytes: Vec<u8> = v.as_bytes().into();
492        Value::String(Arc::new(bytes))
493    }
494}
495
496impl From<Value> for String {
497    fn from(mut v: Value) -> Self {
498        if let Value::String(ref mut x) = &mut v {
499            let mut tmp = Arc::new(Vec::new());
500            mem::swap(x, &mut tmp);
501            if let Ok(result) = str::from_utf8(tmp.as_ref()) {
502                return result.into();
503            }
504        }
505        let from = SqlType::from(v);
506        panic!("Can't convert Value::{from} into String.");
507    }
508}
509
510pub(crate) fn get_str_buffer(value: &Value) -> &[u8] {
511    match value {
512        Value::String(bs) => bs.as_slice(),
513        _ => {
514            let from = SqlType::from(value.clone());
515            panic!("Can't convert Value::{} into &[u8].", from);
516        }
517    }
518}
519
520impl From<Value> for Vec<u8> {
521    fn from(v: Value) -> Self {
522        match v {
523            Value::String(bs) => bs.to_vec(),
524            _ => {
525                let from = SqlType::from(v);
526                panic!("Can't convert Value::{from} into Vec<u8>.")
527            }
528        }
529    }
530}
531
532macro_rules! from_value {
533    ( $( $t:ty : $k:ident ),* ) => {
534        $(
535            impl convert::From<Value> for $t {
536                fn from(v: Value) -> $t {
537                    if let Value::$k(x) = v {
538                        return x;
539                    }
540                    let from = SqlType::from(v);
541                    panic!("Can't convert Value::{} into {}", from, stringify!($t))
542                }
543            }
544        )*
545    };
546}
547
548impl From<Value> for AppDate {
549    fn from(v: Value) -> AppDate {
550        if let Value::Date(x) = v {
551            return NaiveDate::from_ymd_opt(1970, 1, 1)
552                .map(|unix_epoch| unix_epoch + Duration::days(x.into()))
553                .unwrap();
554        }
555        let from = SqlType::from(v);
556        panic!("Can't convert Value::{} into {}", from, "AppDate")
557    }
558}
559
560impl From<Value> for AppDateTime {
561    fn from(v: Value) -> AppDateTime {
562        match v {
563            Value::DateTime(u, tz) => tz.timestamp_opt(i64::from(u), 0).unwrap(),
564            Value::DateTime64(u, params) => {
565                let (precision, tz) = params;
566                to_datetime(u, precision, tz)
567            }
568            Value::ChronoDateTime(dt) => dt,
569            _ => {
570                let from = SqlType::from(v);
571                panic!("Can't convert Value::{} into {}", from, "DateTime<Tz>")
572            }
573        }
574    }
575}
576
577from_value! {
578    bool: Bool,
579    u8: UInt8,
580    u16: UInt16,
581    u32: UInt32,
582    u64: UInt64,
583    u128: UInt128,
584    i8: Int8,
585    i16: Int16,
586    i32: Int32,
587    i64: Int64,
588    i128: Int128,
589    f32: Float32,
590    f64: Float64,
591    [u8; 4]: Ipv4
592}
593
594pub(crate) fn decode_ipv4(octets: &[u8; 4]) -> Ipv4Addr {
595    let mut buffer = *octets;
596    buffer.reverse();
597    Ipv4Addr::from(buffer)
598}
599
600pub(crate) fn decode_ipv6(octets: &[u8; 16]) -> Ipv6Addr {
601    Ipv6Addr::from(*octets)
602}
603
604#[cfg(test)]
605mod test {
606    use super::*;
607    use chrono_tz::Tz::{self, UTC};
608    use std::fmt;
609
610    use crate::{row, Block};
611    use rand::{
612        distributions::{Distribution, Standard},
613        random,
614    };
615
616    fn test_into_t<T>(v: Value, x: &T)
617    where
618        Value: Into<T>,
619        T: PartialEq + fmt::Debug,
620    {
621        let a: T = v.into();
622        assert_eq!(a, *x);
623    }
624
625    fn test_from_rnd<T>()
626    where
627        Value: Into<T> + From<T>,
628        T: PartialEq + fmt::Debug + Clone,
629        Standard: Distribution<T>,
630    {
631        for _ in 0..100 {
632            let value = random::<T>();
633            test_into_t::<T>(Value::from(value.clone()), &value);
634        }
635    }
636
637    fn test_from_t<T>(value: &T)
638    where
639        Value: Into<T> + From<T>,
640        T: PartialEq + fmt::Debug + Clone,
641    {
642        test_into_t::<T>(Value::from(value.clone()), value);
643    }
644
645    macro_rules! test_type {
646        ( $( $k:ident : $t:ty ),* ) => {
647            $(
648                #[test]
649                fn $k() {
650                    test_from_rnd::<$t>();
651                }
652            )*
653        };
654    }
655
656    test_type! {
657        test_u8: u8,
658        test_u16: u16,
659        test_u32: u32,
660        test_u64: u64,
661
662        test_i8: i8,
663        test_i16: i16,
664        test_i32: i32,
665        test_i64: i64,
666
667        test_f32: f32,
668        test_f64: f64,
669
670        test_ipv4: [u8; 4]
671    }
672
673    #[test]
674    fn test_string() {
675        test_from_t(&"284222f9-aba2-4b05-bcf5-e4e727fe34d1".to_string());
676    }
677
678    #[test]
679    fn test_from_u32() {
680        let v = Value::UInt32(32);
681        let u: u32 = u32::from(v);
682        assert_eq!(u, 32);
683    }
684
685    #[test]
686    fn test_uuid() {
687        let uuid = Uuid::parse_str("936da01f-9abd-4d9d-80c7-02af85c822a8").unwrap();
688        let v = Value::from(uuid);
689        assert_eq!(v.to_string(), "936da01f-9abd-4d9d-80c7-02af85c822a8");
690    }
691
692    #[test]
693    fn test_from_datetime_utc() {
694        let date_time_value: DateTime<Utc> = UTC
695            .with_ymd_and_hms(2014, 7, 8, 14, 0, 0)
696            .unwrap()
697            .with_timezone(&Utc);
698        let v = Value::from(date_time_value);
699        assert_eq!(v, Value::DateTime(date_time_value.timestamp() as u32, UTC));
700    }
701
702    #[test]
703    fn test_from_date() {
704        let date_value: NaiveDate = UTC
705            .with_ymd_and_hms(2016, 10, 22, 0, 0, 0)
706            .unwrap()
707            .date_naive();
708        let date_time_value: DateTime<Tz> = UTC.with_ymd_and_hms(2014, 7, 8, 14, 0, 0).unwrap();
709
710        let d: Value = Value::from(date_value);
711        let dt: Value = date_time_value.into();
712
713        assert_eq!(Value::Date(u16::get_days(date_value)), d);
714        assert_eq!(Value::ChronoDateTime(date_time_value), dt);
715    }
716
717    #[test]
718    fn test_boolean() {
719        let v = Value::from(false);
720        let w = Value::from(true);
721        assert_eq!(v, Value::Bool(false));
722        assert_eq!(w, Value::Bool(true));
723    }
724
725    #[test]
726    fn test_string_from() {
727        let v = Value::String(Arc::new(b"df47a455-bb3c-4bd6-b2f2-a24be3db36ab".to_vec()));
728        let u = String::from(v);
729        assert_eq!("df47a455-bb3c-4bd6-b2f2-a24be3db36ab".to_string(), u);
730    }
731
732    #[test]
733    fn test_into_string() {
734        let v = Value::String(Arc::new(b"d2384838-dfe8-43ea-b1f7-63fb27b91088".to_vec()));
735        let u: String = v.into();
736        assert_eq!("d2384838-dfe8-43ea-b1f7-63fb27b91088".to_string(), u);
737    }
738
739    #[test]
740    fn test_into_vec() {
741        let v = Value::String(Arc::new(vec![1, 2, 3]));
742        let u: Vec<u8> = v.into();
743        assert_eq!(vec![1, 2, 3], u);
744    }
745
746    #[test]
747    fn test_display() {
748        assert_eq!("42".to_string(), format!("{}", Value::UInt8(42)));
749        assert_eq!("42".to_string(), format!("{}", Value::UInt16(42)));
750        assert_eq!("42".to_string(), format!("{}", Value::UInt32(42)));
751        assert_eq!("42".to_string(), format!("{}", Value::UInt64(42)));
752        assert_eq!("42".to_string(), format!("{}", Value::UInt128(42)));
753
754        assert_eq!("42".to_string(), format!("{}", Value::Int8(42)));
755        assert_eq!("42".to_string(), format!("{}", Value::Int16(42)));
756        assert_eq!("42".to_string(), format!("{}", Value::Int32(42)));
757        assert_eq!("42".to_string(), format!("{}", Value::Int64(42)));
758        assert_eq!("42".to_string(), format!("{}", Value::Int128(42)));
759
760        assert_eq!(
761            "text".to_string(),
762            format!("{}", Value::String(Arc::new(b"text".to_vec())))
763        );
764
765        assert_eq!(
766            "\u{1}\u{2}\u{3}".to_string(),
767            format!("{}", Value::String(Arc::new(vec![1, 2, 3])))
768        );
769
770        assert_eq!(
771            "NULL".to_string(),
772            format!("{}", Value::Nullable(Either::Left(SqlType::UInt8.into())))
773        );
774        assert_eq!(
775            "42".to_string(),
776            format!(
777                "{}",
778                Value::Nullable(Either::Right(Box::new(Value::UInt8(42))))
779            )
780        );
781
782        assert_eq!(
783            "[1, 2, 3]".to_string(),
784            format!(
785                "{}",
786                Value::Array(
787                    SqlType::Int32.into(),
788                    Arc::new(vec![Value::Int32(1), Value::Int32(2), Value::Int32(3)])
789                )
790            )
791        );
792    }
793
794    #[test]
795    fn test_default_fixed_str() {
796        for n in 0_usize..1000_usize {
797            let actual = Value::default(SqlType::FixedString(n));
798            let actual_str: String = actual.into();
799            assert_eq!(actual_str.len(), n);
800            for ch in actual_str.as_bytes() {
801                assert_eq!(*ch, 0_u8);
802            }
803        }
804    }
805
806    #[test]
807    fn test_size_of() {
808        use std::mem;
809        assert_eq!(56, mem::size_of::<[Value; 1]>());
810    }
811
812    #[test]
813    fn test_from_some() {
814        assert_eq!(
815            Value::from(Some(1_u32)),
816            Value::Nullable(Either::Right(Value::UInt32(1).into()))
817        );
818        assert_eq!(
819            Value::from(Some("text")),
820            Value::Nullable(Either::Right(Value::String(b"text".to_vec().into()).into()))
821        );
822        assert_eq!(
823            Value::from(Some(3.1)),
824            Value::Nullable(Either::Right(Value::Float64(3.1).into()))
825        );
826        let date_time_val = UTC.with_ymd_and_hms(2019, 1, 1, 0, 0, 0).unwrap();
827        assert_eq!(
828            Value::from(Some(date_time_val)),
829            Value::Nullable(Either::Right(Value::ChronoDateTime(date_time_val).into()))
830        );
831    }
832
833    #[test]
834    fn test_value_array_from() {
835        let mut block = Block::with_capacity(5);
836        block
837            .push(row! {
838                u16: vec![1_u16, 2, 3],
839                u32: vec![1_u32, 2, 3],
840                u64: vec![1_u64, 2, 3],
841                i8: vec![1_i8, 2, 3],
842                i16: vec![1_i16, 2, 3],
843                i32: vec![1_i32, 2, 3],
844                i64: vec![1_i64, 2, 3],
845                f32: vec![1_f32, 2.0, 3.0],
846                f64: vec![1_f64, 2.0, 3.0],
847            })
848            .unwrap();
849
850        assert_eq!(block.row_count(), 1);
851        assert_eq!(block.column_count(), 9);
852    }
853}