diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DateDiff.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DateDiff.java index 2d766295f649b4..cea905fade0826 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DateDiff.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DateDiff.java @@ -40,11 +40,11 @@ public class DateDiff extends ScalarFunction implements BinaryExpression, ExplicitlyCastableSignature, PropagateNullable { public static final List SIGNATURES = ImmutableList.of( - FunctionSignature.ret(IntegerType.INSTANCE) - .args(TimeStampTzType.WILDCARD, TimeStampTzType.WILDCARD), FunctionSignature.ret(IntegerType.INSTANCE) .args(DateTimeV2Type.WILDCARD, DateTimeV2Type.WILDCARD), - FunctionSignature.ret(IntegerType.INSTANCE).args(DateV2Type.INSTANCE, DateV2Type.INSTANCE)); + FunctionSignature.ret(IntegerType.INSTANCE).args(DateV2Type.INSTANCE, DateV2Type.INSTANCE), + FunctionSignature.ret(IntegerType.INSTANCE) + .args(TimeStampTzType.WILDCARD, TimeStampTzType.WILDCARD)); /** * constructor with 2 arguments. diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DaysDiff.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DaysDiff.java index 012ad7c6399c26..ae02922a63d36f 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DaysDiff.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DaysDiff.java @@ -42,9 +42,9 @@ public class DaysDiff extends ScalarFunction implements BinaryExpression, Explic PropagateNullable, DateDiffMonotonic { private static final List SIGNATURES = ImmutableList.of( - FunctionSignature.ret(BigIntType.INSTANCE).args(TimeStampTzType.WILDCARD, TimeStampTzType.WILDCARD), FunctionSignature.ret(BigIntType.INSTANCE).args(DateTimeV2Type.WILDCARD, DateTimeV2Type.WILDCARD), - FunctionSignature.ret(BigIntType.INSTANCE).args(DateV2Type.INSTANCE, DateV2Type.INSTANCE)); + FunctionSignature.ret(BigIntType.INSTANCE).args(DateV2Type.INSTANCE, DateV2Type.INSTANCE), + FunctionSignature.ret(BigIntType.INSTANCE).args(TimeStampTzType.WILDCARD, TimeStampTzType.WILDCARD)); /** * constructor with 2 arguments. diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/HoursDiff.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/HoursDiff.java index c601497c45de27..eb32eb29caedcd 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/HoursDiff.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/HoursDiff.java @@ -42,11 +42,11 @@ public class HoursDiff extends ScalarFunction implements BinaryExpression, Expli PropagateNullable, DateDiffMonotonic { public static final List SIGNATURES = ImmutableList.of( - FunctionSignature.ret(BigIntType.INSTANCE) - .args(TimeStampTzType.WILDCARD, TimeStampTzType.WILDCARD), FunctionSignature.ret(BigIntType.INSTANCE) .args(DateTimeV2Type.WILDCARD, DateTimeV2Type.WILDCARD), - FunctionSignature.ret(BigIntType.INSTANCE).args(DateV2Type.INSTANCE, DateV2Type.INSTANCE)); + FunctionSignature.ret(BigIntType.INSTANCE).args(DateV2Type.INSTANCE, DateV2Type.INSTANCE), + FunctionSignature.ret(BigIntType.INSTANCE) + .args(TimeStampTzType.WILDCARD, TimeStampTzType.WILDCARD)); /** * constructor with 2 arguments. diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MicroSecondsDiff.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MicroSecondsDiff.java index 26081a347a05e4..3cf8304f6e1914 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MicroSecondsDiff.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MicroSecondsDiff.java @@ -42,10 +42,9 @@ public class MicroSecondsDiff extends ScalarFunction implements BinaryExpression private static final List SIGNATURES = ImmutableList.of( FunctionSignature.ret(BigIntType.INSTANCE) - .args(TimeStampTzType.WILDCARD, TimeStampTzType.WILDCARD), + .args(DateTimeV2Type.WILDCARD, DateTimeV2Type.WILDCARD), FunctionSignature.ret(BigIntType.INSTANCE) - .args(DateTimeV2Type.WILDCARD, DateTimeV2Type.WILDCARD) - ); + .args(TimeStampTzType.WILDCARD, TimeStampTzType.WILDCARD)); /** * constructor with 2 arguments. diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MilliSecondsDiff.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MilliSecondsDiff.java index 9cda6cb8e4ad2e..6634cc9ec6203d 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MilliSecondsDiff.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MilliSecondsDiff.java @@ -42,10 +42,9 @@ public class MilliSecondsDiff extends ScalarFunction implements BinaryExpression private static final List SIGNATURES = ImmutableList.of( FunctionSignature.ret(BigIntType.INSTANCE) - .args(TimeStampTzType.WILDCARD, TimeStampTzType.WILDCARD), + .args(DateTimeV2Type.WILDCARD, DateTimeV2Type.WILDCARD), FunctionSignature.ret(BigIntType.INSTANCE) - .args(DateTimeV2Type.WILDCARD, DateTimeV2Type.WILDCARD) - ); + .args(TimeStampTzType.WILDCARD, TimeStampTzType.WILDCARD)); /** * constructor with 2 arguments. diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MinutesDiff.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MinutesDiff.java index f1a320932f09d4..972e59d269d1ca 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MinutesDiff.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MinutesDiff.java @@ -42,11 +42,11 @@ public class MinutesDiff extends ScalarFunction implements BinaryExpression, Exp PropagateNullable, DateDiffMonotonic { private static final List SIGNATURES = ImmutableList.of( - FunctionSignature.ret(BigIntType.INSTANCE) - .args(TimeStampTzType.WILDCARD, TimeStampTzType.WILDCARD), FunctionSignature.ret(BigIntType.INSTANCE) .args(DateTimeV2Type.WILDCARD, DateTimeV2Type.WILDCARD), - FunctionSignature.ret(BigIntType.INSTANCE).args(DateV2Type.INSTANCE, DateV2Type.INSTANCE)); + FunctionSignature.ret(BigIntType.INSTANCE).args(DateV2Type.INSTANCE, DateV2Type.INSTANCE), + FunctionSignature.ret(BigIntType.INSTANCE) + .args(TimeStampTzType.WILDCARD, TimeStampTzType.WILDCARD)); /** * constructor with 2 arguments. diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MonthsDiff.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MonthsDiff.java index 7c11156861b87f..31a8ae3aa09850 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MonthsDiff.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MonthsDiff.java @@ -42,11 +42,11 @@ public class MonthsDiff extends ScalarFunction implements BinaryExpression, Expl PropagateNullable, DateDiffMonotonic { private static final List SIGNATURES = ImmutableList.of( - FunctionSignature.ret(BigIntType.INSTANCE) - .args(TimeStampTzType.WILDCARD, TimeStampTzType.WILDCARD), FunctionSignature.ret(BigIntType.INSTANCE) .args(DateTimeV2Type.WILDCARD, DateTimeV2Type.WILDCARD), - FunctionSignature.ret(BigIntType.INSTANCE).args(DateV2Type.INSTANCE, DateV2Type.INSTANCE)); + FunctionSignature.ret(BigIntType.INSTANCE).args(DateV2Type.INSTANCE, DateV2Type.INSTANCE), + FunctionSignature.ret(BigIntType.INSTANCE) + .args(TimeStampTzType.WILDCARD, TimeStampTzType.WILDCARD)); /** * constructor with 2 arguments. diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/QuartersDiff.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/QuartersDiff.java index ec8f889baa5621..f450454b13815d 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/QuartersDiff.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/QuartersDiff.java @@ -42,12 +42,11 @@ public class QuartersDiff extends ScalarFunction implements BinaryExpression, Ex PropagateNullable, DateDiffMonotonic { private static final List SIGNATURES = ImmutableList.of( - FunctionSignature.ret(BigIntType.INSTANCE) - .args(TimeStampTzType.WILDCARD, TimeStampTzType.WILDCARD), FunctionSignature.ret(BigIntType.INSTANCE) .args(DateTimeV2Type.WILDCARD, DateTimeV2Type.WILDCARD), - FunctionSignature.ret(BigIntType.INSTANCE).args(DateV2Type.INSTANCE, DateV2Type.INSTANCE) - ); + FunctionSignature.ret(BigIntType.INSTANCE).args(DateV2Type.INSTANCE, DateV2Type.INSTANCE), + FunctionSignature.ret(BigIntType.INSTANCE) + .args(TimeStampTzType.WILDCARD, TimeStampTzType.WILDCARD)); /** * constructor with 2 arguments. diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/SecondsDiff.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/SecondsDiff.java index bb7df199d284ca..3eea019c39490a 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/SecondsDiff.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/SecondsDiff.java @@ -42,11 +42,11 @@ public class SecondsDiff extends ScalarFunction implements BinaryExpression, Exp PropagateNullable, DateDiffMonotonic { private static final List SIGNATURES = ImmutableList.of( - FunctionSignature.ret(BigIntType.INSTANCE) - .args(TimeStampTzType.WILDCARD, TimeStampTzType.WILDCARD), FunctionSignature.ret(BigIntType.INSTANCE) .args(DateTimeV2Type.WILDCARD, DateTimeV2Type.WILDCARD), - FunctionSignature.ret(BigIntType.INSTANCE).args(DateV2Type.INSTANCE, DateV2Type.INSTANCE)); + FunctionSignature.ret(BigIntType.INSTANCE).args(DateV2Type.INSTANCE, DateV2Type.INSTANCE), + FunctionSignature.ret(BigIntType.INSTANCE) + .args(TimeStampTzType.WILDCARD, TimeStampTzType.WILDCARD)); /** * constructor with 2 arguments. diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/TimeDiff.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/TimeDiff.java index a25ce2d45f84bb..020e1f6978ca7c 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/TimeDiff.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/TimeDiff.java @@ -40,11 +40,11 @@ public class TimeDiff extends ScalarFunction implements BinaryExpression, ExplicitlyCastableSignature, PropagateNullable { private static final List SIGNATURES = ImmutableList.of( - FunctionSignature.ret(TimeV2Type.WILDCARD) - .args(TimeStampTzType.WILDCARD, TimeStampTzType.WILDCARD), FunctionSignature.ret(TimeV2Type.WILDCARD) .args(DateTimeV2Type.WILDCARD, DateTimeV2Type.WILDCARD), - FunctionSignature.ret(TimeV2Type.SYSTEM_DEFAULT).args(DateV2Type.INSTANCE, DateV2Type.INSTANCE)); + FunctionSignature.ret(TimeV2Type.SYSTEM_DEFAULT).args(DateV2Type.INSTANCE, DateV2Type.INSTANCE), + FunctionSignature.ret(TimeV2Type.WILDCARD) + .args(TimeStampTzType.WILDCARD, TimeStampTzType.WILDCARD)); /** * constructor with 2 arguments. diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/WeeksDiff.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/WeeksDiff.java index 771d43d2cb3da5..1fb945344cfe07 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/WeeksDiff.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/WeeksDiff.java @@ -42,11 +42,11 @@ public class WeeksDiff extends ScalarFunction implements BinaryExpression, Expli PropagateNullable, DateDiffMonotonic { private static final List SIGNATURES = ImmutableList.of( - FunctionSignature.ret(BigIntType.INSTANCE) - .args(TimeStampTzType.WILDCARD, TimeStampTzType.WILDCARD), FunctionSignature.ret(BigIntType.INSTANCE) .args(DateTimeV2Type.WILDCARD, DateTimeV2Type.WILDCARD), - FunctionSignature.ret(BigIntType.INSTANCE).args(DateV2Type.INSTANCE, DateV2Type.INSTANCE)); + FunctionSignature.ret(BigIntType.INSTANCE).args(DateV2Type.INSTANCE, DateV2Type.INSTANCE), + FunctionSignature.ret(BigIntType.INSTANCE) + .args(TimeStampTzType.WILDCARD, TimeStampTzType.WILDCARD)); /** * constructor with 2 arguments. diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/YearsDiff.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/YearsDiff.java index da227338e0ad0c..634271efc0f767 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/YearsDiff.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/YearsDiff.java @@ -42,11 +42,11 @@ public class YearsDiff extends ScalarFunction implements BinaryExpression, Expli PropagateNullable, DateDiffMonotonic { private static final List SIGNATURES = ImmutableList.of( - FunctionSignature.ret(BigIntType.INSTANCE) - .args(TimeStampTzType.WILDCARD, TimeStampTzType.WILDCARD), FunctionSignature.ret(BigIntType.INSTANCE) .args(DateTimeV2Type.WILDCARD, DateTimeV2Type.WILDCARD), - FunctionSignature.ret(BigIntType.INSTANCE).args(DateV2Type.INSTANCE, DateV2Type.INSTANCE)); + FunctionSignature.ret(BigIntType.INSTANCE).args(DateV2Type.INSTANCE, DateV2Type.INSTANCE), + FunctionSignature.ret(BigIntType.INSTANCE) + .args(TimeStampTzType.WILDCARD, TimeStampTzType.WILDCARD)); /** * constructor with 2 arguments. diff --git a/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DiffFunctionSignatureTest.java b/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DiffFunctionSignatureTest.java new file mode 100644 index 00000000000000..1a213626eb2579 --- /dev/null +++ b/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DiffFunctionSignatureTest.java @@ -0,0 +1,101 @@ +// 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. + +package org.apache.doris.nereids.trees.expressions.functions.scalar; + +import org.apache.doris.catalog.FunctionSignature; +import org.apache.doris.nereids.trees.expressions.Expression; +import org.apache.doris.nereids.trees.expressions.SlotReference; +import org.apache.doris.nereids.trees.expressions.functions.ComputeSignature; +import org.apache.doris.nereids.types.DateTimeV2Type; +import org.apache.doris.nereids.types.TimeStampTzType; +import org.apache.doris.nereids.types.VarcharType; + +import com.google.common.collect.ImmutableList; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.util.List; +import java.util.function.BiFunction; + +/** + * Regression tests for apache/doris#66120. + * + *

All 12 Nereids {@code *_diff} scalar functions used to list their TIMESTAMPTZ signature + * FIRST in SIGNATURES. {@code SearchSignature}'s timezone-coercion tie-break only fires for + * inspectable literals ({@code ExpressionUtils.getLiteralAfterUnwrapNullable}), so a + * non-literal VARCHAR-typed argument (varchar column, subquery slot, UNION slot) ties across + * every candidate signature and the tie-break falls through to "keep the first-listed + * candidate" - which was always TIMESTAMPTZ. Casting a plain varchar through timestamptz(6) + * silently UTC-shifts the value whenever the session {@code time_zone} is not UTC. + * + *

The fix moves each file's TimeStampTz signature to LAST in SIGNATURES, so the tie + * resolves to DATETIMEV2 instead. Non-literal TIMESTAMPTZ-typed arguments must still bind to + * the TimeStampTzType signature - this class also guards against that regressing. + */ +public class DiffFunctionSignatureTest { + + private static final List DIFF_CONSTRUCTORS = ImmutableList.of( + new NamedDiffConstructor("DateDiff", DateDiff::new), + new NamedDiffConstructor("DaysDiff", DaysDiff::new), + new NamedDiffConstructor("HoursDiff", HoursDiff::new), + new NamedDiffConstructor("MicroSecondsDiff", MicroSecondsDiff::new), + new NamedDiffConstructor("MilliSecondsDiff", MilliSecondsDiff::new), + new NamedDiffConstructor("MinutesDiff", MinutesDiff::new), + new NamedDiffConstructor("MonthsDiff", MonthsDiff::new), + new NamedDiffConstructor("QuartersDiff", QuartersDiff::new), + new NamedDiffConstructor("SecondsDiff", SecondsDiff::new), + new NamedDiffConstructor("TimeDiff", TimeDiff::new), + new NamedDiffConstructor("WeeksDiff", WeeksDiff::new), + new NamedDiffConstructor("YearsDiff", YearsDiff::new)); + + @Test + public void testVarcharSlotsBindToDateTimeV2NotTimeStampTz() { + SlotReference left = SlotReference.of("a", VarcharType.SYSTEM_DEFAULT); + SlotReference right = SlotReference.of("b", VarcharType.SYSTEM_DEFAULT); + for (NamedDiffConstructor c : DIFF_CONSTRUCTORS) { + FunctionSignature signature = c.constructor.apply(left, right).getSignature(); + Assertions.assertInstanceOf(DateTimeV2Type.class, signature.getArgType(0), + c.name + ": varchar arg0 should bind to DateTimeV2Type, not TimeStampTzType (issue #66120)"); + Assertions.assertInstanceOf(DateTimeV2Type.class, signature.getArgType(1), + c.name + ": varchar arg1 should bind to DateTimeV2Type, not TimeStampTzType (issue #66120)"); + } + } + + @Test + public void testTimeStampTzSlotsStillBindToTimeStampTz() { + SlotReference left = SlotReference.of("a", TimeStampTzType.of(6)); + SlotReference right = SlotReference.of("b", TimeStampTzType.of(6)); + for (NamedDiffConstructor c : DIFF_CONSTRUCTORS) { + FunctionSignature signature = c.constructor.apply(left, right).getSignature(); + Assertions.assertInstanceOf(TimeStampTzType.class, signature.getArgType(0), + c.name + ": timestamptz arg0 should still bind to TimeStampTzType"); + Assertions.assertInstanceOf(TimeStampTzType.class, signature.getArgType(1), + c.name + ": timestamptz arg1 should still bind to TimeStampTzType"); + } + } + + private static final class NamedDiffConstructor { + private final String name; + private final BiFunction constructor; + + private NamedDiffConstructor(String name, BiFunction constructor) { + this.name = name; + this.constructor = constructor; + } + } +}