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/01/29 05:42:55 UTC
[7/7] incubator-calcite git commit: [CALCITE-575] Variant of
ProjectRemoveRule that considers a project trivial only if its field names
are identical (John Pullokkaran)
[CALCITE-575] Variant of ProjectRemoveRule that considers a project trivial only if its field names are identical (John Pullokkaran)
Project: http://git-wip-us.apache.org/repos/asf/incubator-calcite/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-calcite/commit/341bdd8e
Tree: http://git-wip-us.apache.org/repos/asf/incubator-calcite/tree/341bdd8e
Diff: http://git-wip-us.apache.org/repos/asf/incubator-calcite/diff/341bdd8e
Branch: refs/heads/master
Commit: 341bdd8e2e1a48165652bab1d6341ef4d09e2523
Parents: f036de8
Author: John Pullokkaran <jp...@hortonworks.com>
Authored: Wed Jan 28 12:45:58 2015 -0800
Committer: Julian Hyde <jh...@apache.org>
Committed: Wed Jan 28 14:46:43 2015 -0800
----------------------------------------------------------------------
.../calcite/rel/rules/ProjectRemoveRule.java | 68 ++++++++++++++++++--
.../java/org/apache/calcite/rex/RexUtil.java | 31 +++++++++
.../apache/calcite/sql2rel/RelFieldTrimmer.java | 46 ++++++++++++-
3 files changed, 136 insertions(+), 9 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/341bdd8e/core/src/main/java/org/apache/calcite/rel/rules/ProjectRemoveRule.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rel/rules/ProjectRemoveRule.java b/core/src/main/java/org/apache/calcite/rel/rules/ProjectRemoveRule.java
index 5e39853..2bc5d59 100644
--- a/core/src/main/java/org/apache/calcite/rel/rules/ProjectRemoveRule.java
+++ b/core/src/main/java/org/apache/calcite/rel/rules/ProjectRemoveRule.java
@@ -41,29 +41,52 @@ import java.util.List;
*/
public class ProjectRemoveRule extends RelOptRule {
//~ Static fields/initializers ---------------------------------------------
+ private final boolean useNamesInIdentityProjCalc;
private static final Predicate<Project> PREDICATE =
new Predicate<Project>() {
public boolean apply(Project input) {
- return isTrivial(input);
+ return isTrivial(input, false);
}
};
- public static final ProjectRemoveRule INSTANCE = new ProjectRemoveRule();
+ private static final Predicate<Project> NAME_CALC_PREDICATE =
+ new Predicate<Project>() {
+ public boolean apply(Project input) {
+ return isTrivial(input, true);
+ }
+ };
+
+ public static final ProjectRemoveRule INSTANCE = new ProjectRemoveRule(false);
+
+ /** @deprecated Remove before
+ * {@link org.apache.calcite.util.Bug#upgrade Calcite-1.1}. */
+ public static final ProjectRemoveRule NAME_CALC_INSTANCE =
+ new ProjectRemoveRule(true);
//~ Constructors -----------------------------------------------------------
- private ProjectRemoveRule() {
+ /**
+ * Creates a ProjectRemoveRule.
+ *
+ * @param useNamesInIdentityProjCalc If true consider names while determining
+ * if two projects are same
+ */
+ private ProjectRemoveRule(boolean useNamesInIdentityProjCalc) {
// Create a specialized operand to detect non-matches early. This keeps
// the rule queue short.
- super(operand(Project.class, null, PREDICATE, any()));
+ super(
+ operand(Project.class, null,
+ useNamesInIdentityProjCalc ? NAME_CALC_PREDICATE : PREDICATE,
+ any()));
+ this.useNamesInIdentityProjCalc = useNamesInIdentityProjCalc;
}
//~ Methods ----------------------------------------------------------------
public void onMatch(RelOptRuleCall call) {
Project project = call.rel(0);
- assert isTrivial(project);
+ assert isTrivial(project, useNamesInIdentityProjCalc);
RelNode stripped = project.getInput();
if (stripped instanceof Project) {
// Rename columns of child projection if desired field names are given.
@@ -84,10 +107,35 @@ public class ProjectRemoveRule extends RelOptRule {
return isTrivial(project) ? project.getInput() : project;
}
+ /**
+ * Returns the child of a project if the project is trivial
+ * otherwise the project itself. If useNamesInIdentityProjCalc is true
+ * then trivial comparison uses both names and types.
+ *
+ * @deprecated Remove before
+ * {@link org.apache.calcite.util.Bug#upgrade Calcite-1.1}. */
+ public static RelNode strip(Project project,
+ boolean useNamesInIdentityProjCalc) {
+ return isTrivial(project, useNamesInIdentityProjCalc)
+ ? project.getInput() : project;
+ }
+
public static boolean isTrivial(Project project) {
+ return isTrivial(project, false);
+ }
+
+ /** @deprecated Remove before
+ * {@link org.apache.calcite.util.Bug#upgrade Calcite-1.1}. */
+ public static boolean isTrivial(Project project,
+ boolean useNamesInIdentityProjCalc) {
RelNode child = project.getInput();
final RelDataType childRowType = child.getRowType();
- return isIdentity(project.getProjects(), childRowType);
+ if (useNamesInIdentityProjCalc) {
+ return isIdentity(project.getProjects(), project.getRowType(),
+ childRowType);
+ } else {
+ return isIdentity(project.getProjects(), childRowType);
+ }
}
public static boolean isIdentity(List<? extends RexNode> exps,
@@ -95,6 +143,14 @@ public class ProjectRemoveRule extends RelOptRule {
return childRowType.getFieldCount() == exps.size()
&& RexUtil.containIdentity(exps, childRowType, false);
}
+
+ /** @deprecated Remove before
+ * {@link org.apache.calcite.util.Bug#upgrade Calcite-1.1}. */
+ public static boolean isIdentity(List<? extends RexNode> exps,
+ RelDataType rowType, RelDataType childRowType) {
+ return childRowType.getFieldCount() == exps.size()
+ && RexUtil.containIdentity(exps, rowType, childRowType);
+ }
}
// End ProjectRemoveRule.java
http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/341bdd8e/core/src/main/java/org/apache/calcite/rex/RexUtil.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rex/RexUtil.java b/core/src/main/java/org/apache/calcite/rex/RexUtil.java
index e70205c..f7712e1 100644
--- a/core/src/main/java/org/apache/calcite/rex/RexUtil.java
+++ b/core/src/main/java/org/apache/calcite/rex/RexUtil.java
@@ -614,6 +614,37 @@ public class RexUtil {
}
/**
+ * Returns whether the leading edge of a given array of expressions is
+ * wholly {@link RexInputRef} objects with types and names corresponding
+ * to the underlying row type.
+ *
+ * @deprecated Remove before
+ * {@link org.apache.calcite.util.Bug#upgrade Calcite-1.1}. */
+ public static boolean containIdentity(List<? extends RexNode> exps,
+ RelDataType rowType, RelDataType childRowType) {
+ List<RelDataTypeField> fields = rowType.getFieldList();
+ List<RelDataTypeField> childFields = childRowType.getFieldList();
+ int fieldCount = childFields.size();
+ if (exps.size() != fieldCount) {
+ return false;
+ }
+ for (int i = 0; i < exps.size(); i++) {
+ RexNode exp = exps.get(i);
+ if (!(exp instanceof RexInputRef)) {
+ return false;
+ }
+ RexInputRef var = (RexInputRef) exp;
+ if (var.getIndex() != i) {
+ return false;
+ }
+ if (!fields.get(i).getName().equals(childFields.get(i).getName())) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
* Converts a collection of expressions into an AND.
* If there are zero expressions, returns TRUE.
* If there is one expression, returns just that expression.
http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/341bdd8e/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 a41606e..e108c78 100644
--- a/core/src/main/java/org/apache/calcite/sql2rel/RelFieldTrimmer.java
+++ b/core/src/main/java/org/apache/calcite/sql2rel/RelFieldTrimmer.java
@@ -106,6 +106,7 @@ public class RelFieldTrimmer implements ReflectiveVisitor {
private final RelFactories.SortFactory sortFactory;
private final RelFactories.AggregateFactory aggregateFactory;
private final RelFactories.SetOpFactory setOpFactory;
+ private final boolean useNamesInIdentityProjCalc;
//~ Constructors -----------------------------------------------------------
@@ -138,6 +139,36 @@ public class RelFieldTrimmer implements ReflectiveVisitor {
RelFactories.SortFactory sortFactory,
RelFactories.AggregateFactory aggregateFactory,
RelFactories.SetOpFactory setOpFactory) {
+ this(validator, projectFactory, filterFactory, joinFactory,
+ semiJoinFactory, sortFactory, aggregateFactory, setOpFactory,
+ false);
+ }
+
+ /**
+ * Creates a RelFieldTrimmer.
+ *
+ * @param validator Validator
+ * @param projectFactory Project factory
+ * @param filterFactory Filter factory
+ * @param joinFactory Join factory
+ * @param semiJoinFactory SemiJoin factory
+ * @param sortFactory Sort factory
+ * @param aggregateFactory Aggregate factory
+ * @param setOpFactory SetOp factory
+ * @param useNamesInIdentityProjCalc
+ * Include field names in identity project determination
+ *
+ * @deprecated Remove before
+ * {@link org.apache.calcite.util.Bug#upgrade Calcite-1.1}. */
+ public RelFieldTrimmer(SqlValidator validator,
+ RelFactories.ProjectFactory projectFactory,
+ RelFactories.FilterFactory filterFactory,
+ RelFactories.JoinFactory joinFactory,
+ RelFactories.SemiJoinFactory semiJoinFactory,
+ RelFactories.SortFactory sortFactory,
+ RelFactories.AggregateFactory aggregateFactory,
+ RelFactories.SetOpFactory setOpFactory,
+ boolean useNamesInIdentityProjCalc) {
Util.discard(validator); // may be useful one day
this.trimFieldsDispatcher =
ReflectUtil.createMethodDispatcher(
@@ -154,6 +185,7 @@ public class RelFieldTrimmer implements ReflectiveVisitor {
this.sortFactory = Preconditions.checkNotNull(sortFactory);
this.aggregateFactory = Preconditions.checkNotNull(aggregateFactory);
this.setOpFactory = Preconditions.checkNotNull(setOpFactory);
+ this.useNamesInIdentityProjCalc = useNamesInIdentityProjCalc;
}
//~ Methods ----------------------------------------------------------------
@@ -378,9 +410,8 @@ public class RelFieldTrimmer implements ReflectiveVisitor {
mapping);
final RelNode newProject;
- if (ProjectRemoveRule.isIdentity(
- newProjectExprList,
- newInput.getRowType())) {
+ if (isIdentityProject(newProjectExprList, newRowType,
+ newInput.getRowType())) {
// The new project would be the identity. It is equivalent to return
// its child.
newProject = newInput;
@@ -392,6 +423,15 @@ public class RelFieldTrimmer implements ReflectiveVisitor {
return new TrimResult(newProject, mapping);
}
+ private boolean isIdentityProject(List<? extends RexNode> exps,
+ RelDataType rowType, RelDataType childRowType) {
+ if (this.useNamesInIdentityProjCalc) {
+ return ProjectRemoveRule.isIdentity(exps, rowType, childRowType);
+ } else {
+ return ProjectRemoveRule.isIdentity(exps, childRowType);
+ }
+ }
+
/** Creates a project with a dummy column, to protect the parts of the system
* that cannot handle a relational expression with no columns.
*