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

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


The following commit(s) were added to refs/heads/branch-4.2 by this push:
     new 6281a99c31a branch-4.2: [fix](infer-predicate) Preserve datetime 
precision in predicate inference #67653 (#70015)
6281a99c31a is described below

commit 6281a99c31ac35e05e58bcf1beaf6b9880cdf2a6
Author: morrySnow <[email protected]>
AuthorDate: Tue Nov 3 16:59:36 2026 +0800

    branch-4.2: [fix](infer-predicate) Preserve datetime precision in predicate 
inference #67653 (#70015)
    
    picked from master #67653
    
    Co-authored-by: feiniaofeiafei <[email protected]>
---
 .../doris/nereids/util/PredicateInferUtils.java    |  4 +-
 .../rules/rewrite/InferPredicateByReplaceTest.java | 26 +++++++++++
 .../infer_datetimev2_cast_precision.out            |  7 +++
 .../infer_datetimev2_cast_precision.groovy         | 50 ++++++++++++++++++++++
 4 files changed, 86 insertions(+), 1 deletion(-)

diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/util/PredicateInferUtils.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/util/PredicateInferUtils.java
index d6f7dfc145c..2a3ac016c49 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/util/PredicateInferUtils.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/util/PredicateInferUtils.java
@@ -156,7 +156,9 @@ public class PredicateInferUtils {
                 if (childType.isTimeStampNsType()) {
                     return Optional.empty();
                 }
-                return validForInfer(child, inferType);
+                if (!(childType instanceof DateTimeV2Type) || 
childType.isInjectiveCastTo(dataType)) {
+                    return validForInfer(child, inferType);
+                }
             }
         } else if (inferType == InferType.STRING) {
             // avoid substring cast such as cast(char(3) as char(2))
diff --git 
a/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/rewrite/InferPredicateByReplaceTest.java
 
b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/rewrite/InferPredicateByReplaceTest.java
index 2fec983dd21..ca2d9dc1c79 100644
--- 
a/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/rewrite/InferPredicateByReplaceTest.java
+++ 
b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/rewrite/InferPredicateByReplaceTest.java
@@ -232,6 +232,32 @@ public class InferPredicateByReplaceTest {
         Assertions.assertEquals(3, result.size());
     }
 
+    @Test
+    public void testInferWithDateTimeV2CastPrecision() {
+        for (int sourceScale : new int[] {0, 3, 6}) {
+            SlotReference a = new SlotReference("a", 
DateTimeV2Type.of(sourceScale));
+            SlotReference b = new SlotReference("b", 
DateTimeV2Type.of(sourceScale));
+            InPredicate predicate = new InPredicate(a, ImmutableList.of(
+                    new DateTimeV2Literal(DateTimeV2Type.of(sourceScale), 
"2025-01-01 00:00:00"),
+                    new DateTimeV2Literal(DateTimeV2Type.of(sourceScale), 
"2025-01-01 00:00:01")));
+            InPredicate expected = new InPredicate(b, predicate.getOptions());
+            for (int targetScale : new int[] {0, 3, 6}) {
+                EqualTo equality = new EqualTo(new Cast(a, 
DateTimeV2Type.of(targetScale)),
+                        new Cast(b, DateTimeV2Type.of(targetScale)));
+                Set<Expression> inputs = new 
HashSet<>(ImmutableList.of(equality, predicate));
+                Assertions.assertEquals(sourceScale <= targetScale,
+                        
InferPredicateByReplace.infer(inputs).contains(expected),
+                        "Unexpected inference for scale " + sourceScale + " -> 
" + targetScale);
+            }
+            EqualTo nestedEquality = new EqualTo(
+                    new Cast(new Cast(a, DateTimeV2Type.of(0)), 
DateTimeV2Type.of(6)),
+                    new Cast(new Cast(b, DateTimeV2Type.of(0)), 
DateTimeV2Type.of(6)));
+            Set<Expression> inputs = new 
HashSet<>(ImmutableList.of(nestedEquality, predicate));
+            Assertions.assertEquals(sourceScale == 0, 
InferPredicateByReplace.infer(inputs).contains(expected),
+                    "Nested casts must not hide precision loss");
+        }
+    }
+
     @Test
     public void testValidForInfer() {
         SlotReference a = new SlotReference("a", TinyIntType.INSTANCE);
diff --git 
a/regression-test/data/nereids_rules_p0/infer_predicate/infer_datetimev2_cast_precision.out
 
b/regression-test/data/nereids_rules_p0/infer_predicate/infer_datetimev2_cast_precision.out
new file mode 100644
index 00000000000..d037fd99f05
--- /dev/null
+++ 
b/regression-test/data/nereids_rules_p0/infer_predicate/infer_datetimev2_cast_precision.out
@@ -0,0 +1,7 @@
+-- This file is automatically generated. You should know what you did if you 
want to edit this
+-- !without_inference --
+1      1       10
+
+-- !with_inference --
+1      1       10
+
diff --git 
a/regression-test/suites/nereids_rules_p0/infer_predicate/infer_datetimev2_cast_precision.groovy
 
b/regression-test/suites/nereids_rules_p0/infer_predicate/infer_datetimev2_cast_precision.groovy
new file mode 100644
index 00000000000..5047cd9a0e7
--- /dev/null
+++ 
b/regression-test/suites/nereids_rules_p0/infer_predicate/infer_datetimev2_cast_precision.groovy
@@ -0,0 +1,50 @@
+// 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.
+suite("infer_datetimev2_cast_precision", "p0") {
+    sql "DROP TABLE IF EXISTS infer_datetimev2_cast_l"
+    sql "DROP TABLE IF EXISTS infer_datetimev2_cast_r"
+    sql """
+        CREATE TABLE infer_datetimev2_cast_l (id INT, a DATETIMEV2(6))
+        DUPLICATE KEY(id)
+        DISTRIBUTED BY HASH(id) BUCKETS 1
+        PROPERTIES ("replication_num" = "1")
+    """
+    sql """
+        CREATE TABLE infer_datetimev2_cast_r (id INT, b DATETIMEV2(6))
+        DUPLICATE KEY(id)
+        DISTRIBUTED BY HASH(id) BUCKETS 1
+        PROPERTIES ("replication_num" = "1")
+    """
+    sql "INSERT INTO infer_datetimev2_cast_l VALUES (1, '2025-01-01 
00:00:00.100000')"
+    sql "INSERT INTO infer_datetimev2_cast_r VALUES (10, '2025-01-01 
00:00:00.200000')"
+
+    // Distinct raw values become equal after narrowing the fractional-second 
precision.
+    sql "SET disable_nereids_rules = 'INFER_PREDICATES'"
+    order_qt_without_inference """
+        SELECT COUNT(*) AS cnt, MIN(l.id) AS left_id, MIN(r.id) AS right_id
+        FROM infer_datetimev2_cast_l l JOIN infer_datetimev2_cast_r r
+          ON CAST(l.a AS DATETIMEV2(0)) = CAST(r.b AS DATETIMEV2(0))
+        WHERE l.a IN ('2025-01-01 00:00:00.100000', '2025-01-01 
00:00:00.300000')
+    """
+    sql "SET disable_nereids_rules = ''"
+    order_qt_with_inference """
+        SELECT COUNT(*) AS cnt, MIN(l.id) AS left_id, MIN(r.id) AS right_id
+        FROM infer_datetimev2_cast_l l JOIN infer_datetimev2_cast_r r
+          ON CAST(l.a AS DATETIMEV2(0)) = CAST(r.b AS DATETIMEV2(0))
+        WHERE l.a IN ('2025-01-01 00:00:00.100000', '2025-01-01 
00:00:00.300000')
+    """
+}


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

Reply via email to