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/04 01:43:06 UTC

[calcite] branch master updated: [CALCITE-3121] VolcanoPlanner hangs due to subquery with dynamic star

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 0ed54bd  [CALCITE-3121] VolcanoPlanner hangs due to subquery with dynamic star
0ed54bd is described below

commit 0ed54bd64d0beb0849a499e65e872c43f00efce9
Author: yuzhao.cyz <yu...@alibaba-inc.com>
AuthorDate: Tue Jul 2 14:06:48 2019 +0800

    [CALCITE-3121] VolcanoPlanner hangs due to subquery with dynamic star
---
 .../rel/rules/ProjectFilterTransposeRule.java      | 21 +++++++++
 .../org/apache/calcite/test/RelOptRulesTest.java   | 55 +++++++++++++++++++++-
 .../org/apache/calcite/test/RelOptRulesTest.xml    | 21 +++++++++
 3 files changed, 95 insertions(+), 2 deletions(-)

diff --git a/core/src/main/java/org/apache/calcite/rel/rules/ProjectFilterTransposeRule.java b/core/src/main/java/org/apache/calcite/rel/rules/ProjectFilterTransposeRule.java
index dd1c0c9..7106560 100644
--- a/core/src/main/java/org/apache/calcite/rel/rules/ProjectFilterTransposeRule.java
+++ b/core/src/main/java/org/apache/calcite/rel/rules/ProjectFilterTransposeRule.java
@@ -98,6 +98,27 @@ public class ProjectFilterTransposeRule extends RelOptRule {
       return;
     }
 
+    if ((origProj != null)
+        && origProj.getRowType().getFieldList().get(0).isDynamicStar()) {
+      // The PushProjector would change the plan:
+      //
+      //    prj(**=[$0])
+      //    : - filter
+      //        : - scan
+      //
+      // to form like:
+      //
+      //    prj(**=[$0])                    (1)
+      //    : - filter                      (2)
+      //        : - prj(**=[$0], ITEM= ...) (3)
+      //            :  - scan
+      // This new plan has more cost that the old one, because of the new
+      // redundant project (3), if we also have FilterProjectTransposeRule in
+      // the rule set, it will also trigger infinite match of the ProjectMergeRule
+      // for project (1) and (3).
+      return;
+    }
+
     PushProjector pushProjector =
         new PushProjector(
             origProj, origFilter, rel, preserveExprCondition, call.builder());
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 337ce66..244ff05 100644
--- a/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java
+++ b/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java
@@ -165,6 +165,7 @@ import java.util.Arrays;
 import java.util.Collections;
 import java.util.EnumSet;
 import java.util.List;
+import java.util.Locale;
 import java.util.Properties;
 import java.util.function.Predicate;
 
@@ -4994,8 +4995,7 @@ public class RelOptRulesTest extends RelOptTestBase {
 
   /** Test case for testing type created by SubQueryRemoveRule: an
    * ANY sub-query is non-nullable therefore plan should have cast. */
-  @Test public void
-  testAnyInProjectNonNullable() {
+  @Test public void testAnyInProjectNonNullable() {
     final String sql = "select name, deptno > ANY (\n"
         + "  select deptno from emp)\n"
         + "from dept";
@@ -5148,6 +5148,57 @@ public class RelOptRulesTest extends RelOptTestBase {
     checkSubQuery(sql).check();
   }
 
+  /** Test case for
+   * <a href="https://issues.apache.org/jira/browse/CALCITE-3121">[CALCITE-3121]
+   * VolcanoPlanner hangs due to subquery with dynamic star</a>. */
+  @Test public void testSubQueryWithDynamicStarHang() {
+    String sql = "select n.n_regionkey from (select * from "
+        + "(select * from sales.customer) t) n where n.n_nationkey >1";
+
+    VolcanoPlanner planner = new VolcanoPlanner(null, null);
+    planner.addRelTraitDef(ConventionTraitDef.INSTANCE);
+
+    Tester dynamicTester = createDynamicTester().withDecorrelation(true)
+        .withClusterFactory(
+            relOptCluster -> RelOptCluster.create(planner, relOptCluster.getRexBuilder()));
+
+    RelRoot root = dynamicTester.convertSqlToRel(sql);
+
+    String planBefore = NL + RelOptUtil.toString(root.rel);
+    getDiffRepos().assertEquals("planBefore", "${planBefore}", planBefore);
+
+    PushProjector.ExprCondition exprCondition = expr -> {
+      if (expr instanceof RexCall) {
+        RexCall call = (RexCall) expr;
+        return "item".equals(call.getOperator().getName().toLowerCase(Locale.ROOT));
+      }
+      return false;
+    };
+    RuleSet ruleSet =
+        RuleSets.ofList(
+            FilterProjectTransposeRule.INSTANCE,
+            FilterMergeRule.INSTANCE,
+            ProjectMergeRule.INSTANCE,
+            new ProjectFilterTransposeRule(Project.class, Filter .class,
+                RelFactories.LOGICAL_BUILDER, exprCondition),
+            EnumerableRules.ENUMERABLE_PROJECT_RULE,
+            EnumerableRules.ENUMERABLE_FILTER_RULE,
+            EnumerableRules.ENUMERABLE_SORT_RULE,
+            EnumerableRules.ENUMERABLE_LIMIT_RULE,
+            EnumerableRules.ENUMERABLE_TABLE_SCAN_RULE);
+    Program program = Programs.of(ruleSet);
+
+    RelTraitSet toTraits =
+        root.rel.getCluster().traitSet()
+            .replace(0, EnumerableConvention.INSTANCE);
+
+    RelNode relAfter = program.run(planner, root.rel, toTraits,
+        Collections.emptyList(), Collections.emptyList());
+
+    String planAfter = NL + RelOptUtil.toString(relAfter);
+    getDiffRepos().assertEquals("planAfter", "${planAfter}", planAfter);
+  }
+
   @Ignore("[CALCITE-1045]")
   @Test public void testExpandJoinIn() throws Exception {
     final String sql = "select empno\n"
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 0453f4a..1e1bc06 100644
--- a/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml
+++ b/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml
@@ -9522,6 +9522,27 @@ LogicalProject(EMPNO=[$0])
 ]]>
         </Resource>
     </TestCase>
+    <TestCase name="testSubQueryWithDynamicStarHang">
+        <Resource name="sql">
+            <![CDATA[select n.n_regionkey from (select * from
+(select * from sales.customer) t) n where n.n_nationkey >1]]>
+        </Resource>
+        <Resource name="planBefore">
+            <![CDATA[
+LogicalProject(N_REGIONKEY=[ITEM($0, 'N_REGIONKEY')])
+  LogicalFilter(condition=[>(ITEM($0, 'N_NATIONKEY'), 1)])
+    LogicalProject(**=[$0])
+      LogicalTableScan(table=[[CATALOG, SALES, CUSTOMER]])
+]]>
+        </Resource>
+        <Resource name="planAfter">
+            <![CDATA[
+EnumerableProject(N_REGIONKEY=[ITEM($0, 'N_REGIONKEY')])
+  EnumerableFilter(condition=[>(ITEM($0, 'N_NATIONKEY'), 1)])
+    EnumerableTableScan(table=[[CATALOG, SALES, CUSTOMER]])
+]]>
+        </Resource>
+    </TestCase>
     <TestCase name="testExpandFilterExists">
         <Resource name="sql">
             <![CDATA[select empno