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

yiguolei pushed a commit to branch branch-2.1
in repository https://gitbox.apache.org/repos/asf/doris.git


The following commit(s) were added to refs/heads/branch-2.1 by this push:
     new 8eb6a2a7c1a [enhancement](Nereids) boost characterLiteralTypeCoercion 
(#42941) (#43092)
8eb6a2a7c1a is described below

commit 8eb6a2a7c1ae2d37746c0bc500af1e23f90f5f4f
Author: 924060929 <924060...@qq.com>
AuthorDate: Mon Nov 4 11:50:44 2024 +0800

    [enhancement](Nereids) boost characterLiteralTypeCoercion (#42941) (#43092)
    
    cherry pick from #42941
---
 .../expressions/functions/SearchSignature.java     |   9 +-
 .../trees/expressions/literal/DateLiteral.java     |  75 +++-
 .../trees/expressions/literal/DateTimeLiteral.java |  75 +++-
 .../expressions/literal/DateTimeV2Literal.java     |   2 +-
 .../expressions/literal/DecimalV3Literal.java      |  13 +-
 .../nereids/trees/expressions/literal/Result.java  |  66 +++
 .../expressions/literal/format/AndChecker.java     |  45 ++
 .../expressions/literal/format/AtLeastChecker.java |  49 ++
 .../expressions/literal/format/CharChecker.java    |  36 ++
 .../expressions/literal/format/CheckResult.java    |  49 ++
 .../literal/format/CustomCharChecker.java          |  39 ++
 .../literal/format/DateTimeChecker.java            | 137 ++++++
 .../expressions/literal/format/DebugChecker.java   |  38 ++
 .../expressions/literal/format/DigitChecker.java   |  45 ++
 .../expressions/literal/format/FloatChecker.java   |  55 +++
 .../expressions/literal/format/FormatChecker.java  | 170 +++++++
 .../expressions/literal/format/IntegerChecker.java |  43 ++
 .../expressions/literal/format/LetterChecker.java  |  45 ++
 .../expressions/literal/format/OptionChecker.java  |  36 ++
 .../expressions/literal/format/OrChecker.java      |  55 +++
 .../expressions/literal/format/StringChecker.java  |  44 ++
 .../expressions/literal/format/StringInspect.java  |  64 +++
 .../apache/doris/nereids/types/DecimalV3Type.java  |  25 +-
 .../doris/nereids/util/TypeCoercionUtils.java      |  54 ++-
 .../trees/expressions/literal/DateLiteralTest.java |  16 +-
 .../expressions/literal/DateTimeLiteralTest.java   | 496 +++++++++++----------
 .../expressions/literal/FloatLiteralTest.java      |  80 ++++
 .../expressions/literal/IntegerLiteralTest.java    |  64 +++
 28 files changed, 1605 insertions(+), 320 deletions(-)

diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/SearchSignature.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/SearchSignature.java
index 4d6bb658356..5fa426a99a2 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/SearchSignature.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/SearchSignature.java
@@ -207,13 +207,14 @@ public class SearchSignature {
         int arity = arguments.size();
         for (int i = 0; i < arity; i++) {
             DataType sigArgType = sig.getArgType(i);
-            DataType realType = arguments.get(i).getDataType();
+            Expression argument = arguments.get(i);
+            DataType realType = argument.getDataType();
             // we need to try to do string literal coercion when search 
signature.
             // for example, FUNC_A has two signature FUNC_A(datetime) and 
FUNC_A(string)
             // if SQL block is `FUNC_A('2020-02-02 00:00:00')`, we should 
return signature FUNC_A(datetime).
-            if (arguments.get(i).isLiteral() && realType.isStringLikeType()) {
-                realType = 
TypeCoercionUtils.characterLiteralTypeCoercion(((Literal) 
arguments.get(i)).getStringValue(),
-                        sigArgType).orElse(arguments.get(i)).getDataType();
+            if (!argument.isNullLiteral() && argument.isLiteral() && 
realType.isStringLikeType()) {
+                realType = 
TypeCoercionUtils.characterLiteralTypeCoercion(((Literal) 
argument).getStringValue(),
+                        sigArgType).orElse(argument).getDataType();
             }
             if (!typePredicate.apply(sigArgType, realType)) {
                 return false;
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 e74e3f42387..c224a294b9f 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
@@ -44,6 +44,10 @@ import java.util.function.UnaryOperator;
 public class DateLiteral extends Literal {
     public static final String JAVA_DATE_FORMAT = "yyyy-MM-dd";
 
+    public static final Set<Character> punctuations = ImmutableSet.of('!', 
'@', '#', '$', '%', '^', '&', '*', '(', ')',
+            '-', '+', '=', '_', '{', '}', '[', ']', '|', '\\', ':', ';', '"', 
'\'', '<', '>', ',', '.', '?', '/', '~',
+            '`');
+
     // for cast datetime type to date type.
     private static final LocalDateTime START_OF_A_DAY = LocalDateTime.of(0, 1, 
1, 0, 0, 0);
     private static final LocalDateTime END_OF_A_DAY = LocalDateTime.of(9999, 
12, 31, 23, 59, 59, 999999000);
@@ -51,10 +55,6 @@ public class DateLiteral extends Literal {
     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 Set<Character> punctuations = ImmutableSet.of('!', 
'@', '#', '$', '%', '^', '&', '*', '(', ')',
-            '-', '+', '=', '_', '{', '}', '[', ']', '|', '\\', ':', ';', '"', 
'\'', '<', '>', ',', '.', '?', '/', '~',
-            '`');
-
     protected long year;
     protected long month;
     protected long day;
@@ -145,7 +145,7 @@ public class DateLiteral extends Literal {
         return punctuations.contains(c);
     }
 
-    static String normalize(String s) {
+    static Result<String, AnalysisException> normalize(String s) {
         // merge consecutive space
         if (s.contains("  ")) {
             s = s.replaceAll(" +", " ");
@@ -208,7 +208,10 @@ public class DateLiteral extends Literal {
                         sb.append('0').append(c);
                     }
                 } else {
-                    throw new AnalysisException("date/datetime literal [" + s 
+ "] is invalid");
+                    final String currentString = s;
+                    return Result.err(
+                            () -> new AnalysisException("date/datetime literal 
[" + currentString + "] is invalid")
+                    );
                 }
                 i = j;
                 partNumber += 1;
@@ -228,7 +231,10 @@ public class DateLiteral extends Literal {
                 } else if (partNumber > 3 && isPunctuation(c)) {
                     sb.append(':');
                 } else {
-                    throw new AnalysisException("date/datetime literal [" + s 
+ "] is invalid");
+                    final String currentString = s;
+                    return Result.err(
+                            () -> new AnalysisException("date/datetime literal 
[" + currentString + "] is invalid")
+                    );
                 }
             } else {
                 break;
@@ -259,15 +265,33 @@ public class DateLiteral extends Literal {
         // trim use to remove any blank before zone id or zone offset
         sb.append(s.substring(i).trim());
 
-        return sb.toString();
+        return Result.ok(sb.toString());
     }
 
-    protected static TemporalAccessor parse(String s) {
+    /** parseDateLiteral */
+    public static Result<DateLiteral, AnalysisException> 
parseDateLiteral(String s) {
+        Result<TemporalAccessor, AnalysisException> parseResult = 
parseDateTime(s);
+        if (parseResult.isError()) {
+            return parseResult.cast();
+        }
+        TemporalAccessor dateTime = parseResult.get();
+        int year = DateUtils.getOrDefault(dateTime, ChronoField.YEAR);
+        int month = DateUtils.getOrDefault(dateTime, 
ChronoField.MONTH_OF_YEAR);
+        int day = DateUtils.getOrDefault(dateTime, ChronoField.DAY_OF_MONTH);
+
+        if (checkDatetime(dateTime) || checkRange(year, month, day) || 
checkDate(year, month, day)) {
+            return Result.err(() -> new AnalysisException("date/datetime 
literal [" + s + "] is out of range"));
+        }
+        return Result.ok(new DateLiteral(year, month, day));
+    }
+
+    /** parseDateTime */
+    public static Result<TemporalAccessor, AnalysisException> 
parseDateTime(String s) {
         // fast parse '2022-01-01'
         if (s.length() == 10 && s.charAt(4) == '-' && s.charAt(7) == '-') {
             TemporalAccessor date = fastParseDate(s);
             if (date != null) {
-                return date;
+                return Result.ok(date);
             }
         }
 
@@ -289,15 +313,20 @@ public class DateLiteral extends Literal {
             if (!containsPunctuation) {
                 s = normalizeBasic(s);
                 // mysql reject "20200219 010101" "200219 010101", can't use ' 
' spilt basic date time.
+
                 if (!s.contains("T")) {
                     dateTime = 
DateTimeFormatterUtils.BASIC_FORMATTER_WITHOUT_T.parse(s);
                 } else {
                     dateTime = 
DateTimeFormatterUtils.BASIC_DATE_TIME_FORMATTER.parse(s);
                 }
-                return dateTime;
+                return Result.ok(dateTime);
             }
 
-            s = normalize(s);
+            Result<String, AnalysisException> normalizeResult = normalize(s);
+            if (normalizeResult.isError()) {
+                return normalizeResult.cast();
+            }
+            s = normalizeResult.get();
 
             if (!s.contains(" ")) {
                 dateTime = DateTimeFormatterUtils.ZONE_DATE_FORMATTER.parse(s);
@@ -307,33 +336,35 @@ public class DateLiteral extends Literal {
 
             // if Year is not present, throw exception
             if (!dateTime.isSupported(ChronoField.YEAR)) {
-                throw new AnalysisException("date/datetime literal [" + 
originalString + "] is invalid");
+                return Result.err(
+                        () -> new AnalysisException("date/datetime literal [" 
+ originalString + "] is invalid")
+                );
             }
 
-            return dateTime;
+            return Result.ok(dateTime);
         } catch (Exception ex) {
-            throw new AnalysisException("date/datetime literal [" + 
originalString + "] is invalid");
+            return Result.err(() -> new AnalysisException("date/datetime 
literal [" + originalString + "] is invalid"));
         }
     }
 
     protected void init(String s) throws AnalysisException {
-        TemporalAccessor dateTime = parse(s);
+        TemporalAccessor dateTime = parseDateTime(s).get();
         year = DateUtils.getOrDefault(dateTime, ChronoField.YEAR);
         month = DateUtils.getOrDefault(dateTime, ChronoField.MONTH_OF_YEAR);
         day = DateUtils.getOrDefault(dateTime, ChronoField.DAY_OF_MONTH);
 
-        if (checkDatetime(dateTime) || checkRange() || checkDate()) {
+        if (checkDatetime(dateTime) || checkRange(year, month, day) || 
checkDate(year, month, day)) {
             throw new AnalysisException("date/datetime literal [" + s + "] is 
out of range");
         }
     }
 
-    protected boolean checkRange() {
+    protected static boolean checkRange(long year, long month, long day) {
         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)) {
+    protected static boolean checkDate(long year, long month, long day) {
+        if (month != 0 && day > DAYS_IN_MONTH[(int) month]) {
+            if (month == 2 && day == 29 && (Year.isLeap(year) && year > 0)) {
                 return false;
             }
             return true;
@@ -345,7 +376,7 @@ public class DateLiteral extends Literal {
         return dateTime == null || dateTime.isBefore(START_OF_A_DAY) || 
dateTime.isAfter(END_OF_A_DAY);
     }
 
-    private boolean checkDatetime(TemporalAccessor dateTime) {
+    private static boolean checkDatetime(TemporalAccessor dateTime) {
         return DateUtils.getOrDefault(dateTime, ChronoField.HOUR_OF_DAY) != 0
                 || DateUtils.getOrDefault(dateTime, 
ChronoField.MINUTE_OF_HOUR) != 0
                 || DateUtils.getOrDefault(dateTime, 
ChronoField.SECOND_OF_MINUTE) != 0
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 726c39c8bb9..27470187eae 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
@@ -23,6 +23,7 @@ import org.apache.doris.nereids.exceptions.AnalysisException;
 import org.apache.doris.nereids.trees.expressions.Expression;
 import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor;
 import org.apache.doris.nereids.types.DateTimeType;
+import org.apache.doris.nereids.types.DateTimeV2Type;
 import org.apache.doris.nereids.types.coercion.DateLikeType;
 import org.apache.doris.nereids.util.DateUtils;
 
@@ -108,7 +109,7 @@ public class DateTimeLiteral extends DateLiteral {
         if (s.indexOf("-") == s.lastIndexOf("-") && s.indexOf(":") == 
s.lastIndexOf(":")) {
             return 0;
         }
-        s = normalize(s);
+        s = normalize(s).get();
         if (s.length() <= 19 || s.charAt(19) != '.') {
             return 0;
         }
@@ -130,10 +131,73 @@ public class DateTimeLiteral extends DateLiteral {
         return scale;
     }
 
-    @Override
+    /** parseDateTimeLiteral */
+    public static Result<DateTimeLiteral, AnalysisException> 
parseDateTimeLiteral(String s, boolean isV2) {
+        Result<TemporalAccessor, AnalysisException> parseResult = 
parseDateTime(s);
+        if (parseResult.isError()) {
+            return parseResult.cast();
+        }
+
+        TemporalAccessor temporal = parseResult.get();
+        long year = DateUtils.getOrDefault(temporal, ChronoField.YEAR);
+        long month = DateUtils.getOrDefault(temporal, 
ChronoField.MONTH_OF_YEAR);
+        long day = DateUtils.getOrDefault(temporal, ChronoField.DAY_OF_MONTH);
+        long hour = DateUtils.getOrDefault(temporal, ChronoField.HOUR_OF_DAY);
+        long minute = DateUtils.getOrDefault(temporal, 
ChronoField.MINUTE_OF_HOUR);
+        long second = DateUtils.getOrDefault(temporal, 
ChronoField.SECOND_OF_MINUTE);
+
+        ZoneId zoneId = temporal.query(TemporalQueries.zone());
+        if (zoneId != null) {
+            // get correct DST of that time.
+            Instant thatTime = ZonedDateTime
+                    .of((int) year, (int) month, (int) day, (int) hour, (int) 
minute, (int) second, 0, zoneId)
+                    .toInstant();
+
+            int offset = 
DateUtils.getTimeZone().getRules().getOffset(thatTime).getTotalSeconds()
+                    - zoneId.getRules().getOffset(thatTime).getTotalSeconds();
+            if (offset != 0) {
+                DateTimeLiteral tempLiteral = new DateTimeLiteral(year, month, 
day, hour, minute, second);
+                DateTimeLiteral result = (DateTimeLiteral) 
tempLiteral.plusSeconds(offset);
+                second = result.second;
+                minute = result.minute;
+                hour = result.hour;
+                day = result.day;
+                month = result.month;
+                year = result.year;
+            }
+        }
+
+        long microSecond = DateUtils.getOrDefault(temporal, 
ChronoField.NANO_OF_SECOND) / 100L;
+        // Microseconds have 7 digits.
+        long sevenDigit = microSecond % 10;
+        microSecond = microSecond / 10;
+        if (sevenDigit >= 5 && isV2) {
+            DateTimeV2Literal tempLiteral = new DateTimeV2Literal(year, month, 
day, hour, minute, second, microSecond);
+            DateTimeV2Literal result = (DateTimeV2Literal) 
tempLiteral.plusMicroSeconds(1);
+            second = result.second;
+            minute = result.minute;
+            hour = result.hour;
+            day = result.day;
+            month = result.month;
+            year = result.year;
+            microSecond = result.microSecond;
+        }
+
+        if (checkRange(year, month, day) || checkDate(year, month, day)) {
+            return Result.err(() -> new AnalysisException("datetime literal [" 
+ s + "] is out of range"));
+        }
+
+        if (isV2) {
+            DateTimeV2Type type = DateTimeV2Type.forTypeFromString(s);
+            return Result.ok(new DateTimeV2Literal(type, year, month, day, 
hour, minute, second, microSecond));
+        } else {
+            return Result.ok(new DateTimeLiteral(DateTimeType.INSTANCE, year, 
month, day, hour, minute, second));
+        }
+    }
+
     protected void init(String s) throws AnalysisException {
         // TODO: check and do fast parse like fastParseDate
-        TemporalAccessor temporal = parse(s);
+        TemporalAccessor temporal = parseDateTime(s).get();
 
         year = DateUtils.getOrDefault(temporal, ChronoField.YEAR);
         month = DateUtils.getOrDefault(temporal, ChronoField.MONTH_OF_YEAR);
@@ -177,14 +241,13 @@ public class DateTimeLiteral extends DateLiteral {
             this.microSecond = result.microSecond;
         }
 
-        if (checkRange() || checkDate()) {
+        if (checkRange(year, month, day) || checkDate(year, month, day)) {
             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()
+        return checkRange(year, month, day) || hour > MAX_DATETIME.getHour() 
|| minute > MAX_DATETIME.getMinute()
                 || second > MAX_DATETIME.getSecond() || microSecond > 
MAX_MICROSECOND;
     }
 
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 0ca19bf2a92..c6ec4b99d4f 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
@@ -77,7 +77,7 @@ public class DateTimeV2Literal extends DateTimeLiteral {
             this.second = localDateTime.getSecond();
             this.microSecond -= 1000000;
         }
-        if (checkRange() || checkDate()) {
+        if (checkRange() || checkDate(year, month, day)) {
             // may fallback to legacy planner. make sure the behaviour of 
rounding is same.
             throw new AnalysisException("datetime literal [" + toString() + "] 
is out of range");
         }
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/DecimalV3Literal.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/DecimalV3Literal.java
index 1ff2e50169c..d8be4faf0c9 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/DecimalV3Literal.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/DecimalV3Literal.java
@@ -44,11 +44,16 @@ public class DecimalV3Literal extends FractionalLiteral {
      * Constructor for DecimalV3Literal
      */
     public DecimalV3Literal(DecimalV3Type dataType, BigDecimal value) {
-        
super(DecimalV3Type.createDecimalV3TypeLooseCheck(dataType.getPrecision(), 
dataType.getScale()));
+        super(DecimalV3Type.createDecimalV3TypeLooseCheck(
+                dataType.getPrecision() == -1 ? value.precision() : 
dataType.getPrecision(),
+                dataType.getScale() == -1 ? value.scale() : 
dataType.getScale())
+        );
+
+        int precision = dataType.getPrecision() == -1 ? value.precision() : 
dataType.getPrecision();
+        int scale = dataType.getScale() == -1 ? value.scale() : 
dataType.getScale();
         Objects.requireNonNull(value, "value not be null");
-        checkPrecisionAndScale(dataType.getPrecision(), dataType.getScale(), 
value);
-        BigDecimal adjustedValue = value.scale() < 0 ? value
-                : value.setScale(dataType.getScale(), RoundingMode.HALF_UP);
+        checkPrecisionAndScale(precision, scale, value);
+        BigDecimal adjustedValue = value.scale() < 0 ? value : 
value.setScale(scale, RoundingMode.HALF_UP);
         this.value = Objects.requireNonNull(adjustedValue);
     }
 
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/Result.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/Result.java
new file mode 100644
index 00000000000..aa5040abcf4
--- /dev/null
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/Result.java
@@ -0,0 +1,66 @@
+// 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.literal;
+
+import java.util.Optional;
+import java.util.function.Supplier;
+
+/** Result */
+public class Result<R, T extends RuntimeException> {
+    private final Optional<R> result;
+    private final Optional<Supplier<T>> exceptionSupplier;
+
+    private Result(Optional<R> result, Optional<Supplier<T>> 
exceptionSupplier) {
+        this.result = result;
+        this.exceptionSupplier = exceptionSupplier;
+    }
+
+    public static <R, T extends RuntimeException> Result<R, T> ok(R result) {
+        return new Result<>(Optional.of(result), Optional.empty());
+    }
+
+    public static <R, T extends RuntimeException> Result<R, T> err(Supplier<T> 
exceptionSupplier) {
+        return new Result<>(Optional.empty(), Optional.of(exceptionSupplier));
+    }
+
+    public boolean isOk() {
+        return !exceptionSupplier.isPresent();
+    }
+
+    public boolean isError() {
+        return exceptionSupplier.isPresent();
+    }
+
+    public <R, T extends RuntimeException> Result<R, T> cast() {
+        return (Result<R, T>) this;
+    }
+
+    public R get() {
+        if (exceptionSupplier.isPresent()) {
+            throw exceptionSupplier.get().get();
+        }
+        return result.get();
+    }
+
+    public R orElse(R other) {
+        if (exceptionSupplier.isPresent()) {
+            return other;
+        }
+        return result.get();
+    }
+}
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/format/AndChecker.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/format/AndChecker.java
new file mode 100644
index 00000000000..377d8b2202b
--- /dev/null
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/format/AndChecker.java
@@ -0,0 +1,45 @@
+// 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.literal.format;
+
+import org.apache.doris.nereids.util.Utils;
+
+import java.util.List;
+import java.util.Objects;
+
+/** AndChecker */
+public class AndChecker extends FormatChecker {
+    private final List<FormatChecker> checkers;
+
+    public AndChecker(String name, List<FormatChecker> checkers) {
+        super(name);
+        this.checkers = Utils.fastToImmutableList(
+                Objects.requireNonNull(checkers, "checkers can not be null")
+        );
+    }
+
+    @Override
+    protected boolean doCheck(StringInspect stringInspect) {
+        for (FormatChecker checker : checkers) {
+            if (!checker.check(stringInspect).matched) {
+                return false;
+            }
+        }
+        return true;
+    }
+}
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/format/AtLeastChecker.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/format/AtLeastChecker.java
new file mode 100644
index 00000000000..f69c942d966
--- /dev/null
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/format/AtLeastChecker.java
@@ -0,0 +1,49 @@
+// 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.literal.format;
+
+import java.util.Objects;
+import java.util.function.Predicate;
+
+/** AtLeastChecker */
+public class AtLeastChecker extends FormatChecker {
+    private final int minCount;
+    private final int maxRead;
+    private final Predicate<Character> checker;
+
+    public AtLeastChecker(String name, int minCount, int maxRead, 
Predicate<Character> checker) {
+        super(name);
+        this.minCount = minCount;
+        this.maxRead = maxRead;
+        this.checker = Objects.requireNonNull(checker, "checker can not be 
null");
+    }
+
+    @Override
+    protected boolean doCheck(StringInspect stringInspect) {
+        int count = 0;
+        boolean checkRead = maxRead >= 0;
+        while (!stringInspect.eos() && (!checkRead || count < maxRead)) {
+            if (!checker.test(stringInspect.lookAt())) {
+                break;
+            }
+            stringInspect.step();
+            count++;
+        }
+        return count >= minCount;
+    }
+}
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/format/CharChecker.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/format/CharChecker.java
new file mode 100644
index 00000000000..14934bcb846
--- /dev/null
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/format/CharChecker.java
@@ -0,0 +1,36 @@
+// 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.literal.format;
+
+/** CharChecker */
+public class CharChecker extends FormatChecker {
+    public final char c;
+
+    public CharChecker(String name, char c) {
+        super(name);
+        this.c = c;
+    }
+
+    @Override
+    protected boolean doCheck(StringInspect stringInspect) {
+        if (stringInspect.eos() || stringInspect.lookAndStep() != c) {
+            return false;
+        }
+        return true;
+    }
+}
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/format/CheckResult.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/format/CheckResult.java
new file mode 100644
index 00000000000..b604a3516ab
--- /dev/null
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/format/CheckResult.java
@@ -0,0 +1,49 @@
+// 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.literal.format;
+
+/** CheckResult */
+public class CheckResult {
+    public final FormatChecker checker;
+    public final StringInspect stringInspect;
+    public final boolean matched;
+    public final int checkStartIndex;
+    public final int checkEndIndex;
+
+    public CheckResult(
+            FormatChecker checker, StringInspect stringInspect,
+            boolean matched, int checkStartIndex, int checkEndIndex) {
+        this.checker = checker;
+        this.stringInspect = stringInspect;
+        this.matched = matched;
+        this.checkStartIndex = checkStartIndex;
+        this.checkEndIndex = checkEndIndex;
+    }
+
+    public int matchesLength() {
+        return checkEndIndex - checkStartIndex;
+    }
+
+    public String matchesContent() {
+        return stringInspect.str.substring(checkStartIndex, checkEndIndex);
+    }
+
+    public void stepBack() {
+        stringInspect.setIndex(checkStartIndex);
+    }
+}
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/format/CustomCharChecker.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/format/CustomCharChecker.java
new file mode 100644
index 00000000000..0718202bf03
--- /dev/null
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/format/CustomCharChecker.java
@@ -0,0 +1,39 @@
+// 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.literal.format;
+
+import java.util.Objects;
+import java.util.function.Predicate;
+
+/** CustomCharChecker */
+public class CustomCharChecker extends FormatChecker {
+    private final Predicate<Character> checker;
+
+    public CustomCharChecker(String name, Predicate<Character> checker) {
+        super(name);
+        this.checker = Objects.requireNonNull(checker, "checker can not be 
null");
+    }
+
+    @Override
+    protected boolean doCheck(StringInspect stringInspect) {
+        if (stringInspect.eos() || !checker.test(stringInspect.lookAndStep())) 
{
+            return false;
+        }
+        return true;
+    }
+}
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/format/DateTimeChecker.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/format/DateTimeChecker.java
new file mode 100644
index 00000000000..7d60a01c041
--- /dev/null
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/format/DateTimeChecker.java
@@ -0,0 +1,137 @@
+// 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.literal.format;
+
+import org.apache.doris.nereids.trees.expressions.literal.DateLiteral;
+
+/** DateTimeChecker */
+public class DateTimeChecker extends FormatChecker {
+    private static final DateTimeChecker INSTANCE = new DateTimeChecker();
+
+    private final FormatChecker checker;
+
+    private DateTimeChecker() {
+        super("DateTimeChecker");
+
+        this.checker =
+                or(
+                    // date
+                    and("Date",
+                        or(
+                            // 20241012
+                            digit(8, 8),
+                            // 2024-10-12
+                            and(
+                                digit(1, 4), // year
+                                chars(DateLiteral.punctuations::contains),
+                                digit(1, 2), // month
+                                chars(DateLiteral.punctuations::contains),
+                                digit(1, 2) // day
+                            )
+                        )
+                    ),
+                    // datetime
+                    and("DateTime",
+                        or("YearToSecond",
+                            // 20241012010203
+                            and("FullCompactDateTime",
+                                digit(8, 8),
+                                atLeast(0, c -> c == 'T'),
+                                digit(6, 6)
+                            ),
+
+                            // 241012010203 or 241012T010203
+                            and("ShortCompactDateTime",
+                                digit(6, 6),
+                                atLeast(0, c -> c == 'T'),
+                                digit(6, 6)
+                            ),
+
+                            // 2024-01-01 01:02:03
+                            and("NormalDateTime",
+                                digit(1, 4), // year
+                                chars(DateLiteral.punctuations::contains),
+                                digit(1, 2), // month
+                                chars(DateLiteral.punctuations::contains),
+                                digit(1, 2), // day
+                                atLeast(1, c -> c == 'T' || c == ' ' || 
DateLiteral.punctuations.contains(c)),
+                                digit(1, 2), // hour
+                                option(
+                                    and(
+                                        
chars(DateLiteral.punctuations::contains),
+                                        digit(1, 2), // minute
+                                        option(
+                                            and(
+                                                
chars(DateLiteral.punctuations::contains),
+                                                digit(1, 2) // second
+                                            )
+                                        )
+                                    )
+                                )
+                            )
+                        ),
+                        option("NanoSecond", nanoSecond()),
+                        option("TimeZone", timeZone())
+                    )
+               );
+    }
+
+    public static boolean isValidDateTime(String str) {
+        str = str.trim();
+        StringInspect stringInspect = new StringInspect(str.trim());
+        return INSTANCE.check(stringInspect).matched && stringInspect.eos();
+    }
+
+    @Override
+    protected boolean doCheck(StringInspect stringInspect) {
+        return checker.check(stringInspect).matched;
+    }
+
+    private FormatChecker nanoSecond() {
+        return and(
+            ch('.'),
+            digit(1)
+        );
+    }
+
+    private FormatChecker timeZone() {
+        // Z or +08:00 or UTC-01:00
+        return and(
+            // timezone: Europe/London, America/New_York
+            atLeast(0, c -> ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') 
|| c == '/' || c == '_'),
+            option(
+                and(
+                    chars(c -> c == '+' || c == '-'),
+                    digit(1, 2),
+                    option(
+                        and(
+                            ch(':'),
+                            digit(1, 2),
+                            option(
+                                and(
+                                    ch(':'),
+                                    digit(1, 2)
+                                )
+                            )
+                        )
+                    )
+                )
+            )
+        );
+    }
+}
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/format/DebugChecker.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/format/DebugChecker.java
new file mode 100644
index 00000000000..6569b914d5e
--- /dev/null
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/format/DebugChecker.java
@@ -0,0 +1,38 @@
+// 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.literal.format;
+
+import java.util.Objects;
+import java.util.function.Predicate;
+
+/** DebugChecker */
+public class DebugChecker<T extends FormatChecker> extends FormatChecker {
+    private final T childChecker;
+    private final Predicate<T> debugPoint;
+
+    public DebugChecker(String name, T childChecker, Predicate<T> debugPoint) {
+        super(name);
+        this.childChecker = Objects.requireNonNull(childChecker, "childChecker 
can not be null");
+        this.debugPoint = Objects.requireNonNull(debugPoint, "debugPoint can 
not be null");
+    }
+
+    @Override
+    protected boolean doCheck(StringInspect stringInspect) {
+        return debugPoint.test(childChecker);
+    }
+}
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/format/DigitChecker.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/format/DigitChecker.java
new file mode 100644
index 00000000000..fe1cb26fda4
--- /dev/null
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/format/DigitChecker.java
@@ -0,0 +1,45 @@
+// 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.literal.format;
+
+/** DigitChecker */
+public class DigitChecker extends FormatChecker {
+    private final int minCount;
+    private final int maxRead;
+
+    public DigitChecker(String name, int minCount, int maxRead) {
+        super(name);
+        this.minCount = minCount;
+        this.maxRead = maxRead;
+    }
+
+    @Override
+    protected boolean doCheck(StringInspect stringInspect) {
+        int numberCount = 0;
+        boolean checkRead = maxRead >= 0;
+        while (!stringInspect.eos() && (!checkRead || numberCount < maxRead)) {
+            char c = stringInspect.lookAt();
+            if (!('0' <= c && c <= '9')) {
+                break;
+            }
+            stringInspect.step();
+            numberCount++;
+        }
+        return numberCount >= minCount;
+    }
+}
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/format/FloatChecker.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/format/FloatChecker.java
new file mode 100644
index 00000000000..9b438f45324
--- /dev/null
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/format/FloatChecker.java
@@ -0,0 +1,55 @@
+// 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.literal.format;
+
+/** FloatChecker */
+public class FloatChecker extends FormatChecker {
+    private static final FloatChecker INSTANCE = new FloatChecker();
+    private final FormatChecker checker;
+
+    private FloatChecker() {
+        super("FloatChecker");
+        checker = and(
+            option(chars(c -> c == '+' || c == '-')),
+            or(
+                // 123 or 123.456
+                and(digit(1), option(and(ch('.'), digit(0)))),
+                // .123
+                and(ch('.'), digit(1))
+            ),
+            option(
+                // E+10 or E-10 or E10
+                and(
+                    chars(c -> c == 'e' || c == 'E'),
+                    option(chars(c -> c == '+' || c == '-')),
+                    digit(1)
+                )
+            )
+        );
+    }
+
+    public static boolean isValidFloat(String str) {
+        StringInspect stringInspect = new StringInspect(str.trim());
+        return INSTANCE.check(stringInspect).matched && stringInspect.eos();
+    }
+
+    @Override
+    protected boolean doCheck(StringInspect stringInspect) {
+        return checker.check(stringInspect).matched;
+    }
+}
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/format/FormatChecker.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/format/FormatChecker.java
new file mode 100644
index 00000000000..fc6d2acc993
--- /dev/null
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/format/FormatChecker.java
@@ -0,0 +1,170 @@
+// 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.literal.format;
+
+import org.apache.doris.nereids.util.Utils;
+
+import java.util.Objects;
+import java.util.function.Predicate;
+
+/**
+ * FormatChecker
+ *
+ * This class is used to check whether the string satisfy the underscore 
format(like DSL), without throw Exception.
+ * For example, to check whether the string can be converted to integer, you 
can use below format, it can
+ * check "1", "-123", and "-143". More complex example is DateTimeChecker
+ *
+ * <pre>
+ *     FormatChecker checker = and(
+ *       option(chars(c -> c == '+' || c == '-')),
+ *       digit(1)
+ *     );
+ *
+ *     checker.check(new StringInspector("+12345"))
+ * </pre>
+ */
+public abstract class FormatChecker {
+    public final String name;
+
+    public FormatChecker(String name) {
+        this.name = Objects.requireNonNull(name, "name can not be null");
+    }
+
+    protected abstract boolean doCheck(StringInspect stringInspect);
+
+    /** check */
+    public final CheckResult check(StringInspect stringInspect) {
+        int checkStartIndex = stringInspect.index();
+        boolean matches = doCheck(stringInspect);
+        int checkEndIndex = stringInspect.index();
+        CheckResult checkResult = new CheckResult(this, stringInspect, 
matches, checkStartIndex, checkEndIndex);
+        if (!matches) {
+            checkResult.stepBack();
+        }
+        return checkResult;
+    }
+
+    protected <T extends FormatChecker> DebugChecker<T> debug(T childChecker, 
Predicate<T> debugPoint) {
+        return debug("DebugChecker", childChecker, debugPoint);
+    }
+
+    protected <T extends FormatChecker> DebugChecker<T> debug(String name, T 
childChecker, Predicate<T> debugPoint) {
+        return new DebugChecker<>(name, childChecker, debugPoint);
+    }
+
+    protected OptionChecker option(FormatChecker checker) {
+        return option("OptionChecker", checker);
+    }
+
+    protected OptionChecker option(String name, FormatChecker checker) {
+        return new OptionChecker(name, checker);
+    }
+
+    protected AndChecker and(FormatChecker... checkers) {
+        return and("AndChecker", checkers);
+    }
+
+    protected AndChecker and(String name, FormatChecker... checkers) {
+        return new AndChecker(name, Utils.fastToImmutableList(checkers));
+    }
+
+    protected OrChecker or(FormatChecker... checkers) {
+        return or("OrChecker", checkers);
+    }
+
+    protected OrChecker or(String name, FormatChecker... checkers) {
+        return new OrChecker(name, Utils.fastToImmutableList(checkers));
+    }
+
+    protected AtLeastChecker atLeast(int minCount, Predicate<Character> 
checker) {
+        return atLeast("AtLeastChecker", minCount, -1, checker);
+    }
+
+    protected AtLeastChecker atLeast(String name, int minCount, 
Predicate<Character> checker) {
+        return new AtLeastChecker(name, minCount, -1, checker);
+    }
+
+    protected AtLeastChecker atLeast(int minCount, int maxRead, 
Predicate<Character> checker) {
+        return atLeast("AtLeastChecker", minCount, maxRead, checker);
+    }
+
+    protected AtLeastChecker atLeast(String name, int minCount, int maxRead, 
Predicate<Character> checker) {
+        return new AtLeastChecker(name, minCount, maxRead, checker);
+    }
+
+    protected DigitChecker digit(int minCount) {
+        return digit("DigitChecker", minCount, -1);
+    }
+
+    protected DigitChecker digit(String name, int minCount) {
+        return new DigitChecker(name, minCount, -1);
+    }
+
+    protected DigitChecker digit(int minCount, int maxRead) {
+        return digit("DigitChecker", minCount, maxRead);
+    }
+
+    protected DigitChecker digit(String name, int minCount, int maxRead) {
+        return new DigitChecker(name, minCount, maxRead);
+    }
+
+    protected LetterChecker letter(int minCount) {
+        return letter("LetterChecker", minCount, -1);
+    }
+
+    protected LetterChecker letter(String name, int minCount) {
+        return new LetterChecker(name, minCount, -1);
+    }
+
+    protected LetterChecker letter(int minCount, int maxRead) {
+        return letter("LetterChecker", minCount, maxRead);
+    }
+
+    protected LetterChecker letter(String name, int minCount, int maxRead) {
+        return new LetterChecker(name, minCount, maxRead);
+    }
+
+    protected CharChecker ch(char c) {
+        return ch("CharChecker", c);
+    }
+
+    protected CharChecker ch(String name, char c) {
+        return new CharChecker(name, c);
+    }
+
+    protected CustomCharChecker chars(Predicate<Character> checker) {
+        return chars("CustomCharChecker", checker);
+    }
+
+    protected CustomCharChecker chars(String name, Predicate<Character> 
checker) {
+        return new CustomCharChecker(name, checker);
+    }
+
+    protected StringChecker string(String equalsTo) {
+        return string("StringChecker", equalsTo);
+    }
+
+    protected StringChecker string(String name, String equalsTo) {
+        return new StringChecker(name, equalsTo);
+    }
+
+    @Override
+    public String toString() {
+        return name;
+    }
+}
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/format/IntegerChecker.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/format/IntegerChecker.java
new file mode 100644
index 00000000000..54efc875705
--- /dev/null
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/format/IntegerChecker.java
@@ -0,0 +1,43 @@
+// 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.literal.format;
+
+/** IntegerChecker */
+public class IntegerChecker extends FormatChecker {
+    private static final IntegerChecker INSTANCE = new IntegerChecker();
+
+    private final FormatChecker checker;
+
+    private IntegerChecker() {
+        super("IntegerChecker");
+        checker = and(
+            option(chars(c -> c == '+' || c == '-')),
+            digit(1)
+        );
+    }
+
+    public static boolean isValidInteger(String string) {
+        StringInspect stringInspect = new StringInspect(string);
+        return INSTANCE.check(stringInspect).matched && stringInspect.eos();
+    }
+
+    @Override
+    protected boolean doCheck(StringInspect stringInspect) {
+        return checker.check(stringInspect).matched;
+    }
+}
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/format/LetterChecker.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/format/LetterChecker.java
new file mode 100644
index 00000000000..d4ba3131608
--- /dev/null
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/format/LetterChecker.java
@@ -0,0 +1,45 @@
+// 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.literal.format;
+
+/** LetterChecker */
+public class LetterChecker extends FormatChecker {
+    private final int minCount;
+    private final int maxRead;
+
+    public LetterChecker(String name, int minCount, int maxRead) {
+        super(name);
+        this.minCount = minCount;
+        this.maxRead = maxRead;
+    }
+
+    @Override
+    protected boolean doCheck(StringInspect stringInspect) {
+        int numberCount = 0;
+        boolean checkRead = maxRead >= 0;
+        while (!stringInspect.eos() && (!checkRead || numberCount < maxRead)) {
+            char c = stringInspect.lookAt();
+            if (!(('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z'))) {
+                break;
+            }
+            stringInspect.step();
+            numberCount++;
+        }
+        return numberCount >= minCount;
+    }
+}
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/format/OptionChecker.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/format/OptionChecker.java
new file mode 100644
index 00000000000..0946c95fefc
--- /dev/null
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/format/OptionChecker.java
@@ -0,0 +1,36 @@
+// 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.literal.format;
+
+import java.util.Objects;
+
+/** OptionChecker */
+public class OptionChecker extends FormatChecker {
+    private final FormatChecker checker;
+
+    public OptionChecker(String name, FormatChecker checker) {
+        super(name);
+        this.checker = Objects.requireNonNull(checker, "checker can not be 
null");
+    }
+
+    @Override
+    protected boolean doCheck(StringInspect stringInspect) {
+        checker.check(stringInspect);
+        return true;
+    }
+}
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/format/OrChecker.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/format/OrChecker.java
new file mode 100644
index 00000000000..dbf109d8193
--- /dev/null
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/format/OrChecker.java
@@ -0,0 +1,55 @@
+// 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.literal.format;
+
+import org.apache.doris.nereids.util.Utils;
+
+import java.util.List;
+import java.util.Objects;
+
+/** OrChecker */
+public class OrChecker extends FormatChecker {
+    private final List<FormatChecker> checkers;
+
+    public OrChecker(String name, List<FormatChecker> checkers) {
+        super(name);
+        this.checkers = Utils.fastToImmutableList(
+                Objects.requireNonNull(checkers, "checkers can not be null")
+        );
+    }
+
+    @Override
+    protected boolean doCheck(StringInspect stringInspect) {
+        int maxMatches = -1;
+        CheckResult maxMatchesResult = null;
+        for (FormatChecker checker : checkers) {
+            CheckResult checkResult = checker.check(stringInspect);
+            if (checkResult.matched && checkResult.matchesLength() > 
maxMatches) {
+                maxMatches = checkResult.matchesLength();
+                maxMatchesResult = checkResult;
+            }
+            checkResult.stepBack();
+        }
+        if (maxMatches >= 0) {
+            stringInspect.setIndex(maxMatchesResult.checkEndIndex);
+            return true;
+        } else {
+            return false;
+        }
+    }
+}
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/format/StringChecker.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/format/StringChecker.java
new file mode 100644
index 00000000000..e1bf9e0f9b5
--- /dev/null
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/format/StringChecker.java
@@ -0,0 +1,44 @@
+// 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.literal.format;
+
+import java.util.Objects;
+
+/** StringChecker */
+public class StringChecker extends FormatChecker {
+    private final String str;
+
+    public StringChecker(String name, String str) {
+        super(name);
+        this.str = Objects.requireNonNull(str, "str can not be null");
+    }
+
+    @Override
+    protected boolean doCheck(StringInspect stringInspect) {
+        if (stringInspect.remain() < str.length()) {
+            return false;
+        }
+
+        for (int i = 0; i < str.length(); i++) {
+            if (stringInspect.lookAndStep() != str.charAt(i)) {
+                return false;
+            }
+        }
+        return true;
+    }
+}
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/format/StringInspect.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/format/StringInspect.java
new file mode 100644
index 00000000000..fab366b6078
--- /dev/null
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/format/StringInspect.java
@@ -0,0 +1,64 @@
+// 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.literal.format;
+
+import java.util.Objects;
+
+/**
+ * StringInspect, a simple lexer can save and move the index
+ */
+public class StringInspect {
+    public final String str;
+    private int index;
+
+    public StringInspect(String str) {
+        this.str = Objects.requireNonNull(str, "str cannot be null");
+    }
+
+    public boolean eos() {
+        return index >= str.length();
+    }
+
+    public int remain() {
+        return str.length() - index;
+    }
+
+    public char lookAt() {
+        return str.charAt(index);
+    }
+
+    public void step() {
+        this.index++;
+    }
+
+    public void step(int step) {
+        this.index += step;
+    }
+
+    public void setIndex(int index) {
+        this.index = index;
+    }
+
+    public char lookAndStep() {
+        return str.charAt(index++);
+    }
+
+    public int index() {
+        return index;
+    }
+}
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/types/DecimalV3Type.java 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/types/DecimalV3Type.java
index aaef3775b34..3dd2ae35c3e 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/types/DecimalV3Type.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/types/DecimalV3Type.java
@@ -20,6 +20,7 @@ package org.apache.doris.nereids.types;
 import org.apache.doris.catalog.ScalarType;
 import org.apache.doris.catalog.Type;
 import org.apache.doris.nereids.annotation.Developing;
+import org.apache.doris.nereids.exceptions.AnalysisException;
 import org.apache.doris.nereids.exceptions.NotSupportedException;
 import org.apache.doris.nereids.types.coercion.FractionalType;
 import org.apache.doris.qe.ConnectContext;
@@ -136,15 +137,25 @@ public class DecimalV3Type extends FractionalType {
             enableDecimal256 = 
connectContext.getSessionVariable().isEnableDecimal256();
         }
         if (enableDecimal256) {
-            Preconditions.checkArgument(precision > 0 && precision <= 
MAX_DECIMAL256_PRECISION,
-                    "precision should in (0, " + MAX_DECIMAL256_PRECISION + 
"], but real precision is " + precision);
+            if (!(precision > 0 && precision <= MAX_DECIMAL256_PRECISION)) {
+                throw new AnalysisException(
+                        "precision should in (0, " + MAX_DECIMAL256_PRECISION 
+ "], but real precision is " + precision
+                );
+            }
         } else {
-            Preconditions.checkArgument(precision > 0 && precision <= 
MAX_DECIMAL128_PRECISION,
-                    "precision should in (0, " + MAX_DECIMAL128_PRECISION + 
"], but real precision is " + precision);
+            if (!(precision > 0 && precision <= MAX_DECIMAL128_PRECISION)) {
+                throw new AnalysisException(
+                        "precision should in (0, " + MAX_DECIMAL128_PRECISION 
+ "], but real precision is " + precision
+                );
+            }
+        }
+        if (scale < 0) {
+            throw new AnalysisException("scale should not smaller than 0, but 
real scale is " + scale);
+        }
+        if (precision < scale) {
+            throw new AnalysisException("precision should not smaller than 
scale,"
+                    + " but precision is " + precision + ", scale is " + 
scale);
         }
-        Preconditions.checkArgument(scale >= 0, "scale should not smaller than 
0, but real scale is " + scale);
-        Preconditions.checkArgument(precision >= scale, "precision should not 
smaller than scale,"
-                + " but precision is " + precision, ", scale is " + scale);
         return new DecimalV3Type(precision, scale);
     }
 
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 651e018c20e..3acf4508ac9 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
@@ -66,11 +66,15 @@ import 
org.apache.doris.nereids.trees.expressions.literal.LargeIntLiteral;
 import org.apache.doris.nereids.trees.expressions.literal.Literal;
 import org.apache.doris.nereids.trees.expressions.literal.MapLiteral;
 import org.apache.doris.nereids.trees.expressions.literal.NullLiteral;
+import org.apache.doris.nereids.trees.expressions.literal.Result;
 import org.apache.doris.nereids.trees.expressions.literal.SmallIntLiteral;
 import org.apache.doris.nereids.trees.expressions.literal.StringLikeLiteral;
 import org.apache.doris.nereids.trees.expressions.literal.StringLiteral;
 import org.apache.doris.nereids.trees.expressions.literal.TinyIntLiteral;
 import org.apache.doris.nereids.trees.expressions.literal.VarcharLiteral;
+import 
org.apache.doris.nereids.trees.expressions.literal.format.DateTimeChecker;
+import org.apache.doris.nereids.trees.expressions.literal.format.FloatChecker;
+import 
org.apache.doris.nereids.trees.expressions.literal.format.IntegerChecker;
 import org.apache.doris.nereids.types.ArrayType;
 import org.apache.doris.nereids.types.BigIntType;
 import org.apache.doris.nereids.types.BooleanType;
@@ -534,7 +538,7 @@ public class TypeCoercionUtils {
                 if ("false".equalsIgnoreCase(value)) {
                     ret = BooleanLiteral.FALSE;
                 }
-            } else if (dataType instanceof TinyIntType) {
+            } else if (dataType instanceof TinyIntType && 
IntegerChecker.isValidInteger(value)) {
                 BigInteger bigInt = new BigInteger(value);
                 if (BigInteger.valueOf(bigInt.byteValue()).equals(bigInt)) {
                     ret = new TinyIntLiteral(bigInt.byteValue());
@@ -547,7 +551,7 @@ public class TypeCoercionUtils {
                 } else {
                     ret = new LargeIntLiteral(bigInt);
                 }
-            } else if (dataType instanceof SmallIntType) {
+            } else if (dataType instanceof SmallIntType && 
IntegerChecker.isValidInteger(value)) {
                 BigInteger bigInt = new BigInteger(value);
                 if (BigInteger.valueOf(bigInt.shortValue()).equals(bigInt)) {
                     ret = new SmallIntLiteral(bigInt.shortValue());
@@ -558,7 +562,7 @@ public class TypeCoercionUtils {
                 } else {
                     ret = new LargeIntLiteral(bigInt);
                 }
-            } else if (dataType instanceof IntegerType) {
+            } else if (dataType instanceof IntegerType && 
IntegerChecker.isValidInteger(value)) {
                 BigInteger bigInt = new BigInteger(value);
                 if (BigInteger.valueOf(bigInt.intValue()).equals(bigInt)) {
                     ret = new IntegerLiteral(bigInt.intValue());
@@ -567,23 +571,23 @@ public class TypeCoercionUtils {
                 } else {
                     ret = new LargeIntLiteral(bigInt);
                 }
-            } else if (dataType instanceof BigIntType) {
+            } else if (dataType instanceof BigIntType && 
IntegerChecker.isValidInteger(value)) {
                 BigInteger bigInt = new BigInteger(value);
                 if (BigInteger.valueOf(bigInt.longValue()).equals(bigInt)) {
                     ret = new BigIntLiteral(bigInt.longValueExact());
                 } else {
                     ret = new LargeIntLiteral(bigInt);
                 }
-            } else if (dataType instanceof LargeIntType) {
+            } else if (dataType instanceof LargeIntType && 
IntegerChecker.isValidInteger(value)) {
                 BigInteger bigInt = new BigInteger(value);
                 ret = new LargeIntLiteral(bigInt);
-            } else if (dataType instanceof FloatType) {
+            } else if (dataType instanceof FloatType && 
FloatChecker.isValidFloat(value)) {
                 ret = new FloatLiteral(Float.parseFloat(value));
-            } else if (dataType instanceof DoubleType) {
+            } else if (dataType instanceof DoubleType && 
FloatChecker.isValidFloat(value)) {
                 ret = new DoubleLiteral(Double.parseDouble(value));
-            } else if (dataType instanceof DecimalV2Type) {
+            } else if (dataType instanceof DecimalV2Type && 
FloatChecker.isValidFloat(value)) {
                 ret = new DecimalLiteral(new BigDecimal(value));
-            } else if (dataType instanceof DecimalV3Type) {
+            } else if (dataType instanceof DecimalV3Type && 
FloatChecker.isValidFloat(value)) {
                 ret = new DecimalV3Literal((DecimalV3Type) dataType, new 
BigDecimal(value));
             } else if (dataType instanceof CharType) {
                 ret = new VarcharLiteral(value, ((CharType) 
dataType).getLen());
@@ -591,22 +595,24 @@ public class TypeCoercionUtils {
                 ret = new VarcharLiteral(value, ((VarcharType) 
dataType).getLen());
             } else if (dataType instanceof StringType) {
                 ret = new StringLiteral(value);
-            } else if (dataType.isDateTimeV2Type()) {
-                ret = new DateTimeV2Literal(value);
-            } else if (dataType.isDateTimeType()) {
-                ret = new DateTimeLiteral(value);
-            } else if (dataType.isDateV2Type()) {
-                try {
-                    ret = new DateV2Literal(value);
-                } catch (AnalysisException e) {
-                    ret = new DateTimeV2Literal(value);
-                }
-            } else if (dataType.isDateType()) {
-                try {
-                    ret = new DateLiteral(value);
-                } catch (AnalysisException e) {
-                    ret = new DateTimeLiteral(value);
+            } else if (dataType.isDateTimeV2Type() && 
DateTimeChecker.isValidDateTime(value)) {
+                ret = DateTimeLiteral.parseDateTimeLiteral(value, 
true).orElse(null);
+            } else if (dataType.isDateTimeType() && 
DateTimeChecker.isValidDateTime(value)) {
+                ret = DateTimeLiteral.parseDateTimeLiteral(value, 
false).orElse(null);
+            } else if (dataType.isDateV2Type() && 
DateTimeChecker.isValidDateTime(value)) {
+                Result<DateLiteral, AnalysisException> parseResult
+                        = DateV2Literal.parseDateLiteral(value);
+                if (parseResult.isOk()) {
+                    ret = parseResult.get();
+                } else {
+                    Result<DateTimeLiteral, AnalysisException> parseResult2
+                            = DateTimeV2Literal.parseDateTimeLiteral(value, 
true);
+                    if (parseResult2.isOk()) {
+                        ret = parseResult2.get();
+                    }
                 }
+            } else if (dataType.isDateType() && 
DateTimeChecker.isValidDateTime(value)) {
+                ret = DateLiteral.parseDateLiteral(value).orElse(null);
             }
         } catch (Exception e) {
             if (LOG.isDebugEnabled()) {
diff --git 
a/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/expressions/literal/DateLiteralTest.java
 
b/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/expressions/literal/DateLiteralTest.java
index 7c8ad5ed0e6..8db1c9446d0 100644
--- 
a/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/expressions/literal/DateLiteralTest.java
+++ 
b/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/expressions/literal/DateLiteralTest.java
@@ -36,22 +36,22 @@ class DateLiteralTest {
 
     @Test
     void testNormalize() {
-        String s = DateLiteral.normalize("2021-5");
+        String s = DateLiteral.normalize("2021-5").get();
         Assertions.assertEquals("2021-05", s);
-        s = DateLiteral.normalize("2021-5-1");
+        s = DateLiteral.normalize("2021-5-1").get();
         Assertions.assertEquals("2021-05-01", s);
-        s = DateLiteral.normalize("2021-5-01");
+        s = DateLiteral.normalize("2021-5-01").get();
         Assertions.assertEquals("2021-05-01", s);
 
-        s = DateLiteral.normalize("2021-5-01 0:0:0");
+        s = DateLiteral.normalize("2021-5-01 0:0:0").get();
         Assertions.assertEquals("2021-05-01 00:00:00", s);
-        s = DateLiteral.normalize("2021-5-01 0:0:0.001");
+        s = DateLiteral.normalize("2021-5-01 0:0:0.001").get();
         Assertions.assertEquals("2021-05-01 00:00:00.001", s);
-        s = DateLiteral.normalize("2021-5-01 0:0:0.12345678");
+        s = DateLiteral.normalize("2021-5-01 0:0:0.12345678").get();
         Assertions.assertEquals("2021-05-01 00:00:00.1234567", s);
-        s = DateLiteral.normalize("2021-5-1    Asia/Shanghai");
+        s = DateLiteral.normalize("2021-5-1    Asia/Shanghai").get();
         Assertions.assertEquals("2021-05-01Asia/Shanghai", s);
-        s = DateLiteral.normalize("2021-5-1 0:0:0.12345678   Asia/Shanghai");
+        s = DateLiteral.normalize("2021-5-1 0:0:0.12345678   
Asia/Shanghai").get();
         Assertions.assertEquals("2021-05-01 00:00:00.1234567Asia/Shanghai", s);
     }
 
diff --git 
a/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/expressions/literal/DateTimeLiteralTest.java
 
b/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/expressions/literal/DateTimeLiteralTest.java
index 68e2d80826b..54b0ea1e6c3 100644
--- 
a/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/expressions/literal/DateTimeLiteralTest.java
+++ 
b/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/expressions/literal/DateTimeLiteralTest.java
@@ -17,6 +17,7 @@
 
 package org.apache.doris.nereids.trees.expressions.literal;
 
+import 
org.apache.doris.nereids.trees.expressions.literal.format.DateTimeChecker;
 import org.apache.doris.nereids.types.DateTimeV2Type;
 
 import org.junit.jupiter.api.Assertions;
@@ -24,20 +25,22 @@ import org.junit.jupiter.api.Disabled;
 import org.junit.jupiter.api.Test;
 
 import java.util.function.Consumer;
+import java.util.function.Function;
 
 class DateTimeLiteralTest {
     @Test
     void reject() {
         // Assertions.assertThrows(IllegalArgumentException.class, () -> {
-        //     new DateTimeV2Literal("2022-08-01T01:01:01-00:00");
+        //     check("", DateTimeV2Literal::new"2022-08-01T01:01:01-00:00");
         // });
     }
 
     @Test
     void mysqlStrangeCase() {
-        new DateTimeV2Literal("0-08-01 13:21:03");
-        new DateTimeV2Literal("0001-01-01: 00:01:01.001");
-        new DateTimeV2Literal("2021?01?01 00.00.00");
+        check("0-08-01 13:21:03", DateTimeV2Literal::new);
+        check("0-08-01 13:21:03", DateTimeV2Literal::new);
+        check("0001-01-01: 00:01:01.001", DateTimeV2Literal::new);
+        check("2021?01?01 00.00.00", DateTimeV2Literal::new);
     }
 
     @Test
@@ -51,43 +54,43 @@ class DateTimeLiteralTest {
             Assertions.assertEquals(2, datetime.second);
         };
 
-        assertFunc.accept(new DateTimeV2Literal("20220801010102"));
-        assertFunc.accept(new DateTimeV2Literal("20220801T010102"));
-        assertFunc.accept(new DateTimeV2Literal("220801010102"));
-        assertFunc.accept(new DateTimeV2Literal("220801T010102"));
-        assertFunc.accept(new DateTimeV2Literal("20220801010101.9999999"));
+        assertFunc.accept(check("20220801010102", DateTimeV2Literal::new));
+        assertFunc.accept(check("20220801T010102", DateTimeV2Literal::new));
+        assertFunc.accept(check("220801010102", DateTimeV2Literal::new));
+        assertFunc.accept(check("220801T010102", DateTimeV2Literal::new));
+        assertFunc.accept(check("20220801010101.9999999", 
DateTimeV2Literal::new));
     }
 
     @Test
     void testMicrosecond() {
         DateTimeV2Literal literal;
-        literal = new DateTimeV2Literal("2016-07-02 00:00:00.123");
+        literal = check("2016-07-02 00:00:00.123", DateTimeV2Literal::new);
         Assertions.assertEquals(123000, literal.microSecond);
-        literal = new DateTimeV2Literal("2016-07-02 00:00:00.123456");
+        literal = check("2016-07-02 00:00:00.123456", DateTimeV2Literal::new);
         Assertions.assertEquals(123456, literal.microSecond);
-        literal = new DateTimeV2Literal("2016-07-02 00:00:00.1");
+        literal = check("2016-07-02 00:00:00.1", DateTimeV2Literal::new);
         Assertions.assertEquals(100000, literal.microSecond);
-        literal = new DateTimeV2Literal("2016-07-02 00:00:00.000001");
+        literal = check("2016-07-02 00:00:00.000001", DateTimeV2Literal::new);
         Assertions.assertEquals(1, literal.microSecond);
-        literal = new DateTimeV2Literal("2016-07-02 00:00:00.12345");
+        literal = check("2016-07-02 00:00:00.12345", DateTimeV2Literal::new);
         Assertions.assertEquals(123450, literal.microSecond);
     }
 
     @Test
     void testWithoutZoneOrOffset() {
-        new DateTimeV2Literal("2022-08-01");
+        check("2022-08-01", DateTimeV2Literal::new);
 
-        new DateTimeV2Literal("2022-08-01 01:01:01");
-        new DateTimeV2Literal("2022-08-01 01:01");
-        new DateTimeV2Literal("2022-08-01 01");
+        check("2022-08-01 01:01:01", DateTimeV2Literal::new);
+        check("2022-08-01 01:01", DateTimeV2Literal::new);
+        check("2022-08-01 01", DateTimeV2Literal::new);
 
-        new DateTimeV2Literal("2022-08-01T01:01:01");
-        new DateTimeV2Literal("2022-08-01T01:01");
-        new DateTimeV2Literal("2022-08-01T01");
+        check("2022-08-01T01:01:01", DateTimeV2Literal::new);
+        check("2022-08-01T01:01", DateTimeV2Literal::new);
+        check("2022-08-01T01", DateTimeV2Literal::new);
 
-        new DateTimeV2Literal("22-08-01T01:01:01");
-        new DateTimeV2Literal("22-08-01T01:01");
-        new DateTimeV2Literal("22-08-01T01");
+        check("22-08-01T01:01:01", DateTimeV2Literal::new);
+        check("22-08-01T01:01", DateTimeV2Literal::new);
+        check("22-08-01T01", DateTimeV2Literal::new);
     }
 
     @Test
@@ -112,102 +115,102 @@ class DateTimeLiteralTest {
 
     @Test
     void testTwoDigitYear() {
-        new DateTimeV2Literal("22-08-01T01");
-        new DateTimeV2Literal("22-08-01 01");
-        new DateTimeV2Literal("22-08-01T01:01");
-        new DateTimeV2Literal("22-08-01 01:01");
-        new DateTimeV2Literal("22-08-01T01:01:01");
-        new DateTimeV2Literal("22-08-01 01:01:01");
-        new DateTimeV2Literal("22-08-01T01");
-        new DateTimeV2Literal("22-08-01 01");
-        new DateTimeV2Literal("22-08-01T01:01");
-        new DateTimeV2Literal("22-08-01 01:01");
-        new DateTimeV2Literal("22-08-01T01:01:01");
-        new DateTimeV2Literal("22-08-01 01:01:01");
+        check("22-08-01T01", DateTimeV2Literal::new);
+        check("22-08-01 01", DateTimeV2Literal::new);
+        check("22-08-01T01:01", DateTimeV2Literal::new);
+        check("22-08-01 01:01", DateTimeV2Literal::new);
+        check("22-08-01T01:01:01", DateTimeV2Literal::new);
+        check("22-08-01 01:01:01", DateTimeV2Literal::new);
+        check("22-08-01T01", DateTimeV2Literal::new);
+        check("22-08-01 01", DateTimeV2Literal::new);
+        check("22-08-01T01:01", DateTimeV2Literal::new);
+        check("22-08-01 01:01", DateTimeV2Literal::new);
+        check("22-08-01T01:01:01", DateTimeV2Literal::new);
+        check("22-08-01 01:01:01", DateTimeV2Literal::new);
     }
 
     @Test
     void testZone() {
-        new DateTimeV2Literal("2022-08-01 01:01:01UTC");
-        new DateTimeV2Literal("2022-08-01 01:01:01UT");
-        new DateTimeV2Literal("2022-08-01 01:01:01GMT");
-        new DateTimeV2Literal("2022-08-01 01:01:01Z");
-        new DateTimeV2Literal("2022-08-01 01:01:01Europe/London");
-        new DateTimeV2Literal("2022-08-01 01:01:01America/New_York");
-        new DateTimeV2Literal("2022-08-01 01:01:01Z");
-        new DateTimeV2Literal("2022-08-01 01:01:01Europe/Berlin");
-        new DateTimeV2Literal("2022-08-01 01:01:01Europe/London");
-        new DateTimeV2Literal("2022-08-01 00:00:00Asia/Shanghai");
+        check("2022-08-01 01:01:01UTC", DateTimeV2Literal::new);
+        check("2022-08-01 01:01:01UT", DateTimeV2Literal::new);
+        check("2022-08-01 01:01:01GMT", DateTimeV2Literal::new);
+        check("2022-08-01 01:01:01Z", DateTimeV2Literal::new);
+        check("2022-08-01 01:01:01Europe/London", DateTimeV2Literal::new);
+        check("2022-08-01 01:01:01America/New_York", DateTimeV2Literal::new);
+        check("2022-08-01 01:01:01Z", DateTimeV2Literal::new);
+        check("2022-08-01 01:01:01Europe/Berlin", DateTimeV2Literal::new);
+        check("2022-08-01 01:01:01Europe/London", DateTimeV2Literal::new);
+        check("2022-08-01 00:00:00Asia/Shanghai", DateTimeV2Literal::new);
     }
 
     @Test
     void testTwoDigitalYearZone() {
-        new DateTimeV2Literal("22-08-01 01:01:01UTC");
-        new DateTimeV2Literal("22-08-01 01:01:01UT");
-        new DateTimeV2Literal("22-08-01 01:01:01GMT");
-        new DateTimeV2Literal("22-08-01 01:01:01Z");
-        new DateTimeV2Literal("22-08-01 01:01:01Europe/London");
-        new DateTimeV2Literal("22-08-01 01:01:01UTC");
-        new DateTimeV2Literal("22-08-01 01:01:01America/New_York");
-        new DateTimeV2Literal("22-08-01 01:01:01Z");
-        new DateTimeV2Literal("22-08-01 01:01:01Europe/Berlin");
-        new DateTimeV2Literal("22-08-01 01:01:01Europe/London");
+        check("22-08-01 01:01:01UTC", DateTimeV2Literal::new);
+        check("22-08-01 01:01:01UT", DateTimeV2Literal::new);
+        check("22-08-01 01:01:01GMT", DateTimeV2Literal::new);
+        check("22-08-01 01:01:01Z", DateTimeV2Literal::new);
+        check("22-08-01 01:01:01Europe/London", DateTimeV2Literal::new);
+        check("22-08-01 01:01:01UTC", DateTimeV2Literal::new);
+        check("22-08-01 01:01:01America/New_York", DateTimeV2Literal::new);
+        check("22-08-01 01:01:01Z", DateTimeV2Literal::new);
+        check("22-08-01 01:01:01Europe/Berlin", DateTimeV2Literal::new);
+        check("22-08-01 01:01:01Europe/London", DateTimeV2Literal::new);
     }
 
     @Test
     @Disabled
     void testTwoDigitalYearZoneOffset() {
-        new DateTimeV2Literal("22-08-01 01:01:01UTC+01:01:01");
-        new DateTimeV2Literal("22-08-01 01:01:01UTC+1:1:1");
+        check("22-08-01 01:01:01UTC+01:01:01", DateTimeV2Literal::new);
+        check("22-08-01 01:01:01UTC+1:1:1", DateTimeV2Literal::new);
 
-        new DateTimeV2Literal("22-08-01 01:01:01UTC+01:01");
+        check("22-08-01 01:01:01UTC+01:01", DateTimeV2Literal::new);
 
-        new DateTimeV2Literal("22-08-01 01:01:01UTC+01");
-        new DateTimeV2Literal("22-08-01 01:01:01UTC+1");
+        check("22-08-01 01:01:01UTC+01", DateTimeV2Literal::new);
+        check("22-08-01 01:01:01UTC+1", DateTimeV2Literal::new);
     }
 
     @Test
     void testOffset() {
-        new DateTimeV2Literal("2022-05-01 01:02:55+02:30");
-        new DateTimeV2Literal("2022-05-01 01:02:55.123-02:30");
-        new DateTimeV2Literal("2022-06-01T01:02:55+04:30");
-        new DateTimeV2Literal("2022-06-01 01:02:55.123-07:30");
-        new DateTimeV2Literal("2022-05-01 01:02:55+02:30");
-
-        new DateTimeV2Literal("2022-05-01 01:02:55.123-02:30");
-        new DateTimeV2Literal("2022-06-01T01:02:55+04:30");
-        new DateTimeV2Literal("2022-06-01 01:02:55.123-07:30");
-
-        new DateTimeV2Literal("20220701010255+07:00");
-        new DateTimeV2Literal("20220701010255-05:00");
+        check("2022-05-01 01:02:55+02:30", DateTimeV2Literal::new);
+        check("2022-05-01 01:02:55.123-02:30", DateTimeV2Literal::new);
+        check("2022-06-01T01:02:55+04:30", DateTimeV2Literal::new);
+        check("2022-06-01 01:02:55.123-07:30", DateTimeV2Literal::new);
+        check("2022-05-01 01:02:55+02:30", DateTimeV2Literal::new);
+
+        check("2022-05-01 01:02:55.123-02:30", DateTimeV2Literal::new);
+        check("2022-06-01T01:02:55+04:30", DateTimeV2Literal::new);
+        check("2022-06-01 01:02:55.123-07:30", DateTimeV2Literal::new);
+
+        check("20220701010255+07:00", DateTimeV2Literal::new);
+        check("20220701010255-05:00", DateTimeV2Literal::new);
     }
 
     @Test
     @Disabled
     void testDateTimeZone() {
-        new DateTimeV2Literal("0001-01-01 00:01:01");
-        new DateTimeV2Literal("0001-01-01 00:01:01.001");
-        new DateTimeV2Literal("0001-01-01 00:01:01.00305");
-
-        new DateTimeV2Literal("2022-01-01 01:02:55");
-        new DateTimeV2Literal("2022-01-01 01:02:55.123");
-        new DateTimeV2Literal("2022-02-01 01:02:55Z");
-        new DateTimeV2Literal("2022-02-01 01:02:55.123Z");
-        new DateTimeV2Literal("2022-03-01 01:02:55UTC+8");
-        new DateTimeV2Literal("2022-03-01 01:02:55.123UTC");
-        new DateTimeV2Literal("2022-04-01 01:02:55UTC-6");
-        new DateTimeV2Literal("2022-04-01T01:02:55UTC-6");
-        new DateTimeV2Literal("2022-04-01T01:02:55.123UTC+6");
-
-        new DateTimeV2Literal("2022-01-01 01:02:55");
-        new DateTimeV2Literal("2022-01-01 01:02:55.123");
-        new DateTimeV2Literal("2022-02-01 01:02:55Z");
-        new DateTimeV2Literal("2022-02-01 01:02:55.123Z");
-        new DateTimeV2Literal("2022-03-01 01:02:55UTC+8");
-        new DateTimeV2Literal("2022-03-01 01:02:55.123UTC");
-        new DateTimeV2Literal("2022-04-01T01:02:55UTC-6");
-
-        new DateTimeV2Literal("0001-01-01");
+        check("0001-01-01 00:01:01", DateTimeV2Literal::new);
+        check("0001-01-01 00:01:01.001", DateTimeV2Literal::new);
+        check("0001-01-01 00:01:01.00305", DateTimeV2Literal::new);
+
+        check("2022-01-01 01:02:55", DateTimeV2Literal::new);
+        check("2022-01-01 01:02:55.123", DateTimeV2Literal::new);
+        check("2022-02-01 01:02:55Z", DateTimeV2Literal::new);
+        check("2022-02-01 01:02:55.123Z", DateTimeV2Literal::new);
+        check("2022-03-01 01:02:55UTC+8", DateTimeV2Literal::new);
+        check("2022-03-01 01:02:55.123UTC", DateTimeV2Literal::new);
+        check("2022-04-01 01:02:55UTC-6", DateTimeV2Literal::new);
+        check("2022-04-01T01:02:55UTC-6", DateTimeV2Literal::new);
+        check("2022-04-01T01:02:55.123UTC+6", DateTimeV2Literal::new);
+
+        check("2022-01-01 01:02:55", DateTimeV2Literal::new);
+        check("2022-01-01 01:02:55.123", DateTimeV2Literal::new);
+        check("2022-02-01 01:02:55Z", DateTimeV2Literal::new);
+        check("2022-02-01 01:02:55.123Z", DateTimeV2Literal::new);
+        check("2022-03-01 01:02:55UTC+8", DateTimeV2Literal::new);
+        check("2022-03-01 01:02:55.123UTC", DateTimeV2Literal::new);
+        check("2022-04-01T01:02:55UTC-6", DateTimeV2Literal::new);
+
+        check("0001-01-01", DateTimeV2Literal::new);
     }
 
     @Test
@@ -221,191 +224,191 @@ class DateTimeLiteralTest {
             Assertions.assertEquals(0, datetime.second);
         };
         DateTimeV2Literal literal;
-        literal = new DateTimeV2Literal("2022-01-02 12:00:00UTC+08:00");
+        literal = check("2022-01-02 12:00:00UTC+08:00", 
DateTimeV2Literal::new);
         assertFunc.accept(literal);
-        literal = new DateTimeV2Literal("2022-01-02 04:00:00UTC");
+        literal = check("2022-01-02 04:00:00UTC", DateTimeV2Literal::new);
         assertFunc.accept(literal);
-        literal = new DateTimeV2Literal("2022-01-01 20:00:00UTC-08:00");
+        literal = check("2022-01-01 20:00:00UTC-08:00", 
DateTimeV2Literal::new);
         assertFunc.accept(literal);
-        literal = new DateTimeV2Literal("2022-01-02 04:00:00Z");
+        literal = check("2022-01-02 04:00:00Z", DateTimeV2Literal::new);
         assertFunc.accept(literal);
     }
 
     @Test
     void testIrregularDateTime() {
 
-        new DateTimeV2Literal("2016-7-02 01:01:00");
-        new DateTimeV2Literal("2016-07-2 01:01:00");
-        new DateTimeV2Literal("2016-7-2 01:01:00");
-
-        new DateTimeV2Literal("2016-07-02 1:01:00");
-        new DateTimeV2Literal("2016-07-02 01:1:00");
-        new DateTimeV2Literal("2016-07-02 01:01:0");
-        new DateTimeV2Literal("2016-07-02 1:1:00");
-        new DateTimeV2Literal("2016-07-02 1:01:0");
-        new DateTimeV2Literal("2016-07-02 10:1:0");
-        new DateTimeV2Literal("2016-07-02 1:1:0");
-
-        new DateTimeV2Literal("2016-7-2 1:1:0");
-        new DateTimeV2Literal("2016-7-02 1:01:0");
-        new DateTimeV2Literal("2016-07-2 1:1:0");
-        new DateTimeV2Literal("2016-7-02 01:01:0");
-        new DateTimeV2Literal("2016-7-2 01:1:0");
+        check("2016-7-02 01:01:00", DateTimeV2Literal::new);
+        check("2016-07-2 01:01:00", DateTimeV2Literal::new);
+        check("2016-7-2 01:01:00", DateTimeV2Literal::new);
+
+        check("2016-07-02 1:01:00", DateTimeV2Literal::new);
+        check("2016-07-02 01:1:00", DateTimeV2Literal::new);
+        check("2016-07-02 01:01:0", DateTimeV2Literal::new);
+        check("2016-07-02 1:1:00", DateTimeV2Literal::new);
+        check("2016-07-02 1:01:0", DateTimeV2Literal::new);
+        check("2016-07-02 10:1:0", DateTimeV2Literal::new);
+        check("2016-07-02 1:1:0", DateTimeV2Literal::new);
+
+        check("2016-7-2 1:1:0", DateTimeV2Literal::new);
+        check("2016-7-02 1:01:0", DateTimeV2Literal::new);
+        check("2016-07-2 1:1:0", DateTimeV2Literal::new);
+        check("2016-7-02 01:01:0", DateTimeV2Literal::new);
+        check("2016-7-2 01:1:0", DateTimeV2Literal::new);
     }
 
     @Test
     void testIrregularDateTimeHour() {
-        new DateTimeV2Literal("2016-07-02 01");
-        new DateTimeV2Literal("2016-07-02 1");
+        check("2016-07-02 01", DateTimeV2Literal::new);
+        check("2016-07-02 1", DateTimeV2Literal::new);
 
-        new DateTimeV2Literal("2016-7-02 1");
-        new DateTimeV2Literal("2016-7-02 01");
+        check("2016-7-02 1", DateTimeV2Literal::new);
+        check("2016-7-02 01", DateTimeV2Literal::new);
 
-        new DateTimeV2Literal("2016-07-2 1");
-        new DateTimeV2Literal("2016-07-2 01");
+        check("2016-07-2 1", DateTimeV2Literal::new);
+        check("2016-07-2 01", DateTimeV2Literal::new);
 
-        new DateTimeV2Literal("2016-7-2 1");
-        new DateTimeV2Literal("2016-7-2 01");
+        check("2016-7-2 1", DateTimeV2Literal::new);
+        check("2016-7-2 01", DateTimeV2Literal::new);
     }
 
     @Test
     void testIrregularDateTimeHourMinute() {
-        new DateTimeV2Literal("2016-07-02 01:01");
-        new DateTimeV2Literal("2016-07-02 1:01");
-        new DateTimeV2Literal("2016-07-02 01:1");
-        new DateTimeV2Literal("2016-07-02 1:1");
-
-        new DateTimeV2Literal("2016-7-02 01:01");
-        new DateTimeV2Literal("2016-7-02 1:01");
-        new DateTimeV2Literal("2016-7-02 01:1");
-        new DateTimeV2Literal("2016-7-02 1:1");
-
-        new DateTimeV2Literal("2016-07-2 01:01");
-        new DateTimeV2Literal("2016-07-2 1:01");
-        new DateTimeV2Literal("2016-07-2 01:1");
-        new DateTimeV2Literal("2016-07-2 1:1");
-
-        new DateTimeV2Literal("2016-7-2 01:01");
-        new DateTimeV2Literal("2016-7-2 1:01");
-        new DateTimeV2Literal("2016-7-2 01:1");
-        new DateTimeV2Literal("2016-7-2 1:1");
+        check("2016-07-02 01:01", DateTimeV2Literal::new);
+        check("2016-07-02 1:01", DateTimeV2Literal::new);
+        check("2016-07-02 01:1", DateTimeV2Literal::new);
+        check("2016-07-02 1:1", DateTimeV2Literal::new);
+
+        check("2016-7-02 01:01", DateTimeV2Literal::new);
+        check("2016-7-02 1:01", DateTimeV2Literal::new);
+        check("2016-7-02 01:1", DateTimeV2Literal::new);
+        check("2016-7-02 1:1", DateTimeV2Literal::new);
+
+        check("2016-07-2 01:01", DateTimeV2Literal::new);
+        check("2016-07-2 1:01", DateTimeV2Literal::new);
+        check("2016-07-2 01:1", DateTimeV2Literal::new);
+        check("2016-07-2 1:1", DateTimeV2Literal::new);
+
+        check("2016-7-2 01:01", DateTimeV2Literal::new);
+        check("2016-7-2 1:01", DateTimeV2Literal::new);
+        check("2016-7-2 01:1", DateTimeV2Literal::new);
+        check("2016-7-2 1:1", DateTimeV2Literal::new);
     }
 
     @Test
     void testIrregularDateTimeHourMinuteSecond() {
-        new DateTimeV2Literal("2016-07-02 01:01:01");
-        new DateTimeV2Literal("2016-07-02 1:01:01");
-        new DateTimeV2Literal("2016-07-02 01:1:01");
-        new DateTimeV2Literal("2016-07-02 1:1:01");
-        new DateTimeV2Literal("2016-07-02 01:01:1");
-        new DateTimeV2Literal("2016-07-02 1:01:1");
-        new DateTimeV2Literal("2016-07-02 01:1:1");
-        new DateTimeV2Literal("2016-07-02 1:1:1");
-
-        new DateTimeV2Literal("2016-7-02 01:01:01");
-        new DateTimeV2Literal("2016-7-02 1:01:01");
-        new DateTimeV2Literal("2016-7-02 01:1:01");
-        new DateTimeV2Literal("2016-7-02 1:1:01");
-        new DateTimeV2Literal("2016-7-02 01:01:1");
-        new DateTimeV2Literal("2016-7-02 1:01:1");
-        new DateTimeV2Literal("2016-7-02 01:1:1");
-        new DateTimeV2Literal("2016-7-02 1:1:1");
-
-        new DateTimeV2Literal("2016-07-2 01:01:01");
-        new DateTimeV2Literal("2016-07-2 1:01:01");
-        new DateTimeV2Literal("2016-07-2 01:1:01");
-        new DateTimeV2Literal("2016-07-2 1:1:01");
-        new DateTimeV2Literal("2016-07-2 01:01:1");
-        new DateTimeV2Literal("2016-07-2 1:01:1");
-        new DateTimeV2Literal("2016-07-2 01:1:1");
-        new DateTimeV2Literal("2016-07-2 1:1:1");
-
-        new DateTimeV2Literal("2016-7-2 01:01:01");
-        new DateTimeV2Literal("2016-7-2 1:01:01");
-        new DateTimeV2Literal("2016-7-2 01:1:01");
-        new DateTimeV2Literal("2016-7-2 1:1:01");
-        new DateTimeV2Literal("2016-7-2 01:01:1");
-        new DateTimeV2Literal("2016-7-2 1:01:1");
-        new DateTimeV2Literal("2016-7-2 01:1:1");
-        new DateTimeV2Literal("2016-7-2 1:1:1");
+        check("2016-07-02 01:01:01", DateTimeV2Literal::new);
+        check("2016-07-02 1:01:01", DateTimeV2Literal::new);
+        check("2016-07-02 01:1:01", DateTimeV2Literal::new);
+        check("2016-07-02 1:1:01", DateTimeV2Literal::new);
+        check("2016-07-02 01:01:1", DateTimeV2Literal::new);
+        check("2016-07-02 1:01:1", DateTimeV2Literal::new);
+        check("2016-07-02 01:1:1", DateTimeV2Literal::new);
+        check("2016-07-02 1:1:1", DateTimeV2Literal::new);
+
+        check("2016-7-02 01:01:01", DateTimeV2Literal::new);
+        check("2016-7-02 1:01:01", DateTimeV2Literal::new);
+        check("2016-7-02 01:1:01", DateTimeV2Literal::new);
+        check("2016-7-02 1:1:01", DateTimeV2Literal::new);
+        check("2016-7-02 01:01:1", DateTimeV2Literal::new);
+        check("2016-7-02 1:01:1", DateTimeV2Literal::new);
+        check("2016-7-02 01:1:1", DateTimeV2Literal::new);
+        check("2016-7-02 1:1:1", DateTimeV2Literal::new);
+
+        check("2016-07-2 01:01:01", DateTimeV2Literal::new);
+        check("2016-07-2 1:01:01", DateTimeV2Literal::new);
+        check("2016-07-2 01:1:01", DateTimeV2Literal::new);
+        check("2016-07-2 1:1:01", DateTimeV2Literal::new);
+        check("2016-07-2 01:01:1", DateTimeV2Literal::new);
+        check("2016-07-2 1:01:1", DateTimeV2Literal::new);
+        check("2016-07-2 01:1:1", DateTimeV2Literal::new);
+        check("2016-07-2 1:1:1", DateTimeV2Literal::new);
+
+        check("2016-7-2 01:01:01", DateTimeV2Literal::new);
+        check("2016-7-2 1:01:01", DateTimeV2Literal::new);
+        check("2016-7-2 01:1:01", DateTimeV2Literal::new);
+        check("2016-7-2 1:1:01", DateTimeV2Literal::new);
+        check("2016-7-2 01:01:1", DateTimeV2Literal::new);
+        check("2016-7-2 1:01:1", DateTimeV2Literal::new);
+        check("2016-7-2 01:1:1", DateTimeV2Literal::new);
+        check("2016-7-2 1:1:1", DateTimeV2Literal::new);
     }
 
     @Test
     void testIrregularDateTimeHourMinuteSecondMicrosecond() {
-        new DateTimeV2Literal("2016-07-02 01:01:01.1");
-        new DateTimeV2Literal("2016-07-02 1:01:01.1");
-        new DateTimeV2Literal("2016-07-02 01:1:01.1");
-        new DateTimeV2Literal("2016-07-02 1:1:01.1");
-        new DateTimeV2Literal("2016-07-02 01:01:1.1");
-        new DateTimeV2Literal("2016-07-02 1:01:1.1");
-        new DateTimeV2Literal("2016-07-02 01:1:1.1");
-        new DateTimeV2Literal("2016-07-02 1:1:1.1");
-
-        new DateTimeV2Literal("2016-7-02 01:01:01.1");
-        new DateTimeV2Literal("2016-7-02 1:01:01.1");
-        new DateTimeV2Literal("2016-7-02 01:1:01.1");
-        new DateTimeV2Literal("2016-7-02 1:1:01.1");
-        new DateTimeV2Literal("2016-7-02 01:01:1.1");
-        new DateTimeV2Literal("2016-7-02 1:01:1.1");
-        new DateTimeV2Literal("2016-7-02 01:1:1.1");
-        new DateTimeV2Literal("2016-7-02 1:1:1.1");
-
-        new DateTimeV2Literal("2016-07-2 01:01:01.1");
-        new DateTimeV2Literal("2016-07-2 1:01:01.1");
-        new DateTimeV2Literal("2016-07-2 01:1:01.1");
-        new DateTimeV2Literal("2016-07-2 1:1:01.1");
-        new DateTimeV2Literal("2016-07-2 01:01:1.1");
-        new DateTimeV2Literal("2016-07-2 1:01:1.1");
-        new DateTimeV2Literal("2016-07-2 01:1:1.1");
-        new DateTimeV2Literal("2016-07-2 1:1:1.1");
-
-        new DateTimeV2Literal("2016-7-2 01:01:01.1");
-        new DateTimeV2Literal("2016-7-2 1:01:01.1");
-        new DateTimeV2Literal("2016-7-2 01:1:01.1");
-        new DateTimeV2Literal("2016-7-2 1:1:01.1");
-        new DateTimeV2Literal("2016-7-2 01:01:1.1");
-        new DateTimeV2Literal("2016-7-2 1:01:1.1");
-        new DateTimeV2Literal("2016-7-2 01:1:1.1");
-        new DateTimeV2Literal("2016-7-2 1:1:1.1");
+        check("2016-07-02 01:01:01.1", DateTimeV2Literal::new);
+        check("2016-07-02 1:01:01.1", DateTimeV2Literal::new);
+        check("2016-07-02 01:1:01.1", DateTimeV2Literal::new);
+        check("2016-07-02 1:1:01.1", DateTimeV2Literal::new);
+        check("2016-07-02 01:01:1.1", DateTimeV2Literal::new);
+        check("2016-07-02 1:01:1.1", DateTimeV2Literal::new);
+        check("2016-07-02 01:1:1.1", DateTimeV2Literal::new);
+        check("2016-07-02 1:1:1.1", DateTimeV2Literal::new);
+
+        check("2016-7-02 01:01:01.1", DateTimeV2Literal::new);
+        check("2016-7-02 1:01:01.1", DateTimeV2Literal::new);
+        check("2016-7-02 01:1:01.1", DateTimeV2Literal::new);
+        check("2016-7-02 1:1:01.1", DateTimeV2Literal::new);
+        check("2016-7-02 01:01:1.1", DateTimeV2Literal::new);
+        check("2016-7-02 1:01:1.1", DateTimeV2Literal::new);
+        check("2016-7-02 01:1:1.1", DateTimeV2Literal::new);
+        check("2016-7-02 1:1:1.1", DateTimeV2Literal::new);
+
+        check("2016-07-2 01:01:01.1", DateTimeV2Literal::new);
+        check("2016-07-2 1:01:01.1", DateTimeV2Literal::new);
+        check("2016-07-2 01:1:01.1", DateTimeV2Literal::new);
+        check("2016-07-2 1:1:01.1", DateTimeV2Literal::new);
+        check("2016-07-2 01:01:1.1", DateTimeV2Literal::new);
+        check("2016-07-2 1:01:1.1", DateTimeV2Literal::new);
+        check("2016-07-2 01:1:1.1", DateTimeV2Literal::new);
+        check("2016-07-2 1:1:1.1", DateTimeV2Literal::new);
+
+        check("2016-7-2 01:01:01.1", DateTimeV2Literal::new);
+        check("2016-7-2 1:01:01.1", DateTimeV2Literal::new);
+        check("2016-7-2 01:1:01.1", DateTimeV2Literal::new);
+        check("2016-7-2 1:1:01.1", DateTimeV2Literal::new);
+        check("2016-7-2 01:01:1.1", DateTimeV2Literal::new);
+        check("2016-7-2 1:01:1.1", DateTimeV2Literal::new);
+        check("2016-7-2 01:1:1.1", DateTimeV2Literal::new);
+        check("2016-7-2 1:1:1.1", DateTimeV2Literal::new);
 
         // Testing with microsecond of length 2
-        new DateTimeV2Literal("2016-07-02 01:01:01.12");
-        new DateTimeV2Literal("2016-7-02 01:01:01.12");
+        check("2016-07-02 01:01:01.12", DateTimeV2Literal::new);
+        check("2016-7-02 01:01:01.12", DateTimeV2Literal::new);
 
         // Testing with microsecond of length 3
-        new DateTimeV2Literal("2016-07-02 01:01:01.123");
-        new DateTimeV2Literal("2016-7-02 01:01:01.123");
+        check("2016-07-02 01:01:01.123", DateTimeV2Literal::new);
+        check("2016-7-02 01:01:01.123", DateTimeV2Literal::new);
 
         // Testing with microsecond of length 4
-        new DateTimeV2Literal("2016-07-02 01:01:01.1234");
-        new DateTimeV2Literal("2016-7-02 01:01:01.1234");
+        check("2016-07-02 01:01:01.1234", DateTimeV2Literal::new);
+        check("2016-7-02 01:01:01.1234", DateTimeV2Literal::new);
 
         // Testing with microsecond of length 5
-        new DateTimeV2Literal("2016-07-02 01:01:01.12345");
-        new DateTimeV2Literal("2016-7-02 01:01:01.12345");
+        check("2016-07-02 01:01:01.12345", DateTimeV2Literal::new);
+        check("2016-7-02 01:01:01.12345", DateTimeV2Literal::new);
 
         // Testing with microsecond of length 6
-        new DateTimeV2Literal("2016-07-02 01:01:01.123456");
-        new DateTimeV2Literal("2016-7-02 01:01:01.123456");
+        check("2016-07-02 01:01:01.123456", DateTimeV2Literal::new);
+        check("2016-7-02 01:01:01.123456", DateTimeV2Literal::new);
 
         // Testing with microsecond of length 7
-        DateTimeV2Literal literal = new DateTimeV2Literal("2016-07-02 
01:01:01.12345678");
+        DateTimeV2Literal literal = check("2016-07-02 01:01:01.12345678", 
DateTimeV2Literal::new);
         Assertions.assertEquals(123457, literal.microSecond);
 
-        literal = new DateTimeV2Literal("2016-07-02 01:01:01.44444444");
+        literal = check("2016-07-02 01:01:01.44444444", 
DateTimeV2Literal::new);
         Assertions.assertEquals(444444, literal.microSecond);
 
-        literal = new DateTimeV2Literal("2016-07-02 01:01:01.44444445");
+        literal = check("2016-07-02 01:01:01.44444445", 
DateTimeV2Literal::new);
         Assertions.assertEquals(444444, literal.microSecond);
 
-        literal = new DateTimeV2Literal("2016-07-02 01:01:01.4444445");
+        literal = check("2016-07-02 01:01:01.4444445", DateTimeV2Literal::new);
         Assertions.assertEquals(444445, literal.microSecond);
 
-        literal = new DateTimeV2Literal("2016-07-02 01:01:01.9999995");
+        literal = check("2016-07-02 01:01:01.9999995", DateTimeV2Literal::new);
         Assertions.assertEquals(0, literal.microSecond);
         Assertions.assertEquals(2, literal.second);
 
-        literal = new DateTimeV2Literal("2021-01-01 23:59:59.9999995");
+        literal = check("2021-01-01 23:59:59.9999995", DateTimeV2Literal::new);
         Assertions.assertEquals(0, literal.microSecond);
         Assertions.assertEquals(0, literal.second);
         Assertions.assertEquals(0, literal.minute);
@@ -415,33 +418,33 @@ class DateTimeLiteralTest {
     @Test
     void testDateTimeV2Scale() {
         Assertions.assertEquals(
-                new DateTimeV2Literal(DateTimeV2Type.of(3), "2016-07-02 
00:00:00.123"),
-                new DateTimeV2Literal(DateTimeV2Type.of(3), "2016-07-02 
00:00:00.123"));
+                check("2016-07-02 00:00:00.123", s -> new 
DateTimeV2Literal(DateTimeV2Type.of(3), s)),
+                check("2016-07-02 00:00:00.123", s -> new 
DateTimeV2Literal(DateTimeV2Type.of(3), s)));
 
         Assertions.assertEquals(
-                new DateTimeV2Literal(DateTimeV2Type.of(3), "2016-07-02 
00:00:00.123456"),
-                new DateTimeV2Literal(DateTimeV2Type.of(3), "2016-07-02 
00:00:00.123"));
+                check("2016-07-02 00:00:00.123456", s -> new 
DateTimeV2Literal(DateTimeV2Type.of(3), s)),
+                check("2016-07-02 00:00:00.123", s -> new 
DateTimeV2Literal(DateTimeV2Type.of(3), s)));
 
         Assertions.assertEquals(
-                new DateTimeV2Literal(DateTimeV2Type.of(4), "2016-07-02 
00:00:00.12345"),
-                new DateTimeV2Literal(DateTimeV2Type.of(4), "2016-07-02 
00:00:00.1235"));
+                check("2016-07-02 00:00:00.12345", s -> new 
DateTimeV2Literal(DateTimeV2Type.of(4), s)),
+                check("2016-07-02 00:00:00.1235", s -> new 
DateTimeV2Literal(DateTimeV2Type.of(4), s)));
 
         Assertions.assertEquals(
-                new DateTimeV2Literal(DateTimeV2Type.of(0), "2016-07-02 
00:00:00.12345"),
-                new DateTimeV2Literal(DateTimeV2Type.of(0), "2016-07-02 
00:00:00"));
+                check("2016-07-02 00:00:00.12345", s -> new 
DateTimeV2Literal(DateTimeV2Type.of(0), s)),
+                check("2016-07-02 00:00:00", s -> new 
DateTimeV2Literal(DateTimeV2Type.of(0), s)));
 
         Assertions.assertEquals(
-                new DateTimeV2Literal(DateTimeV2Type.of(0), "2016-07-02 
00:00:00.5123"),
-                new DateTimeV2Literal(DateTimeV2Type.of(0), "2016-07-02 
00:00:01"));
+                check("2016-07-02 00:00:00.5123", s -> new 
DateTimeV2Literal(DateTimeV2Type.of(0), s)),
+                check("2016-07-02 00:00:01", s -> new 
DateTimeV2Literal(DateTimeV2Type.of(0), s)));
 
         Assertions.assertEquals(
-                new DateTimeV2Literal(DateTimeV2Type.of(5), "2016-07-02 
00:00:00.999999"),
-                new DateTimeV2Literal(DateTimeV2Type.of(5), "2016-07-02 
00:00:01.00000"));
+                check("2016-07-02 00:00:00.999999", s -> new 
DateTimeV2Literal(DateTimeV2Type.of(5), s)),
+                check("2016-07-02 00:00:01.00000", s -> new 
DateTimeV2Literal(DateTimeV2Type.of(5), s)));
 
         // test overflow
         Assertions.assertEquals(
-                new DateTimeV2Literal(DateTimeV2Type.of(5), "2016-12-31 
23:59:59.999999"),
-                new DateTimeV2Literal(DateTimeV2Type.of(5), "2017-01-01 
00:00:00.00000"));
+                check("2016-12-31 23:59:59.999999", s -> new 
DateTimeV2Literal(DateTimeV2Type.of(5), s)),
+                check("2017-01-01 00:00:00.00000", s -> new 
DateTimeV2Literal(DateTimeV2Type.of(5), s)));
     }
 
     @Test
@@ -485,4 +488,9 @@ class DateTimeLiteralTest {
         Assertions.assertEquals(l1, l2);
         Assertions.assertNotEquals(l1, l3);
     }
+
+    private <L extends DateLiteral> L check(String str, Function<String, L> 
literalBuilder) {
+        Assertions.assertTrue(DateTimeChecker.isValidDateTime(str), "Invalid 
date: " + str);
+        return literalBuilder.apply(str);
+    }
 }
diff --git 
a/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/expressions/literal/FloatLiteralTest.java
 
b/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/expressions/literal/FloatLiteralTest.java
new file mode 100644
index 00000000000..11561846afe
--- /dev/null
+++ 
b/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/expressions/literal/FloatLiteralTest.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.literal;
+
+import org.apache.doris.nereids.trees.expressions.literal.format.FloatChecker;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+import java.math.BigDecimal;
+import java.util.function.Function;
+
+public class FloatLiteralTest {
+    @Test
+    public void testChecker() {
+        assertValid(
+                "123.45",
+                "-34.56",
+                "0",
+                "0.01",
+                "10000",
+                "+1",
+                "-1",
+                "+1",
+                "1.0",
+                "-1.0",
+                "-1.0e3",
+                ".1",
+                "1.",
+                "1e3"
+        );
+
+        assertInValid(
+                "e3",
+                "abc",
+                "12.34.56",
+                "1,234.56"
+        );
+
+        Assertions.assertThrows(
+                Throwable.class,
+                () -> check("e3", s -> new FloatLiteral(new 
BigDecimal(s).floatValue()))
+        );
+    }
+
+    private void assertValid(String...validString) {
+        for (String str : validString) {
+            check(str, s -> new FloatLiteral(new BigDecimal(s).floatValue()));
+        }
+    }
+
+    private void assertInValid(String...validString) {
+        for (String str : validString) {
+            Assertions.assertThrows(
+                    Throwable.class,
+                    () -> check(str, s -> new FloatLiteral(new 
BigDecimal(s).floatValue()))
+            );
+        }
+    }
+
+    private <T extends FractionalLiteral> T check(String str, Function<String, 
T> literalBuilder) {
+        Assertions.assertTrue(FloatChecker.isValidFloat(str), "Invalid 
fractional: " + str);
+        return literalBuilder.apply(str);
+    }
+}
diff --git 
a/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/expressions/literal/IntegerLiteralTest.java
 
b/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/expressions/literal/IntegerLiteralTest.java
new file mode 100644
index 00000000000..9f23d7fd5ff
--- /dev/null
+++ 
b/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/expressions/literal/IntegerLiteralTest.java
@@ -0,0 +1,64 @@
+// 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.literal;
+
+import 
org.apache.doris.nereids.trees.expressions.literal.format.IntegerChecker;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+import java.math.BigInteger;
+import java.util.function.Function;
+
+public class IntegerLiteralTest {
+    @Test
+    public void testChecker() {
+        assertValid(
+                "1",
+                "+1",
+                "-1",
+                "456"
+        );
+
+        assertInValid(
+                "1.0",
+                "1e3",
+                "abc"
+        );
+    }
+
+    private void assertValid(String...validString) {
+        for (String str : validString) {
+            check(str, s -> new IntegerLiteral(new 
BigInteger(s).intValueExact()));
+        }
+    }
+
+    private void assertInValid(String...validString) {
+        for (String str : validString) {
+            Assertions.assertThrows(
+                    Throwable.class,
+                    () -> check(str, s -> new IntegerLiteral(new 
BigInteger(s).intValueExact()))
+            );
+        }
+    }
+
+    private <T extends IntegerLikeLiteral> T check(String str, 
Function<String, T> literalBuilder) {
+        Assertions.assertTrue(IntegerChecker.isValidInteger(str), "Invalid 
integer: " + str);
+        return literalBuilder.apply(str);
+    }
+}


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscr...@doris.apache.org
For additional commands, e-mail: commits-h...@doris.apache.org

Reply via email to