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

morrysnow 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 469b6b8466 [enhancement](Nereids) datetime v2 type precision derive 
(#17079)
469b6b8466 is described below

commit 469b6b846682105f6cc8b5510e2896fbf5e6b232
Author: morrySnow <[email protected]>
AuthorDate: Sun Feb 26 22:33:55 2023 +0800

    [enhancement](Nereids) datetime v2 type precision derive (#17079)
---
 .../trees/expressions/TimestampArithmetic.java     |  26 +--
 .../expressions/functions/ComputeSignature.java    |  18 +-
 .../trees/expressions/literal/DateLiteral.java     |  56 ++++--
 .../trees/expressions/literal/DateTimeLiteral.java | 200 ++++++++++++++++-----
 .../expressions/literal/DateTimeV2Literal.java     |  59 +++---
 .../trees/expressions/literal/DateV2Literal.java   |  15 +-
 .../apache/doris/nereids/types/DateTimeV2Type.java |   1 +
 .../org/apache/doris/nereids/util/DateUtils.java   |  86 +++++----
 .../doris/nereids/util/TypeCoercionUtils.java      |  12 +-
 .../expression/rewrite/ExpressionRewriteTest.java  |   4 +-
 .../test_timestamp_arithmetic.out                  |   4 +
 .../test_timestamp_arithmetic.groovy               |  32 ++++
 12 files changed, 371 insertions(+), 142 deletions(-)

diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/TimestampArithmetic.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/TimestampArithmetic.java
index b0c0a19b8f..1da77201c9 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/TimestampArithmetic.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/TimestampArithmetic.java
@@ -25,12 +25,11 @@ import 
org.apache.doris.nereids.trees.expressions.shape.BinaryExpression;
 import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor;
 import org.apache.doris.nereids.types.DataType;
 import org.apache.doris.nereids.types.DateTimeType;
+import org.apache.doris.nereids.types.DateTimeV2Type;
 import org.apache.doris.nereids.types.DateType;
-import org.apache.doris.nereids.types.IntegerType;
-import org.apache.doris.nereids.types.coercion.AbstractDataType;
+import org.apache.doris.nereids.types.DateV2Type;
 
 import com.google.common.base.Preconditions;
-import com.google.common.collect.ImmutableList;
 
 import java.util.List;
 import java.util.Objects;
@@ -44,15 +43,6 @@ import java.util.Objects;
  */
 public class TimestampArithmetic extends Expression implements 
BinaryExpression, PropagateNullable {
 
-    //the size and order of EXPECTED_INPUT_TYPES must follow the function 
signature parameters
-    //For example: days_sub('2000-01-01', interval 5 days),
-    // '2000-01-01'->DateTimeType.INSTANCE
-    // 5 -> IntegerType
-    private static final List<AbstractDataType> EXPECTED_INPUT_TYPES = 
ImmutableList.of(
-            DateTimeType.INSTANCE,
-            IntegerType.INSTANCE
-    );
-
     private final String funcName;
     private final boolean intervalFirst;
     private final Operator op;
@@ -98,7 +88,17 @@ public class TimestampArithmetic extends Expression 
implements BinaryExpression,
         if (intervalFirst) {
             dateChildIndex = 1;
         }
-        if (child(dateChildIndex).getDataType() instanceof DateTimeType || 
timeUnit.isDateTimeUnit()) {
+        DataType childType = child(dateChildIndex).getDataType();
+        if (childType instanceof DateTimeV2Type) {
+            return childType;
+        }
+        if (childType instanceof DateV2Type) {
+            if (timeUnit.isDateTimeUnit()) {
+                return DateTimeV2Type.SYSTEM_DEFAULT;
+            }
+            return DateV2Type.INSTANCE;
+        }
+        if (childType instanceof DateTimeType || timeUnit.isDateTimeUnit()) {
             return DateTimeType.INSTANCE;
         } else {
             return DateType.INSTANCE;
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/ComputeSignature.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/ComputeSignature.java
index 93d6d74928..5ed35349d1 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/ComputeSignature.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/ComputeSignature.java
@@ -19,9 +19,11 @@ package org.apache.doris.nereids.trees.expressions.functions;
 
 import org.apache.doris.catalog.FunctionSignature;
 import org.apache.doris.nereids.annotation.Developing;
+import org.apache.doris.nereids.trees.expressions.Expression;
 import 
org.apache.doris.nereids.trees.expressions.functions.ComputeSignatureHelper.ComputeSignatureChain;
 import 
org.apache.doris.nereids.trees.expressions.typecoercion.ImplicitCastInputTypes;
 import org.apache.doris.nereids.types.DataType;
+import org.apache.doris.nereids.types.DateTimeV2Type;
 import org.apache.doris.nereids.types.coercion.AbstractDataType;
 
 import com.google.common.collect.ImmutableList;
@@ -88,7 +90,21 @@ public interface ComputeSignature extends FunctionTrait, 
ImplicitCastInputTypes
      */
     @Override
     default DataType getDataType() {
-        return (DataType) getSignature().returnType;
+        DataType returnType = (DataType) getSignature().returnType;
+
+        // datetime v2 type precision derive
+        if (returnType instanceof DateTimeV2Type) {
+            for (Expression argument : getArguments()) {
+                if (argument.getDataType() instanceof DateTimeV2Type) {
+                    DateTimeV2Type argType = (DateTimeV2Type) 
argument.getDataType();
+                    if (((DateTimeV2Type) returnType).getScale() < 
argType.getScale()) {
+                        returnType = argType;
+                    }
+                }
+            }
+        }
+
+        return returnType;
     }
 
     @Override
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/DateLiteral.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/DateLiteral.java
index e7ff6d9327..a56ce591d3 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/DateLiteral.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/DateLiteral.java
@@ -28,8 +28,12 @@ import org.apache.doris.nereids.util.DateUtils;
 
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
-import org.joda.time.LocalDateTime;
-import org.joda.time.format.DateTimeFormatter;
+
+import java.time.LocalDateTime;
+import java.time.Year;
+import java.time.format.DateTimeFormatter;
+import java.time.temporal.ChronoField;
+import java.time.temporal.TemporalAccessor;
 
 /**
  * Date literal in Nereids.
@@ -41,6 +45,10 @@ public class DateLiteral extends Literal {
     protected static DateTimeFormatter DATEKEY_FORMATTER = null;
 
     private static final Logger LOG = LogManager.getLogger(DateLiteral.class);
+
+    private static final DateLiteral MIN_DATE = new DateLiteral(0000, 1, 1);
+    private static final DateLiteral MAX_DATE = new DateLiteral(9999, 12, 31);
+    private static final int[] DAYS_IN_MONTH = new int[] {0, 31, 28, 31, 30, 
31, 30, 31, 31, 30, 31, 30, 31};
     private static final int DATEKEY_LENGTH = 8;
 
     protected long year;
@@ -100,20 +108,38 @@ public class DateLiteral extends Literal {
 
     protected void init(String s) throws AnalysisException {
         try {
-            LocalDateTime dateTime;
+            TemporalAccessor dateTime;
             if (s.split("-")[0].length() == 2) {
-                dateTime = DATE_FORMATTER_TWO_DIGIT.parseLocalDateTime(s);
+                dateTime = DATE_FORMATTER_TWO_DIGIT.parse(s);
             } else if (s.length() == DATEKEY_LENGTH && !s.contains("-")) {
-                dateTime = DATEKEY_FORMATTER.parseLocalDateTime(s);
+                dateTime = DATEKEY_FORMATTER.parse(s);
             } else {
-                dateTime = DATE_FORMATTER.parseLocalDateTime(s);
+                dateTime = DATE_FORMATTER.parse(s);
             }
-            year = dateTime.getYear();
-            month = dateTime.getMonthOfYear();
-            day = dateTime.getDayOfMonth();
+            year = DateUtils.getOrDefault(dateTime, ChronoField.YEAR);
+            month = DateUtils.getOrDefault(dateTime, 
ChronoField.MONTH_OF_YEAR);
+            day = DateUtils.getOrDefault(dateTime, ChronoField.DAY_OF_MONTH);
         } catch (Exception ex) {
             throw new AnalysisException("date literal [" + s + "] is invalid");
         }
+
+        if (checkRange() || checkDate()) {
+            throw new AnalysisException("date literal [" + s + "] is out of 
range");
+        }
+    }
+
+    protected boolean checkRange() {
+        return year > MAX_DATE.getYear() || month > MAX_DATE.getMonth() || day 
> MAX_DATE.getDay();
+    }
+
+    protected boolean checkDate() {
+        if (month != 0 && day > DAYS_IN_MONTH[((int) month)]) {
+            if (month == 2 && day == 29 && Year.isLeap(year)) {
+                return false;
+            }
+            return true;
+        }
+        return false;
     }
 
     @Override
@@ -159,18 +185,18 @@ public class DateLiteral extends Literal {
     }
 
     public DateLiteral plusDays(int days) {
-        LocalDateTime dateTime = LocalDateTime.parse(getStringValue(), 
DATE_FORMATTER).plusDays(days);
-        return new DateLiteral(dateTime.getYear(), dateTime.getMonthOfYear(), 
dateTime.getDayOfMonth());
+        LocalDateTime dateTime = DateUtils.getTime(DATE_FORMATTER, 
getStringValue()).plusDays(days);
+        return new DateLiteral(dateTime.getYear(), dateTime.getMonthValue(), 
dateTime.getDayOfMonth());
     }
 
     public DateLiteral plusMonths(int months) {
-        LocalDateTime dateTime = LocalDateTime.parse(getStringValue(), 
DATE_FORMATTER).plusMonths(months);
-        return new DateLiteral(dateTime.getYear(), dateTime.getMonthOfYear(), 
dateTime.getDayOfMonth());
+        LocalDateTime dateTime = DateUtils.getTime(DATE_FORMATTER, 
getStringValue()).plusMonths(months);
+        return new DateLiteral(dateTime.getYear(), dateTime.getMonthValue(), 
dateTime.getDayOfMonth());
     }
 
     public DateLiteral plusYears(int years) {
-        LocalDateTime dateTime = LocalDateTime.parse(getStringValue(), 
DATE_FORMATTER).plusYears(years);
-        return new DateLiteral(dateTime.getYear(), dateTime.getMonthOfYear(), 
dateTime.getDayOfMonth());
+        LocalDateTime dateTime = DateUtils.getTime(DATE_FORMATTER, 
getStringValue()).plusYears(years);
+        return new DateLiteral(dateTime.getYear(), dateTime.getMonthValue(), 
dateTime.getDayOfMonth());
     }
 }
 
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/DateTimeLiteral.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/DateTimeLiteral.java
index a2211d5c8f..a0a9abbd81 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/DateTimeLiteral.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/DateTimeLiteral.java
@@ -25,11 +25,19 @@ import org.apache.doris.nereids.types.DateTimeType;
 import org.apache.doris.nereids.types.coercion.DateLikeType;
 import org.apache.doris.nereids.util.DateUtils;
 
+import com.google.common.collect.Lists;
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
-import org.joda.time.LocalDateTime;
-import org.joda.time.format.DateTimeFormatter;
 
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import java.time.format.DateTimeFormatterBuilder;
+import java.time.format.DateTimeParseException;
+import java.time.format.ResolverStyle;
+import java.time.temporal.ChronoField;
+import java.time.temporal.TemporalAccessor;
+import java.util.Collections;
+import java.util.List;
 import java.util.Objects;
 
 /**
@@ -37,20 +45,24 @@ import java.util.Objects;
  */
 public class DateTimeLiteral extends DateLiteral {
 
-    protected static final int DATETIME_TO_MINUTE_STRING_LENGTH = 16;
-    protected static final int DATETIME_TO_HOUR_STRING_LENGTH = 13;
-    protected static final int DATETIME_DEFAULT_STRING_LENGTH = 10;
-    protected static DateTimeFormatter DATE_TIME_DEFAULT_FORMATTER = null;
     protected static DateTimeFormatter DATE_TIME_FORMATTER = null;
     protected static DateTimeFormatter DATE_TIME_FORMATTER_TO_HOUR = null;
     protected static DateTimeFormatter DATE_TIME_FORMATTER_TO_MINUTE = null;
     protected static DateTimeFormatter DATE_TIME_FORMATTER_TWO_DIGIT = null;
+    protected static DateTimeFormatter DATETIMEKEY_FORMATTER = null;
+    protected static DateTimeFormatter DATE_TIME_FORMATTER_TO_MICRO_SECOND = 
null;
+    protected static List<DateTimeFormatter> formatterList = null;
+
+    private static final DateTimeLiteral MIN_DATETIME = new 
DateTimeLiteral(0000, 1, 1, 0, 0, 0);
+    private static final DateTimeLiteral MAX_DATETIME = new 
DateTimeLiteral(9999, 12, 31, 23, 59, 59);
+    private static final int MAX_MICROSECOND = 999999;
 
     private static final Logger LOG = 
LogManager.getLogger(DateTimeLiteral.class);
 
     protected long hour;
     protected long minute;
     protected long second;
+    protected long microSecond;
 
     static {
         try {
@@ -58,7 +70,24 @@ public class DateTimeLiteral extends DateLiteral {
             DATE_TIME_FORMATTER_TO_HOUR = DateUtils.formatBuilder("%Y-%m-%d 
%H").toFormatter();
             DATE_TIME_FORMATTER_TO_MINUTE = DateUtils.formatBuilder("%Y-%m-%d 
%H:%i").toFormatter();
             DATE_TIME_FORMATTER_TWO_DIGIT = DateUtils.formatBuilder("%y-%m-%d 
%H:%i:%s").toFormatter();
-            DATE_TIME_DEFAULT_FORMATTER = 
DateUtils.formatBuilder("%Y-%m-%d").toFormatter();
+
+            DATETIMEKEY_FORMATTER = 
DateUtils.formatBuilder("%Y%m%d%H%i%s").toFormatter();
+
+            DATE_TIME_FORMATTER_TO_MICRO_SECOND = new 
DateTimeFormatterBuilder()
+                    .appendPattern("uuuu-MM-dd HH:mm:ss")
+                    .appendFraction(ChronoField.MICRO_OF_SECOND, 0, 6, true)
+                    .toFormatter();
+
+            formatterList = Lists.newArrayList(
+                    
DateUtils.formatBuilder("%Y%m%d").appendLiteral('T').appendPattern("HHmmss")
+                            .appendFraction(ChronoField.MICRO_OF_SECOND, 0, 6, 
true).toFormatter(),
+                    
DateUtils.formatBuilder("%Y%m%d").appendLiteral('T').appendPattern("HHmmss")
+                            .appendFraction(ChronoField.MICRO_OF_SECOND, 0, 6, 
false).toFormatter(),
+                    DateUtils.formatBuilder("%Y%m%d%H%i%s")
+                            .appendFraction(ChronoField.MICRO_OF_SECOND, 0, 6, 
true).toFormatter(),
+                    DateUtils.formatBuilder("%Y%m%d%H%i%s")
+                            .appendFraction(ChronoField.MICRO_OF_SECOND, 0, 6, 
false).toFormatter(),
+                    DATETIMEKEY_FORMATTER, DATEKEY_FORMATTER);
         } catch (AnalysisException e) {
             LOG.error("invalid date format", e);
             System.exit(-1);
@@ -86,10 +115,19 @@ public class DateTimeLiteral extends DateLiteral {
      */
     public DateTimeLiteral(DateLikeType dataType, long year, long month, long 
day,
             long hour, long minute, long second) {
+        this(dataType, year, month, day, hour, minute, second, 0L);
+    }
+
+    /**
+     * C'tor data time literal.
+     */
+    public DateTimeLiteral(DateLikeType dataType, long year, long month, long 
day,
+            long hour, long minute, long second, long microSecond) {
         super(dataType);
         this.hour = hour;
         this.minute = minute;
         this.second = second;
+        this.microSecond = microSecond;
         this.year = year;
         this.month = month;
         this.day = day;
@@ -98,29 +136,105 @@ public class DateTimeLiteral extends DateLiteral {
     @Override
     protected void init(String s) throws AnalysisException {
         try {
-            LocalDateTime dateTime;
-            if (s.split("-")[0].length() == 2) {
-                dateTime = DATE_TIME_FORMATTER_TWO_DIGIT.parseLocalDateTime(s);
+            TemporalAccessor dateTime = null;
+            if (!s.contains("-")) {
+                // handle format like 20210106, but should not handle 2021-1-6
+                boolean parsed = false;
+                for (DateTimeFormatter formatter : formatterList) {
+                    try {
+                        dateTime = formatter.parse(s);
+                        parsed = true;
+                        break;
+                    } catch (DateTimeParseException ex) {
+                        // ignore
+                    }
+                }
+                if (!parsed) {
+                    throw new AnalysisException("datetime literal [" + s + "] 
is invalid");
+                }
             } else {
-                if (s.length() == DATETIME_TO_MINUTE_STRING_LENGTH) {
-                    dateTime = 
DATE_TIME_FORMATTER_TO_MINUTE.parseLocalDateTime(s);
-                } else if (s.length() == DATETIME_TO_HOUR_STRING_LENGTH) {
-                    dateTime = 
DATE_TIME_FORMATTER_TO_HOUR.parseLocalDateTime(s);
-                } else if (s.length() == DATETIME_DEFAULT_STRING_LENGTH) {
-                    dateTime = 
DATE_TIME_DEFAULT_FORMATTER.parseLocalDateTime(s);
-                } else {
-                    dateTime = DATE_TIME_FORMATTER.parseLocalDateTime(s);
+                String[] datePart = s.contains(" ") ? s.split(" 
")[0].split("-") : s.split("-");
+                DateTimeFormatterBuilder builder = new 
DateTimeFormatterBuilder();
+                if (datePart.length != 3) {
+                    throw new AnalysisException("datetime literal [" + s + "] 
is invalid");
+                }
+                for (int i = 0; i < datePart.length; i++) {
+                    switch (i) {
+                        case 0:
+                            if (datePart[i].length() == 2) {
+                                // If year is represented by two digits, 
number bigger than 70 will be prefixed
+                                // with 19 otherwise 20. e.g. 69 -> 2069, 70 
-> 1970.
+                                builder.appendValueReduced(ChronoField.YEAR, 
2, 2, 1970);
+                            } else {
+                                builder.appendPattern(String.join("", 
Collections.nCopies(datePart[i].length(), "u")));
+                            }
+                            break;
+                        case 1:
+                            builder.appendPattern(String.join("", 
Collections.nCopies(datePart[i].length(), "M")));
+                            break;
+                        case 2:
+                            builder.appendPattern(String.join("", 
Collections.nCopies(datePart[i].length(), "d")));
+                            break;
+                        default:
+                            throw new AnalysisException("two many parts in 
date format " + s);
+                    }
+                    if (i < datePart.length - 1) {
+                        builder.appendLiteral("-");
+                    }
+                }
+                if (s.contains(" ")) {
+                    builder.appendLiteral(" ");
                 }
+                String[] timePart = s.contains(" ") ? s.split(" 
")[1].split(":") : new String[]{};
+                for (int i = 0; i < timePart.length; i++) {
+                    switch (i) {
+                        case 0:
+                            builder.appendPattern(String.join("", 
Collections.nCopies(timePart[i].length(), "H")));
+                            break;
+                        case 1:
+                            builder.appendPattern(String.join("", 
Collections.nCopies(timePart[i].length(), "m")));
+                            break;
+                        case 2:
+                            builder.appendPattern(String.join("", 
Collections.nCopies(timePart[i].contains(".")
+                                    ? timePart[i].split("\\.")[0].length() : 
timePart[i].length(), "s")));
+                            if (timePart[i].contains(".")) {
+                                
builder.appendFraction(ChronoField.MICRO_OF_SECOND, 0, 6, true);
+                            }
+                            break;
+                        default:
+                            throw new AnalysisException("too many parts in 
time format " + s);
+                    }
+                    if (i < timePart.length - 1) {
+                        builder.appendLiteral(":");
+                    }
+                }
+                // The default resolver style is 'SMART', which parses 
"2022-06-31" as "2022-06-30"
+                // and does not throw an exception. 'STRICT' is used here.
+                DateTimeFormatter formatter = 
builder.toFormatter().withResolverStyle(ResolverStyle.STRICT);
+                dateTime = formatter.parse(s);
             }
-            year = dateTime.getYear();
-            month = dateTime.getMonthOfYear();
-            day = dateTime.getDayOfMonth();
-            hour = dateTime.getHourOfDay();
-            minute = dateTime.getMinuteOfHour();
-            second = dateTime.getSecondOfMinute();
+
+            year = DateUtils.getOrDefault(dateTime, ChronoField.YEAR);
+            month = DateUtils.getOrDefault(dateTime, 
ChronoField.MONTH_OF_YEAR);
+            day = DateUtils.getOrDefault(dateTime, ChronoField.DAY_OF_MONTH);
+            hour = DateUtils.getOrDefault(dateTime, ChronoField.HOUR_OF_DAY);
+            minute = DateUtils.getOrDefault(dateTime, 
ChronoField.MINUTE_OF_HOUR);
+            second = DateUtils.getOrDefault(dateTime, 
ChronoField.SECOND_OF_MINUTE);
+            microSecond = DateUtils.getOrDefault(dateTime, 
ChronoField.MICRO_OF_SECOND);
+
         } catch (Exception ex) {
-            throw new AnalysisException("date time literal [" + s + "] is 
invalid");
+            throw new AnalysisException("datetime literal [" + s + "] is 
invalid");
         }
+
+        if (checkRange() || checkDate()) {
+            throw new AnalysisException("datetime literal [" + s + "] is out 
of range");
+        }
+    }
+
+    @Override
+    protected boolean checkRange() {
+        return super.checkRange() || hour > MAX_DATETIME.getHour() || minute > 
MAX_DATETIME.getMinute()
+                || second > MAX_DATETIME.getSecond() || microSecond > 
MAX_MICROSECOND;
     }
 
     @Override
@@ -154,39 +268,39 @@ public class DateTimeLiteral extends DateLiteral {
     }
 
     public DateTimeLiteral plusDays(int days) {
-        LocalDateTime d = LocalDateTime.parse(getStringValue(), 
DATE_TIME_FORMATTER).plusDays(days);
-        return new DateTimeLiteral(d.getYear(), d.getMonthOfYear(), 
d.getDayOfMonth(),
-                d.getHourOfDay(), d.getMinuteOfHour(), d.getSecondOfMinute());
+        LocalDateTime d = DateUtils.getTime(DATE_TIME_FORMATTER, 
getStringValue()).plusDays(days);
+        return new DateTimeLiteral(d.getYear(), d.getMonthValue(), 
d.getDayOfMonth(),
+                d.getHour(), d.getMinute(), d.getSecond());
     }
 
     public DateTimeLiteral plusYears(int years) {
-        LocalDateTime d = LocalDateTime.parse(getStringValue(), 
DATE_TIME_FORMATTER).plusYears(years);
-        return new DateTimeLiteral(d.getYear(), d.getMonthOfYear(), 
d.getDayOfMonth(),
-                d.getHourOfDay(), d.getMinuteOfHour(), d.getSecondOfMinute());
+        LocalDateTime d = DateUtils.getTime(DATE_TIME_FORMATTER, 
getStringValue()).plusYears(years);
+        return new DateTimeLiteral(d.getYear(), d.getMonthValue(), 
d.getDayOfMonth(),
+                d.getHour(), d.getMinute(), d.getSecond());
     }
 
     public DateTimeLiteral plusMonths(int months) {
-        LocalDateTime d = LocalDateTime.parse(getStringValue(), 
DATE_TIME_FORMATTER).plusMonths(months);
-        return new DateTimeLiteral(d.getYear(), d.getMonthOfYear(), 
d.getDayOfMonth(),
-                d.getHourOfDay(), d.getMinuteOfHour(), d.getSecondOfMinute());
+        LocalDateTime d = DateUtils.getTime(DATE_TIME_FORMATTER, 
getStringValue()).plusMonths(months);
+        return new DateTimeLiteral(d.getYear(), d.getMonthValue(), 
d.getDayOfMonth(),
+                d.getHour(), d.getMinute(), d.getSecond());
     }
 
     public DateTimeLiteral plusHours(int hours) {
-        LocalDateTime d = LocalDateTime.parse(getStringValue(), 
DATE_TIME_FORMATTER).plusHours(hours);
-        return new DateTimeLiteral(d.getYear(), d.getMonthOfYear(), 
d.getDayOfMonth(),
-                d.getHourOfDay(), d.getMinuteOfHour(), d.getSecondOfMinute());
+        LocalDateTime d = DateUtils.getTime(DATE_TIME_FORMATTER, 
getStringValue()).plusHours(hours);
+        return new DateTimeLiteral(d.getYear(), d.getMonthValue(), 
d.getDayOfMonth(),
+                d.getHour(), d.getMinute(), d.getSecond());
     }
 
     public DateTimeLiteral plusMinutes(int minutes) {
-        LocalDateTime d = LocalDateTime.parse(getStringValue(), 
DATE_TIME_FORMATTER).plusMinutes(minutes);
-        return new DateTimeLiteral(d.getYear(), d.getMonthOfYear(), 
d.getDayOfMonth(),
-                d.getHourOfDay(), d.getMinuteOfHour(), d.getSecondOfMinute());
+        LocalDateTime d = DateUtils.getTime(DATE_TIME_FORMATTER, 
getStringValue()).plusMinutes(minutes);
+        return new DateTimeLiteral(d.getYear(), d.getMonthValue(), 
d.getDayOfMonth(),
+                d.getHour(), d.getMinute(), d.getSecond());
     }
 
     public DateTimeLiteral plusSeconds(int seconds) {
-        LocalDateTime d = LocalDateTime.parse(getStringValue(), 
DATE_TIME_FORMATTER).plusSeconds(seconds);
-        return new DateTimeLiteral(d.getYear(), d.getMonthOfYear(), 
d.getDayOfMonth(),
-                d.getHourOfDay(), d.getMinuteOfHour(), d.getSecondOfMinute());
+        LocalDateTime d = DateUtils.getTime(DATE_TIME_FORMATTER, 
getStringValue()).plusSeconds(seconds);
+        return new DateTimeLiteral(d.getYear(), d.getMonthValue(), 
d.getDayOfMonth(),
+                d.getHour(), d.getMinute(), d.getSecond());
     }
 
     public long getHour() {
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 b611016c93..1ddfef835e 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,8 +19,9 @@ package org.apache.doris.nereids.trees.expressions.literal;
 
 import org.apache.doris.nereids.exceptions.UnboundException;
 import org.apache.doris.nereids.types.DateTimeV2Type;
+import org.apache.doris.nereids.util.DateUtils;
 
-import org.joda.time.LocalDateTime;
+import java.time.LocalDateTime;
 
 /**
  * date time v2 literal for nereids
@@ -28,16 +29,16 @@ import org.joda.time.LocalDateTime;
 public class DateTimeV2Literal extends DateTimeLiteral {
 
     public DateTimeV2Literal(String s) {
-        super(DateTimeV2Type.SYSTEM_DEFAULT, s);
+        super(DateTimeV2Type.MAX, s);
     }
 
-    public DateTimeV2Literal(long year, long month, long day, long hour, long 
minute, long second) {
-        super(DateTimeV2Type.SYSTEM_DEFAULT, year, month, day, hour, minute, 
second);
+    public DateTimeV2Literal(long year, long month, long day, long hour, long 
minute, long second, long microSecond) {
+        super(DateTimeV2Type.SYSTEM_DEFAULT, year, month, day, hour, minute, 
second, microSecond);
     }
 
     public DateTimeV2Literal(DateTimeV2Type dataType,
-            long year, long month, long day, long hour, long minute, long 
second) {
-        super(dataType, year, month, day, hour, minute, second);
+            long year, long month, long day, long hour, long minute, long 
second, long microSecond) {
+        super(dataType, year, month, day, hour, minute, second, microSecond);
     }
 
     @Override
@@ -45,45 +46,55 @@ public class DateTimeV2Literal extends DateTimeLiteral {
         return (DateTimeV2Type) super.getDataType();
     }
 
+    @Override
+    public String toString() {
+        return String.format("%04d-%02d-%02d %02d:%02d:%02d.%06d", year, 
month, day, hour, minute, second, microSecond);
+    }
+
+    @Override
+    public String getStringValue() {
+        return String.format("%04d-%02d-%02d %02d:%02d:%02d.%06d", year, 
month, day, hour, minute, second, microSecond);
+    }
+
     @Override
     public DateTimeV2Literal plusYears(int years) {
-        LocalDateTime d = LocalDateTime.parse(getStringValue(), 
DATE_TIME_FORMATTER).plusYears(years);
-        return new DateTimeV2Literal(this.getDataType(), d.getYear(), 
d.getMonthOfYear(), d.getDayOfMonth(),
-                d.getHourOfDay(), d.getMinuteOfHour(), d.getSecondOfMinute());
+        LocalDateTime d = 
DateUtils.getTime(DATE_TIME_FORMATTER_TO_MICRO_SECOND, 
getStringValue()).plusYears(years);
+        return new DateTimeV2Literal(this.getDataType(), d.getYear(), 
d.getMonthValue(), d.getDayOfMonth(),
+                d.getHour(), d.getMinute(), d.getSecond(), d.getNano() / 
1000L);
     }
 
     @Override
     public DateTimeV2Literal plusMonths(int months) {
-        LocalDateTime d = LocalDateTime.parse(getStringValue(), 
DATE_TIME_FORMATTER).plusMonths(months);
-        return new DateTimeV2Literal(this.getDataType(), d.getYear(), 
d.getMonthOfYear(), d.getDayOfMonth(),
-                d.getHourOfDay(), d.getMinuteOfHour(), d.getSecondOfMinute());
+        LocalDateTime d = 
DateUtils.getTime(DATE_TIME_FORMATTER_TO_MICRO_SECOND, 
getStringValue()).plusMonths(months);
+        return new DateTimeV2Literal(this.getDataType(), d.getYear(), 
d.getMonthValue(), d.getDayOfMonth(),
+                d.getHour(), d.getMinute(), d.getSecond(), d.getNano() / 
1000L);
     }
 
     @Override
     public DateTimeV2Literal plusDays(int days) {
-        LocalDateTime d = LocalDateTime.parse(getStringValue(), 
DATE_TIME_FORMATTER).plusDays(days);
-        return new DateTimeV2Literal(this.getDataType(), d.getYear(), 
d.getMonthOfYear(), d.getDayOfMonth(),
-                d.getHourOfDay(), d.getMinuteOfHour(), d.getSecondOfMinute());
+        LocalDateTime d = 
DateUtils.getTime(DATE_TIME_FORMATTER_TO_MICRO_SECOND, 
getStringValue()).plusDays(days);
+        return new DateTimeV2Literal(this.getDataType(), d.getYear(), 
d.getMonthValue(), d.getDayOfMonth(),
+                d.getHour(), d.getMinute(), d.getSecond(), d.getNano() / 
1000L);
     }
 
     @Override
     public DateTimeV2Literal plusHours(int hours) {
-        LocalDateTime d = LocalDateTime.parse(getStringValue(), 
DATE_TIME_FORMATTER).plusHours(hours);
-        return new DateTimeV2Literal(this.getDataType(), d.getYear(), 
d.getMonthOfYear(), d.getDayOfMonth(),
-                d.getHourOfDay(), d.getMinuteOfHour(), d.getSecondOfMinute());
+        LocalDateTime d = 
DateUtils.getTime(DATE_TIME_FORMATTER_TO_MICRO_SECOND, 
getStringValue()).plusHours(hours);
+        return new DateTimeV2Literal(this.getDataType(), d.getYear(), 
d.getMonthValue(), d.getDayOfMonth(),
+                d.getHour(), d.getMinute(), d.getSecond(), d.getNano() / 
1000L);
     }
 
     @Override
     public DateTimeV2Literal plusMinutes(int minutes) {
-        LocalDateTime d = LocalDateTime.parse(getStringValue(), 
DATE_TIME_FORMATTER).plusMinutes(minutes);
-        return new DateTimeV2Literal(this.getDataType(), d.getYear(), 
d.getMonthOfYear(), d.getDayOfMonth(),
-                d.getHourOfDay(), d.getMinuteOfHour(), d.getSecondOfMinute());
+        LocalDateTime d = 
DateUtils.getTime(DATE_TIME_FORMATTER_TO_MICRO_SECOND, 
getStringValue()).plusMinutes(minutes);
+        return new DateTimeV2Literal(this.getDataType(), d.getYear(), 
d.getMonthValue(), d.getDayOfMonth(),
+                d.getHour(), d.getMinute(), d.getSecond(), d.getNano() / 
1000L);
     }
 
     @Override
     public DateTimeV2Literal plusSeconds(int seconds) {
-        LocalDateTime d = LocalDateTime.parse(getStringValue(), 
DATE_TIME_FORMATTER).plusSeconds(seconds);
-        return new DateTimeV2Literal(this.getDataType(), d.getYear(), 
d.getMonthOfYear(), d.getDayOfMonth(),
-                d.getHourOfDay(), d.getMinuteOfHour(), d.getSecondOfMinute());
+        LocalDateTime d = 
DateUtils.getTime(DATE_TIME_FORMATTER_TO_MICRO_SECOND, 
getStringValue()).plusSeconds(seconds);
+        return new DateTimeV2Literal(this.getDataType(), d.getYear(), 
d.getMonthValue(), d.getDayOfMonth(),
+                d.getHour(), d.getMinute(), d.getSecond(), d.getNano() / 
1000L);
     }
 }
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/DateV2Literal.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/DateV2Literal.java
index d40af8031e..f70454a942 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/DateV2Literal.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/DateV2Literal.java
@@ -21,8 +21,9 @@ import org.apache.doris.analysis.LiteralExpr;
 import org.apache.doris.catalog.Type;
 import org.apache.doris.nereids.exceptions.AnalysisException;
 import org.apache.doris.nereids.types.DateV2Type;
+import org.apache.doris.nereids.util.DateUtils;
 
-import org.joda.time.LocalDateTime;
+import java.time.LocalDateTime;
 
 /**
  * date v2 literal for nereids
@@ -43,17 +44,17 @@ public class DateV2Literal extends DateLiteral {
     }
 
     public DateV2Literal plusDays(int days) {
-        LocalDateTime dateTime = LocalDateTime.parse(getStringValue(), 
DATE_FORMATTER).plusDays(days);
-        return new DateV2Literal(dateTime.getYear(), 
dateTime.getMonthOfYear(), dateTime.getDayOfMonth());
+        LocalDateTime dateTime = DateUtils.getTime(DATE_FORMATTER, 
getStringValue()).plusDays(days);
+        return new DateV2Literal(dateTime.getYear(), dateTime.getMonthValue(), 
dateTime.getDayOfMonth());
     }
 
     public DateV2Literal plusMonths(int months) {
-        LocalDateTime dateTime = LocalDateTime.parse(getStringValue(), 
DATE_FORMATTER).plusMonths(months);
-        return new DateV2Literal(dateTime.getYear(), 
dateTime.getMonthOfYear(), dateTime.getDayOfMonth());
+        LocalDateTime dateTime = DateUtils.getTime(DATE_FORMATTER, 
getStringValue()).plusMonths(months);
+        return new DateV2Literal(dateTime.getYear(), dateTime.getMonthValue(), 
dateTime.getDayOfMonth());
     }
 
     public DateV2Literal plusYears(int years) {
-        LocalDateTime dateTime = LocalDateTime.parse(getStringValue(), 
DATE_FORMATTER).plusYears(years);
-        return new DateV2Literal(dateTime.getYear(), 
dateTime.getMonthOfYear(), dateTime.getDayOfMonth());
+        LocalDateTime dateTime = DateUtils.getTime(DATE_FORMATTER, 
getStringValue()).plusYears(years);
+        return new DateV2Literal(dateTime.getYear(), dateTime.getMonthValue(), 
dateTime.getDayOfMonth());
     }
 }
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/types/DateTimeV2Type.java 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/types/DateTimeV2Type.java
index 51c604e2e8..b046df7c9f 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/types/DateTimeV2Type.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/types/DateTimeV2Type.java
@@ -33,6 +33,7 @@ import java.util.Objects;
 public class DateTimeV2Type extends DateLikeType {
     public static final int MAX_SCALE = 6;
     public static final DateTimeV2Type SYSTEM_DEFAULT = new DateTimeV2Type(0);
+    public static final DateTimeV2Type MAX = new DateTimeV2Type(MAX_SCALE);
 
     private static final int WIDTH = 8;
 
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/util/DateUtils.java 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/util/DateUtils.java
index 6228fe8ef8..06da317dee 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/util/DateUtils.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/util/DateUtils.java
@@ -19,7 +19,12 @@ package org.apache.doris.nereids.util;
 
 import org.apache.doris.nereids.exceptions.AnalysisException;
 
-import org.joda.time.format.DateTimeFormatterBuilder;
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import java.time.format.DateTimeFormatterBuilder;
+import java.time.format.TextStyle;
+import java.time.temporal.ChronoField;
+import java.time.temporal.TemporalAccessor;
 
 /**
  * date util tools.
@@ -37,84 +42,75 @@ public class DateUtils {
             if (escaped) {
                 switch (character) {
                     case 'a': // %a Abbreviated weekday name (Sun..Sat)
-                        builder.appendDayOfWeekShortText();
+                        builder.appendText(ChronoField.DAY_OF_WEEK, 
TextStyle.SHORT);
                         break;
                     case 'b': // %b Abbreviated month name (Jan..Dec)
-                        builder.appendMonthOfYearShortText();
+                        builder.appendText(ChronoField.MONTH_OF_YEAR, 
TextStyle.SHORT);
                         break;
                     case 'c': // %c Month, numeric (0..12)
-                        builder.appendMonthOfYear(1);
+                        builder.appendValue(ChronoField.MONTH_OF_YEAR);
                         break;
                     case 'd': // %d Day of the month, numeric (00..31)
-                        builder.appendDayOfMonth(2);
+                        builder.appendValue(ChronoField.DAY_OF_MONTH, 2);
                         break;
                     case 'e': // %e Day of the month, numeric (0..31)
-                        builder.appendDayOfMonth(1);
+                        builder.appendValue(ChronoField.DAY_OF_MONTH);
                         break;
                     case 'H': // %H Hour (00..23)
-                        builder.appendHourOfDay(2);
+                        builder.appendValue(ChronoField.HOUR_OF_DAY, 2);
                         break;
                     case 'h': // %h Hour (01..12)
                     case 'I': // %I Hour (01..12)
-                        builder.appendClockhourOfHalfday(2);
+                        builder.appendValue(ChronoField.HOUR_OF_AMPM, 2);
                         break;
                     case 'i': // %i Minutes, numeric (00..59)
-                        builder.appendMinuteOfHour(2);
+                        builder.appendValue(ChronoField.MINUTE_OF_HOUR, 2);
                         break;
                     case 'j': // %j Day of year (001..366)
-                        builder.appendDayOfYear(3);
+                        builder.appendValue(ChronoField.DAY_OF_YEAR, 3);
                         break;
                     case 'k': // %k Hour (0..23)
-                        builder.appendHourOfDay(1);
+                        builder.appendValue(ChronoField.HOUR_OF_DAY);
                         break;
                     case 'l': // %l Hour (1..12)
-                        builder.appendClockhourOfHalfday(1);
+                        builder.appendValue(ChronoField.HOUR_OF_AMPM);
                         break;
                     case 'M': // %M Month name (January..December)
-                        builder.appendMonthOfYearText();
+                        builder.appendText(ChronoField.MONTH_OF_YEAR, 
TextStyle.FULL);
                         break;
                     case 'm': // %m Month, numeric (00..12)
-                        builder.appendMonthOfYear(2);
+                        builder.appendValue(ChronoField.MONTH_OF_YEAR, 2);
                         break;
                     case 'p': // %p AM or PM
-                        builder.appendHalfdayOfDayText();
+                        builder.appendText(ChronoField.AMPM_OF_DAY);
                         break;
                     case 'r': // %r Time, 12-hour (hh:mm:ss followed by AM or 
PM)
-                        builder.appendClockhourOfHalfday(2)
-                                .appendLiteral(':')
-                                .appendMinuteOfHour(2)
-                                .appendLiteral(':')
-                                .appendSecondOfMinute(2)
-                                .appendLiteral(' ')
-                                .appendHalfdayOfDayText();
+                        builder.appendValue(ChronoField.HOUR_OF_AMPM, 2)
+                                .appendPattern(":mm:ss ")
+                                .appendText(ChronoField.AMPM_OF_DAY, 
TextStyle.FULL)
+                                .toFormatter();
                         break;
                     case 'S': // %S Seconds (00..59)
                     case 's': // %s Seconds (00..59)
-                        builder.appendSecondOfMinute(2);
+                        builder.appendValue(ChronoField.SECOND_OF_MINUTE, 2);
                         break;
                     case 'T': // %T Time, 24-hour (hh:mm:ss)
-                        builder.appendHourOfDay(2)
-                                .appendLiteral(':')
-                                .appendMinuteOfHour(2)
-                                .appendLiteral(':')
-                                .appendSecondOfMinute(2);
+                        builder.appendPattern("HH:mm:ss");
                         break;
                     case 'v': // %v Week (01..53), where Monday is the first 
day of the week; used with %x
-                        builder.appendWeekOfWeekyear(2);
+                        builder.appendValue(ChronoField.ALIGNED_WEEK_OF_YEAR, 
2);
                         break;
                     case 'x':
+                    case 'Y': // %Y Year, numeric, four digits
                         // %x Year for the week, where Monday is the first day 
of the week,
                         // numeric, four digits; used with %v
-                        builder.appendWeekyear(4, 4);
+                        builder.appendValue(ChronoField.YEAR, 4);
                         break;
                     case 'W': // %W Weekday name (Sunday..Saturday)
-                        builder.appendDayOfWeekText();
-                        break;
-                    case 'Y': // %Y Year, numeric, four digits
-                        builder.appendYear(4, 4);
+                        builder.appendText(ChronoField.DAY_OF_WEEK, 
TextStyle.FULL);
                         break;
                     case 'y': // %y Year, numeric (two digits)
-                        builder.appendTwoDigitYear(2020);
+                        builder.appendValueReduced(ChronoField.YEAR, 2, 2, 
1970);
                         break;
                     // TODO(Gabriel): support microseconds in date literal
                     case 'f': // %f Microseconds (000000..999999)
@@ -143,4 +139,24 @@ public class DateUtils {
         }
         return builder;
     }
+
+    /**
+     * construct local date time from string
+     */
+    public static LocalDateTime getTime(DateTimeFormatter formatter, String 
value) {
+        TemporalAccessor accessor = formatter.parse(value);
+        return LocalDateTime.of(
+                getOrDefault(accessor, ChronoField.YEAR),
+                getOrDefault(accessor, ChronoField.MONTH_OF_YEAR),
+                getOrDefault(accessor, ChronoField.DAY_OF_MONTH),
+                getOrDefault(accessor, ChronoField.HOUR_OF_DAY),
+                getOrDefault(accessor, ChronoField.MINUTE_OF_HOUR),
+                getOrDefault(accessor, ChronoField.SECOND_OF_MINUTE),
+                getOrDefault(accessor, ChronoField.MICRO_OF_SECOND)
+        );
+    }
+
+    public static int getOrDefault(final TemporalAccessor accessor, final 
ChronoField field) {
+        return accessor.isSupported(field) ? accessor.get(field) : /*default 
value*/ 0;
+    }
 }
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/util/TypeCoercionUtils.java 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/util/TypeCoercionUtils.java
index c29a88aa38..0f75e5537e 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/util/TypeCoercionUtils.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/util/TypeCoercionUtils.java
@@ -612,9 +612,17 @@ public class TypeCoercionUtils {
             if (leftType.isDateTimeV2Type() && rightType.isDateTimeV2Type()) {
                 return DateTimeV2Type.getWiderDatetimeV2Type((DateTimeV2Type) 
leftType, (DateTimeV2Type) rightType);
             } else if (leftType.isDateTimeV2Type()) {
-                return leftType;
+                if (rightType.isIntegerLikeType()) {
+                    return leftType;
+                } else {
+                    return DateTimeV2Type.MAX;
+                }
             } else if (rightType.isDateTimeV2Type()) {
-                return rightType;
+                if (rightType.isIntegerLikeType()) {
+                    return rightType;
+                } else {
+                    return DateTimeV2Type.MAX;
+                }
             } else if (leftType.isDateV2Type() && (rightType.isDateType() || 
rightType.isDateV2Type())) {
                 return leftType;
             } else if (rightType.isDateV2Type() && (leftType.isDateType() || 
leftType.isDateV2Type())) {
diff --git 
a/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/expression/rewrite/ExpressionRewriteTest.java
 
b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/expression/rewrite/ExpressionRewriteTest.java
index 32e7e0b394..a55659dbaa 100644
--- 
a/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/expression/rewrite/ExpressionRewriteTest.java
+++ 
b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/expression/rewrite/ExpressionRewriteTest.java
@@ -228,7 +228,7 @@ public class ExpressionRewriteTest extends 
ExpressionRewriteTestHelper {
     public void testSimplifyComparisonPredicateRule() {
         executor = new 
ExpressionRuleExecutor(ImmutableList.of(SimplifyComparisonPredicate.INSTANCE));
 
-        Expression dtv2 = new DateTimeV2Literal(1, 1, 1, 1, 1, 1);
+        Expression dtv2 = new DateTimeV2Literal(1, 1, 1, 1, 1, 1, 0);
         Expression dt = new DateTimeLiteral(1, 1, 1, 1, 1, 1);
         Expression dtNoTime = new DateTimeLiteral(1, 1, 1, 0, 0, 0);
         Expression dv2 = new DateV2Literal(1, 1, 1);
@@ -291,7 +291,7 @@ public class ExpressionRewriteTest extends 
ExpressionRewriteTestHelper {
                 new GreaterThan(new Cast(d, DateTimeType.INSTANCE), dtNoTime));
 
         // test hour, minute and second all zero
-        Expression dtv2AtZeroClock = new DateTimeV2Literal(1, 1, 1, 0, 0, 0);
+        Expression dtv2AtZeroClock = new DateTimeV2Literal(1, 1, 1, 0, 0, 0, 
0);
         assertRewrite(
                 new GreaterThan(new Cast(dv2, DateTimeV2Type.SYSTEM_DEFAULT), 
dtv2AtZeroClock),
                 new GreaterThan(dv2, dv2));
diff --git 
a/regression-test/data/nereids_syntax_p0/test_timestamp_arithmetic.out 
b/regression-test/data/nereids_syntax_p0/test_timestamp_arithmetic.out
new file mode 100644
index 0000000000..521083445d
--- /dev/null
+++ b/regression-test/data/nereids_syntax_p0/test_timestamp_arithmetic.out
@@ -0,0 +1,4 @@
+-- This file is automatically generated. You should know what you did if you 
want to edit this
+-- !test_add --
+0001-01-02     0001-01-01T00:00:01     0001-01-02T00:01:01     
0001-01-02T00:01:01.001 0001-01-02T00:01:01.003050
+
diff --git 
a/regression-test/suites/nereids_syntax_p0/test_timestamp_arithmetic.groovy 
b/regression-test/suites/nereids_syntax_p0/test_timestamp_arithmetic.groovy
index a3e1c04511..46bb27fe42 100644
--- a/regression-test/suites/nereids_syntax_p0/test_timestamp_arithmetic.groovy
+++ b/regression-test/suites/nereids_syntax_p0/test_timestamp_arithmetic.groovy
@@ -29,4 +29,36 @@ suite("nereids_timestamp_arithmetic") {
         sql = "select date '20200808' + interval array() day;"
         exception = "the second argument must be a scalar type. but it is 
array()"
     }
+
+    sql """
+    DROP TABLE IF EXISTS nereids_test_ta;
+    """
+    sql """
+        CREATE TABLE `nereids_test_ta` (
+          `c1` int(11) NULL,
+          `c2` date NULL,
+          `c3` datev2 NULL,
+          `c4` datetime NULL,
+          `c5` datetimev2(3) NULL,
+          `c6` datetimev2(5) NULL
+        ) ENGINE=OLAP
+        DUPLICATE KEY(`c1`, `c2`, `c3`)
+        COMMENT 'OLAP'
+        DISTRIBUTED BY HASH(`c1`) BUCKETS 10
+        PROPERTIES (
+        "replication_allocation" = "tag.location.default: 1",
+        "in_memory" = "false",
+        "storage_format" = "V2",
+        "light_schema_change" = "true",
+        "disable_auto_compaction" = "false"
+        );
+    """
+
+    sql """
+        INSERT INTO nereids_test_ta VALUES (1, '0001-01-01', '0001-01-01', 
'0001-01-01 00:01:01', '0001-01-01: 00:01:01.001', '0001-01-01 00:01:01.00305');
+    """
+
+    qt_test_add """
+        SELECT c2 + INTERVAL 1 DAY, c3 + INTERVAL 1 SECOND, c4 + INTERVAL 1 
DAY, c5 + INTERVAL 1 DAY, c6 + INTERVAL 1 DAY FROM nereids_test_ta
+    """
 }
\ No newline at end of file


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

Reply via email to