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

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


The following commit(s) were added to refs/heads/master by this push:
     new 61725116570 [fix](expr opt) Handle maximum date in function rewrite 
(#67815)
61725116570 is described below

commit 617251165709d8e4ac917b5a493d7c1dfd821a4d
Author: morrySnow <[email protected]>
AuthorDate: Fri Sep 11 14:35:53 2026 +0800

    [fix](expr opt) Handle maximum date in function rewrite (#67815)
    
    ### What problem does this PR solve?
    
    Problem Summary:
    
    A valid comparison against the maximum supported date failed during
    planning:
    
    ```sql
    EXPLAIN SELECT * FROM t_datetime
    WHERE DATE(dt) > '9999-12-31';
    ```
    
    `DateFunctionRewrite` normally converts `DATE(datetime) > date_literal`
    into a comparison with the beginning of the following day. For
    `9999-12-31`, constructing that bound creates year 10000, which is
    outside the Doris date domain and raises `datetime out of range`.
    
    The rewrite now detects when the following day is outside the supported
    range. Because no non-null `DATETIME` or `DATETIMEV2` value can have a
    date above the maximum date, it simplifies the predicate to false while
    preserving NULL semantics through `falseOrNull`. Other dates continue to
    use the existing range rewrite.
    
    Unit tests cover both datetime families, nullable values, and the
    preceding day. Regression tests reproduce the original planning failure
    for `DATETIME` and `DATETIMEV2(6)` and verify both filter and projection
    semantics.
    
    ### Release note
    
    Fix planning failures for `DATE` comparisons at the maximum supported
    date.
    
    ### Check List (For Author)
    
    - Test: Unit Test and Regression Test
    - Behavior changed: Yes. An impossible upper-bound predicate is safely
    simplified instead of failing planning.
    - Does this need documentation: No
---
 .../expression/rules/DateFunctionRewrite.java      | 23 +++++++++++++---
 .../expression/rules/DateFunctionRewriteTest.java  | 26 ++++++++++++++++++
 .../date_function_rewrite.out                      |  9 ++++++
 .../date_function_rewrite.groovy                   | 32 +++++++++++++++++++++-
 4 files changed, 85 insertions(+), 5 deletions(-)

diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/DateFunctionRewrite.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/DateFunctionRewrite.java
index 92b89221b43..84a70ba936e 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/DateFunctionRewrite.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/DateFunctionRewrite.java
@@ -36,6 +36,7 @@ import 
org.apache.doris.nereids.trees.expressions.literal.DateV2Literal;
 import org.apache.doris.nereids.types.DateTimeType;
 import org.apache.doris.nereids.types.DateTimeV2Type;
 import org.apache.doris.nereids.types.TimeStampNsType;
+import org.apache.doris.nereids.util.ExpressionUtils;
 
 import com.google.common.collect.ImmutableList;
 
@@ -103,21 +104,35 @@ public class DateFunctionRewrite implements 
ExpressionPatternRuleFactory {
             // V1
             if (greaterThan.left().child(0).getDataType() instanceof 
DateTimeType
                     && greaterThan.right() instanceof DateLiteral) {
-                DateTimeLiteral newLiteral = ((DateLiteral) 
greaterThan.right()).toBeginOfTomorrow();
-                return new GreaterThanEqual(greaterThan.left().child(0), 
newLiteral);
+                Expression dateTime = greaterThan.left().child(0);
+                DateLiteral date = (DateLiteral) greaterThan.right();
+                if (isTomorrowOutOfRange(date)) {
+                    return ExpressionUtils.falseOrNull(dateTime);
+                }
+                DateTimeLiteral newLiteral = date.toBeginOfTomorrow();
+                return new GreaterThanEqual(dateTime, newLiteral);
             }
 
             // V2
             if (greaterThan.left().child(0).getDataType() instanceof 
DateTimeV2Type
                     && greaterThan.right() instanceof DateV2Literal) {
-                DateTimeV2Literal newLiteral = ((DateV2Literal) 
greaterThan.right()).toBeginOfTomorrow();
-                return new GreaterThanEqual(greaterThan.left().child(0), 
newLiteral);
+                Expression dateTime = greaterThan.left().child(0);
+                DateV2Literal date = (DateV2Literal) greaterThan.right();
+                if (isTomorrowOutOfRange(date)) {
+                    return ExpressionUtils.falseOrNull(dateTime);
+                }
+                DateTimeV2Literal newLiteral = date.toBeginOfTomorrow();
+                return new GreaterThanEqual(dateTime, newLiteral);
             }
         }
 
         return greaterThan;
     }
 
+    private static boolean isTomorrowOutOfRange(DateLiteral date) {
+        return DateLiteral.isDateOutOfRange(date.toJavaDateType().plusDays(1));
+    }
+
     private static Expression rewriteGreaterThanEqual(GreaterThanEqual 
greaterThanEqual) {
         if (isTimeStampNsDateComparison(greaterThanEqual)) {
             return rewriteTimeStampNsDateComparison(greaterThanEqual);
diff --git 
a/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/expression/rules/DateFunctionRewriteTest.java
 
b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/expression/rules/DateFunctionRewriteTest.java
index 721414f0f70..03e464328a2 100644
--- 
a/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/expression/rules/DateFunctionRewriteTest.java
+++ 
b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/expression/rules/DateFunctionRewriteTest.java
@@ -28,12 +28,18 @@ import org.apache.doris.nereids.trees.expressions.LessThan;
 import org.apache.doris.nereids.trees.expressions.LessThanEqual;
 import org.apache.doris.nereids.trees.expressions.SlotReference;
 import org.apache.doris.nereids.trees.expressions.functions.scalar.Date;
+import org.apache.doris.nereids.trees.expressions.literal.DateLiteral;
+import org.apache.doris.nereids.trees.expressions.literal.DateTimeLiteral;
+import org.apache.doris.nereids.trees.expressions.literal.DateTimeV2Literal;
 import org.apache.doris.nereids.trees.expressions.literal.DateV2Literal;
 import org.apache.doris.nereids.trees.expressions.literal.TimeStampNsLiteral;
+import org.apache.doris.nereids.types.DateTimeType;
+import org.apache.doris.nereids.types.DateTimeV2Type;
 import org.apache.doris.nereids.types.TimeStampNsType;
 import org.apache.doris.nereids.util.ExpressionUtils;
 
 import com.google.common.collect.ImmutableList;
+import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 
@@ -81,4 +87,24 @@ class DateFunctionRewriteTest extends 
ExpressionRewriteTestHelper {
         assertRewrite(new GreaterThanEqual(dateFunction, beforeMin), 
ExpressionUtils.trueOrNull(timestampNs));
         assertRewrite(new LessThanEqual(dateFunction, afterMax), 
ExpressionUtils.trueOrNull(timestampNs));
     }
+
+    @Test
+    void testRewriteGreaterThanAtMaximumDate() {
+        Expression dateTime = new SlotReference("dateTime", 
DateTimeType.INSTANCE, true);
+        DateLiteral maxDate = new DateLiteral("9999-12-31");
+        Assertions.assertEquals(ExpressionUtils.falseOrNull(dateTime), 
executor.rewrite(
+                new GreaterThan(new Date(dateTime), maxDate), context));
+
+        Expression dateTimeV2 = new SlotReference("dateTimeV2", 
DateTimeV2Type.of(6), true);
+        DateV2Literal maxDateV2 = new DateV2Literal("9999-12-31");
+        assertRewrite(new GreaterThan(new Date(dateTimeV2), maxDateV2), 
ExpressionUtils.falseOrNull(dateTimeV2));
+
+        DateLiteral previousDate = new DateLiteral("9999-12-30");
+        Assertions.assertEquals(new GreaterThanEqual(dateTime, new 
DateTimeLiteral("9999-12-31 00:00:00")),
+                executor.rewrite(new GreaterThan(new Date(dateTime), 
previousDate), context));
+
+        DateV2Literal previousDateV2 = new DateV2Literal("9999-12-30");
+        assertRewrite(new GreaterThan(new Date(dateTimeV2), previousDateV2),
+                new GreaterThanEqual(dateTimeV2, new 
DateTimeV2Literal("9999-12-31 00:00:00")));
+    }
 }
diff --git 
a/regression-test/data/nereids_rules_p0/date_function_rewrite/date_function_rewrite.out
 
b/regression-test/data/nereids_rules_p0/date_function_rewrite/date_function_rewrite.out
index 2ef8304a2a0..f289de300bd 100644
--- 
a/regression-test/data/nereids_rules_p0/date_function_rewrite/date_function_rewrite.out
+++ 
b/regression-test/data/nereids_rules_p0/date_function_rewrite/date_function_rewrite.out
@@ -2,3 +2,12 @@
 -- !test --
 1
 
+-- !date_v1_greater_than_max --
+
+-- !date_v2_greater_than_max --
+
+-- !date_greater_than_max_null_semantics --
+1      false   false
+2      \N      \N
+3      false   false
+
diff --git 
a/regression-test/suites/nereids_rules_p0/date_function_rewrite/date_function_rewrite.groovy
 
b/regression-test/suites/nereids_rules_p0/date_function_rewrite/date_function_rewrite.groovy
index 01afc01431a..0be58e60260 100644
--- 
a/regression-test/suites/nereids_rules_p0/date_function_rewrite/date_function_rewrite.groovy
+++ 
b/regression-test/suites/nereids_rules_p0/date_function_rewrite/date_function_rewrite.groovy
@@ -27,4 +27,34 @@ suite("date_function_rewrite") {
     qt_test """
     select if (date(date_add(FROM_UNIXTIME(t1.test_time, '%Y-%m-%d'),2)) > 
'2023-07-25',1,0) from test_date_func t1;
     """
-}
\ No newline at end of file
+
+    sql "drop table if exists test_date_func_boundary"
+    sql """
+        create table test_date_func_boundary(
+            id int,
+            dt datetime,
+            dtv2 datetimev2(6)
+        ) distributed by hash(id) buckets 1
+        properties("replication_num"="1")
+    """
+    sql """
+        insert into test_date_func_boundary values
+            (1, '9999-12-31 23:59:59', '9999-12-31 23:59:59.999999'),
+            (2, null, null),
+            (3, '9999-12-30 12:00:00', '9999-12-30 12:00:00.123456')
+    """
+
+    qt_date_v1_greater_than_max """
+        select id from test_date_func_boundary where date(dt) > '9999-12-31'
+    """
+
+    qt_date_v2_greater_than_max """
+        select id from test_date_func_boundary where date(dtv2) > '9999-12-31'
+    """
+
+    order_qt_date_greater_than_max_null_semantics """
+        select id, date(dt) > '9999-12-31', date(dtv2) > '9999-12-31'
+        from test_date_func_boundary
+        order by id
+    """
+}


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

Reply via email to