calcite-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From jh...@apache.org
Subject [3/3] incubator-calcite git commit: [CALCITE-479] Migrate RelNode.getChildExps to RelNode.accept(RexShuttle)
Date Thu, 18 Dec 2014 07:28:12 GMT
[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 <sitnikov.vladimir@gmail.com>
Authored: Sun Dec 14 15:41:57 2014 +0300
Committer: Julian Hyde <jhyde@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();
 


Mime
View raw message