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

mbudiu pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/calcite.git


The following commit(s) were added to refs/heads/main by this push:
     new ce6a160397 [CALCITE-5387] Type-mismatch on nullability in 
JoinPushTransitivePredicatesRule RelRule
ce6a160397 is described below

commit ce6a160397aa967ffe85ccb65f37fae8448680d8
Author: Zhen Chen <[email protected]>
AuthorDate: Thu May 1 08:35:15 2025 +0800

    [CALCITE-5387] Type-mismatch on nullability in 
JoinPushTransitivePredicatesRule RelRule
---
 .../calcite/rel/metadata/RelMdPredicates.java      |  4 +--
 .../calcite/rex/RexPermuteInputsShuttle.java       | 42 +++++++++++++++++++---
 .../org/apache/calcite/test/RelOptRulesTest.java   | 19 ++++++++++
 .../org/apache/calcite/test/RelOptRulesTest.xml    | 35 ++++++++++++++++++
 4 files changed, 94 insertions(+), 6 deletions(-)

diff --git 
a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdPredicates.java 
b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdPredicates.java
index cfdc372392..9dcfb8e92e 100644
--- a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdPredicates.java
+++ b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdPredicates.java
@@ -803,12 +803,12 @@ public RelOptPredicateList inferPredicates(
           Mappings.createShiftMapping(nSysFields + nFieldsLeft + nFieldsRight,
               0, nSysFields + nFieldsLeft, nFieldsRight);
       final RexPermuteInputsShuttle rightPermute =
-          new RexPermuteInputsShuttle(rightMapping, joinRel);
+          new RexPermuteInputsShuttle(rightMapping, true, joinRel.getRight());
       Mappings.TargetMapping leftMapping =
           Mappings.createShiftMapping(nSysFields + nFieldsLeft, 0, nSysFields,
               nFieldsLeft);
       final RexPermuteInputsShuttle leftPermute =
-          new RexPermuteInputsShuttle(leftMapping, joinRel);
+          new RexPermuteInputsShuttle(leftMapping, true, joinRel.getLeft());
       final List<RexNode> leftInferredPredicates = new ArrayList<>();
       final List<RexNode> rightInferredPredicates = new ArrayList<>();
 
diff --git 
a/core/src/main/java/org/apache/calcite/rex/RexPermuteInputsShuttle.java 
b/core/src/main/java/org/apache/calcite/rex/RexPermuteInputsShuttle.java
index 9f418b1b72..0906a6610d 100644
--- a/core/src/main/java/org/apache/calcite/rex/RexPermuteInputsShuttle.java
+++ b/core/src/main/java/org/apache/calcite/rex/RexPermuteInputsShuttle.java
@@ -37,6 +37,7 @@ public class RexPermuteInputsShuttle extends RexShuttle {
 
   private final Mappings.TargetMapping mapping;
   private final ImmutableList<RelDataTypeField> fields;
+  private final boolean matchTargetType;
 
   //~ Constructors -----------------------------------------------------------
 
@@ -54,14 +55,41 @@ public class RexPermuteInputsShuttle extends RexShuttle {
   public RexPermuteInputsShuttle(
       Mappings.TargetMapping mapping,
       RelNode... inputs) {
-    this(mapping, fields(inputs));
+    this(mapping, fields(inputs), false);
+  }
+
+  /**
+   * Creates a RexPermuteInputsShuttle.
+   *
+   * <p>The mapping provides at most one target for every source.
+   *
+   * @param mapping               Mapping
+   * @param shouldMatchTargetType If {@code false}, each input reference is 
substituted
+   *                              with a reference retaining the original 
input's type.
+   *                              If {@code true}, each input reference is 
substituted
+   *                              with a reference matching the target type.
+   * @param inputs                Input relational expressions
+   */
+  public RexPermuteInputsShuttle(
+      Mappings.TargetMapping mapping,
+      boolean shouldMatchTargetType,
+      RelNode... inputs) {
+    this(mapping, fields(inputs), shouldMatchTargetType);
   }
 
   private RexPermuteInputsShuttle(
       Mappings.TargetMapping mapping,
       ImmutableList<RelDataTypeField> fields) {
+    this(mapping, fields, false);
+  }
+
+  private RexPermuteInputsShuttle(
+      Mappings.TargetMapping mapping,
+      ImmutableList<RelDataTypeField> fields,
+      boolean matchTargetType) {
     this.mapping = mapping;
     this.fields = fields;
+    this.matchTargetType = matchTargetType;
   }
 
   /** Creates a shuttle with an empty field list. It cannot handle GET calls 
but
@@ -85,9 +113,15 @@ private static ImmutableList<RelDataTypeField> 
fields(RelNode[] inputs) {
   @Override public RexNode visitInputRef(RexInputRef local) {
     final int index = local.getIndex();
     int target = mapping.getTarget(index);
-    return new RexInputRef(
-        target,
-        local.getType());
+    if (!matchTargetType) {
+      return new RexInputRef(
+          target,
+          local.getType());
+    } else {
+      return new RexInputRef(
+          target,
+          fields.get(target).getType());
+    }
   }
 
   @Override public RexNode visitCall(RexCall call) {
diff --git a/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java 
b/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java
index 65c9f41723..3278dab3e5 100644
--- a/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java
+++ b/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java
@@ -6896,6 +6896,25 @@ private HepProgram getTransitiveProgram() {
         .checkUnchanged();
   }
 
+  /** Test case for
+   * <a 
href="https://issues.apache.org/jira/browse/CALCITE-5387";>[CALCITE-5387]
+   * Type-mismatch on nullability in JoinPushTransitivePredicatesRule 
RelRule</a>. */
+  @Test void testJoinPushTransitivePredicatesNullabilityIssue() {
+    final String sql = "WITH\n"
+        + "non_null_table AS (\n"
+        + "  SELECT DATE '2023-08-07' AS date_col_non_null FROM dept\n"
+        + "),\n"
+        + "null_table AS (\n"
+        + "  SELECT CAST(null as DATE) AS date_col_null FROM dept\n"
+        + ")\n"
+        + "SELECT *\n"
+        + "FROM non_null_table\n"
+        + "JOIN null_table\n"
+        + "ON null_table.date_col_null = non_null_table.date_col_non_null";
+
+    sql(sql).withRule(CoreRules.JOIN_PUSH_TRANSITIVE_PREDICATES).check();
+  }
+
   /** Test case of
    * <a 
href="https://issues.apache.org/jira/browse/CALCITE-6432";>[CALCITE-6432]
    * Infinite loop for JoinPushTransitivePredicatesRule</a>. */
diff --git 
a/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml 
b/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml
index 1a4a98bbb8..37915af905 100644
--- a/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml
+++ b/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml
@@ -7468,6 +7468,41 @@ LogicalProject(DEPTNO=[$0], NAME=[$1], R=[$3], 
EXPR$1=[$4])
       LogicalTableScan(table=[[CATALOG, SALES, DEPT]])
       LogicalProject(R=[RANK() OVER (ORDER BY $1)], EXPR$1=[+(1, 1)])
         LogicalTableScan(table=[[CATALOG, SALES, DEPT]])
+]]>
+    </Resource>
+  </TestCase>
+  <TestCase name="testJoinPushTransitivePredicatesNullabilityIssue">
+    <Resource name="sql">
+      <![CDATA[WITH
+non_null_table AS (
+  SELECT DATE '2023-08-07' AS date_col_non_null FROM dept
+),
+null_table AS (
+  SELECT CAST(null as DATE) AS date_col_null FROM dept
+)
+SELECT *
+FROM non_null_table
+JOIN null_table
+ON null_table.date_col_null = non_null_table.date_col_non_null]]>
+    </Resource>
+    <Resource name="planBefore">
+      <![CDATA[
+LogicalProject(DATE_COL_NON_NULL=[$0], DATE_COL_NULL=[$1])
+  LogicalJoin(condition=[=($1, $0)], joinType=[inner])
+    LogicalProject(DATE_COL_NON_NULL=[2023-08-07])
+      LogicalTableScan(table=[[CATALOG, SALES, DEPT]])
+    LogicalProject(DATE_COL_NULL=[null:DATE])
+      LogicalTableScan(table=[[CATALOG, SALES, DEPT]])
+]]>
+    </Resource>
+    <Resource name="planAfter">
+      <![CDATA[
+LogicalProject(DATE_COL_NON_NULL=[$0], DATE_COL_NULL=[$1])
+  LogicalJoin(condition=[=($1, $0)], joinType=[inner])
+    LogicalValues(tuples=[[]])
+    LogicalFilter(condition=[=($0, 2023-08-07)])
+      LogicalProject(DATE_COL_NULL=[null:DATE])
+        LogicalTableScan(table=[[CATALOG, SALES, DEPT]])
 ]]>
     </Resource>
   </TestCase>

Reply via email to