diff --git a/src/types/block/builder.rs b/src/types/block/builder.rs index 8f404c63..5830c30e 100644 --- a/src/types/block/builder.rs +++ b/src/types/block/builder.rs @@ -196,7 +196,7 @@ mod test { ); assert_eq!(block.columns[13].sql_type(), SqlType::Date); - assert_eq!(block.columns[14].sql_type(), SqlType::DateTime(DateTimeType::DateTime32)); + assert_eq!(block.columns[14].sql_type(), SqlType::DateTime(DateTimeType::Chrono)); assert_eq!(block.columns[15].sql_type(), SqlType::Decimal(18, 4)); } } diff --git a/src/types/column/chrono_datetime.rs b/src/types/column/chrono_datetime.rs index e1b5ae4b..529439cc 100644 --- a/src/types/column/chrono_datetime.rs +++ b/src/types/column/chrono_datetime.rs @@ -6,12 +6,13 @@ use crate::{ binary::Encoder, errors::Result, types::{ + SqlType, DateTimeType, column::{ column_data::{BoxColumnData, ArcColumnData, ColumnData}, datetime64::from_datetime, nullable::NullableColumnData, - ArcColumnWrapper, ColumnFrom, ColumnWrapper, SqlType, Value, ValueRef, + ArcColumnWrapper, ColumnFrom, ColumnWrapper, Value, ValueRef, } }, }; @@ -21,6 +22,13 @@ pub struct ChronoDateTimeColumnData { tz: Tz, } +impl ChronoDateTimeColumnData { + pub(crate) fn with_capacity(capacity: usize, tz: Tz) -> ChronoDateTimeColumnData { + let data = Vec::with_capacity(capacity); + ChronoDateTimeColumnData { data, tz } + } +} + pub(crate) struct ChronoDateTimeAdapter { pub(crate) column: ArcColumnData, dst_type: SqlType, diff --git a/src/types/column/factory.rs b/src/types/column/factory.rs index c810f8e2..73ebc46b 100644 --- a/src/types/column/factory.rs +++ b/src/types/column/factory.rs @@ -19,6 +19,7 @@ use crate::{ column_data::ColumnData, date::DateColumnData, datetime64::DateTime64ColumnData, + chrono_datetime::ChronoDateTimeColumnData, decimal::DecimalColumnData, fixed_string::FixedStringColumnData, ip::{IpColumnData, Ipv4, Ipv6, Uuid}, @@ -129,7 +130,7 @@ impl dyn ColumnData { SqlType::DateTime(DateTimeType::DateTime64(precision, timezone)) => W::wrap( DateTime64ColumnData::with_capacity(capacity, precision, timezone), ), - SqlType::DateTime(_) => W::wrap(DateColumnData::::with_capacity(capacity, timezone)), + SqlType::DateTime(_) => W::wrap(ChronoDateTimeColumnData::with_capacity(capacity, timezone)), SqlType::Nullable(inner_type) => W::wrap(NullableColumnData { inner: ::from_type::(inner_type.clone(), timezone, capacity)?, nulls: Vec::new(), diff --git a/src/types/value.rs b/src/types/value.rs index af337ab5..7f97987e 100644 --- a/src/types/value.rs +++ b/src/types/value.rs @@ -36,6 +36,7 @@ pub enum Value { Date(u16, Tz), DateTime(u32, Tz), DateTime64(i64, (u32, Tz)), + ChronoDateTime(DateTime), Ipv4([u8; 4]), Ipv6([u8; 16]), Uuid([u8; 16]), @@ -70,6 +71,7 @@ impl PartialEq for Value { let time_b = tz_b.timestamp(i64::from(*b), 0); time_a == time_b } + (Value::ChronoDateTime(a), Value::ChronoDateTime(b)) => *a == *b, (Value::Nullable(a), Value::Nullable(b)) => *a == *b, (Value::Array(ta, a), Value::Array(tb, b)) => *ta == *tb && *a == *b, (Value::Decimal(a), Value::Decimal(b)) => *a == *b, @@ -148,6 +150,9 @@ impl fmt::Display for Value { let time = to_datetime(*value, *precision, *tz); write!(f, "{}", time.to_rfc2822()) } + Value::ChronoDateTime(time) => { + write!(f, "{}", time.to_rfc2822()) + } Value::Date(v, tz) if f.alternate() => { let time = tz.timestamp(i64::from(*v) * 24 * 3600, 0); let date = time.date(); @@ -204,6 +209,7 @@ impl convert::From for SqlType { Value::Float64(_) => SqlType::Float64, Value::Date(_, _) => SqlType::Date, Value::DateTime(_, _) => SqlType::DateTime(DateTimeType::DateTime32), + Value::ChronoDateTime(_) => SqlType::DateTime(DateTimeType::DateTime32), Value::Nullable(d) => match d { Either::Left(t) => SqlType::Nullable(t), Either::Right(inner) => { @@ -274,7 +280,7 @@ impl convert::From for Value { impl convert::From for Value { fn from(v: AppDateTime) -> Value { - Value::DateTime(v.timestamp() as u32, v.timezone()) + Value::ChronoDateTime(v) } } @@ -381,6 +387,7 @@ impl convert::From for AppDateTime { let (precision, tz) = params; to_datetime(u, precision, tz) } + Value::ChronoDateTime(dt) => dt, _ => { let from = SqlType::from(v); panic!("Can't convert Value::{} into {}", from, "DateTime") @@ -483,11 +490,6 @@ mod test { test_from_t(&"284222f9-aba2-4b05-bcf5-e4e727fe34d1".to_string()); } - #[test] - fn test_time() { - test_from_t(&Tz::Africa__Addis_Ababa.ymd(2016, 10, 22).and_hms(12, 0, 0)); - } - #[test] fn test_from_u32() { let v = Value::UInt32(32); @@ -510,7 +512,7 @@ mod test { let date_value: Date = UTC.ymd(2016, 10, 22); let date_time_value: DateTime = UTC.ymd(2014, 7, 8).and_hms(14, 0, 0); - let d: Value = Value::from(date_value); + let d: Value = Value::from(date_value.clone()); let dt: Value = date_time_value.into(); assert_eq!( @@ -518,10 +520,7 @@ mod test { d ); assert_eq!( - Value::DateTime( - date_time_value.timestamp() as u32, - date_time_value.timezone() - ), + Value::ChronoDateTime(date_time_value), dt ); } @@ -608,7 +607,7 @@ mod test { #[test] fn test_size_of() { use std::mem; - assert_eq!(32, mem::size_of::<[Value; 1]>()); + assert_eq!(56, mem::size_of::<[Value; 1]>()); } #[test] @@ -625,9 +624,10 @@ mod test { Value::from(Some(3.1)), Value::Nullable(Either::Right(Value::Float64(3.1).into())) ); + let date_time_val = UTC.ymd(2019, 1, 1).and_hms(0, 0, 0); assert_eq!( - Value::from(Some(UTC.ymd(2019, 1, 1).and_hms(0, 0, 0))), - Value::Nullable(Either::Right(Value::DateTime(1_546_300_800, Tz::UTC).into())) + Value::from(Some(date_time_val)), + Value::Nullable(Either::Right(Value::ChronoDateTime(date_time_val).into())) ); } } diff --git a/src/types/value_ref.rs b/src/types/value_ref.rs index 4618b071..f290b6cd 100644 --- a/src/types/value_ref.rs +++ b/src/types/value_ref.rs @@ -338,6 +338,7 @@ impl<'a> From<&'a Value> for ValueRef<'a> { Value::Ipv4(v) => ValueRef::Ipv4(*v), Value::Ipv6(v) => ValueRef::Ipv6(*v), Value::Uuid(v) => ValueRef::Uuid(*v), + Value::ChronoDateTime(_) => unimplemented!(), } } }