You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@calcite.apache.org by da...@apache.org on 2019/07/08 12:55:50 UTC
[calcite] branch master updated: [CALCITE-3171] SemiJoin on
conditions push down throws IndexOutOfBoundsException
This is an automated email from the ASF dual-hosted git repository.
danny0405 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/calcite.git
The following commit(s) were added to refs/heads/master by this push:
new e1875e3 [CALCITE-3171] SemiJoin on conditions push down throws IndexOutOfBoundsException
e1875e3 is described below
commit e1875e3f78d91711ba174834cdead500361b19e6
Author: yuzhao.cyz <yu...@alibaba-inc.com>
AuthorDate: Sun Jul 7 14:09:10 2019 +0800
[CALCITE-3171] SemiJoin on conditions push down throws IndexOutOfBoundsException
RelOptUtil#pushDownJoinConditions should only project left side above
the join node when the join type only returns left side.
---
.../java/org/apache/calcite/plan/RelOptUtil.java | 13 ++++---
.../org/apache/calcite/test/RelOptRulesTest.java | 41 ++++++++++++++++++++++
.../org/apache/calcite/test/RelOptRulesTest.xml | 17 +++++++++
3 files changed, 66 insertions(+), 5 deletions(-)
diff --git a/core/src/main/java/org/apache/calcite/plan/RelOptUtil.java b/core/src/main/java/org/apache/calcite/plan/RelOptUtil.java
index 452f528..9487b0b 100644
--- a/core/src/main/java/org/apache/calcite/plan/RelOptUtil.java
+++ b/core/src/main/java/org/apache/calcite/plan/RelOptUtil.java
@@ -3367,14 +3367,17 @@ public abstract class RelOptUtil {
relBuilder.push(
originalJoin.copy(originalJoin.getTraitSet(),
joinCond, left, right, joinType, originalJoin.isSemiJoinDone()));
-
if (!extraLeftExprs.isEmpty() || !extraRightExprs.isEmpty()) {
+ final int totalFields = joinType.projectsRight()
+ ? leftCount + extraLeftExprs.size() + rightCount + extraRightExprs.size()
+ : leftCount + extraLeftExprs.size();
+ final int[] mappingRanges = joinType.projectsRight()
+ ? new int[] { 0, 0, leftCount, leftCount, leftCount + extraLeftExprs.size(), rightCount }
+ : new int[] { 0, 0, leftCount };
Mappings.TargetMapping mapping =
Mappings.createShiftMapping(
- leftCount + extraLeftExprs.size()
- + rightCount + extraRightExprs.size(),
- 0, 0, leftCount,
- leftCount, leftCount + extraLeftExprs.size(), rightCount);
+ totalFields,
+ mappingRanges);
relBuilder.project(relBuilder.fields(mapping.inverse()));
}
return relBuilder.build();
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 244ff05..b25cb7b 100644
--- a/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java
+++ b/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java
@@ -129,6 +129,7 @@ import org.apache.calcite.rel.rules.ValuesReduceRule;
import org.apache.calcite.rel.type.RelDataType;
import org.apache.calcite.rel.type.RelDataTypeFactory;
import org.apache.calcite.rex.RexCall;
+import org.apache.calcite.rex.RexInputRef;
import org.apache.calcite.rex.RexNode;
import org.apache.calcite.runtime.Hook;
import org.apache.calcite.sql.SqlFunction;
@@ -414,6 +415,46 @@ public class RelOptRulesTest extends RelOptTestBase {
.check();
}
+ /** Test case for
+ * <a href="https://issues.apache.org/jira/browse/CALCITE-3171">[CALCITE-3171]
+ * SemiJoin on conditions push down throws IndexOutOfBoundsException</a>. */
+ @Test public void testPushSemiJoinConditionsToLeft() {
+ final RelBuilder relBuilder = RelBuilder.create(RelBuilderTest.config().build());
+ // build a rel equivalent to sql:
+ // select * from emp
+ // where emp.deptno
+ // in (select dept.deptno from dept where emp.empno > 20)
+ RelNode left = relBuilder.scan("EMP").build();
+ RelNode right = relBuilder.scan("DEPT").build();
+ RelNode join = relBuilder.push(left)
+ .push(right)
+ .semiJoin(
+ relBuilder.call(SqlStdOperatorTable.IS_NOT_DISTINCT_FROM,
+ relBuilder.field(2, 0, "DEPTNO"),
+ relBuilder.field(2, 1, "DEPTNO")),
+ relBuilder.call(SqlStdOperatorTable.GREATER_THAN,
+ RexInputRef.of(0, left.getRowType()),
+ relBuilder.literal(20)))
+ .build();
+
+ relBuilder.push(join);
+ RelNode relNode = relBuilder.project(relBuilder.field(0))
+ .build();
+
+ HepProgram program = new HepProgramBuilder()
+ .addRuleInstance(JoinPushExpressionsRule.INSTANCE)
+ .build();
+
+ HepPlanner hepPlanner = new HepPlanner(program);
+ hepPlanner.setRoot(relNode);
+ RelNode output = hepPlanner.findBestExp();
+
+ final String planAfter = NL + RelOptUtil.toString(output);
+ final DiffRepository diffRepos = getDiffRepos();
+ diffRepos.assertEquals("planAfter", "${planAfter}", planAfter);
+ SqlToRelTestBase.assertValid(output);
+ }
+
@Test public void testFullOuterJoinSimplificationToLeftOuter() {
checkPlanning(FilterJoinRule.FILTER_ON_JOIN,
"select 1 from sales.dept d full outer join sales.emp e"
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 1e1bc06..1edf4f1 100644
--- a/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml
+++ b/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml
@@ -5987,6 +5987,23 @@ LogicalProject(DEPTNO=[$0], NAME=[$1], EMPNO=[$2], ENAME=[$3], JOB=[$4], MGR=[$5
]]>
</Resource>
</TestCase>
+ <TestCase name="testPushSemiJoinConditionsToLeft">
+ <Resource name="sql">
+ <![CDATA[select * from emp
+where emp.deptno
+in (select dept.deptno from dept where emp.empno > 20)]]>
+ </Resource>
+ <Resource name="planAfter">
+ <![CDATA[
+LogicalProject(EMPNO=[$0])
+ LogicalProject(EMPNO=[$0], ENAME=[$1], JOB=[$2], MGR=[$3], HIREDATE=[$4], SAL=[$5], COMM=[$6], DEPTNO=[$7])
+ LogicalJoin(condition=[AND(IS NOT DISTINCT FROM($7, $9), $8)], joinType=[semi])
+ LogicalProject(EMPNO=[$0], ENAME=[$1], JOB=[$2], MGR=[$3], HIREDATE=[$4], SAL=[$5], COMM=[$6], DEPTNO=[$7], $f8=[>($0, 20)])
+ LogicalTableScan(table=[[scott, EMP]])
+ LogicalTableScan(table=[[scott, DEPT]])
+]]>
+ </Resource>
+ </TestCase>
<TestCase name="testSemiJoinRuleExists">
<Resource name="sql">
<![CDATA[select * from dept where exists (