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>