You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@calcite.apache.org by za...@apache.org on 2019/04/02 17:06:34 UTC

[calcite] branch master updated: [CALCITE-2930] IllegalStateException when FilterCorrelateRule matches a SEMI or ANTI Correlate (Ruben Quesada Lopez)

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 <ru...@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(