This is an automated email from the ASF dual-hosted git repository. zabetak 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 43ba147 [CALCITE-2930] IllegalStateException when FilterCorrelateRule matches a SEMI or ANTI Correlate (Ruben Quesada Lopez) 43ba147 is described below commit 43ba147937dc53dfb86ee8723d45562e48b14d20 Author: rubenada <rube...@gmail.com> AuthorDate: Mon Mar 18 12:21:34 2019 +0100 [CALCITE-2930] IllegalStateException when FilterCorrelateRule matches a SEMI or ANTI Correlate (Ruben Quesada Lopez) Close #1112 --- .../java/org/apache/calcite/plan/RelOptUtil.java | 15 ++++++++--- .../calcite/rel/rules/FilterCorrelateRule.java | 5 ++-- .../test/enumerable/EnumerableCorrelateTest.java | 29 ++++++++++++++++++++++ 3 files changed, 44 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 9160b04..809dd27 100644 --- a/core/src/main/java/org/apache/calcite/plan/RelOptUtil.java +++ b/core/src/main/java/org/apache/calcite/plan/RelOptUtil.java @@ -26,6 +26,7 @@ import org.apache.calcite.rel.RelVisitor; import org.apache.calcite.rel.RelWriter; import org.apache.calcite.rel.core.AggregateCall; import org.apache.calcite.rel.core.Calc; +import org.apache.calcite.rel.core.Correlate; import org.apache.calcite.rel.core.CorrelationId; import org.apache.calcite.rel.core.Filter; import org.apache.calcite.rel.core.Join; @@ -2355,9 +2356,10 @@ public abstract class RelOptUtil { final List<RelDataTypeField> rightFields = joinRel.getInputs().get(1).getRowType().getFieldList(); final int nFieldsRight = rightFields.size(); - assert nTotalFields == (joinRel instanceof SemiJoin - ? nSysFields + nFieldsLeft - : nSysFields + nFieldsLeft + nFieldsRight); + + assert nTotalFields == (returnsJustFirstInput(joinRel) + ? nSysFields + nFieldsLeft + : nSysFields + nFieldsLeft + nFieldsRight); // set the reference bitmaps for the left and right children ImmutableBitSet leftBitmap = @@ -2444,6 +2446,13 @@ public abstract class RelOptUtil { return !filtersToRemove.isEmpty(); } + private static boolean returnsJustFirstInput(RelNode joinRel) { + // SemiJoin, CorrelateSemiJoin, CorrelateAntiJoin: right fields are not returned + return joinRel instanceof SemiJoin + || (joinRel instanceof Correlate + && ((Correlate) joinRel).getJoinType().returnsJustFirstInput()); + } + private static RexNode shiftFilter( int start, int end, diff --git a/core/src/main/java/org/apache/calcite/rel/rules/FilterCorrelateRule.java b/core/src/main/java/org/apache/calcite/rel/rules/FilterCorrelateRule.java index 7bd9c5f..7fd4732 100644 --- a/core/src/main/java/org/apache/calcite/rel/rules/FilterCorrelateRule.java +++ b/core/src/main/java/org/apache/calcite/rel/rules/FilterCorrelateRule.java @@ -27,6 +27,7 @@ import org.apache.calcite.rel.core.RelFactories; import org.apache.calcite.rex.RexBuilder; import org.apache.calcite.rex.RexNode; import org.apache.calcite.rex.RexUtil; +import org.apache.calcite.sql.SemiJoinType; import org.apache.calcite.tools.RelBuilder; import org.apache.calcite.tools.RelBuilderFactory; @@ -86,8 +87,8 @@ public class FilterCorrelateRule extends RelOptRule { aboveFilters, JoinRelType.INNER, false, - !corr.getJoinType().toJoinType().generatesNullsOnLeft(), - !corr.getJoinType().toJoinType().generatesNullsOnRight(), + true, + corr.getJoinType() == SemiJoinType.INNER, aboveFilters, leftFilters, rightFilters); diff --git a/core/src/test/java/org/apache/calcite/test/enumerable/EnumerableCorrelateTest.java b/core/src/test/java/org/apache/calcite/test/enumerable/EnumerableCorrelateTest.java index 451d95d..d5f05a0 100644 --- a/core/src/test/java/org/apache/calcite/test/enumerable/EnumerableCorrelateTest.java +++ b/core/src/test/java/org/apache/calcite/test/enumerable/EnumerableCorrelateTest.java @@ -21,6 +21,7 @@ import org.apache.calcite.adapter.java.ReflectiveSchema; import org.apache.calcite.config.CalciteConnectionProperty; import org.apache.calcite.config.Lex; import org.apache.calcite.plan.RelOptPlanner; +import org.apache.calcite.rel.rules.FilterCorrelateRule; import org.apache.calcite.rel.rules.JoinToCorrelateRule; import org.apache.calcite.runtime.Hook; import org.apache.calcite.test.CalciteAssert; @@ -103,6 +104,34 @@ public class EnumerableCorrelateTest { "empid=150; name=Sebastian"); } + /** Test case for + * <a href="https://issues.apache.org/jira/browse/CALCITE-2930">[CALCITE-2930] + * FilterCorrelateRule on a Correlate with SemiJoinType SEMI (or ANTI) + * throws IllegalStateException</a> */ + @Test public void semiJoinCorrelateWithFilterCorrelateRule() { + tester(false, new JdbcTest.HrSchema()) + .query( + "select empid, name from emps e where e.deptno in (select d.deptno from depts d) and e.empid > 100") + .withHook(Hook.PLANNER, (Consumer<RelOptPlanner>) planner -> { + // force the semi-join to run via EnumerableCorrelate instead of EnumerableJoin/SemiJoin, + // and push the 'empid > 100' filter into the Correlate + planner.addRule(JoinToCorrelateRule.SEMI); + planner.addRule(FilterCorrelateRule.INSTANCE); + planner.removeRule(EnumerableRules.ENUMERABLE_JOIN_RULE); + planner.removeRule(EnumerableRules.ENUMERABLE_SEMI_JOIN_RULE); + }) + .explainContains("" + + "EnumerableCalc(expr#0..2=[{inputs}], empid=[$t0], name=[$t2])\n" + + " EnumerableCorrelate(correlation=[$cor3], joinType=[semi], requiredColumns=[{1}])\n" + + " EnumerableCalc(expr#0..4=[{inputs}], expr#5=[100], expr#6=[>($t0, $t5)], proj#0..2=[{exprs}], $condition=[$t6])\n" + + " EnumerableTableScan(table=[[s, emps]])\n" + + " EnumerableCalc(expr#0..3=[{inputs}], expr#4=[$cor3], expr#5=[$t4.deptno], expr#6=[=($t5, $t0)], proj#0..3=[{exprs}], $condition=[$t6])\n" + + " EnumerableTableScan(table=[[s, depts]])") + .returnsUnordered( + "empid=110; name=Theodore", + "empid=150; name=Sebastian"); + } + @Test public void simpleCorrelate() { tester(false, new JdbcTest.HrSchema()) .query(