You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@calcite.apache.org by jh...@apache.org on 2014/09/16 00:14:33 UTC

git commit: [OPTIQ-409] PushFilterPastProjectRule should not push filters past windowed aggregates

Repository: incubator-optiq
Updated Branches:
  refs/heads/master 0184cc575 -> d0b284908


[OPTIQ-409] PushFilterPastProjectRule should not push filters past windowed aggregates


Project: http://git-wip-us.apache.org/repos/asf/incubator-optiq/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-optiq/commit/d0b28490
Tree: http://git-wip-us.apache.org/repos/asf/incubator-optiq/tree/d0b28490
Diff: http://git-wip-us.apache.org/repos/asf/incubator-optiq/diff/d0b28490

Branch: refs/heads/master
Commit: d0b284908d1047ac9ef59ff8760d939b144ca607
Parents: 0184cc5
Author: Harish Butani <hb...@hortonworks.com>
Authored: Mon Sep 15 14:21:54 2014 -0700
Committer: Julian Hyde <jh...@apache.org>
Committed: Mon Sep 15 14:42:54 2014 -0700

----------------------------------------------------------------------
 .../rel/rules/PushFilterPastProjectRule.java    | 14 +++++-
 .../org/eigenbase/test/RelOptRulesTest.java     | 22 +++++++++
 .../org/eigenbase/test/RelOptRulesTest.xml      | 48 ++++++++++++++++++++
 3 files changed, 82 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-optiq/blob/d0b28490/core/src/main/java/org/eigenbase/rel/rules/PushFilterPastProjectRule.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/eigenbase/rel/rules/PushFilterPastProjectRule.java b/core/src/main/java/org/eigenbase/rel/rules/PushFilterPastProjectRule.java
index 659d781..2e07d23 100644
--- a/core/src/main/java/org/eigenbase/rel/rules/PushFilterPastProjectRule.java
+++ b/core/src/main/java/org/eigenbase/rel/rules/PushFilterPastProjectRule.java
@@ -50,11 +50,11 @@ public class PushFilterPastProjectRule extends RelOptRule {
   public PushFilterPastProjectRule(
       Class<? extends FilterRelBase> filterClass,
       RelFactories.FilterFactory filterFactory,
-      Class<? extends ProjectRelBase> projectRelBaseClass,
+      Class<? extends ProjectRelBase> projectClass,
       RelFactories.ProjectFactory projectFactory) {
     super(
         operand(filterClass,
-            operand(projectRelBaseClass, any())));
+            operand(projectClass, any())));
     this.filterFactory = filterFactory;
     this.projectFactory = projectFactory;
   }
