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)]]>