From 167be10f8acc7a0aa959dbab8dc2f45ff4e9d3b8 Mon Sep 17 00:00:00 2001 From: Chojan Shang Date: Thu, 17 Nov 2022 14:35:52 +0800 Subject: [PATCH 1/4] feat: bump main deps of opensrv-mysql --- mysql/Cargo.toml | 8 ++++---- mysql/src/tests/value/decode.rs | 7 +++++-- mysql/src/tests/value/encode.rs | 18 ++++++++++-------- mysql/src/value/decode.rs | 12 +++++++----- mysql/src/value/encode.rs | 12 ++++++++---- mysql/tests/it/async.rs | 5 ++++- 6 files changed, 38 insertions(+), 24 deletions(-) diff --git a/mysql/Cargo.toml b/mysql/Cargo.toml index 488b174..5f43d77 100644 --- a/mysql/Cargo.toml +++ b/mysql/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "opensrv-mysql" -version = "0.2.0" +version = "0.3.0" authors = ["Databend Authors "] edition = "2021" license = "Apache-2.0" @@ -16,14 +16,14 @@ doctest = false [dependencies] async-trait = "0.1.52" byteorder = "1.4.3" -chrono = "0.4.19" +chrono = "0.4.20" mysql_common = { version = "0.29.0", features = ["chrono"] } nom = "7.1.0" tokio = { version = "1.17.0", features = ["io-util", "io-std"] } [dev-dependencies] -mysql = "22.0.0" -mysql_async = "0.30.0" +mysql = "23.0.0" +mysql_async = "0.31.0" tokio = { version = "1.0", features = ["full"] } futures = "0.3" diff --git a/mysql/src/tests/value/decode.rs b/mysql/src/tests/value/decode.rs index f79fc1a..6a40216 100644 --- a/mysql/src/tests/value/decode.rs +++ b/mysql/src/tests/value/decode.rs @@ -168,13 +168,16 @@ rt!( rt!( time, chrono::NaiveDate, - chrono::Local::today().naive_local(), + chrono::Local::now().date_naive(), ColumnType::MYSQL_TYPE_DATE ); rt!( datetime, chrono::NaiveDateTime, - chrono::Utc.ymd(1989, 12, 7).and_hms(8, 0, 4).naive_utc(), + chrono::Utc + .with_ymd_and_hms(1989, 12, 7, 8, 0, 4) + .unwrap() + .naive_utc(), ColumnType::MYSQL_TYPE_DATETIME ); rt!( diff --git a/mysql/src/tests/value/encode.rs b/mysql/src/tests/value/encode.rs index f1fa05c..7e0f0bc 100644 --- a/mysql/src/tests/value/encode.rs +++ b/mysql/src/tests/value/encode.rs @@ -69,15 +69,14 @@ mod roundtrip_text { rt!(opt_none, Option, None); rt!(opt_some, Option, Some(1)); - rt!( - time, - chrono::NaiveDate, - chrono::Local::today().naive_local() - ); + rt!(time, chrono::NaiveDate, chrono::Local::now().date_naive()); rt!( datetime, chrono::NaiveDateTime, - chrono::Utc.ymd(1989, 12, 7).and_hms(8, 0, 4).naive_utc() + chrono::Utc + .with_ymd_and_hms(1989, 12, 7, 8, 0, 4) + .unwrap() + .naive_utc() ); rt!(dur, time::Duration, time::Duration::from_secs(1893)); rt!(dur_micro, time::Duration, time::Duration::new(1893, 5000)); @@ -261,13 +260,16 @@ mod roundtrip_bin { rt!( time, chrono::NaiveDate, - chrono::Local::today().naive_local(), + chrono::Local::now().date_naive(), ColumnType::MYSQL_TYPE_DATE ); rt!( datetime, chrono::NaiveDateTime, - chrono::Utc.ymd(1989, 12, 7).and_hms(8, 0, 4).naive_utc(), + chrono::Utc + .with_ymd_and_hms(1989, 12, 7, 8, 0, 4) + .unwrap() + .naive_utc(), ColumnType::MYSQL_TYPE_DATETIME ); rt!( diff --git a/mysql/src/value/decode.rs b/mysql/src/value/decode.rs index 1407774..1d1193c 100644 --- a/mysql/src/value/decode.rs +++ b/mysql/src/value/decode.rs @@ -221,11 +221,12 @@ impl<'a> From> for NaiveDate { fn from(val: Value<'a>) -> Self { if let ValueInner::Date(mut v) = val.0 { assert_eq!(v.len(), 4); - NaiveDate::from_ymd( + NaiveDate::from_ymd_opt( i32::from(v.read_u16::().unwrap()), u32::from(v.read_u8().unwrap()), u32::from(v.read_u8().unwrap()), ) + .unwrap() } else { panic!("invalid type conversion from {:?} to date", val) } @@ -236,11 +237,12 @@ impl<'a> From> for NaiveDateTime { fn from(val: Value<'a>) -> Self { if let ValueInner::Datetime(mut v) = val.0 { assert!(v.len() == 7 || v.len() == 11); - let d = NaiveDate::from_ymd( + let d = NaiveDate::from_ymd_opt( i32::from(v.read_u16::().unwrap()), u32::from(v.read_u8().unwrap()), u32::from(v.read_u8().unwrap()), - ); + ) + .unwrap(); let h = u32::from(v.read_u8().unwrap()); let m = u32::from(v.read_u8().unwrap()); @@ -248,9 +250,9 @@ impl<'a> From> for NaiveDateTime { if v.len() == 11 { let us = v.read_u32::().unwrap(); - d.and_hms_micro(h, m, s, us) + d.and_hms_micro_opt(h, m, s, us).unwrap() } else { - d.and_hms(h, m, s) + d.and_hms_opt(h, m, s).unwrap() } } else { panic!("invalid type conversion from {:?} to datetime", val) diff --git a/mysql/src/value/encode.rs b/mysql/src/value/encode.rs index 8c45d75..acc1439 100644 --- a/mysql/src/value/encode.rs +++ b/mysql/src/value/encode.rs @@ -580,8 +580,10 @@ impl ToMysqlValue for myc::value::Value { myc::value::Value::Float(f) => f.to_mysql_text(w), myc::value::Value::Double(f) => f.to_mysql_text(w), myc::value::Value::Date(y, mo, d, h, mi, s, us) => { - NaiveDate::from_ymd(i32::from(y), u32::from(mo), u32::from(d)) - .and_hms_micro(u32::from(h), u32::from(mi), u32::from(s), us) + NaiveDate::from_ymd_opt(i32::from(y), u32::from(mo), u32::from(d)) + .unwrap() + .and_hms_micro_opt(u32::from(h), u32::from(mi), u32::from(s), us) + .unwrap() .to_mysql_text(w) } myc::value::Value::Time(neg, d, h, m, s, us) => { @@ -645,8 +647,10 @@ impl ToMysqlValue for myc::value::Value { myc::value::Value::Float(f) => f.to_mysql_bin(w, c), myc::value::Value::Double(f) => f.to_mysql_bin(w, c), myc::value::Value::Date(y, mo, d, h, mi, s, us) => { - NaiveDate::from_ymd(i32::from(y), u32::from(mo), u32::from(d)) - .and_hms_micro(u32::from(h), u32::from(mi), u32::from(s), us) + NaiveDate::from_ymd_opt(i32::from(y), u32::from(mo), u32::from(d)) + .unwrap() + .and_hms_micro_opt(u32::from(h), u32::from(mi), u32::from(s), us) + .unwrap() .to_mysql_bin(w, c) } myc::value::Value::Time(neg, d, h, m, s, us) => { diff --git a/mysql/tests/it/async.rs b/mysql/tests/it/async.rs index 123b21e..d273f72 100644 --- a/mysql/tests/it/async.rs +++ b/mysql/tests/it/async.rs @@ -608,7 +608,10 @@ async fn insert_exec() { ); assert_eq!( Into::::into(params[3].value), - chrono::NaiveDate::from_ymd(2018, 4, 6).and_hms(13, 0, 56) + chrono::NaiveDate::from_ymd_opt(2018, 4, 6) + .unwrap() + .and_hms_opt(13, 0, 56) + .unwrap() ); assert_eq!(Into::<&str>::into(params[4].value), "token199"); assert_eq!(Into::<&str>::into(params[5].value), "rsstoken199"); From bd7d19a771d7b35e368f075e15d6d6b279fdb6f9 Mon Sep 17 00:00:00 2001 From: Chojan Shang Date: Fri, 25 Nov 2022 12:25:44 +0800 Subject: [PATCH 2/4] feat: bump main deps of opensrv-clickhouse --- clickhouse/Cargo.toml | 6 +-- clickhouse/src/types/block/builder.rs | 1 - .../src/types/column/chrono_datetime.rs | 2 +- clickhouse/src/types/column/date.rs | 16 +++---- clickhouse/src/types/column/datetime64.rs | 2 +- clickhouse/src/types/column/iter.rs | 17 ++++--- clickhouse/src/types/date_converter.rs | 9 ++-- clickhouse/src/types/from_sql.rs | 14 +++--- clickhouse/src/types/mod.rs | 2 +- clickhouse/src/types/options.rs | 1 + clickhouse/src/types/value.rs | 46 +++++++++---------- clickhouse/src/types/value_ref.rs | 46 +++++++++---------- clickhouse/tests/it/types/block/builder.rs | 7 ++- clickhouse/tests/it/types/column/date.rs | 11 +++-- clickhouse/tests/it/types/column/tuple.rs | 15 +++++- clickhouse/tests/it/types/value.rs | 20 ++++---- clickhouse/tests/it/types/value_ref.rs | 16 ++----- 17 files changed, 126 insertions(+), 105 deletions(-) diff --git a/clickhouse/Cargo.toml b/clickhouse/Cargo.toml index 202cc93..4bb2b20 100644 --- a/clickhouse/Cargo.toml +++ b/clickhouse/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "opensrv-clickhouse" -version = "0.2.0" +version = "0.3.0" authors = ["Databend Authors "] edition = "2021" license = "Apache-2.0" @@ -21,8 +21,8 @@ tls = ["tokio-native-tls"] async-trait = "0.1.52" byteorder = "1.4.3" bytes = "1.1.0" -chrono = { version = "0.4.19", default-features = false, features = ["std"] } -chrono-tz = "0.6.1" +chrono = { version = "0.4.20", default-features = false, features = ["std"] } +chrono-tz = "0.8.0" combine = "4.6.3" hostname = "0.3.1" lz4 = "1.23.2" diff --git a/clickhouse/src/types/block/builder.rs b/clickhouse/src/types/block/builder.rs index 0b962f9..9ce5d35 100644 --- a/clickhouse/src/types/block/builder.rs +++ b/clickhouse/src/types/block/builder.rs @@ -133,7 +133,6 @@ fn put_param( fn extract_timezone(value: &Value) -> Tz { match value { - Value::Date(_, tz) => *tz, Value::DateTime(_, tz) => *tz, Value::Nullable(Either::Right(d)) => extract_timezone(d), Value::Array(_, data) => { diff --git a/clickhouse/src/types/column/chrono_datetime.rs b/clickhouse/src/types/column/chrono_datetime.rs index 7698fa0..f006754 100644 --- a/clickhouse/src/types/column/chrono_datetime.rs +++ b/clickhouse/src/types/column/chrono_datetime.rs @@ -77,7 +77,7 @@ impl ColumnFrom for Vec>> { match time { None => { nulls.push(1); - values.push(tz.timestamp(0, 0)) + values.push(tz.timestamp_opt(0, 0).unwrap()) } Some(time) => { nulls.push(0); diff --git a/clickhouse/src/types/column/date.rs b/clickhouse/src/types/column/date.rs index 745cd04..f23d64e 100644 --- a/clickhouse/src/types/column/date.rs +++ b/clickhouse/src/types/column/date.rs @@ -17,7 +17,7 @@ use std::fmt; use std::sync::Arc; use chrono::prelude::*; -use chrono::Date; +use chrono::NaiveDate; use chrono_tz::Tz; use micromarshal::Marshal; use micromarshal::Unmarshal; @@ -92,7 +92,7 @@ where } } -impl ColumnFrom for Vec> { +impl ColumnFrom for Vec { fn column_from(source: Self) -> W::Wrapper { let mut data = List::::with_capacity(source.len()); for s in source { @@ -104,9 +104,9 @@ impl ColumnFrom for Vec> { } } -impl ColumnFrom for Vec>> { +impl ColumnFrom for Vec> { fn column_from(source: Self) -> W::Wrapper { - let fake: Vec> = Vec::with_capacity(source.len()); + let fake: Vec = Vec::with_capacity(source.len()); let inner = Vec::column_from::(fake); let sql_type = inner.sql_type(); @@ -119,7 +119,7 @@ impl ColumnFrom for Vec>> { let mut inner = Vec::with_capacity(vs.len()); for v in vs { let days = u16::get_days(v); - let value: Value = Value::Date(days, v.timezone()); + let value: Value = Value::Date(days); inner.push(value); } data.push(Value::Array(sql_type.clone().into(), Arc::new(inner))); @@ -153,9 +153,9 @@ impl ColumnFrom for Vec>> { } } -impl ColumnFrom for Vec>> { +impl ColumnFrom for Vec> { fn column_from(source: Self) -> ::Wrapper { - let fake: Vec> = Vec::with_capacity(source.len()); + let fake: Vec = Vec::with_capacity(source.len()); let inner = Vec::column_from::(fake); let mut data = NullableColumnData { @@ -168,7 +168,7 @@ impl ColumnFrom for Vec>> { None => data.push(Value::Nullable(Either::Left(SqlType::Date.into()))), Some(d) => { let days = u16::get_days(d); - let value = Value::Date(days, d.timezone()); + let value = Value::Date(days); data.push(Value::Nullable(Either::Right(Box::new(value)))) } } diff --git a/clickhouse/src/types/column/datetime64.rs b/clickhouse/src/types/column/datetime64.rs index e222436..9052f22 100644 --- a/clickhouse/src/types/column/datetime64.rs +++ b/clickhouse/src/types/column/datetime64.rs @@ -122,5 +122,5 @@ pub fn to_datetime(value: i64, precision: u32, tz: Tz) -> DateTime { let sec = nano / 1_000_000_000; let nsec = nano - sec * 1_000_000_000; - tz.timestamp(sec, nsec as u32) + tz.timestamp_opt(sec, nsec as u32).unwrap() } diff --git a/clickhouse/src/types/column/iter.rs b/clickhouse/src/types/column/iter.rs index 73959f6..1dcc3ba 100644 --- a/clickhouse/src/types/column/iter.rs +++ b/clickhouse/src/types/column/iter.rs @@ -23,7 +23,7 @@ use std::ptr; use std::slice; use chrono::prelude::*; -use chrono::Date; +use chrono::NaiveDate; use chrono_tz::Tz; use crate::errors::Error; @@ -418,12 +418,15 @@ impl<'a> ExactSizeIterator for UuidIterator<'a> { impl<'a> DateIterator<'a> { #[inline(always)] - unsafe fn next_unchecked(&mut self) -> Date { + unsafe fn next_unchecked(&mut self) -> NaiveDate { let current_value = *self.ptr; self.ptr = self.ptr.offset(1); - let time = self.tz.timestamp(i64::from(current_value) * 24 * 3600, 0); - time.date() + let time = self + .tz + .timestamp_opt(i64::from(current_value) * 24 * 3600, 0) + .unwrap(); + time.date_naive() } #[inline(always)] @@ -439,7 +442,7 @@ impl<'a> DateTimeIterator<'a> { DateTimeInnerIterator::DateTime32(ptr, _) => { let current_value = **ptr; *ptr = ptr.offset(1); - self.tz.timestamp(i64::from(current_value), 0) + self.tz.timestamp_opt(i64::from(current_value), 0).unwrap() } DateTimeInnerIterator::DateTime64(ptr, _, precision) => { let current_value = **ptr; @@ -474,7 +477,7 @@ impl ExactSizeIterator for DateTimeIterator<'_> { } } -iterator! { DateIterator: Date } +iterator! { DateIterator: NaiveDate } impl<'a> Iterator for DateTimeIterator<'a> { type Item = DateTime; @@ -803,7 +806,7 @@ impl<'a> Iterable<'a, Simple> for DateTime { } } -impl<'a> Iterable<'a, Simple> for Date { +impl<'a> Iterable<'a, Simple> for NaiveDate { type Iter = DateIterator<'a>; fn iter(column: &'a Column, column_type: SqlType) -> Result { diff --git a/clickhouse/src/types/date_converter.rs b/clickhouse/src/types/date_converter.rs index b4f8216..b55e2ae 100644 --- a/clickhouse/src/types/date_converter.rs +++ b/clickhouse/src/types/date_converter.rs @@ -13,7 +13,6 @@ // limitations under the License. use chrono::prelude::*; -use chrono::Date; use chrono_tz::Tz; use crate::types::DateTimeType; @@ -26,7 +25,7 @@ pub trait DateConverter { fn get_stamp(source: Value) -> Self; fn date_type() -> SqlType; - fn get_days(date: Date) -> u16 { + fn get_days(date: NaiveDate) -> u16 { const UNIX_EPOCH_DAY: i64 = 719_163; let gregorian_day = i64::from(date.num_days_from_ce()); (gregorian_day - UNIX_EPOCH_DAY) as u16 @@ -35,11 +34,13 @@ pub trait DateConverter { impl DateConverter for u16 { fn to_date(&self, tz: Tz) -> ValueRef<'static> { - ValueRef::Date(*self, tz) + let time = tz.timestamp_opt(i64::from(*self) * 24 * 3600, 0).unwrap(); + let date = time.date_naive(); + ValueRef::Date(Self::get_days(date)) } fn get_stamp(source: Value) -> Self { - Self::get_days(Date::::from(source)) + Self::get_days(NaiveDate::from(source)) } fn date_type() -> SqlType { diff --git a/clickhouse/src/types/from_sql.rs b/clickhouse/src/types/from_sql.rs index 4c33619..c22e073 100644 --- a/clickhouse/src/types/from_sql.rs +++ b/clickhouse/src/types/from_sql.rs @@ -204,7 +204,7 @@ from_sql_vec_impl! { String: SqlType::String => |v| v.as_string(), &'a [u8]: SqlType::String => |v| v.as_bytes(), Vec: SqlType::String => |v| v.as_bytes().map(<[u8]>::to_vec), - Date: SqlType::Date => |z| Ok(z.into()), + NaiveDate: SqlType::Date => |z| Ok(z.into()), DateTime: SqlType::DateTime(_) => |z| Ok(z.into()) } @@ -286,18 +286,18 @@ where } } -impl<'a> FromSql<'a> for Date { +impl<'a> FromSql<'a> for NaiveDate { fn from_sql(value: ValueRef<'a>) -> FromSqlResult { match value { - ValueRef::Date(v, tz) => { - let time = tz.timestamp(i64::from(v) * 24 * 3600, 0); - Ok(time.date()) + ValueRef::Date(v) => { + let time = Tz::Zulu.timestamp_opt(i64::from(v) * 24 * 3600, 0).unwrap(); + Ok(time.date_naive()) } _ => { let from = SqlType::from(value).to_string(); Err(Error::FromSql(FromSqlError::InvalidType { src: from, - dst: "Date".into(), + dst: "NaiveDate".into(), })) } } @@ -308,7 +308,7 @@ impl<'a> FromSql<'a> for DateTime { fn from_sql(value: ValueRef<'a>) -> FromSqlResult { match value { ValueRef::DateTime(v, tz) => { - let time = tz.timestamp(i64::from(v), 0); + let time = tz.timestamp_opt(i64::from(v), 0).unwrap(); Ok(time) } ValueRef::DateTime64(v, params) => { diff --git a/clickhouse/src/types/mod.rs b/clickhouse/src/types/mod.rs index c22793a..ed1a276 100644 --- a/clickhouse/src/types/mod.rs +++ b/clickhouse/src/types/mod.rs @@ -188,7 +188,7 @@ has_sql_type! { String: SqlType::String, f32: SqlType::Float32, f64: SqlType::Float64, - Date: SqlType::Date, + NaiveDate: SqlType::Date, DateTime: SqlType::DateTime(DateTimeType::DateTime32) } diff --git a/clickhouse/src/types/options.rs b/clickhouse/src/types/options.rs index 7e2e263..2942b1b 100644 --- a/clickhouse/src/types/options.rs +++ b/clickhouse/src/types/options.rs @@ -163,6 +163,7 @@ impl convert::From for native_tls::Certificate { /// Clickhouse connection options. // the trait `std::cmp::Eq` is not implemented for `types::options::Certificate` // so we can't use `derive(Eq)` in tls feature. +#[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq)] pub struct Options { /// Address of clickhouse server (defaults to `127.0.0.1:9000`). diff --git a/clickhouse/src/types/value.rs b/clickhouse/src/types/value.rs index 4247e45..d56b958 100644 --- a/clickhouse/src/types/value.rs +++ b/clickhouse/src/types/value.rs @@ -36,7 +36,7 @@ use crate::types::HasSqlType; use crate::types::SqlType; pub(crate) type AppDateTime = DateTime; -pub(crate) type AppDate = Date; +pub(crate) type AppDate = NaiveDate; /// Client side representation of a value of Clickhouse column. #[derive(Clone, Debug)] @@ -52,7 +52,7 @@ pub enum Value { String(Arc>), Float32(f32), Float64(f64), - Date(u16, Tz), + Date(u16), DateTime(u32, Tz), DateTime64(i64, (u32, Tz)), Ipv4([u8; 4]), @@ -80,14 +80,10 @@ impl PartialEq for Value { (Value::String(a), Value::String(b)) => *a == *b, (Value::Float32(a), Value::Float32(b)) => *a == *b, (Value::Float64(a), Value::Float64(b)) => *a == *b, - (Value::Date(a, tz_a), Value::Date(b, tz_b)) => { - let time_a = tz_a.timestamp(i64::from(*a) * 24 * 3600, 0); - let time_b = tz_b.timestamp(i64::from(*b) * 24 * 3600, 0); - time_a.date() == time_b.date() - } + (Value::Date(a), Value::Date(b)) => *a == *b, (Value::DateTime(a, tz_a), Value::DateTime(b, tz_b)) => { - let time_a = tz_a.timestamp(i64::from(*a), 0); - let time_b = tz_b.timestamp(i64::from(*b), 0); + let time_a = tz_a.timestamp_opt(i64::from(*a), 0).unwrap(); + let time_b = tz_b.timestamp_opt(i64::from(*b), 0).unwrap(); time_a == time_b } (Value::Nullable(a), Value::Nullable(b)) => *a == *b, @@ -163,11 +159,11 @@ impl fmt::Display for Value { Value::Float32(ref v) => fmt::Display::fmt(v, f), Value::Float64(ref v) => fmt::Display::fmt(v, f), Value::DateTime(u, tz) if f.alternate() => { - let time = tz.timestamp(i64::from(*u), 0); + let time = tz.timestamp_opt(i64::from(*u), 0).unwrap(); fmt::Display::fmt(&time, f) } Value::DateTime(u, tz) => { - let time = tz.timestamp(i64::from(*u), 0); + let time = tz.timestamp_opt(i64::from(*u), 0).unwrap(); write!(f, "{}", time.to_rfc2822()) } Value::DateTime64(value, params) => { @@ -175,14 +171,18 @@ impl fmt::Display for Value { let time = to_datetime(*value, *precision, *tz); 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(); + Value::Date(v) if f.alternate() => { + let time = Tz::Zulu + .timestamp_opt(i64::from(*v) * 24 * 3600, 0) + .unwrap(); + let date = time.date_naive(); fmt::Display::fmt(&date, f) } - Value::Date(v, tz) => { - let time = tz.timestamp(i64::from(*v) * 24 * 3600, 0); - let date = time.date(); + Value::Date(v) => { + let time = Tz::Zulu + .timestamp_opt(i64::from(*v) * 24 * 3600, 0) + .unwrap(); + let date = time.date_naive(); fmt::Display::fmt(&date.format("%Y-%m-%d"), f) } Value::Nullable(v) => match v { @@ -233,7 +233,7 @@ impl convert::From for SqlType { Value::String(_) => SqlType::String, Value::Float32(_) => SqlType::Float32, Value::Float64(_) => SqlType::Float64, - Value::Date(_, _) => SqlType::Date, + Value::Date(_) => SqlType::Date, Value::DateTime(_, _) => SqlType::DateTime(DateTimeType::DateTime32), Value::Nullable(d) => match d { Either::Left(t) => SqlType::Nullable(t), @@ -294,7 +294,7 @@ macro_rules! value_from { impl convert::From for Value { fn from(v: AppDate) -> Value { - Value::Date(u16::get_days(v), v.timezone()) + Value::Date(u16::get_days(v)) } } @@ -402,9 +402,9 @@ macro_rules! from_value { impl convert::From for AppDate { fn from(v: Value) -> AppDate { - if let Value::Date(x, tz) = v { - let time = tz.timestamp(i64::from(x) * 24 * 3600, 0); - return time.date(); + if let Value::Date(x) = v { + let time = Tz::Zulu.timestamp_opt(i64::from(x) * 24 * 3600, 0).unwrap(); + return time.date_naive(); } let from = SqlType::from(v); panic!("Can't convert Value::{} into {}", from, "AppDate") @@ -414,7 +414,7 @@ impl convert::From for AppDate { impl convert::From for AppDateTime { fn from(v: Value) -> AppDateTime { match v { - Value::DateTime(u, tz) => tz.timestamp(i64::from(u), 0), + Value::DateTime(u, tz) => tz.timestamp_opt(i64::from(u), 0).unwrap(), Value::DateTime64(u, params) => { let (precision, tz) = params; to_datetime(u, precision, tz) diff --git a/clickhouse/src/types/value_ref.rs b/clickhouse/src/types/value_ref.rs index 5ee40f7..94e58b3 100644 --- a/clickhouse/src/types/value_ref.rs +++ b/clickhouse/src/types/value_ref.rs @@ -50,7 +50,7 @@ pub enum ValueRef<'a> { String(&'a [u8]), Float32(f32), Float64(f64), - Date(u16, Tz), + Date(u16), DateTime(u32, Tz), DateTime64(i64, &'a (u32, Tz)), Nullable(Either<&'static SqlType, Box>>), @@ -78,14 +78,10 @@ impl<'a> PartialEq for ValueRef<'a> { (ValueRef::String(a), ValueRef::String(b)) => *a == *b, (ValueRef::Float32(a), ValueRef::Float32(b)) => *a == *b, (ValueRef::Float64(a), ValueRef::Float64(b)) => *a == *b, - (ValueRef::Date(a, tz_a), ValueRef::Date(b, tz_b)) => { - let time_a = tz_a.timestamp(i64::from(*a) * 24 * 3600, 0); - let time_b = tz_b.timestamp(i64::from(*b) * 24 * 3600, 0); - time_a.date() == time_b.date() - } + (ValueRef::Date(a), ValueRef::Date(b)) => *a == *b, (ValueRef::DateTime(a, tz_a), ValueRef::DateTime(b, tz_b)) => { - let time_a = tz_a.timestamp(i64::from(*a), 0); - let time_b = tz_b.timestamp(i64::from(*b), 0); + let time_a = tz_a.timestamp_opt(i64::from(*a), 0).unwrap(); + let time_b = tz_b.timestamp_opt(i64::from(*b), 0).unwrap(); time_a == time_b } (ValueRef::Nullable(a), ValueRef::Nullable(b)) => *a == *b, @@ -124,22 +120,26 @@ impl<'a> fmt::Display for ValueRef<'a> { }, ValueRef::Float32(v) => fmt::Display::fmt(v, f), ValueRef::Float64(v) => fmt::Display::fmt(v, f), - ValueRef::Date(v, tz) if f.alternate() => { - let time = tz.timestamp(i64::from(*v) * 24 * 3600, 0); - let date = time.date(); + ValueRef::Date(v) if f.alternate() => { + let time = Tz::Zulu + .timestamp_opt(i64::from(*v) * 24 * 3600, 0) + .unwrap(); + let date = time.date_naive(); fmt::Display::fmt(&date, f) } - ValueRef::Date(v, tz) => { - let time = tz.timestamp(i64::from(*v) * 24 * 3600, 0); - let date = time.date(); + ValueRef::Date(v) => { + let time = Tz::Zulu + .timestamp_opt(i64::from(*v) * 24 * 3600, 0) + .unwrap(); + let date = time.date_naive(); fmt::Display::fmt(&date.format("%Y-%m-%d"), f) } ValueRef::DateTime(u, tz) if f.alternate() => { - let time = tz.timestamp(i64::from(*u), 0); + let time = tz.timestamp_opt(i64::from(*u), 0).unwrap(); write!(f, "{}", time.to_rfc2822()) } ValueRef::DateTime(u, tz) => { - let time = tz.timestamp(i64::from(*u), 0); + let time = tz.timestamp_opt(i64::from(*u), 0).unwrap(); fmt::Display::fmt(&time.format("%Y-%m-%d %H:%M:%S"), f) } ValueRef::DateTime64(u, params) => { @@ -195,7 +195,7 @@ impl<'a> convert::From> for SqlType { ValueRef::String(_) => SqlType::String, ValueRef::Float32(_) => SqlType::Float32, ValueRef::Float64(_) => SqlType::Float64, - ValueRef::Date(_, _) => SqlType::Date, + ValueRef::Date(_) => SqlType::Date, ValueRef::DateTime(_, _) => SqlType::DateTime(DateTimeType::DateTime32), ValueRef::Nullable(u) => match u { Either::Left(sql_type) => SqlType::Nullable(sql_type), @@ -265,7 +265,7 @@ impl<'a> From> for Value { ValueRef::String(v) => Value::String(Arc::new(v.into())), ValueRef::Float32(v) => Value::Float32(v), ValueRef::Float64(v) => Value::Float64(v), - ValueRef::Date(v, tz) => Value::Date(v, tz), + ValueRef::Date(v) => Value::Date(v), ValueRef::DateTime(v, tz) => Value::DateTime(v, tz), ValueRef::Nullable(u) => match u { Either::Left(sql_type) => Value::Nullable(Either::Left((sql_type.clone()).into())), @@ -354,7 +354,7 @@ impl<'a> From<&'a Value> for ValueRef<'a> { Value::String(v) => ValueRef::String(v), Value::Float32(v) => ValueRef::Float32(*v), Value::Float64(v) => ValueRef::Float64(*v), - Value::Date(v, tz) => ValueRef::Date(*v, *tz), + Value::Date(v) => ValueRef::Date(*v), Value::DateTime(v, tz) => ValueRef::DateTime(*v, *tz), Value::DateTime64(v, params) => ValueRef::DateTime64(*v, params), Value::Nullable(u) => match u { @@ -409,9 +409,9 @@ macro_rules! value_from { impl<'a> From> for AppDate { fn from(value: ValueRef<'a>) -> Self { - if let ValueRef::Date(v, tz) = value { - let time = tz.timestamp(i64::from(v) * 24 * 3600, 0); - return time.date(); + if let ValueRef::Date(v) = value { + let time = Tz::Zulu.timestamp_opt(i64::from(v) * 24 * 3600, 0).unwrap(); + return time.date_naive(); } let from = format!("{}", SqlType::from(value.clone())); panic!("Can't convert ValueRef::{} into {}.", from, stringify!($t)) @@ -421,7 +421,7 @@ impl<'a> From> for AppDate { impl<'a> From> for AppDateTime { fn from(value: ValueRef<'a>) -> Self { match value { - ValueRef::DateTime(x, tz) => tz.timestamp(i64::from(x), 0), + ValueRef::DateTime(x, tz) => tz.timestamp_opt(i64::from(x), 0).unwrap(), ValueRef::DateTime64(x, params) => { let (precision, tz) = *params; to_datetime(x, precision, tz) diff --git a/clickhouse/tests/it/types/block/builder.rs b/clickhouse/tests/it/types/block/builder.rs index 23eaa57..7a04a6e 100644 --- a/clickhouse/tests/it/types/block/builder.rs +++ b/clickhouse/tests/it/types/block/builder.rs @@ -22,8 +22,11 @@ use opensrv_clickhouse::types::*; #[test] fn test_push_row() { - 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 date_value: NaiveDate = UTC + .with_ymd_and_hms(2016, 10, 22, 0, 0, 0) + .unwrap() + .date_naive(); + let date_time_value: DateTime = UTC.with_ymd_and_hms(2014, 7, 8, 14, 0, 0).unwrap(); let decimal = Decimal::of(2.0_f64, 4); diff --git a/clickhouse/tests/it/types/column/date.rs b/clickhouse/tests/it/types/column/date.rs index fc9c797..532683d 100644 --- a/clickhouse/tests/it/types/column/date.rs +++ b/clickhouse/tests/it/types/column/date.rs @@ -20,14 +20,19 @@ use opensrv_clickhouse::types::*; #[test] fn test_create_date() { let tz = Tz::Zulu; - let column = Vec::column_from::(vec![tz.ymd(2016, 10, 22)]); - assert_eq!("2016-10-22UTC", format!("{:#}", column.at(0))); + let column = Vec::column_from::(vec![tz + .with_ymd_and_hms(2016, 10, 22, 0, 0, 0) + .unwrap() + .date_naive()]); + assert_eq!("2016-10-22", format!("{:#}", column.at(0))); assert_eq!(SqlType::Date, column.sql_type()); } #[test] fn test_create_date_time() { let tz = Tz::Zulu; - let column = Vec::column_from::(vec![tz.ymd(2016, 10, 22).and_hms(12, 0, 0)]); + let column = Vec::column_from::(vec![tz + .with_ymd_and_hms(2016, 10, 22, 12, 0, 0) + .unwrap()]); assert_eq!(format!("{}", column.at(0)), "2016-10-22 12:00:00"); } diff --git a/clickhouse/tests/it/types/column/tuple.rs b/clickhouse/tests/it/types/column/tuple.rs index b39bf92..27e08fd 100644 --- a/clickhouse/tests/it/types/column/tuple.rs +++ b/clickhouse/tests/it/types/column/tuple.rs @@ -23,7 +23,14 @@ use opensrv_clickhouse::types::*; fn test_tuple_type() { let tz = Tz::Zulu; let inner = vec![ - Vec::column_from::(vec![tz.ymd(2016, 10, 22), tz.ymd(2017, 11, 23)]), + Vec::column_from::(vec![ + tz.with_ymd_and_hms(2016, 10, 22, 0, 0, 0) + .unwrap() + .date_naive(), + tz.with_ymd_and_hms(2017, 11, 23, 0, 0, 0) + .unwrap() + .date_naive(), + ]), Vec::column_from::(vec![1_i32, 2]), Vec::column_from::(vec!["hello", "data"]), ]; @@ -36,7 +43,11 @@ fn test_tuple_type() { assert_eq!(2, column.len()); let value = Value::Tuple(Arc::new(vec![ - Value::Date(u16::get_days(tz.ymd(2018, 12, 24)), tz), + Value::Date(u16::get_days( + tz.with_ymd_and_hms(2018, 12, 24, 0, 0, 0) + .unwrap() + .date_naive(), + )), Value::Int32(3), Value::String(Arc::new(b"bend".to_vec())), ])); diff --git a/clickhouse/tests/it/types/value.rs b/clickhouse/tests/it/types/value.rs index 8c181cb..d7bdbb7 100644 --- a/clickhouse/tests/it/types/value.rs +++ b/clickhouse/tests/it/types/value.rs @@ -87,7 +87,11 @@ fn test_string() { #[test] fn test_time() { - test_from_t(&Tz::Africa__Addis_Ababa.ymd(2016, 10, 22).and_hms(12, 0, 0)); + test_from_t( + &Tz::Africa__Addis_Ababa + .with_ymd_and_hms(2016, 10, 22, 12, 0, 0) + .unwrap(), + ); } #[test] @@ -109,16 +113,16 @@ fn test_uuid() { #[test] fn test_from_date() { - 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 date_value: NaiveDate = UTC + .with_ymd_and_hms(2016, 10, 22, 0, 0, 0) + .unwrap() + .date_naive(); + let date_time_value: DateTime = UTC.with_ymd_and_hms(2014, 7, 8, 14, 0, 0).unwrap(); let d: Value = Value::from(date_value); let dt: Value = date_time_value.into(); - assert_eq!( - Value::Date(u16::get_days(date_value), date_value.timezone()), - d - ); + assert_eq!(Value::Date(u16::get_days(date_value)), d); assert_eq!( Value::DateTime( date_time_value.timestamp() as u32, @@ -240,7 +244,7 @@ fn test_from_some() { Value::Nullable(Either::Right(Value::Float64(3.1).into())) ); assert_eq!( - Value::from(Some(UTC.ymd(2019, 1, 1).and_hms(0, 0, 0))), + Value::from(Some(UTC.with_ymd_and_hms(2019, 1, 1, 0, 0, 0).unwrap())), Value::Nullable(Either::Right( Value::DateTime(1_546_300_800, Tz::UTC).into() )) diff --git a/clickhouse/tests/it/types/value_ref.rs b/clickhouse/tests/it/types/value_ref.rs index 1129f17..04c858d 100644 --- a/clickhouse/tests/it/types/value_ref.rs +++ b/clickhouse/tests/it/types/value_ref.rs @@ -83,14 +83,11 @@ fn test_display() { ) ); - assert_eq!( - "1970-01-01".to_string(), - format!("{}", ValueRef::Date(0, Tz::Zulu)) - ); + assert_eq!("1970-01-01".to_string(), format!("{}", ValueRef::Date(0))); assert_eq!( - "1970-01-01UTC".to_string(), - format!("{:#}", ValueRef::Date(0, Tz::Zulu)) + "1970-01-01".to_string(), + format!("{:#}", ValueRef::Date(0)) ); assert_eq!( @@ -130,10 +127,7 @@ fn test_value_from_ref() { assert_eq!(Value::from(ValueRef::Float32(42.0)), Value::Float32(42.0)); assert_eq!(Value::from(ValueRef::Float64(42.0)), Value::Float64(42.0)); - assert_eq!( - Value::from(ValueRef::Date(42, Tz::Zulu)), - Value::Date(42, Tz::Zulu) - ); + assert_eq!(Value::from(ValueRef::Date(42)), Value::Date(42)); assert_eq!( Value::from(ValueRef::DateTime(42, Tz::Zulu)), Value::DateTime(42, Tz::Zulu) @@ -200,7 +194,7 @@ fn test_get_sql_type() { assert_eq!(SqlType::from(ValueRef::String(&[])), SqlType::String); - assert_eq!(SqlType::from(ValueRef::Date(42, Tz::Zulu)), SqlType::Date); + assert_eq!(SqlType::from(ValueRef::Date(42)), SqlType::Date); assert_eq!( SqlType::from(ValueRef::DateTime(42, Tz::Zulu)), SqlType::DateTime(DateTimeType::DateTime32) From 4c94faccbba76b5b2ef8a18aa8218ab1ae0f5f27 Mon Sep 17 00:00:00 2001 From: Chojan Shang Date: Fri, 25 Nov 2022 12:38:40 +0800 Subject: [PATCH 3/4] fix: make clippy happy --- clickhouse/src/types/column/ip.rs | 24 ++++++++++++------------ clickhouse/src/types/column/mod.rs | 4 ++-- clickhouse/tests/it/types/value_ref.rs | 5 +---- 3 files changed, 15 insertions(+), 18 deletions(-) diff --git a/clickhouse/src/types/column/ip.rs b/clickhouse/src/types/column/ip.rs index f4ce8ff..3510354 100644 --- a/clickhouse/src/types/column/ip.rs +++ b/clickhouse/src/types/column/ip.rs @@ -59,7 +59,7 @@ impl IpVersion for Ipv4 { #[inline(always)] fn push(inner: &mut Vec, value: Value) { if let Value::Ipv4(v) = value { - inner.extend(&v); + inner.extend(v); } else { panic!(); } @@ -87,7 +87,7 @@ impl IpVersion for Ipv6 { #[inline(always)] fn push(inner: &mut Vec, value: Value) { if let Value::Ipv6(v) = value { - inner.extend(&v); + inner.extend(v); } else { panic!(); } @@ -115,7 +115,7 @@ impl IpVersion for Uuid { #[inline(always)] fn push(inner: &mut Vec, value: Value) { if let Value::Uuid(v) = value { - inner.extend(&v); + inner.extend(v); } else { panic!(); } @@ -135,7 +135,7 @@ impl ColumnFrom for Vec { for ip in data { let mut buffer = ip.octets(); buffer.reverse(); - inner.extend(&buffer); + inner.extend(buffer); } W::wrap(IpColumnData:: { @@ -149,7 +149,7 @@ impl ColumnFrom for Vec { fn column_from(data: Self) -> W::Wrapper { let mut inner = Vec::with_capacity(data.len()); for ip in data { - inner.extend(&ip.octets()); + inner.extend(ip.octets()); } W::wrap(IpColumnData:: { @@ -166,7 +166,7 @@ impl ColumnFrom for Vec { let mut buffer = *uuid.as_bytes(); buffer[..8].reverse(); buffer[8..].reverse(); - inner.extend(&buffer); + inner.extend(buffer); } W::wrap(IpColumnData:: { @@ -185,13 +185,13 @@ impl ColumnFrom for Vec> { for ip in source { match ip { None => { - inner.extend(&[0; 4]); + inner.extend([0; 4]); nulls.push(1); } Some(ip) => { let mut buffer = ip.octets(); buffer.reverse(); - inner.extend(&buffer); + inner.extend(buffer); nulls.push(0); } } @@ -217,11 +217,11 @@ impl ColumnFrom for Vec> { for ip in source { match ip { None => { - inner.extend(&[0; 16]); + inner.extend([0; 16]); nulls.push(1); } Some(ip) => { - inner.extend(&ip.octets()); + inner.extend(ip.octets()); nulls.push(0); } } @@ -247,14 +247,14 @@ impl ColumnFrom for Vec> { for uuid in source { match uuid { None => { - inner.extend(&[0; 16]); + inner.extend([0; 16]); nulls.push(1); } Some(uuid) => { let mut buffer = *uuid.as_bytes(); buffer[..8].reverse(); buffer[8..].reverse(); - inner.extend(&buffer); + inner.extend(buffer); nulls.push(0); } } diff --git a/clickhouse/src/types/column/mod.rs b/clickhouse/src/types/column/mod.rs index df66739..03af545 100644 --- a/clickhouse/src/types/column/mod.rs +++ b/clickhouse/src/types/column/mod.rs @@ -404,7 +404,7 @@ impl Column { let mut buffer = [0_u8; 4]; buffer.copy_from_slice(&ip.octets()); buffer.reverse(); - inner.extend(&buffer); + inner.extend(buffer); } let data = Arc::new(IpColumnData:: { @@ -426,7 +426,7 @@ impl Column { for i in 0..n { let source = self.at(i).as_str().unwrap(); let ip: Ipv6Addr = source.parse().unwrap(); - inner.extend(&ip.octets()); + inner.extend(ip.octets()); } let data = Arc::new(IpColumnData:: { diff --git a/clickhouse/tests/it/types/value_ref.rs b/clickhouse/tests/it/types/value_ref.rs index 04c858d..268ad1c 100644 --- a/clickhouse/tests/it/types/value_ref.rs +++ b/clickhouse/tests/it/types/value_ref.rs @@ -85,10 +85,7 @@ fn test_display() { assert_eq!("1970-01-01".to_string(), format!("{}", ValueRef::Date(0))); - assert_eq!( - "1970-01-01".to_string(), - format!("{:#}", ValueRef::Date(0)) - ); + assert_eq!("1970-01-01".to_string(), format!("{:#}", ValueRef::Date(0))); assert_eq!( "1970-01-01 00:00:00".to_string(), From 2df2c1fb2dc47a26f2d6536d0fc0f6425b13ee56 Mon Sep 17 00:00:00 2001 From: Chojan Shang Date: Fri, 25 Nov 2022 13:08:07 +0800 Subject: [PATCH 4/4] refactor: remove useless timezone --- clickhouse/src/types/date_converter.rs | 9 ++++----- clickhouse/src/types/from_sql.rs | 6 ++++-- clickhouse/src/types/mod.rs | 1 + clickhouse/src/types/value.rs | 20 ++++++++++---------- clickhouse/src/types/value_ref.rs | 20 ++++++++++---------- 5 files changed, 29 insertions(+), 27 deletions(-) diff --git a/clickhouse/src/types/date_converter.rs b/clickhouse/src/types/date_converter.rs index b55e2ae..d542586 100644 --- a/clickhouse/src/types/date_converter.rs +++ b/clickhouse/src/types/date_converter.rs @@ -20,23 +20,22 @@ use crate::types::SqlType; use crate::types::Value; use crate::types::ValueRef; +pub const UNIX_EPOCH_DAY: i64 = 719_163; + pub trait DateConverter { fn to_date(&self, tz: Tz) -> ValueRef<'static>; fn get_stamp(source: Value) -> Self; fn date_type() -> SqlType; fn get_days(date: NaiveDate) -> u16 { - const UNIX_EPOCH_DAY: i64 = 719_163; let gregorian_day = i64::from(date.num_days_from_ce()); (gregorian_day - UNIX_EPOCH_DAY) as u16 } } impl DateConverter for u16 { - fn to_date(&self, tz: Tz) -> ValueRef<'static> { - let time = tz.timestamp_opt(i64::from(*self) * 24 * 3600, 0).unwrap(); - let date = time.date_naive(); - ValueRef::Date(Self::get_days(date)) + fn to_date(&self, _: Tz) -> ValueRef<'static> { + ValueRef::Date(*self) } fn get_stamp(source: Value) -> Self { diff --git a/clickhouse/src/types/from_sql.rs b/clickhouse/src/types/from_sql.rs index c22e073..9324030 100644 --- a/clickhouse/src/types/from_sql.rs +++ b/clickhouse/src/types/from_sql.rs @@ -30,6 +30,7 @@ use crate::types::Enum16; use crate::types::Enum8; use crate::types::SqlType; use crate::types::ValueRef; +use crate::types::UNIX_EPOCH_DAY; pub type FromSqlResult = Result; @@ -290,8 +291,9 @@ impl<'a> FromSql<'a> for NaiveDate { fn from_sql(value: ValueRef<'a>) -> FromSqlResult { match value { ValueRef::Date(v) => { - let time = Tz::Zulu.timestamp_opt(i64::from(v) * 24 * 3600, 0).unwrap(); - Ok(time.date_naive()) + let date = NaiveDate::from_num_days_from_ce_opt((v as i64 + UNIX_EPOCH_DAY) as i32) + .unwrap(); + Ok(date) } _ => { let from = SqlType::from(value).to_string(); diff --git a/clickhouse/src/types/mod.rs b/clickhouse/src/types/mod.rs index ed1a276..380b05d 100644 --- a/clickhouse/src/types/mod.rs +++ b/clickhouse/src/types/mod.rs @@ -38,6 +38,7 @@ pub use self::column::Either; pub use self::column::Simple; pub use self::column::StringPool; pub use self::date_converter::DateConverter; +pub use self::date_converter::UNIX_EPOCH_DAY; pub use self::decimal::decimal2str; pub use self::decimal::Decimal; pub use self::decimal::NoBits; diff --git a/clickhouse/src/types/value.rs b/clickhouse/src/types/value.rs index d56b958..f39726a 100644 --- a/clickhouse/src/types/value.rs +++ b/clickhouse/src/types/value.rs @@ -34,6 +34,7 @@ use crate::types::Enum16; use crate::types::Enum8; use crate::types::HasSqlType; use crate::types::SqlType; +use crate::types::UNIX_EPOCH_DAY; pub(crate) type AppDateTime = DateTime; pub(crate) type AppDate = NaiveDate; @@ -172,17 +173,15 @@ impl fmt::Display for Value { write!(f, "{}", time.to_rfc2822()) } Value::Date(v) if f.alternate() => { - let time = Tz::Zulu - .timestamp_opt(i64::from(*v) * 24 * 3600, 0) - .unwrap(); - let date = time.date_naive(); + let date = + NaiveDate::from_num_days_from_ce_opt((*v as i64 + UNIX_EPOCH_DAY) as i32) + .unwrap(); fmt::Display::fmt(&date, f) } Value::Date(v) => { - let time = Tz::Zulu - .timestamp_opt(i64::from(*v) * 24 * 3600, 0) - .unwrap(); - let date = time.date_naive(); + let date = + NaiveDate::from_num_days_from_ce_opt((*v as i64 + UNIX_EPOCH_DAY) as i32) + .unwrap(); fmt::Display::fmt(&date.format("%Y-%m-%d"), f) } Value::Nullable(v) => match v { @@ -403,8 +402,9 @@ macro_rules! from_value { impl convert::From for AppDate { fn from(v: Value) -> AppDate { if let Value::Date(x) = v { - let time = Tz::Zulu.timestamp_opt(i64::from(x) * 24 * 3600, 0).unwrap(); - return time.date_naive(); + let date = + NaiveDate::from_num_days_from_ce_opt((x as i64 + UNIX_EPOCH_DAY) as i32).unwrap(); + return date; } let from = SqlType::from(v); panic!("Can't convert Value::{} into {}", from, "AppDate") diff --git a/clickhouse/src/types/value_ref.rs b/clickhouse/src/types/value_ref.rs index 94e58b3..664e024 100644 --- a/clickhouse/src/types/value_ref.rs +++ b/clickhouse/src/types/value_ref.rs @@ -36,6 +36,7 @@ use crate::types::Enum16; use crate::types::Enum8; use crate::types::SqlType; use crate::types::Value; +use crate::types::UNIX_EPOCH_DAY; #[derive(Clone, Debug)] pub enum ValueRef<'a> { @@ -121,17 +122,15 @@ impl<'a> fmt::Display for ValueRef<'a> { ValueRef::Float32(v) => fmt::Display::fmt(v, f), ValueRef::Float64(v) => fmt::Display::fmt(v, f), ValueRef::Date(v) if f.alternate() => { - let time = Tz::Zulu - .timestamp_opt(i64::from(*v) * 24 * 3600, 0) - .unwrap(); - let date = time.date_naive(); + let date = + NaiveDate::from_num_days_from_ce_opt((*v as i64 + UNIX_EPOCH_DAY) as i32) + .unwrap(); fmt::Display::fmt(&date, f) } ValueRef::Date(v) => { - let time = Tz::Zulu - .timestamp_opt(i64::from(*v) * 24 * 3600, 0) - .unwrap(); - let date = time.date_naive(); + let date = + NaiveDate::from_num_days_from_ce_opt((*v as i64 + UNIX_EPOCH_DAY) as i32) + .unwrap(); fmt::Display::fmt(&date.format("%Y-%m-%d"), f) } ValueRef::DateTime(u, tz) if f.alternate() => { @@ -410,8 +409,9 @@ macro_rules! value_from { impl<'a> From> for AppDate { fn from(value: ValueRef<'a>) -> Self { if let ValueRef::Date(v) = value { - let time = Tz::Zulu.timestamp_opt(i64::from(v) * 24 * 3600, 0).unwrap(); - return time.date_naive(); + let date = + NaiveDate::from_num_days_from_ce_opt((v as i64 + UNIX_EPOCH_DAY) as i32).unwrap(); + return date; } let from = format!("{}", SqlType::from(value.clone())); panic!("Can't convert ValueRef::{} into {}.", from, stringify!($t))