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/12/18 08:28:10 UTC
[1/3] incubator-calcite git commit: [CALCITE-532] Support for
grouping sets in AggregateFilterTransposeRule (Jesus Camacho Rodriguez)
Repository: incubator-calcite
Updated Branches:
refs/heads/master 2b3581923 -> 288254b22
[CALCITE-532] Support for grouping sets in AggregateFilterTransposeRule (Jesus Camacho Rodriguez)
Close apache/incubator-calcite#33
Project: http://git-wip-us.apache.org/repos/asf/incubator-calcite/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-calcite/commit/e8ee2b31
Tree: http://git-wip-us.apache.org/repos/asf/incubator-calcite/tree/e8ee2b31
Diff: http://git-wip-us.apache.org/repos/asf/incubator-calcite/diff/e8ee2b31
Branch: refs/heads/master
Commit: e8ee2b31e7cec6bf26c7f0bb45ea870a9d4744d9
Parents: 2b35819
Author: Jesus Camacho Rodriguez <jc...@hortonworks.com>
Authored: Mon Dec 15 16:55:45 2014 +0100
Committer: Julian Hyde <jh...@apache.org>
Committed: Wed Dec 17 12:45:48 2014 -0800
----------------------------------------------------------------------
.../rel/rules/AggregateFilterTransposeRule.java | 34 ++++++++++---
.../apache/calcite/test/RelOptRulesTest.java | 36 +++++++++++++
.../org/apache/calcite/test/RelOptRulesTest.xml | 53 ++++++++++++++++++++
3 files changed, 115 insertions(+), 8 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/e8ee2b31/core/src/main/java/org/apache/calcite/rel/rules/AggregateFilterTransposeRule.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rel/rules/AggregateFilterTransposeRule.java b/core/src/main/java/org/apache/calcite/rel/rules/AggregateFilterTransposeRule.java
index 82c30f1..dfa325d 100644
--- a/core/src/main/java/org/apache/calcite/rel/rules/AggregateFilterTransposeRule.java
+++ b/core/src/main/java/org/apache/calcite/rel/rules/AggregateFilterTransposeRule.java
@@ -58,7 +58,7 @@ public class AggregateFilterTransposeRule extends RelOptRule {
private AggregateFilterTransposeRule() {
super(
- operand(Aggregate.class, null, Aggregate.IS_SIMPLE,
+ operand(Aggregate.class,
operand(Filter.class, any())));
}
@@ -80,9 +80,11 @@ public class AggregateFilterTransposeRule extends RelOptRule {
// the rule fires forever: A-F => A-F-A => A-A-F-A => A-A-A-F-A => ...
return;
}
+ boolean allColumnsInAggregate = aggregate.getGroupSet().
+ contains(filterColumns);
final Aggregate newAggregate =
- aggregate.copy(aggregate.getTraitSet(), input, false, newGroupSet, null,
- aggregate.getAggCallList());
+ aggregate.copy(aggregate.getTraitSet(), input,
+ false, newGroupSet, null, aggregate.getAggCallList());
final Mappings.TargetMapping mapping = Mappings.target(
new Function<Integer, Integer>() {
public Integer apply(Integer a0) {
@@ -95,17 +97,32 @@ public class AggregateFilterTransposeRule extends RelOptRule {
RexUtil.apply(mapping, filter.getCondition());
final Filter newFilter = filter.copy(filter.getTraitSet(),
newAggregate, newCondition);
- if (aggregate.getGroupSet().contains(filterColumns)) {
+ if (allColumnsInAggregate && !aggregate.indicator) {
// Everything needed by the filter is returned by the aggregate.
assert newGroupSet.equals(aggregate.getGroupSet());
call.transformTo(newFilter);
} else {
- // The filter needs at least one extra column.
- // Now aggregate it away.
+ // If aggregate uses grouping sets, we always need to split it.
+ // Otherwise, it means that grouping sets are not used, but the
+ // filter needs at least one extra column, and now aggregate it away.
final ImmutableBitSet.Builder topGroupSet = ImmutableBitSet.builder();
for (int c : aggregate.getGroupSet()) {
topGroupSet.set(newGroupSet.indexOf(c));
}
+ ImmutableList<ImmutableBitSet> newGroupingSets = null;
+ if (aggregate.indicator) {
+ ImmutableList.Builder<ImmutableBitSet> newGroupingSetsBuilder =
+ ImmutableList.builder();
+ for (ImmutableBitSet groupingSet: aggregate.getGroupSets()) {
+ final ImmutableBitSet.Builder newGroupingSet =
+ ImmutableBitSet.builder();
+ for (int c : groupingSet) {
+ newGroupingSet.set(newGroupSet.indexOf(c));
+ }
+ newGroupingSetsBuilder.add(newGroupingSet.build());
+ }
+ newGroupingSets = newGroupingSetsBuilder.build();
+ }
final List<AggregateCall> topAggCallList = Lists.newArrayList();
int i = newGroupSet.cardinality();
for (AggregateCall aggregateCall : aggregate.getAggCallList()) {
@@ -124,8 +141,9 @@ public class AggregateFilterTransposeRule extends RelOptRule {
ImmutableList.of(i++), aggregateCall.type, aggregateCall.name));
}
final Aggregate topAggregate =
- aggregate.copy(aggregate.getTraitSet(), newFilter, false,
- topGroupSet.build(), null, topAggCallList);
+ aggregate.copy(aggregate.getTraitSet(), newFilter,
+ aggregate.indicator, topGroupSet.build(),
+ newGroupingSets, topAggCallList);
call.transformTo(topAggregate);
}
}
http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/e8ee2b31/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java
----------------------------------------------------------------------
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 f1db459..bfa65c9 100644
--- a/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java
+++ b/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java
@@ -29,6 +29,7 @@ import org.apache.calcite.rel.metadata.ChainedRelMetadataProvider;
import org.apache.calcite.rel.metadata.DefaultRelMetadataProvider;
import org.apache.calcite.rel.metadata.RelMetadataProvider;
import org.apache.calcite.rel.rules.AggregateExpandDistinctAggregatesRule;
+import org.apache.calcite.rel.rules.AggregateFilterTransposeRule;
import org.apache.calcite.rel.rules.AggregateProjectMergeRule;
import org.apache.calcite.rel.rules.AggregateProjectPullUpConstantsRule;
import org.apache.calcite.rel.rules.AggregateReduceFunctionsRule;
@@ -995,6 +996,41 @@ public class RelOptRulesTest extends RelOptTestBase {
basePushAggThroughUnion();
}
+ @Test public void testPullFilterThroughAggregate() throws Exception {
+ HepProgram preProgram = HepProgram.builder()
+ .addRuleInstance(ProjectMergeRule.INSTANCE)
+ .addRuleInstance(ProjectFilterTransposeRule.INSTANCE)
+ .build();
+ HepProgram program = HepProgram.builder()
+ .addRuleInstance(AggregateFilterTransposeRule.INSTANCE)
+ .build();
+ checkPlanning(tester, preProgram,
+ new HepPlanner(program),
+ "select empno, sal, deptno from ("
+ + " select empno, sal, deptno"
+ + " from emp"
+ + " where sal > 5000)"
+ + "group by empno, sal, deptno");
+ }
+
+ @Test public void testPullFilterThroughAggregateGroupingSets()
+ throws Exception {
+ HepProgram preProgram = HepProgram.builder()
+ .addRuleInstance(ProjectMergeRule.INSTANCE)
+ .addRuleInstance(ProjectFilterTransposeRule.INSTANCE)
+ .build();
+ HepProgram program = HepProgram.builder()
+ .addRuleInstance(AggregateFilterTransposeRule.INSTANCE)
+ .build();
+ checkPlanning(tester, preProgram,
+ new HepPlanner(program),
+ "select empno, sal, deptno from ("
+ + " select empno, sal, deptno"
+ + " from emp"
+ + " where sal > 5000)"
+ + "group by rollup(empno, sal, deptno)");
+ }
+
private void basePullConstantTroughAggregate() throws Exception {
HepProgram program = new HepProgramBuilder()
.addRuleInstance(ProjectMergeRule.INSTANCE)
http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/e8ee2b31/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml
----------------------------------------------------------------------
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 1f20cc4..9ffdaf4 100644
--- a/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml
+++ b/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml
@@ -1468,6 +1468,59 @@ LogicalProject(DEPTNO=[CASE($2, null, $0)], JOB=[CASE($3, null, $1)], EXPR$2=[$4
]]>
</Resource>
</TestCase>
+ <TestCase name="testPullFilterThroughAggregate">
+ <Resource name="sql">
+ <![CDATA[select empno, sal, deptno from (
+ select empno, sal, deptno
+ from emp
+ where sal > 5000)
+ group by empno, sal, deptno]]>
+ </Resource>
+ <Resource name="planBefore">
+ <![CDATA[
+LogicalAggregate(group=[{0, 1, 2}])
+ LogicalFilter(condition=[>($1, 5000)])
+ LogicalProject(EMPNO=[$0], SAL=[$5], DEPTNO=[$7])
+ LogicalTableScan(table=[[CATALOG, SALES, EMP]])
+]]>
+ </Resource>
+ <Resource name="planAfter">
+ <![CDATA[
+LogicalFilter(condition=[>($1, 5000)])
+ LogicalAggregate(group=[{0, 1, 2}])
+ LogicalProject(EMPNO=[$0], SAL=[$5], DEPTNO=[$7])
+ LogicalTableScan(table=[[CATALOG, SALES, EMP]])
+]]>
+ </Resource>
+ </TestCase>
+ <TestCase name="testPullFilterThroughAggregateGroupingSets">
+ <Resource name="sql">
+ <![CDATA[select empno, sal, deptno from (
+ select empno, sal, deptno
+ from emp
+ where sal > 5000)
+ group by rollup(empno, sal, deptno)]]>
+ </Resource>
+ <Resource name="planBefore">
+ <![CDATA[
+LogicalProject(EMPNO=[CASE($3, null, $0)], SAL=[CASE($4, null, $1)], DEPTNO=[CASE($5, null, $2)])
+ LogicalAggregate(group=[{0, 1, 2}], groups=[[{0, 1, 2}, {0, 1}, {0}, {}]], indicator=[true])
+ LogicalFilter(condition=[>($1, 5000)])
+ LogicalProject(EMPNO=[$0], SAL=[$5], DEPTNO=[$7])
+ LogicalTableScan(table=[[CATALOG, SALES, EMP]])
+]]>
+ </Resource>
+ <Resource name="planAfter">
+ <![CDATA[
+LogicalProject(EMPNO=[CASE($3, null, $0)], SAL=[CASE($4, null, $1)], DEPTNO=[CASE($5, null, $2)])
+ LogicalAggregate(group=[{0, 1, 2}], groups=[[{0, 1, 2}, {0, 1}, {0}, {}]], indicator=[true])
+ LogicalFilter(condition=[>($1, 5000)])
+ LogicalAggregate(group=[{0, 1, 2}])
+ LogicalProject(EMPNO=[$0], SAL=[$5], DEPTNO=[$7])
+ LogicalTableScan(table=[[CATALOG, SALES, EMP]])
+]]>
+ </Resource>
+ </TestCase>
<TestCase name="testPullConstantThroughConstLast">
<Resource name="sql">
<![CDATA[select deptno, max(mgr) from (
[3/3] incubator-calcite git commit: [CALCITE-479] Migrate
RelNode.getChildExps to RelNode.accept(RexShuttle)
Posted by jh...@apache.org.
[CALCITE-479] Migrate RelNode.getChildExps to RelNode.accept(RexShuttle)
Close apache/incubator-calcite#31
Project: http://git-wip-us.apache.org/repos/asf/incubator-calcite/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-calcite/commit/288254b2
Tree: http://git-wip-us.apache.org/repos/asf/incubator-calcite/tree/288254b2
Diff: http://git-wip-us.apache.org/repos/asf/incubator-calcite/diff/288254b2
Branch: refs/heads/master
Commit: 288254b22b270b9a6e893490e776a3ba4ff01fb6
Parents: 86c7c08
Author: Vladimir Sitnikov <si...@gmail.com>
Authored: Sun Dec 14 15:41:57 2014 +0300
Committer: Julian Hyde <jh...@apache.org>
Committed: Wed Dec 17 20:50:56 2014 -0800
----------------------------------------------------------------------
.../enumerable/EnumerableTableFunctionScan.java | 10 ++-
.../org/apache/calcite/plan/RelOptUtil.java | 30 ++++---
.../apache/calcite/plan/VisitorRelVisitor.java | 55 -------------
.../org/apache/calcite/rel/AbstractRelNode.java | 5 ++
.../calcite/rel/RelHomogeneousShuttle.java | 86 ++++++++++++++++++++
.../java/org/apache/calcite/rel/RelNode.java | 14 ++++
.../java/org/apache/calcite/rel/core/Calc.java | 28 +++++++
.../org/apache/calcite/rel/core/Filter.java | 9 ++
.../java/org/apache/calcite/rel/core/Join.java | 9 ++
.../org/apache/calcite/rel/core/Project.java | 9 ++
.../java/org/apache/calcite/rel/core/Sort.java | 15 ++++
.../calcite/rel/core/TableFunctionScan.java | 65 +++++++++++++--
.../calcite/rel/externalize/RelWriterImpl.java | 22 ++---
.../rel/logical/LogicalTableFunctionScan.java | 14 +++-
.../org/apache/calcite/rel/rules/MultiJoin.java | 25 ++++++
.../rel/rules/ReduceExpressionsRule.java | 10 ++-
.../java/org/apache/calcite/rex/RexShuttle.java | 5 +-
.../sql2rel/DeduplicateCorrelateVariables.java | 45 ++--------
.../apache/calcite/sql2rel/RelFieldTrimmer.java | 4 +-
19 files changed, 318 insertions(+), 142 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/288254b2/core/src/main/java/org/apache/calcite/adapter/enumerable/EnumerableTableFunctionScan.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/adapter/enumerable/EnumerableTableFunctionScan.java b/core/src/main/java/org/apache/calcite/adapter/enumerable/EnumerableTableFunctionScan.java
index 936e7fc..d8baf19 100644
--- a/core/src/main/java/org/apache/calcite/adapter/enumerable/EnumerableTableFunctionScan.java
+++ b/core/src/main/java/org/apache/calcite/adapter/enumerable/EnumerableTableFunctionScan.java
@@ -45,9 +45,15 @@ public class EnumerableTableFunctionScan extends TableFunctionScan
columnMappings);
}
- @Override public RelNode copy(RelTraitSet traitSet, List<RelNode> inputs) {
+ @Override public EnumerableTableFunctionScan copy(
+ RelTraitSet traitSet,
+ List<RelNode> inputs,
+ RexNode rexCall,
+ Type elementType,
+ RelDataType rowType,
+ Set<RelColumnMapping> columnMappings) {
return new EnumerableTableFunctionScan(getCluster(), traitSet, inputs,
- getElementType(), getRowType(), getCall(), getColumnMappings());
+ elementType, rowType, rexCall, columnMappings);
}
public Result implement(EnumerableRelImplementor implementor, Prefer pref) {
http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/288254b2/core/src/main/java/org/apache/calcite/plan/RelOptUtil.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/plan/RelOptUtil.java b/core/src/main/java/org/apache/calcite/plan/RelOptUtil.java
index 3c31ed2..9cc2401 100644
--- a/core/src/main/java/org/apache/calcite/plan/RelOptUtil.java
+++ b/core/src/main/java/org/apache/calcite/plan/RelOptUtil.java
@@ -19,7 +19,9 @@ package org.apache.calcite.plan;
import org.apache.calcite.linq4j.Ord;
import org.apache.calcite.rel.RelCollation;
import org.apache.calcite.rel.RelCollationImpl;
+import org.apache.calcite.rel.RelHomogeneousShuttle;
import org.apache.calcite.rel.RelNode;
+import org.apache.calcite.rel.RelShuttle;
import org.apache.calcite.rel.RelVisitor;
import org.apache.calcite.rel.RelWriter;
import org.apache.calcite.rel.core.AggregateCall;
@@ -152,22 +154,18 @@ public abstract class RelOptUtil {
*/
public static Set<String> getVariablesUsed(RelNode rel) {
final VariableUsedVisitor vuv = new VariableUsedVisitor();
- final VisitorRelVisitor visitor =
- new VisitorRelVisitor(vuv) {
- // implement RelVisitor
- public void visit(
- RelNode p,
- int ordinal,
- RelNode parent) {
- p.collectVariablesUsed(vuv.variables);
- super.visit(p, ordinal, parent);
-
- // Important! Remove stopped variables AFTER we visit
- // children. (which what super.visit() does)
- vuv.variables.removeAll(p.getVariablesStopped());
- }
- };
- visitor.go(rel);
+ RelShuttle visitor = new RelHomogeneousShuttle() {
+ @Override public RelNode visit(RelNode other) {
+ other.collectVariablesUsed(vuv.variables);
+ other.accept(vuv);
+ RelNode result = super.visit(other);
+ // Important! Remove stopped variables AFTER we visit
+ // children. (which what super.visit() does)
+ vuv.variables.removeAll(other.getVariablesStopped());
+ return result;
+ }
+ };
+ rel.accept(visitor);
return vuv.variables;
}
http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/288254b2/core/src/main/java/org/apache/calcite/plan/VisitorRelVisitor.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/plan/VisitorRelVisitor.java b/core/src/main/java/org/apache/calcite/plan/VisitorRelVisitor.java
deleted file mode 100644
index d4cd0f5..0000000
--- a/core/src/main/java/org/apache/calcite/plan/VisitorRelVisitor.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * 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.apache.calcite.plan;
-
-import org.apache.calcite.rel.RelNode;
-import org.apache.calcite.rel.RelVisitor;
-import org.apache.calcite.rex.RexNode;
-import org.apache.calcite.rex.RexVisitor;
-
-import java.util.List;
-
-/**
- * Walks over a tree of {@link RelNode relational expressions}, walking a
- * {@link RexVisitor} over every expression in that tree.
- */
-public class VisitorRelVisitor extends RelVisitor {
- //~ Instance fields --------------------------------------------------------
-
- protected final RexVisitor<?> visitor;
-
- //~ Constructors -----------------------------------------------------------
-
- public VisitorRelVisitor(RexVisitor<?> visitor) {
- this.visitor = visitor;
- }
-
- //~ Methods ----------------------------------------------------------------
-
- public void visit(
- RelNode p,
- int ordinal,
- RelNode parent) {
- List<RexNode> childExps = p.getChildExps();
- for (RexNode childExp : childExps) {
- childExp.accept(visitor);
- }
- p.childrenAccept(this);
- }
-}
-
-// End VisitorRelVisitor.java
http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/288254b2/core/src/main/java/org/apache/calcite/rel/AbstractRelNode.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rel/AbstractRelNode.java b/core/src/main/java/org/apache/calcite/rel/AbstractRelNode.java
index a1f78d4..7b24e46 100644
--- a/core/src/main/java/org/apache/calcite/rel/AbstractRelNode.java
+++ b/core/src/main/java/org/apache/calcite/rel/AbstractRelNode.java
@@ -31,6 +31,7 @@ import org.apache.calcite.rel.metadata.Metadata;
import org.apache.calcite.rel.metadata.RelMetadataQuery;
import org.apache.calcite.rel.type.RelDataType;
import org.apache.calcite.rex.RexNode;
+import org.apache.calcite.rex.RexShuttle;
import org.apache.calcite.sql.SqlExplainLevel;
import org.apache.calcite.util.ImmutableBitSet;
import org.apache.calcite.util.Pair;
@@ -253,6 +254,10 @@ public abstract class AbstractRelNode implements RelNode {
return shuttle.visit(this);
}
+ public RelNode accept(RexShuttle shuttle) {
+ return this;
+ }
+
public RelOptCost computeSelfCost(RelOptPlanner planner) {
// by default, assume cost is proportional to number of rows
double rowCount = RelMetadataQuery.getRowCount(this);
http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/288254b2/core/src/main/java/org/apache/calcite/rel/RelHomogeneousShuttle.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rel/RelHomogeneousShuttle.java b/core/src/main/java/org/apache/calcite/rel/RelHomogeneousShuttle.java
new file mode 100644
index 0000000..56fa883
--- /dev/null
+++ b/core/src/main/java/org/apache/calcite/rel/RelHomogeneousShuttle.java
@@ -0,0 +1,86 @@
+/*
+ * 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.apache.calcite.rel;
+
+import org.apache.calcite.rel.core.Sort;
+import org.apache.calcite.rel.core.TableFunctionScan;
+import org.apache.calcite.rel.core.TableScan;
+import org.apache.calcite.rel.logical.LogicalAggregate;
+import org.apache.calcite.rel.logical.LogicalCorrelate;
+import org.apache.calcite.rel.logical.LogicalFilter;
+import org.apache.calcite.rel.logical.LogicalIntersect;
+import org.apache.calcite.rel.logical.LogicalJoin;
+import org.apache.calcite.rel.logical.LogicalMinus;
+import org.apache.calcite.rel.logical.LogicalProject;
+import org.apache.calcite.rel.logical.LogicalUnion;
+import org.apache.calcite.rel.logical.LogicalValues;
+
+/**
+ * Visits all the relations in a homogeneous way: always redirects calls to
+ * {@code accept(RelNode)}.
+ */
+public class RelHomogeneousShuttle extends RelShuttleImpl {
+ @Override public RelNode visit(LogicalAggregate aggregate) {
+ return visit((RelNode) aggregate);
+ }
+
+ @Override public RelNode visit(TableScan scan) {
+ return visit((RelNode) scan);
+ }
+
+ @Override public RelNode visit(TableFunctionScan scan) {
+ return visit((RelNode) scan);
+ }
+
+ @Override public RelNode visit(LogicalValues values) {
+ return visit((RelNode) values);
+ }
+
+ @Override public RelNode visit(LogicalFilter filter) {
+ return visit((RelNode) filter);
+ }
+
+ @Override public RelNode visit(LogicalProject project) {
+ return visit((RelNode) project);
+ }
+
+ @Override public RelNode visit(LogicalJoin join) {
+ return visit((RelNode) join);
+ }
+
+ @Override public RelNode visit(LogicalCorrelate correlate) {
+ return visit((RelNode) correlate);
+ }
+
+ @Override public RelNode visit(LogicalUnion union) {
+ return visit((RelNode) union);
+ }
+
+ @Override public RelNode visit(LogicalIntersect intersect) {
+ return visit((RelNode) intersect);
+ }
+
+ @Override public RelNode visit(LogicalMinus minus) {
+ return visit((RelNode) minus);
+ }
+
+ @Override public RelNode visit(Sort sort) {
+ return visit((RelNode) sort);
+ }
+}
+
+// End RelHomogeneousShuttle.java
http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/288254b2/core/src/main/java/org/apache/calcite/rel/RelNode.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rel/RelNode.java b/core/src/main/java/org/apache/calcite/rel/RelNode.java
index 36e735e..c4a2aca 100644
--- a/core/src/main/java/org/apache/calcite/rel/RelNode.java
+++ b/core/src/main/java/org/apache/calcite/rel/RelNode.java
@@ -27,6 +27,7 @@ import org.apache.calcite.rel.metadata.Metadata;
import org.apache.calcite.rel.metadata.RelMetadataQuery;
import org.apache.calcite.rel.type.RelDataType;
import org.apache.calcite.rex.RexNode;
+import org.apache.calcite.rex.RexShuttle;
import org.apache.calcite.util.ImmutableBitSet;
import java.util.List;
@@ -85,8 +86,11 @@ public interface RelNode extends RelOptNode, Cloneable {
* implementations will return an immutable list. If there are no
* child expressions, returns an empty list, not <code>null</code>.
*
+ * @deprecated use #accept(org.apache.calcite.rex.RexShuttle)
* @return List of this relational expression's child expressions
+ * @see #accept(org.apache.calcite.rex.RexShuttle)
*/
+ @Deprecated
List<RexNode> getChildExps();
/**
@@ -369,6 +373,16 @@ public interface RelNode extends RelOptNode, Cloneable {
* this node's children
*/
RelNode accept(RelShuttle shuttle);
+
+ /**
+ * Accepts a visit from a shuttle. If the shuttle updates expression, then
+ * a copy of the relation should be created.
+ *
+ * @param shuttle Shuttle
+ * @return A copy of this node incorporating changes made by the shuttle to
+ * this node's children
+ */
+ RelNode accept(RexShuttle shuttle);
}
// End RelNode.java
http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/288254b2/core/src/main/java/org/apache/calcite/rel/core/Calc.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rel/core/Calc.java b/core/src/main/java/org/apache/calcite/rel/core/Calc.java
index 47240f0..b8b9b5c 100644
--- a/core/src/main/java/org/apache/calcite/rel/core/Calc.java
+++ b/core/src/main/java/org/apache/calcite/rel/core/Calc.java
@@ -28,7 +28,10 @@ import org.apache.calcite.rel.RelWriter;
import org.apache.calcite.rel.SingleRel;
import org.apache.calcite.rel.logical.LogicalFilter;
import org.apache.calcite.rel.metadata.RelMetadataQuery;
+import org.apache.calcite.rex.RexLocalRef;
+import org.apache.calcite.rex.RexNode;
import org.apache.calcite.rex.RexProgram;
+import org.apache.calcite.rex.RexShuttle;
import com.google.common.collect.ImmutableList;
@@ -144,6 +147,31 @@ public abstract class Calc extends SingleRel {
public RelWriter explainTerms(RelWriter pw) {
return program.explainCalc(super.explainTerms(pw));
}
+
+ public RelNode accept(RexShuttle shuttle) {
+ List<RexNode> oldExprs = program.getExprList();
+ List<RexNode> exprs = shuttle.apply(oldExprs);
+ List<RexLocalRef> oldProjects = program.getProjectList();
+ List<RexLocalRef> projects = shuttle.apply(oldProjects);
+ RexLocalRef oldCondition = program.getCondition();
+ RexNode condition = shuttle.apply(oldCondition);
+ assert condition instanceof RexLocalRef
+ : "Invalid condition after rewrite. Expected RexLocalRef, got "
+ + condition;
+ if (exprs == oldExprs
+ && projects == oldProjects
+ && condition == oldCondition) {
+ return this;
+ }
+ return copy(traitSet, getInput(),
+ new RexProgram(
+ program.getInputRowType(),
+ exprs,
+ projects,
+ (RexLocalRef) condition,
+ program.getOutputRowType()),
+ collationList);
+ }
}
// End Calc.java
http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/288254b2/core/src/main/java/org/apache/calcite/rel/core/Filter.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rel/core/Filter.java b/core/src/main/java/org/apache/calcite/rel/core/Filter.java
index 8fbdb0e..ca271db 100644
--- a/core/src/main/java/org/apache/calcite/rel/core/Filter.java
+++ b/core/src/main/java/org/apache/calcite/rel/core/Filter.java
@@ -29,6 +29,7 @@ import org.apache.calcite.rex.RexChecker;
import org.apache.calcite.rex.RexLocalRef;
import org.apache.calcite.rex.RexNode;
import org.apache.calcite.rex.RexProgram;
+import org.apache.calcite.rex.RexShuttle;
import org.apache.calcite.rex.RexUtil;
import com.google.common.collect.ImmutableList;
@@ -96,6 +97,14 @@ public abstract class Filter extends SingleRel {
return ImmutableList.of(condition);
}
+ public RelNode accept(RexShuttle shuttle) {
+ RexNode condition = shuttle.apply(this.condition);
+ if (this.condition == condition) {
+ return this;
+ }
+ return copy(traitSet, getInput(), condition);
+ }
+
public RexNode getCondition() {
return condition;
}
http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/288254b2/core/src/main/java/org/apache/calcite/rel/core/Join.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rel/core/Join.java b/core/src/main/java/org/apache/calcite/rel/core/Join.java
index 9405a6e..1a6b5c1 100644
--- a/core/src/main/java/org/apache/calcite/rel/core/Join.java
+++ b/core/src/main/java/org/apache/calcite/rel/core/Join.java
@@ -29,6 +29,7 @@ import org.apache.calcite.rel.type.RelDataTypeFactory;
import org.apache.calcite.rel.type.RelDataTypeField;
import org.apache.calcite.rex.RexChecker;
import org.apache.calcite.rex.RexNode;
+import org.apache.calcite.rex.RexShuttle;
import org.apache.calcite.sql.type.SqlTypeName;
import com.google.common.collect.ImmutableList;
@@ -97,6 +98,14 @@ public abstract class Join extends BiRel {
return ImmutableList.of(condition);
}
+ public RelNode accept(RexShuttle shuttle) {
+ RexNode condition = shuttle.apply(this.condition);
+ if (this.condition == condition) {
+ return this;
+ }
+ return copy(traitSet, condition, left, right, joinType, isSemiJoinDone());
+ }
+
public RexNode getCondition() {
return condition;
}
http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/288254b2/core/src/main/java/org/apache/calcite/rel/core/Project.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rel/core/Project.java b/core/src/main/java/org/apache/calcite/rel/core/Project.java
index 9032ca3..ec3978b 100644
--- a/core/src/main/java/org/apache/calcite/rel/core/Project.java
+++ b/core/src/main/java/org/apache/calcite/rel/core/Project.java
@@ -38,6 +38,7 @@ import org.apache.calcite.rex.RexFieldAccess;
import org.apache.calcite.rex.RexInputRef;
import org.apache.calcite.rex.RexLocalRef;
import org.apache.calcite.rex.RexNode;
+import org.apache.calcite.rex.RexShuttle;
import org.apache.calcite.rex.RexUtil;
import org.apache.calcite.rex.RexVisitorImpl;
import org.apache.calcite.sql.SqlExplainLevel;
@@ -151,6 +152,14 @@ public abstract class Project extends SingleRel {
return exps;
}
+ public RelNode accept(RexShuttle shuttle) {
+ List<RexNode> exps = shuttle.apply(this.exps);
+ if (this.exps == exps) {
+ return this;
+ }
+ return copy(traitSet, getInput(), exps, rowType);
+ }
+
/**
* Returns the project expressions.
*
http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/288254b2/core/src/main/java/org/apache/calcite/rel/core/Sort.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rel/core/Sort.java b/core/src/main/java/org/apache/calcite/rel/core/Sort.java
index 5c91666..445afb2 100644
--- a/core/src/main/java/org/apache/calcite/rel/core/Sort.java
+++ b/core/src/main/java/org/apache/calcite/rel/core/Sort.java
@@ -32,6 +32,7 @@ import org.apache.calcite.rel.RelWriter;
import org.apache.calcite.rel.SingleRel;
import org.apache.calcite.rel.metadata.RelMetadataQuery;
import org.apache.calcite.rex.RexNode;
+import org.apache.calcite.rex.RexShuttle;
import org.apache.calcite.util.Util;
import com.google.common.collect.ImmutableList;
@@ -162,6 +163,20 @@ public class Sort extends SingleRel {
return fieldExps;
}
+ public RelNode accept(RexShuttle shuttle) {
+ RexNode offset = shuttle.apply(this.offset);
+ RexNode fetch = shuttle.apply(this.fetch);
+ List<RexNode> fieldExps = shuttle.apply(this.fieldExps);
+ assert fieldExps == this.fieldExps
+ : "Sort node does not support modification of input field expressions."
+ + " Old expressions: " + this.fieldExps + ", new ones: " + fieldExps;
+ if (offset == this.offset
+ && fetch == this.fetch) {
+ return this;
+ }
+ return copy(traitSet, getInput(), collation, offset, fetch);
+ }
+
/**
* Returns the array of {@link RelFieldCollation}s asked for by the sort
* specification, from most significant to least significant.
http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/288254b2/core/src/main/java/org/apache/calcite/rel/core/TableFunctionScan.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rel/core/TableFunctionScan.java b/core/src/main/java/org/apache/calcite/rel/core/TableFunctionScan.java
index 282b1f3..bffa50f 100644
--- a/core/src/main/java/org/apache/calcite/rel/core/TableFunctionScan.java
+++ b/core/src/main/java/org/apache/calcite/rel/core/TableFunctionScan.java
@@ -27,6 +27,7 @@ import org.apache.calcite.rel.metadata.RelColumnMapping;
import org.apache.calcite.rel.metadata.RelMetadataQuery;
import org.apache.calcite.rel.type.RelDataType;
import org.apache.calcite.rex.RexNode;
+import org.apache.calcite.rex.RexShuttle;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
@@ -63,18 +64,19 @@ public abstract class TableFunctionScan extends AbstractRelNode {
*
* @param cluster Cluster that this relational expression belongs to
* @param inputs 0 or more relational inputs
- * @param rexCall function invocation expression
- * @param elementType element type of the collection that will implement
+ * @param rexCall Function invocation expression
+ * @param elementType Element type of the collection that will implement
* this table
- * @param rowType row type produced by function
- * @param columnMappings column mappings associated with this function
+ * @param rowType Row type produced by function
+ * @param columnMappings Column mappings associated with this function
*/
protected TableFunctionScan(
RelOptCluster cluster,
RelTraitSet traits,
List<RelNode> inputs,
RexNode rexCall,
- Type elementType, RelDataType rowType,
+ Type elementType,
+ RelDataType rowType,
Set<RelColumnMapping> columnMappings) {
super(cluster, traits);
this.rexCall = rexCall;
@@ -98,6 +100,34 @@ public abstract class TableFunctionScan extends AbstractRelNode {
//~ Methods ----------------------------------------------------------------
+ @Override public final TableFunctionScan copy(RelTraitSet traitSet,
+ List<RelNode> inputs) {
+ return copy(traitSet, inputs, rexCall, elementType, rowType,
+ columnMappings);
+ }
+
+ /**
+ * Copies this relational expression, substituting traits and
+ * inputs.
+ *
+ * @param traitSet Traits
+ * @param inputs 0 or more relational inputs
+ * @param rexCall Function invocation expression
+ * @param elementType Element type of the collection that will implement
+ * this table
+ * @param rowType Row type produced by function
+ * @param columnMappings Column mappings associated with this function
+ * @return Copy of this relational expression, substituting traits and
+ * inputs
+ */
+ public abstract TableFunctionScan copy(
+ RelTraitSet traitSet,
+ List<RelNode> inputs,
+ RexNode rexCall,
+ Type elementType,
+ RelDataType rowType,
+ Set<RelColumnMapping> columnMappings);
+
@Override public List<RelNode> getInputs() {
return inputs;
}
@@ -106,6 +136,15 @@ public abstract class TableFunctionScan extends AbstractRelNode {
return ImmutableList.of(rexCall);
}
+ public RelNode accept(RexShuttle shuttle) {
+ RexNode rexCall = shuttle.apply(this.rexCall);
+ if (rexCall == this.rexCall) {
+ return this;
+ }
+ return copy(traitSet, inputs, rexCall, elementType, rowType,
+ columnMappings);
+ }
+
@Override public void replaceInput(int ordinalInParent, RelNode p) {
final List<RelNode> newInputs = new ArrayList<RelNode>(inputs);
newInputs.set(ordinalInParent, p);
@@ -132,10 +171,16 @@ public abstract class TableFunctionScan extends AbstractRelNode {
return nRows;
}
+ /**
+ * Returns function invocation expression.
+ *
+ * <p>Within this rexCall, instances of
+ * {@link org.apache.calcite.rex.RexInputRef} refer to entire input
+ * {@link org.apache.calcite.rel.RelNode}s rather than their fields.
+ *
+ * @return function invocation expression
+ */
public RexNode getCall() {
- // NOTE jvs 7-May-2006: Within this rexCall, instances
- // of RexInputRef refer to entire input RelNodes rather
- // than their fields.
return rexCall;
}
@@ -153,6 +198,9 @@ public abstract class TableFunctionScan extends AbstractRelNode {
}
/**
+ * Returns set of mappings known for this table function, or null if unknown
+ * (not the same as empty!).
+ *
* @return set of mappings known for this table function, or null if unknown
* (not the same as empty!)
*/
@@ -162,6 +210,7 @@ public abstract class TableFunctionScan extends AbstractRelNode {
/**
* Returns element type of the collection that will implement this table.
+ *
* @return element type of the collection that will implement this table
*/
public Type getElementType() {
http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/288254b2/core/src/main/java/org/apache/calcite/rel/externalize/RelWriterImpl.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rel/externalize/RelWriterImpl.java b/core/src/main/java/org/apache/calcite/rel/externalize/RelWriterImpl.java
index e39e421..63fb3ab 100644
--- a/core/src/main/java/org/apache/calcite/rel/externalize/RelWriterImpl.java
+++ b/core/src/main/java/org/apache/calcite/rel/externalize/RelWriterImpl.java
@@ -21,7 +21,6 @@ import org.apache.calcite.linq4j.Ord;
import org.apache.calcite.rel.RelNode;
import org.apache.calcite.rel.RelWriter;
import org.apache.calcite.rel.metadata.RelMetadataQuery;
-import org.apache.calcite.rex.RexNode;
import org.apache.calcite.sql.SqlExplainLevel;
import org.apache.calcite.util.Pair;
@@ -154,6 +153,16 @@ public class RelWriterImpl implements RelWriter {
}
public RelWriter done(RelNode node) {
+ assert checkInputsPresentInExplain(node);
+ final List<Pair<String, Object>> valuesCopy =
+ ImmutableList.copyOf(values);
+ values.clear();
+ explain_(node, valuesCopy);
+ pw.flush();
+ return this;
+ }
+
+ private boolean checkInputsPresentInExplain(RelNode node) {
int i = 0;
if (values.size() > 0 && values.get(0).left.equals("subset")) {
++i;
@@ -162,16 +171,7 @@ public class RelWriterImpl implements RelWriter {
assert values.get(i).right == input;
++i;
}
- for (RexNode expr : node.getChildExps()) {
- assert values.get(i).right == expr;
- ++i;
- }
- final List<Pair<String, Object>> valuesCopy =
- ImmutableList.copyOf(values);
- values.clear();
- explain_(node, valuesCopy);
- pw.flush();
- return this;
+ return true;
}
public boolean nest() {
http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/288254b2/core/src/main/java/org/apache/calcite/rel/logical/LogicalTableFunctionScan.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rel/logical/LogicalTableFunctionScan.java b/core/src/main/java/org/apache/calcite/rel/logical/LogicalTableFunctionScan.java
index de0d1fa..e4e02f6 100644
--- a/core/src/main/java/org/apache/calcite/rel/logical/LogicalTableFunctionScan.java
+++ b/core/src/main/java/org/apache/calcite/rel/logical/LogicalTableFunctionScan.java
@@ -75,14 +75,20 @@ public class LogicalTableFunctionScan extends TableFunctionScan {
//~ Methods ----------------------------------------------------------------
- @Override public LogicalTableFunctionScan copy(RelTraitSet traitSet,
- List<RelNode> inputs) {
+ @Override public LogicalTableFunctionScan copy(
+ RelTraitSet traitSet,
+ List<RelNode> inputs,
+ RexNode rexCall,
+ Type elementType,
+ RelDataType rowType,
+ Set<RelColumnMapping> columnMappings) {
assert traitSet.containsIfApplicable(Convention.NONE);
return new LogicalTableFunctionScan(
getCluster(),
inputs,
- getCall(),
- getElementType(), getRowType(),
+ rexCall,
+ elementType,
+ rowType,
columnMappings);
}
http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/288254b2/core/src/main/java/org/apache/calcite/rel/rules/MultiJoin.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rel/rules/MultiJoin.java b/core/src/main/java/org/apache/calcite/rel/rules/MultiJoin.java
index ce651bc..153f31b 100644
--- a/core/src/main/java/org/apache/calcite/rel/rules/MultiJoin.java
+++ b/core/src/main/java/org/apache/calcite/rel/rules/MultiJoin.java
@@ -26,6 +26,7 @@ import org.apache.calcite.rel.RelWriter;
import org.apache.calcite.rel.core.JoinRelType;
import org.apache.calcite.rel.type.RelDataType;
import org.apache.calcite.rex.RexNode;
+import org.apache.calcite.rex.RexShuttle;
import org.apache.calcite.util.ImmutableBitSet;
import org.apache.calcite.util.ImmutableIntList;
import org.apache.calcite.util.ImmutableNullableList;
@@ -182,6 +183,30 @@ public final class MultiJoin extends AbstractRelNode {
return ImmutableList.of(joinFilter);
}
+ public RelNode accept(RexShuttle shuttle) {
+ RexNode joinFilter = shuttle.apply(this.joinFilter);
+ List<RexNode> outerJoinConditions = shuttle.apply(this.outerJoinConditions);
+ RexNode postJoinFilter = shuttle.apply(this.postJoinFilter);
+
+ if (joinFilter == this.joinFilter
+ && outerJoinConditions == this.outerJoinConditions
+ && postJoinFilter == this.postJoinFilter) {
+ return this;
+ }
+
+ return new MultiJoin(
+ getCluster(),
+ inputs,
+ joinFilter,
+ rowType,
+ isFullOuterJoin,
+ outerJoinConditions,
+ joinTypes,
+ projFields,
+ joinFieldRefCountsMap,
+ postJoinFilter);
+ }
+
/**
* @return join filters associated with this MultiJoin
*/
http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/288254b2/core/src/main/java/org/apache/calcite/rel/rules/ReduceExpressionsRule.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rel/rules/ReduceExpressionsRule.java b/core/src/main/java/org/apache/calcite/rel/rules/ReduceExpressionsRule.java
index c41a99d..f5a0ef7 100644
--- a/core/src/main/java/org/apache/calcite/rel/rules/ReduceExpressionsRule.java
+++ b/core/src/main/java/org/apache/calcite/rel/rules/ReduceExpressionsRule.java
@@ -88,7 +88,8 @@ public abstract class ReduceExpressionsRule extends RelOptRule {
"ReduceExpressionsRule(Filter)") {
public void onMatch(RelOptRuleCall call) {
LogicalFilter filter = call.rel(0);
- List<RexNode> expList = new ArrayList<RexNode>(filter.getChildExps());
+ List<RexNode> expList = new ArrayList<RexNode>(1);
+ expList.add(filter.getCondition());
RexNode newConditionExp;
boolean reduced;
if (reduceExpressions(filter, expList)) {
@@ -100,7 +101,7 @@ public abstract class ReduceExpressionsRule extends RelOptRule {
// predicate to see if it was already a constant,
// in which case we don't need any runtime decision
// about filtering.
- newConditionExp = filter.getChildExps().get(0);
+ newConditionExp = filter.getCondition();
reduced = false;
}
if (newConditionExp.isAlwaysTrue()) {
@@ -178,7 +179,7 @@ public abstract class ReduceExpressionsRule extends RelOptRule {
public void onMatch(RelOptRuleCall call) {
LogicalProject project = call.rel(0);
List<RexNode> expList =
- new ArrayList<RexNode>(project.getChildExps());
+ new ArrayList<RexNode>(project.getProjects());
if (reduceExpressions(project, expList)) {
call.transformTo(
new LogicalProject(
@@ -200,7 +201,8 @@ public abstract class ReduceExpressionsRule extends RelOptRule {
"ReduceExpressionsRule(Join)") {
public void onMatch(RelOptRuleCall call) {
final Join join = call.rel(0);
- List<RexNode> expList = new ArrayList<RexNode>(join.getChildExps());
+ List<RexNode> expList = new ArrayList<RexNode>(1);
+ expList.add(join.getCondition());
if (reduceExpressions(join, expList)) {
call.transformTo(
join.copy(
http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/288254b2/core/src/main/java/org/apache/calcite/rex/RexShuttle.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rex/RexShuttle.java b/core/src/main/java/org/apache/calcite/rex/RexShuttle.java
index bd3ce46..9c6e46d 100644
--- a/core/src/main/java/org/apache/calcite/rex/RexShuttle.java
+++ b/core/src/main/java/org/apache/calcite/rex/RexShuttle.java
@@ -218,7 +218,7 @@ public class RexShuttle implements RexVisitor<RexNode> {
int changeCount = 0;
for (int i = 0; i < exprList.size(); i++) {
T expr = exprList.get(i);
- T expr2 = (T) expr.accept(this);
+ T expr2 = (T) apply(expr); // Avoid NPE if expr is null
if (expr != expr2) {
++changeCount;
exprList.set(i, expr2);
@@ -232,6 +232,9 @@ public class RexShuttle implements RexVisitor<RexNode> {
* resulting list. Does not modify the initial list.
*/
public final <T extends RexNode> List<T> apply(List<T> exprList) {
+ if (exprList == null) {
+ return null;
+ }
final List<T> list2 = new ArrayList<T>(exprList);
if (mutate(list2)) {
return list2;
http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/288254b2/core/src/main/java/org/apache/calcite/sql2rel/DeduplicateCorrelateVariables.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/sql2rel/DeduplicateCorrelateVariables.java b/core/src/main/java/org/apache/calcite/sql2rel/DeduplicateCorrelateVariables.java
index 206ed2b..2ce1048 100644
--- a/core/src/main/java/org/apache/calcite/sql2rel/DeduplicateCorrelateVariables.java
+++ b/core/src/main/java/org/apache/calcite/sql2rel/DeduplicateCorrelateVariables.java
@@ -16,24 +16,20 @@
*/
package org.apache.calcite.sql2rel;
+import org.apache.calcite.rel.RelHomogeneousShuttle;
import org.apache.calcite.rel.RelNode;
-import org.apache.calcite.rel.RelShuttleImpl;
-import org.apache.calcite.rel.logical.LogicalFilter;
-import org.apache.calcite.rel.logical.LogicalJoin;
-import org.apache.calcite.rel.logical.LogicalProject;
import org.apache.calcite.rex.RexBuilder;
import org.apache.calcite.rex.RexCorrelVariable;
import org.apache.calcite.rex.RexNode;
import org.apache.calcite.rex.RexShuttle;
-import java.util.List;
import java.util.Set;
/**
* Rewrites relations to ensure the same correlation is referenced by the same
* correlation variable.
*/
-public class DeduplicateCorrelateVariables extends RelShuttleImpl {
+public class DeduplicateCorrelateVariables extends RelHomogeneousShuttle {
private final RexShuttle dedupRex;
/**
@@ -67,40 +63,9 @@ public class DeduplicateCorrelateVariables extends RelShuttleImpl {
canonical, altNames);
}
- @Override
- public RelNode visit(LogicalFilter filter) {
- LogicalFilter newFilter = (LogicalFilter) super.visit(filter);
- RexNode condition = filter.getCondition();
- RexNode newCondition = condition.accept(dedupRex);
- if (condition != newCondition) {
- return newFilter.copy(newFilter.getTraitSet(), newFilter.getInput(),
- newCondition);
- }
- return newFilter;
- }
-
- @Override
- public RelNode visit(LogicalProject project) {
- LogicalProject project2 = (LogicalProject) super.visit(project);
- List<RexNode> childExps = project2.getChildExps();
- List<RexNode> newExps = dedupRex.apply(childExps);
- if (childExps != newExps) {
- return project2.copy(project2.getTraitSet(), project2.getInput(),
- newExps, project2.getRowType());
- }
- return project2;
- }
-
- @Override
- public RelNode visit(LogicalJoin join) {
- LogicalJoin join2 = (LogicalJoin) super.visit(join);
- RexNode condition = join2.getCondition();
- RexNode newCondition = condition.accept(dedupRex);
- if (condition != newCondition) {
- return join2.copy(join2.getTraitSet(), newCondition, join2.getLeft(),
- join2.getRight(), join2.getJoinType(), join2.isSemiJoinDone());
- }
- return join2;
+ @Override public RelNode visit(RelNode other) {
+ RelNode next = super.visit(other);
+ return next.accept(dedupRex);
}
}
http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/288254b2/core/src/main/java/org/apache/calcite/sql2rel/RelFieldTrimmer.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/sql2rel/RelFieldTrimmer.java b/core/src/main/java/org/apache/calcite/sql2rel/RelFieldTrimmer.java
index dbbfa3f..4bfe35b 100644
--- a/core/src/main/java/org/apache/calcite/sql2rel/RelFieldTrimmer.java
+++ b/core/src/main/java/org/apache/calcite/sql2rel/RelFieldTrimmer.java
@@ -925,7 +925,9 @@ public class RelFieldTrimmer implements ReflectiveVisitor {
LogicalTableFunctionScan newTabFun = tabFun;
if (!tabFun.getInputs().equals(newInputs)) {
- newTabFun = tabFun.copy(tabFun.getTraitSet(), newInputs);
+ newTabFun = tabFun.copy(tabFun.getTraitSet(), newInputs,
+ tabFun.getCall(), tabFun.getElementType(), tabFun.getRowType(),
+ tabFun.getColumnMappings());
}
assert newTabFun.getClass() == tabFun.getClass();
[2/3] incubator-calcite git commit: [CALCITE-533] Support for
grouping sets in FilterAggregateTransposeRule (Jesus Camacho Rodriguez)
Posted by jh...@apache.org.
[CALCITE-533] Support for grouping sets in FilterAggregateTransposeRule (Jesus Camacho Rodriguez)
Close apache/incubator-calcite#34
Project: http://git-wip-us.apache.org/repos/asf/incubator-calcite/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-calcite/commit/86c7c081
Tree: http://git-wip-us.apache.org/repos/asf/incubator-calcite/tree/86c7c081
Diff: http://git-wip-us.apache.org/repos/asf/incubator-calcite/diff/86c7c081
Branch: refs/heads/master
Commit: 86c7c081107524aa67a3edbf26b554f4d1c99456
Parents: e8ee2b3
Author: Jesus Camacho Rodriguez <jc...@hortonworks.com>
Authored: Tue Dec 16 16:53:54 2014 +0100
Committer: Julian Hyde <jh...@apache.org>
Committed: Wed Dec 17 13:37:42 2014 -0800
----------------------------------------------------------------------
.../rel/rules/FilterAggregateTransposeRule.java | 14 ++++-
.../apache/calcite/test/RelOptRulesTest.java | 21 ++++++++
.../org/apache/calcite/test/RelOptRulesTest.xml | 56 ++++++++++++++++++++
3 files changed, 90 insertions(+), 1 deletion(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/86c7c081/core/src/main/java/org/apache/calcite/rel/rules/FilterAggregateTransposeRule.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rel/rules/FilterAggregateTransposeRule.java b/core/src/main/java/org/apache/calcite/rel/rules/FilterAggregateTransposeRule.java
index 8af01e3..0d10081 100644
--- a/core/src/main/java/org/apache/calcite/rel/rules/FilterAggregateTransposeRule.java
+++ b/core/src/main/java/org/apache/calcite/rel/rules/FilterAggregateTransposeRule.java
@@ -89,7 +89,19 @@ public class FilterAggregateTransposeRule extends RelOptRule {
for (RexNode condition : conditions) {
ImmutableBitSet rCols = RelOptUtil.InputFinder.bits(condition);
- if (groupKeys.contains(rCols)) {
+ boolean push = groupKeys.contains(rCols);
+ if (push && aggRel.indicator) {
+ // If grouping sets are used, the filter can be pushed if
+ // the columns referenced in the predicate are present in
+ // all the grouping sets.
+ for (ImmutableBitSet groupingSet: aggRel.getGroupSets()) {
+ if (!groupingSet.contains(rCols)) {
+ push = false;
+ break;
+ }
+ }
+ }
+ if (push) {
pushedConditions.add(
condition.accept(
new RelOptUtil.RexInputConverter(rexBuilder, origFields,
http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/86c7c081/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java
----------------------------------------------------------------------
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 bfa65c9..cf78de9 100644
--- a/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java
+++ b/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java
@@ -207,6 +207,27 @@ public class RelOptRulesTest extends RelOptTestBase {
+ " where dname = 'Charlie'");
}
+ private void basePushFilterPastAggWithGroupingSets() throws Exception {
+ final HepProgram preProgram =
+ HepProgram.builder()
+ .addRuleInstance(ProjectMergeRule.INSTANCE)
+ .addRuleInstance(FilterProjectTransposeRule.INSTANCE)
+ .build();
+ final HepProgram program =
+ HepProgram.builder()
+ .addRuleInstance(FilterAggregateTransposeRule.INSTANCE)
+ .build();
+ checkPlanning(tester, preProgram, new HepPlanner(program), "${sql}");
+ }
+
+ @Test public void testPushFilterPastAggWithGroupingSets1() throws Exception {
+ basePushFilterPastAggWithGroupingSets();
+ }
+
+ @Test public void testPushFilterPastAggWithGroupingSets2() throws Exception {
+ basePushFilterPastAggWithGroupingSets();
+ }
+
/** Test case for
* <a href="https://issues.apache.org/jira/browse/CALCITE-434">[CALCITE-434],
* FilterAggregateTransposeRule loses conditions that cannot be pushed</a>. */
http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/86c7c081/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml
----------------------------------------------------------------------
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 9ffdaf4..4ddefe1 100644
--- a/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml
+++ b/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml
@@ -283,6 +283,62 @@ LogicalProject(DNAME=[$0], C=[$1])
]]>
</Resource>
</TestCase>
+ <TestCase name="testPushFilterPastAggWithGroupingSets1">
+ <Resource name="sql">
+ <![CDATA[select ddeptno, dname, c from
+ (select deptno ddeptno, name dname, count(*) as c
+ from dept group by rollup(deptno,name)) t
+ where dname = 'Charlie']]>
+ </Resource>
+ <Resource name="planBefore">
+ <![CDATA[
+LogicalProject(DDEPTNO=[$0], DNAME=[$1], C=[$2])
+ LogicalProject(DDEPTNO=[CASE($2, null, $0)], DNAME=[CASE($3, null, $1)], C=[$4])
+ LogicalFilter(condition=[=(CASE($3, null, $1), 'Charlie')])
+ LogicalAggregate(group=[{0, 1}], groups=[[{0, 1}, {0}, {}]], indicator=[true], C=[COUNT()])
+ LogicalProject(DDEPTNO=[$0], DNAME=[$1])
+ LogicalTableScan(table=[[CATALOG, SALES, DEPT]])
+]]>
+ </Resource>
+ <Resource name="planAfter">
+ <![CDATA[
+LogicalProject(DDEPTNO=[$0], DNAME=[$1], C=[$2])
+ LogicalProject(DDEPTNO=[CASE($2, null, $0)], DNAME=[CASE($3, null, $1)], C=[$4])
+ LogicalFilter(condition=[=(CASE($3, null, $1), 'Charlie')])
+ LogicalAggregate(group=[{0, 1}], groups=[[{0, 1}, {0}, {}]], indicator=[true], C=[COUNT()])
+ LogicalProject(DDEPTNO=[$0], DNAME=[$1])
+ LogicalTableScan(table=[[CATALOG, SALES, DEPT]])
+]]>
+ </Resource>
+ </TestCase>
+ <TestCase name="testPushFilterPastAggWithGroupingSets2">
+ <Resource name="sql">
+ <![CDATA[select dname, ddeptno, c from
+ (select name dname, deptno ddeptno, count(*) as c
+ from dept group by grouping sets ((name,deptno),(name))) t
+ where dname = 'Charlie']]>
+ </Resource>
+ <Resource name="planBefore">
+ <![CDATA[
+LogicalProject(DNAME=[$0], DDEPTNO=[$1], C=[$2])
+ LogicalProject(DNAME=[$0], DDEPTNO=[CASE($3, null, $1)], C=[$4])
+ LogicalFilter(condition=[=($0, 'Charlie')])
+ LogicalAggregate(group=[{0, 1}], groups=[[{0, 1}, {0}]], indicator=[true], C=[COUNT()])
+ LogicalProject(DNAME=[$1], DDEPTNO=[$0])
+ LogicalTableScan(table=[[CATALOG, SALES, DEPT]])
+]]>
+ </Resource>
+ <Resource name="planAfter">
+ <![CDATA[
+LogicalProject(DNAME=[$0], DDEPTNO=[$1], C=[$2])
+ LogicalProject(DNAME=[$0], DDEPTNO=[CASE($3, null, $1)], C=[$4])
+ LogicalAggregate(group=[{0, 1}], groups=[[{0, 1}, {0}]], indicator=[true], C=[COUNT()])
+ LogicalFilter(condition=[=($0, 'Charlie')])
+ LogicalProject(DNAME=[$1], DDEPTNO=[$0])
+ LogicalTableScan(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]]>