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 2015/07/21 21:53:12 UTC
[2/2] incubator-calcite git commit: [CALCITE-808] Optimize
ProjectMergeRule
[CALCITE-808] Optimize ProjectMergeRule
Project: http://git-wip-us.apache.org/repos/asf/incubator-calcite/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-calcite/commit/b550ff88
Tree: http://git-wip-us.apache.org/repos/asf/incubator-calcite/tree/b550ff88
Diff: http://git-wip-us.apache.org/repos/asf/incubator-calcite/diff/b550ff88
Branch: refs/heads/master
Commit: b550ff887b41c51348f14c0dc10481fe18aadf0f
Parents: c9fe32b
Author: Julian Hyde <jh...@apache.org>
Authored: Tue Jul 21 11:12:46 2015 -0700
Committer: Julian Hyde <jh...@apache.org>
Committed: Tue Jul 21 12:29:15 2015 -0700
----------------------------------------------------------------------
.../org/apache/calcite/plan/RelOptUtil.java | 34 ++++++---
.../calcite/rel/rules/ProjectMergeRule.java | 73 +++++---------------
.../org/apache/calcite/test/RelOptRulesTest.xml | 28 ++++----
3 files changed, 57 insertions(+), 78 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/b550ff88/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 6892dfd..d2686a0 100644
--- a/core/src/main/java/org/apache/calcite/plan/RelOptUtil.java
+++ b/core/src/main/java/org/apache/calcite/plan/RelOptUtil.java
@@ -2379,14 +2379,32 @@ public abstract class RelOptUtil {
* @param project Project underneath the expression
* @return converted expression
*/
- public static RexNode pushPastProject(RexNode node,
- final Project project) {
- return node.accept(
- new RexShuttle() {
- @Override public RexNode visitInputRef(RexInputRef ref) {
- return project.getProjects().get(ref.getIndex());
- }
- });
+ public static RexNode pushPastProject(RexNode node, Project project) {
+ return node.accept(pushShuttle(project));
+ }
+
+ /**
+ * Converts a list of expressions that are based on the output fields of a
+ * {@link Project} to equivalent expressions on the Project's
+ * input fields.
+ *
+ * @param nodes The expressions to be converted
+ * @param project Project underneath the expression
+ * @return converted expressions
+ */
+ public static List<RexNode> pushPastProject(List<? extends RexNode> nodes,
+ Project project) {
+ final List<RexNode> list = new ArrayList<>();
+ pushShuttle(project).visitList(nodes, list);
+ return list;
+ }
+
+ private static RexShuttle pushShuttle(final Project project) {
+ return new RexShuttle() {
+ @Override public RexNode visitInputRef(RexInputRef ref) {
+ return project.getProjects().get(ref.getIndex());
+ }
+ };
}
/**
http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/b550ff88/core/src/main/java/org/apache/calcite/rel/rules/ProjectMergeRule.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rel/rules/ProjectMergeRule.java b/core/src/main/java/org/apache/calcite/rel/rules/ProjectMergeRule.java
index cef654e..89ed15f 100644
--- a/core/src/main/java/org/apache/calcite/rel/rules/ProjectMergeRule.java
+++ b/core/src/main/java/org/apache/calcite/rel/rules/ProjectMergeRule.java
@@ -23,14 +23,9 @@ import org.apache.calcite.rel.RelNode;
import org.apache.calcite.rel.core.Project;
import org.apache.calcite.rel.core.RelFactories;
import org.apache.calcite.rel.core.RelFactories.ProjectFactory;
-import org.apache.calcite.rex.RexBuilder;
-import org.apache.calcite.rex.RexLocalRef;
import org.apache.calcite.rex.RexNode;
-import org.apache.calcite.rex.RexProgram;
-import org.apache.calcite.rex.RexProgramBuilder;
import org.apache.calcite.util.Permutation;
-import java.util.ArrayList;
import java.util.List;
/**
@@ -39,7 +34,8 @@ import java.util.List;
* provided the projects aren't projecting identical sets of input references.
*/
public class ProjectMergeRule extends RelOptRule {
- public static final ProjectMergeRule INSTANCE = new ProjectMergeRule();
+ public static final ProjectMergeRule INSTANCE =
+ new ProjectMergeRule(true, RelFactories.DEFAULT_PROJECT_FACTORY);
//~ Instance fields --------------------------------------------------------
@@ -51,13 +47,6 @@ public class ProjectMergeRule extends RelOptRule {
//~ Constructors -----------------------------------------------------------
/**
- * Creates a ProjectMergeRule.
- */
- private ProjectMergeRule() {
- this(false, RelFactories.DEFAULT_PROJECT_FACTORY);
- }
-
- /**
* Creates a ProjectMergeRule, specifying whether to always merge projects.
*
* @param force Whether to always merge projects
@@ -66,7 +55,7 @@ public class ProjectMergeRule extends RelOptRule {
super(
operand(Project.class,
operand(Project.class, any())),
- "ProjectMergeRule" + (force ? ":force_mode" : ""));
+ "ProjectMergeRule" + (force ? ":force_mode" : ""));
this.force = force;
this.projectFactory = projectFactory;
}
@@ -74,9 +63,8 @@ public class ProjectMergeRule extends RelOptRule {
//~ Methods ----------------------------------------------------------------
public void onMatch(RelOptRuleCall call) {
- Project topProject = call.rel(0);
- Project bottomProject = call.rel(1);
- RexBuilder rexBuilder = topProject.getCluster().getRexBuilder();
+ final Project topProject = call.rel(0);
+ final Project bottomProject = call.rel(1);
// If one or both projects are permutations, short-circuit the complex logic
// of building a RexProgram.
@@ -101,48 +89,25 @@ public class ProjectMergeRule extends RelOptRule {
}
}
- // if we're not in force mode and the two projects reference identical
- // inputs, then return and either let FennelRenameRule or
- // ProjectRemoveRule replace the projects
+ // If we're not in force mode and the two projects reference identical
+ // inputs, then return and let ProjectRemoveRule replace the projects.
if (!force) {
- if (RelOptUtil.checkProjAndChildInputs(topProject, false)) {
+ if (ProjectRemoveRule.isIdentity(topProject.getProjects(),
+ topProject.getInput().getRowType())) {
return;
}
}
- // create a RexProgram for the bottom project
- RexProgram bottomProgram =
- RexProgram.create(
- bottomProject.getInput().getRowType(),
- bottomProject.getProjects(),
- null,
- bottomProject.getRowType(),
- rexBuilder);
-
- // create a RexProgram for the topmost project
- final List<RexNode> projects = topProject.getProjects();
- RexProgram topProgram =
- RexProgram.create(
- bottomProject.getRowType(),
- projects,
- null,
- topProject.getRowType(),
- rexBuilder);
-
- // combine the two RexPrograms
- RexProgram mergedProgram =
- RexProgramBuilder.mergePrograms(
- topProgram,
- bottomProgram,
- rexBuilder);
-
- // re-expand the topmost projection expressions, now that they
- // reference the children of the bottom-most project
- final int projectCount = projects.size();
- final List<RexNode> newProjects = new ArrayList<>();
- List<RexLocalRef> projectRefs = mergedProgram.getProjectList();
- for (int i = 0; i < projectCount; i++) {
- newProjects.add(mergedProgram.expandLocalRef(projectRefs.get(i)));
+ final List<RexNode> newProjects =
+ RelOptUtil.pushPastProject(topProject.getProjects(), bottomProject);
+ final RelNode input = bottomProject.getInput();
+ if (ProjectRemoveRule.isIdentity(newProjects, input.getRowType())) {
+ if (force
+ || input.getRowType().getFieldNames()
+ .equals(topProject.getRowType().getFieldNames())) {
+ call.transformTo(input);
+ return;
+ }
}
// replace the two projects with a combined projection
http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/b550ff88/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 eb9ed66..d01a8d1 100644
--- a/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml
+++ b/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml
@@ -1636,10 +1636,9 @@ LogicalProject(DEPTNO=[$0], EXPR$1=[$2])
</Resource>
<Resource name="planAfter">
<![CDATA[
-LogicalProject(DEPTNO=[$0], EXPR$1=[$1])
- LogicalAggregate(group=[{0}], EXPR$1=[MAX($2)])
- LogicalProject(DEPTNO=[$7], FOUR=[4], MGR=[$3])
- LogicalTableScan(table=[[CATALOG, SALES, EMP]])
+LogicalAggregate(group=[{0}], EXPR$1=[MAX($2)])
+ LogicalProject(DEPTNO=[$7], FOUR=[4], MGR=[$3])
+ LogicalTableScan(table=[[CATALOG, SALES, EMP]])
]]>
</Resource>
</TestCase>
@@ -1660,10 +1659,9 @@ LogicalProject(DEPTNO=[$0], EXPR$1=[$2])
</Resource>
<Resource name="planAfter">
<![CDATA[
-LogicalProject(DEPTNO=[$0], EXPR$1=[$1])
- LogicalAggregate(group=[{0}], EXPR$1=[MAX($2)])
- LogicalProject(DEPTNO=[$7], FOUR=[4], ENAME=[$1])
- LogicalTableScan(table=[[CATALOG, SALES, EMP]])
+LogicalAggregate(group=[{0}], EXPR$1=[MAX($2)])
+ LogicalProject(DEPTNO=[$7], FOUR=[4], ENAME=[$1])
+ LogicalTableScan(table=[[CATALOG, SALES, EMP]])
]]>
</Resource>
</TestCase>
@@ -1708,10 +1706,9 @@ LogicalProject(DEPTNO=[$1], EXPR$1=[$2])
</Resource>
<Resource name="planAfter">
<![CDATA[
-LogicalProject(DEPTNO=[$0], EXPR$1=[$1])
- LogicalAggregate(group=[{0}], EXPR$1=[MAX($2)])
- LogicalProject(DEPTNO=[$7], FOUR=[4], MGR=[$3])
- LogicalTableScan(table=[[CATALOG, SALES, EMP]])
+LogicalAggregate(group=[{0}], EXPR$1=[MAX($2)])
+ LogicalProject(DEPTNO=[$7], FOUR=[4], MGR=[$3])
+ LogicalTableScan(table=[[CATALOG, SALES, EMP]])
]]>
</Resource>
</TestCase>
@@ -1732,10 +1729,9 @@ LogicalProject(DEPTNO=[$1], EXPR$1=[$2])
</Resource>
<Resource name="planAfter">
<![CDATA[
-LogicalProject(DEPTNO=[$0], EXPR$1=[$1])
- LogicalAggregate(group=[{0}], EXPR$1=[MAX($2)])
- LogicalProject(DEPTNO=[$7], $f0=[+(42, 24)], MGR=[$3])
- LogicalTableScan(table=[[CATALOG, SALES, EMP]])
+LogicalAggregate(group=[{0}], EXPR$1=[MAX($2)])
+ LogicalProject(DEPTNO=[$7], $f0=[+(42, 24)], MGR=[$3])
+ LogicalTableScan(table=[[CATALOG, SALES, EMP]])
]]>
</Resource>
</TestCase>