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#[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 #[rustfmt::skip]
126 const MULTIPLIERS: [i64; 10] = [
127 1_000_000_000, 100_000_000,
129 10_000_000,
130 1_000_000, 100_000,
132 10_000,
133 1_000, 100,
135 10,
136 1, ];
138
139 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}