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

mihaibudiu 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 1df1872c88 [CALCITE-7766] Type-mismatch on nullability in 
JoinPushTransitivePredicatesRule for RIGHT join
1df1872c88 is described below

commit 1df1872c88885753ca6091e8055bc18cb12310ea
Author: Ilia Korol <[email protected]>
AuthorDate: Mon Sep 7 17:54:53 2026 +0300

    [CALCITE-7766] Type-mismatch on nullability in 
JoinPushTransitivePredicatesRule for RIGHT join
---
 .../calcite/rel/metadata/RelMdPredicates.java      |  4 +--
 .../org/apache/calcite/test/RelOptRulesTest.java   | 22 +++++++++++++
 .../org/apache/calcite/test/RelOptRulesTest.xml    | 36 ++++++++++++++++++++++
 3 files changed, 59 insertions(+), 3 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 e04e2098ff..c37853448c 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
@@ -140,8 +140,6 @@ public class RelMdPredicates
   public static final RelMetadataProvider SOURCE = 
ReflectiveRelMetadataProvider
       .reflectiveSource(new RelMdPredicates(), 
BuiltInMetadata.Predicates.Handler.class);
 
-  private static final List<RexNode> EMPTY_LIST = ImmutableList.of();
-
   @Override public MetadataDef<BuiltInMetadata.Predicates> getDef() {
     return BuiltInMetadata.Predicates.DEF;
   }
@@ -878,7 +876,7 @@ public RelOptPredicateList inferPredicates(
       case RIGHT:
         return RelOptPredicateList.of(rexBuilder,
             RelOptUtil.conjunctions(rightChildPredicates),
-            inferredPredicates, EMPTY_LIST);
+            leftInferredPredicates, rightInferredPredicates);
       default:
         assert inferredPredicates.isEmpty();
         return RelOptPredicateList.EMPTY;
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 76ff0a8313..198e869177 100644
--- a/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java
+++ b/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java
@@ -7808,6 +7808,28 @@ private HepProgram getTransitiveProgram() {
     sql(sql).withRule(CoreRules.JOIN_PUSH_TRANSITIVE_PREDICATES).check();
   }
 
+  /** As {@link #testJoinPushTransitivePredicatesNullabilityIssue()}, but the 
join is a
+   * RIGHT join, so the predicate is inferred for the left input.
+   *
+   * <p>Test case for
+   * <a 
href="https://issues.apache.org/jira/browse/CALCITE-7766";>[CALCITE-7766]
+   * Type-mismatch on nullability in JoinPushTransitivePredicatesRule for 
RIGHT join</a>. */
+  @Test void testJoinPushTransitivePredicatesNullabilityIssueRightJoin() {
+    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 null_table\n"
+        + "RIGHT JOIN non_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 35dc172427..85d71efdf8 100644
--- a/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml
+++ b/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml
@@ -8943,6 +8943,42 @@ LogicalProject(DATE_COL_NON_NULL=[$0], 
DATE_COL_NULL=[$1])
     LogicalFilter(condition=[=($0, 2023-08-07)])
       LogicalProject(DATE_COL_NULL=[null:DATE])
         LogicalTableScan(table=[[CATALOG, SALES, DEPT]])
+]]>
+    </Resource>
+  </TestCase>
+  <TestCase name="testJoinPushTransitivePredicatesNullabilityIssueRightJoin">
+    <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 null_table
+RIGHT JOIN non_null_table
+ON null_table.date_col_null = non_null_table.date_col_non_null]]>
+    </Resource>
+    <Resource name="planBefore">
+      <![CDATA[
+LogicalProject(DATE_COL_NULL=[$0], DATE_COL_NON_NULL=[$1])
+  LogicalJoin(condition=[=($0, $1)], joinType=[right])
+    LogicalProject(DATE_COL_NULL=[null:DATE])
+      LogicalTableScan(table=[[CATALOG, SALES, DEPT]])
+    LogicalProject(DATE_COL_NON_NULL=[2023-08-07])
+      LogicalTableScan(table=[[CATALOG, SALES, DEPT]])
+]]>
+    </Resource>
+    <Resource name="planAfter">
+      <![CDATA[
+LogicalProject(DATE_COL_NULL=[$0], DATE_COL_NON_NULL=[$1])
+  LogicalJoin(condition=[=($0, $1)], joinType=[right])
+    LogicalFilter(condition=[=($0, 2023-08-07)])
+      LogicalProject(DATE_COL_NULL=[null:DATE])
+        LogicalTableScan(table=[[CATALOG, SALES, DEPT]])
+    LogicalProject(DATE_COL_NON_NULL=[2023-08-07])
+      LogicalTableScan(table=[[CATALOG, SALES, DEPT]])
 ]]>
     </Resource>
   </TestCase>

Reply via email to