@@ -66,6 +66,16 @@ public class PushFilterPastProjectRule extends RelOptRule {
     final FilterRelBase filterRel = call.rel(0);
     final ProjectRelBase projRel = call.rel(1);
 
+    if (RexOver.containsOver(projRel.getProjects(), null)) {
+      // In general a filter cannot be pushed below a windowing calculation.
+      // Applying the filter before the aggregation function changes
+      // the results of the windowing invocation.
+      //
+      // When the filter is on the PARTITION BY expression of the OVER clause
+      // it can be pushed down. For now we don't support this.
+      return;
+    }
+
     // convert the filter to one that references the child of the project
     RexNode newCondition =
         RelOptUtil.pushFilterPastProject(filterRel.getCondition(), projRel);

http://git-wip-us.apache.org/repos/asf/incubator-optiq/blob/d0b28490/core/src/test/java/org/eigenbase/test/RelOptRulesTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/eigenbase/test/RelOptRulesTest.java b/core/src/test/java/org/eigenbase/test/RelOptRulesTest.java
index 31a9906..b6bc208 100644
--- a/core/src/test/java/org/eigenbase/test/RelOptRulesTest.java
+++ b/core/src/test/java/org/eigenbase/test/RelOptRulesTest.java
@@ -1001,6 +1001,28 @@ public class RelOptRulesTest extends RelOptTestBase {
   @Test public void testTransitiveInferenceComplexPredicate() throws Exception {
     transitiveInference();
   }
+
+  @Test public void testPushFilterWithRank() throws Exception {
+    HepProgram program = new HepProgramBuilder().addRuleInstance(
+        PushFilterPastProjectRule.INSTANCE).build();
+    checkPlanning(program, "select e1.ename, r\n"
+        + "from (\n"
+        + "  select ename, "
+        + "  rank() over(partition by  deptno order by sal) as r "
+        + "  from emp) e1\n"
+        + "where r < 2");
+  }
+
+  @Test public void testPushFilterWithRankExpr() throws Exception {
+    HepProgram program = new HepProgramBuilder().addRuleInstance(
+        PushFilterPastProjectRule.INSTANCE).build();
+    checkPlanning(program, "select e1.ename, r\n"
+        + "from (\n"
+        + "  select ename,\n"
+        + "  rank() over(partition by  deptno order by sal) + 1 as r "
+        + "  from emp) e1\n"
+        + "where r < 2");
+  }
 }
 
 // End RelOptRulesTest.java

http://git-wip-us.apache.org/repos/asf/incubator-optiq/blob/d0b28490/core/src/test/resources/org/eigenbase/test/RelOptRulesTest.xml
----------------------------------------------------------------------
diff --git a/core/src/test/resources/org/eigenbase/test/RelOptRulesTest.xml b/core/src/test/resources/org/eigenbase/test/RelOptRulesTest.xml
index e96dfb1..07eeb68 100644
--- a/core/src/test/resources/org/eigenbase/test/RelOptRulesTest.xml
+++ b/core/src/test/resources/org/eigenbase/test/RelOptRulesTest.xml
@@ -2158,4 +2158,52 @@ ProjectRel(X=[$0], EXPR$1=[$2], Y=[$1])
 ]]>
         </Resource>
     </TestCase>
+    <TestCase name="testPushFilterWithRank">
+        <Resource name="sql">
+            <![CDATA[select e1.ename, r
+from (select ename, rank() over(partition by  deptno order by sal) as r from emp) e1
+where r < 2
+]]>
+        </Resource>
+        <Resource name="planBefore">
+            <![CDATA[
+ProjectRel(ENAME=[$0], R=[$1])
+  FilterRel(condition=[<($1, 2)])
+    ProjectRel(ENAME=[$1], R=[RANK() OVER (PARTITION BY $7 ORDER BY $5 RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW)])
+      TableAccessRel(table=[[CATALOG, SALES, EMP]])
+]]>
+        </Resource>
+        <Resource name="planAfter">
+            <![CDATA[
+ProjectRel(ENAME=[$0], R=[$1])
+  FilterRel(condition=[<($1, 2)])
+    ProjectRel(ENAME=[$1], R=[RANK() OVER (PARTITION BY $7 ORDER BY $5 RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW)])
+      TableAccessRel(table=[[CATALOG, SALES, EMP]])
+]]>
+        </Resource>
+    </TestCase>
+    <TestCase name="testPushFilterWithRankExpr">
+        <Resource name="sql">
+            <![CDATA[select e1.ename, r
+from (select ename, rank() over(partition by  deptno order by sal) as r + 1 from emp) e1
+where r < 2
+]]>
+        </Resource>
+        <Resource name="planBefore">
+            <![CDATA[
+ProjectRel(ENAME=[$0], R=[$1])
+  FilterRel(condition=[<($1, 2)])
+    ProjectRel(ENAME=[$1], R=[+(RANK() OVER (PARTITION BY $7 ORDER BY $5 RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), 1)])
+      TableAccessRel(table=[[CATALOG, SALES, EMP]])
+]]>
+        </Resource>
+        <Resource name="planAfter">
+            <![CDATA[
+ProjectRel(ENAME=[$0], R=[$1])
+  FilterRel(condition=[<($1, 2)])
+    ProjectRel(ENAME=[$1], R=[+(RANK() OVER (PARTITION BY $7 ORDER BY $5 RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), 1)])
+      TableAccessRel(table=[[CATALOG, SALES, EMP]])
+]]>
+        </Resource>
+    </TestCase>
 </Root>