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"