You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@calcite.apache.org by ru...@apache.org on 2023/04/25 11:17:03 UTC
[calcite] branch main updated: [CALCITE-5670] Assertion error in SemiJoinJoinTransposeRule when Semi-Join has keys from both tables of the bottom Join
This is an automated email from the ASF dual-hosted git repository.
rubenql 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 cc3c5fed07 [CALCITE-5670] Assertion error in SemiJoinJoinTransposeRule when Semi-Join has keys from both tables of the bottom Join
cc3c5fed07 is described below
commit cc3c5fed072dad2efc8d0961e66fea38ba8f3817
Author: Roman Kondakov <rk...@querifylabs.com>
AuthorDate: Sun Apr 23 18:35:12 2023 +0700
[CALCITE-5670] Assertion error in SemiJoinJoinTransposeRule when Semi-Join has keys from both tables of the bottom Join
---
.../rel/rules/SemiJoinJoinTransposeRule.java | 9 ++++---
.../org/apache/calcite/test/RelOptRulesTest.java | 12 +++++++++
.../org/apache/calcite/test/RelOptRulesTest.xml | 31 ++++++++++++++++++++++
3 files changed, 48 insertions(+), 4 deletions(-)
diff --git a/core/src/main/java/org/apache/calcite/rel/rules/SemiJoinJoinTransposeRule.java b/core/src/main/java/org/apache/calcite/rel/rules/SemiJoinJoinTransposeRule.java
index 9ad23cc92e..d314b2819a 100644
--- a/core/src/main/java/org/apache/calcite/rel/rules/SemiJoinJoinTransposeRule.java
+++ b/core/src/main/java/org/apache/calcite/rel/rules/SemiJoinJoinTransposeRule.java
@@ -76,7 +76,6 @@ public class SemiJoinJoinTransposeRule
if (join.isSemiJoin()) {
return;
}
- final ImmutableIntList leftKeys = semiJoin.analyzeCondition().leftKeys;
// X is the left child of the join below the semi-join
// Y is the right child of the join below the semi-join
@@ -102,6 +101,7 @@ public class SemiJoinJoinTransposeRule
// determine which operands below the semi-join are the actual
// Rels that participate in the semi-join
+ final ImmutableIntList leftKeys = semiJoin.analyzeCondition().leftKeys;
int nKeysFromX = 0;
for (int leftKey : leftKeys) {
if (leftKey < nFieldsX) {
@@ -109,9 +109,10 @@ public class SemiJoinJoinTransposeRule
}
}
- // the keys must all originate from either the left or right;
- // otherwise, a semi-join wouldn't have been created
- assert (nKeysFromX == 0) || (nKeysFromX == leftKeys.size());
+ if (nKeysFromX != 0 && nKeysFromX != leftKeys.size()) {
+ // We can not push semi-join down if it has keys from both tables of the bottom join
+ return;
+ }
// need to convert the semi-join condition and possibly the keys
final RexNode newSemiJoinFilter;
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 4fd8e82711..841c32a700 100644
--- a/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java
+++ b/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java
@@ -2666,6 +2666,18 @@ class RelOptRulesTest extends RelOptTestBase {
.check();
}
+ @Test void testPushSemiJoinPastJoinRuleNotHappensJoinKeysDifferentOrigin() {
+ // tests the case where the semijoin is not pushed because it uses join keys from both tables
+ // of the bottom join.
+ final String sql = "select e.ename from emp e, dept d, bonus b\n"
+ + "where e.deptno = d.deptno and e.ename = b.ename and d.name = b.job";
+ sql(sql)
+ .withRule(CoreRules.FILTER_INTO_JOIN,
+ CoreRules.JOIN_ADD_REDUNDANT_SEMI_JOIN,
+ CoreRules.SEMI_JOIN_JOIN_TRANSPOSE)
+ .check();
+ }
+
@Test void testPushSemiJoinPastFilter() {
final String sql = "select e.ename from emp e, dept d\n"
+ "where e.deptno = d.deptno and e.ename = 'foo'";
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 91c54a496b..72567797e3 100644
--- a/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml
+++ b/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml
@@ -10533,6 +10533,37 @@ LogicalProject(ENAME=[$1])
LogicalTableScan(table=[[CATALOG, SALES, EMP]])
LogicalTableScan(table=[[CATALOG, SALES, DEPT]])
LogicalTableScan(table=[[CATALOG, SALES, EMP]])
+]]>
+ </Resource>
+ </TestCase>
+ <TestCase name="testPushSemiJoinPastJoinRuleNotHappensJoinKeysDifferentOrigin">
+ <Resource name="sql">
+ <![CDATA[select e.ename from emp e, dept d, bonus b
+where e.deptno = d.deptno and e.ename = b.ename and d.name = b.job]]>
+ </Resource>
+ <Resource name="planBefore">
+ <![CDATA[
+LogicalProject(ENAME=[$1])
+ LogicalFilter(condition=[AND(=($7, $9), =($1, $11), =($10, $12))])
+ LogicalJoin(condition=[true], joinType=[inner])
+ LogicalJoin(condition=[true], joinType=[inner])
+ LogicalTableScan(table=[[CATALOG, SALES, EMP]])
+ LogicalTableScan(table=[[CATALOG, SALES, DEPT]])
+ LogicalTableScan(table=[[CATALOG, SALES, BONUS]])
+]]>
+ </Resource>
+ <Resource name="planAfter">
+ <![CDATA[
+LogicalProject(ENAME=[$1])
+ LogicalJoin(condition=[AND(=($1, $11), =($10, $12))], joinType=[inner], semiJoinDone=[true])
+ LogicalJoin(condition=[AND(=($1, $11), =($10, $12))], joinType=[semi])
+ LogicalJoin(condition=[=($7, $9)], joinType=[inner], semiJoinDone=[true])
+ LogicalJoin(condition=[=($7, $9)], joinType=[semi])
+ LogicalTableScan(table=[[CATALOG, SALES, EMP]])
+ LogicalTableScan(table=[[CATALOG, SALES, DEPT]])
+ LogicalTableScan(table=[[CATALOG, SALES, DEPT]])
+ LogicalTableScan(table=[[CATALOG, SALES, BONUS]])
+ LogicalTableScan(table=[[CATALOG, SALES, BONUS]])
]]>
</Resource>
</TestCase>