This is an automated email from the ASF dual-hosted git repository.

starocean999 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/doris.git


The following commit(s) were added to refs/heads/master by this push:
     new fce83e968db [Enhancement](function) The date_add function supports 
MINUTE_SECOND as interval type (#58032)
fce83e968db is described below

commit fce83e968dbf596460d9a24e21877c89d6d509b4
Author: csding <[email protected]>
AuthorDate: Thu Nov 27 14:08:39 2025 +0800

    [Enhancement](function) The date_add function supports MINUTE_SECOND as 
interval type (#58032)
    
    
    The date_add function supports new type: MINUTE_SECOND, now we can use a
    string in the format 'minute:second' as the INTERVAL parameter.
    
    ```
    mysql> select DATE_ADD('2025-10-23 10:10:10', INTERVAL '1:1' MINUTE_SECOND);
    +---------------------------------------------------------------+
    | DATE_ADD('2025-10-23 10:10:10', INTERVAL '1:1' MINUTE_SECOND) |
    +---------------------------------------------------------------+
    | 2025-10-23 10:11:11                                           |
    +---------------------------------------------------------------+
    1 row in set (0.01 sec)
    
    mysql> select DATE_ADD('2025-10-23 10:10:10', INTERVAL '-1:1' 
MINUTE_SECOND);
    +----------------------------------------------------------------+
    | DATE_ADD('2025-10-23 10:10:10', INTERVAL '-1:1' MINUTE_SECOND) |
    +----------------------------------------------------------------+
    | 2025-10-23 10:09:09                                            |
    +----------------------------------------------------------------+
    1 row in set (0.00 sec)
    ``
---
 .../function_date_or_datetime_computation.cpp      |   3 +
 .../function_date_or_datetime_computation.h        |  66 ++++++++++++
 be/test/vec/function/function_time_test.cpp        |  35 +++++++
 .../antlr4/org/apache/doris/nereids/DorisLexer.g4  |   1 +
 .../antlr4/org/apache/doris/nereids/DorisParser.g4 |   1 +
 .../rules/analysis/DatetimeFunctionBinder.java     |   3 +
 .../functions/executable/DateTimeArithmetic.java   |   8 ++
 .../functions/scalar/MinuteSecondAdd.java          |  80 +++++++++++++++
 .../expressions/literal/DateTimeV2Literal.java     |  53 ++++++++--
 .../trees/expressions/literal/Interval.java        |   1 +
 .../expressions/visitor/ScalarFunctionVisitor.java |   5 +
 .../nereids/rules/expression/FoldConstantTest.java |  17 ++++
 .../test_dateadd_with_other_timeunit.out           |  79 ++++++++++++---
 .../test_dateadd_with_other_timeunit.groovy        | 112 ++++++++++++++++-----
 14 files changed, 417 insertions(+), 47 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 ff081c270f5..2719b43254a 100644
--- a/be/src/vec/functions/function_date_or_datetime_computation.cpp
+++ b/be/src/vec/functions/function_date_or_datetime_computation.cpp
@@ -94,6 +94,8 @@ using FunctionDatetimeAddDaySecond =
         FunctionDateOrDateTimeComputation<AddDaySecondImpl<TYPE_DATETIMEV2>>;
 using FunctionDatetimeAddDayHour =
         FunctionDateOrDateTimeComputation<AddDayHourImpl<TYPE_DATETIMEV2>>;
+using FunctionDatetimeAddMinuteSecond =
+        
FunctionDateOrDateTimeComputation<AddMinuteSecondImpl<TYPE_DATETIMEV2>>;
 using FunctionDatetimeSubMicroseconds =
         
FunctionDateOrDateTimeComputation<SubtractMicrosecondsImpl<TYPE_DATETIMEV2>>;
 using FunctionDatetimeSubMilliseconds =
@@ -195,6 +197,7 @@ void 
register_function_date_time_computation(SimpleFunctionFactory& factory) {
     factory.register_function<FunctionDatetimeAddQuarters>();
     factory.register_function<FunctionDatetimeAddDaySecond>();
     factory.register_function<FunctionDatetimeAddDayHour>();
+    factory.register_function<FunctionDatetimeAddMinuteSecond>();
 
     factory.register_function<FunctionSubDays>();
     factory.register_function<FunctionSubMonths>();
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 dfc57f1694e..03c95ed46fc 100644
--- a/be/src/vec/functions/function_date_or_datetime_computation.h
+++ b/be/src/vec/functions/function_date_or_datetime_computation.h
@@ -286,6 +286,72 @@ struct AddDayHourImpl {
     }
 };
 
+template <PrimitiveType PType>
+struct AddMinuteSecondImpl {
+    static constexpr PrimitiveType ArgPType = PType;
+    static constexpr PrimitiveType ReturnType = PType;
+    static constexpr PrimitiveType IntervalPType = PrimitiveType ::TYPE_STRING;
+    using InputNativeType = typename PrimitiveTypeTraits<PType>::DataType 
::FieldType;
+    using ReturnNativeType = InputNativeType;
+    using IntervalDataType = typename 
PrimitiveTypeTraits<IntervalPType>::DataType;
+    using IntervalNativeType = IntervalDataType::FieldType; // string
+    using ConvertedType = typename 
PrimitiveTypeTraits<TYPE_BIGINT>::DataType::FieldType;
+
+    static constexpr auto name = "minute_second_add";
+    static constexpr auto is_nullable = false;
+
+    static inline ReturnNativeType execute(const InputNativeType& t, 
IntervalNativeType delta) {
+        long seconds = parse_minute_second_string_to_seconds(delta);
+        return date_time_add<TimeUnit::SECOND, PType, ConvertedType>(t, 
seconds);
+    }
+
+    static DataTypes get_variadic_argument_types() {
+        return {std ::make_shared<typename 
PrimitiveTypeTraits<PType>::DataType>(),
+                std ::make_shared<typename 
PrimitiveTypeTraits<IntervalPType>::DataType>()};
+    }
+
+    static long parse_minute_second_string_to_seconds(IntervalNativeType 
time_str_ref) {
+        bool is_negative = false;
+        auto time_str = StringRef {time_str_ref.data(), 
time_str_ref.length()}.trim();
+        // string format: "m:s"
+        size_t colon_pos = time_str.find_first_of(':');
+        if (colon_pos == std::string::npos) {
+            throw Exception(ErrorCode::INVALID_ARGUMENT,
+                            "Invalid time format, missing colon in '{}'",
+                            std::string_view {time_str.data, time_str.size});
+        }
+        // minute
+        StringRef minutes_sub = time_str.substring(0, colon_pos).trim();
+        StringParser::ParseResult success;
+        int minutes = StringParser::string_to_int_internal<int32_t, true>(
+                minutes_sub.data, minutes_sub.size, &success);
+        if (success != StringParser::PARSE_SUCCESS) {
+            throw Exception(ErrorCode::INVALID_ARGUMENT, "Invalid minutes 
format in '{}'",
+                            std::string_view {time_str.data, time_str.size});
+        }
+        if (minutes < 0) {
+            is_negative = true;
+        }
+
+        // second
+        StringRef second_sub = time_str.substring(colon_pos + 1).trim();
+        int seconds = StringParser::string_to_int_internal<int32_t, true>(
+                second_sub.data, second_sub.size, &success);
+        if (success != StringParser::PARSE_SUCCESS) {
+            throw Exception(ErrorCode::INVALID_ARGUMENT, "Invalid seconds 
format in '{}'",
+                            std::string_view {time_str.data, time_str.size});
+        }
+
+        long part0 = minutes * 60;
+        // NOTE: Compatible with MySQL
+        long part1 = std::abs(seconds);
+        if (is_negative) {
+            part1 *= -1;
+        }
+        return part0 + part1;
+    }
+};
+
 template <PrimitiveType PType>
 struct AddQuartersImpl {
     static constexpr PrimitiveType ArgPType = PType;
diff --git a/be/test/vec/function/function_time_test.cpp 
b/be/test/vec/function/function_time_test.cpp
index 4ba2b16bdf5..a211fb7b227 100644
--- a/be/test/vec/function/function_time_test.cpp
+++ b/be/test/vec/function/function_time_test.cpp
@@ -1195,6 +1195,41 @@ TEST(VTimestampFunctionsTest, day_hour_add_v2_test) {
     }
 }
 
+TEST(VTimestampFunctionsTest, minute_second_add_v2_test) {
+    std::string func_name = "minute_second_add";
+
+    InputTypeSet input_types = {PrimitiveType::TYPE_DATETIMEV2,
+                                Consted {PrimitiveType::TYPE_STRING}};
+
+    {
+        DataSet data_set = {
+                {{std::string("2020-10-23 00:00:11.123"), std::string("1:1")},
+                 std::string("2020-10-23 00:01:12.123")},
+        };
+
+        static_cast<void>(
+                check_function<DataTypeDateTimeV2, true>(func_name, 
input_types, data_set));
+    }
+    {
+        DataSet data_set = {
+                {{std::string("2020-05-23 00:00:11.123"), std::string("1:10")},
+                 std::string("2020-05-23 00:01:21.123")},
+        };
+
+        static_cast<void>(
+                check_function<DataTypeDateTimeV2, true>(func_name, 
input_types, data_set));
+    }
+    {
+        DataSet data_set = {
+                {{std::string("2020-05-23 00:00:11.123"), std::string("5:0")},
+                 std::string("2020-05-23 00:05:11.123")},
+        };
+
+        static_cast<void>(
+                check_function<DataTypeDateTimeV2, true>(func_name, 
input_types, data_set));
+    }
+}
+
 TEST(VTimestampFunctionsTest, to_days_v2_test) {
     std::string func_name = "to_days";
 
diff --git a/fe/fe-core/src/main/antlr4/org/apache/doris/nereids/DorisLexer.g4 
b/fe/fe-core/src/main/antlr4/org/apache/doris/nereids/DorisLexer.g4
index 8cf376907f0..490fa43cf9a 100644
--- a/fe/fe-core/src/main/antlr4/org/apache/doris/nereids/DorisLexer.g4
+++ b/fe/fe-core/src/main/antlr4/org/apache/doris/nereids/DorisLexer.g4
@@ -362,6 +362,7 @@ MIN: 'MIN';
 MINUS: 'MINUS';
 MINUTE: 'MINUTE';
 MINUTES: 'MINUTES';
+MINUTE_SECOND: 'MINUTE_SECOND';
 MODIFY: 'MODIFY';
 MONTH: 'MONTH';
 MTMV: 'MTMV';
diff --git a/fe/fe-core/src/main/antlr4/org/apache/doris/nereids/DorisParser.g4 
b/fe/fe-core/src/main/antlr4/org/apache/doris/nereids/DorisParser.g4
index 282a303f582..8bf46106d15 100644
--- a/fe/fe-core/src/main/antlr4/org/apache/doris/nereids/DorisParser.g4
+++ b/fe/fe-core/src/main/antlr4/org/apache/doris/nereids/DorisParser.g4
@@ -1769,6 +1769,7 @@ interval
 
 unitIdentifier
        : YEAR | QUARTER | MONTH | WEEK | DAY | HOUR | MINUTE | SECOND | 
DAY_SECOND | DAY_HOUR
+    | MINUTE_SECOND
     ;
 
 dataTypeWithNullable
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/DatetimeFunctionBinder.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/DatetimeFunctionBinder.java
index 8dc9df95ea0..474b9f3a0a7 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/DatetimeFunctionBinder.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/DatetimeFunctionBinder.java
@@ -45,6 +45,7 @@ import 
org.apache.doris.nereids.trees.expressions.functions.scalar.HoursDiff;
 import org.apache.doris.nereids.trees.expressions.functions.scalar.HoursSub;
 import org.apache.doris.nereids.trees.expressions.functions.scalar.MinuteCeil;
 import org.apache.doris.nereids.trees.expressions.functions.scalar.MinuteFloor;
+import 
org.apache.doris.nereids.trees.expressions.functions.scalar.MinuteSecondAdd;
 import org.apache.doris.nereids.trees.expressions.functions.scalar.MinutesAdd;
 import org.apache.doris.nereids.trees.expressions.functions.scalar.MinutesDiff;
 import org.apache.doris.nereids.trees.expressions.functions.scalar.MinutesSub;
@@ -305,6 +306,8 @@ public class DatetimeFunctionBinder {
                 return new DaySecondAdd(timestamp, amount);
             case DAY_HOUR:
                 return new DayHourAdd(timestamp, amount);
+            case MINUTE_SECOND:
+                return new MinuteSecondAdd(timestamp, amount);
             default:
                 throw new AnalysisException("Unsupported time stamp add time 
unit: " + unit
                         + ", supported time unit: 
YEAR/QUARTER/MONTH/WEEK/DAY/HOUR/MINUTE/SECOND");
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/executable/DateTimeArithmetic.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/executable/DateTimeArithmetic.java
index e879bf7ce38..d3647a87220 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/executable/DateTimeArithmetic.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/executable/DateTimeArithmetic.java
@@ -54,6 +54,14 @@ public class DateTimeArithmetic {
         return date.plusDayHour(dayHour);
     }
 
+    /**
+     * datetime arithmetic function minute_second-add.
+     */
+    @ExecFunction(name = "minute_second_add")
+    public static Expression minuteSecondAdd(DateTimeV2Literal date, 
VarcharLiteral minuteSecond) {
+        return date.plusMinuteSecond(minuteSecond);
+    }
+
     /**
      * datetime arithmetic function date-sub.
      */
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MinuteSecondAdd.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MinuteSecondAdd.java
new file mode 100644
index 00000000000..c34ede1eff2
--- /dev/null
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MinuteSecondAdd.java
@@ -0,0 +1,80 @@
+// 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.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.VarcharType;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableList;
+
+import java.util.List;
+
+/**
+ * ScalarFunction 'minute_second_add'.
+ */
+public class MinuteSecondAdd extends ScalarFunction
+        implements BinaryExpression, ExplicitlyCastableSignature,
+        ComputeSignatureForDateArithmetic, PropagateNullable, 
DateAddSubMonotonic {
+    public static final List<FunctionSignature> SIGNATURES = ImmutableList.of(
+            
FunctionSignature.ret(DateTimeV2Type.WILDCARD).args(DateTimeV2Type.WILDCARD,
+            VarcharType.SYSTEM_DEFAULT));
+
+    public MinuteSecondAdd(Expression arg0, Expression arg1) {
+        super("minute_second_add", arg0, arg1);
+    }
+
+    /** constructor for withChildren and reuse signature */
+    private MinuteSecondAdd(ScalarFunctionParams functionParams) {
+        super(functionParams);
+    }
+
+    @Override
+    public MinuteSecondAdd withChildren(List<Expression> children) {
+        Preconditions.checkArgument(children.size() == 2);
+        return new MinuteSecondAdd(getFunctionParams(children));
+    }
+
+    @Override
+    public List<FunctionSignature> getSignatures() {
+        return SIGNATURES;
+    }
+
+    @Override
+    public <R, C> R accept(ExpressionVisitor<R, C> visitor, C context) {
+        return visitor.visitMinuteSecondAdd(this, context);
+    }
+
+    @Override
+    public Expression withConstantArgs(Expression literal) {
+        return new MinuteSecondAdd(literal, child(1));
+    }
+
+    @Override
+    public FunctionSignature computeSignature(FunctionSignature signature) {
+        return super.computeSignature(signature);
+    }
+}
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/DateTimeV2Literal.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/DateTimeV2Literal.java
index b91390afb2e..8fd73a69e31 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/DateTimeV2Literal.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/DateTimeV2Literal.java
@@ -19,6 +19,7 @@ package org.apache.doris.nereids.trees.expressions.literal;
 
 import org.apache.doris.analysis.LiteralExpr;
 import org.apache.doris.nereids.exceptions.AnalysisException;
+import org.apache.doris.nereids.exceptions.NotSupportedException;
 import org.apache.doris.nereids.exceptions.UnboundException;
 import org.apache.doris.nereids.trees.expressions.Expression;
 import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor;
@@ -220,19 +221,19 @@ public class DateTimeV2Literal extends DateTimeLiteral {
         String stringValue = daySecond.getStringValue().trim();
 
         if (!stringValue.matches("[0-9:\\-\\s]+")) {
-            return new NullLiteral(dataType);
+            throw new NotSupportedException("Invalid time format");
         }
 
         String[] split = stringValue.split("\\s+");
         if (split.length != 2) {
-            return new NullLiteral(dataType);
+            throw new NotSupportedException("Invalid time format");
         }
 
         String day = split[0];
         String[] hourMinuteSecond = split[1].split(":");
 
         if (hourMinuteSecond.length != 3) {
-            return new NullLiteral(dataType);
+            throw new NotSupportedException("Invalid time format");
         }
 
         try {
@@ -259,7 +260,7 @@ public class DateTimeV2Literal extends DateTimeLiteral {
                 .plusMinutes(minutes)
                 .plusSeconds(seconds), getDataType().getScale());
         } catch (NumberFormatException e) {
-            return new NullLiteral(dataType);
+            throw new NotSupportedException("Invalid time format");
         }
     }
 
@@ -294,12 +295,12 @@ public class DateTimeV2Literal extends DateTimeLiteral {
         String stringValue = dayHour.getStringValue().trim();
 
         if (!stringValue.matches("[0-9\\-\\s]+")) {
-            return new NullLiteral(dataType);
+            throw new NotSupportedException("Invalid time format");
         }
 
         String[] split = stringValue.split("\\s+");
         if (split.length != 2) {
-            return new NullLiteral(dataType);
+            throw new NotSupportedException("Invalid time format");
         }
 
         String day = split[0];
@@ -321,7 +322,45 @@ public class DateTimeV2Literal extends DateTimeLiteral {
                 .plusDays(days)
                 .plusHours(hours), getDataType().getScale());
         } catch (NumberFormatException e) {
-            return new NullLiteral(dataType);
+            throw new NotSupportedException("Invalid time format");
+        }
+    }
+
+    /**
+     * plusMinuteSecond
+     */
+    public Expression plusMinuteSecond(VarcharLiteral minuteSecond) {
+        String stringValue = minuteSecond.getStringValue().trim();
+
+        if (!stringValue.matches("[0-9\\-:\\s]+")) {
+            throw new NotSupportedException("Invalid time format");
+        }
+
+        String[] split = stringValue.split(":");
+        if (split.length != 2) {
+            throw new NotSupportedException("Invalid time format");
+        }
+
+        String minute = split[0].trim();
+        String second = split[1].trim();
+
+        try {
+            long minutes = Long.parseLong(minute);
+            boolean minutePositive = minutes >= 0;
+
+            long seconds = Long.parseLong(second);
+
+            if (minutePositive) {
+                seconds = Math.abs(seconds);
+            } else {
+                seconds = -Math.abs(seconds);
+            }
+
+            return fromJavaDateType(toJavaDateType()
+                .plusMinutes(minutes)
+                .plusSeconds(seconds), getDataType().getScale());
+        } catch (NumberFormatException e) {
+            throw new NotSupportedException("Invalid time format");
         }
     }
 
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/Interval.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/Interval.java
index eb98ceb48c1..28de8fc3e7b 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/Interval.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/Interval.java
@@ -83,6 +83,7 @@ public class Interval extends Expression implements 
UnaryExpression, AlwaysNotNu
      * Supported time unit.
      */
     public enum TimeUnit {
+        MINUTE_SECOND("MINUTE_SECOND", false, 1100),
         DAY_HOUR("DAY_HOUR", false, 1000),
         DAY_SECOND("DAY_SECOND", false, 900),
         YEAR("YEAR", false, 800),
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 ecc9706702c..1999161c61e 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
@@ -348,6 +348,7 @@ import 
org.apache.doris.nereids.trees.expressions.functions.scalar.MilliSecondsS
 import org.apache.doris.nereids.trees.expressions.functions.scalar.Minute;
 import org.apache.doris.nereids.trees.expressions.functions.scalar.MinuteCeil;
 import org.apache.doris.nereids.trees.expressions.functions.scalar.MinuteFloor;
+import 
org.apache.doris.nereids.trees.expressions.functions.scalar.MinuteSecondAdd;
 import org.apache.doris.nereids.trees.expressions.functions.scalar.MinutesAdd;
 import org.apache.doris.nereids.trees.expressions.functions.scalar.MinutesDiff;
 import org.apache.doris.nereids.trees.expressions.functions.scalar.MinutesSub;
@@ -1153,6 +1154,10 @@ public interface ScalarFunctionVisitor<R, C> {
         return visitScalarFunction(dayHourAdd, context);
     }
 
+    default R visitMinuteSecondAdd(MinuteSecondAdd minuteSecondAdd, C context) 
{
+        return visitScalarFunction(minuteSecondAdd, context);
+    }
+
     default R visitDaysAdd(DaysAdd daysAdd, C context) {
         return visitScalarFunction(daysAdd, context);
     }
diff --git 
a/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/expression/FoldConstantTest.java
 
b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/expression/FoldConstantTest.java
index 5e2fbbf09ea..a68a1eaedcf 100644
--- 
a/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/expression/FoldConstantTest.java
+++ 
b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/expression/FoldConstantTest.java
@@ -80,6 +80,7 @@ import 
org.apache.doris.nereids.trees.expressions.functions.scalar.Log10;
 import org.apache.doris.nereids.trees.expressions.functions.scalar.Log2;
 import 
org.apache.doris.nereids.trees.expressions.functions.scalar.MicroSecondsAdd;
 import 
org.apache.doris.nereids.trees.expressions.functions.scalar.MilliSecondsAdd;
+import 
org.apache.doris.nereids.trees.expressions.functions.scalar.MinuteSecondAdd;
 import org.apache.doris.nereids.trees.expressions.functions.scalar.MinutesAdd;
 import 
org.apache.doris.nereids.trees.expressions.functions.scalar.MonthsBetween;
 import org.apache.doris.nereids.trees.expressions.functions.scalar.NextDay;
@@ -450,6 +451,22 @@ class FoldConstantTest extends ExpressionRewriteTestHelper 
{
                 new VarcharLiteral("-1 -1"));
         rewritten = executor.rewrite(dayHourAdd, context);
         Assertions.assertEquals(dayHourAdd, rewritten);
+
+        MinuteSecondAdd minuteSecondAdd = new MinuteSecondAdd(
+                DateTimeV2Literal.fromJavaDateType(LocalDateTime.of(1, 1, 1, 
1, 1, 1), 0),
+                new VarcharLiteral("1:1"));
+        rewritten = executor.rewrite(minuteSecondAdd, context);
+        Assertions.assertEquals(new DateTimeV2Literal("0001-01-01 01:02:02"), 
rewritten);
+        // fail to fold, because the result is out of range
+        minuteSecondAdd = new MinuteSecondAdd(
+                    DateTimeV2Literal.fromJavaDateType(LocalDateTime.of(9999, 
12, 31, 23, 59, 1), 0),
+                    new VarcharLiteral("3:1"));
+        rewritten = executor.rewrite(minuteSecondAdd, context);
+        Assertions.assertEquals(minuteSecondAdd, rewritten);
+        minuteSecondAdd = new 
MinuteSecondAdd(DateTimeV2Literal.fromJavaDateType(LocalDateTime.of(0, 1, 1, 0, 
1, 1), 0),
+                new VarcharLiteral("-2:-1"));
+        rewritten = executor.rewrite(minuteSecondAdd, context);
+        Assertions.assertEquals(minuteSecondAdd, rewritten);
     }
 
     @Test
diff --git 
a/regression-test/data/query_p0/sql_functions/datetime_functions/test_dateadd_with_other_timeunit.out
 
b/regression-test/data/query_p0/sql_functions/datetime_functions/test_dateadd_with_other_timeunit.out
index 33be94a3355..cf0676a342f 100644
--- 
a/regression-test/data/query_p0/sql_functions/datetime_functions/test_dateadd_with_other_timeunit.out
+++ 
b/regression-test/data/query_p0/sql_functions/datetime_functions/test_dateadd_with_other_timeunit.out
@@ -33,21 +33,6 @@
 -- !sql --
 2025-10-27T22:58:59
 
--- !sql --
-\N
-
--- !sql --
-\N
-
--- !sql --
-\N
-
--- !sql --
-\N
-
--- !sql --
-\N
-
 -- !sql --
 2025-10-25T02:02:03.456700
 2025-10-30T11:10:10
@@ -112,3 +97,67 @@
 -- !sql --
 2025-10-27T14:00
 
+-- !sql --
+2025-10-24T01:03:04.456700
+2025-10-29T10:11:11
+
+-- !sql --
+2025-10-24T01:03:04.456700
+2025-10-29T10:11:11
+
+-- !sql --
+2025-10-23T23:58:59
+2025-10-28T23:58:59
+
+-- !sql --
+2025-10-23T23:58:59
+2025-10-28T23:58:59
+
+-- !sql --
+2025-10-29T10:11:11
+
+-- !sql --
+2025-10-29T10:11:11
+
+-- !sql --
+2025-10-29T10:11:20
+
+-- !sql --
+2025-10-29T10:11:20
+
+-- !sql --
+2025-10-29T10:09:09
+
+-- !sql --
+2025-10-29T10:09:09
+
+-- !sql --
+2025-10-29T10:09
+
+-- !sql --
+2025-10-29T10:09
+
+-- !sql --
+2025-10-29T00:01:01
+
+-- !sql --
+2025-10-29T00:01:01
+
+-- !sql --
+2025-10-29T00:01:10
+
+-- !sql --
+2025-10-29T00:01:10
+
+-- !sql --
+2025-10-28T23:58:59
+
+-- !sql --
+2025-10-28T23:58:59
+
+-- !sql --
+2025-10-28T23:58:50
+
+-- !sql --
+2025-10-28T23:58:50
+
diff --git 
a/regression-test/suites/query_p0/sql_functions/datetime_functions/test_dateadd_with_other_timeunit.groovy
 
b/regression-test/suites/query_p0/sql_functions/datetime_functions/test_dateadd_with_other_timeunit.groovy
index c05f9201fbb..d64ce939461 100644
--- 
a/regression-test/suites/query_p0/sql_functions/datetime_functions/test_dateadd_with_other_timeunit.groovy
+++ 
b/regression-test/suites/query_p0/sql_functions/datetime_functions/test_dateadd_with_other_timeunit.groovy
@@ -68,53 +68,48 @@ suite("test_dateadd_with_other_timeunit") {
     qt_sql """ select date_add("2025-10-29", INTERVAL "-1 -1:1:1" DAY_SECOND); 
"""
     qt_sql """ select date_add("2025-10-29", INTERVAL "-1 -1:-1:1" 
DAY_SECOND); """
     qt_sql """ select date_add("2025-10-29", INTERVAL "-1 -1:-1:-1" 
DAY_SECOND); """
-    qt_sql """ select date_add("2025-10-29 10:10:10", INTERVAL "-1 -1:1:1 43" 
DAY_SECOND); """
-    qt_sql """ select date_add("2025-10-29 10:10:10", INTERVAL "-1 -1:1:1xxx" 
DAY_SECOND); """
-    qt_sql """ select date_add("2025-10-29 10:10:10", INTERVAL "1 1:1:1.1234" 
DAY_SECOND); """
-    qt_sql """ select date_add("2025-10-29", INTERVAL "-1 -1:1:1 34" 
DAY_SECOND); """
-    qt_sql """ select date_add("2025-10-29", INTERVAL "-1 -1:1:1xx" 
DAY_SECOND); """
 
     test {
+        sql """ select date_add("2025-10-29 10:10:10", INTERVAL "-1 -1:1:1 43" 
DAY_SECOND); """
+        exception "Invalid time format"
+
+        sql """ select date_add("2025-10-29 10:10:10", INTERVAL "-1 -1:1:1xxx" 
DAY_SECOND); """
+        exception "Invalid time format"
+
+        sql """ select date_add("2025-10-29 10:10:10", INTERVAL "1 1:1:1.1234" 
DAY_SECOND); """
+        exception "Invalid time format"
+
+        sql """ select date_add("2025-10-29", INTERVAL "-1 -1:1:1 34" 
DAY_SECOND); """
+        exception "Invalid time format"
+
+        sql """ select date_add("2025-10-29", INTERVAL "-1 -1:1:1xx" 
DAY_SECOND); """
+        exception "Invalid time format"
+
         sql """ select date_add(test_datetime, INTERVAL '1' DAY_SECOND) result 
from ${tableName}; """
         exception "Invalid time format"
-    }
 
-    test {
         sql """ select date_add(test_datetime, INTERVAL '1 2' DAY_SECOND) 
result from ${tableName}; """
         exception "Invalid time format"
-    }
 
-    test {
         sql """ select date_add(test_datetime, INTERVAL '1 2:3' DAY_SECOND) 
result from ${tableName}; """
         exception "Invalid time format"
-    }
 
-    test {
         sql """ select date_add(test_datetime, INTERVAL '1 2:3:4.5678' 
DAY_SECOND) result from ${tableName}; """
         exception "Invalid seconds format"
-    }
 
-    test {
         sql """ select date_add(test_datetime, INTERVAL 'xx 00:00:01' 
DAY_SECOND) result from ${tableName}; """
         exception "Invalid days format"
-    }
 
-    test {
-        sql """ select date_add(test_datetime, INTERVAL '1 xx:00:01' 
DAY_SECOND) result from ${tableName}; """
+        sql """ select date_add(test_datetime, interval '1 xx:00:01' 
day_second) result from ${tableName}; """
         exception "Invalid hours format"
-    }
 
-    test {
         sql """ select date_add(test_datetime, INTERVAL '1 00:xx:01' 
DAY_SECOND) result from ${tableName}; """
         exception "Invalid minutes format"
-    }
 
-    test {
         sql """ select date_add(test_datetime, INTERVAL '1 00:00:xx' 
DAY_SECOND) result from ${tableName}; """
         exception "Invalid seconds format"
     }
 
-
     // DAY_HOUR
     testFoldConst """ select date_add("2025-10-29 10:10:10", INTERVAL "1 1" 
DAY_HOUR); """
     testFoldConst """ select date_add("2025-10-29 10:10:10", INTERVAL "1 -1" 
DAY_HOUR); """
@@ -157,18 +152,85 @@ suite("test_dateadd_with_other_timeunit") {
     qt_sql """ select date_add("2025-10-29", INTERVAL "-1 -10" DAY_HOUR); """
 
     test {
+        sql """ select date_add("2025-10-29 10:10:10", INTERVAL '1' DAY_HOUR) 
; """
+        exception "Invalid time format"
+
+        sql """ select date_add("2025-10-29 10:10:10", INTERVAL 'xx 10' 
DAY_HOUR) ; """
+        exception "Invalid time format"
+
+        sql """ select date_add("2025-10-29 10:10:10", INTERVAL '1 xx' 
DAY_HOUR) ; """
+        exception "Invalid time format"
+
         sql """ select date_add(test_datetime, INTERVAL '1' DAY_HOUR) result 
from ${tableName}; """
         exception "Invalid time format"
-    }
 
-    test {
         sql """ select date_add(test_datetime, INTERVAL 'xx 10' DAY_HOUR) 
result from ${tableName}; """
         exception "Invalid days format"
-    }
 
-    test {
         sql """ select date_add(test_datetime, INTERVAL '1 xx' DAY_HOUR) 
result from ${tableName}; """
         exception "Invalid hours format"
     }
 
+
+    // MINUTE_SECOND
+    testFoldConst """ select date_add("2025-10-29 10:10:10", INTERVAL "1:1" 
MINUTE_SECOND); """
+    testFoldConst """ select date_add("2025-10-29 10:10:10", INTERVAL "1:-1" 
MINUTE_SECOND); """
+    testFoldConst """ select date_add("2025-10-29 10:10:10", INTERVAL "1:10" 
MINUTE_SECOND); """
+    testFoldConst """ select date_add("2025-10-29 10:10:10", INTERVAL "1:-10" 
MINUTE_SECOND); """
+    testFoldConst """ select date_add("2025-10-29 10:10:10", INTERVAL "-1:1" 
MINUTE_SECOND); """
+    testFoldConst """ select date_add("2025-10-29 10:10:10", INTERVAL "-1:-1" 
MINUTE_SECOND); """
+    testFoldConst """ select date_add("2025-10-29 10:10:10", INTERVAL "-1:10" 
MINUTE_SECOND); """
+    testFoldConst """ select date_add("2025-10-29 10:10:10", INTERVAL "-1:-10" 
MINUTE_SECOND); """
+    testFoldConst """ select date_add("2025-10-29", INTERVAL "1:1" 
MINUTE_SECOND); """
+    testFoldConst """ select date_add("2025-10-29", INTERVAL "1:-1" 
MINUTE_SECOND); """
+    testFoldConst """ select date_add("2025-10-29", INTERVAL "1:10" 
MINUTE_SECOND); """
+    testFoldConst """ select date_add("2025-10-29", INTERVAL "1:-10" 
MINUTE_SECOND); """
+    testFoldConst """ select date_add("2025-10-29", INTERVAL "-1:1" 
MINUTE_SECOND); """
+    testFoldConst """ select date_add("2025-10-29", INTERVAL "-1:-1" 
MINUTE_SECOND); """
+    testFoldConst """ select date_add("2025-10-29", INTERVAL "-1:10" 
MINUTE_SECOND); """
+    testFoldConst """ select date_add("2025-10-29", INTERVAL "-1:-10" 
MINUTE_SECOND); """
+
+    qt_sql """ select date_add(test_datetime, INTERVAL "1:1" MINUTE_SECOND) 
result from ${tableName}; """
+    qt_sql """ select date_add(test_datetime, INTERVAL "1:1" MINUTE_SECOND) 
result from ${tableName}; """
+
+    qt_sql """ select date_add(test_date, INTERVAL "-1:1" MINUTE_SECOND) 
result from ${tableName}; """
+    qt_sql """ select date_add(test_date, INTERVAL "-1:-1" MINUTE_SECOND) 
result from ${tableName}; """
+
+    qt_sql """ select date_add("2025-10-29 10:10:10", INTERVAL "1:1" 
MINUTE_SECOND); """
+    qt_sql """ select date_add("2025-10-29 10:10:10", INTERVAL "1:-1" 
MINUTE_SECOND); """
+    qt_sql """ select date_add("2025-10-29 10:10:10", INTERVAL "1:10" 
MINUTE_SECOND); """
+    qt_sql """ select date_add("2025-10-29 10:10:10", INTERVAL "1:-10" 
MINUTE_SECOND); """
+    qt_sql """ select date_add("2025-10-29 10:10:10", INTERVAL "-1:1" 
MINUTE_SECOND); """
+    qt_sql """ select date_add("2025-10-29 10:10:10", INTERVAL "-1:-1" 
MINUTE_SECOND); """
+    qt_sql """ select date_add("2025-10-29 10:10:10", INTERVAL "-1:10" 
MINUTE_SECOND); """
+    qt_sql """ select date_add("2025-10-29 10:10:10", INTERVAL "-1:-10" 
MINUTE_SECOND); """
+    qt_sql """ select date_add("2025-10-29", INTERVAL "1:1" MINUTE_SECOND); """
+    qt_sql """ select date_add("2025-10-29", INTERVAL "1:-1" MINUTE_SECOND); 
"""
+    qt_sql """ select date_add("2025-10-29", INTERVAL "1:10" MINUTE_SECOND); 
"""
+    qt_sql """ select date_add("2025-10-29", INTERVAL "1:-10" MINUTE_SECOND); 
"""
+    qt_sql """ select date_add("2025-10-29", INTERVAL "-1:1" MINUTE_SECOND); 
"""
+    qt_sql """ select date_add("2025-10-29", INTERVAL "-1:-1" MINUTE_SECOND); 
"""
+    qt_sql """ select date_add("2025-10-29", INTERVAL "-1:10" MINUTE_SECOND); 
"""
+    qt_sql """ select date_add("2025-10-29", INTERVAL "-1:-10" MINUTE_SECOND); 
"""
+
+    test {
+        sql """ select date_add("2025-10-29 10:10:10", INTERVAL '1' 
MINUTE_SECOND) ; """
+        exception "Invalid time format"
+
+        sql """ select date_add("2025-10-29 10:10:10", INTERVAL 'xx:10' 
MINUTE_SECOND) ; """
+        exception "Invalid time format"
+
+        sql """ select date_add("2025-10-29 10:10:10", INTERVAL '1:xx' 
MINUTE_SECOND) ; """
+        exception "Invalid time format"
+
+        sql """ select date_add(test_datetime, INTERVAL '1' MINUTE_SECOND) 
result from ${tableName}; """
+        exception "Invalid time format"
+
+        sql """ select date_add(test_datetime, INTERVAL 'xx:10' MINUTE_SECOND) 
result from ${tableName}; """
+        exception "Invalid minutes format"
+
+        sql """ select date_add(test_datetime, INTERVAL '1:xx' MINUTE_SECOND) 
result from ${tableName}; """
+        exception "Invalid seconds format"
+    }
+
 }


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]


Reply via email to