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/11 05:09:07 UTC

[calcite] branch master updated: [CALCITE-3188] IndexOutOfBoundsException in ProjectFilterTransposeRule when executing SELECT COUNT(*)

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 954f27c  [CALCITE-3188] IndexOutOfBoundsException in ProjectFilterTransposeRule when executing SELECT COUNT(*)
954f27c is described below

commit 954f27c2a09e019dd22d689ddd770ffb42c1c10c
Author: yuzhao.cyz <yu...@alibaba-inc.com>
AuthorDate: Wed Jul 10 21:11:34 2019 +0800

    [CALCITE-3188] IndexOutOfBoundsException in ProjectFilterTransposeRule when executing SELECT COUNT(*)
---
 .../rel/rules/ProjectFilterTransposeRule.java      |  5 +-
 .../org/apache/calcite/test/RelOptRulesTest.java   | 55 +++++++++++++++-------
 .../org/apache/calcite/test/RelOptRulesTest.xml    | 10 ++++
 3 files changed, 51 insertions(+), 19 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 7106560..ade34a1 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
@@ -25,6 +25,7 @@ import org.apache.calcite.rel.core.Project;
 import org.apache.calcite.rel.core.RelFactories;
 import org.apache.calcite.rel.logical.LogicalFilter;
 import org.apache.calcite.rel.logical.LogicalProject;
+import org.apache.calcite.rel.type.RelDataTypeField;
 import org.apache.calcite.rex.RexNode;
 import org.apache.calcite.rex.RexOver;
 import org.apache.calcite.tools.RelBuilderFactory;
@@ -99,7 +100,9 @@ public class ProjectFilterTransposeRule extends RelOptRule {
     }
 
     if ((origProj != null)
-        && origProj.getRowType().getFieldList().get(0).isDynamicStar()) {
+        && origProj.getRowType().isStruct()
+        && origProj.getRowType().getFieldList().stream()
+          .anyMatch(RelDataTypeField::isDynamicStar)) {
       // The PushProjector would change the plan:
       //
       //    prj(**=[$0])
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 0bb3c54..756d223 100644
--- a/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java
+++ b/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java
@@ -426,7 +426,7 @@ public class RelOptRulesTest extends RelOptTestBase {
     // not in (select dept.deptno from dept where emp.deptno > 20)
     RelNode left = relBuilder.scan("EMP").build();
     RelNode right = relBuilder.scan("DEPT").build();
-    RelNode join = relBuilder.push(left)
+    RelNode relNode = relBuilder.push(left)
         .push(right)
         .antiJoin(
             relBuilder.call(SqlStdOperatorTable.IS_NOT_DISTINCT_FROM,
@@ -435,10 +435,7 @@ public class RelOptRulesTest extends RelOptTestBase {
             relBuilder.call(SqlStdOperatorTable.GREATER_THAN,
             RexInputRef.of(0, left.getRowType()),
             relBuilder.literal(20)))
-        .build();
-
-    relBuilder.push(join);
-    RelNode relNode = relBuilder.project(relBuilder.field(0))
+        .project(relBuilder.field(0))
         .build();
 
     HepProgram program = new HepProgramBuilder()
@@ -461,20 +458,15 @@ public class RelOptRulesTest extends RelOptTestBase {
     // select * from emp
     // where emp.deptno
     // not in (select dept.deptno from dept where dept.dname = 'ddd')
-    RelNode left = relBuilder.scan("EMP").build();
-    RelNode right = relBuilder.scan("DEPT").build();
-    RelNode join = relBuilder.push(left)
-        .push(right)
+    RelNode relNode = relBuilder.scan("EMP")
+        .scan("DEPT")
         .antiJoin(
             relBuilder.call(SqlStdOperatorTable.IS_NOT_DISTINCT_FROM,
                 relBuilder.field(2, 0, "DEPTNO"),
                 relBuilder.field(2, 1, "DEPTNO")),
             relBuilder.equals(relBuilder.field(2, 1, "DNAME"),
                 relBuilder.literal("ddd")))
-        .build();
-
-    relBuilder.push(join);
-    RelNode relNode = relBuilder.project(relBuilder.field(0))
+        .project(relBuilder.field(0))
         .build();
 
     HepProgram program = new HepProgramBuilder()
@@ -502,7 +494,7 @@ public class RelOptRulesTest extends RelOptTestBase {
     // 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)
+    RelNode relNode = relBuilder.push(left)
         .push(right)
         .semiJoin(
             relBuilder.call(SqlStdOperatorTable.IS_NOT_DISTINCT_FROM,
@@ -511,10 +503,7 @@ public class RelOptRulesTest extends RelOptTestBase {
             relBuilder.call(SqlStdOperatorTable.GREATER_THAN,
                 RexInputRef.of(0, left.getRowType()),
                 relBuilder.literal(20)))
-        .build();
-
-    relBuilder.push(join);
-    RelNode relNode = relBuilder.project(relBuilder.field(0))
+        .project(relBuilder.field(0))
         .build();
 
     HepProgram program = new HepProgramBuilder()
@@ -5316,6 +5305,36 @@ public class RelOptRulesTest extends RelOptTestBase {
     getDiffRepos().assertEquals("planAfter", "${planAfter}", planAfter);
   }
 
+  /** Test case for
+   * <a href="https://issues.apache.org/jira/browse/CALCITE-3188">[CALCITE-3188]
+   * IndexOutOfBoundsException in ProjectFilterTransposeRule when executing SELECT COUNT(*)</a>. */
+  @Test public void testProjectFilterTransposeRuleOnEmptyRowType() {
+    final RelBuilder relBuilder = RelBuilder.create(RelBuilderTest.config().build());
+    // build a rel equivalent to sql:
+    // select `empty` from emp
+    // where emp.deptno = 20
+    RelNode relNode = relBuilder.scan("EMP")
+        .filter(relBuilder
+            .equals(
+                relBuilder.field(1, 0, "DEPTNO"),
+                relBuilder.literal(20)))
+        .project(ImmutableList.of())
+        .build();
+
+    HepProgram program = new HepProgramBuilder()
+        .addRuleInstance(ProjectFilterTransposeRule.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);
+  }
+
   @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 13ea276..d2d83e0 100644
--- a/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml
+++ b/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml
@@ -9590,6 +9590,16 @@ EnumerableProject(N_REGIONKEY=[ITEM($0, 'N_REGIONKEY')])
 ]]>
         </Resource>
     </TestCase>
+    <TestCase name="testProjectFilterTransposeRuleOnEmptyRowType">
+        <Resource name="planAfter">
+            <![CDATA[
+LogicalProject
+  LogicalFilter(condition=[=($0, 20)])
+    LogicalProject(DEPTNO=[$7])
+      LogicalTableScan(table=[[scott, EMP]])
+]]>
+        </Resource>
+    </TestCase>
     <TestCase name="testExpandFilterExists">
         <Resource name="sql">
             <![CDATA[select empno