diff --git a/src/common/function/src/scalars/timestamp.rs b/src/common/function/src/scalars/timestamp.rs index fbee4279212d..fecf884ce02b 100644 --- a/src/common/function/src/scalars/timestamp.rs +++ b/src/common/function/src/scalars/timestamp.rs @@ -14,11 +14,9 @@ use std::sync::Arc; mod greatest; -mod to_timezone; mod to_unixtime; use greatest::GreatestFunction; -use to_timezone::ToTimezoneFunction; use to_unixtime::ToUnixtimeFunction; use crate::function_registry::FunctionRegistry; @@ -27,7 +25,6 @@ pub(crate) struct TimestampFunction; impl TimestampFunction { pub fn register(registry: &FunctionRegistry) { - registry.register(Arc::new(ToTimezoneFunction)); registry.register(Arc::new(ToUnixtimeFunction)); registry.register(Arc::new(GreatestFunction)); } diff --git a/src/common/function/src/scalars/timestamp/to_timezone.rs b/src/common/function/src/scalars/timestamp/to_timezone.rs deleted file mode 100644 index 1b366ccde3f2..000000000000 --- a/src/common/function/src/scalars/timestamp/to_timezone.rs +++ /dev/null @@ -1,313 +0,0 @@ -// Copyright 2023 Greptime Team -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -use std::fmt; -use std::sync::Arc; - -use common_query::error::{InvalidFuncArgsSnafu, Result, UnsupportedInputDataTypeSnafu}; -use common_query::prelude::Signature; -use common_time::{Timestamp, Timezone}; -use datatypes::data_type::ConcreteDataType; -use datatypes::prelude::VectorRef; -use datatypes::types::TimestampType; -use datatypes::value::Value; -use datatypes::vectors::{ - Int64Vector, StringVector, TimestampMicrosecondVector, TimestampMillisecondVector, - TimestampNanosecondVector, TimestampSecondVector, Vector, -}; -use snafu::{ensure, OptionExt}; - -use crate::function::{Function, FunctionContext}; -use crate::helper; - -#[derive(Clone, Debug, Default)] -pub struct ToTimezoneFunction; - -const NAME: &str = "to_timezone"; - -fn convert_to_timezone(arg: &str) -> Option { - Timezone::from_tz_string(arg).ok() -} - -fn convert_to_timestamp(arg: &Value) -> Option { - match arg { - Value::Timestamp(ts) => Some(*ts), - Value::Int64(i) => Some(Timestamp::new_millisecond(*i)), - _ => None, - } -} - -impl fmt::Display for ToTimezoneFunction { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "TO_TIMEZONE") - } -} - -impl Function for ToTimezoneFunction { - fn name(&self) -> &str { - NAME - } - - fn return_type(&self, input_types: &[ConcreteDataType]) -> Result { - // type checked by signature - MUST BE timestamp - Ok(input_types[0].clone()) - } - - fn signature(&self) -> Signature { - helper::one_of_sigs2( - vec![ - ConcreteDataType::int32_datatype(), - ConcreteDataType::int64_datatype(), - ConcreteDataType::timestamp_second_datatype(), - ConcreteDataType::timestamp_millisecond_datatype(), - ConcreteDataType::timestamp_microsecond_datatype(), - ConcreteDataType::timestamp_nanosecond_datatype(), - ], - vec![ConcreteDataType::string_datatype()], - ) - } - - fn eval(&self, _ctx: FunctionContext, columns: &[VectorRef]) -> Result { - ensure!( - columns.len() == 2, - InvalidFuncArgsSnafu { - err_msg: format!( - "The length of the args is not correct, expect exactly 2, have: {}", - columns.len() - ), - } - ); - - let array = columns[0].to_arrow_array(); - let times = match columns[0].data_type() { - ConcreteDataType::Int64(_) | ConcreteDataType::Int32(_) => { - let vector = Int64Vector::try_from_arrow_array(array).unwrap(); - (0..vector.len()) - .map(|i| convert_to_timestamp(&vector.get(i))) - .collect::>() - } - ConcreteDataType::Timestamp(ts) => match ts { - TimestampType::Second(_) => { - let vector = TimestampSecondVector::try_from_arrow_array(array).unwrap(); - (0..vector.len()) - .map(|i| convert_to_timestamp(&vector.get(i))) - .collect::>() - } - TimestampType::Millisecond(_) => { - let vector = TimestampMillisecondVector::try_from_arrow_array(array).unwrap(); - (0..vector.len()) - .map(|i| convert_to_timestamp(&vector.get(i))) - .collect::>() - } - TimestampType::Microsecond(_) => { - let vector = TimestampMicrosecondVector::try_from_arrow_array(array).unwrap(); - (0..vector.len()) - .map(|i| convert_to_timestamp(&vector.get(i))) - .collect::>() - } - TimestampType::Nanosecond(_) => { - let vector = TimestampNanosecondVector::try_from_arrow_array(array).unwrap(); - (0..vector.len()) - .map(|i| convert_to_timestamp(&vector.get(i))) - .collect::>() - } - }, - _ => UnsupportedInputDataTypeSnafu { - function: NAME, - datatypes: columns.iter().map(|c| c.data_type()).collect::>(), - } - .fail()?, - }; - - let tzs = { - let array = columns[1].to_arrow_array(); - let vector = StringVector::try_from_arrow_array(&array) - .ok() - .with_context(|| UnsupportedInputDataTypeSnafu { - function: NAME, - datatypes: columns.iter().map(|c| c.data_type()).collect::>(), - })?; - (0..vector.len()) - .map(|i| convert_to_timezone(&vector.get(i).to_string())) - .collect::>() - }; - - let result = times - .iter() - .zip(tzs.iter()) - .map(|(time, tz)| match (time, tz) { - (Some(time), _) => Some(time.to_timezone_aware_string(tz.as_ref())), - _ => None, - }) - .collect::>>(); - Ok(Arc::new(StringVector::from(result))) - } -} - -#[cfg(test)] -mod tests { - - use datatypes::scalars::ScalarVector; - use datatypes::timestamp::{ - TimestampMicrosecond, TimestampMillisecond, TimestampNanosecond, TimestampSecond, - }; - use datatypes::vectors::{Int64Vector, StringVector}; - - use super::*; - - #[test] - fn test_timestamp_to_timezone() { - let f = ToTimezoneFunction; - assert_eq!("to_timezone", f.name()); - - let results = vec![ - Some("1969-12-31 19:00:01"), - None, - Some("1970-01-01 03:00:01"), - None, - ]; - let times: Vec> = vec![ - Some(TimestampSecond::new(1)), - None, - Some(TimestampSecond::new(1)), - None, - ]; - let ts_vector: TimestampSecondVector = - TimestampSecondVector::from_owned_iterator(times.into_iter()); - let tzs = vec![Some("America/New_York"), None, Some("Europe/Moscow"), None]; - let args: Vec = vec![ - Arc::new(ts_vector), - Arc::new(StringVector::from(tzs.clone())), - ]; - let vector = f.eval(FunctionContext::default(), &args).unwrap(); - assert_eq!(4, vector.len()); - let expect_times: VectorRef = Arc::new(StringVector::from(results)); - assert_eq!(expect_times, vector); - - let results = vec![ - Some("1969-12-31 19:00:00.001"), - None, - Some("1970-01-01 03:00:00.001"), - None, - ]; - let times: Vec> = vec![ - Some(TimestampMillisecond::new(1)), - None, - Some(TimestampMillisecond::new(1)), - None, - ]; - let ts_vector: TimestampMillisecondVector = - TimestampMillisecondVector::from_owned_iterator(times.into_iter()); - let args: Vec = vec![ - Arc::new(ts_vector), - Arc::new(StringVector::from(tzs.clone())), - ]; - let vector = f.eval(FunctionContext::default(), &args).unwrap(); - assert_eq!(4, vector.len()); - let expect_times: VectorRef = Arc::new(StringVector::from(results)); - assert_eq!(expect_times, vector); - - let results = vec![ - Some("1969-12-31 19:00:00.000001"), - None, - Some("1970-01-01 03:00:00.000001"), - None, - ]; - let times: Vec> = vec![ - Some(TimestampMicrosecond::new(1)), - None, - Some(TimestampMicrosecond::new(1)), - None, - ]; - let ts_vector: TimestampMicrosecondVector = - TimestampMicrosecondVector::from_owned_iterator(times.into_iter()); - - let args: Vec = vec![ - Arc::new(ts_vector), - Arc::new(StringVector::from(tzs.clone())), - ]; - let vector = f.eval(FunctionContext::default(), &args).unwrap(); - assert_eq!(4, vector.len()); - let expect_times: VectorRef = Arc::new(StringVector::from(results)); - assert_eq!(expect_times, vector); - - let results = vec![ - Some("1969-12-31 19:00:00.000000001"), - None, - Some("1970-01-01 03:00:00.000000001"), - None, - ]; - let times: Vec> = vec![ - Some(TimestampNanosecond::new(1)), - None, - Some(TimestampNanosecond::new(1)), - None, - ]; - let ts_vector: TimestampNanosecondVector = - TimestampNanosecondVector::from_owned_iterator(times.into_iter()); - - let args: Vec = vec![ - Arc::new(ts_vector), - Arc::new(StringVector::from(tzs.clone())), - ]; - let vector = f.eval(FunctionContext::default(), &args).unwrap(); - assert_eq!(4, vector.len()); - let expect_times: VectorRef = Arc::new(StringVector::from(results)); - assert_eq!(expect_times, vector); - } - - #[test] - fn test_numerical_to_timezone() { - let f = ToTimezoneFunction; - let results = vec![ - Some("1969-12-31 19:00:00.001"), - None, - Some("1970-01-01 03:00:00.001"), - None, - Some("2024-03-26 23:01:50"), - None, - Some("2024-03-27 06:02:00"), - None, - ]; - let times: Vec> = vec![ - Some(1), - None, - Some(1), - None, - Some(1711508510000), - None, - Some(1711508520000), - None, - ]; - let ts_vector: Int64Vector = Int64Vector::from_owned_iterator(times.into_iter()); - let tzs = vec![ - Some("America/New_York"), - None, - Some("Europe/Moscow"), - None, - Some("America/New_York"), - None, - Some("Europe/Moscow"), - None, - ]; - let args: Vec = vec![ - Arc::new(ts_vector), - Arc::new(StringVector::from(tzs.clone())), - ]; - let vector = f.eval(FunctionContext::default(), &args).unwrap(); - assert_eq!(8, vector.len()); - let expect_times: VectorRef = Arc::new(StringVector::from(results)); - assert_eq!(expect_times, vector); - } -} diff --git a/tests/cases/standalone/common/function/time.result b/tests/cases/standalone/common/function/time.result index 83589ced352a..123b6a3f2f7c 100644 --- a/tests/cases/standalone/common/function/time.result +++ b/tests/cases/standalone/common/function/time.result @@ -20,51 +20,3 @@ select GREATEST('2000-02-11'::Date, '2020-12-30'::Date); | 2020-12-30 | +-------------------------------------------------+ -select to_timezone('2022-09-20T14:16:43.012345+08:00', 'Europe/Berlin'); - -+-----------------------------------------------------------------------------+ -| to_timezone(Utf8("2022-09-20T14:16:43.012345+08:00"),Utf8("Europe/Berlin")) | -+-----------------------------------------------------------------------------+ -| 2022-09-20 08:16:43.012345 | -+-----------------------------------------------------------------------------+ - -select to_timezone('2022-09-20T14:16:43.012345+08:00'::Timestamp, 'Europe/Berlin'); - -+------------------------------------------------------------------------------------------------------------------------------+ -| to_timezone(arrow_cast(Utf8("2022-09-20T14:16:43.012345+08:00"),Utf8("Timestamp(Millisecond, None)")),Utf8("Europe/Berlin")) | -+------------------------------------------------------------------------------------------------------------------------------+ -| 2022-09-20 08:16:43.012 | -+------------------------------------------------------------------------------------------------------------------------------+ - -select to_timezone('2024-03-29T14:16:43.012345Z', 'Asia/Shanghai'); - -+------------------------------------------------------------------------+ -| to_timezone(Utf8("2024-03-29T14:16:43.012345Z"),Utf8("Asia/Shanghai")) | -+------------------------------------------------------------------------+ -| 2024-03-29 22:16:43.012345 | -+------------------------------------------------------------------------+ - -select to_timezone('2024-03-29T14:16:43.012345Z'::Timestamp, 'Asia/Shanghai'); - -+-------------------------------------------------------------------------------------------------------------------------+ -| to_timezone(arrow_cast(Utf8("2024-03-29T14:16:43.012345Z"),Utf8("Timestamp(Millisecond, None)")),Utf8("Asia/Shanghai")) | -+-------------------------------------------------------------------------------------------------------------------------+ -| 2024-03-29 22:16:43.012 | -+-------------------------------------------------------------------------------------------------------------------------+ - -select to_timezone(1709992225, 'Asia/Shanghai'); - -+------------------------------------------------------+ -| to_timezone(Int64(1709992225),Utf8("Asia/Shanghai")) | -+------------------------------------------------------+ -| 1970-01-21 02:59:52.225 | -+------------------------------------------------------+ - -select to_timezone(1711508510000::INT64, 'Asia/Shanghai'); - -+-----------------------------------------------------------------------------------+ -| to_timezone(arrow_cast(Int64(1711508510000),Utf8("Int64")),Utf8("Asia/Shanghai")) | -+-----------------------------------------------------------------------------------+ -| 2024-03-27 11:01:50 | -+-----------------------------------------------------------------------------------+ - diff --git a/tests/cases/standalone/common/function/time.sql b/tests/cases/standalone/common/function/time.sql index 678bb48af329..46d5c2347fd5 100644 --- a/tests/cases/standalone/common/function/time.sql +++ b/tests/cases/standalone/common/function/time.sql @@ -3,13 +3,5 @@ select current_time(); select GREATEST('1999-01-30', '2023-03-01'); -select GREATEST('2000-02-11'::Date, '2020-12-30'::Date); - -select to_timezone('2022-09-20T14:16:43.012345+08:00', 'Europe/Berlin'); -select to_timezone('2022-09-20T14:16:43.012345+08:00'::Timestamp, 'Europe/Berlin'); -select to_timezone('2024-03-29T14:16:43.012345Z', 'Asia/Shanghai'); -select to_timezone('2024-03-29T14:16:43.012345Z'::Timestamp, 'Asia/Shanghai'); -select to_timezone(1709992225, 'Asia/Shanghai'); - -select to_timezone(1711508510000::INT64, 'Asia/Shanghai'); +select GREATEST('2000-02-11'::Date, '2020-12-30'::Date);