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 186bb62a75 [CALCITE-6501] Assertion Error in JoinUnifyRule Due to Type 
Mismatch
186bb62a75 is described below

commit 186bb62a751e2713b44989003a0789804db3cd21
Author: suibianwanwan <[email protected]>
AuthorDate: Tue Aug 13 12:56:06 2024 +0800

    [CALCITE-6501] Assertion Error in JoinUnifyRule Due to Type Mismatch
---
 .../apache/calcite/plan/SubstitutionVisitor.java   |  44 +++++++++
 .../MaterializedViewSubstitutionVisitorTest.java   | 105 +++++++++++++++++++++
 2 files changed, 149 insertions(+)

diff --git 
a/core/src/main/java/org/apache/calcite/plan/SubstitutionVisitor.java 
b/core/src/main/java/org/apache/calcite/plan/SubstitutionVisitor.java
index 4688a4bb7a..fba9e92fdd 100644
--- a/core/src/main/java/org/apache/calcite/plan/SubstitutionVisitor.java
+++ b/core/src/main/java/org/apache/calcite/plan/SubstitutionVisitor.java
@@ -1226,6 +1226,12 @@ public class SubstitutionVisitor {
       if (!canPullUpFilterUnderJoin(joinRelType, qInput0Cond, null)) {
         return null;
       }
+
+      // Check if join project nullable can be pull up
+      if (!canPullUpProjectUnderJoin(joinRelType, qInput0Projs, null)) {
+        return null;
+      }
+
       // Try pulling up MutableCalc only when Join condition references 
mapping.
       final List<RexNode> identityProjects =
           rexBuilder.identityProjects(qInput1.rowType);
@@ -1310,6 +1316,12 @@ public class SubstitutionVisitor {
       if (!canPullUpFilterUnderJoin(joinRelType, null, qInput1Cond)) {
         return null;
       }
+
+      // Check if join project nullable can be pull up
+      if (!canPullUpProjectUnderJoin(joinRelType, null, qInput1Projs)) {
+        return null;
+      }
+
       // Try pulling up MutableCalc only when Join condition references 
mapping.
       final List<RexNode> identityProjects =
           rexBuilder.identityProjects(qInput0.rowType);
@@ -1400,6 +1412,12 @@ public class SubstitutionVisitor {
       if (!canPullUpFilterUnderJoin(joinRelType, qInput0Cond, qInput1Cond)) {
         return null;
       }
+
+      // Check if join project nullable can be pull up
+      if (!canPullUpProjectUnderJoin(joinRelType, qInput0Projs, qInput1Projs)) 
{
+        return null;
+      }
+
       if (!referenceByMapping(query.condition, qInput0Projs, qInput1Projs)) {
         return null;
       }
@@ -2178,6 +2196,32 @@ public class SubstitutionVisitor {
     return false;
   }
 
+  /**
+   * Check if project under join can be pulled up,
+   * when meeting JoinOnCalc of query unify to Join of target.
+   * Working in rules: {@link JoinOnLeftCalcToJoinUnifyRule} <br/>
+   * {@link JoinOnRightCalcToJoinUnifyRule} <br/>
+   * {@link JoinOnCalcsToJoinUnifyRule} <br/>
+   */
+  private static boolean canPullUpProjectUnderJoin(JoinRelType joinType,
+      @Nullable List<RexNode> leftProjects, @Nullable List<RexNode> 
rightProjects) {
+    if (leftProjects != null && joinType.generatesNullsOn(0)
+        && !allProjectsNullable(leftProjects)) {
+      return false;
+    }
+    if (rightProjects != null && joinType.generatesNullsOn(1)
+        && !allProjectsNullable(rightProjects)) {
+      return false;
+    }
+    return true;
+  }
+
+  /** Returns whether all projects are nullable. */
+  private static boolean allProjectsNullable(List<RexNode> projects) {
+    return projects.stream()
+        .allMatch(project -> project.getType().isNullable());
+  }
+
   /** Operand to a {@link UnifyRule}. */
   public abstract static class Operand {
     protected final Class<? extends MutableRel> clazz;
diff --git 
a/core/src/test/java/org/apache/calcite/test/MaterializedViewSubstitutionVisitorTest.java
 
b/core/src/test/java/org/apache/calcite/test/MaterializedViewSubstitutionVisitorTest.java
index dca173b571..ea7c7258e0 100644
--- 
a/core/src/test/java/org/apache/calcite/test/MaterializedViewSubstitutionVisitorTest.java
+++ 
b/core/src/test/java/org/apache/calcite/test/MaterializedViewSubstitutionVisitorTest.java
@@ -1136,6 +1136,111 @@ public class MaterializedViewSubstitutionVisitorTest {
     sql(mv, query).ok();
   }
 
+  /** Test case for
+   * <a 
href="https://issues.apache.org/jira/browse/CALCITE-6501";>[CALCITE-6501]
+   * Assertion Error in JoinUnifyRule Due to Type Mismatch</a>. */
+  @Test void testLeftProjectOnRightJoinToJoinFailed() {
+    String mv = "select * from \n"
+        + "(select \"empid\", \"deptno\", \"name\" from \"emps\") \"t1\"\n"
+        + "right join (select \"deptno\", \"name\" from \"depts\") \"t2\"\n"
+        + "on \"t1\".\"deptno\" = \"t2\".\"deptno\"";
+    String query = "select * from \n"
+        + "(select \"empid\", \"empid\" a, \"deptno\", \"name\" from \"emps\") 
\"t1\"\n"
+        + "right join (select \"deptno\", \"name\" from \"depts\") \"t2\"\n"
+        + "on \"t1\".\"deptno\" = \"t2\".\"deptno\"";
+    sql(mv, query).noMat();
+  }
+
+  /** Test case for
+   * <a 
href="https://issues.apache.org/jira/browse/CALCITE-6501";>[CALCITE-6501]
+   * Assertion Error in JoinUnifyRule Due to Type Mismatch</a>. */
+  @Test void testLeftProjectOnFullJoinToJoinFailed() {
+    String mv = "select * from \n"
+        + "(select \"empid\", \"deptno\", \"name\" from \"emps\") \"t1\"\n"
+        + "full join (select \"deptno\", \"name\" from \"depts\") \"t2\"\n"
+        + "on \"t1\".\"deptno\" = \"t2\".\"deptno\"";
+    String query = "select * from \n"
+        + "(select \"empid\", \"empid\" a, \"deptno\", \"name\" from \"emps\") 
\"t1\"\n"
+        + "full join (select \"deptno\", \"name\" from \"depts\") \"t2\"\n"
+        + "on \"t1\".\"deptno\" = \"t2\".\"deptno\"";
+    sql(mv, query).noMat();
+  }
+
+  /** Test case for
+   * <a 
href="https://issues.apache.org/jira/browse/CALCITE-6501";>[CALCITE-6501]
+   * Assertion Error in JoinUnifyRule Due to Type Mismatch</a>. */
+  @Test void testRightProjectOnLeftJoinToJoinFailed() {
+    String mv = "select * from \n"
+        + "(select \"empid\", \"deptno\", \"name\" from \"emps\") \"t1\"\n"
+        + "left join (select \"deptno\", \"name\" from \"depts\") \"t2\"\n"
+        + "on \"t1\".\"deptno\" = \"t2\".\"deptno\"";
+    String query = "select * from \n"
+        + "(select \"empid\", \"deptno\", \"name\" from \"emps\") \"t1\"\n"
+        + "left join (select \"deptno\", \"deptno\" a, \"name\" from 
\"depts\") \"t2\"\n"
+        + "on \"t1\".\"deptno\" = \"t2\".\"deptno\"";
+    sql(mv, query).noMat();
+  }
+
+  /** Test case for
+   * <a 
href="https://issues.apache.org/jira/browse/CALCITE-6501";>[CALCITE-6501]
+   * Assertion Error in JoinUnifyRule Due to Type Mismatch</a>. */
+  @Test void testRightProjectOnFullJoinToJoinFailed() {
+    String mv = "select * from \n"
+        + "(select \"empid\", \"deptno\", \"name\" from \"emps\") \"t1\"\n"
+        + "full join (select \"deptno\", \"name\" from \"depts\") \"t2\"\n"
+        + "on \"t1\".\"deptno\" = \"t2\".\"deptno\"";
+    String query = "select * from \n"
+        + "(select \"empid\", \"deptno\", \"name\" from \"emps\") \"t1\"\n"
+        + "full join (select \"deptno\", \"deptno\" a, \"name\" from 
\"depts\") \"t2\"\n"
+        + "on \"t1\".\"deptno\" = \"t2\".\"deptno\"";
+    sql(mv, query).noMat();
+  }
+
+  /** Test case for
+   * <a 
href="https://issues.apache.org/jira/browse/CALCITE-6501";>[CALCITE-6501]
+   * Assertion Error in JoinUnifyRule Due to Type Mismatch</a>. */
+  @Test void testLeftProjectAndRightProjectOnLeftJoinToJoinFailed() {
+    String mv = "select * from \n"
+        + "(select \"empid\", \"deptno\", \"name\" from \"emps\") \"t1\"\n"
+        + "left join (select \"deptno\", \"name\" from \"depts\") \"t2\"\n"
+        + "on \"t1\".\"deptno\" = \"t2\".\"deptno\"";
+    String query = "select * from \n"
+        + "(select \"empid\", \"empid\" a, \"deptno\", \"name\" from \"emps\") 
\"t1\"\n"
+        + "left join (select \"deptno\", \"deptno\" a, \"name\" from 
\"depts\") \"t2\"\n"
+        + "on \"t1\".\"deptno\" = \"t2\".\"deptno\"";
+    sql(mv, query).noMat();
+  }
+
+  /** Test case for
+   * <a 
href="https://issues.apache.org/jira/browse/CALCITE-6501";>[CALCITE-6501]
+   * Assertion Error in JoinUnifyRule Due to Type Mismatch</a>. */
+  @Test void testLeftProjectAndRightProjectOnRightJoinToJoinFailed() {
+    String mv = "select * from \n"
+        + "(select \"empid\", \"deptno\", \"name\" from \"emps\") \"t1\"\n"
+        + "right join (select \"deptno\", \"name\" from \"depts\") \"t2\"\n"
+        + "on \"t1\".\"deptno\" = \"t2\".\"deptno\"";
+    String query = "select * from \n"
+        + "(select \"empid\", \"empid\" a, \"deptno\", \"name\" from \"emps\") 
\"t1\"\n"
+        + "right join (select \"deptno\", \"deptno\" a, \"name\" from 
\"depts\") \"t2\"\n"
+        + "on \"t1\".\"deptno\" = \"t2\".\"deptno\"";
+    sql(mv, query).noMat();
+  }
+
+  /** Test case for
+   * <a 
href="https://issues.apache.org/jira/browse/CALCITE-6501";>[CALCITE-6501]
+   * Assertion Error in JoinUnifyRule Due to Type Mismatch</a>. */
+  @Test void testLeftProjectAndRightProjectOnFullJoinToJoinFailed() {
+    String mv = "select * from \n"
+        + "(select \"empid\", \"deptno\", \"name\" from \"emps\") \"t1\"\n"
+        + "full join (select \"deptno\", \"name\" from \"depts\") \"t2\"\n"
+        + "on \"t1\".\"deptno\" = \"t2\".\"deptno\"";
+    String query = "select * from \n"
+        + "(select \"empid\", \"deptno\", \"name\" from \"emps\") \"t1\"\n"
+        + "full join (select \"deptno\", \"deptno\" a, \"name\" from 
\"depts\") \"t2\"\n"
+        + "on \"t1\".\"deptno\" = \"t2\".\"deptno\"";
+    sql(mv, query).noMat();
+  }
+
   @Test void testLeftFilterOnRightJoinToJoinFail() {
     String mv = "select * from \n"
         + "(select \"empid\", \"deptno\", \"name\" from \"emps\") \"t1\"\n"

Reply via email to