This is an automated email from the ASF dual-hosted git repository.

hongze 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 b03cdc4  [CALCITE-2343] PushProjector with OVER expression causes 
infinite loop (Chunwei Lei)
b03cdc4 is described below

commit b03cdc486cf5c7232bbc6fa9b5f02f564e9601c3
Author: Chunwei Lei <[email protected]>
AuthorDate: Sun Apr 14 10:27:36 2019 +0800

    [CALCITE-2343] PushProjector with OVER expression causes infinite loop 
(Chunwei Lei)
    
    Also, remove unnecessary cast to RexNode in PushProjector.java.
    
    Close apache/calcite#1162
---
 .../rel/rules/ProjectJoinTransposeRule.java        |  3 +-
 .../apache/calcite/rel/rules/PushProjector.java    |  4 +-
 .../org/apache/calcite/test/RelOptRulesTest.java   | 34 +++++++++
 .../org/apache/calcite/test/RelOptRulesTest.xml    | 81 ++++++++++++++++++++++
 4 files changed, 119 insertions(+), 3 deletions(-)

diff --git 
a/core/src/main/java/org/apache/calcite/rel/rules/ProjectJoinTransposeRule.java 
b/core/src/main/java/org/apache/calcite/rel/rules/ProjectJoinTransposeRule.java
index 34dee11..52d22cc 100644
--- 
a/core/src/main/java/org/apache/calcite/rel/rules/ProjectJoinTransposeRule.java
+++ 
b/core/src/main/java/org/apache/calcite/rel/rules/ProjectJoinTransposeRule.java
@@ -25,6 +25,7 @@ import org.apache.calcite.rel.core.RelFactories;
 import org.apache.calcite.rel.core.SemiJoin;
 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;
 
 import java.util.ArrayList;
