This is an automated email from the ASF dual-hosted git repository.
yiguolei pushed a commit to branch branch-4.1
in repository https://gitbox.apache.org/repos/asf/doris.git
The following commit(s) were added to refs/heads/branch-4.1 by this push:
new 89da1665cc2 branch-4.1: [Fix](ttz) Fix TIMESTAMPTZ elapsed-time
semantics to use UTC #63161 (#63248)
89da1665cc2 is described below
commit 89da1665cc2112ca44e29cef8236dacf0220ccae
Author: github-actions[bot]
<41898282+github-actions[bot]@users.noreply.github.com>
AuthorDate: Fri May 15 12:31:38 2026 +0800
branch-4.1: [Fix](ttz) Fix TIMESTAMPTZ elapsed-time semantics to use UTC
#63161 (#63248)
Cherry-picked from #63161
Co-authored-by: linrrarity <[email protected]>
---
be/src/core/value/timestamptz_value.h | 6 +
.../aggregate_function_sequence_match.cpp | 3 +
.../aggregate/aggregate_function_sequence_match.h | 7 +-
.../aggregate/aggregate_function_window_funnel.cpp | 7 +-
.../aggregate/aggregate_function_window_funnel.h | 34 ++--
.../aggregate_function_window_funnel_v2.cpp | 7 +-
.../aggregate_function_window_funnel_v2.h | 27 +--
.../function_date_or_datetime_computation.cpp | 6 +-
.../function_date_or_datetime_computation.h | 16 +-
.../expressions/functions/agg/SequenceCount.java | 3 +
.../functions/agg/SequenceFunction.java | 2 +-
.../expressions/functions/agg/SequenceMatch.java | 3 +
.../expressions/functions/agg/TopNWeighted.java | 8 +
.../expressions/functions/agg/WindowFunnel.java | 15 +-
.../expressions/functions/agg/WindowFunnelV2.java | 15 +-
.../expressions/functions/scalar/DateDiff.java | 3 +
.../expressions/functions/scalar/DaysDiff.java | 2 +
.../expressions/functions/scalar/HoursDiff.java | 3 +
.../functions/scalar/MicroSecondsDiff.java | 3 +
.../functions/scalar/MilliSecondsDiff.java | 3 +
.../expressions/functions/scalar/MinutesDiff.java | 3 +
.../expressions/functions/scalar/MonthsDiff.java | 7 +-
.../expressions/functions/scalar/QuartersDiff.java | 7 +-
.../expressions/functions/scalar/SecondsDiff.java | 3 +
.../expressions/functions/scalar/TimeDiff.java | 11 ++
.../expressions/functions/scalar/WeeksDiff.java | 7 +-
.../expressions/functions/scalar/YearsDiff.java | 7 +-
.../timestamptz/test_timestamptz_utc_functions.out | 33 ++++
.../test_timestamptz_utc_functions.groovy | 183 +++++++++++++++++++++
29 files changed, 378 insertions(+), 56 deletions(-)
diff --git a/be/src/core/value/timestamptz_value.h
b/be/src/core/value/timestamptz_value.h
index 1a0fa21f004..a3e3861ac2b 100644
--- a/be/src/core/value/timestamptz_value.h
+++ b/be/src/core/value/timestamptz_value.h
@@ -96,6 +96,10 @@ public:
return _utc_dt.datetime_diff_in_seconds(other._utc_dt);
}
+ int64_t datetime_diff_in_microseconds(const TimestampTzValue& other) const
{
+ return _utc_dt.datetime_diff_in_microseconds(other._utc_dt);
+ }
+
template <TimeUnit unit>
bool date_set_interval(const TimeInterval& interval) {
return _utc_dt.date_set_interval<unit>(interval);
@@ -143,6 +147,8 @@ public:
_utc_dt.unix_timestamp(timestamp, ctz);
}
+ std::string debug_string() const { return _utc_dt.debug_string(); }
+
// Convert UTC time to local time based on the given timezone
void convert_utc_to_local(const cctz::time_zone& local_time_zone,
DateV2Value<DateTimeV2ValueType>& dt) const;
diff --git a/be/src/exprs/aggregate/aggregate_function_sequence_match.cpp
b/be/src/exprs/aggregate/aggregate_function_sequence_match.cpp
index 2e2d9a6cc60..755dd6a2520 100644
--- a/be/src/exprs/aggregate/aggregate_function_sequence_match.cpp
+++ b/be/src/exprs/aggregate/aggregate_function_sequence_match.cpp
@@ -52,6 +52,9 @@ AggregateFunctionPtr
create_aggregate_function_sequence_base(const std::string&
case TYPE_DATEV2:
return creator_without_type::create<AggregateFunction<TYPE_DATEV2>>(
argument_types, result_is_nullable, attr);
+ case TYPE_TIMESTAMPTZ:
+ return
creator_without_type::create<AggregateFunction<TYPE_TIMESTAMPTZ>>(
+ argument_types, result_is_nullable, attr);
default:
return nullptr;
}
diff --git a/be/src/exprs/aggregate/aggregate_function_sequence_match.h
b/be/src/exprs/aggregate/aggregate_function_sequence_match.h
index d7084f57695..bb308159328 100644
--- a/be/src/exprs/aggregate/aggregate_function_sequence_match.h
+++ b/be/src/exprs/aggregate/aggregate_function_sequence_match.h
@@ -74,10 +74,6 @@ constexpr auto sequence_match_max_iterations = 1000000l;
template <PrimitiveType T, typename Derived>
struct AggregateFunctionSequenceMatchData final {
using Timestamp = typename PrimitiveTypeTraits<T>::CppType;
- using NativeType =
- std::conditional_t<T == TYPE_DATEV2, uint32_t,
- std::conditional_t<T == TYPE_DATETIMEV2,
uint64_t,
- typename
PrimitiveTypeTraits<T>::CppType>>;
using Events = std::bitset<MAX_EVENTS>;
using TimestampEvents = std::pair<Timestamp, Events>;
using Comparator = ComparePairFirst<std::less>;
@@ -280,7 +276,7 @@ private:
return;
}
- NativeType duration = 0;
+ uint64_t duration = 0;
if (!parse_uint(duration)) {
throw_exception("Could not parse number");
return;
@@ -618,7 +614,6 @@ class AggregateFunctionSequenceBase
: public
IAggregateFunctionDataHelper<AggregateFunctionSequenceMatchData<T, Derived>,
Derived> {
public:
- using NativeType = typename PrimitiveTypeTraits<T>::CppType;
AggregateFunctionSequenceBase(const DataTypes& arguments)
:
IAggregateFunctionDataHelper<AggregateFunctionSequenceMatchData<T, Derived>,
Derived>(
arguments) {
diff --git a/be/src/exprs/aggregate/aggregate_function_window_funnel.cpp
b/be/src/exprs/aggregate/aggregate_function_window_funnel.cpp
index fbd9fde900e..8249e3ee812 100644
--- a/be/src/exprs/aggregate/aggregate_function_window_funnel.cpp
+++ b/be/src/exprs/aggregate/aggregate_function_window_funnel.cpp
@@ -38,10 +38,13 @@ AggregateFunctionPtr
create_aggregate_function_window_funnel(const std::string&
return nullptr;
}
if (argument_types[2]->get_primitive_type() == TYPE_DATETIMEV2) {
- return creator_without_type::create<AggregateFunctionWindowFunnel>(
+ return
creator_without_type::create<AggregateFunctionWindowFunnel<TYPE_DATETIMEV2>>(
+ argument_types, result_is_nullable, attr);
+ } else if (argument_types[2]->get_primitive_type() == TYPE_TIMESTAMPTZ) {
+ return
creator_without_type::create<AggregateFunctionWindowFunnel<TYPE_TIMESTAMPTZ>>(
argument_types, result_is_nullable, attr);
} else {
- LOG(WARNING) << "Only support DateTime type as window argument!";
+ LOG(WARNING) << "Only support DateTime or TimeStampTz type as window
argument!";
return nullptr;
}
}
diff --git a/be/src/exprs/aggregate/aggregate_function_window_funnel.h
b/be/src/exprs/aggregate/aggregate_function_window_funnel.h
index 07e18fb4a64..778bc903ee9 100644
--- a/be/src/exprs/aggregate/aggregate_function_window_funnel.h
+++ b/be/src/exprs/aggregate/aggregate_function_window_funnel.h
@@ -70,9 +70,11 @@ inline WindowFunnelMode string_to_window_funnel_mode(const
String& string) {
}
}
+template <PrimitiveType T>
struct DataValue {
using TimestampEvent = std::vector<ColumnUInt8::Container>;
- std::vector<DateV2Value<DateTimeV2ValueType>> dt;
+ using DateValueType = typename PrimitiveTypeTraits<T>::CppType;
+ std::vector<DateValueType> dt;
TimestampEvent event_columns_data;
bool operator<(const DataValue& other) const { return dt < other.dt; }
void clear() {
@@ -97,15 +99,16 @@ struct DataValue {
}
};
+template <PrimitiveType T>
struct WindowFunnelState {
- static constexpr PrimitiveType PType = PrimitiveType::TYPE_DATETIMEV2;
- using NativeType = UInt64;
- using DateValueType = DateV2Value<DateTimeV2ValueType>;
+ static constexpr PrimitiveType PType = T;
+ using NativeType = typename PrimitiveTypeTraits<T>::StorageFieldType;
+ using DateValueType = typename PrimitiveTypeTraits<T>::CppType;
int event_count = 0;
int64_t window;
bool enable_mode;
WindowFunnelMode window_funnel_mode;
- DataValue events_list;
+ DataValue<T> events_list;
WindowFunnelState() {
event_count = 0;
@@ -123,7 +126,8 @@ struct WindowFunnelState {
window = win;
window_funnel_mode = enable_mode ? mode : WindowFunnelMode::DEFAULT;
events_list.dt.emplace_back(
- assert_cast<const
ColumnVector<PType>&>(*arg_columns[2]).get_data()[row_num]);
+ assert_cast<const typename
PrimitiveTypeTraits<PType>::ColumnType&>(*arg_columns[2])
+ .get_data()[row_num]);
for (int i = 0; i < event_count; i++) {
events_list.event_columns_data[i].emplace_back(
assert_cast<const ColumnUInt8&>(*arg_columns[3 +
i]).get_data()[row_num]);
@@ -268,7 +272,7 @@ struct WindowFunnelState {
}
}
- void merge(const WindowFunnelState& other) {
+ void merge(const WindowFunnelState<T>& other) {
if (other.events_list.empty()) {
return;
}
@@ -327,7 +331,9 @@ struct WindowFunnelState {
events_list.clear();
events_list.dt.resize(size);
for (auto i = 0; i < size; i++) {
- read_var_int(*reinterpret_cast<Int64*>(&events_list.dt[i]), in);
+ Int64 timestamp = 0;
+ read_var_int(timestamp, in);
+ events_list.dt[i] = DateValueType(static_cast<UInt64>(timestamp));
}
events_list.event_columns_data.resize(event_count);
for (int64_t i = 0; i < event_count; i++) {
@@ -342,17 +348,19 @@ struct WindowFunnelState {
}
};
+template <PrimitiveType T>
class AggregateFunctionWindowFunnel final
- : public IAggregateFunctionDataHelper<WindowFunnelState,
AggregateFunctionWindowFunnel>,
+ : public IAggregateFunctionDataHelper<WindowFunnelState<T>,
+
AggregateFunctionWindowFunnel<T>>,
MultiExpression,
NullableAggregateFunction {
public:
AggregateFunctionWindowFunnel(const DataTypes& argument_types_)
- : IAggregateFunctionDataHelper<WindowFunnelState,
AggregateFunctionWindowFunnel>(
+ : IAggregateFunctionDataHelper<WindowFunnelState<T>,
AggregateFunctionWindowFunnel<T>>(
argument_types_) {}
void create(AggregateDataPtr __restrict place) const override {
- auto data = new (place) WindowFunnelState(
+ auto data = new (place) WindowFunnelState<T>(
cast_set<int>(IAggregateFunction::get_argument_types().size()
- 3));
/// support window funnel mode from 2.0. See
`BeExecVersionManager::max_be_exec_version`
data->enable_mode = IAggregateFunction::version >= 3;
@@ -390,8 +398,8 @@ public:
// place is essentially an AggregateDataPtr, passed as a
ConstAggregateDataPtr.
this->data(const_cast<AggregateDataPtr>(place)).sort();
assert_cast<ColumnInt32&>(to).get_data().push_back(
- IAggregateFunctionDataHelper<WindowFunnelState,
-
AggregateFunctionWindowFunnel>::data(place)
+ IAggregateFunctionDataHelper<WindowFunnelState<T>,
+
AggregateFunctionWindowFunnel<T>>::data(place)
.get());
}
diff --git a/be/src/exprs/aggregate/aggregate_function_window_funnel_v2.cpp
b/be/src/exprs/aggregate/aggregate_function_window_funnel_v2.cpp
index 8cb73675c34..0445602a0b1 100644
--- a/be/src/exprs/aggregate/aggregate_function_window_funnel_v2.cpp
+++ b/be/src/exprs/aggregate/aggregate_function_window_funnel_v2.cpp
@@ -40,10 +40,13 @@ AggregateFunctionPtr
create_aggregate_function_window_funnel_v2(const std::strin
return nullptr;
}
if (argument_types[2]->get_primitive_type() == TYPE_DATETIMEV2) {
- return creator_without_type::create<AggregateFunctionWindowFunnelV2>(
+ return
creator_without_type::create<AggregateFunctionWindowFunnelV2<TYPE_DATETIMEV2>>(
+ argument_types, result_is_nullable, attr);
+ } else if (argument_types[2]->get_primitive_type() == TYPE_TIMESTAMPTZ) {
+ return
creator_without_type::create<AggregateFunctionWindowFunnelV2<TYPE_TIMESTAMPTZ>>(
argument_types, result_is_nullable, attr);
} else {
- LOG(WARNING) << "Only support DateTime type as window argument!";
+ LOG(WARNING) << "Only support DateTime or TimeStampTz type as window
argument!";
return nullptr;
}
}
diff --git a/be/src/exprs/aggregate/aggregate_function_window_funnel_v2.h
b/be/src/exprs/aggregate/aggregate_function_window_funnel_v2.h
index 8fb35addaf9..25557c039c9 100644
--- a/be/src/exprs/aggregate/aggregate_function_window_funnel_v2.h
+++ b/be/src/exprs/aggregate/aggregate_function_window_funnel_v2.h
@@ -77,6 +77,7 @@ void merge_events_list(T& events_list, size_t prefix_size,
bool prefix_sorted, b
/// The algorithm uses this to ensure each funnel step comes from a different
row.
///
/// This approach adds ZERO storage overhead — each event remains 9 bytes
(UInt64 + UInt8).
+template <PrimitiveType T>
struct WindowFunnelStateV2 {
/// (timestamp_int_val, 1-based event_index with continuation flag in bit
7)
///
@@ -136,10 +137,10 @@ struct WindowFunnelStateV2 {
window = win;
window_funnel_mode = mode;
- // get_data() returns DateV2Value<DateTimeV2ValueType>; convert to
packed UInt64
- auto timestamp = assert_cast<const
ColumnVector<TYPE_DATETIMEV2>&>(*arg_columns[2])
- .get_data()[row_num]
- .to_date_int_val();
+ auto timestamp =
+ assert_cast<const typename
PrimitiveTypeTraits<T>::ColumnType&>(*arg_columns[2])
+ .get_data()[row_num]
+ .to_date_int_val();
// Iterate from last event to first (reverse order).
// This ensures that after stable_sort, events with the same timestamp
@@ -174,7 +175,7 @@ struct WindowFunnelStateV2 {
}
}
- void merge(const WindowFunnelStateV2& other) {
+ void merge(const WindowFunnelStateV2<T>& other) {
if (other.events_list.empty()) {
return;
}
@@ -617,20 +618,22 @@ private:
}
};
+template <PrimitiveType T>
class AggregateFunctionWindowFunnelV2 final
- : public IAggregateFunctionDataHelper<WindowFunnelStateV2,
AggregateFunctionWindowFunnelV2>,
+ : public IAggregateFunctionDataHelper<WindowFunnelStateV2<T>,
+
AggregateFunctionWindowFunnelV2<T>>,
MultiExpression,
NullableAggregateFunction {
public:
AggregateFunctionWindowFunnelV2(const DataTypes& argument_types_)
- : IAggregateFunctionDataHelper<WindowFunnelStateV2,
AggregateFunctionWindowFunnelV2>(
- argument_types_) {
- WindowFunnelStateV2::validate_event_count(
+ : IAggregateFunctionDataHelper<WindowFunnelStateV2<T>,
+
AggregateFunctionWindowFunnelV2<T>>(argument_types_) {
+ WindowFunnelStateV2<T>::validate_event_count(
cast_set<int>(IAggregateFunction::get_argument_types().size()
- 3));
}
void create(AggregateDataPtr __restrict place) const override {
- new (place) WindowFunnelStateV2(
+ new (place) WindowFunnelStateV2<T>(
cast_set<int>(IAggregateFunction::get_argument_types().size()
- 3));
}
@@ -665,8 +668,8 @@ public:
void insert_result_into(ConstAggregateDataPtr __restrict place, IColumn&
to) const override {
this->data(const_cast<AggregateDataPtr>(place)).sort();
assert_cast<ColumnInt32&>(to).get_data().push_back(
- IAggregateFunctionDataHelper<WindowFunnelStateV2,
-
AggregateFunctionWindowFunnelV2>::data(place)
+ IAggregateFunctionDataHelper<WindowFunnelStateV2<T>,
+
AggregateFunctionWindowFunnelV2<T>>::data(place)
.get());
}
diff --git a/be/src/exprs/function/function_date_or_datetime_computation.cpp
b/be/src/exprs/function/function_date_or_datetime_computation.cpp
index 26cda7e4138..8973cab77e3 100644
--- a/be/src/exprs/function/function_date_or_datetime_computation.cpp
+++ b/be/src/exprs/function/function_date_or_datetime_computation.cpp
@@ -186,7 +186,8 @@ using FunctionSubTimeTimestampTz =
#define ALL_FUNCTION_TIME_DIFF(NAME, IMPL) \
FUNCTION_TIME_DIFF(NAME, IMPL, TYPE_DATETIMEV2) \
- FUNCTION_TIME_DIFF(NAME, IMPL, TYPE_DATEV2)
+ FUNCTION_TIME_DIFF(NAME, IMPL, TYPE_DATEV2) \
+ FUNCTION_TIME_DIFF(NAME, IMPL, TYPE_TIMESTAMPTZ)
// these diff functions accept all v2 types. but for v1 only datetime.
ALL_FUNCTION_TIME_DIFF(FunctionDatetimeDateDiff, DateDiffImpl)
ALL_FUNCTION_TIME_DIFF(FunctionDatetimeTimeDiff, TimeDiffImpl)
@@ -324,7 +325,8 @@ void
register_function_date_time_computation(SimpleFunctionFactory& factory) {
#define REGISTER_ALL_DATEV2_FUNCTIONS_DIFF(NAME) \
REGISTER_DATEV2_FUNCTIONS_DIFF(NAME, TYPE_DATETIMEV2) \
- REGISTER_DATEV2_FUNCTIONS_DIFF(NAME, TYPE_DATEV2)
+ REGISTER_DATEV2_FUNCTIONS_DIFF(NAME, TYPE_DATEV2) \
+ REGISTER_DATEV2_FUNCTIONS_DIFF(NAME, TYPE_TIMESTAMPTZ)
REGISTER_ALL_DATEV2_FUNCTIONS_DIFF(FunctionDatetimeDateDiff)
REGISTER_ALL_DATEV2_FUNCTIONS_DIFF(FunctionDatetimeTimeDiff)
diff --git a/be/src/exprs/function/function_date_or_datetime_computation.h
b/be/src/exprs/function/function_date_or_datetime_computation.h
index 90938d78d19..b5bc21bb00d 100644
--- a/be/src/exprs/function/function_date_or_datetime_computation.h
+++ b/be/src/exprs/function/function_date_or_datetime_computation.h
@@ -573,7 +573,8 @@ struct TimeDiffImpl {
using ValueType = typename PrimitiveTypeTraits<DateType>::CppType;
using ArgType = typename
PrimitiveTypeTraits<DateType>::DataType::FieldType;
//TODO: remove V1 since FE already removed it.
- static constexpr bool UsingTimev2 = is_date_v2_or_datetime_v2(DateType);
+ static constexpr bool UsingTimev2 =
+ is_date_v2_or_datetime_v2(DateType) || DateType ==
TYPE_TIMESTAMPTZ;
static constexpr PrimitiveType ReturnType = TYPE_TIMEV2;
static constexpr auto name = "timediff";
@@ -601,8 +602,19 @@ struct TimeDiffImpl {
return
std::make_shared<DataTypeTimeV2>(arguments[0].type->get_scale());
}
};
+
+template <TimeUnit UNIT, typename T0, typename T1>
+int64_t diff_on_utc_datetime(const T0& ts1, const T1& ts0) {
+ return datetime_diff<UNIT>(ts1, ts0);
+}
+
+template <TimeUnit UNIT>
+int64_t diff_on_utc_datetime(const TimestampTzValue& ts1, const
TimestampTzValue& ts0) {
+ return datetime_diff<UNIT>(ts1.utc_dt(), ts0.utc_dt());
+}
+
#define TIME_DIFF_FUNCTION_IMPL(CLASS, NAME, UNIT) \
- DECLARE_DATE_FUNCTIONS(CLASS, NAME, TYPE_BIGINT,
datetime_diff<TimeUnit::UNIT>(ts1, ts0))
+ DECLARE_DATE_FUNCTIONS(CLASS, NAME, TYPE_BIGINT,
diff_on_utc_datetime<TimeUnit::UNIT>(ts1, ts0))
// all these functions implemented by datediff
TIME_DIFF_FUNCTION_IMPL(YearsDiffImpl, years_diff, YEAR);
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/SequenceCount.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/SequenceCount.java
index 5cbc0903979..e4ad5956c1c 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/SequenceCount.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/SequenceCount.java
@@ -27,6 +27,7 @@ import org.apache.doris.nereids.types.BooleanType;
import org.apache.doris.nereids.types.DateTimeV2Type;
import org.apache.doris.nereids.types.DateV2Type;
import org.apache.doris.nereids.types.StringType;
+import org.apache.doris.nereids.types.TimeStampTzType;
import org.apache.doris.nereids.util.ExpressionUtils;
import com.google.common.base.Preconditions;
@@ -43,6 +44,8 @@ public class SequenceCount extends
NotNullableAggregateFunction
public static final List<FunctionSignature> SIGNATURES = ImmutableList.of(
FunctionSignature.ret(BigIntType.INSTANCE)
.varArgs(StringType.INSTANCE, DateV2Type.INSTANCE,
BooleanType.INSTANCE),
+ FunctionSignature.ret(BigIntType.INSTANCE)
+ .varArgs(StringType.INSTANCE, TimeStampTzType.WILDCARD,
BooleanType.INSTANCE),
FunctionSignature.ret(BigIntType.INSTANCE)
.varArgs(StringType.INSTANCE, DateTimeV2Type.WILDCARD,
BooleanType.INSTANCE)
);
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/SequenceFunction.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/SequenceFunction.java
index 673c91479a4..6bbf4e6e992 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/SequenceFunction.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/SequenceFunction.java
@@ -36,7 +36,7 @@ public interface SequenceFunction extends FunctionTrait {
}
if (!getArgumentType(1).isDateLikeType()) {
throw new AnalysisException("The timestamp params of " +
functionName
- + " function must be DATE or DATETIME, but it is " +
getArgumentType(1));
+ + " function must be DATE, DATETIME or TIMESTAMPTZ, but it
is " + getArgumentType(1));
}
String pattern = ((StringLikeLiteral) firstArg).getStringValue();
if (!FunctionCallExpr.parsePattern(pattern)) {
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/SequenceMatch.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/SequenceMatch.java
index c6cf9e436a4..c9f15731a19 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/SequenceMatch.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/SequenceMatch.java
@@ -25,6 +25,7 @@ import org.apache.doris.nereids.types.BooleanType;
import org.apache.doris.nereids.types.DateTimeV2Type;
import org.apache.doris.nereids.types.DateV2Type;
import org.apache.doris.nereids.types.StringType;
+import org.apache.doris.nereids.types.TimeStampTzType;
import org.apache.doris.nereids.util.ExpressionUtils;
import com.google.common.base.Preconditions;
@@ -41,6 +42,8 @@ public class SequenceMatch extends NullableAggregateFunction
public static final List<FunctionSignature> SIGNATURES = ImmutableList.of(
FunctionSignature.ret(BooleanType.INSTANCE)
.varArgs(StringType.INSTANCE, DateV2Type.INSTANCE,
BooleanType.INSTANCE),
+ FunctionSignature.ret(BooleanType.INSTANCE)
+ .varArgs(StringType.INSTANCE, TimeStampTzType.WILDCARD,
BooleanType.INSTANCE),
FunctionSignature.ret(BooleanType.INSTANCE)
.varArgs(StringType.INSTANCE, DateTimeV2Type.WILDCARD,
BooleanType.INSTANCE)
);
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/TopNWeighted.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/TopNWeighted.java
index 79db1318c62..1ed1586f99f 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/TopNWeighted.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/TopNWeighted.java
@@ -35,6 +35,7 @@ import org.apache.doris.nereids.types.IntegerType;
import org.apache.doris.nereids.types.LargeIntType;
import org.apache.doris.nereids.types.SmallIntType;
import org.apache.doris.nereids.types.StringType;
+import org.apache.doris.nereids.types.TimeStampTzType;
import org.apache.doris.nereids.types.TinyIntType;
import org.apache.doris.nereids.types.VarcharType;
@@ -71,6 +72,8 @@ public class TopNWeighted extends NullableAggregateFunction
.args(FloatType.INSTANCE,
BigIntType.INSTANCE, IntegerType.INSTANCE),
FunctionSignature.ret(ArrayType.of(DateV2Type.INSTANCE))
.args(DateV2Type.INSTANCE, BigIntType.INSTANCE,
IntegerType.INSTANCE),
+ FunctionSignature.ret(ArrayType.of(TimeStampTzType.WILDCARD))
+ .args(TimeStampTzType.WILDCARD, BigIntType.INSTANCE,
IntegerType.INSTANCE),
FunctionSignature.ret(ArrayType.of(DateTimeV2Type.WILDCARD))
.args(DateTimeV2Type.WILDCARD, BigIntType.INSTANCE,
IntegerType.INSTANCE),
FunctionSignature.ret(ArrayType.of(StringType.INSTANCE))
@@ -105,6 +108,11 @@ public class TopNWeighted extends NullableAggregateFunction
IntegerType.INSTANCE),
FunctionSignature.ret(ArrayType.of(DateV2Type.INSTANCE))
.args(DateV2Type.INSTANCE, BigIntType.INSTANCE,
IntegerType.INSTANCE, IntegerType.INSTANCE),
+ FunctionSignature.ret(ArrayType.of(TimeStampTzType.WILDCARD))
+ .args(TimeStampTzType.WILDCARD,
+ BigIntType.INSTANCE,
+ IntegerType.INSTANCE,
+ IntegerType.INSTANCE),
FunctionSignature.ret(VarcharType.SYSTEM_DEFAULT)
.args(DateTimeV2Type.WILDCARD,
BigIntType.INSTANCE,
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/WindowFunnel.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/WindowFunnel.java
index 848d3cfd6d5..ef60c0a8c07 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/WindowFunnel.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/WindowFunnel.java
@@ -24,14 +24,17 @@ import
org.apache.doris.nereids.trees.expressions.functions.ExplicitlyCastableSi
import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor;
import org.apache.doris.nereids.types.BigIntType;
import org.apache.doris.nereids.types.BooleanType;
+import org.apache.doris.nereids.types.DataType;
import org.apache.doris.nereids.types.DateTimeV2Type;
import org.apache.doris.nereids.types.DateV2Type;
import org.apache.doris.nereids.types.IntegerType;
import org.apache.doris.nereids.types.StringType;
+import org.apache.doris.nereids.types.TimeStampTzType;
import org.apache.doris.nereids.util.ExpressionUtils;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Lists;
import java.util.List;
@@ -42,6 +45,9 @@ public class WindowFunnel extends NullableAggregateFunction
implements ExplicitlyCastableSignature {
public static final List<FunctionSignature> SIGNATURES = ImmutableList.of(
+ FunctionSignature.ret(IntegerType.INSTANCE)
+ .varArgs(BigIntType.INSTANCE, StringType.INSTANCE,
TimeStampTzType.WILDCARD,
+ BooleanType.INSTANCE),
FunctionSignature.ret(IntegerType.INSTANCE)
.varArgs(BigIntType.INSTANCE, StringType.INSTANCE,
DateTimeV2Type.WILDCARD,
BooleanType.INSTANCE)
@@ -84,7 +90,8 @@ public class WindowFunnel extends NullableAggregateFunction
throw new AnalysisException("The mode params of " + functionName +
" function must be string");
}
if (!getArgumentType(2).isDateLikeType()) {
- throw new AnalysisException("The 3rd param of " + functionName + "
function must be DATE or DATETIME");
+ throw new AnalysisException("The 3rd param of " + functionName
+ + " function must be DATE, DATETIME or TIMESTAMPTZ");
}
for (int i = 3; i < arity(); i++) {
if (!getArgumentType(i).isBooleanType()) {
@@ -98,9 +105,9 @@ public class WindowFunnel extends NullableAggregateFunction
public FunctionSignature computeSignature(FunctionSignature signature) {
FunctionSignature functionSignature =
super.computeSignature(signature);
if (functionSignature.getArgType(2) instanceof DateV2Type) {
- return functionSignature.withArgumentTypes(getArguments(), (index,
originType, arg) ->
- (index == 2) ? DateTimeV2Type.SYSTEM_DEFAULT : originType
- );
+ List<DataType> newTypes =
Lists.newArrayList(functionSignature.argumentsTypes);
+ newTypes.set(2, DateTimeV2Type.SYSTEM_DEFAULT);
+ return
functionSignature.withArgumentTypes(functionSignature.hasVarArgs, newTypes);
}
return functionSignature;
}
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/WindowFunnelV2.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/WindowFunnelV2.java
index fa4f5d8e469..697774eb47f 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/WindowFunnelV2.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/WindowFunnelV2.java
@@ -24,14 +24,17 @@ import
org.apache.doris.nereids.trees.expressions.functions.ExplicitlyCastableSi
import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor;
import org.apache.doris.nereids.types.BigIntType;
import org.apache.doris.nereids.types.BooleanType;
+import org.apache.doris.nereids.types.DataType;
import org.apache.doris.nereids.types.DateTimeV2Type;
import org.apache.doris.nereids.types.DateV2Type;
import org.apache.doris.nereids.types.IntegerType;
import org.apache.doris.nereids.types.StringType;
+import org.apache.doris.nereids.types.TimeStampTzType;
import org.apache.doris.nereids.util.ExpressionUtils;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Lists;
import java.util.List;
@@ -45,6 +48,9 @@ public class WindowFunnelV2 extends NullableAggregateFunction
public static final int MAX_EVENT_CONDITIONS = 127;
public static final List<FunctionSignature> SIGNATURES = ImmutableList.of(
+ FunctionSignature.ret(IntegerType.INSTANCE)
+ .varArgs(BigIntType.INSTANCE, StringType.INSTANCE,
TimeStampTzType.WILDCARD,
+ BooleanType.INSTANCE),
FunctionSignature.ret(IntegerType.INSTANCE)
.varArgs(BigIntType.INSTANCE, StringType.INSTANCE,
DateTimeV2Type.WILDCARD,
BooleanType.INSTANCE)
@@ -93,7 +99,8 @@ public class WindowFunnelV2 extends NullableAggregateFunction
throw new AnalysisException("The mode params of " + functionName +
" function must be string");
}
if (!getArgumentType(2).isDateLikeType()) {
- throw new AnalysisException("The 3rd param of " + functionName + "
function must be DATE or DATETIME");
+ throw new AnalysisException("The 3rd param of " + functionName
+ + " function must be DATE, DATETIME or TIMESTAMPTZ");
}
for (int i = 3; i < arity(); i++) {
if (!getArgumentType(i).isBooleanType()) {
@@ -107,9 +114,9 @@ public class WindowFunnelV2 extends
NullableAggregateFunction
public FunctionSignature computeSignature(FunctionSignature signature) {
FunctionSignature functionSignature =
super.computeSignature(signature);
if (functionSignature.getArgType(2) instanceof DateV2Type) {
- return functionSignature.withArgumentTypes(getArguments(), (index,
originType, arg) ->
- (index == 2) ? DateTimeV2Type.SYSTEM_DEFAULT : originType
- );
+ List<DataType> newTypes =
Lists.newArrayList(functionSignature.argumentsTypes);
+ newTypes.set(2, DateTimeV2Type.SYSTEM_DEFAULT);
+ return
functionSignature.withArgumentTypes(functionSignature.hasVarArgs, newTypes);
}
return functionSignature;
}
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 16a2e1cf325..2d766295f64 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
@@ -26,6 +26,7 @@ import
org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor;
import org.apache.doris.nereids.types.DateTimeV2Type;
import org.apache.doris.nereids.types.DateV2Type;
import org.apache.doris.nereids.types.IntegerType;
+import org.apache.doris.nereids.types.TimeStampTzType;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
@@ -39,6 +40,8 @@ public class DateDiff extends ScalarFunction
implements BinaryExpression, ExplicitlyCastableSignature,
PropagateNullable {
public static final List<FunctionSignature> 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));
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 f894c9f09a6..012ad7c6399 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
@@ -28,6 +28,7 @@ import
org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor;
import org.apache.doris.nereids.types.BigIntType;
import org.apache.doris.nereids.types.DateTimeV2Type;
import org.apache.doris.nereids.types.DateV2Type;
+import org.apache.doris.nereids.types.TimeStampTzType;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
@@ -41,6 +42,7 @@ public class DaysDiff extends ScalarFunction implements
BinaryExpression, Explic
PropagateNullable, DateDiffMonotonic {
private static final List<FunctionSignature> 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));
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 b4d8f4ce181..c601497c45d 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
@@ -28,6 +28,7 @@ import
org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor;
import org.apache.doris.nereids.types.BigIntType;
import org.apache.doris.nereids.types.DateTimeV2Type;
import org.apache.doris.nereids.types.DateV2Type;
+import org.apache.doris.nereids.types.TimeStampTzType;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
@@ -41,6 +42,8 @@ public class HoursDiff extends ScalarFunction implements
BinaryExpression, Expli
PropagateNullable, DateDiffMonotonic {
public static final List<FunctionSignature> 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));
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 434043119a0..26081a347a0 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
@@ -27,6 +27,7 @@ import
org.apache.doris.nereids.trees.expressions.shape.BinaryExpression;
import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor;
import org.apache.doris.nereids.types.BigIntType;
import org.apache.doris.nereids.types.DateTimeV2Type;
+import org.apache.doris.nereids.types.TimeStampTzType;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
@@ -40,6 +41,8 @@ public class MicroSecondsDiff extends ScalarFunction
implements BinaryExpression
PropagateNullable, DateDiffMonotonic {
private static final List<FunctionSignature> SIGNATURES = ImmutableList.of(
+ FunctionSignature.ret(BigIntType.INSTANCE)
+ .args(TimeStampTzType.WILDCARD, TimeStampTzType.WILDCARD),
FunctionSignature.ret(BigIntType.INSTANCE)
.args(DateTimeV2Type.WILDCARD, DateTimeV2Type.WILDCARD)
);
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 3f07927f920..9cda6cb8e4a 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
@@ -27,6 +27,7 @@ import
org.apache.doris.nereids.trees.expressions.shape.BinaryExpression;
import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor;
import org.apache.doris.nereids.types.BigIntType;
import org.apache.doris.nereids.types.DateTimeV2Type;
+import org.apache.doris.nereids.types.TimeStampTzType;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
@@ -40,6 +41,8 @@ public class MilliSecondsDiff extends ScalarFunction
implements BinaryExpression
PropagateNullable, DateDiffMonotonic {
private static final List<FunctionSignature> SIGNATURES = ImmutableList.of(
+ FunctionSignature.ret(BigIntType.INSTANCE)
+ .args(TimeStampTzType.WILDCARD, TimeStampTzType.WILDCARD),
FunctionSignature.ret(BigIntType.INSTANCE)
.args(DateTimeV2Type.WILDCARD, DateTimeV2Type.WILDCARD)
);
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 a66b5beb53f..f1a320932f0 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
@@ -28,6 +28,7 @@ import
org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor;
import org.apache.doris.nereids.types.BigIntType;
import org.apache.doris.nereids.types.DateTimeV2Type;
import org.apache.doris.nereids.types.DateV2Type;
+import org.apache.doris.nereids.types.TimeStampTzType;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
@@ -41,6 +42,8 @@ public class MinutesDiff extends ScalarFunction implements
BinaryExpression, Exp
PropagateNullable, DateDiffMonotonic {
private static final List<FunctionSignature> 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));
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 32735b3931e..7c11156861b 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
@@ -28,6 +28,7 @@ import
org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor;
import org.apache.doris.nereids.types.BigIntType;
import org.apache.doris.nereids.types.DateTimeV2Type;
import org.apache.doris.nereids.types.DateV2Type;
+import org.apache.doris.nereids.types.TimeStampTzType;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
@@ -41,9 +42,11 @@ public class MonthsDiff extends ScalarFunction implements
BinaryExpression, Expl
PropagateNullable, DateDiffMonotonic {
private static final List<FunctionSignature> SIGNATURES = ImmutableList.of(
-
FunctionSignature.ret(BigIntType.INSTANCE).args(DateV2Type.INSTANCE,
DateV2Type.INSTANCE),
FunctionSignature.ret(BigIntType.INSTANCE)
- .args(DateTimeV2Type.WILDCARD, DateTimeV2Type.WILDCARD));
+ .args(TimeStampTzType.WILDCARD, TimeStampTzType.WILDCARD),
+ FunctionSignature.ret(BigIntType.INSTANCE)
+ .args(DateTimeV2Type.WILDCARD, DateTimeV2Type.WILDCARD),
+
FunctionSignature.ret(BigIntType.INSTANCE).args(DateV2Type.INSTANCE,
DateV2Type.INSTANCE));
/**
* 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 d13b49db683..ec8f889baa5 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
@@ -28,6 +28,7 @@ import
org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor;
import org.apache.doris.nereids.types.BigIntType;
import org.apache.doris.nereids.types.DateTimeV2Type;
import org.apache.doris.nereids.types.DateV2Type;
+import org.apache.doris.nereids.types.TimeStampTzType;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
@@ -41,9 +42,11 @@ public class QuartersDiff extends ScalarFunction implements
BinaryExpression, Ex
PropagateNullable, DateDiffMonotonic {
private static final List<FunctionSignature> SIGNATURES = ImmutableList.of(
-
FunctionSignature.ret(BigIntType.INSTANCE).args(DateV2Type.INSTANCE,
DateV2Type.INSTANCE),
FunctionSignature.ret(BigIntType.INSTANCE)
- .args(DateTimeV2Type.WILDCARD, DateTimeV2Type.WILDCARD)
+ .args(TimeStampTzType.WILDCARD, TimeStampTzType.WILDCARD),
+ FunctionSignature.ret(BigIntType.INSTANCE)
+ .args(DateTimeV2Type.WILDCARD, DateTimeV2Type.WILDCARD),
+
FunctionSignature.ret(BigIntType.INSTANCE).args(DateV2Type.INSTANCE,
DateV2Type.INSTANCE)
);
/**
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 aab4fb18054..bb7df199d28 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
@@ -28,6 +28,7 @@ import
org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor;
import org.apache.doris.nereids.types.BigIntType;
import org.apache.doris.nereids.types.DateTimeV2Type;
import org.apache.doris.nereids.types.DateV2Type;
+import org.apache.doris.nereids.types.TimeStampTzType;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
@@ -41,6 +42,8 @@ public class SecondsDiff extends ScalarFunction implements
BinaryExpression, Exp
PropagateNullable, DateDiffMonotonic {
private static final List<FunctionSignature> 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));
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 7602743ec5c..a25ce2d45f8 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
@@ -25,6 +25,7 @@ import
org.apache.doris.nereids.trees.expressions.shape.BinaryExpression;
import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor;
import org.apache.doris.nereids.types.DateTimeV2Type;
import org.apache.doris.nereids.types.DateV2Type;
+import org.apache.doris.nereids.types.TimeStampTzType;
import org.apache.doris.nereids.types.TimeV2Type;
import com.google.common.base.Preconditions;
@@ -39,6 +40,8 @@ public class TimeDiff extends ScalarFunction
implements BinaryExpression, ExplicitlyCastableSignature,
PropagateNullable {
private static final List<FunctionSignature> 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));
@@ -83,11 +86,19 @@ public class TimeDiff extends ScalarFunction
DateTimeV2Type left = (DateTimeV2Type)
getArgument(0).getDataType();
scale = Math.max(scale, left.getScale());
useTimev2 = true;
+ } else if (getArgument(0).getDataType() instanceof TimeStampTzType) {
+ TimeStampTzType left = (TimeStampTzType)
getArgument(0).getDataType();
+ scale = Math.max(scale, left.getScale());
+ useTimev2 = true;
}
if (getArgument(1).getDataType() instanceof DateTimeV2Type) {
DateTimeV2Type right = (DateTimeV2Type)
getArgument(1).getDataType();
scale = Math.max(scale, right.getScale());
useTimev2 = true;
+ } else if (getArgument(1).getDataType() instanceof TimeStampTzType) {
+ TimeStampTzType right = (TimeStampTzType)
getArgument(1).getDataType();
+ scale = Math.max(scale, right.getScale());
+ useTimev2 = true;
}
if (useTimev2) {
signature = signature.withReturnType(TimeV2Type.of(scale));
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 cc884d44911..771d43d2cb3 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
@@ -28,6 +28,7 @@ import
org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor;
import org.apache.doris.nereids.types.BigIntType;
import org.apache.doris.nereids.types.DateTimeV2Type;
import org.apache.doris.nereids.types.DateV2Type;
+import org.apache.doris.nereids.types.TimeStampTzType;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
@@ -41,9 +42,11 @@ public class WeeksDiff extends ScalarFunction implements
BinaryExpression, Expli
PropagateNullable, DateDiffMonotonic {
private static final List<FunctionSignature> SIGNATURES = ImmutableList.of(
-
FunctionSignature.ret(BigIntType.INSTANCE).args(DateV2Type.INSTANCE,
DateV2Type.INSTANCE),
FunctionSignature.ret(BigIntType.INSTANCE)
- .args(DateTimeV2Type.WILDCARD, DateTimeV2Type.WILDCARD));
+ .args(TimeStampTzType.WILDCARD, TimeStampTzType.WILDCARD),
+ FunctionSignature.ret(BigIntType.INSTANCE)
+ .args(DateTimeV2Type.WILDCARD, DateTimeV2Type.WILDCARD),
+
FunctionSignature.ret(BigIntType.INSTANCE).args(DateV2Type.INSTANCE,
DateV2Type.INSTANCE));
/**
* 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 060daf4fc57..da227338e0a 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
@@ -28,6 +28,7 @@ import
org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor;
import org.apache.doris.nereids.types.BigIntType;
import org.apache.doris.nereids.types.DateTimeV2Type;
import org.apache.doris.nereids.types.DateV2Type;
+import org.apache.doris.nereids.types.TimeStampTzType;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
@@ -41,9 +42,11 @@ public class YearsDiff extends ScalarFunction implements
BinaryExpression, Expli
PropagateNullable, DateDiffMonotonic {
private static final List<FunctionSignature> SIGNATURES = ImmutableList.of(
-
FunctionSignature.ret(BigIntType.INSTANCE).args(DateV2Type.INSTANCE,
DateV2Type.INSTANCE),
FunctionSignature.ret(BigIntType.INSTANCE)
- .args(DateTimeV2Type.WILDCARD, DateTimeV2Type.WILDCARD));
+ .args(TimeStampTzType.WILDCARD, TimeStampTzType.WILDCARD),
+ FunctionSignature.ret(BigIntType.INSTANCE)
+ .args(DateTimeV2Type.WILDCARD, DateTimeV2Type.WILDCARD),
+
FunctionSignature.ret(BigIntType.INSTANCE).args(DateV2Type.INSTANCE,
DateV2Type.INSTANCE));
/**
* constructor with 2 arguments.
diff --git
a/regression-test/data/datatype_p0/timestamptz/test_timestamptz_utc_functions.out
b/regression-test/data/datatype_p0/timestamptz/test_timestamptz_utc_functions.out
new file mode 100644
index 00000000000..12744160ea0
--- /dev/null
+++
b/regression-test/data/datatype_p0/timestamptz/test_timestamptz_utc_functions.out
@@ -0,0 +1,33 @@
+-- This file is automatically generated. You should know what you did if you
want to edit this
+-- !timestamptz_diff_utc --
+600000 600000000 600 10 0 0 0 0 0
0 0 00:10:00.000000
+
+-- !timestamptz_diff_ny --
+600000 600000000 600 10 0 0 0 0 0
0 0 00:10:00.000000
+
+-- !timestamptz_diff_spring_forward_ny --
+600000 600 10 0 00:10:00.000000
+
+-- !timestamptz_diff_mixed_scale_ny --
+600123 600123000 600 00:10:00.123
+
+-- !timestamptz_agg_utc --
+true 1 2 2
+
+-- !timestamptz_agg_ny --
+true 1 2 2
+
+-- !timestamptz_agg_by_group_ny --
+1 true 1 2 2
+3 true 1 2 2
+
+-- !timestamptz_column_diff_ny --
+600000 600 00:10:00.000000
+
+-- !timestamptz_topn_weighted --
+1 2024-11-03 06:30:00.000000+00:00 2024-11-03 06:30:00.000000+00:00
+3 2024-03-10 07:30:00.000000+00:00 2024-03-10 07:30:00.000000+00:00
+
+-- !timestamptz_null --
+\N 0
+
diff --git
a/regression-test/suites/datatype_p0/timestamptz/test_timestamptz_utc_functions.groovy
b/regression-test/suites/datatype_p0/timestamptz/test_timestamptz_utc_functions.groovy
new file mode 100644
index 00000000000..69c15e4d197
--- /dev/null
+++
b/regression-test/suites/datatype_p0/timestamptz/test_timestamptz_utc_functions.groovy
@@ -0,0 +1,183 @@
+// 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_utc_functions") {
+ sql "SET enable_nereids_planner = true;"
+ sql "SET enable_fallback_to_original_planner = false;"
+
+ // Fall-back DST fold:
+ // lhs UTC=2024-11-03 06:05:00, NY local=2024-11-03 01:05:00;
+ // rhs UTC=2024-11-03 05:55:00, NY local=2024-11-03 01:55:00.
+ // Expected: TIMESTAMPTZ functions use UTC instants, so lhs - rhs = +10
minutes, not local -50 minutes.
+ def lhs = "CAST('2024-11-03 01:05:00 -05:00' AS TIMESTAMPTZ(6))"
+ def rhs = "CAST('2024-11-03 01:55:00 -04:00' AS TIMESTAMPTZ(6))"
+
+ // Spring-forward DST gap:
+ // lhs UTC=2024-03-10 07:05:00, NY local=2024-03-10 03:05:00;
+ // rhs UTC=2024-03-10 06:55:00, NY local=2024-03-10 01:55:00.
+ // Expected: TIMESTAMPTZ functions use UTC instants, so lhs - rhs = +10
minutes, not local +70 minutes.
+ def springLhs = "CAST('2024-03-10 03:05:00 -04:00' AS TIMESTAMPTZ(6))"
+ def springRhs = "CAST('2024-03-10 01:55:00 -05:00' AS TIMESTAMPTZ(6))"
+
+ // Mixed scale: lhs UTC=2024-11-03 06:05:00.123, rhs UTC=2024-11-03
05:55:00.
+ // Expected: lhs - rhs = +600123 ms, and non-default TIMESTAMPTZ scales
bind directly.
+ def scale3Lhs = "CAST('2024-11-03 01:05:00.123 -05:00' AS TIMESTAMPTZ(3))"
+ def scale0Rhs = "CAST('2024-11-03 01:55:00 -04:00' AS TIMESTAMPTZ(0))"
+
+ // Scalar diff results should be identical in UTC and America/New_York
sessions.
+ sql "SET time_zone = '+00:00';"
+ qt_timestamptz_diff_utc """
+ SELECT milliseconds_diff(${lhs}, ${rhs}) AS ms_diff,
+ microseconds_diff(${lhs}, ${rhs}) AS us_diff,
+ seconds_diff(${lhs}, ${rhs}) AS sec_diff,
+ minutes_diff(${lhs}, ${rhs}) AS min_diff,
+ hours_diff(${lhs}, ${rhs}) AS hour_diff,
+ days_diff(${lhs}, ${rhs}) AS day_diff,
+ weeks_diff(${lhs}, ${rhs}) AS week_diff,
+ months_diff(${lhs}, ${rhs}) AS month_diff,
+ quarters_diff(${lhs}, ${rhs}) AS quarter_diff,
+ years_diff(${lhs}, ${rhs}) AS year_diff,
+ datediff(${lhs}, ${rhs}) AS date_diff,
+ timediff(${lhs}, ${rhs}) AS time_diff;
+ """
+
+ sql "SET time_zone = 'America/New_York';"
+ qt_timestamptz_diff_ny """
+ SELECT milliseconds_diff(${lhs}, ${rhs}) AS ms_diff,
+ microseconds_diff(${lhs}, ${rhs}) AS us_diff,
+ seconds_diff(${lhs}, ${rhs}) AS sec_diff,
+ minutes_diff(${lhs}, ${rhs}) AS min_diff,
+ hours_diff(${lhs}, ${rhs}) AS hour_diff,
+ days_diff(${lhs}, ${rhs}) AS day_diff,
+ weeks_diff(${lhs}, ${rhs}) AS week_diff,
+ months_diff(${lhs}, ${rhs}) AS month_diff,
+ quarters_diff(${lhs}, ${rhs}) AS quarter_diff,
+ years_diff(${lhs}, ${rhs}) AS year_diff,
+ datediff(${lhs}, ${rhs}) AS date_diff,
+ timediff(${lhs}, ${rhs}) AS time_diff;
+ """
+
+ qt_timestamptz_diff_spring_forward_ny """
+ SELECT milliseconds_diff(${springLhs}, ${springRhs}) AS ms_diff,
+ seconds_diff(${springLhs}, ${springRhs}) AS sec_diff,
+ minutes_diff(${springLhs}, ${springRhs}) AS min_diff,
+ hours_diff(${springLhs}, ${springRhs}) AS hour_diff,
+ timediff(${springLhs}, ${springRhs}) AS time_diff;
+ """
+
+ qt_timestamptz_diff_mixed_scale_ny """
+ SELECT milliseconds_diff(${scale3Lhs}, ${scale0Rhs}) AS ms_diff,
+ microseconds_diff(${scale3Lhs}, ${scale0Rhs}) AS us_diff,
+ seconds_diff(${scale3Lhs}, ${scale0Rhs}) AS sec_diff,
+ timediff(${scale3Lhs}, ${scale0Rhs}) AS time_diff;
+ """
+
+ testFoldConst("""
+ SELECT milliseconds_diff(${lhs}, ${rhs}),
+ seconds_diff(${lhs}, ${rhs}),
+ timediff(${lhs}, ${rhs});
+ """)
+
+ sql "DROP TABLE IF EXISTS tz_utc_function_events;"
+ sql """
+ CREATE TABLE tz_utc_function_events (
+ id INT,
+ grp INT,
+ weight BIGINT,
+ ts TIMESTAMPTZ(6),
+ e1 BOOLEAN,
+ e2 BOOLEAN
+ )
+ DUPLICATE KEY(id)
+ DISTRIBUTED BY HASH(id) BUCKETS 1
+ PROPERTIES('replication_num' = '1');
+ """
+ sql """
+ INSERT INTO tz_utc_function_events VALUES
+ (1, 1, 10, CAST('2024-11-03 01:55:00 -04:00' AS TIMESTAMPTZ(6)), true,
false),
+ (2, 1, 20, CAST('2024-11-03 01:05:00 -05:00' AS TIMESTAMPTZ(6)),
false, true),
+ (3, 1, 30, CAST('2024-11-03 01:30:00 -05:00' AS TIMESTAMPTZ(6)),
false, false),
+ (4, 2, 40, NULL, true, false),
+ (5, 3, 50, CAST('2024-03-10 01:55:00 -05:00' AS TIMESTAMPTZ(6)), true,
false),
+ (6, 3, 60, CAST('2024-03-10 03:05:00 -04:00' AS TIMESTAMPTZ(6)),
false, true),
+ (7, 3, 70, CAST('2024-03-10 03:30:00 -04:00' AS TIMESTAMPTZ(6)),
false, false);
+ """
+
+ // Aggregates should also compare TIMESTAMPTZ values by UTC instant.
+ sql "SET time_zone = '+00:00';"
+ qt_timestamptz_agg_utc """
+ SELECT sequence_match('(?1)(?t<=600)(?2)', ts, e1, e2) AS seq_match,
+ sequence_count('(?1)(?t<=600)(?2)', ts, e1, e2) AS seq_count,
+ window_funnel(600, 'default', ts, e1, e2) AS funnel_v1,
+ window_funnel_v2(600, 'default', ts, e1, e2) AS funnel_v2
+ FROM tz_utc_function_events
+ WHERE grp = 1;
+ """
+
+ sql "SET time_zone = 'America/New_York';"
+ qt_timestamptz_agg_ny """
+ SELECT sequence_match('(?1)(?t<=600)(?2)', ts, e1, e2) AS seq_match,
+ sequence_count('(?1)(?t<=600)(?2)', ts, e1, e2) AS seq_count,
+ window_funnel(600, 'default', ts, e1, e2) AS funnel_v1,
+ window_funnel_v2(600, 'default', ts, e1, e2) AS funnel_v2
+ FROM tz_utc_function_events
+ WHERE grp = 1;
+ """
+
+ // Grouped aggregation verifies both DST shapes.
+ order_qt_timestamptz_agg_by_group_ny """
+ SELECT grp,
+ sequence_match('(?1)(?t<=600)(?2)', ts, e1, e2) AS seq_match,
+ sequence_count('(?1)(?t<=600)(?2)', ts, e1, e2) AS seq_count,
+ window_funnel(600, 'default', ts, e1, e2) AS funnel_v1,
+ window_funnel_v2(600, 'default', ts, e1, e2) AS funnel_v2
+ FROM tz_utc_function_events
+ WHERE grp IN (1, 3)
+ GROUP BY grp
+ ORDER BY grp;
+ """
+
+ // Column inputs should also use UTC instant semantics.
+ qt_timestamptz_column_diff_ny """
+ SELECT milliseconds_diff(t2.ts, t1.ts) AS ms_diff,
+ seconds_diff(t2.ts, t1.ts) AS sec_diff,
+ timediff(t2.ts, t1.ts) AS time_diff
+ FROM tz_utc_function_events t1, tz_utc_function_events t2
+ WHERE t1.id = 1 AND t2.id = 2;
+ """
+
+ // topn_weighted should preserve TIMESTAMPTZ as the result array item type.
+ sql "SET time_zone = '+00:00';"
+ order_qt_timestamptz_topn_weighted """
+ SELECT grp,
+ CAST(topn_weighted(ts, weight, 2)[1] AS VARCHAR(64)) AS top_ts,
+ CAST(topn_weighted(ts, weight, 2, 100)[1] AS VARCHAR(64)) AS
top_ts_with_default
+ FROM tz_utc_function_events
+ WHERE grp IN (1, 3)
+ GROUP BY grp
+ ORDER BY grp;
+ """
+
+ // NULL input remains NULL, and sequence_count ignores the NULL timestamp
row.
+ qt_timestamptz_null """
+ SELECT milliseconds_diff(MAX(ts), NULL), sequence_count('(?1)(?2)',
ts, e1, e2)
+ FROM tz_utc_function_events
+ WHERE grp = 2;
+ """
+
+ sql "SET time_zone = default;"
+}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]