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/26 23:07:28 UTC
git commit: [OPTIQ-425] Add FilterAggregateTransposeRule,
that pushes a filter through an aggregate.
Repository: incubator-optiq
Updated Branches:
refs/heads/master 232a8f4da -> a5665df97
[OPTIQ-425] Add FilterAggregateTransposeRule, that pushes a filter through an aggregate.
Project: http://git-wip-us.apache.org/repos/asf/incubator-optiq/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-optiq/commit/a5665df9
Tree: http://git-wip-us.apache.org/repos/asf/incubator-optiq/tree/a5665df9
Diff: http://git-wip-us.apache.org/repos/asf/incubator-optiq/diff/a5665df9
Branch: refs/heads/master
Commit: a5665df971c128bfcc83e143c61522fecff942e2
Parents: 232a8f4
Author: Harish Butani <hb...@hortonworks.com>
Authored: Fri Sep 26 12:37:42 2014 -0700
Committer: Julian Hyde <jh...@apache.org>
Committed: Fri Sep 26 13:40:06 2014 -0700
----------------------------------------------------------------------
.../optiq/prepare/OptiqPrepareImpl.java | 1 +
.../net/hydromatic/optiq/tools/Programs.java | 1 +
.../rel/rules/AggregateFilterTransposeRule.java | 2 +
.../rel/rules/FilterAggregateTransposeRule.java | 109 +++++++++++++++++++
.../net/hydromatic/optiq/test/JdbcTest.java | 7 +-
.../org/eigenbase/test/RelOptRulesTest.java | 10 +-
.../org/eigenbase/test/RelOptRulesTest.xml | 23 ++++
7 files changed, 148 insertions(+), 5 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-optiq/blob/a5665df9/core/src/main/java/net/hydromatic/optiq/prepare/OptiqPrepareImpl.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/net/hydromatic/optiq/prepare/OptiqPrepareImpl.java b/core/src/main/java/net/hydromatic/optiq/prepare/OptiqPrepareImpl.java
index a34d80c..9907a5b 100644
--- a/core/src/main/java/net/hydromatic/optiq/prepare/OptiqPrepareImpl.java
+++ b/core/src/main/java/net/hydromatic/optiq/prepare/OptiqPrepareImpl.java
@@ -132,6 +132,7 @@ public class OptiqPrepareImpl implements OptiqPrepare {
PushFilterPastJoinRule.FILTER_ON_JOIN,
RemoveDistinctAggregateRule.INSTANCE,
ReduceAggregatesRule.INSTANCE,
+ FilterAggregateTransposeRule.INSTANCE,
SwapJoinRule.INSTANCE,
PushJoinThroughJoinRule.RIGHT,
PushJoinThroughJoinRule.LEFT,
http://git-wip-us.apache.org/repos/asf/incubator-optiq/blob/a5665df9/core/src/main/java/net/hydromatic/optiq/tools/Programs.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/net/hydromatic/optiq/tools/Programs.java b/core/src/main/java/net/hydromatic/optiq/tools/Programs.java
index cfa2cdb..2b7fe78 100644
--- a/core/src/main/java/net/hydromatic/optiq/tools/Programs.java
+++ b/core/src/main/java/net/hydromatic/optiq/tools/Programs.java
@@ -95,6 +95,7 @@ public class Programs {
PushFilterPastJoinRule.FILTER_ON_JOIN,
RemoveDistinctAggregateRule.INSTANCE,
ReduceAggregatesRule.INSTANCE,
+ FilterAggregateTransposeRule.INSTANCE,
SwapJoinRule.INSTANCE,
PushJoinThroughJoinRule.RIGHT,
PushJoinThroughJoinRule.LEFT,
http://git-wip-us.apache.org/repos/asf/incubator-optiq/blob/a5665df9/core/src/main/java/org/eigenbase/rel/rules/AggregateFilterTransposeRule.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/eigenbase/rel/rules/AggregateFilterTransposeRule.java b/core/src/main/java/org/eigenbase/rel/rules/AggregateFilterTransposeRule.java
index 44a5818..06693fa 100644
--- a/core/src/main/java/org/eigenbase/rel/rules/AggregateFilterTransposeRule.java
+++ b/core/src/main/java/org/eigenbase/rel/rules/AggregateFilterTransposeRule.java
@@ -50,6 +50,8 @@ import com.google.common.collect.Lists;
* away. The rule might be beneficial if the predicate is very expensive to
* evaluate. The main use of the rule is to match a query that has a filter
* under an aggregate to an existing aggregate table.
+ *
+ * @see org.eigenbase.rel.rules.FilterAggregateTransposeRule
*/
public class AggregateFilterTransposeRule extends RelOptRule {
public static final AggregateFilterTransposeRule INSTANCE =
http://git-wip-us.apache.org/repos/asf/incubator-optiq/blob/a5665df9/core/src/main/java/org/eigenbase/rel/rules/FilterAggregateTransposeRule.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/eigenbase/rel/rules/FilterAggregateTransposeRule.java b/core/src/main/java/org/eigenbase/rel/rules/FilterAggregateTransposeRule.java
new file mode 100644
index 0000000..0ff4b58
--- /dev/null
+++ b/core/src/main/java/org/eigenbase/rel/rules/FilterAggregateTransposeRule.java
@@ -0,0 +1,109 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.eigenbase.rel.rules;
+
+import java.util.BitSet;
+import java.util.List;
+
+import org.eigenbase.rel.*;
+import org.eigenbase.relopt.*;
+import org.eigenbase.reltype.RelDataTypeField;
+import org.eigenbase.rex.*;
+
+import net.hydromatic.optiq.util.BitSets;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Lists;
+
+/**
+ * Planner rule that pushes a {@link FilterRelBase}
+ * past a {@link AggregateRelBase}.
+ *
+ * @see org.eigenbase.rel.rules.AggregateFilterTransposeRule
+ */
+public class FilterAggregateTransposeRule extends RelOptRule {
+
+ /** The default instance of
+ * {@link FilterAggregateTransposeRule}.
+ *
+ * <p>It matches any kind of agg. or filter */
+ public static final FilterAggregateTransposeRule INSTANCE =
+ new FilterAggregateTransposeRule(FilterRelBase.class,
+ RelFactories.DEFAULT_FILTER_FACTORY,
+ AggregateRelBase.class);
+
+ private final RelFactories.FilterFactory filterFactory;
+
+ //~ Constructors -----------------------------------------------------------
+
+ /**
+ * Creates a PushFilterPastAggRule.
+ *
+ * <p>If {@code filterFactory} is null, creates the same kind of filter as
+ * matched in the rule. Similarly {@code aggregateFactory}.</p>
+ */
+ public FilterAggregateTransposeRule(
+ Class<? extends FilterRelBase> filterClass,
+ RelFactories.FilterFactory filterFactory,
+ Class<? extends AggregateRelBase> aggregateClass) {
+ super(
+ operand(filterClass,
+ operand(aggregateClass, any())));
+ this.filterFactory = filterFactory;
+ }
+
+ //~ Methods ----------------------------------------------------------------
+
+ // implement RelOptRule
+ public void onMatch(RelOptRuleCall call) {
+ final FilterRelBase filterRel = call.rel(0);
+ final AggregateRelBase aggRel = call.rel(1);
+
+ final List<RexNode> conditions =
+ RelOptUtil.conjunctions(filterRel.getCondition());
+ final BitSet groupKeys = aggRel.getGroupSet();
+ final RexBuilder rexBuilder = filterRel.getCluster().getRexBuilder();
+ final List<RelDataTypeField> origFields =
+ aggRel.getRowType().getFieldList();
+ final int[] adjustments = new int[origFields.size()];
+ final List<RexNode> pushedConditions = Lists.newArrayList();
+
+ for (RexNode condition : conditions) {
+ BitSet rCols = RelOptUtil.InputFinder.bits(condition);
+ if (BitSets.contains(groupKeys, rCols)) {
+ pushedConditions.add(
+ condition.accept(
+ new RelOptUtil.RexInputConverter(rexBuilder, origFields,
+ aggRel.getInput(0).getRowType().getFieldList(),
+ adjustments)));
+ }
+ }
+
+ final RexNode pushedCondition = RexUtil.composeConjunction(rexBuilder,
+ pushedConditions, true);
+
+ if (pushedCondition != null) {
+ RelNode newFilterRel = filterFactory.createFilter(aggRel.getInput(0),
+ pushedCondition);
+ RelNode newAggRel = aggRel.copy(aggRel.getTraitSet(),
+ ImmutableList.of(newFilterRel));
+ call.transformTo(newAggRel);
+ }
+ }
+}
+
+// End FilterAggregateTransposeRule.java
http://git-wip-us.apache.org/repos/asf/incubator-optiq/blob/a5665df9/core/src/test/java/net/hydromatic/optiq/test/JdbcTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/net/hydromatic/optiq/test/JdbcTest.java b/core/src/test/java/net/hydromatic/optiq/test/JdbcTest.java
index d87476f..9ce3b1a 100644
--- a/core/src/test/java/net/hydromatic/optiq/test/JdbcTest.java
+++ b/core/src/test/java/net/hydromatic/optiq/test/JdbcTest.java
@@ -2072,10 +2072,9 @@ public class JdbcTest {
.explainContains(
"EnumerableCalcRel(expr#0..8=[{inputs}], c0=[$t3], c1=[$t2], c2=[$t1], c3=[$t0], c4=[$t8], c5=[$t8], c6=[$t6], c7=[$t4], c8=[$t7], c9=[$t5])\n"
+ " EnumerableSortRel(sort0=[$3], sort1=[$2], sort2=[$1], sort3=[$8], dir0=[ASC-nulls-last], dir1=[ASC-nulls-last], dir2=[ASC-nulls-last], dir3=[ASC-nulls-last])\n"
- + " EnumerableCalcRel(expr#0..8=[{inputs}], expr#9=['%Jeanne%'], expr#10=[LIKE($t8, $t9)], proj#0..8=[{exprs}], $condition=[$t10])\n"
- + " EnumerableAggregateRel(group=[{0, 1, 2, 3, 4, 5, 6, 7, 8}])\n"
- + " EnumerableCalcRel(expr#0..9=[{inputs}], expr#10=[CAST($t0):INTEGER], expr#11=[1997], expr#12=[=($t10, $t11)], $f0=[$t1], $f1=[$t2], $f2=[$t3], $f3=[$t4], $f4=[$t5], $f5=[$t6], $f6=[$t7], $f7=[$t8], $f8=[$t9], $f9=[$t0], $condition=[$t12])\n"
- + " EnumerableTableAccessRel(table=[[foodmart, m{12, 18, 27, 28, 30, 35, 36, 37, 40, 46}]])")
+ + " EnumerableAggregateRel(group=[{0, 1, 2, 3, 4, 5, 6, 7, 8}])\n"
+ + " EnumerableCalcRel(expr#0..9=[{inputs}], expr#10=[CAST($t0):INTEGER], expr#11=[1997], expr#12=[=($t10, $t11)], expr#13=['%Jeanne%'], expr#14=[LIKE($t9, $t13)], expr#15=[AND($t12, $t14)], $f0=[$t1], $f1=[$t2], $f2=[$t3], $f3=[$t4], $f4=[$t5], $f5=[$t6], $f6=[$t7], $f7=[$t8], $f8=[$t9], $f9=[$t0], $condition=[$t15])\n"
+ + " EnumerableTableAccessRel(table=[[foodmart, m{12, 18, 27, 28, 30, 35, 36, 37, 40, 46}]])")
.runs();
}
http://git-wip-us.apache.org/repos/asf/incubator-optiq/blob/a5665df9/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 b6bc208..095d7d4 100644
--- a/core/src/test/java/org/eigenbase/test/RelOptRulesTest.java
+++ b/core/src/test/java/org/eigenbase/test/RelOptRulesTest.java
@@ -29,6 +29,7 @@ import org.eigenbase.rel.rules.AggregateProjectMergeRule;
import org.eigenbase.rel.rules.CoerceInputsRule;
import org.eigenbase.rel.rules.ConvertMultiJoinRule;
import org.eigenbase.rel.rules.ExtractJoinFilterRule;
+import org.eigenbase.rel.rules.FilterAggregateTransposeRule;
import org.eigenbase.rel.rules.FilterToCalcRule;
import org.eigenbase.rel.rules.MergeCalcRule;
import org.eigenbase.rel.rules.MergeProjectRule;
@@ -163,6 +164,14 @@ public class RelOptRulesTest extends RelOptTestBase {
+ " where d.name = 'Charlie'");
}
+ @Test public void testPushFilterPastAgg() {
+ checkPlanning(
+ FilterAggregateTransposeRule.INSTANCE,
+ "select dname, c from"
+ + " (select name dname, count(*) as c from dept group by name) t"
+ + " where dname = 'Charlie'");
+ }
+
@Test public void testSemiJoinRule() {
final HepProgram preProgram =
HepProgram.builder()
@@ -183,7 +192,6 @@ public class RelOptRulesTest extends RelOptTestBase {
}
protected void semiJoinTrim() {
-
final DiffRepository diffRepos = getDiffRepos();
String sql = diffRepos.expand(null, "${sql}");
http://git-wip-us.apache.org/repos/asf/incubator-optiq/blob/a5665df9/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 07eeb68..7016804 100644
--- a/core/src/test/resources/org/eigenbase/test/RelOptRulesTest.xml
+++ b/core/src/test/resources/org/eigenbase/test/RelOptRulesTest.xml
@@ -108,6 +108,29 @@ ProjectRel(EXPR$0=[1])
]]>
</Resource>
</TestCase>
+ <TestCase name="testPushFilterPastAgg">
+ <Resource name="sql">
+ <![CDATA[select dname, c from (select name dname, count(*) as c from dept group by name) t where dname = 'Charlie']]>
+ </Resource>
+ <Resource name="planBefore">
+ <![CDATA[
+ProjectRel(DNAME=[$0], C=[$1])
+ FilterRel(condition=[=($0, 'Charlie')])
+ AggregateRel(group=[{0}], C=[COUNT()])
+ ProjectRel(DNAME=[$1])
+ TableAccessRel(table=[[CATALOG, SALES, DEPT]])
+]]>
+ </Resource>
+ <Resource name="planAfter">
+ <![CDATA[
+ProjectRel(DNAME=[$0], C=[$1])
+ AggregateRel(group=[{0}], C=[COUNT()])
+ FilterRel(condition=[=($0, 'Charlie')])
+ ProjectRel(DNAME=[$1])
+ TableAccessRel(table=[[CATALOG, SALES, DEPT]])
+]]>
+ </Resource>
+ </TestCase>
<TestCase name="testReduceAverage">
<Resource name="sql">
<![CDATA[select name, max(name), avg(deptno), min(name) from sales.dept group by name]]>