From 2681cffa6dbf57ad50e3359cf9930342a47e8a07 Mon Sep 17 00:00:00 2001 From: Mryange Date: Mon, 17 Aug 2026 17:01:02 +0800 Subject: [PATCH 1/3] [fix](fe) Preserve TIMESTAMPTZ for microsecond interval arithmetic ### What problem does this PR solve? Issue Number: None Related PR: None Problem Summary: Nereids forced day, hour, and minute microsecond interval arithmetic signatures to DATETIMEV2 even when the input was TIMESTAMPTZ. Preserve the TIMESTAMPTZ argument and return types so these interval operations can be planned and executed correctly. ### Release note Support TIMESTAMPTZ values in day, hour, and minute microsecond interval addition and subtraction. ### Check List (For Author) - Test: Regression test and FE build - Regression test - Behavior changed: Yes, TIMESTAMPTZ microsecond interval arithmetic is now supported - Does this need documentation: No --- .../functions/scalar/DayMicrosecondAdd.java | 3 ++ .../functions/scalar/DayMicrosecondSub.java | 3 ++ .../functions/scalar/HourMicrosecondAdd.java | 3 ++ .../functions/scalar/HourMicrosecondSub.java | 3 ++ .../scalar/MinuteMicrosecondAdd.java | 3 ++ .../scalar/MinuteMicrosecondSub.java | 3 ++ .../test_timestamptz_microsecond_interval.out | 4 ++ ...st_timestamptz_microsecond_interval.groovy | 46 +++++++++++++++++++ 8 files changed, 68 insertions(+) create mode 100644 regression-test/data/datatype_p0/timestamptz/test_timestamptz_microsecond_interval.out create mode 100644 regression-test/suites/datatype_p0/timestamptz/test_timestamptz_microsecond_interval.groovy diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DayMicrosecondAdd.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DayMicrosecondAdd.java index 22b319464bc08a..10d0f6cf0c298c 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DayMicrosecondAdd.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DayMicrosecondAdd.java @@ -80,6 +80,9 @@ public Expression withConstantArgs(Expression literal) { @Override public FunctionSignature computeSignature(FunctionSignature signature) { signature = super.computeSignature(signature); + if (signature.argumentsTypes.get(0) instanceof TimeStampTzType) { + return signature.withArgumentType(0, TimeStampTzType.MAX).withReturnType(TimeStampTzType.MAX); + } return signature.withArgumentType(0, DateTimeV2Type.MAX).withReturnType(DateTimeV2Type.MAX); } } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DayMicrosecondSub.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DayMicrosecondSub.java index efb61c5f72ec17..882bc6ef6d5b73 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DayMicrosecondSub.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DayMicrosecondSub.java @@ -80,6 +80,9 @@ public Expression withConstantArgs(Expression literal) { @Override public FunctionSignature computeSignature(FunctionSignature signature) { signature = super.computeSignature(signature); + if (signature.argumentsTypes.get(0) instanceof TimeStampTzType) { + return signature.withArgumentType(0, TimeStampTzType.MAX).withReturnType(TimeStampTzType.MAX); + } return signature.withArgumentType(0, DateTimeV2Type.MAX).withReturnType(DateTimeV2Type.MAX); } } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/HourMicrosecondAdd.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/HourMicrosecondAdd.java index d7f7c9e2a31faa..507fc3906dd15c 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/HourMicrosecondAdd.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/HourMicrosecondAdd.java @@ -80,6 +80,9 @@ public Expression withConstantArgs(Expression literal) { @Override public FunctionSignature computeSignature(FunctionSignature signature) { signature = super.computeSignature(signature); + if (signature.argumentsTypes.get(0) instanceof TimeStampTzType) { + return signature.withArgumentType(0, TimeStampTzType.MAX).withReturnType(TimeStampTzType.MAX); + } return signature.withArgumentType(0, DateTimeV2Type.MAX).withReturnType(DateTimeV2Type.MAX); } } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/HourMicrosecondSub.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/HourMicrosecondSub.java index 1d43cb8e94cc5b..f6a5c7d65c73e7 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/HourMicrosecondSub.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/HourMicrosecondSub.java @@ -80,6 +80,9 @@ public Expression withConstantArgs(Expression literal) { @Override public FunctionSignature computeSignature(FunctionSignature signature) { signature = super.computeSignature(signature); + if (signature.argumentsTypes.get(0) instanceof TimeStampTzType) { + return signature.withArgumentType(0, TimeStampTzType.MAX).withReturnType(TimeStampTzType.MAX); + } return signature.withArgumentType(0, DateTimeV2Type.MAX).withReturnType(DateTimeV2Type.MAX); } } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MinuteMicrosecondAdd.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MinuteMicrosecondAdd.java index 135666d6d52cf4..aaee9387be9e14 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MinuteMicrosecondAdd.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MinuteMicrosecondAdd.java @@ -80,6 +80,9 @@ public Expression withConstantArgs(Expression literal) { @Override public FunctionSignature computeSignature(FunctionSignature signature) { signature = super.computeSignature(signature); + if (signature.argumentsTypes.get(0) instanceof TimeStampTzType) { + return signature.withArgumentType(0, TimeStampTzType.MAX).withReturnType(TimeStampTzType.MAX); + } return signature.withArgumentType(0, DateTimeV2Type.MAX).withReturnType(DateTimeV2Type.MAX); } } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MinuteMicrosecondSub.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MinuteMicrosecondSub.java index 45b7272d505f46..f11cff14f7e796 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MinuteMicrosecondSub.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MinuteMicrosecondSub.java @@ -80,6 +80,9 @@ public Expression withConstantArgs(Expression literal) { @Override public FunctionSignature computeSignature(FunctionSignature signature) { signature = super.computeSignature(signature); + if (signature.argumentsTypes.get(0) instanceof TimeStampTzType) { + return signature.withArgumentType(0, TimeStampTzType.MAX).withReturnType(TimeStampTzType.MAX); + } return signature.withArgumentType(0, DateTimeV2Type.MAX).withReturnType(DateTimeV2Type.MAX); } } diff --git a/regression-test/data/datatype_p0/timestamptz/test_timestamptz_microsecond_interval.out b/regression-test/data/datatype_p0/timestamptz/test_timestamptz_microsecond_interval.out new file mode 100644 index 00000000000000..bf21c3b4c103eb --- /dev/null +++ b/regression-test/data/datatype_p0/timestamptz/test_timestamptz_microsecond_interval.out @@ -0,0 +1,4 @@ +-- This file is automatically generated. You should know what you did if you want to edit this +-- !timestamptz_microsecond_interval -- +1 2024-01-03T05:07:09.246456 2024-01-01T01:01:00.999544 2024-01-02T05:07:09.246456 2024-01-02T01:01:00.999544 2024-01-02T03:07:09.246456 2024-01-02T03:01:00.999544 + diff --git a/regression-test/suites/datatype_p0/timestamptz/test_timestamptz_microsecond_interval.groovy b/regression-test/suites/datatype_p0/timestamptz/test_timestamptz_microsecond_interval.groovy new file mode 100644 index 00000000000000..c3647a57b10404 --- /dev/null +++ b/regression-test/suites/datatype_p0/timestamptz/test_timestamptz_microsecond_interval.groovy @@ -0,0 +1,46 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you 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. + +suite("test_timestamptz_microsecond_interval") { + sql "set time_zone = '+08:00'" + sql "drop table if exists test_timestamptz_microsecond_interval" + sql """ + create table test_timestamptz_microsecond_interval ( + id int, + ts timestamptz(3) + ) + duplicate key(id) + distributed by hash(id) buckets 1 + properties("replication_num" = "1") + """ + sql """ + insert into test_timestamptz_microsecond_interval values + (1, '2024-01-02 03:04:05.123 +08:00') + """ + + order_qt_timestamptz_microsecond_interval """ + select id, + date_add(ts, interval '1 02:03:04.123456' day_microsecond), + date_sub(ts, interval '1 02:03:04.123456' day_microsecond), + date_add(ts, interval '02:03:04.123456' hour_microsecond), + date_sub(ts, interval '02:03:04.123456' hour_microsecond), + date_add(ts, interval '03:04.123456' minute_microsecond), + date_sub(ts, interval '03:04.123456' minute_microsecond) + from test_timestamptz_microsecond_interval + order by id + """ +} From d86cce4460e5b3df24b796a96aa42a595ebc0edd Mon Sep 17 00:00:00 2001 From: Mryange Date: Mon, 17 Aug 2026 19:27:55 +0800 Subject: [PATCH 2/3] [fix](fe) Match wildcard scales for microsecond intervals ### What problem does this PR solve? Issue Number: None Related PR: #66843 Problem Summary: Concrete scale-6 candidate signatures were selected before return-type computation, so TIMESTAMPTZ inputs with scales below 6 could match the DATETIMEV2 candidate. Use wildcard-scale candidates for all day, hour, and minute microsecond add/subtract functions, then promote the selected type family to scale 6. Extend regression coverage across TIMESTAMPTZ(0), TIMESTAMPTZ(3), and TIMESTAMPTZ(6), including return-type checks and existing timezone-literal expectations. ### Release note Preserve TIMESTAMPTZ results for day, hour, and minute microsecond interval arithmetic at all supported input scales. ### Check List (For Author) - Test: FE build and regression tests - Regression test - Behavior changed: Yes, TIMESTAMPTZ inputs now retain their type family and return scale 6 - Does this need documentation: No --- .../functions/scalar/DayMicrosecondAdd.java | 8 +-- .../functions/scalar/DayMicrosecondSub.java | 8 +-- .../functions/scalar/HourMicrosecondAdd.java | 8 +-- .../functions/scalar/HourMicrosecondSub.java | 8 +-- .../scalar/MinuteMicrosecondAdd.java | 8 +-- .../scalar/MinuteMicrosecondSub.java | 8 +-- .../test_timestamptz_microsecond_interval.out | 10 ++- .../test_add_sub_union_type.out | 36 +++++----- ...st_timestamptz_microsecond_interval.groovy | 68 ++++++++++++++++--- 9 files changed, 109 insertions(+), 53 deletions(-) diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DayMicrosecondAdd.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DayMicrosecondAdd.java index 10d0f6cf0c298c..5c66f81e21f051 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DayMicrosecondAdd.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DayMicrosecondAdd.java @@ -41,10 +41,10 @@ public class DayMicrosecondAdd extends ScalarFunction implements BinaryExpression, ExplicitlyCastableSignature, ComputeSignatureForDateArithmetic, PropagateNullable, DateAddSubMonotonic { public static final List SIGNATURES = ImmutableList.of( - FunctionSignature.ret(DateTimeV2Type.MAX) - .args(DateTimeV2Type.MAX, VarcharType.SYSTEM_DEFAULT), - FunctionSignature.ret(TimeStampTzType.MAX) - .args(TimeStampTzType.MAX, VarcharType.SYSTEM_DEFAULT) + FunctionSignature.ret(DateTimeV2Type.WILDCARD) + .args(DateTimeV2Type.WILDCARD, VarcharType.SYSTEM_DEFAULT), + FunctionSignature.ret(TimeStampTzType.WILDCARD) + .args(TimeStampTzType.WILDCARD, VarcharType.SYSTEM_DEFAULT) ); public DayMicrosecondAdd(Expression arg0, Expression arg1) { diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DayMicrosecondSub.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DayMicrosecondSub.java index 882bc6ef6d5b73..8632af81cd7bb5 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DayMicrosecondSub.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DayMicrosecondSub.java @@ -41,10 +41,10 @@ public class DayMicrosecondSub extends ScalarFunction implements BinaryExpression, ExplicitlyCastableSignature, ComputeSignatureForDateArithmetic, PropagateNullable, DateAddSubMonotonic { public static final List SIGNATURES = ImmutableList.of( - FunctionSignature.ret(DateTimeV2Type.MAX) - .args(DateTimeV2Type.MAX, VarcharType.SYSTEM_DEFAULT), - FunctionSignature.ret(TimeStampTzType.MAX) - .args(TimeStampTzType.MAX, VarcharType.SYSTEM_DEFAULT) + FunctionSignature.ret(DateTimeV2Type.WILDCARD) + .args(DateTimeV2Type.WILDCARD, VarcharType.SYSTEM_DEFAULT), + FunctionSignature.ret(TimeStampTzType.WILDCARD) + .args(TimeStampTzType.WILDCARD, VarcharType.SYSTEM_DEFAULT) ); public DayMicrosecondSub(Expression arg0, Expression arg1) { diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/HourMicrosecondAdd.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/HourMicrosecondAdd.java index 507fc3906dd15c..2c3af7fba39919 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/HourMicrosecondAdd.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/HourMicrosecondAdd.java @@ -41,10 +41,10 @@ public class HourMicrosecondAdd extends ScalarFunction implements BinaryExpression, ExplicitlyCastableSignature, ComputeSignatureForDateArithmetic, PropagateNullable, DateAddSubMonotonic { public static final List SIGNATURES = ImmutableList.of( - FunctionSignature.ret(DateTimeV2Type.MAX) - .args(DateTimeV2Type.MAX, VarcharType.SYSTEM_DEFAULT), - FunctionSignature.ret(TimeStampTzType.MAX) - .args(TimeStampTzType.MAX, VarcharType.SYSTEM_DEFAULT) + FunctionSignature.ret(DateTimeV2Type.WILDCARD) + .args(DateTimeV2Type.WILDCARD, VarcharType.SYSTEM_DEFAULT), + FunctionSignature.ret(TimeStampTzType.WILDCARD) + .args(TimeStampTzType.WILDCARD, VarcharType.SYSTEM_DEFAULT) ); public HourMicrosecondAdd(Expression arg0, Expression arg1) { diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/HourMicrosecondSub.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/HourMicrosecondSub.java index f6a5c7d65c73e7..dff62b08966124 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/HourMicrosecondSub.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/HourMicrosecondSub.java @@ -41,10 +41,10 @@ public class HourMicrosecondSub extends ScalarFunction implements BinaryExpression, ExplicitlyCastableSignature, ComputeSignatureForDateArithmetic, PropagateNullable, DateAddSubMonotonic { public static final List SIGNATURES = ImmutableList.of( - FunctionSignature.ret(DateTimeV2Type.MAX) - .args(DateTimeV2Type.MAX, VarcharType.SYSTEM_DEFAULT), - FunctionSignature.ret(TimeStampTzType.MAX) - .args(TimeStampTzType.MAX, VarcharType.SYSTEM_DEFAULT) + FunctionSignature.ret(DateTimeV2Type.WILDCARD) + .args(DateTimeV2Type.WILDCARD, VarcharType.SYSTEM_DEFAULT), + FunctionSignature.ret(TimeStampTzType.WILDCARD) + .args(TimeStampTzType.WILDCARD, VarcharType.SYSTEM_DEFAULT) ); public HourMicrosecondSub(Expression arg0, Expression arg1) { diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MinuteMicrosecondAdd.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MinuteMicrosecondAdd.java index aaee9387be9e14..fa62f3a2e3ca69 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MinuteMicrosecondAdd.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MinuteMicrosecondAdd.java @@ -41,10 +41,10 @@ public class MinuteMicrosecondAdd extends ScalarFunction implements BinaryExpression, ExplicitlyCastableSignature, ComputeSignatureForDateArithmetic, PropagateNullable, DateAddSubMonotonic { public static final List SIGNATURES = ImmutableList.of( - FunctionSignature.ret(DateTimeV2Type.MAX) - .args(DateTimeV2Type.MAX, VarcharType.SYSTEM_DEFAULT), - FunctionSignature.ret(TimeStampTzType.MAX) - .args(TimeStampTzType.MAX, VarcharType.SYSTEM_DEFAULT) + FunctionSignature.ret(DateTimeV2Type.WILDCARD) + .args(DateTimeV2Type.WILDCARD, VarcharType.SYSTEM_DEFAULT), + FunctionSignature.ret(TimeStampTzType.WILDCARD) + .args(TimeStampTzType.WILDCARD, VarcharType.SYSTEM_DEFAULT) ); public MinuteMicrosecondAdd(Expression arg0, Expression arg1) { diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MinuteMicrosecondSub.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MinuteMicrosecondSub.java index f11cff14f7e796..fc2a102ff8da53 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MinuteMicrosecondSub.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MinuteMicrosecondSub.java @@ -41,10 +41,10 @@ public class MinuteMicrosecondSub extends ScalarFunction implements BinaryExpression, ExplicitlyCastableSignature, ComputeSignatureForDateArithmetic, PropagateNullable, DateAddSubMonotonic { public static final List SIGNATURES = ImmutableList.of( - FunctionSignature.ret(DateTimeV2Type.MAX) - .args(DateTimeV2Type.MAX, VarcharType.SYSTEM_DEFAULT), - FunctionSignature.ret(TimeStampTzType.MAX) - .args(TimeStampTzType.MAX, VarcharType.SYSTEM_DEFAULT) + FunctionSignature.ret(DateTimeV2Type.WILDCARD) + .args(DateTimeV2Type.WILDCARD, VarcharType.SYSTEM_DEFAULT), + FunctionSignature.ret(TimeStampTzType.WILDCARD) + .args(TimeStampTzType.WILDCARD, VarcharType.SYSTEM_DEFAULT) ); public MinuteMicrosecondSub(Expression arg0, Expression arg1) { diff --git a/regression-test/data/datatype_p0/timestamptz/test_timestamptz_microsecond_interval.out b/regression-test/data/datatype_p0/timestamptz/test_timestamptz_microsecond_interval.out index bf21c3b4c103eb..51f6bcdd3b3df9 100644 --- a/regression-test/data/datatype_p0/timestamptz/test_timestamptz_microsecond_interval.out +++ b/regression-test/data/datatype_p0/timestamptz/test_timestamptz_microsecond_interval.out @@ -1,4 +1,10 @@ -- This file is automatically generated. You should know what you did if you want to edit this --- !timestamptz_microsecond_interval -- -1 2024-01-03T05:07:09.246456 2024-01-01T01:01:00.999544 2024-01-02T05:07:09.246456 2024-01-02T01:01:00.999544 2024-01-02T03:07:09.246456 2024-01-02T03:01:00.999544 +-- !timestamptz_microsecond_interval_scale_0 -- +1 2024-01-03 05:07:09.123456+08:00 2024-01-01 01:01:00.876544+08:00 2024-01-02 05:07:09.123456+08:00 2024-01-02 01:01:00.876544+08:00 2024-01-02 03:07:09.123456+08:00 2024-01-02 03:01:00.876544+08:00 + +-- !timestamptz_microsecond_interval_scale_3 -- +1 2024-01-03 05:07:09.246456+08:00 2024-01-01 01:01:00.999544+08:00 2024-01-02 05:07:09.246456+08:00 2024-01-02 01:01:00.999544+08:00 2024-01-02 03:07:09.246456+08:00 2024-01-02 03:01:00.999544+08:00 + +-- !timestamptz_microsecond_interval_scale_6 -- +1 2024-01-03 05:07:09.246912+08:00 2024-01-01 01:01:01.000000+08:00 2024-01-02 05:07:09.246912+08:00 2024-01-02 01:01:01.000000+08:00 2024-01-02 03:07:09.246912+08:00 2024-01-02 03:01:01.000000+08:00 diff --git a/regression-test/data/query_p0/sql_functions/datetime_functions/test_add_sub_union_type.out b/regression-test/data/query_p0/sql_functions/datetime_functions/test_add_sub_union_type.out index 1236449bdfc43a..b3791ba116cd55 100644 --- a/regression-test/data/query_p0/sql_functions/datetime_functions/test_add_sub_union_type.out +++ b/regression-test/data/query_p0/sql_functions/datetime_functions/test_add_sub_union_type.out @@ -331,13 +331,13 @@ 2024-07-31T10:20:30.123456 -- !day_microsecond_add_11 -- -2024-08-31T11:20:30.123456 +2024-08-31 11:20:30.123456+08:00 -- !day_microsecond_add_12 -- -2024-09-30T19:20:30.123456 +2024-09-30 19:20:30.123456+08:00 -- !day_microsecond_add_13 -- -2024-11-01T00:50:30.123456 +2024-11-01 00:50:30.123456+08:00 -- !day_microsecond_sub_1 -- 2023-01-01T01:01:00.555566 @@ -352,13 +352,13 @@ 2017-02-27T13:39:29.876544 -- !day_microsecond_sub_5 -- -2017-03-30T14:39:29.876544 +2017-03-30 14:39:29.876544+08:00 -- !day_microsecond_sub_6 -- -2017-04-29T22:39:29.876544 +2017-04-29 22:39:29.876544+08:00 -- !day_microsecond_sub_7 -- -2017-05-31T04:09:29.876544 +2017-05-31 04:09:29.876544+08:00 -- !day_microsecond_extract_1 -- 02 03:04:05.123456 @@ -550,13 +550,13 @@ 2013-12-31T10:20:30.123456 -- !hour_microsecond_add_10 -- -2013-11-30T11:20:30.123456 +2013-11-30 11:20:30.123456+08:00 -- !hour_microsecond_add_11 -- -2013-10-31T19:20:30.123456 +2013-10-31 19:20:30.123456+08:00 -- !hour_microsecond_add_12 -- -2013-10-01T00:50:30.123456 +2013-10-01 00:50:30.123456+08:00 -- !hour_microsecond_sub_1 -- 2023-01-02T00:33:25 @@ -571,13 +571,13 @@ 2011-12-30T13:39:29.876544 -- !hour_microsecond_sub_5 -- -2011-11-29T14:39:29.876544 +2011-11-29 14:39:29.876544+08:00 -- !hour_microsecond_sub_6 -- -2011-10-30T22:39:29.876544 +2011-10-30 22:39:29.876544+08:00 -- !hour_microsecond_sub_7 -- -2011-09-30T04:09:29.876544 +2011-09-30 04:09:29.876544+08:00 -- !hour_microsecond_extract_1 -- 03:04:05.123456 @@ -699,13 +699,13 @@ 2007-12-30T00:10:20.123456 -- !minute_microsecond_add_11 -- -2007-11-30T01:10:20.123456 +2007-11-30 01:10:20.123456+08:00 -- !minute_microsecond_add_12 -- -2007-10-31T09:10:20.123456 +2007-10-31 09:10:20.123456+08:00 -- !minute_microsecond_add_13 -- -2007-09-30T14:40:20.123456 +2007-09-30 14:40:20.123456+08:00 -- !minute_microsecond_sub_1 -- 2023-01-02T02:18:15 @@ -720,13 +720,13 @@ 2005-12-30T23:49:39.876544 -- !minute_microsecond_sub_5 -- -2005-11-30T00:49:39.876544 +2005-11-30 00:49:39.876544+08:00 -- !minute_microsecond_sub_6 -- -2005-10-31T08:49:39.876544 +2005-10-31 08:49:39.876544+08:00 -- !minute_microsecond_sub_7 -- -2005-09-30T14:19:39.876544 +2005-09-30 14:19:39.876544+08:00 -- !minute_microsecond_extract_1 -- 04:05.123456 diff --git a/regression-test/suites/datatype_p0/timestamptz/test_timestamptz_microsecond_interval.groovy b/regression-test/suites/datatype_p0/timestamptz/test_timestamptz_microsecond_interval.groovy index c3647a57b10404..37ce80415394bf 100644 --- a/regression-test/suites/datatype_p0/timestamptz/test_timestamptz_microsecond_interval.groovy +++ b/regression-test/suites/datatype_p0/timestamptz/test_timestamptz_microsecond_interval.groovy @@ -21,7 +21,9 @@ suite("test_timestamptz_microsecond_interval") { sql """ create table test_timestamptz_microsecond_interval ( id int, - ts timestamptz(3) + ts0 timestamptz(0), + ts3 timestamptz(3), + ts6 timestamptz(6) ) duplicate key(id) distributed by hash(id) buckets 1 @@ -29,17 +31,65 @@ suite("test_timestamptz_microsecond_interval") { """ sql """ insert into test_timestamptz_microsecond_interval values - (1, '2024-01-02 03:04:05.123 +08:00') + (1, + '2024-01-02 03:04:05 +08:00', + '2024-01-02 03:04:05.123 +08:00', + '2024-01-02 03:04:05.123456 +08:00') """ - order_qt_timestamptz_microsecond_interval """ + ["ts0", "ts3", "ts6"].each { column -> + explain { + sql """ + select + date_add(${column}, interval '1 02:03:04.123456' day_microsecond) as day_add, + date_sub(${column}, interval '1 02:03:04.123456' day_microsecond) as day_sub, + date_add(${column}, interval '02:03:04.123456' hour_microsecond) as hour_add, + date_sub(${column}, interval '02:03:04.123456' hour_microsecond) as hour_sub, + date_add(${column}, interval '03:04.123456' minute_microsecond) as minute_add, + date_sub(${column}, interval '03:04.123456' minute_microsecond) as minute_sub + from test_timestamptz_microsecond_interval + """ + checkSlotTypeOf("day_add", "timestamptz(6)") + checkSlotTypeOf("day_sub", "timestamptz(6)") + checkSlotTypeOf("hour_add", "timestamptz(6)") + checkSlotTypeOf("hour_sub", "timestamptz(6)") + checkSlotTypeOf("minute_add", "timestamptz(6)") + checkSlotTypeOf("minute_sub", "timestamptz(6)") + } + } + + order_qt_timestamptz_microsecond_interval_scale_0 """ + select id, + date_add(ts0, interval '1 02:03:04.123456' day_microsecond), + date_sub(ts0, interval '1 02:03:04.123456' day_microsecond), + date_add(ts0, interval '02:03:04.123456' hour_microsecond), + date_sub(ts0, interval '02:03:04.123456' hour_microsecond), + date_add(ts0, interval '03:04.123456' minute_microsecond), + date_sub(ts0, interval '03:04.123456' minute_microsecond) + from test_timestamptz_microsecond_interval + order by id + """ + + order_qt_timestamptz_microsecond_interval_scale_3 """ + select id, + date_add(ts3, interval '1 02:03:04.123456' day_microsecond), + date_sub(ts3, interval '1 02:03:04.123456' day_microsecond), + date_add(ts3, interval '02:03:04.123456' hour_microsecond), + date_sub(ts3, interval '02:03:04.123456' hour_microsecond), + date_add(ts3, interval '03:04.123456' minute_microsecond), + date_sub(ts3, interval '03:04.123456' minute_microsecond) + from test_timestamptz_microsecond_interval + order by id + """ + + order_qt_timestamptz_microsecond_interval_scale_6 """ select id, - date_add(ts, interval '1 02:03:04.123456' day_microsecond), - date_sub(ts, interval '1 02:03:04.123456' day_microsecond), - date_add(ts, interval '02:03:04.123456' hour_microsecond), - date_sub(ts, interval '02:03:04.123456' hour_microsecond), - date_add(ts, interval '03:04.123456' minute_microsecond), - date_sub(ts, interval '03:04.123456' minute_microsecond) + date_add(ts6, interval '1 02:03:04.123456' day_microsecond), + date_sub(ts6, interval '1 02:03:04.123456' day_microsecond), + date_add(ts6, interval '02:03:04.123456' hour_microsecond), + date_sub(ts6, interval '02:03:04.123456' hour_microsecond), + date_add(ts6, interval '03:04.123456' minute_microsecond), + date_sub(ts6, interval '03:04.123456' minute_microsecond) from test_timestamptz_microsecond_interval order by id """ From 1a605ec9d081787a9612b3953cfdcd4862908d4c Mon Sep 17 00:00:00 2001 From: Mryange Date: Mon, 17 Aug 2026 20:57:01 +0800 Subject: [PATCH 3/3] [fix](fe) Cover remaining microsecond interval functions ### What problem does this PR solve? Issue Number: None Related PR: #66843 Problem Summary: The second-microsecond, microseconds, and milliseconds add/subtract functions still used concrete scale-6 candidate signatures. During overload selection, TIMESTAMPTZ inputs with scales below 6 could therefore match the DATETIMEV2 candidate before return-type computation. Use wildcard-scale candidates for the remaining functions, preserve the selected type family, and promote the argument and return type to scale 6. Extend the regression matrix so all twelve microsecond interval functions verify both return types and runtime values for TIMESTAMPTZ(0), TIMESTAMPTZ(3), and TIMESTAMPTZ(6). ### Release note Preserve TIMESTAMPTZ results for all microsecond interval arithmetic functions at every supported input scale. ### Check List (For Author) - Test: FE build and regression test - Regression test - Behavior changed: Yes, the remaining microsecond interval functions retain TIMESTAMPTZ and return scale 6 - Does this need documentation: No --- .../functions/scalar/MicroSecondsAdd.java | 6 +- .../functions/scalar/MicroSecondsSub.java | 8 +- .../functions/scalar/MilliSecondsAdd.java | 10 ++- .../functions/scalar/MilliSecondsSub.java | 8 +- .../scalar/SecondMicrosecondAdd.java | 8 +- .../scalar/SecondMicrosecondSub.java | 8 +- .../test_timestamptz_microsecond_interval.out | 6 +- ...st_timestamptz_microsecond_interval.groovy | 84 ++++++++----------- 8 files changed, 68 insertions(+), 70 deletions(-) diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MicroSecondsAdd.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MicroSecondsAdd.java index c83c2f8f5edc3b..4c5af813540aa2 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MicroSecondsAdd.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MicroSecondsAdd.java @@ -40,8 +40,10 @@ public class MicroSecondsAdd extends ScalarFunction implements BinaryExpression, PropagateNullable, DateAddSubMonotonic { private static final List SIGNATURES = ImmutableList.of( - FunctionSignature.ret(DateTimeV2Type.MAX).args(DateTimeV2Type.MAX, BigIntType.INSTANCE), - FunctionSignature.ret(TimeStampTzType.MAX).args(TimeStampTzType.MAX, BigIntType.INSTANCE) + FunctionSignature.ret(DateTimeV2Type.WILDCARD) + .args(DateTimeV2Type.WILDCARD, BigIntType.INSTANCE), + FunctionSignature.ret(TimeStampTzType.WILDCARD) + .args(TimeStampTzType.WILDCARD, BigIntType.INSTANCE) ); public MicroSecondsAdd(Expression arg0, Expression arg1) { diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MicroSecondsSub.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MicroSecondsSub.java index a407a945481918..2dd4a5f9fe3667 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MicroSecondsSub.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MicroSecondsSub.java @@ -39,9 +39,11 @@ public class MicroSecondsSub extends ScalarFunction implements BinaryExpression, ExplicitlyCastableSignature, PropagateNullable, DateAddSubMonotonic { - private static final List SIGNATURES = ImmutableList - .of(FunctionSignature.ret(DateTimeV2Type.MAX).args(DateTimeV2Type.MAX, BigIntType.INSTANCE), - FunctionSignature.ret(TimeStampTzType.MAX).args(TimeStampTzType.MAX, BigIntType.INSTANCE) + private static final List SIGNATURES = ImmutableList.of( + FunctionSignature.ret(DateTimeV2Type.WILDCARD) + .args(DateTimeV2Type.WILDCARD, BigIntType.INSTANCE), + FunctionSignature.ret(TimeStampTzType.WILDCARD) + .args(TimeStampTzType.WILDCARD, BigIntType.INSTANCE) ); public MicroSecondsSub(Expression arg0, Expression arg1) { diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MilliSecondsAdd.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MilliSecondsAdd.java index 4880e260eb2064..efeecce9f8fd7c 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MilliSecondsAdd.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MilliSecondsAdd.java @@ -39,10 +39,12 @@ public class MilliSecondsAdd extends ScalarFunction implements BinaryExpression, ExplicitlyCastableSignature, PropagateNullable, DateAddSubMonotonic { - private static final List SIGNATURES = ImmutableList - .of(FunctionSignature.ret(DateTimeV2Type.MAX).args(DateTimeV2Type.MAX, BigIntType.INSTANCE), - FunctionSignature.ret(TimeStampTzType.MAX).args(TimeStampTzType.MAX, BigIntType.INSTANCE) - ); + private static final List SIGNATURES = ImmutableList.of( + FunctionSignature.ret(DateTimeV2Type.WILDCARD) + .args(DateTimeV2Type.WILDCARD, BigIntType.INSTANCE), + FunctionSignature.ret(TimeStampTzType.WILDCARD) + .args(TimeStampTzType.WILDCARD, BigIntType.INSTANCE) + ); public MilliSecondsAdd(Expression arg0, Expression arg1) { super("milliseconds_add", arg0, arg1); diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MilliSecondsSub.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MilliSecondsSub.java index 2bf37e4b81fcc8..bd4532bd1c3e71 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MilliSecondsSub.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MilliSecondsSub.java @@ -39,9 +39,11 @@ public class MilliSecondsSub extends ScalarFunction implements BinaryExpression, ExplicitlyCastableSignature, PropagateNullable, DateAddSubMonotonic { - private static final List SIGNATURES = ImmutableList - .of(FunctionSignature.ret(DateTimeV2Type.MAX).args(DateTimeV2Type.MAX, BigIntType.INSTANCE), - FunctionSignature.ret(TimeStampTzType.MAX).args(TimeStampTzType.MAX, BigIntType.INSTANCE) + private static final List SIGNATURES = ImmutableList.of( + FunctionSignature.ret(DateTimeV2Type.WILDCARD) + .args(DateTimeV2Type.WILDCARD, BigIntType.INSTANCE), + FunctionSignature.ret(TimeStampTzType.WILDCARD) + .args(TimeStampTzType.WILDCARD, BigIntType.INSTANCE) ); public MilliSecondsSub(Expression arg0, Expression arg1) { diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/SecondMicrosecondAdd.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/SecondMicrosecondAdd.java index 8411699aedf2f9..dc19f6223c4cc1 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/SecondMicrosecondAdd.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/SecondMicrosecondAdd.java @@ -41,10 +41,10 @@ public class SecondMicrosecondAdd extends ScalarFunction implements BinaryExpression, ExplicitlyCastableSignature, ComputeSignatureForDateArithmetic, PropagateNullable, DateAddSubMonotonic { public static final List SIGNATURES = ImmutableList.of( - FunctionSignature.ret(DateTimeV2Type.MAX).args(DateTimeV2Type.MAX, - VarcharType.SYSTEM_DEFAULT), - FunctionSignature.ret(TimeStampTzType.MAX).args(TimeStampTzType.MAX, - VarcharType.SYSTEM_DEFAULT) + FunctionSignature.ret(DateTimeV2Type.WILDCARD) + .args(DateTimeV2Type.WILDCARD, VarcharType.SYSTEM_DEFAULT), + FunctionSignature.ret(TimeStampTzType.WILDCARD) + .args(TimeStampTzType.WILDCARD, VarcharType.SYSTEM_DEFAULT) ); public SecondMicrosecondAdd(Expression arg0, Expression arg1) { diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/SecondMicrosecondSub.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/SecondMicrosecondSub.java index af4350f28f26ba..5e1f0db06594c5 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/SecondMicrosecondSub.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/SecondMicrosecondSub.java @@ -41,10 +41,10 @@ public class SecondMicrosecondSub extends ScalarFunction implements BinaryExpression, ExplicitlyCastableSignature, ComputeSignatureForDateArithmetic, PropagateNullable, DateAddSubMonotonic { public static final List SIGNATURES = ImmutableList.of( - FunctionSignature.ret(DateTimeV2Type.MAX).args(DateTimeV2Type.MAX, - VarcharType.SYSTEM_DEFAULT), - FunctionSignature.ret(TimeStampTzType.MAX).args(TimeStampTzType.MAX, - VarcharType.SYSTEM_DEFAULT) + FunctionSignature.ret(DateTimeV2Type.WILDCARD) + .args(DateTimeV2Type.WILDCARD, VarcharType.SYSTEM_DEFAULT), + FunctionSignature.ret(TimeStampTzType.WILDCARD) + .args(TimeStampTzType.WILDCARD, VarcharType.SYSTEM_DEFAULT) ); public SecondMicrosecondSub(Expression arg0, Expression arg1) { diff --git a/regression-test/data/datatype_p0/timestamptz/test_timestamptz_microsecond_interval.out b/regression-test/data/datatype_p0/timestamptz/test_timestamptz_microsecond_interval.out index 51f6bcdd3b3df9..28133c32858f14 100644 --- a/regression-test/data/datatype_p0/timestamptz/test_timestamptz_microsecond_interval.out +++ b/regression-test/data/datatype_p0/timestamptz/test_timestamptz_microsecond_interval.out @@ -1,10 +1,10 @@ -- This file is automatically generated. You should know what you did if you want to edit this -- !timestamptz_microsecond_interval_scale_0 -- -1 2024-01-03 05:07:09.123456+08:00 2024-01-01 01:01:00.876544+08:00 2024-01-02 05:07:09.123456+08:00 2024-01-02 01:01:00.876544+08:00 2024-01-02 03:07:09.123456+08:00 2024-01-02 03:01:00.876544+08:00 +1 2024-01-03 05:07:09.123456+08:00 2024-01-01 01:01:00.876544+08:00 2024-01-02 05:07:09.123456+08:00 2024-01-02 01:01:00.876544+08:00 2024-01-02 03:07:09.123456+08:00 2024-01-02 03:01:00.876544+08:00 2024-01-02 03:04:09.123456+08:00 2024-01-02 03:04:00.876544+08:00 2024-01-02 03:04:05.123456+08:00 2024-01-02 03:04:04.876544+08:00 2024-01-02 03:04:05.123000+08:00 2024-01-02 03:04:04.877000+08:00 -- !timestamptz_microsecond_interval_scale_3 -- -1 2024-01-03 05:07:09.246456+08:00 2024-01-01 01:01:00.999544+08:00 2024-01-02 05:07:09.246456+08:00 2024-01-02 01:01:00.999544+08:00 2024-01-02 03:07:09.246456+08:00 2024-01-02 03:01:00.999544+08:00 +1 2024-01-03 05:07:09.246456+08:00 2024-01-01 01:01:00.999544+08:00 2024-01-02 05:07:09.246456+08:00 2024-01-02 01:01:00.999544+08:00 2024-01-02 03:07:09.246456+08:00 2024-01-02 03:01:00.999544+08:00 2024-01-02 03:04:09.246456+08:00 2024-01-02 03:04:00.999544+08:00 2024-01-02 03:04:05.246456+08:00 2024-01-02 03:04:04.999544+08:00 2024-01-02 03:04:05.246000+08:00 2024-01-02 03:04:05.000000+08:00 -- !timestamptz_microsecond_interval_scale_6 -- -1 2024-01-03 05:07:09.246912+08:00 2024-01-01 01:01:01.000000+08:00 2024-01-02 05:07:09.246912+08:00 2024-01-02 01:01:01.000000+08:00 2024-01-02 03:07:09.246912+08:00 2024-01-02 03:01:01.000000+08:00 +1 2024-01-03 05:07:09.246912+08:00 2024-01-01 01:01:01.000000+08:00 2024-01-02 05:07:09.246912+08:00 2024-01-02 01:01:01.000000+08:00 2024-01-02 03:07:09.246912+08:00 2024-01-02 03:01:01.000000+08:00 2024-01-02 03:04:09.246912+08:00 2024-01-02 03:04:01.000000+08:00 2024-01-02 03:04:05.246912+08:00 2024-01-02 03:04:05.000000+08:00 2024-01-02 03:04:05.246456+08:00 2024-01-02 03:04:05.000456+08:00 diff --git a/regression-test/suites/datatype_p0/timestamptz/test_timestamptz_microsecond_interval.groovy b/regression-test/suites/datatype_p0/timestamptz/test_timestamptz_microsecond_interval.groovy index 37ce80415394bf..da2e0cd401bfe6 100644 --- a/regression-test/suites/datatype_p0/timestamptz/test_timestamptz_microsecond_interval.groovy +++ b/regression-test/suites/datatype_p0/timestamptz/test_timestamptz_microsecond_interval.groovy @@ -37,60 +37,50 @@ suite("test_timestamptz_microsecond_interval") { '2024-01-02 03:04:05.123456 +08:00') """ + def microsecondExpressions = { String column -> + [ + day_add: "date_add(${column}, interval '1 02:03:04.123456' day_microsecond)", + day_sub: "date_sub(${column}, interval '1 02:03:04.123456' day_microsecond)", + hour_add: "date_add(${column}, interval '02:03:04.123456' hour_microsecond)", + hour_sub: "date_sub(${column}, interval '02:03:04.123456' hour_microsecond)", + minute_add: "date_add(${column}, interval '03:04.123456' minute_microsecond)", + minute_sub: "date_sub(${column}, interval '03:04.123456' minute_microsecond)", + second_add: "date_add(${column}, interval '04.123456' second_microsecond)", + second_sub: "date_sub(${column}, interval '04.123456' second_microsecond)", + microseconds_add: "microseconds_add(${column}, 123456)", + microseconds_sub: "microseconds_sub(${column}, 123456)", + milliseconds_add: "milliseconds_add(${column}, 123)", + milliseconds_sub: "milliseconds_sub(${column}, 123)" + ] + } + + def runtimeQuery = { String column -> + def expressions = microsecondExpressions(column) + """ + select id, + ${expressions.values().join(",\n ")} + from test_timestamptz_microsecond_interval + order by id + """ + } + ["ts0", "ts3", "ts6"].each { column -> + def expressions = microsecondExpressions(column) explain { sql """ select - date_add(${column}, interval '1 02:03:04.123456' day_microsecond) as day_add, - date_sub(${column}, interval '1 02:03:04.123456' day_microsecond) as day_sub, - date_add(${column}, interval '02:03:04.123456' hour_microsecond) as hour_add, - date_sub(${column}, interval '02:03:04.123456' hour_microsecond) as hour_sub, - date_add(${column}, interval '03:04.123456' minute_microsecond) as minute_add, - date_sub(${column}, interval '03:04.123456' minute_microsecond) as minute_sub + ${expressions.collect { alias, expression -> + "${expression} as ${alias}" + }.join(",\n ")} from test_timestamptz_microsecond_interval """ - checkSlotTypeOf("day_add", "timestamptz(6)") - checkSlotTypeOf("day_sub", "timestamptz(6)") - checkSlotTypeOf("hour_add", "timestamptz(6)") - checkSlotTypeOf("hour_sub", "timestamptz(6)") - checkSlotTypeOf("minute_add", "timestamptz(6)") - checkSlotTypeOf("minute_sub", "timestamptz(6)") + expressions.keySet().each { alias -> + checkSlotTypeOf(alias, "timestamptz(6)") + } } } - order_qt_timestamptz_microsecond_interval_scale_0 """ - select id, - date_add(ts0, interval '1 02:03:04.123456' day_microsecond), - date_sub(ts0, interval '1 02:03:04.123456' day_microsecond), - date_add(ts0, interval '02:03:04.123456' hour_microsecond), - date_sub(ts0, interval '02:03:04.123456' hour_microsecond), - date_add(ts0, interval '03:04.123456' minute_microsecond), - date_sub(ts0, interval '03:04.123456' minute_microsecond) - from test_timestamptz_microsecond_interval - order by id - """ - - order_qt_timestamptz_microsecond_interval_scale_3 """ - select id, - date_add(ts3, interval '1 02:03:04.123456' day_microsecond), - date_sub(ts3, interval '1 02:03:04.123456' day_microsecond), - date_add(ts3, interval '02:03:04.123456' hour_microsecond), - date_sub(ts3, interval '02:03:04.123456' hour_microsecond), - date_add(ts3, interval '03:04.123456' minute_microsecond), - date_sub(ts3, interval '03:04.123456' minute_microsecond) - from test_timestamptz_microsecond_interval - order by id - """ - - order_qt_timestamptz_microsecond_interval_scale_6 """ - select id, - date_add(ts6, interval '1 02:03:04.123456' day_microsecond), - date_sub(ts6, interval '1 02:03:04.123456' day_microsecond), - date_add(ts6, interval '02:03:04.123456' hour_microsecond), - date_sub(ts6, interval '02:03:04.123456' hour_microsecond), - date_add(ts6, interval '03:04.123456' minute_microsecond), - date_sub(ts6, interval '03:04.123456' minute_microsecond) - from test_timestamptz_microsecond_interval - order by id - """ + order_qt_timestamptz_microsecond_interval_scale_0 runtimeQuery("ts0") + order_qt_timestamptz_microsecond_interval_scale_3 runtimeQuery("ts3") + order_qt_timestamptz_microsecond_interval_scale_6 runtimeQuery("ts6") }