diff --git a/src/common/column/src/types/mod.rs b/src/common/column/src/types/mod.rs index e10af5be2065..c8adb38c157f 100644 --- a/src/common/column/src/types/mod.rs +++ b/src/common/column/src/types/mod.rs @@ -85,8 +85,8 @@ pub enum PrimitiveType { Float64, /// Two i32 representing days and ms DaysMs, - /// months_days_ns(i32, i32, i64) - MonthDayNano, + /// months_days_micros(i32, i32, i64) + MonthDayMicros, } mod private { diff --git a/src/common/column/src/types/native.rs b/src/common/column/src/types/native.rs index 9fb915813b9d..217adeb766a1 100644 --- a/src/common/column/src/types/native.rs +++ b/src/common/column/src/types/native.rs @@ -13,7 +13,10 @@ // See the License for the specific language governing permissions and // limitations under the License. +use std::cmp::Ordering; use std::convert::TryFrom; +use std::hash::Hash; +use std::hash::Hasher; use std::ops::Neg; use std::panic::RefUnwindSafe; @@ -252,11 +255,7 @@ impl NativeType for days_ms { Copy, Clone, Default, - PartialEq, - PartialOrd, - Ord, Eq, - Hash, Zeroable, Pod, Serialize, @@ -268,6 +267,33 @@ impl NativeType for days_ms { #[repr(C)] pub struct months_days_micros(pub i128); +const MICROS_PER_DAY: i64 = 24 * 3600 * 1_000_000; +const MICROS_PER_MONTH: i64 = 30 * MICROS_PER_DAY; + +impl Hash for months_days_micros { + fn hash(&self, state: &mut H) { + self.total_micros().hash(state) + } +} +impl PartialEq for months_days_micros { + fn eq(&self, other: &Self) -> bool { + self.total_micros() == other.total_micros() + } +} +impl PartialOrd for months_days_micros { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + +impl Ord for months_days_micros { + fn cmp(&self, other: &Self) -> Ordering { + let total_micros = self.total_micros(); + let other_micros = other.total_micros(); + total_micros.cmp(&other_micros) + } +} + impl months_days_micros { pub fn new(months: i32, days: i32, microseconds: i64) -> Self { let months_bits = (months as i128) << 96; @@ -291,10 +317,16 @@ impl months_days_micros { pub fn microseconds(&self) -> i64 { (self.0 & 0xFFFFFFFFFFFFFFFF) as i64 } + + pub fn total_micros(&self) -> i64 { + (self.months() as i64 * MICROS_PER_MONTH) + + (self.days() as i64 * MICROS_PER_DAY) + + self.microseconds() + } } impl NativeType for months_days_micros { - const PRIMITIVE: PrimitiveType = PrimitiveType::MonthDayNano; + const PRIMITIVE: PrimitiveType = PrimitiveType::MonthDayMicros; type Bytes = [u8; 16]; #[inline] fn to_le_bytes(&self) -> Self::Bytes { diff --git a/src/common/io/tests/it/interval.rs b/src/common/io/tests/it/interval.rs index 2036fbfb6785..1a320d91e8d0 100644 --- a/src/common/io/tests/it/interval.rs +++ b/src/common/io/tests/it/interval.rs @@ -76,7 +76,7 @@ fn test_interval_from_string() { } #[test] -fn test_string_to_interval() { +fn test_interval_to_string() { let tests = vec![ ( Interval { @@ -142,6 +142,14 @@ fn test_string_to_interval() { }, "-1 day 1:23:45", ), + ( + Interval { + months: 0, + days: -225, + micros: -52550000000, + }, + "-225 days -14:35:50", + ), ( Interval { months: 0, diff --git a/src/common/native/src/write/primitive.rs b/src/common/native/src/write/primitive.rs index c11be5d3676f..3988ce037fa0 100644 --- a/src/common/native/src/write/primitive.rs +++ b/src/common/native/src/write/primitive.rs @@ -87,7 +87,7 @@ pub(crate) fn write_primitive( PrimitiveType::Float16 => unimplemented!(), PrimitiveType::DaysMs => unimplemented!(), - PrimitiveType::MonthDayNano => unimplemented!(), + PrimitiveType::MonthDayMicros => unimplemented!(), PrimitiveType::UInt128 => unimplemented!(), } w.write_all(scratch.as_slice())?; diff --git a/src/query/functions/src/scalars/comparison.rs b/src/query/functions/src/scalars/comparison.rs index 7a5ee1fa771e..b89d2d202139 100644 --- a/src/query/functions/src/scalars/comparison.rs +++ b/src/query/functions/src/scalars/comparison.rs @@ -28,6 +28,7 @@ use databend_common_expression::types::DataType; use databend_common_expression::types::DateType; use databend_common_expression::types::EmptyArrayType; use databend_common_expression::types::GenericType; +use databend_common_expression::types::IntervalType; use databend_common_expression::types::MutableBitmap; use databend_common_expression::types::NumberClass; use databend_common_expression::types::NumberType; @@ -65,6 +66,7 @@ pub fn register(registry: &mut FunctionRegistry) { register_array_cmp(registry); register_tuple_cmp(registry); register_like(registry); + register_interval_cmp(registry); } pub const ALL_COMP_FUNC_NAMES: &[&str] = &["eq", "noteq", "lt", "lte", "gt", "gte", "contains"]; @@ -226,6 +228,10 @@ fn register_timestamp_cmp(registry: &mut FunctionRegistry) { register_simple_domain_type_cmp!(registry, TimestampType); } +fn register_interval_cmp(registry: &mut FunctionRegistry) { + register_simple_domain_type_cmp!(registry, IntervalType); +} + fn register_boolean_cmp(registry: &mut FunctionRegistry) { registry.register_comparison_2_arg::( "eq", diff --git a/src/query/functions/src/scalars/interval.rs b/src/query/functions/src/scalars/interval.rs index 8e086c34501c..6416c7c2eed8 100644 --- a/src/query/functions/src/scalars/interval.rs +++ b/src/query/functions/src/scalars/interval.rs @@ -13,13 +13,17 @@ // limitations under the License. use databend_common_column::types::months_days_micros; +use databend_common_expression::date_helper::EvalMonthsImpl; use databend_common_expression::error_to_null; use databend_common_expression::types::interval::interval_to_string; use databend_common_expression::types::interval::string_to_interval; +use databend_common_expression::types::Int64Type; use databend_common_expression::types::IntervalType; use databend_common_expression::types::NullableType; use databend_common_expression::types::StringType; +use databend_common_expression::types::TimestampType; use databend_common_expression::vectorize_with_builder_1_arg; +use databend_common_expression::vectorize_with_builder_2_arg; use databend_common_expression::EvalContext; use databend_common_expression::FunctionDomain; use databend_common_expression::FunctionRegistry; @@ -30,6 +34,9 @@ pub fn register(registry: &mut FunctionRegistry) { // to_interval(xx) register_string_to_interval(registry); register_interval_to_string(registry); + // data/timestamp/interval +/- interval + register_interval_add_sub(registry); + register_number_to_interval(registry); } fn register_string_to_interval(registry: &mut FunctionRegistry) { @@ -79,3 +86,227 @@ fn register_interval_to_string(registry: &mut FunctionRegistry) { ), ); } + +fn register_interval_add_sub(registry: &mut FunctionRegistry) { + registry.register_passthrough_nullable_2_arg::( + "plus", + |_, _, _| FunctionDomain::MayThrow, + vectorize_with_builder_2_arg::( + |a, b, output, _| { + output.push(months_days_micros::new( + a.months() + b.months(), + a.days() + b.days(), + a.microseconds() + b.microseconds(), + )) + }, + ), + ); + + registry + .register_passthrough_nullable_2_arg::( + "plus", + |_, _, _| FunctionDomain::MayThrow, + vectorize_with_builder_2_arg::( + |a, b, output, ctx| { + // plus microseconds and days + let ts = a + .wrapping_add(b.microseconds()) + .wrapping_add((b.days() as i64).wrapping_mul(86_400_000_000)); + match EvalMonthsImpl::eval_timestamp( + ts, + ctx.func_ctx.jiff_tz.clone(), + b.months(), + ) { + Ok(t) => output.push(t), + Err(e) => { + ctx.set_error(output.len(), e); + output.push(0); + } + } + }, + ), + ); + + registry + .register_passthrough_nullable_2_arg::( + "plus", + |_, _, _| FunctionDomain::MayThrow, + vectorize_with_builder_2_arg::( + |b, a, output, ctx| { + // plus microseconds and days + let ts = a + .wrapping_add(b.microseconds()) + .wrapping_add((b.days() as i64).wrapping_mul(86_400_000_000)); + match EvalMonthsImpl::eval_timestamp( + ts, + ctx.func_ctx.jiff_tz.clone(), + b.months(), + ) { + Ok(t) => output.push(t), + Err(e) => { + ctx.set_error(output.len(), e); + output.push(0); + } + } + }, + ), + ); + + registry.register_passthrough_nullable_2_arg::( + "minus", + |_, _, _| FunctionDomain::MayThrow, + vectorize_with_builder_2_arg::( + |a, b, output, _| { + output.push(months_days_micros::new( + a.months() - b.months(), + a.days() - b.days(), + a.microseconds() - b.microseconds(), + )); + }, + ), + ); + + registry + .register_passthrough_nullable_2_arg::( + "minus", + |_, _, _| FunctionDomain::MayThrow, + vectorize_with_builder_2_arg::( + |a, b, output, ctx| { + // plus microseconds and days + let ts = a + .wrapping_sub(b.microseconds()) + .wrapping_sub((b.days() as i64).wrapping_mul(86_400_000_000)); + match EvalMonthsImpl::eval_timestamp( + ts, + ctx.func_ctx.jiff_tz.clone(), + -b.months(), + ) { + Ok(t) => output.push(t), + Err(e) => { + ctx.set_error(output.len(), e); + output.push(0); + } + } + }, + ), + ); +} + +fn register_number_to_interval(registry: &mut FunctionRegistry) { + registry.register_passthrough_nullable_1_arg::( + "epoch", + |_, _| FunctionDomain::MayThrow, + vectorize_with_builder_1_arg::(|val, output, _| { + let res = months_days_micros::new(0, 0, val * 1_000_000); + output.push(res); + }), + ); + + registry.register_passthrough_nullable_1_arg::( + "to_centuries", + |_, _| FunctionDomain::MayThrow, + vectorize_with_builder_1_arg::(|val, output, _| { + let res = months_days_micros::new((val * 100 * 12) as i32, 0, 0); + output.push(res); + }), + ); + + registry.register_passthrough_nullable_1_arg::( + "to_days", + |_, _| FunctionDomain::MayThrow, + vectorize_with_builder_1_arg::(|val, output, _| { + let res = months_days_micros::new(0, val as i32, 0); + output.push(res); + }), + ); + + registry.register_passthrough_nullable_1_arg::( + "to_weeks", + |_, _| FunctionDomain::MayThrow, + vectorize_with_builder_1_arg::(|val, output, _| { + let res = months_days_micros::new(0, (val * 7) as i32, 0); + output.push(res); + }), + ); + + registry.register_passthrough_nullable_1_arg::( + "to_decades", + |_, _| FunctionDomain::MayThrow, + vectorize_with_builder_1_arg::(|val, output, _| { + let res = months_days_micros::new((val * 10 * 12) as i32, 0, 0); + output.push(res); + }), + ); + + registry.register_passthrough_nullable_1_arg::( + "to_hours", + |_, _| FunctionDomain::MayThrow, + vectorize_with_builder_1_arg::(|val, output, _| { + let res = months_days_micros::new(0, 0, val * 3600 * 1_000_000); + output.push(res); + }), + ); + + registry.register_passthrough_nullable_1_arg::( + "to_microseconds", + |_, _| FunctionDomain::MayThrow, + vectorize_with_builder_1_arg::(|val, output, _| { + let res = months_days_micros::new(0, 0, val); + output.push(res); + }), + ); + + registry.register_passthrough_nullable_1_arg::( + "to_millennia", + |_, _| FunctionDomain::MayThrow, + vectorize_with_builder_1_arg::(|val, output, _| { + let res = months_days_micros::new((val * 1000 * 12) as i32, 0, 0); + output.push(res); + }), + ); + + registry.register_passthrough_nullable_1_arg::( + "to_milliseconds", + |_, _| FunctionDomain::MayThrow, + vectorize_with_builder_1_arg::(|val, output, _| { + let res = months_days_micros::new(0, 0, val * 1000); + output.push(res); + }), + ); + + registry.register_passthrough_nullable_1_arg::( + "to_minutes", + |_, _| FunctionDomain::MayThrow, + vectorize_with_builder_1_arg::(|val, output, _| { + let res = months_days_micros::new(0, 0, val * 60 * 1_000_000); + output.push(res); + }), + ); + + registry.register_passthrough_nullable_1_arg::( + "to_months", + |_, _| FunctionDomain::MayThrow, + vectorize_with_builder_1_arg::(|val, output, _| { + let res = months_days_micros::new(val as i32, 0, 0); + output.push(res); + }), + ); + + registry.register_passthrough_nullable_1_arg::( + "to_seconds", + |_, _| FunctionDomain::MayThrow, + vectorize_with_builder_1_arg::(|val, output, _| { + let res = months_days_micros::new(0, 0, val * 1_000_000); + output.push(res); + }), + ); + + registry.register_passthrough_nullable_1_arg::( + "to_years", + |_, _| FunctionDomain::MayThrow, + vectorize_with_builder_1_arg::(|val, output, _| { + let res = months_days_micros::new((val * 12) as i32, 0, 0); + output.push(res); + }), + ); +} diff --git a/src/query/functions/tests/it/scalars/comparison.rs b/src/query/functions/tests/it/scalars/comparison.rs index 318673980cb0..df750d4f431d 100644 --- a/src/query/functions/tests/it/scalars/comparison.rs +++ b/src/query/functions/tests/it/scalars/comparison.rs @@ -52,6 +52,11 @@ fn test_eq(file: &mut impl Write) { run_ast(file, "(1, 'a') = (1, 'a')", &[]); run_ast(file, "(1, 'a') = (1, 'b')", &[]); run_ast(file, "today()='2020-01-01'", &[]); + run_ast( + file, + "to_interval('1 hour')=to_interval('3600 seconds')", + &[], + ); run_ast( file, "to_timestamp(-315360000000000)=to_timestamp(-100)", @@ -117,6 +122,11 @@ fn test_noteq(file: &mut impl Write) { run_ast(file, "(1, 'a') != (1,)", &[]); run_ast(file, "(1, 'a') != (1, 'a')", &[]); run_ast(file, "(1, 'a') != (1, 'b')", &[]); + run_ast( + file, + "to_interval('1 hour')!=to_interval('3600 seconds')", + &[], + ); run_ast( file, "to_timestamp(-315360000000000)!=to_timestamp(-100)", @@ -163,6 +173,7 @@ fn test_lt(file: &mut impl Write) { run_ast(file, "(1, 'b') < (1, 'a')", &[]); run_ast(file, "(1, 'a') < (1, 'b')", &[]); run_ast(file, "(1, 'a') < (2, 'a')", &[]); + run_ast(file, "to_interval('29 days') (1, 'a')", &[]); run_ast(file, "(1, 'a') > (1, 'b')", &[]); run_ast(file, "(1, 'a') > (2, 'a')", &[]); + run_ast(file, "to_interval('29 days')>to_interval('1 month')", &[]); run_ast( file, "to_timestamp(-315360000000000)>to_timestamp(-100)", @@ -311,6 +324,7 @@ fn test_gte(file: &mut impl Write) { run_ast(file, "(1, 'b') >= (1, 'a')", &[]); run_ast(file, "(1, 'a') >= (1, 'b')", &[]); run_ast(file, "(1, 'a') >= (2, 'a')", &[]); + run_ast(file, "to_interval('29 days')>=to_interval('1 month')", &[]); run_ast( file, "to_timestamp(-315360000000000)>=to_timestamp(-100)", diff --git a/src/query/functions/tests/it/scalars/testdata/comparison.txt b/src/query/functions/tests/it/scalars/testdata/comparison.txt index f68ccccfc9b8..b0f66e1ad65e 100644 --- a/src/query/functions/tests/it/scalars/testdata/comparison.txt +++ b/src/query/functions/tests/it/scalars/testdata/comparison.txt @@ -116,7 +116,7 @@ candidate functions: eq(Variant, Variant) :: Boolean : unable to unify `Tuple(UInt8, String)` with `Variant` eq(Variant NULL, Variant NULL) :: Boolean NULL : unable to unify `Tuple(UInt8, String)` with `Variant` eq(String, String) :: Boolean : unable to unify `Tuple(UInt8, String)` with `String` -... and 32 more +... and 34 more @@ -147,6 +147,15 @@ output domain : {FALSE} output : false +ast : to_interval('1 hour')=to_interval('3600 seconds') +raw expr : eq(to_interval('1 hour'), to_interval('3600 seconds')) +checked expr : eq(to_interval("1 hour"), to_interval("3600 seconds")) +optimized expr : true +output type : Boolean +output domain : {TRUE} +output : true + + ast : to_timestamp(-315360000000000)=to_timestamp(-100) raw expr : eq(to_timestamp(minus(315360000000000)), to_timestamp(minus(100))) checked expr : eq(to_timestamp(minus(315360000000000_u64)), to_timestamp(to_int64(minus(100_u8)))) @@ -350,7 +359,7 @@ candidate functions: noteq(Variant, Variant) :: Boolean : unable to unify `Tuple(UInt8, String)` with `Variant` noteq(Variant NULL, Variant NULL) :: Boolean NULL : unable to unify `Tuple(UInt8, String)` with `Variant` noteq(String, String) :: Boolean : unable to unify `Tuple(UInt8, String)` with `String` -... and 32 more +... and 34 more @@ -372,6 +381,15 @@ output domain : {TRUE} output : true +ast : to_interval('1 hour')!=to_interval('3600 seconds') +raw expr : noteq(to_interval('1 hour'), to_interval('3600 seconds')) +checked expr : noteq(to_interval("1 hour"), to_interval("3600 seconds")) +optimized expr : false +output type : Boolean +output domain : {FALSE} +output : false + + ast : to_timestamp(-315360000000000)!=to_timestamp(-100) raw expr : noteq(to_timestamp(minus(315360000000000)), to_timestamp(minus(100))) checked expr : noteq(to_timestamp(minus(315360000000000_u64)), to_timestamp(to_int64(minus(100_u8)))) @@ -537,6 +555,15 @@ output domain : {TRUE} output : true +ast : to_interval('29 days')(to_interval("29 days"), to_interval("1 month")) +optimized expr : true +output type : Boolean +output domain : {TRUE} +output : true + + ast : to_timestamp(-315360000000000)(to_timestamp(minus(315360000000000_u64)), to_timestamp(to_int64(minus(100_u8)))) @@ -717,6 +744,15 @@ output domain : {TRUE} output : true +ast : to_interval('29 days')<=to_interval('1 month') +raw expr : lte(to_interval('29 days'), to_interval('1 month')) +checked expr : lte(to_interval("29 days"), to_interval("1 month")) +optimized expr : true +output type : Boolean +output domain : {TRUE} +output : true + + ast : to_timestamp(-315360000000000)<=to_timestamp(-100) raw expr : lte(to_timestamp(minus(315360000000000)), to_timestamp(minus(100))) checked expr : lte(to_timestamp(minus(315360000000000_u64)), to_timestamp(to_int64(minus(100_u8)))) @@ -880,6 +916,15 @@ output domain : {FALSE} output : false +ast : to_interval('29 days')>to_interval('1 month') +raw expr : gt(to_interval('29 days'), to_interval('1 month')) +checked expr : gt(to_interval("29 days"), to_interval("1 month")) +optimized expr : false +output type : Boolean +output domain : {FALSE} +output : false + + ast : to_timestamp(-315360000000000)>to_timestamp(-100) raw expr : gt(to_timestamp(minus(315360000000000)), to_timestamp(minus(100))) checked expr : gt(to_timestamp(minus(315360000000000_u64)), to_timestamp(to_int64(minus(100_u8)))) @@ -1078,6 +1123,15 @@ output domain : {FALSE} output : false +ast : to_interval('29 days')>=to_interval('1 month') +raw expr : gte(to_interval('29 days'), to_interval('1 month')) +checked expr : gte(to_interval("29 days"), to_interval("1 month")) +optimized expr : false +output type : Boolean +output domain : {FALSE} +output : false + + ast : to_timestamp(-315360000000000)>=to_timestamp(-100) raw expr : gte(to_timestamp(minus(315360000000000)), to_timestamp(minus(100))) checked expr : gte(to_timestamp(minus(315360000000000_u64)), to_timestamp(to_int64(minus(100_u8)))) diff --git a/src/query/functions/tests/it/scalars/testdata/function_list.txt b/src/query/functions/tests/it/scalars/testdata/function_list.txt index de43c814ba43..52a632f4a454 100644 --- a/src/query/functions/tests/it/scalars/testdata/function_list.txt +++ b/src/query/functions/tests/it/scalars/testdata/function_list.txt @@ -1966,6 +1966,8 @@ Functions overloads: 97 divnull(Float32 NULL, Float64 NULL) :: Float64 NULL 98 divnull(Float64 NULL, Float32 NULL) :: Float64 NULL 99 divnull(Float64 NULL, Float64 NULL) :: Float64 NULL +0 epoch(Int64) :: Interval +1 epoch(Int64 NULL) :: Interval NULL 0 eq(Variant, Variant) :: Boolean 1 eq(Variant NULL, Variant NULL) :: Boolean NULL 2 eq(String, String) :: Boolean @@ -2002,6 +2004,8 @@ Functions overloads: 33 eq(Array(T0), Array(T0)) :: Boolean 34 eq(Array(T0) NULL, Array(T0) NULL) :: Boolean NULL 35 eq FACTORY +36 eq(Interval, Interval) :: Boolean +37 eq(Interval NULL, Interval NULL) :: Boolean NULL 0 exp(UInt8) :: Float64 1 exp(UInt8 NULL) :: Float64 NULL 2 exp(UInt16) :: Float64 @@ -2123,6 +2127,8 @@ Functions overloads: 33 gt(Array(T0), Array(T0)) :: Boolean 34 gt(Array(T0) NULL, Array(T0) NULL) :: Boolean NULL 35 gt FACTORY +36 gt(Interval, Interval) :: Boolean +37 gt(Interval NULL, Interval NULL) :: Boolean NULL 0 gte(Variant, Variant) :: Boolean 1 gte(Variant NULL, Variant NULL) :: Boolean NULL 2 gte(String, String) :: Boolean @@ -2159,6 +2165,8 @@ Functions overloads: 33 gte(Array(T0), Array(T0)) :: Boolean 34 gte(Array(T0) NULL, Array(T0) NULL) :: Boolean NULL 35 gte FACTORY +36 gte(Interval, Interval) :: Boolean +37 gte(Interval NULL, Interval NULL) :: Boolean NULL 0 h3_cell_area_m2(UInt64) :: Float64 1 h3_cell_area_m2(UInt64 NULL) :: Float64 NULL 0 h3_cell_area_rads2(UInt64) :: Float64 @@ -2498,6 +2506,8 @@ Functions overloads: 33 lt(Array(T0), Array(T0)) :: Boolean 34 lt(Array(T0) NULL, Array(T0) NULL) :: Boolean NULL 35 lt FACTORY +36 lt(Interval, Interval) :: Boolean +37 lt(Interval NULL, Interval NULL) :: Boolean NULL 0 lte(Variant, Variant) :: Boolean 1 lte(Variant NULL, Variant NULL) :: Boolean NULL 2 lte(String, String) :: Boolean @@ -2534,6 +2544,8 @@ Functions overloads: 33 lte(Array(T0), Array(T0)) :: Boolean 34 lte(Array(T0) NULL, Array(T0) NULL) :: Boolean NULL 35 lte FACTORY +36 lte(Interval, Interval) :: Boolean +37 lte(Interval NULL, Interval NULL) :: Boolean NULL 0 ltrim(String) :: String 1 ltrim(String NULL) :: String NULL 2 ltrim(String, String) :: String @@ -2798,6 +2810,10 @@ Functions overloads: 231 minus(Date NULL, Int64 NULL) :: Date NULL 232 minus(Timestamp, Int64) :: Timestamp 233 minus(Timestamp NULL, Int64 NULL) :: Timestamp NULL +234 minus(Interval, Interval) :: Interval +235 minus(Interval NULL, Interval NULL) :: Interval NULL +236 minus(Timestamp, Interval) :: Timestamp +237 minus(Timestamp NULL, Interval NULL) :: Timestamp NULL 0 modulo(UInt8, UInt8) :: UInt8 1 modulo(UInt8 NULL, UInt8 NULL) :: UInt8 NULL 2 modulo(UInt8, UInt16) :: UInt16 @@ -3241,6 +3257,8 @@ Functions overloads: 33 noteq(Array(T0), Array(T0)) :: Boolean 34 noteq(Array(T0) NULL, Array(T0) NULL) :: Boolean NULL 35 noteq FACTORY +36 noteq(Interval, Interval) :: Boolean +37 noteq(Interval NULL, Interval NULL) :: Boolean NULL 0 now() :: Timestamp 0 oct(Int64) :: String 1 oct(Int64 NULL) :: String NULL @@ -3460,6 +3478,12 @@ Functions overloads: 202 plus(Date NULL, Int64 NULL) :: Date NULL 203 plus(Timestamp, Int64) :: Timestamp 204 plus(Timestamp NULL, Int64 NULL) :: Timestamp NULL +205 plus(Interval, Interval) :: Interval +206 plus(Interval NULL, Interval NULL) :: Interval NULL +207 plus(Timestamp, Interval) :: Timestamp +208 plus(Timestamp NULL, Interval NULL) :: Timestamp NULL +209 plus(Interval, Timestamp) :: Timestamp +210 plus(Interval NULL, Timestamp NULL) :: Timestamp NULL 0 point_in_ellipses FACTORY 0 point_in_polygon FACTORY 1 point_in_polygon FACTORY @@ -3801,6 +3825,8 @@ Functions overloads: 21 to_boolean(Float32 NULL) :: Boolean NULL 22 to_boolean(Float64) :: Boolean 23 to_boolean(Float64 NULL) :: Boolean NULL +0 to_centuries(Int64) :: Interval +1 to_centuries(Int64 NULL) :: Interval NULL 0 to_char(Int64, String) :: String 1 to_char(Int64 NULL, String NULL) :: String NULL 2 to_char(Float32, String) :: String @@ -3829,6 +3855,10 @@ Functions overloads: 1 to_day_of_year(Date NULL) :: UInt16 NULL 2 to_day_of_year(Timestamp) :: UInt16 3 to_day_of_year(Timestamp NULL) :: UInt16 NULL +0 to_days(Int64) :: Interval +1 to_days(Int64 NULL) :: Interval NULL +0 to_decades(Int64) :: Interval +1 to_decades(Int64 NULL) :: Interval NULL 0 to_decimal FACTORY 1 to_decimal FACTORY 0 to_float32(Variant) :: Float32 @@ -3903,6 +3933,8 @@ Functions overloads: 5 to_hex(Binary NULL) :: String NULL 0 to_hour(Timestamp) :: UInt8 1 to_hour(Timestamp NULL) :: UInt8 NULL +0 to_hours(Int64) :: Interval +1 to_hours(Int64 NULL) :: Interval NULL 0 to_int16(Variant) :: Int16 1 to_int16(Variant NULL) :: Int16 NULL 2 to_int16(String) :: Int16 @@ -4029,8 +4061,16 @@ Functions overloads: 1 to_last_of_year(Date NULL) :: Date NULL 2 to_last_of_year(Timestamp) :: Date 3 to_last_of_year(Timestamp NULL) :: Date NULL +0 to_microseconds(Int64) :: Interval +1 to_microseconds(Int64 NULL) :: Interval NULL +0 to_millennia(Int64) :: Interval +1 to_millennia(Int64 NULL) :: Interval NULL +0 to_milliseconds(Int64) :: Interval +1 to_milliseconds(Int64 NULL) :: Interval NULL 0 to_minute(Timestamp) :: UInt8 1 to_minute(Timestamp NULL) :: UInt8 NULL +0 to_minutes(Int64) :: Interval +1 to_minutes(Int64 NULL) :: Interval NULL 0 to_monday(Date) :: Date 1 to_monday(Date NULL) :: Date NULL 2 to_monday(Timestamp) :: Date @@ -4039,6 +4079,8 @@ Functions overloads: 1 to_month(Date NULL) :: UInt8 NULL 2 to_month(Timestamp) :: UInt8 3 to_month(Timestamp NULL) :: UInt8 NULL +0 to_months(Int64) :: Interval +1 to_months(Int64 NULL) :: Interval NULL 0 to_next_friday(Date) :: Date 1 to_next_friday(Date NULL) :: Date NULL 2 to_next_friday(Timestamp) :: Date @@ -4103,6 +4145,8 @@ Functions overloads: 3 to_quarter(Timestamp NULL) :: UInt8 NULL 0 to_second(Timestamp) :: UInt8 1 to_second(Timestamp NULL) :: UInt8 NULL +0 to_seconds(Int64) :: Interval +1 to_seconds(Int64 NULL) :: Interval NULL 0 to_start_of_day(Timestamp) :: Timestamp 1 to_start_of_day(Timestamp NULL) :: Timestamp NULL 0 to_start_of_fifteen_minutes(Timestamp) :: Timestamp @@ -4305,10 +4349,14 @@ Functions overloads: 1 to_week_of_year(Date NULL) :: UInt32 NULL 2 to_week_of_year(Timestamp) :: UInt32 3 to_week_of_year(Timestamp NULL) :: UInt32 NULL +0 to_weeks(Int64) :: Interval +1 to_weeks(Int64 NULL) :: Interval NULL 0 to_year(Date) :: UInt16 1 to_year(Date NULL) :: UInt16 NULL 2 to_year(Timestamp) :: UInt16 3 to_year(Timestamp NULL) :: UInt16 NULL +0 to_years(Int64) :: Interval +1 to_years(Int64 NULL) :: Interval NULL 0 to_yyyymm(Date) :: UInt32 1 to_yyyymm(Date NULL) :: UInt32 NULL 2 to_yyyymm(Timestamp) :: UInt32 diff --git a/tests/sqllogictests/suites/base/06_show/06_0005_show_functions.test b/tests/sqllogictests/suites/base/06_show/06_0005_show_functions.test index 0bcc0f9b023f..248a83488643 100644 --- a/tests/sqllogictests/suites/base/06_show/06_0005_show_functions.test +++ b/tests/sqllogictests/suites/base/06_show/06_0005_show_functions.test @@ -5,7 +5,7 @@ today 0 (empty) query TBT -SHOW FUNCTIONS LIKE 'to_day%' +SHOW FUNCTIONS LIKE 'to_day_o%' ---- to_day_of_month 0 (empty) to_day_of_week 0 (empty) diff --git a/tests/sqllogictests/suites/query/functions/02_0079_function_interval.test b/tests/sqllogictests/suites/query/functions/02_0079_function_interval.test index 771c021ecdca..f5d0facb1de4 100644 --- a/tests/sqllogictests/suites/query/functions/02_0079_function_interval.test +++ b/tests/sqllogictests/suites/query/functions/02_0079_function_interval.test @@ -13,6 +13,12 @@ select * from t order by c1; -1 year -1 month 0:00:00.000001 -1 month -1:00:00 0:00:00.001 +onlyif http +query TT +select * from t where c1 > to_interval('-1 year'); +---- +-1 month -1:00:00 0:00:00.001 + onlyif http statement error 1006 select to_interval('1 month 1 hour ago 1 micros'); @@ -28,3 +34,105 @@ query T select to_interval('1 month 1 hour 1 microsecond ago'); ---- -1 month -1:00:00.000001 + +onlyif http +query T +select to_interval('1 month 1 hour 1 microsecond ago'); +---- +-1 month -1:00:00.000001 + +onlyif http +query T +select to_interval('12 month') = to_interval('360 days') +---- +1 + +onlyif http +query T +select to_interval('12 month') = to_interval('1 year'); +---- +1 + +onlyif http +query T +select to_interval('1 hours') = to_interval('3600 seconds') as eq, to_interval('2 hours') > to_interval('3600 seconds'); +---- +1 1 + +onlyif http +query T +SELECT epoch(10); +---- +0:00:10 + +onlyif http +query T +SELECT to_centuries(2); +---- +200 years + +onlyif http +query T +SELECT to_days(5); +---- +5 days + +onlyif http +query T +SELECT to_decades(3); +---- +30 years + +onlyif http +query T +SELECT TIMESTAMP '2024-12-20 10:00:00' + to_hours(4); +---- +2024-12-20 14:00:00.000000 + +onlyif http +query T +SELECT TIMESTAMP '2024-12-20 10:00:00' + to_microseconds(500000); +---- +2024-12-20 10:00:00.500000 + +onlyif http +query T +SELECT to_millennia(1); +---- +1000 years + +onlyif http +query T +SELECT TIMESTAMP '2024-12-20 10:00:00' + to_milliseconds(750); +---- +2024-12-20 10:00:00.750000 + +onlyif http +query T +SELECT TIMESTAMP '2024-12-20 10:00:00' + to_minutes(30); +---- +2024-12-20 10:30:00.000000 + +onlyif http +query T +SELECT to_months(3); +---- +3 months + +onlyif http +query T +SELECT TIMESTAMP '2024-12-20 10:00:00' + to_seconds(60); +---- +2024-12-20 10:01:00.000000 + +onlyif http +query T +SELECT to_weeks(2); +---- +14 days + +onlyif http +query T +SELECT to_years(10); +---- +10 years diff --git a/tests/sqllogictests/suites/query/functions/02_0080_function_interval_addsub.test b/tests/sqllogictests/suites/query/functions/02_0080_function_interval_addsub.test new file mode 100644 index 000000000000..3158e2e6fb26 --- /dev/null +++ b/tests/sqllogictests/suites/query/functions/02_0080_function_interval_addsub.test @@ -0,0 +1,238 @@ +onlyif http +query T +SELECT DATE '1992-03-01' + to_interval('1 year') +---- +1993-03-01 00:00:00.000000 + +onlyif http +query T +SELECT DATE '1992-03-01' + to_interval('0 month') +---- +1992-03-01 00:00:00.000000 + +onlyif http +query T +SELECT DATE '1992-03-01' - to_interval('0 month') +---- +1992-03-01 00:00:00.000000 + +onlyif http +query T +SELECT DATE '1992-03-01' + to_interval('1 month') +---- +1992-04-01 00:00:00.000000 + +onlyif http +query T +SELECT DATE '1992-03-01' - to_interval('1 month') +---- +1992-02-01 00:00:00.000000 + +onlyif http +query T +SELECT DATE '1992-03-01' + to_interval('2 month') +---- +1992-05-01 00:00:00.000000 + +onlyif http +query T +SELECT DATE '1992-03-01' - to_interval('2 month') +---- +1992-01-01 00:00:00.000000 + +onlyif http +query T +SELECT DATE '1992-03-01' + to_interval('3 month') +---- +1992-06-01 00:00:00.000000 + +onlyif http +query T +SELECT DATE '1992-03-01' - to_interval('3 month') +---- +1991-12-01 00:00:00.000000 + +onlyif http +query T +SELECT DATE '1992-03-01' + to_interval('4 month') +---- +1992-07-01 00:00:00.000000 + +onlyif http +query T +SELECT DATE '1992-03-01' - to_interval('4 month') +---- +1991-11-01 00:00:00.000000 + +onlyif http +query T +SELECT DATE '1992-03-01' + to_interval('5 month') +---- +1992-08-01 00:00:00.000000 + +onlyif http +query T +SELECT DATE '1992-03-01' - to_interval('5 month') +---- +1991-10-01 00:00:00.000000 + +onlyif http +query T +SELECT DATE '1992-03-01' + to_interval('6 month') +---- +1992-09-01 00:00:00.000000 + +onlyif http +query T +SELECT DATE '1992-03-01' - to_interval('6 month') +---- +1991-09-01 00:00:00.000000 + +onlyif http +query T +SELECT DATE '1992-03-01' + to_interval('7 month') +---- +1992-10-01 00:00:00.000000 + +onlyif http +query T +SELECT DATE '1992-03-01' - to_interval('7 month') +---- +1991-08-01 00:00:00.000000 + +onlyif http +query T +SELECT DATE '1992-03-01' + to_interval('8 month') +---- +1992-11-01 00:00:00.000000 + +onlyif http +query T +SELECT DATE '1992-03-01' - to_interval('8 month') +---- +1991-07-01 00:00:00.000000 + +onlyif http +query T +SELECT DATE '1992-03-01' + to_interval('9 month') +---- +1992-12-01 00:00:00.000000 + +onlyif http +query T +SELECT DATE '1992-03-01' - to_interval('9 month') +---- +1991-06-01 00:00:00.000000 + +onlyif http +query T +SELECT DATE '1992-03-01' + to_interval('10 month') +---- +1993-01-01 00:00:00.000000 + +onlyif http +query T +SELECT DATE '1992-03-01' - to_interval('10 month') +---- +1991-05-01 00:00:00.000000 + +onlyif http +query T +SELECT DATE '1992-03-01' + to_interval('11 month') +---- +1993-02-01 00:00:00.000000 + +onlyif http +query T +SELECT DATE '1992-03-01' - to_interval('11 month') +---- +1991-04-01 00:00:00.000000 + +onlyif http +query T +SELECT DATE '1992-03-01' + to_interval('12 month') +---- +1993-03-01 00:00:00.000000 + +onlyif http +query T +SELECT DATE '1992-03-01' - to_interval('12 month') +---- +1991-03-01 00:00:00.000000 + +onlyif http +query T +SELECT DATE '1992-03-01' + to_interval('10 day') +---- +1992-03-11 00:00:00.000000 + +onlyif http +query T +SELECT DATE '1992-03-01' - to_interval('10 day') +---- +1992-02-20 00:00:00.000000 + +onlyif http +query T +SELECT DATE '1993-03-01' - to_interval('10 day') +---- +1993-02-19 00:00:00.000000 + +onlyif http +query T +SELECT DATE '1993-03-01' - to_interval('1 second') +---- +1993-02-28 23:59:59.000000 + +onlyif http +query T +SELECT DATE '1992-03-01' + to_interval('1 second') +---- +1992-03-01 00:00:01.000000 + +onlyif http +query T +SELECT DATE '1992-03-01' - to_interval('1 second') +---- +1992-02-29 23:59:59.000000 + +onlyif http +query T +SELECT DATE '1993-03-01' + to_interval('1000000 second') +---- +1993-03-12 13:46:40.000000 + +onlyif http +query T +SELECT DATE '1993-03-01' - to_interval('1000000 second') +---- +1993-02-17 10:13:20.000000 + +onlyif http +statement error +SELECT to_interval('1000000 second') - DATE '1993-03-01' + +onlyif http +query T +SELECT TIMESTAMP '1992-01-01 10:00:00' + to_interval('1 day') +---- +1992-01-02 10:00:00.000000 + +onlyif http +query T +SELECT to_interval('1 day') + TIMESTAMP '1992-01-01 10:00:00' +---- +1992-01-02 10:00:00.000000 + +onlyif http +query T +SELECT TIMESTAMP '1992-01-01 10:00:05' + to_interval('17 years 3 months 1 day 2 hours 1 minute 57 seconds') +---- +2009-04-02 12:02:02.000000 + +onlyif http +query T +SELECT TIMESTAMP '1992-01-01 10:00:00' - to_interval('1 day') +---- +1991-12-31 10:00:00.000000 +