@@ -38,7 +39,7 @@ import java.util.List;
  */
 public class ProjectJoinTransposeRule extends RelOptRule {
   public static final ProjectJoinTransposeRule INSTANCE =
-      new ProjectJoinTransposeRule(expr -> true,
+      new ProjectJoinTransposeRule(expr -> !(expr instanceof RexOver),
           RelFactories.LOGICAL_BUILDER);
 
   //~ Instance fields --------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rel/rules/PushProjector.java 
b/core/src/main/java/org/apache/calcite/rel/rules/PushProjector.java
index e34a4a8..376651e 100644
--- a/core/src/main/java/org/apache/calcite/rel/rules/PushProjector.java
+++ b/core/src/main/java/org/apache/calcite/rel/rules/PushProjector.java
@@ -514,7 +514,7 @@ public class PushProjector {
       final RelDataTypeField destField = destFields.get(refIdx - offset);
       newProjects.add(
           Pair.of(
-              (RexNode) rexBuilder.makeInputRef(
+              rexBuilder.makeInputRef(
                   destField.getType(), refIdx - offset),
               destField.getName()));
     }
@@ -629,7 +629,7 @@ public class PushProjector {
       for (Ord<RelDataTypeField> field : Ord.zip(childFields)) {
         projects.add(
             Pair.of(
-                (RexNode) rexBuilder.makeInputRef(
+                rexBuilder.makeInputRef(
                     field.e.getType(), field.i), field.e.getName()));
       }
     }
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 bf3eb8e..5c7a18e 100644
--- a/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java
+++ b/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java
@@ -1435,6 +1435,40 @@ public class RelOptRulesTest extends RelOptTestBase {
     sql(sql).withRule(ProjectJoinTransposeRule.INSTANCE).check();
   }
 
+  /** Test case for
+   * <a 
href="https://issues.apache.org/jira/browse/CALCITE-2343";>[CALCITE-2343]
+   * Should not push over whose columns are all from left child past join since
+   * join will affect row count.</a>. */
+  @Test public void testPushProjectWithOverPastJoin1() {
+    checkPlanning(ProjectJoinTransposeRule.INSTANCE,
+        "select e.sal + b.comm,\n"
+            + "count(e.empno) over (partition by e.deptno)\n"
+            + "from emp e join bonus b\n"
+            + "on e.ename = b.ename and e.deptno = 10");
+  }
+
+  /** As {@link #testPushProjectWithOverPastJoin1()};
+   * should not push over whose columns are all from right child past join 
since
+   * join will affect row count. */
+  @Test public void testPushProjectWithOverPastJoin2() {
+    checkPlanning(ProjectJoinTransposeRule.INSTANCE,
+        "select e.sal + b.comm,\n"
+            + "count(b.sal) over (partition by b.job)\n"
+            + "from emp e join bonus b\n"
+            + "on e.ename = b.ename and e.deptno = 10");
+  }
+
+  /** As {@link #testPushProjectWithOverPastJoin2()};
+   * should not push over past join but should push the operands of over past
+   * join. */
+  @Test public void testPushProjectWithOverPastJoin3() {
+    checkPlanning(ProjectJoinTransposeRule.INSTANCE,
+        "select e.sal + b.comm,\n"
+            + "sum(b.sal + b.sal + 100) over (partition by b.job)\n"
+            + "from emp e join bonus b\n"
+            + "on e.ename = b.ename and e.deptno = 10");
+  }
+
   @Test public void testPushProjectPastSetOp() {
     checkPlanning(ProjectSetOpTransposeRule.INSTANCE,
         "select sal from "
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 392c496..427883d 100644
--- a/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml
+++ b/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml
@@ -1754,6 +1754,87 @@ LogicalProject(EXPR$0=[$1], EXPR$1=[$0])
 ]]>
         </Resource>
     </TestCase>
+    <TestCase name="testPushProjectWithOverPastJoin1">
+        <Resource name="sql">
+            <![CDATA[select e.sal + b.comm,
+count(e.empno) over (partition by e.deptno)
+from emp e join bonus b
+on e.ename = b.ename and e.deptno = 10
+]]>
+        </Resource>
+        <Resource name="planBefore">
+            <![CDATA[
+LogicalProject(EXPR$0=[+($5, $12)], EXPR$1=[COUNT($0) OVER (PARTITION BY $7 
RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING)])
+  LogicalJoin(condition=[AND(=($1, $9), =($7, 10))], joinType=[inner])
+    LogicalTableScan(table=[[CATALOG, SALES, EMP]])
+    LogicalTableScan(table=[[CATALOG, SALES, BONUS]])
+]]>
+        </Resource>
+        <Resource name="planAfter">
+            <![CDATA[
+LogicalProject(EXPR$0=[+($2, $6)], EXPR$1=[COUNT($0) OVER (PARTITION BY $3 
RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING)])
+  LogicalJoin(condition=[AND(=($1, $5), $4)], joinType=[inner])
+    LogicalProject(EMPNO=[$0], ENAME=[$1], SAL=[$5], DEPTNO=[$7], ==[=($7, 
10)])
+      LogicalTableScan(table=[[CATALOG, SALES, EMP]])
+    LogicalProject(ENAME=[$0], COMM=[$3])
+      LogicalTableScan(table=[[CATALOG, SALES, BONUS]])
+]]>
+        </Resource>
+    </TestCase>
+    <TestCase name="testPushProjectWithOverPastJoin2">
+        <Resource name="sql">
+            <![CDATA[select e.sal + b.comm,
+count(b.sal) over (partition by b.job)
+from emp e join bonus b
+on e.ename = b.ename and e.deptno = 10
+]]>
+        </Resource>
+        <Resource name="planBefore">
+            <![CDATA[
+LogicalProject(EXPR$0=[+($5, $12)], EXPR$1=[COUNT($11) OVER (PARTITION BY $10 
RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING)])
+  LogicalJoin(condition=[AND(=($1, $9), =($7, 10))], joinType=[inner])
+    LogicalTableScan(table=[[CATALOG, SALES, EMP]])
+    LogicalTableScan(table=[[CATALOG, SALES, BONUS]])
+]]>
+        </Resource>
+        <Resource name="planAfter">
+            <![CDATA[
+LogicalProject(EXPR$0=[+($1, $6)], EXPR$1=[COUNT($5) OVER (PARTITION BY $4 
RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING)])
+  LogicalJoin(condition=[AND(=($0, $3), $2)], joinType=[inner])
+    LogicalProject(ENAME=[$1], SAL=[$5], ==[=($7, 10)])
+      LogicalTableScan(table=[[CATALOG, SALES, EMP]])
+    LogicalProject(ENAME=[$0], JOB=[$1], SAL=[$2], COMM=[$3])
+      LogicalTableScan(table=[[CATALOG, SALES, BONUS]])
+]]>
+        </Resource>
+    </TestCase>
+    <TestCase name="testPushProjectWithOverPastJoin3">
+        <Resource name="sql">
+            <![CDATA[select e.sal + b.comm,
+sum(b.sal + b.sal + 100) over (partition by b.job)
+from emp e join bonus b
+on e.ename = b.ename and e.deptno = 10
+]]>
+        </Resource>
+        <Resource name="planBefore">
+            <![CDATA[
+LogicalProject(EXPR$0=[+($5, $12)], EXPR$1=[SUM(+(+($11, $11), 100)) OVER 
(PARTITION BY $10 RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING)])
+  LogicalJoin(condition=[AND(=($1, $9), =($7, 10))], joinType=[inner])
+    LogicalTableScan(table=[[CATALOG, SALES, EMP]])
+    LogicalTableScan(table=[[CATALOG, SALES, BONUS]])
+]]>
+        </Resource>
+        <Resource name="planAfter">
+            <![CDATA[
+LogicalProject(EXPR$0=[+($1, $5)], EXPR$1=[SUM($6) OVER (PARTITION BY $4 RANGE 
BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING)])
+  LogicalJoin(condition=[AND(=($0, $3), $2)], joinType=[inner])
+    LogicalProject(ENAME=[$1], SAL=[$5], ==[=($7, 10)])
+      LogicalTableScan(table=[[CATALOG, SALES, EMP]])
+    LogicalProject(ENAME=[$0], JOB=[$1], COMM=[$3], +=[+(+($2, $2), 100)])
+      LogicalTableScan(table=[[CATALOG, SALES, BONUS]])
+]]>
+        </Resource>
+    </TestCase>
     <TestCase name="testPushProjectPastSetOp">
         <Resource name="sql">
             <![CDATA[select sal from (select * from emp e1 union all select * 
from emp e2)]]>

Reply via email to