This is an automated email from the ASF dual-hosted git repository.
yiguolei pushed a commit to branch branch-4.0
in repository https://gitbox.apache.org/repos/asf/doris.git
The following commit(s) were added to refs/heads/branch-4.0 by this push:
new 55e9be832c1 branch-4.0: [feature](function) support add/sub_time
functions #56200 (#58428)
55e9be832c1 is described below
commit 55e9be832c1d0a078ac6e788df40b9ae552584b8
Author: github-actions[bot]
<41898282+github-actions[bot]@users.noreply.github.com>
AuthorDate: Thu Nov 27 14:19:55 2025 +0800
branch-4.0: [feature](function) support add/sub_time functions #56200
(#58428)
Cherry-picked from #56200
Co-authored-by: dwdwqfwe <[email protected]>
---
.../function_date_or_datetime_computation.cpp | 12 ++-
.../function_date_or_datetime_computation.h | 115 ++++++++++++++++++++-
.../doris/catalog/BuiltinScalarFunctions.java | 4 +
.../scalar/{YearsAdd.java => AddTime.java} | 31 +++---
.../scalar/{YearsAdd.java => SubTime.java} | 33 +++---
.../expressions/functions/scalar/YearsAdd.java | 2 +-
.../expressions/visitor/ScalarFunctionVisitor.java | 10 ++
.../datetime_functions/test_date_function_v2.out | 81 +++++++++++++++
.../test_date_function_v2.groovy | 58 ++++++++++-
9 files changed, 304 insertions(+), 42 deletions(-)
diff --git a/be/src/vec/functions/function_date_or_datetime_computation.cpp
b/be/src/vec/functions/function_date_or_datetime_computation.cpp
index 938edb8a9d3..ba0fc8c9c7b 100644
--- a/be/src/vec/functions/function_date_or_datetime_computation.cpp
+++ b/be/src/vec/functions/function_date_or_datetime_computation.cpp
@@ -113,6 +113,11 @@ using FunctionDatetimeSubQuarters =
using FunctionDatetimeSubYears =
FunctionDateOrDateTimeComputation<SubtractYearsImpl<TYPE_DATETIMEV2>>;
+using FunctionAddTimeDatetime = FunctionAddTime<TYPE_DATETIMEV2, AddTimeImpl>;
+using FunctionAddTimeTime = FunctionAddTime<TYPE_TIMEV2, AddTimeImpl>;
+using FunctionSubTimeDatetime = FunctionAddTime<TYPE_DATETIMEV2, SubTimeImpl>;
+using FunctionSubTimeTime = FunctionAddTime<TYPE_TIMEV2, SubTimeImpl>;
+
#define FUNCTION_TIME_DIFF(NAME, IMPL, TYPE) using NAME##_##TYPE =
FunctionTimeDiff<IMPL<TYPE>>;
#define ALL_FUNCTION_TIME_DIFF(NAME, IMPL) \
@@ -205,6 +210,11 @@ void
register_function_date_time_computation(SimpleFunctionFactory& factory) {
factory.register_function<FunctionDatetimeSubQuarters>();
factory.register_function<FunctionDatetimeSubWeeks>();
+ factory.register_function<FunctionAddTimeDatetime>();
+ factory.register_function<FunctionAddTimeTime>();
+ factory.register_function<FunctionSubTimeDatetime>();
+ factory.register_function<FunctionSubTimeTime>();
+
#define REGISTER_DATEV2_FUNCTIONS_DIFF(NAME, TYPE)
factory.register_function<NAME##_##TYPE>();
#define REGISTER_ALL_DATEV2_FUNCTIONS_DIFF(NAME) \
@@ -230,4 +240,4 @@ void
register_function_date_time_computation(SimpleFunctionFactory& factory) {
factory.register_function<FunctionDatetimeToWeekTwoArgs>();
}
-} // namespace doris::vectorized
+} // namespace doris::vectorized
\ No newline at end of file
diff --git a/be/src/vec/functions/function_date_or_datetime_computation.h
b/be/src/vec/functions/function_date_or_datetime_computation.h
index 2eb8e9f74fc..ab3d6914af3 100644
--- a/be/src/vec/functions/function_date_or_datetime_computation.h
+++ b/be/src/vec/functions/function_date_or_datetime_computation.h
@@ -66,6 +66,7 @@
namespace doris::vectorized {
#include "common/compile_check_avoid_begin.h"
+
/// because all these functions(xxx_add/xxx_sub) defined in FE use Integer as
the second value
/// so Int64 as delta is needed to support large values. For
upstream(FunctionDateOrDateTimeComputation) we use Int64.
@@ -116,7 +117,6 @@ auto date_time_add(const typename
PrimitiveTypeTraits<ArgType>::DataType::FieldT
std::make_shared<typename
PrimitiveTypeTraits<IntervalPType>::DataType>()}; \
}
\
}
-
ADD_TIME_FUNCTION_IMPL(AddMicrosecondsImpl, microseconds_add, MICROSECOND);
ADD_TIME_FUNCTION_IMPL(AddMillisecondsImpl, milliseconds_add, MILLISECOND);
ADD_TIME_FUNCTION_IMPL(AddSecondsImpl, seconds_add, SECOND);
@@ -1613,5 +1613,118 @@ public:
}
};
+struct AddTimeImpl {
+ static constexpr auto name = "add_time";
+ static bool is_negative() { return false; }
+};
+
+struct SubTimeImpl {
+ static constexpr auto name = "sub_time";
+ static bool is_negative() { return true; }
+};
+
+template <PrimitiveType PType, typename Impl>
+class FunctionAddTime : public IFunction {
+public:
+ static constexpr auto name = Impl::name;
+ static constexpr PrimitiveType ReturnType = PType;
+ static constexpr PrimitiveType ArgType1 = PType;
+ static constexpr PrimitiveType ArgType2 = TYPE_TIMEV2;
+ using ColumnType1 = typename PrimitiveTypeTraits<PType>::ColumnType;
+ using ColumnType2 = typename PrimitiveTypeTraits<TYPE_TIMEV2>::ColumnType;
+ using InputType1 = typename
PrimitiveTypeTraits<PType>::DataType::FieldType;
+ using InputType2 = typename
PrimitiveTypeTraits<TYPE_TIMEV2>::DataType::FieldType;
+ using ReturnNativeType = InputType1;
+ using ReturnDataType = typename PrimitiveTypeTraits<PType>::DataType;
+
+ String get_name() const override { return name; }
+ size_t get_number_of_arguments() const override { return 2; }
+ DataTypes get_variadic_argument_types_impl() const override {
+ return {std::make_shared<typename
PrimitiveTypeTraits<PType>::DataType>(),
+ std::make_shared<typename
PrimitiveTypeTraits<TYPE_TIMEV2>::DataType>()};
+ }
+ DataTypePtr get_return_type_impl(const ColumnsWithTypeAndName& arguments)
const override {
+ return std::make_shared<ReturnDataType>();
+ }
+
+ ReturnNativeType compute(const InputType1& arg1, const InputType2& arg2)
const {
+ if constexpr (PType == TYPE_DATETIMEV2) {
+ DateV2Value<DateTimeV2ValueType> dtv1 =
+ binary_cast<InputType1,
DateV2Value<DateTimeV2ValueType>>(arg1);
+ auto tv2 = static_cast<TimeValue::TimeType>(arg2);
+ TimeInterval interval(TimeUnit::MICROSECOND, tv2,
Impl::is_negative());
+ bool out_range = dtv1.template
date_add_interval<TimeUnit::MICROSECOND>(interval);
+ if (UNLIKELY(!out_range)) {
+ throw Exception(ErrorCode::INVALID_ARGUMENT,
+ "datetime value is out of range in function
{}", name);
+ }
+ return binary_cast<DateV2Value<DateTimeV2ValueType>,
ReturnNativeType>(dtv1);
+ } else if constexpr (PType == TYPE_TIMEV2) {
+ auto tv1 = static_cast<TimeValue::TimeType>(arg1);
+ auto tv2 = static_cast<TimeValue::TimeType>(arg2);
+ double res = TimeValue::limit_with_bound(Impl::is_negative() ? tv1
- tv2 : tv1 + tv2);
+ return res;
+ } else {
+ throw Exception(ErrorCode::FATAL_ERROR, "not support type for
function {}", name);
+ }
+ }
+
+ static FunctionPtr create() { return std::make_shared<FunctionAddTime>(); }
+
+ Status execute_impl(FunctionContext* context, Block& block, const
ColumnNumbers& arguments,
+ uint32_t result, size_t input_rows_count) const
override {
+ DCHECK_EQ(arguments.size(), 2);
+ const auto& [left_col, left_const] =
+ unpack_if_const(block.get_by_position(arguments[0]).column);
+ const auto& [right_col, right_const] =
+ unpack_if_const(block.get_by_position(arguments[1]).column);
+ ColumnPtr nest_col1 = remove_nullable(left_col);
+ ColumnPtr nest_col2 = remove_nullable(right_col);
+ auto res = ColumnVector<ReturnType>::create(input_rows_count, 0);
+
+ if (left_const) {
+ execute_constant_vector(assert_cast<const
ColumnType1&>(*nest_col1).get_element(0),
+ assert_cast<const
ColumnType2&>(*nest_col2).get_data(),
+ res->get_data(), input_rows_count);
+ } else if (right_const) {
+ execute_vector_constant(assert_cast<const
ColumnType1&>(*nest_col1).get_data(),
+ assert_cast<const
ColumnType2&>(*nest_col2).get_element(0),
+ res->get_data(), input_rows_count);
+ } else {
+ execute_vector_vector(assert_cast<const
ColumnType1&>(*nest_col1).get_data(),
+ assert_cast<const
ColumnType2&>(*nest_col2).get_data(),
+ res->get_data(), input_rows_count);
+ }
+
+ block.replace_by_position(result, std::move(res));
+ return Status::OK();
+ }
+ void execute_vector_vector(const PaddedPODArray<InputType1>& left_col,
+ const PaddedPODArray<InputType2>& right_col,
+ PaddedPODArray<ReturnNativeType>& res_data,
+ size_t input_rows_count) const {
+ for (size_t i = 0; i < input_rows_count; ++i) {
+ res_data[i] = compute(left_col[i], right_col[i]);
+ }
+ }
+
+ void execute_vector_constant(const PaddedPODArray<InputType1>& left_col,
+ const InputType2 right_value,
+ PaddedPODArray<ReturnNativeType>& res_data,
+ size_t input_rows_count) const {
+ for (size_t i = 0; i < input_rows_count; ++i) {
+ res_data[i] = compute(left_col[i], right_value);
+ }
+ }
+
+ void execute_constant_vector(const InputType1 left_value,
+ const PaddedPODArray<InputType2>& right_col,
+ PaddedPODArray<ReturnNativeType>& res_data,
+ size_t input_rows_count) const {
+ for (size_t i = 0; i < input_rows_count; ++i) {
+ res_data[i] = compute(left_value, right_col[i]);
+ }
+ }
+};
#include "common/compile_check_avoid_end.h"
} // namespace doris::vectorized
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/catalog/BuiltinScalarFunctions.java
b/fe/fe-core/src/main/java/org/apache/doris/catalog/BuiltinScalarFunctions.java
index e1d4413cf40..e8730d5a538 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/catalog/BuiltinScalarFunctions.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/catalog/BuiltinScalarFunctions.java
@@ -33,6 +33,7 @@ import
org.apache.doris.nereids.trees.expressions.functions.ai.Embed;
import org.apache.doris.nereids.trees.expressions.functions.scalar.Abs;
import org.apache.doris.nereids.trees.expressions.functions.scalar.Acos;
import org.apache.doris.nereids.trees.expressions.functions.scalar.Acosh;
+import org.apache.doris.nereids.trees.expressions.functions.scalar.AddTime;
import org.apache.doris.nereids.trees.expressions.functions.scalar.AesDecrypt;
import org.apache.doris.nereids.trees.expressions.functions.scalar.AesEncrypt;
import
org.apache.doris.nereids.trees.expressions.functions.scalar.AppendTrailingCharIfAbsent;
@@ -475,6 +476,7 @@ import
org.apache.doris.nereids.trees.expressions.functions.scalar.StructElement
import org.apache.doris.nereids.trees.expressions.functions.scalar.SubBinary;
import org.apache.doris.nereids.trees.expressions.functions.scalar.SubBitmap;
import org.apache.doris.nereids.trees.expressions.functions.scalar.SubReplace;
+import org.apache.doris.nereids.trees.expressions.functions.scalar.SubTime;
import org.apache.doris.nereids.trees.expressions.functions.scalar.Substring;
import
org.apache.doris.nereids.trees.expressions.functions.scalar.SubstringIndex;
import org.apache.doris.nereids.trees.expressions.functions.scalar.Tan;
@@ -570,6 +572,7 @@ public class BuiltinScalarFunctions implements
FunctionHelper {
scalar(AIMask.class, "ai_mask"),
scalar(AISummarize.class, "ai_summarize"),
scalar(AISimilarity.class, "ai_similarity"),
+ scalar(AddTime.class, "add_time"),
scalar(AesDecrypt.class, "aes_decrypt"),
scalar(AesEncrypt.class, "aes_encrypt"),
scalar(AppendTrailingCharIfAbsent.class,
"append_trailing_char_if_absent"),
@@ -1023,6 +1026,7 @@ public class BuiltinScalarFunctions implements
FunctionHelper {
scalar(SubBitmap.class, "sub_bitmap"),
scalar(SubReplace.class, "sub_replace"),
scalar(Substring.class, "substr", "substring", "mid"),
+ scalar(SubTime.class, "sub_time"),
scalar(SubstringIndex.class, "substring_index"),
scalar(Tan.class, "tan"),
scalar(Tanh.class, "tanh"),
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/YearsAdd.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/AddTime.java
similarity index 63%
copy from
fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/YearsAdd.java
copy to
fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/AddTime.java
index 7a6dd1df8e2..364ee6cf675 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/YearsAdd.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/AddTime.java
@@ -19,15 +19,13 @@ 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.functions.ComputeSignatureForDateArithmetic;
import
org.apache.doris.nereids.trees.expressions.functions.DateAddSubMonotonic;
import
org.apache.doris.nereids.trees.expressions.functions.ExplicitlyCastableSignature;
import org.apache.doris.nereids.trees.expressions.functions.PropagateNullable;
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.IntegerType;
+import org.apache.doris.nereids.types.TimeV2Type;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
@@ -35,32 +33,29 @@ import com.google.common.collect.ImmutableList;
import java.util.List;
/**
- * ScalarFunction 'days_add'.
+ * ScalarFunction 'add_time'.
*/
-public class YearsAdd extends ScalarFunction implements BinaryExpression,
ExplicitlyCastableSignature,
- ComputeSignatureForDateArithmetic, PropagateNullable,
DateAddSubMonotonic {
+public class AddTime extends ScalarFunction implements BinaryExpression,
ExplicitlyCastableSignature,
+ PropagateNullable, DateAddSubMonotonic {
- //ATTN: must place Datetime before Date, because for castring from string
like literal, date and datetime has
- // the same precedence, but we prefer datetime to avoid data loss. for
string literal which could cast to Date
- // without loss, we handle it by ComputeSignatureForDateArithmetic.
private static final List<FunctionSignature> SIGNATURES = ImmutableList.of(
FunctionSignature.ret(DateTimeV2Type.WILDCARD).args(DateTimeV2Type.WILDCARD,
- IntegerType.INSTANCE),
-
FunctionSignature.ret(DateV2Type.INSTANCE).args(DateV2Type.INSTANCE,
IntegerType.INSTANCE));
+ TimeV2Type.WILDCARD),
+
FunctionSignature.ret(TimeV2Type.WILDCARD).args(TimeV2Type.WILDCARD,
TimeV2Type.WILDCARD));
- public YearsAdd(Expression arg0, Expression arg1) {
- super("years_add", arg0, arg1);
+ public AddTime(Expression arg0, Expression arg1) {
+ super("add_time", arg0, arg1);
}
/** constructor for withChildren and reuse signature */
- private YearsAdd(ScalarFunctionParams functionParams) {
+ private AddTime(ScalarFunctionParams functionParams) {
super(functionParams);
}
@Override
- public YearsAdd withChildren(List<Expression> children) {
+ public AddTime withChildren(List<Expression> children) {
Preconditions.checkArgument(children.size() == 2);
- return new YearsAdd(getFunctionParams(children));
+ return new AddTime(getFunctionParams(children));
}
@Override
@@ -70,11 +65,11 @@ public class YearsAdd extends ScalarFunction implements
BinaryExpression, Explic
@Override
public <R, C> R accept(ExpressionVisitor<R, C> visitor, C context) {
- return visitor.visitYearsAdd(this, context);
+ return visitor.visitAddTime(this, context);
}
@Override
public Expression withConstantArgs(Expression literal) {
- return new YearsAdd(literal, child(1));
+ return new AddTime(literal, child(1));
}
}
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/YearsAdd.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/SubTime.java
similarity index 61%
copy from
fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/YearsAdd.java
copy to
fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/SubTime.java
index 7a6dd1df8e2..347afeed513 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/YearsAdd.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/SubTime.java
@@ -19,15 +19,13 @@ 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.functions.ComputeSignatureForDateArithmetic;
import
org.apache.doris.nereids.trees.expressions.functions.DateAddSubMonotonic;
import
org.apache.doris.nereids.trees.expressions.functions.ExplicitlyCastableSignature;
import org.apache.doris.nereids.trees.expressions.functions.PropagateNullable;
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.IntegerType;
+import org.apache.doris.nereids.types.TimeV2Type;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
@@ -35,32 +33,29 @@ import com.google.common.collect.ImmutableList;
import java.util.List;
/**
- * ScalarFunction 'days_add'.
+ * ScalarFunction 'sub_time'.
*/
-public class YearsAdd extends ScalarFunction implements BinaryExpression,
ExplicitlyCastableSignature,
- ComputeSignatureForDateArithmetic, PropagateNullable,
DateAddSubMonotonic {
+public class SubTime extends ScalarFunction implements BinaryExpression,
ExplicitlyCastableSignature,
+ PropagateNullable, DateAddSubMonotonic {
- //ATTN: must place Datetime before Date, because for castring from string
like literal, date and datetime has
- // the same precedence, but we prefer datetime to avoid data loss. for
string literal which could cast to Date
- // without loss, we handle it by ComputeSignatureForDateArithmetic.
private static final List<FunctionSignature> SIGNATURES = ImmutableList.of(
-
FunctionSignature.ret(DateTimeV2Type.WILDCARD).args(DateTimeV2Type.WILDCARD,
- IntegerType.INSTANCE),
-
FunctionSignature.ret(DateV2Type.INSTANCE).args(DateV2Type.INSTANCE,
IntegerType.INSTANCE));
+
FunctionSignature.ret(DateTimeV2Type.SYSTEM_DEFAULT).args(DateTimeV2Type.SYSTEM_DEFAULT,
+ TimeV2Type.WILDCARD),
+
FunctionSignature.ret(TimeV2Type.WILDCARD).args(TimeV2Type.WILDCARD,
TimeV2Type.WILDCARD));
- public YearsAdd(Expression arg0, Expression arg1) {
- super("years_add", arg0, arg1);
+ public SubTime(Expression arg0, Expression arg1) {
+ super("sub_time", arg0, arg1);
}
/** constructor for withChildren and reuse signature */
- private YearsAdd(ScalarFunctionParams functionParams) {
+ private SubTime(ScalarFunctionParams functionParams) {
super(functionParams);
}
@Override
- public YearsAdd withChildren(List<Expression> children) {
+ public SubTime withChildren(List<Expression> children) {
Preconditions.checkArgument(children.size() == 2);
- return new YearsAdd(getFunctionParams(children));
+ return new SubTime(getFunctionParams(children));
}
@Override
@@ -70,11 +65,11 @@ public class YearsAdd extends ScalarFunction implements
BinaryExpression, Explic
@Override
public <R, C> R accept(ExpressionVisitor<R, C> visitor, C context) {
- return visitor.visitYearsAdd(this, context);
+ return visitor.visitSubTime(this, context);
}
@Override
public Expression withConstantArgs(Expression literal) {
- return new YearsAdd(literal, child(1));
+ return new SubTime(literal, child(1));
}
}
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/YearsAdd.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/YearsAdd.java
index 7a6dd1df8e2..fb4df179006 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/YearsAdd.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/YearsAdd.java
@@ -35,7 +35,7 @@ import com.google.common.collect.ImmutableList;
import java.util.List;
/**
- * ScalarFunction 'days_add'.
+ * ScalarFunction 'years_add'.
*/
public class YearsAdd extends ScalarFunction implements BinaryExpression,
ExplicitlyCastableSignature,
ComputeSignatureForDateArithmetic, PropagateNullable,
DateAddSubMonotonic {
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/visitor/ScalarFunctionVisitor.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/visitor/ScalarFunctionVisitor.java
index 2724f19360e..a26a3b0123a 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/visitor/ScalarFunctionVisitor.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/visitor/ScalarFunctionVisitor.java
@@ -35,6 +35,7 @@ import
org.apache.doris.nereids.trees.expressions.functions.combinator.StateComb
import org.apache.doris.nereids.trees.expressions.functions.scalar.Abs;
import org.apache.doris.nereids.trees.expressions.functions.scalar.Acos;
import org.apache.doris.nereids.trees.expressions.functions.scalar.Acosh;
+import org.apache.doris.nereids.trees.expressions.functions.scalar.AddTime;
import org.apache.doris.nereids.trees.expressions.functions.scalar.AesDecrypt;
import org.apache.doris.nereids.trees.expressions.functions.scalar.AesEncrypt;
import
org.apache.doris.nereids.trees.expressions.functions.scalar.AppendTrailingCharIfAbsent;
@@ -476,6 +477,7 @@ import
org.apache.doris.nereids.trees.expressions.functions.scalar.StructElement
import org.apache.doris.nereids.trees.expressions.functions.scalar.SubBinary;
import org.apache.doris.nereids.trees.expressions.functions.scalar.SubBitmap;
import org.apache.doris.nereids.trees.expressions.functions.scalar.SubReplace;
+import org.apache.doris.nereids.trees.expressions.functions.scalar.SubTime;
import org.apache.doris.nereids.trees.expressions.functions.scalar.Substring;
import
org.apache.doris.nereids.trees.expressions.functions.scalar.SubstringIndex;
import org.apache.doris.nereids.trees.expressions.functions.scalar.Tan;
@@ -566,6 +568,10 @@ public interface ScalarFunctionVisitor<R, C> {
return visitScalarFunction(acosh, context);
}
+ default R visitAddTime(AddTime addTime, C context) {
+ return visitScalarFunction(addTime, context);
+ }
+
default R visitAesDecrypt(AesDecrypt aesDecrypt, C context) {
return visitScalarFunction(aesDecrypt, context);
}
@@ -2247,6 +2253,10 @@ public interface ScalarFunctionVisitor<R, C> {
return visitScalarFunction(subReplace, context);
}
+ default R visitSubTime(SubTime subTime, C context) {
+ return visitScalarFunction(subTime, context);
+ }
+
default R visitSubstring(Substring substring, C context) {
return visitScalarFunction(substring, context);
}
diff --git
a/regression-test/data/nereids_p0/sql_functions/datetime_functions/test_date_function_v2.out
b/regression-test/data/nereids_p0/sql_functions/datetime_functions/test_date_function_v2.out
index 11b715513a3..a6ea92dcafb 100644
---
a/regression-test/data/nereids_p0/sql_functions/datetime_functions/test_date_function_v2.out
+++
b/regression-test/data/nereids_p0/sql_functions/datetime_functions/test_date_function_v2.out
@@ -121,4 +121,85 @@
-- !get_format_time_4 --
\N
+-- !sql_addtime1 --
+2023-10-14T22:35:22
+
+-- !sql_addtime2 --
+2023-10-14T22:35:22.243456
+
+-- !sql_addtime3 --
+2025-01-03T12:46:34.123456
+2023-01-20T11:06:07.123456
+2025-07-05T18:20:52.123456
+
+-- !sql_addtime4 --
+838:59:59.000000
+
+-- !sql_addtime5 --
+-503:36:23.123456
+
+-- !sql_addtime6 --
+2024-12-29T22:46:08.123456
+2023-01-16T08:30:44
+2025-06-30T03:10:34.999999
+
+-- !sql_addtime7 --
+14:34:56.123
+25:59:59.123
+-10:34:55.877
+
+-- !sql_addtime8 --
+2024-12-29T11:41:12.123456
+2023-01-15T10:00:45
+2025-06-30T17:15:30.999999
+
+-- !sql_subtime1 --
+2023-10-13T01:24:38
+
+-- !sql_subtime2 --
+2023-10-13T01:24:37.996544
+
+-- !sql_subtime3 --
+2024-12-28T11:35:49.876544
+2023-01-14T09:55:22.876544
+2025-06-29T17:10:07.876544
+
+-- !sql_subtime4 --
+-838:59:59
+
+-- !sql_subtime5 --
+503:36:23.123456
+
+-- !sql_subtime6 --
+2024-12-28T21:36:16.123456
+2023-01-14T08:30:46
+2025-07-01T04:20:26.999999
+
+-- !sql_subtime7 --
+10:34:55.877
+21:59:58.877
+-14:34:56.123
+
+-- !sql_subtime8 --
+2024-12-29T08:41:12.123456
+2023-01-15T07:00:45
+2025-06-30T14:15:30.999999
+
+-- !sql_addtime10 --
+44:22:32
+
+-- !sql_addtime11 --
+44:22:32
+
+-- !sql_addtime12 --
+2022-12-22T22:10:10
+
+-- !sql_subtime10 --
+00:02:12
+
+-- !sql_subtime11 --
+-44:22:32
+
+-- !sql_subtime12 --
+2022-12-21T01:49:50
diff --git
a/regression-test/suites/nereids_p0/sql_functions/datetime_functions/test_date_function_v2.groovy
b/regression-test/suites/nereids_p0/sql_functions/datetime_functions/test_date_function_v2.groovy
index 8d5158ea87a..d96a6f7c770 100644
---
a/regression-test/suites/nereids_p0/sql_functions/datetime_functions/test_date_function_v2.groovy
+++
b/regression-test/suites/nereids_p0/sql_functions/datetime_functions/test_date_function_v2.groovy
@@ -27,7 +27,9 @@ suite("test_date_function_v2") {
CREATE TABLE IF NOT EXISTS ${tableName} (
`id` INT,
`name` varchar(32),
- `dt` varchar(32)
+ `dt` varchar(32),
+ `time_str` varchar(32),
+ `datetime_val` datetime(6)
) ENGINE=OLAP
UNIQUE KEY(`id`)
DISTRIBUTED BY HASH(`id`) BUCKETS 1
@@ -35,7 +37,11 @@ suite("test_date_function_v2") {
"replication_allocation" = "tag.location.default: 1"
)
"""
- sql """ insert into ${tableName} values (3, 'Carl','2024-12-29 10:11:12')
"""
+ sql """ insert into ${tableName} values
+ (1, 'Carl', '2024-12-29 10:11:12', '12:34:56', '2024-12-29
10:11:12.123456'),
+ (2, 'Bob', '2023-01-15 08:30:45', '23:59:59', '2023-01-15
08:30:45.000000'),
+ (3, 'Alice', '2025-06-30 15:45:30', '-12:34:56', '2025-06-30
15:45:30.999999')
+ """
def result1 = try_sql """
select cast(str_to_date(dt, '%Y-%m-%d %H:%i:%s') as string) from
${tableName};
"""
@@ -154,4 +160,52 @@ suite("test_date_function_v2") {
testFoldConst("SELECT GET_FORMAT(TImE, 'INTERNAL');")
testFoldConst("SELECT GET_FORMAT(TIME, 'Doris');")
testFoldConst("SELECT GET_FORMAT(TIME, '你好');")
+ qt_sql_addtime1 "select add_time('2023-10-14 00:00:00', '22:35:22');"
+ testFoldConst("select add_time('2023-10-14 00:00:00', '22:35:22');")
+ qt_sql_addtime2 "select add_time('2023-10-14 00:00:00.12',
'22:35:22.123456');"
+ testFoldConst("select add_time('2023-10-14 00:00:00.12',
'22:35:22.123456');")
+ qt_sql_addtime3 "select add_time(dt, '122:35:22.123456') from
${tableName};"
+ qt_sql_addtime4 "select add_time(cast('822:35:22.123456' as time(6)),
cast('421:01:01' as time(6)));"
+ qt_sql_addtime5 "select add_time(cast('-82:35:22.123456' as time(6)),
cast('-421:01:01' as time(6)));"
+
+ // test time string and datetime type in table
+ qt_sql_addtime6 "select add_time(datetime_val, time_str) from ${tableName}
order by id;"
+ qt_sql_addtime7 "select add_time(cast(time_str as time),
cast('02:00:00.123' as time(3))) from ${tableName} order by id;"
+ qt_sql_addtime8 "select add_time(datetime_val, cast('01:30:00' as time))
from ${tableName} order by id;"
+
+ test{
+ sql("select add_time('9999-12-29 00:00:00', '122:35:22.123456');")
+ exception "datetime value is out of range in function add_time"
+ }
+
+ qt_sql_subtime1("select sub_time('2023-10-14 00:00:00', '22:35:22');")
+ testFoldConst("select sub_time('2023-10-14 00:00:00', '22:35:22');")
+ qt_sql_subtime2("select sub_time('2023-10-14 00:00:00.12',
'22:35:22.123456');")
+ testFoldConst("select sub_time('2023-10-14 00:00:00.12',
'22:35:22.123456');")
+ qt_sql_subtime3("select sub_time(dt, '22:35:22.123456') from
${tableName};")
+ qt_sql_subtime4("select sub_time('-421:01:01', '822:35:22');")
+ qt_sql_subtime5("select sub_time('421:01:01', '-82:35:22.123456');")
+
+ // test time string and datetime type in table
+ qt_sql_subtime6("select sub_time(datetime_val, time_str) from ${tableName}
order by id;")
+ qt_sql_subtime7("select sub_time(cast(time_str as time),
cast('02:00:00.123' as time(3))) from ${tableName} order by id;")
+ qt_sql_subtime8("select sub_time(datetime_val, cast('01:30:00' as time))
from ${tableName} order by id;")
+
+ test{
+ sql("select sub_time('0000-01-01 00:00:00', '122:35:22.123456');")
+ exception "datetime value is out of range in function sub_time"
+ }
+
+ //test computetimearithmetic regular
+
+ qt_sql_addtime10 "select add_time('22:12:22', '221010');"
+ qt_sql_addtime11 "select add_time('+22:12:22', '221010');"
+
+ //datetime parameter
+ qt_sql_addtime12 "select add_time('22/12/22', '221010');"
+
+ qt_sql_subtime10 "select sub_time('22:12:22', '221010');"
+ qt_sql_subtime11 "select sub_time('-22:12:22', '221010');"
+ //datetime parameter
+ qt_sql_subtime12 "select sub_time('22/12/22', '221010');"
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]