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 2016/01/11 05:47:16 UTC
[15/27] calcite git commit: [CALCITE-794] Detect cycles when
computing statistics
http://git-wip-us.apache.org/repos/asf/calcite/blob/cabdcf44/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 f4067eb..5fe5fcb 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
@@ -25,7 +25,7 @@ import org.apache.calcite.rel.RelCollation;
import org.apache.calcite.rel.RelNode;
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.RelMdUtil;
import org.apache.calcite.rel.metadata.RelMetadataQuery;
import org.apache.calcite.rex.RexLocalRef;
import org.apache.calcite.rex.RexNode;
@@ -131,17 +131,15 @@ public abstract class Calc extends SingleRel {
return program;
}
- public double getRows() {
- return LogicalFilter.estimateFilteredRows(
- getInput(),
- program);
+ @Override public double estimateRowCount(RelMetadataQuery mq) {
+ return RelMdUtil.estimateFilteredRows(getInput(), program, mq);
}
- public RelOptCost computeSelfCost(RelOptPlanner planner) {
- double dRows = RelMetadataQuery.getRowCount(this);
- double dCpu =
- RelMetadataQuery.getRowCount(getInput())
- * program.getExprCount();
+ @Override public RelOptCost computeSelfCost(RelOptPlanner planner,
+ RelMetadataQuery mq) {
+ double dRows = mq.getRowCount(this);
+ double dCpu = mq.getRowCount(getInput())
+ * program.getExprCount();
double dIo = 0;
return planner.getCostFactory().makeCost(dRows, dCpu, dIo);
}
http://git-wip-us.apache.org/repos/asf/calcite/blob/cabdcf44/core/src/main/java/org/apache/calcite/rel/core/Correlate.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rel/core/Correlate.java b/core/src/main/java/org/apache/calcite/rel/core/Correlate.java
index 982a762..f985099 100644
--- a/core/src/main/java/org/apache/calcite/rel/core/Correlate.java
+++ b/core/src/main/java/org/apache/calcite/rel/core/Correlate.java
@@ -185,19 +185,20 @@ public abstract class Correlate extends BiRel {
return ImmutableSet.of(correlationId);
}
- @Override public RelOptCost computeSelfCost(RelOptPlanner planner) {
- double rowCount = RelMetadataQuery.getRowCount(this);
+ @Override public RelOptCost computeSelfCost(RelOptPlanner planner,
+ RelMetadataQuery mq) {
+ double rowCount = mq.getRowCount(this);
- final double rightRowCount = right.getRows();
- final double leftRowCount = left.getRows();
+ final double rightRowCount = right.estimateRowCount(mq);
+ final double leftRowCount = left.estimateRowCount(mq);
if (Double.isInfinite(leftRowCount) || Double.isInfinite(rightRowCount)) {
return planner.getCostFactory().makeInfiniteCost();
}
- Double restartCount = RelMetadataQuery.getRowCount(getLeft());
+ Double restartCount = mq.getRowCount(getLeft());
// RelMetadataQuery.getCumulativeCost(getRight()); does not work for
// RelSubset, so we ask planner to cost-estimate right relation
- RelOptCost rightCost = planner.getCost(getRight());
+ RelOptCost rightCost = planner.getCost(getRight(), mq);
RelOptCost rescanCost =
rightCost.multiplyBy(Math.max(1.0, restartCount - 1));
http://git-wip-us.apache.org/repos/asf/calcite/blob/cabdcf44/core/src/main/java/org/apache/calcite/rel/core/Exchange.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rel/core/Exchange.java b/core/src/main/java/org/apache/calcite/rel/core/Exchange.java
index a9acc86..060fa1c 100644
--- a/core/src/main/java/org/apache/calcite/rel/core/Exchange.java
+++ b/core/src/main/java/org/apache/calcite/rel/core/Exchange.java
@@ -89,10 +89,11 @@ public abstract class Exchange extends SingleRel {
return distribution;
}
- @Override public RelOptCost computeSelfCost(RelOptPlanner planner) {
+ @Override public RelOptCost computeSelfCost(RelOptPlanner planner,
+ RelMetadataQuery mq) {
// Higher cost if rows are wider discourages pushing a project through an
// exchange.
- double rowCount = RelMetadataQuery.getRowCount(this);
+ double rowCount = mq.getRowCount(this);
double bytesPerRow = getRowType().getFieldCount() * 4;
return planner.getCostFactory().makeCost(
Util.nLogN(rowCount) * bytesPerRow, rowCount, 0);
http://git-wip-us.apache.org/repos/asf/calcite/blob/cabdcf44/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 e5461e8..5387804 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
@@ -25,9 +25,9 @@ import org.apache.calcite.rel.RelInput;
import org.apache.calcite.rel.RelNode;
import org.apache.calcite.rel.RelWriter;
import org.apache.calcite.rel.SingleRel;
+import org.apache.calcite.rel.metadata.RelMdUtil;
import org.apache.calcite.rel.metadata.RelMetadataQuery;
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;
@@ -123,37 +123,28 @@ public abstract class Filter extends SingleRel {
return litmus.succeed();
}
- public RelOptCost computeSelfCost(RelOptPlanner planner) {
- double dRows = RelMetadataQuery.getRowCount(this);
- double dCpu = RelMetadataQuery.getRowCount(getInput());
+ @Override public RelOptCost computeSelfCost(RelOptPlanner planner,
+ RelMetadataQuery mq) {
+ double dRows = mq.getRowCount(this);
+ double dCpu = mq.getRowCount(getInput());
double dIo = 0;
return planner.getCostFactory().makeCost(dRows, dCpu, dIo);
}
- // override RelNode
- public double getRows() {
- return estimateFilteredRows(
- getInput(),
- condition);
+ @Override public double estimateRowCount(RelMetadataQuery mq) {
+ return RelMdUtil.estimateFilteredRows(getInput(), condition, mq);
}
+ @Deprecated // to be removed before 2.0
public static double estimateFilteredRows(RelNode child, RexProgram program) {
- // convert the program's RexLocalRef condition to an expanded RexNode
- RexLocalRef programCondition = program.getCondition();
- RexNode condition;
- if (programCondition == null) {
- condition = null;
- } else {
- condition = program.expandLocalRef(programCondition);
- }
- return estimateFilteredRows(
- child,
- condition);
+ final RelMetadataQuery mq = RelMetadataQuery.instance();
+ return RelMdUtil.estimateFilteredRows(child, program, mq);
}
+ @Deprecated // to be removed before 2.0
public static double estimateFilteredRows(RelNode child, RexNode condition) {
- return RelMetadataQuery.getRowCount(child)
- * RelMetadataQuery.getSelectivity(child, condition);
+ final RelMetadataQuery mq = RelMetadataQuery.instance();
+ return RelMdUtil.estimateFilteredRows(child, condition, mq);
}
public RelWriter explainTerms(RelWriter pw) {
http://git-wip-us.apache.org/repos/asf/calcite/blob/cabdcf44/core/src/main/java/org/apache/calcite/rel/core/Intersect.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rel/core/Intersect.java b/core/src/main/java/org/apache/calcite/rel/core/Intersect.java
index 6aecbf8..7495a8f 100644
--- a/core/src/main/java/org/apache/calcite/rel/core/Intersect.java
+++ b/core/src/main/java/org/apache/calcite/rel/core/Intersect.java
@@ -51,12 +51,11 @@ public abstract class Intersect extends SetOp {
super(input);
}
- @Override public double getRows() {
+ @Override public double estimateRowCount(RelMetadataQuery mq) {
// REVIEW jvs 30-May-2005: I just pulled this out of a hat.
double dRows = Double.MAX_VALUE;
for (RelNode input : inputs) {
- dRows = Math.min(
- dRows, RelMetadataQuery.getRowCount(input));
+ dRows = Math.min(dRows, mq.getRowCount(input));
}
dRows *= 0.25;
return dRows;
http://git-wip-us.apache.org/repos/asf/calcite/blob/cabdcf44/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 3ac32d2..7c20f14 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
@@ -179,22 +179,24 @@ public abstract class Join extends BiRel {
return litmus.succeed();
}
- @Override public RelOptCost computeSelfCost(RelOptPlanner planner) {
+ @Override public RelOptCost computeSelfCost(RelOptPlanner planner,
+ RelMetadataQuery mq) {
// REVIEW jvs 9-Apr-2006: Just for now...
- double rowCount = RelMetadataQuery.getRowCount(this);
+ double rowCount = mq.getRowCount(this);
return planner.getCostFactory().makeCost(rowCount, 0, 0);
}
- /** @deprecated Use {@link RelMdUtil#getJoinRowCount(Join, RexNode)}. */
+ /** @deprecated Use {@link RelMdUtil#getJoinRowCount(RelMetadataQuery, Join, RexNode)}. */
@Deprecated // to be removed before 2.0
public static double estimateJoinedRows(
Join joinRel,
RexNode condition) {
- return Util.first(RelMdUtil.getJoinRowCount(joinRel, condition), 1D);
+ final RelMetadataQuery mq = RelMetadataQuery.instance();
+ return Util.first(RelMdUtil.getJoinRowCount(mq, joinRel, condition), 1D);
}
- @Override public double getRows() {
- return Util.first(RelMdUtil.getJoinRowCount(this, condition), 1D);
+ @Override public double estimateRowCount(RelMetadataQuery mq) {
+ return Util.first(RelMdUtil.getJoinRowCount(mq, this, condition), 1D);
}
@Override public Set<CorrelationId> getVariablesSet() {
http://git-wip-us.apache.org/repos/asf/calcite/blob/cabdcf44/core/src/main/java/org/apache/calcite/rel/core/Minus.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rel/core/Minus.java b/core/src/main/java/org/apache/calcite/rel/core/Minus.java
index 18c6f60..9950d78 100644
--- a/core/src/main/java/org/apache/calcite/rel/core/Minus.java
+++ b/core/src/main/java/org/apache/calcite/rel/core/Minus.java
@@ -21,6 +21,7 @@ import org.apache.calcite.plan.RelTraitSet;
import org.apache.calcite.rel.RelInput;
import org.apache.calcite.rel.RelNode;
import org.apache.calcite.rel.metadata.RelMdUtil;
+import org.apache.calcite.rel.metadata.RelMetadataQuery;
import org.apache.calcite.sql.SqlKind;
import java.util.List;
@@ -48,8 +49,8 @@ public abstract class Minus extends SetOp {
super(input);
}
- @Override public double getRows() {
- return RelMdUtil.getMinusRowCount(this);
+ @Override public double estimateRowCount(RelMetadataQuery mq) {
+ return RelMdUtil.getMinusRowCount(mq, this);
}
}
http://git-wip-us.apache.org/repos/asf/calcite/blob/cabdcf44/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 86f4147..e92b04d 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
@@ -210,8 +210,9 @@ public abstract class Project extends SingleRel {
return litmus.succeed();
}
- public RelOptCost computeSelfCost(RelOptPlanner planner) {
- double dRows = RelMetadataQuery.getRowCount(getInput());
+ @Override public RelOptCost computeSelfCost(RelOptPlanner planner,
+ RelMetadataQuery mq) {
+ double dRows = mq.getRowCount(getInput());
double dCpu = dRows * exps.size();
double dIo = 0;
return planner.getCostFactory().makeCost(dRows, dCpu, dIo);
http://git-wip-us.apache.org/repos/asf/calcite/blob/cabdcf44/core/src/main/java/org/apache/calcite/rel/core/SemiJoin.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rel/core/SemiJoin.java b/core/src/main/java/org/apache/calcite/rel/core/SemiJoin.java
index 6db45f1..571e8f6 100644
--- a/core/src/main/java/org/apache/calcite/rel/core/SemiJoin.java
+++ b/core/src/main/java/org/apache/calcite/rel/core/SemiJoin.java
@@ -23,6 +23,7 @@ import org.apache.calcite.plan.RelOptPlanner;
import org.apache.calcite.plan.RelTraitSet;
import org.apache.calcite.rel.RelNode;
import org.apache.calcite.rel.metadata.RelMdUtil;
+import org.apache.calcite.rel.metadata.RelMetadataQuery;
import org.apache.calcite.rel.type.RelDataType;
import org.apache.calcite.rel.type.RelDataTypeField;
import org.apache.calcite.rex.RexNode;
@@ -94,15 +95,16 @@ public class SemiJoin extends EquiJoin {
joinInfo.leftKeys, joinInfo.rightKeys);
}
- @Override public RelOptCost computeSelfCost(RelOptPlanner planner) {
+ @Override public RelOptCost computeSelfCost(RelOptPlanner planner,
+ RelMetadataQuery mq) {
// REVIEW jvs 9-Apr-2006: Just for now...
return planner.getCostFactory().makeTinyCost();
}
- @Override public double getRows() {
- return Util.first(RelMdUtil.getSemiJoinRowCount(left, right, joinType, condition),
+ @Override public double estimateRowCount(RelMetadataQuery mq) {
+ return Util.first(
+ RelMdUtil.getSemiJoinRowCount(mq, left, right, joinType, condition),
1D);
-
}
/**
http://git-wip-us.apache.org/repos/asf/calcite/blob/cabdcf44/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 022479b..ec42fbf 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
@@ -129,10 +129,11 @@ public abstract class Sort extends SingleRel {
public abstract Sort copy(RelTraitSet traitSet, RelNode newInput,
RelCollation newCollation, RexNode offset, RexNode fetch);
- @Override public RelOptCost computeSelfCost(RelOptPlanner planner) {
+ @Override public RelOptCost computeSelfCost(RelOptPlanner planner,
+ RelMetadataQuery mq) {
// Higher cost if rows are wider discourages pushing a project through a
// sort.
- double rowCount = RelMetadataQuery.getRowCount(this);
+ double rowCount = mq.getRowCount(this);
double bytesPerRow = getRowType().getFieldCount() * 4;
return planner.getCostFactory().makeCost(
Util.nLogN(rowCount) * bytesPerRow, rowCount, 0);
http://git-wip-us.apache.org/repos/asf/calcite/blob/cabdcf44/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 bffa50f..7482c39 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
@@ -146,24 +146,24 @@ public abstract class TableFunctionScan extends AbstractRelNode {
}
@Override public void replaceInput(int ordinalInParent, RelNode p) {
- final List<RelNode> newInputs = new ArrayList<RelNode>(inputs);
+ final List<RelNode> newInputs = new ArrayList<>(inputs);
newInputs.set(ordinalInParent, p);
inputs = ImmutableList.copyOf(newInputs);
recomputeDigest();
}
- @Override public double getRows() {
- // Calculate result as the sum of the input rowcount estimates,
+ @Override public double estimateRowCount(RelMetadataQuery mq) {
+ // Calculate result as the sum of the input row count estimates,
// assuming there are any, otherwise use the superclass default. So
// for a no-input UDX, behave like an AbstractRelNode; for a one-input
// UDX, behave like a SingleRel; for a multi-input UDX, behave like
// UNION ALL. TODO jvs 10-Sep-2007: UDX-supplied costing metadata.
if (inputs.size() == 0) {
- return super.getRows();
+ return super.estimateRowCount(mq);
}
double nRows = 0.0;
for (RelNode input : inputs) {
- Double d = RelMetadataQuery.getRowCount(input);
+ Double d = mq.getRowCount(input);
if (d != null) {
nRows += d;
}
http://git-wip-us.apache.org/repos/asf/calcite/blob/cabdcf44/core/src/main/java/org/apache/calcite/rel/core/TableModify.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rel/core/TableModify.java b/core/src/main/java/org/apache/calcite/rel/core/TableModify.java
index fea3a5e..79b6a0d 100644
--- a/core/src/main/java/org/apache/calcite/rel/core/TableModify.java
+++ b/core/src/main/java/org/apache/calcite/rel/core/TableModify.java
@@ -54,7 +54,7 @@ public abstract class TableModify extends SingleRel {
* Enumeration of supported modification operations.
*/
public enum Operation {
- INSERT, UPDATE, DELETE, MERGE;
+ INSERT, UPDATE, DELETE, MERGE
}
//~ Instance fields --------------------------------------------------------
@@ -190,10 +190,10 @@ public abstract class TableModify extends SingleRel {
.item("flattened", flattened);
}
- // implement RelNode
- public RelOptCost computeSelfCost(RelOptPlanner planner) {
+ @Override public RelOptCost computeSelfCost(RelOptPlanner planner,
+ RelMetadataQuery mq) {
// REVIEW jvs 21-Apr-2006: Just for now...
- double rowCount = RelMetadataQuery.getRowCount(this);
+ double rowCount = mq.getRowCount(this);
return planner.getCostFactory().makeCost(rowCount, 0, 0);
}
}
http://git-wip-us.apache.org/repos/asf/calcite/blob/cabdcf44/core/src/main/java/org/apache/calcite/rel/core/TableScan.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rel/core/TableScan.java b/core/src/main/java/org/apache/calcite/rel/core/TableScan.java
index 2b958ef..27f842d 100644
--- a/core/src/main/java/org/apache/calcite/rel/core/TableScan.java
+++ b/core/src/main/java/org/apache/calcite/rel/core/TableScan.java
@@ -27,6 +27,7 @@ import org.apache.calcite.rel.RelInput;
import org.apache.calcite.rel.RelNode;
import org.apache.calcite.rel.RelShuttle;
import org.apache.calcite.rel.RelWriter;
+import org.apache.calcite.rel.metadata.RelMetadataQuery;
import org.apache.calcite.rel.type.RelDataType;
import org.apache.calcite.rel.type.RelDataTypeField;
import org.apache.calcite.rex.RexBuilder;
@@ -70,7 +71,7 @@ public abstract class TableScan extends AbstractRelNode {
//~ Methods ----------------------------------------------------------------
- @Override public double getRows() {
+ @Override public double estimateRowCount(RelMetadataQuery mq) {
return table.getRowCount();
}
@@ -82,7 +83,8 @@ public abstract class TableScan extends AbstractRelNode {
return table.getCollationList();
}
- @Override public RelOptCost computeSelfCost(RelOptPlanner planner) {
+ @Override public RelOptCost computeSelfCost(RelOptPlanner planner,
+ RelMetadataQuery mq) {
double dRows = table.getRowCount();
double dCpu = dRows + 1; // ensure non-zero cost
double dIo = 0;
http://git-wip-us.apache.org/repos/asf/calcite/blob/cabdcf44/core/src/main/java/org/apache/calcite/rel/core/Union.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rel/core/Union.java b/core/src/main/java/org/apache/calcite/rel/core/Union.java
index 1907199..f7c6a42 100644
--- a/core/src/main/java/org/apache/calcite/rel/core/Union.java
+++ b/core/src/main/java/org/apache/calcite/rel/core/Union.java
@@ -20,6 +20,7 @@ import org.apache.calcite.plan.RelOptCluster;
import org.apache.calcite.plan.RelTraitSet;
import org.apache.calcite.rel.RelInput;
import org.apache.calcite.rel.RelNode;
+import org.apache.calcite.rel.metadata.RelMdUtil;
import org.apache.calcite.rel.metadata.RelMetadataQuery;
import org.apache.calcite.sql.SqlKind;
@@ -51,27 +52,19 @@ public abstract class Union extends SetOp {
//~ Methods ----------------------------------------------------------------
- // implement RelNode
- public double getRows() {
- double dRows = estimateRowCount(this);
+ @Override public double estimateRowCount(RelMetadataQuery mq) {
+ double dRows = RelMdUtil.getUnionAllRowCount(RelMetadataQuery.instance(),
+ this);
if (!all) {
dRows *= 0.5;
}
return dRows;
}
- /**
- * Helper method for computing row count for UNION ALL.
- *
- * @param rel node representing UNION ALL
- * @return estimated row count for rel
- */
+ @Deprecated // to be removed before 2.0
public static double estimateRowCount(RelNode rel) {
- double dRows = 0;
- for (RelNode input : rel.getInputs()) {
- dRows += RelMetadataQuery.getRowCount(input);
- }
- return dRows;
+ final RelMetadataQuery mq = RelMetadataQuery.instance();
+ return RelMdUtil.getUnionAllRowCount(mq, (Union) rel);
}
}
http://git-wip-us.apache.org/repos/asf/calcite/blob/cabdcf44/core/src/main/java/org/apache/calcite/rel/core/Values.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rel/core/Values.java b/core/src/main/java/org/apache/calcite/rel/core/Values.java
index 2f4b6ba..bf99fae 100644
--- a/core/src/main/java/org/apache/calcite/rel/core/Values.java
+++ b/core/src/main/java/org/apache/calcite/rel/core/Values.java
@@ -73,7 +73,7 @@ public abstract class Values extends AbstractRelNode {
//~ Instance fields --------------------------------------------------------
- protected final ImmutableList<ImmutableList<RexLiteral>> tuples;
+ public final ImmutableList<ImmutableList<RexLiteral>> tuples;
//~ Constructors -----------------------------------------------------------
@@ -143,14 +143,13 @@ public abstract class Values extends AbstractRelNode {
return true;
}
- // implement RelNode
- protected RelDataType deriveRowType() {
+ @Override protected RelDataType deriveRowType() {
return rowType;
}
- // implement RelNode
- public RelOptCost computeSelfCost(RelOptPlanner planner) {
- double dRows = RelMetadataQuery.getRowCount(this);
+ @Override public RelOptCost computeSelfCost(RelOptPlanner planner,
+ RelMetadataQuery mq) {
+ double dRows = mq.getRowCount(this);
// Assume CPU is negligible since values are precomputed.
double dCpu = 1;
@@ -159,7 +158,7 @@ public abstract class Values extends AbstractRelNode {
}
// implement RelNode
- public double getRows() {
+ public double estimateRowCount(RelMetadataQuery mq) {
return tuples.size();
}
http://git-wip-us.apache.org/repos/asf/calcite/blob/cabdcf44/core/src/main/java/org/apache/calcite/rel/core/Window.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rel/core/Window.java b/core/src/main/java/org/apache/calcite/rel/core/Window.java
index 7efb115..09d9ee7 100644
--- a/core/src/main/java/org/apache/calcite/rel/core/Window.java
+++ b/core/src/main/java/org/apache/calcite/rel/core/Window.java
@@ -170,14 +170,15 @@ public abstract class Window extends SingleRel {
return constants;
}
- public RelOptCost computeSelfCost(RelOptPlanner planner) {
+ @Override public RelOptCost computeSelfCost(RelOptPlanner planner,
+ RelMetadataQuery mq) {
// Cost is proportional to the number of rows and the number of
// components (groups and aggregate functions). There is
// no I/O cost.
//
// TODO #1. Add memory cost.
// TODO #2. MIN and MAX have higher CPU cost than SUM and COUNT.
- final double rowsIn = RelMetadataQuery.getRowCount(getInput());
+ final double rowsIn = mq.getRowCount(getInput());
int count = groups.size();
for (Group group : groups) {
count += group.aggCalls.size();
http://git-wip-us.apache.org/repos/asf/calcite/blob/cabdcf44/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 63fb3ab..9386f81 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
@@ -40,8 +40,8 @@ public class RelWriterImpl implements RelWriter {
private final SqlExplainLevel detailLevel;
private final boolean withIdPrefix;
protected final Spacer spacer = new Spacer();
- private final List<Pair<String, Object>> values =
- new ArrayList<Pair<String, Object>>();
+ private final List<Pair<String, Object>> values = new ArrayList<>();
+ protected final RelMetadataQuery mq = RelMetadataQuery.instance();
//~ Constructors -----------------------------------------------------------
@@ -59,14 +59,11 @@ public class RelWriterImpl implements RelWriter {
//~ Methods ----------------------------------------------------------------
- protected void explain_(
- RelNode rel,
+ protected void explain_(RelNode rel,
List<Pair<String, Object>> values) {
List<RelNode> inputs = rel.getInputs();
- if (!RelMetadataQuery.isVisibleInExplain(
- rel,
- detailLevel)) {
+ if (!mq.isVisibleInExplain(rel, detailLevel)) {
// render children in place of this, at same level
explainInputs(inputs);
return;
@@ -101,9 +98,9 @@ public class RelWriterImpl implements RelWriter {
switch (detailLevel) {
case ALL_ATTRIBUTES:
s.append(": rowcount = ")
- .append(RelMetadataQuery.getRowCount(rel))
+ .append(mq.getRowCount(rel))
.append(", cumulative cost = ")
- .append(RelMetadataQuery.getCumulativeCost(rel));
+ .append(mq.getCumulativeCost(rel));
}
switch (detailLevel) {
case NON_COST_ATTRIBUTES:
http://git-wip-us.apache.org/repos/asf/calcite/blob/cabdcf44/core/src/main/java/org/apache/calcite/rel/logical/LogicalCalc.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rel/logical/LogicalCalc.java b/core/src/main/java/org/apache/calcite/rel/logical/LogicalCalc.java
index 3ca1645..3341ebf 100644
--- a/core/src/main/java/org/apache/calcite/rel/logical/LogicalCalc.java
+++ b/core/src/main/java/org/apache/calcite/rel/logical/LogicalCalc.java
@@ -29,6 +29,7 @@ import org.apache.calcite.rel.core.Calc;
import org.apache.calcite.rel.core.CorrelationId;
import org.apache.calcite.rel.metadata.RelMdCollation;
import org.apache.calcite.rel.metadata.RelMdDistribution;
+import org.apache.calcite.rel.metadata.RelMetadataQuery;
import org.apache.calcite.rel.rules.FilterToCalcRule;
import org.apache.calcite.rel.rules.ProjectToCalcRule;
import org.apache.calcite.rex.RexNode;
@@ -90,18 +91,19 @@ public final class LogicalCalc extends Calc {
public static LogicalCalc create(final RelNode input,
final RexProgram program) {
final RelOptCluster cluster = input.getCluster();
+ final RelMetadataQuery mq = RelMetadataQuery.instance();
final RelTraitSet traitSet = cluster.traitSet()
.replace(Convention.NONE)
.replaceIfs(RelCollationTraitDef.INSTANCE,
new Supplier<List<RelCollation>>() {
public List<RelCollation> get() {
- return RelMdCollation.calc(input, program);
+ return RelMdCollation.calc(mq, input, program);
}
})
.replaceIf(RelDistributionTraitDef.INSTANCE,
new Supplier<RelDistribution>() {
public RelDistribution get() {
- return RelMdDistribution.calc(input, program);
+ return RelMdDistribution.calc(mq, input, program);
}
});
return new LogicalCalc(cluster, traitSet, input, program);
http://git-wip-us.apache.org/repos/asf/calcite/blob/cabdcf44/core/src/main/java/org/apache/calcite/rel/logical/LogicalFilter.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rel/logical/LogicalFilter.java b/core/src/main/java/org/apache/calcite/rel/logical/LogicalFilter.java
index d25874e..1c25fba 100644
--- a/core/src/main/java/org/apache/calcite/rel/logical/LogicalFilter.java
+++ b/core/src/main/java/org/apache/calcite/rel/logical/LogicalFilter.java
@@ -31,6 +31,7 @@ import org.apache.calcite.rel.core.CorrelationId;
import org.apache.calcite.rel.core.Filter;
import org.apache.calcite.rel.metadata.RelMdCollation;
import org.apache.calcite.rel.metadata.RelMdDistribution;
+import org.apache.calcite.rel.metadata.RelMetadataQuery;
import org.apache.calcite.rex.RexNode;
import com.google.common.base.Preconditions;
@@ -106,17 +107,18 @@ public final class LogicalFilter extends Filter {
public static LogicalFilter create(final RelNode input, RexNode condition,
ImmutableSet<CorrelationId> variablesSet) {
final RelOptCluster cluster = input.getCluster();
+ final RelMetadataQuery mq = RelMetadataQuery.instance();
final RelTraitSet traitSet = cluster.traitSetOf(Convention.NONE)
.replaceIfs(RelCollationTraitDef.INSTANCE,
new Supplier<List<RelCollation>>() {
public List<RelCollation> get() {
- return RelMdCollation.filter(input);
+ return RelMdCollation.filter(mq, input);
}
})
.replaceIf(RelDistributionTraitDef.INSTANCE,
new Supplier<RelDistribution>() {
public RelDistribution get() {
- return RelMdDistribution.filter(input);
+ return RelMdDistribution.filter(mq, input);
}
});
return new LogicalFilter(cluster, traitSet, input, condition, variablesSet);
http://git-wip-us.apache.org/repos/asf/calcite/blob/cabdcf44/core/src/main/java/org/apache/calcite/rel/logical/LogicalProject.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rel/logical/LogicalProject.java b/core/src/main/java/org/apache/calcite/rel/logical/LogicalProject.java
index cce5e79..61f2fd7 100644
--- a/core/src/main/java/org/apache/calcite/rel/logical/LogicalProject.java
+++ b/core/src/main/java/org/apache/calcite/rel/logical/LogicalProject.java
@@ -27,6 +27,7 @@ import org.apache.calcite.rel.RelNode;
import org.apache.calcite.rel.RelShuttle;
import org.apache.calcite.rel.core.Project;
import org.apache.calcite.rel.metadata.RelMdCollation;
+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.RexUtil;
@@ -111,13 +112,14 @@ public final class LogicalProject extends Project {
public static LogicalProject create(final RelNode input,
final List<? extends RexNode> projects, RelDataType rowType) {
final RelOptCluster cluster = input.getCluster();
+ final RelMetadataQuery mq = RelMetadataQuery.instance();
final RelTraitSet traitSet =
cluster.traitSet().replace(Convention.NONE)
.replaceIfs(
RelCollationTraitDef.INSTANCE,
new Supplier<List<RelCollation>>() {
public List<RelCollation> get() {
- return RelMdCollation.project(input, projects);
+ return RelMdCollation.project(mq, input, projects);
}
});
return new LogicalProject(cluster, traitSet, input, projects, rowType);
http://git-wip-us.apache.org/repos/asf/calcite/blob/cabdcf44/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 79102db..ec18685 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
@@ -25,6 +25,7 @@ import org.apache.calcite.rel.RelInput;
import org.apache.calcite.rel.RelNode;
import org.apache.calcite.rel.core.TableFunctionScan;
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;
@@ -111,7 +112,7 @@ public class LogicalTableFunctionScan extends TableFunctionScan {
columnMappings);
}
- public RelOptCost computeSelfCost(RelOptPlanner planner) {
+ public RelOptCost computeSelfCost(RelOptPlanner planner, RelMetadataQuery mq) {
// REVIEW jvs 8-Jan-2006: what is supposed to be here
// for an abstract rel?
return planner.getCostFactory().makeHugeCost();
http://git-wip-us.apache.org/repos/asf/calcite/blob/cabdcf44/core/src/main/java/org/apache/calcite/rel/logical/LogicalValues.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rel/logical/LogicalValues.java b/core/src/main/java/org/apache/calcite/rel/logical/LogicalValues.java
index 889f7e6..6d84d74 100644
--- a/core/src/main/java/org/apache/calcite/rel/logical/LogicalValues.java
+++ b/core/src/main/java/org/apache/calcite/rel/logical/LogicalValues.java
@@ -26,6 +26,7 @@ import org.apache.calcite.rel.RelNode;
import org.apache.calcite.rel.RelShuttle;
import org.apache.calcite.rel.core.Values;
import org.apache.calcite.rel.metadata.RelMdCollation;
+import org.apache.calcite.rel.metadata.RelMetadataQuery;
import org.apache.calcite.rel.type.RelDataType;
import org.apache.calcite.rex.RexLiteral;
import org.apache.calcite.sql.type.SqlTypeName;
@@ -81,11 +82,12 @@ public class LogicalValues extends Values {
public static LogicalValues create(RelOptCluster cluster,
final RelDataType rowType,
final ImmutableList<ImmutableList<RexLiteral>> tuples) {
+ final RelMetadataQuery mq = RelMetadataQuery.instance();
final RelTraitSet traitSet = cluster.traitSetOf(Convention.NONE)
.replaceIfs(
RelCollationTraitDef.INSTANCE, new Supplier<List<RelCollation>>() {
public List<RelCollation> get() {
- return RelMdCollation.values(rowType, tuples);
+ return RelMdCollation.values(mq, rowType, tuples);
}
});
return new LogicalValues(cluster, traitSet, rowType, tuples);
http://git-wip-us.apache.org/repos/asf/calcite/blob/cabdcf44/core/src/main/java/org/apache/calcite/rel/metadata/BuiltInMetadata.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rel/metadata/BuiltInMetadata.java b/core/src/main/java/org/apache/calcite/rel/metadata/BuiltInMetadata.java
index 81d6eed..87fbbf4 100644
--- a/core/src/main/java/org/apache/calcite/rel/metadata/BuiltInMetadata.java
+++ b/core/src/main/java/org/apache/calcite/rel/metadata/BuiltInMetadata.java
@@ -122,7 +122,7 @@ public abstract class BuiltInMetadata {
/**
* Estimates the number of rows which will be returned by a relational
* expression. The default implementation for this query asks the rel itself
- * via {@link RelNode#getRows}, but metadata providers can override this
+ * via {@link RelNode#estimateRowCount}, but metadata providers can override this
* with their own cost models.
*
* @return estimated row count, or null if no reliable estimate can be
@@ -131,14 +131,18 @@ public abstract class BuiltInMetadata {
Double getRowCount();
}
- /** Metadata about the max number of rows returned by a relational expression. */
+ /** Metadata about the maximum number of rows returned by a relational
+ * expression. */
public interface MaxRowCount extends Metadata {
/**
* Estimates the max number of rows which will be returned by a relational
- * expression. The default implementation for this query returns Double.POSITIVE_INFINITY,
+ * expression.
+ *
+ * <p>The default implementation for this query returns
+ * {@link Double#POSITIVE_INFINITY},
* but metadata providers can override this with their own cost models.
*
- * @return estimated max row count
+ * @return upper bound on the number of rows returned
*/
Double getMaxRowCount();
}
@@ -338,7 +342,7 @@ public abstract class BuiltInMetadata {
* physical operator implementing this relational expression, and all other
* operators within the same phase, across all splits.
*
- * @see org.apache.calcite.rel.metadata.BuiltInMetadata.Parallelism#splitCount()
+ * @see Parallelism#splitCount()
*/
Double cumulativeMemoryWithinPhase();
http://git-wip-us.apache.org/repos/asf/calcite/blob/cabdcf44/core/src/main/java/org/apache/calcite/rel/metadata/CachingRelMetadataProvider.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rel/metadata/CachingRelMetadataProvider.java b/core/src/main/java/org/apache/calcite/rel/metadata/CachingRelMetadataProvider.java
index 516de3a..8438a8d 100644
--- a/core/src/main/java/org/apache/calcite/rel/metadata/CachingRelMetadataProvider.java
+++ b/core/src/main/java/org/apache/calcite/rel/metadata/CachingRelMetadataProvider.java
@@ -19,11 +19,12 @@ package org.apache.calcite.rel.metadata;
import org.apache.calcite.plan.RelOptPlanner;
import org.apache.calcite.rel.RelNode;
-import com.google.common.base.Function;
import com.google.common.base.Preconditions;
+import com.google.common.base.Throwables;
import com.google.common.collect.ImmutableList;
import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.HashMap;
@@ -37,18 +38,12 @@ import java.util.Map;
public class CachingRelMetadataProvider implements RelMetadataProvider {
//~ Instance fields --------------------------------------------------------
- private final Map<List, CacheEntry> cache;
+ private final Map<List, CacheEntry> cache = new HashMap<>();
private final RelMetadataProvider underlyingProvider;
private final RelOptPlanner planner;
- private static final Object NULL_SENTINEL = new Object() {
- @Override public String toString() {
- return "{null}";
- }
- };
-
//~ Constructors -----------------------------------------------------------
public CachingRelMetadataProvider(
@@ -56,15 +51,14 @@ public class CachingRelMetadataProvider implements RelMetadataProvider {
RelOptPlanner planner) {
this.underlyingProvider = underlyingProvider;
this.planner = planner;
-
- cache = new HashMap<List, CacheEntry>();
}
//~ Methods ----------------------------------------------------------------
- public Function<RelNode, Metadata> apply(Class<? extends RelNode> relClass,
- final Class<? extends Metadata> metadataClass) {
- final Function<RelNode, Metadata> function =
+ public <M extends Metadata> UnboundMetadata<M>
+ apply(Class<? extends RelNode> relClass,
+ final Class<? extends M> metadataClass) {
+ final UnboundMetadata<M> function =
underlyingProvider.apply(relClass, metadataClass);
if (function == null) {
return null;
@@ -72,11 +66,13 @@ public class CachingRelMetadataProvider implements RelMetadataProvider {
// TODO jvs 30-Mar-2006: Use meta-metadata to decide which metadata
// query results can stay fresh until the next Ice Age.
- return new Function<RelNode, Metadata>() {
- public Metadata apply(RelNode input) {
- final Metadata metadata = function.apply(input);
- return (Metadata) Proxy.newProxyInstance(metadataClass.getClassLoader(),
- new Class[]{metadataClass}, new CachingInvocationHandler(metadata));
+ return new UnboundMetadata<M>() {
+ public M bind(RelNode rel, RelMetadataQuery mq) {
+ final Metadata metadata = function.bind(rel, mq);
+ return metadataClass.cast(
+ Proxy.newProxyInstance(metadataClass.getClassLoader(),
+ new Class[]{metadataClass},
+ new CachingInvocationHandler(metadata)));
}
};
}
@@ -113,7 +109,7 @@ public class CachingRelMetadataProvider implements RelMetadataProvider {
if (args != null) {
for (Object arg : args) {
// Replace null values because ImmutableList does not allow them.
- builder.add(arg == null ? NULL_SENTINEL : arg);
+ builder.add(NullSentinel.mask(arg));
}
}
List<Object> key = builder.build();
@@ -129,14 +125,19 @@ public class CachingRelMetadataProvider implements RelMetadataProvider {
}
// Cache miss or stale.
- Object result = method.invoke(metadata, args);
- if (result != null) {
- entry = new CacheEntry();
- entry.timestamp = timestamp;
- entry.result = result;
- cache.put(key, entry);
+ try {
+ Object result = method.invoke(metadata, args);
+ if (result != null) {
+ entry = new CacheEntry();
+ entry.timestamp = timestamp;
+ entry.result = result;
+ cache.put(key, entry);
+ }
+ return result;
+ } catch (InvocationTargetException e) {
+ Throwables.propagateIfPossible(e.getCause());
+ throw e;
}
- return result;
}
}
}
http://git-wip-us.apache.org/repos/asf/calcite/blob/cabdcf44/core/src/main/java/org/apache/calcite/rel/metadata/ChainedRelMetadataProvider.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rel/metadata/ChainedRelMetadataProvider.java b/core/src/main/java/org/apache/calcite/rel/metadata/ChainedRelMetadataProvider.java
index 445cce4..eb8aec5 100644
--- a/core/src/main/java/org/apache/calcite/rel/metadata/ChainedRelMetadataProvider.java
+++ b/core/src/main/java/org/apache/calcite/rel/metadata/ChainedRelMetadataProvider.java
@@ -18,13 +18,15 @@ package org.apache.calcite.rel.metadata;
import org.apache.calcite.rel.RelNode;
-import com.google.common.base.Function;
+import com.google.common.base.Throwables;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
+import java.util.ArrayList;
import java.util.List;
/**
@@ -53,11 +55,12 @@ public class ChainedRelMetadataProvider implements RelMetadataProvider {
//~ Methods ----------------------------------------------------------------
- public Function<RelNode, Metadata> apply(Class<? extends RelNode> relClass,
- final Class<? extends Metadata> metadataClass) {
- final List<Function<RelNode, Metadata>> functions = Lists.newArrayList();
+ public <M extends Metadata> UnboundMetadata<M>
+ apply(Class<? extends RelNode> relClass,
+ final Class<? extends M> metadataClass) {
+ final List<UnboundMetadata<M>> functions = new ArrayList<>();
for (RelMetadataProvider provider : providers) {
- final Function<RelNode, Metadata> function =
+ final UnboundMetadata<M> function =
provider.apply(relClass, metadataClass);
if (function == null) {
continue;
@@ -70,22 +73,21 @@ public class ChainedRelMetadataProvider implements RelMetadataProvider {
case 1:
return functions.get(0);
default:
- return new Function<RelNode, Metadata>() {
- public Metadata apply(RelNode input) {
+ return new UnboundMetadata<M>() {
+ public M bind(RelNode rel, RelMetadataQuery mq) {
final List<Metadata> metadataList = Lists.newArrayList();
- for (Function<RelNode, Metadata> function : functions) {
- final Metadata metadata = function.apply(input);
+ for (UnboundMetadata<M> function : functions) {
+ final Metadata metadata = function.bind(rel, mq);
if (metadata != null) {
metadataList.add(metadata);
}
}
- return (Metadata) Proxy.newProxyInstance(
- metadataClass.getClassLoader(),
- new Class[]{metadataClass},
- new ChainedInvocationHandler(metadataList));
+ return metadataClass.cast(
+ Proxy.newProxyInstance(metadataClass.getClassLoader(),
+ new Class[]{metadataClass},
+ new ChainedInvocationHandler(metadataList)));
}
};
-
}
}
@@ -106,9 +108,17 @@ public class ChainedRelMetadataProvider implements RelMetadataProvider {
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
for (Metadata metadata : metadataList) {
- final Object o = method.invoke(metadata, args);
- if (o != null) {
- return o;
+ try {
+ final Object o = method.invoke(metadata, args);
+ if (o != null) {
+ return o;
+ }
+ } catch (InvocationTargetException e) {
+ if (e.getCause() instanceof CyclicMetadataException) {
+ continue;
+ }
+ Throwables.propagateIfPossible(e.getCause());
+ throw e;
}
}
return null;
http://git-wip-us.apache.org/repos/asf/calcite/blob/cabdcf44/core/src/main/java/org/apache/calcite/rel/metadata/CyclicMetadataException.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rel/metadata/CyclicMetadataException.java b/core/src/main/java/org/apache/calcite/rel/metadata/CyclicMetadataException.java
new file mode 100644
index 0000000..d4dd249
--- /dev/null
+++ b/core/src/main/java/org/apache/calcite/rel/metadata/CyclicMetadataException.java
@@ -0,0 +1,37 @@
+/*
+ * 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.metadata;
+
+/**
+ * Exception that indicates that a cycle has been detected while
+ * computing metadata.
+ */
+public class CyclicMetadataException extends RuntimeException {
+ /** Singleton instance. Since this exception is thrown for signaling purposes,
+ * rather than on an actual error, re-using a singleton instance saves the
+ * effort of constructing an exception instance. */
+ @SuppressWarnings("ThrowableInstanceNeverThrown")
+ public static final CyclicMetadataException INSTANCE =
+ new CyclicMetadataException();
+
+ /** Creates a CyclicMetadataException. */
+ private CyclicMetadataException() {
+ super();
+ }
+}
+
+// End CyclicMetadataException.java
http://git-wip-us.apache.org/repos/asf/calcite/blob/cabdcf44/core/src/main/java/org/apache/calcite/rel/metadata/Metadata.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rel/metadata/Metadata.java b/core/src/main/java/org/apache/calcite/rel/metadata/Metadata.java
index 34e456f..d5d642d 100644
--- a/core/src/main/java/org/apache/calcite/rel/metadata/Metadata.java
+++ b/core/src/main/java/org/apache/calcite/rel/metadata/Metadata.java
@@ -26,7 +26,7 @@ import org.apache.calcite.rel.RelNode;
* kinds of metadata for particular sub-classes of {@link RelNode}.
*
* <p>User code (typically in a planner rule or an implementation of
- * {@link RelNode#computeSelfCost(org.apache.calcite.plan.RelOptPlanner)})
+ * {@link RelNode#computeSelfCost(org.apache.calcite.plan.RelOptPlanner, RelMetadataQuery)})
* acquires a {@code Metadata} instance by calling {@link RelNode#metadata}.
*
* <p>A {@code Metadata} instance already knows which particular {@code RelNode}
http://git-wip-us.apache.org/repos/asf/calcite/blob/cabdcf44/core/src/main/java/org/apache/calcite/rel/metadata/MetadataFactory.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rel/metadata/MetadataFactory.java b/core/src/main/java/org/apache/calcite/rel/metadata/MetadataFactory.java
index 7651ecd..28ca883 100644
--- a/core/src/main/java/org/apache/calcite/rel/metadata/MetadataFactory.java
+++ b/core/src/main/java/org/apache/calcite/rel/metadata/MetadataFactory.java
@@ -31,8 +31,17 @@ import org.apache.calcite.rel.RelNode;
public interface MetadataFactory {
/** Returns a metadata interface to get a particular kind of metadata
* from a particular relational expression. Returns null if that kind of
- * metadata is not available. */
- <T extends Metadata> T query(RelNode rel, Class<T> clazz);
+ * metadata is not available.
+ *
+ * @param <M> Metadata type
+ *
+ * @param rel Relational expression
+ * @param mq Metadata query
+ * @param metadataClazz Metadata class
+ * @return Metadata bound to {@code rel} and {@code query}
+ */
+ <M extends Metadata> M query(RelNode rel, RelMetadataQuery mq,
+ Class<M> metadataClazz);
}
// End MetadataFactory.java
http://git-wip-us.apache.org/repos/asf/calcite/blob/cabdcf44/core/src/main/java/org/apache/calcite/rel/metadata/MetadataFactoryImpl.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rel/metadata/MetadataFactoryImpl.java b/core/src/main/java/org/apache/calcite/rel/metadata/MetadataFactoryImpl.java
index e20d6ce..f5b5717 100644
--- a/core/src/main/java/org/apache/calcite/rel/metadata/MetadataFactoryImpl.java
+++ b/core/src/main/java/org/apache/calcite/rel/metadata/MetadataFactoryImpl.java
@@ -19,8 +19,6 @@ package org.apache.calcite.rel.metadata;
import org.apache.calcite.rel.RelNode;
import org.apache.calcite.util.Pair;
-import com.google.common.base.Function;
-import com.google.common.base.Functions;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
@@ -36,24 +34,27 @@ import java.util.concurrent.ExecutionException;
*/
public class MetadataFactoryImpl implements MetadataFactory {
@SuppressWarnings("unchecked")
- public static final Function<RelNode, Metadata> DUMMY =
- (Function) Functions.<Metadata>constant(null);
+ public static final UnboundMetadata<Metadata> DUMMY =
+ new UnboundMetadata<Metadata>() {
+ public Metadata bind(RelNode rel, RelMetadataQuery mq) {
+ return null;
+ }
+ };
private final LoadingCache<
- Pair<Class<RelNode>, Class<Metadata>>,
- Function<RelNode, Metadata>> cache;
+ Pair<Class<RelNode>, Class<Metadata>>, UnboundMetadata<Metadata>> cache;
public MetadataFactoryImpl(RelMetadataProvider provider) {
this.cache = CacheBuilder.newBuilder().build(loader(provider));
}
static CacheLoader<Pair<Class<RelNode>, Class<Metadata>>,
- Function<RelNode, Metadata>> loader(final RelMetadataProvider provider) {
+ UnboundMetadata<Metadata>> loader(final RelMetadataProvider provider) {
return new CacheLoader<Pair<Class<RelNode>, Class<Metadata>>,
- Function<RelNode, Metadata>>() {
- @Override public Function<RelNode, Metadata> load(
+ UnboundMetadata<Metadata>>() {
+ @Override public UnboundMetadata<Metadata> load(
Pair<Class<RelNode>, Class<Metadata>> key) throws Exception {
- final Function<RelNode, Metadata> function =
+ final UnboundMetadata<Metadata> function =
provider.apply(key.left, key.right);
// Return DUMMY, not null, so the cache knows to not ask again.
return function != null ? function : DUMMY;
@@ -61,14 +62,14 @@ public class MetadataFactoryImpl implements MetadataFactory {
};
}
- public <T extends Metadata> T query(RelNode rel, Class<T> clazz) {
+ public <M extends Metadata> M query(RelNode rel, RelMetadataQuery mq,
+ Class<M> metadataClazz) {
try {
//noinspection unchecked
final Pair<Class<RelNode>, Class<Metadata>> key =
- (Pair) Pair.of(rel.getClass(), clazz);
- final Metadata apply = cache.get(key).apply(rel);
- //noinspection unchecked
- return (T) apply;
+ (Pair) Pair.of(rel.getClass(), metadataClazz);
+ final Metadata apply = cache.get(key).bind(rel, mq);
+ return metadataClazz.cast(apply);
} catch (ExecutionException e) {
if (e.getCause() instanceof RuntimeException) {
throw (RuntimeException) e.getCause();
http://git-wip-us.apache.org/repos/asf/calcite/blob/cabdcf44/core/src/main/java/org/apache/calcite/rel/metadata/ReflectiveRelMetadataProvider.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rel/metadata/ReflectiveRelMetadataProvider.java b/core/src/main/java/org/apache/calcite/rel/metadata/ReflectiveRelMetadataProvider.java
index 7db2c6a..beaedfe 100644
--- a/core/src/main/java/org/apache/calcite/rel/metadata/ReflectiveRelMetadataProvider.java
+++ b/core/src/main/java/org/apache/calcite/rel/metadata/ReflectiveRelMetadataProvider.java
@@ -17,23 +17,29 @@
package org.apache.calcite.rel.metadata;
import org.apache.calcite.rel.RelNode;
+import org.apache.calcite.rex.RexNode;
+import org.apache.calcite.runtime.FlatLists;
import org.apache.calcite.util.BuiltInMethod;
import org.apache.calcite.util.ImmutableNullableList;
import org.apache.calcite.util.Pair;
import org.apache.calcite.util.ReflectiveVisitor;
import org.apache.calcite.util.Util;
-import com.google.common.base.Function;
+import com.google.common.base.Throwables;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Proxy;
+import java.lang.reflect.UndeclaredThrowableException;
+import java.util.ArrayList;
import java.util.Arrays;
+import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -54,8 +60,8 @@ public class ReflectiveRelMetadataProvider
implements RelMetadataProvider, ReflectiveVisitor {
//~ Instance fields --------------------------------------------------------
- private final Map<Class<RelNode>, Function<RelNode, Metadata>> map;
- private final Class<?> metadataClass0;
+ private final Map<Class<RelNode>, UnboundMetadata> map;
+ private final Class<? extends Metadata> metadataClass0;
//~ Constructors -----------------------------------------------------------
@@ -66,8 +72,8 @@ public class ReflectiveRelMetadataProvider
* @param metadataClass0 Metadata class
*/
protected ReflectiveRelMetadataProvider(
- Map<Class<RelNode>, Function<RelNode, Metadata>> map,
- Class<?> metadataClass0) {
+ Map<Class<RelNode>, UnboundMetadata> map,
+ Class<? extends Metadata> metadataClass0) {
assert !map.isEmpty() : "are your methods named wrong?";
this.map = map;
this.metadataClass0 = metadataClass0;
@@ -77,7 +83,7 @@ public class ReflectiveRelMetadataProvider
* methods with a preceding argument.
*
* <p>For example, {@link BuiltInMetadata.Selectivity} has a method
- * {@link BuiltInMetadata.Selectivity#getSelectivity(org.apache.calcite.rex.RexNode)}.
+ * {@link BuiltInMetadata.Selectivity#getSelectivity(RexNode)}.
* A class</p>
*
* <blockquote><pre><code>
@@ -106,7 +112,8 @@ public class ReflectiveRelMetadataProvider
final ImmutableList<Method> methods) {
assert methods.size() > 0;
final Method method0 = methods.get(0);
- final Class<?> metadataClass0 = method0.getDeclaringClass();
+ @SuppressWarnings("unchecked")
+ final Class<Metadata> metadataClass0 = (Class) method0.getDeclaringClass();
assert Metadata.class.isAssignableFrom(metadataClass0);
for (Method method : methods) {
assert method.getDeclaringClass() == metadataClass0;
@@ -128,8 +135,7 @@ public class ReflectiveRelMetadataProvider
}
}
- final Map<Class<RelNode>, Function<RelNode, Metadata>> methodsMap =
- Maps.newHashMap();
+ final Map<Class<RelNode>, UnboundMetadata> methodsMap = new HashMap<>();
for (Class<RelNode> key : classes) {
ImmutableNullableList.Builder<Method> builder =
ImmutableNullableList.builder();
@@ -137,9 +143,10 @@ public class ReflectiveRelMetadataProvider
builder.add(find(handlerMap, key, method));
}
final List<Method> handlerMethods = builder.build();
- final Function<RelNode, Metadata> function =
- new Function<RelNode, Metadata>() {
- public Metadata apply(final RelNode rel) {
+ final UnboundMetadata function =
+ new UnboundMetadata() {
+ public Metadata bind(final RelNode rel,
+ final RelMetadataQuery mq) {
return (Metadata) Proxy.newProxyInstance(
metadataClass0.getClassLoader(),
new Class[]{metadataClass0},
@@ -166,20 +173,46 @@ public class ReflectiveRelMetadataProvider
throw new AssertionError("not handled: " + method
+ " for " + rel);
}
+ final Method handlerMethod = handlerMethods.get(i);
+ if (handlerMethod == null) {
+ throw new AssertionError("not handled: " + method
+ + " for " + rel);
+ }
final Object[] args1;
+ final List key;
if (args == null) {
- args1 = new Object[]{rel};
+ args1 = new Object[]{rel, mq};
+ key = FlatLists.of(rel, method);
} else {
- args1 = new Object[args.length + 1];
+ args1 = new Object[args.length + 2];
args1[0] = rel;
- System.arraycopy(args, 0, args1, 1, args.length);
+ args1[1] = mq;
+ System.arraycopy(args, 0, args1, 2, args.length);
+
+ final Object[] args2 = args1.clone();
+ args2[1] = method; // replace RelMetadataQuery with method
+ for (int j = 0; j < args2.length; j++) {
+ if (args2[j] == null) {
+ args2[j] = NullSentinel.INSTANCE;
+ } else if (args2[j] instanceof RexNode) {
+ // Can't use RexNode.equals - it is not deep
+ args2[j] = args2[j].toString();
+ }
+ }
+ key = FlatLists.copyOf(args2);
}
- final Method handlerMethod = handlerMethods.get(i);
- if (handlerMethod == null) {
- throw new AssertionError("not handled: " + method
- + " for " + rel);
+ if (!mq.set.add(key)) {
+ throw CyclicMetadataException.INSTANCE;
+ }
+ try {
+ return handlerMethod.invoke(target, args1);
+ } catch (InvocationTargetException
+ | UndeclaredThrowableException e) {
+ Throwables.propagateIfPossible(e.getCause());
+ throw e;
+ } finally {
+ mq.set.remove(key);
}
- return handlerMethod.invoke(target, args1);
}
});
}
@@ -229,19 +262,18 @@ public class ReflectiveRelMetadataProvider
}
final Class<?>[] parameterTypes1 = handlerMethod.getParameterTypes();
final Class<?>[] parameterTypes = method.getParameterTypes();
- if (parameterTypes1.length != parameterTypes.length + 1
- || !RelNode.class.isAssignableFrom(parameterTypes1[0])) {
- return false;
- }
- return Util.skip(Arrays.asList(parameterTypes1))
- .equals(Arrays.asList(parameterTypes));
+ return parameterTypes1.length == parameterTypes.length + 2
+ && RelNode.class.isAssignableFrom(parameterTypes1[0])
+ && RelMetadataQuery.class == parameterTypes1[1]
+ && Arrays.asList(parameterTypes)
+ .equals(Util.skip(Arrays.asList(parameterTypes1), 2));
}
//~ Methods ----------------------------------------------------------------
- public Function<RelNode, Metadata> apply(
- Class<? extends RelNode> relClass,
- Class<? extends Metadata> metadataClass) {
+ public <M extends Metadata> UnboundMetadata<M>
+ apply(Class<? extends RelNode> relClass,
+ Class<? extends M> metadataClass) {
if (metadataClass == metadataClass0) {
return apply(relClass);
} else {
@@ -250,11 +282,11 @@ public class ReflectiveRelMetadataProvider
}
@SuppressWarnings({ "unchecked", "SuspiciousMethodCalls" })
- private synchronized Function<RelNode, Metadata> apply(
- Class<? extends RelNode> relClass) {
- List<Class<? extends RelNode>> newSources = Lists.newArrayList();
+ public <M extends Metadata> UnboundMetadata<M>
+ apply(Class<? extends RelNode> relClass) {
+ List<Class<? extends RelNode>> newSources = new ArrayList<>();
for (;;) {
- final Function<RelNode, Metadata> function = map.get(relClass);
+ UnboundMetadata<M> function = map.get(relClass);
if (function != null) {
for (@SuppressWarnings("rawtypes") Class clazz : newSources) {
map.put(clazz, function);
@@ -265,7 +297,7 @@ public class ReflectiveRelMetadataProvider
}
for (Class<?> interfaceClass : relClass.getInterfaces()) {
if (RelNode.class.isAssignableFrom(interfaceClass)) {
- final Function<RelNode, Metadata> function2 = map.get(interfaceClass);
+ final UnboundMetadata<M> function2 = map.get(interfaceClass);
if (function2 != null) {
for (@SuppressWarnings("rawtypes") Class clazz : newSources) {
map.put(clazz, function2);
http://git-wip-us.apache.org/repos/asf/calcite/blob/cabdcf44/core/src/main/java/org/apache/calcite/rel/metadata/RelMdCollation.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdCollation.java b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdCollation.java
index 37ce6da..92b325d 100644
--- a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdCollation.java
+++ b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdCollation.java
@@ -47,12 +47,12 @@ import org.apache.calcite.util.ImmutableIntList;
import org.apache.calcite.util.Pair;
import org.apache.calcite.util.Util;
+import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.LinkedListMultimap;
import com.google.common.collect.Lists;
import com.google.common.collect.Multimap;
import com.google.common.collect.Ordering;
-import com.google.common.collect.Sets;
import java.util.ArrayList;
import java.util.Collection;
@@ -60,6 +60,7 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.SortedSet;
+import java.util.TreeSet;
/**
* RelMdCollation supplies a default implementation of
@@ -77,7 +78,9 @@ public class RelMdCollation {
//~ Methods ----------------------------------------------------------------
- /** Fallback method to deduce collations for any relational expression not
+ /** Catch-all implementation for
+ * {@link BuiltInMetadata.Collation#collations()},
+ * invoked using reflection, for any relational expression not
* handled by a more specific method.
*
* <p>{@link org.apache.calcite.rel.core.Union},
@@ -91,60 +94,72 @@ public class RelMdCollation {
*
* @param rel Relational expression
* @return Relational expression's collations
+ *
+ * @see org.apache.calcite.rel.metadata.RelMetadataQuery#collations(RelNode)
*/
- public ImmutableList<RelCollation> collations(RelNode rel) {
+ public ImmutableList<RelCollation> collations(RelNode rel,
+ RelMetadataQuery mq) {
return ImmutableList.of();
}
- public ImmutableList<RelCollation> collations(Window rel) {
- return ImmutableList.copyOf(window(rel.getInput(), rel.groups));
+ public ImmutableList<RelCollation> collations(Window rel,
+ RelMetadataQuery mq) {
+ return ImmutableList.copyOf(window(mq, rel.getInput(), rel.groups));
}
- public ImmutableList<RelCollation> collations(Filter rel) {
- return RelMetadataQuery.collations(rel.getInput());
+ public ImmutableList<RelCollation> collations(Filter rel,
+ RelMetadataQuery mq) {
+ return mq.collations(rel.getInput());
}
- public ImmutableList<RelCollation> collations(TableScan scan) {
+ public ImmutableList<RelCollation> collations(TableScan scan,
+ RelMetadataQuery mq) {
return ImmutableList.copyOf(table(scan.getTable()));
}
- public ImmutableList<RelCollation> collations(EnumerableMergeJoin join) {
+ public ImmutableList<RelCollation> collations(EnumerableMergeJoin join,
+ RelMetadataQuery mq) {
// In general a join is not sorted. But a merge join preserves the sort
// order of the left and right sides.
return ImmutableList.copyOf(
- RelMdCollation.mergeJoin(join.getLeft(),
- join.getRight(),
- join.getLeftKeys(),
- join.getRightKeys()));
+ RelMdCollation.mergeJoin(mq, join.getLeft(), join.getRight(),
+ join.getLeftKeys(), join.getRightKeys()));
}
- public ImmutableList<RelCollation> collations(Sort sort) {
+ public ImmutableList<RelCollation> collations(Sort sort,
+ RelMetadataQuery mq) {
return ImmutableList.copyOf(
RelMdCollation.sort(sort.getCollation()));
}
- public ImmutableList<RelCollation> collations(SortExchange sort) {
+ public ImmutableList<RelCollation> collations(SortExchange sort,
+ RelMetadataQuery mq) {
return ImmutableList.copyOf(
RelMdCollation.sort(sort.getCollation()));
}
- public ImmutableList<RelCollation> collations(Project project) {
+ public ImmutableList<RelCollation> collations(Project project,
+ RelMetadataQuery mq) {
return ImmutableList.copyOf(
- project(project.getInput(), project.getProjects()));
+ project(mq, project.getInput(), project.getProjects()));
}
- public ImmutableList<RelCollation> collations(Values values) {
+ public ImmutableList<RelCollation> collations(Values values,
+ RelMetadataQuery mq) {
return ImmutableList.copyOf(
- values(values.getRowType(), values.getTuples()));
+ values(mq, values.getRowType(), values.getTuples()));
}
- public ImmutableList<RelCollation> collations(HepRelVertex rel) {
- return RelMetadataQuery.collations(rel.getCurrentRel());
+ public ImmutableList<RelCollation> collations(HepRelVertex rel,
+ RelMetadataQuery mq) {
+ return mq.collations(rel.getCurrentRel());
}
- public ImmutableList<RelCollation> collations(RelSubset rel) {
+ public ImmutableList<RelCollation> collations(RelSubset rel,
+ RelMetadataQuery mq) {
return ImmutableList.copyOf(
- rel.getTraitSet().getTraits(RelCollationTraitDef.INSTANCE));
+ Preconditions.checkNotNull(
+ rel.getTraitSet().getTraits(RelCollationTraitDef.INSTANCE)));
}
// Helper methods
@@ -163,29 +178,28 @@ public class RelMdCollation {
/** Helper method to determine a
* {@link org.apache.calcite.rel.core.Filter}'s collation. */
- public static List<RelCollation> filter(RelNode input) {
- return RelMetadataQuery.collations(input);
+ public static List<RelCollation> filter(RelMetadataQuery mq, RelNode input) {
+ return mq.collations(input);
}
/** Helper method to determine a
* limit's collation. */
- public static List<RelCollation> limit(RelNode input) {
- return RelMetadataQuery.collations(input);
+ public static List<RelCollation> limit(RelMetadataQuery mq, RelNode input) {
+ return mq.collations(input);
}
/** Helper method to determine a
* {@link org.apache.calcite.rel.core.Calc}'s collation. */
- public static List<RelCollation> calc(RelNode input,
+ public static List<RelCollation> calc(RelMetadataQuery mq, RelNode input,
RexProgram program) {
- return program.getCollations(RelMetadataQuery.collations(input));
+ return program.getCollations(mq.collations(input));
}
/** Helper method to determine a {@link Project}'s collation. */
- public static List<RelCollation> project(RelNode input,
- List<? extends RexNode> projects) {
- final SortedSet<RelCollation> collations = Sets.newTreeSet();
- final List<RelCollation> inputCollations =
- RelMetadataQuery.collations(input);
+ public static List<RelCollation> project(RelMetadataQuery mq,
+ RelNode input, List<? extends RexNode> projects) {
+ final SortedSet<RelCollation> collations = new TreeSet<>();
+ final List<RelCollation> inputCollations = mq.collations(input);
if (inputCollations == null || inputCollations.isEmpty()) {
return ImmutableList.of();
}
@@ -202,7 +216,7 @@ public class RelMdCollation {
targetsWithMonotonicity.put(project.i, call.getOperator().getMonotonicity(binding));
}
}
- final List<RelFieldCollation> fieldCollations = Lists.newArrayList();
+ final List<RelFieldCollation> fieldCollations = new ArrayList<>();
loop:
for (RelCollation ic : inputCollations) {
if (ic.getFieldCollations().isEmpty()) {
@@ -251,9 +265,9 @@ public class RelMdCollation {
* from each of its windows. Assuming (quite reasonably) that the
* implementation does not re-order its input rows, then any collations of its
* input are preserved. */
- public static List<RelCollation> window(RelNode input,
+ public static List<RelCollation> window(RelMetadataQuery mq, RelNode input,
ImmutableList<Window.Group> groups) {
- return RelMetadataQuery.collations(input);
+ return mq.collations(input);
}
/** Helper method to determine a
@@ -274,8 +288,9 @@ public class RelMdCollation {
*
* <p>So, for an empty Values with 4 columns, we would emit
* {@code (a, b, c, d), (b, c, d), (c, d), (d)}. */
- public static List<RelCollation> values(RelDataType rowType,
- ImmutableList<ImmutableList<RexLiteral>> tuples) {
+ public static List<RelCollation> values(RelMetadataQuery mq,
+ RelDataType rowType, ImmutableList<ImmutableList<RexLiteral>> tuples) {
+ Util.discard(mq); // for future use
final List<RelCollation> list = Lists.newArrayList();
final int n = rowType.getFieldCount();
final List<Pair<RelFieldCollation, Ordering<List<RexLiteral>>>> pairs =
@@ -336,18 +351,17 @@ public class RelMdCollation {
*
* <p>If the inputs are sorted on other keys <em>in addition to</em> the join
* key, the result preserves those collations too. */
- public static List<RelCollation> mergeJoin(RelNode left, RelNode right,
+ public static List<RelCollation> mergeJoin(RelMetadataQuery mq,
+ RelNode left, RelNode right,
ImmutableIntList leftKeys, ImmutableIntList rightKeys) {
final ImmutableList.Builder<RelCollation> builder = ImmutableList.builder();
- final ImmutableList<RelCollation> leftCollations =
- RelMetadataQuery.collations(left);
+ final ImmutableList<RelCollation> leftCollations = mq.collations(left);
assert RelCollations.contains(leftCollations, leftKeys)
: "cannot merge join: left input is not sorted on left keys";
builder.addAll(leftCollations);
- final ImmutableList<RelCollation> rightCollations =
- RelMetadataQuery.collations(right);
+ final ImmutableList<RelCollation> rightCollations = mq.collations(right);
assert RelCollations.contains(rightCollations, rightKeys)
: "cannot merge join: right input is not sorted on right keys";
final int leftFieldCount = left.getRowType().getFieldCount();
http://git-wip-us.apache.org/repos/asf/calcite/blob/cabdcf44/core/src/main/java/org/apache/calcite/rel/metadata/RelMdColumnOrigins.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdColumnOrigins.java b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdColumnOrigins.java
index 7f06443..3038260 100644
--- a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdColumnOrigins.java
+++ b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdColumnOrigins.java
@@ -53,14 +53,11 @@ public class RelMdColumnOrigins {
//~ Methods ----------------------------------------------------------------
- public Set<RelColumnOrigin> getColumnOrigins(
- Aggregate rel,
- int iOutputColumn) {
+ public Set<RelColumnOrigin> getColumnOrigins(Aggregate rel,
+ RelMetadataQuery mq, int iOutputColumn) {
if (iOutputColumn < rel.getGroupCount()) {
// Group columns pass through directly.
- return invokeGetColumnOrigins(
- rel.getInput(),
- iOutputColumn);
+ return mq.getColumnOrigins(rel.getInput(), iOutputColumn);
}
if (rel.indicator) {
@@ -75,11 +72,10 @@ public class RelMdColumnOrigins {
rel.getAggCallList().get(iOutputColumn
- rel.getGroupCount() - rel.getIndicatorCount());
- Set<RelColumnOrigin> set = new HashSet<RelColumnOrigin>();
+ final Set<RelColumnOrigin> set = new HashSet<>();
for (Integer iInput : call.getArgList()) {
Set<RelColumnOrigin> inputSet =
- invokeGetColumnOrigins(
- rel.getInput(), iInput);
+ mq.getColumnOrigins(rel.getInput(), iInput);
inputSet = createDerivedColumnOrigins(inputSet);
if (inputSet != null) {
set.addAll(inputSet);
@@ -88,25 +84,18 @@ public class RelMdColumnOrigins {
return set;
}
- public Set<RelColumnOrigin> getColumnOrigins(
- Join rel,
+ public Set<RelColumnOrigin> getColumnOrigins(Join rel, RelMetadataQuery mq,
int iOutputColumn) {
int nLeftColumns = rel.getLeft().getRowType().getFieldList().size();
Set<RelColumnOrigin> set;
boolean derived = false;
if (iOutputColumn < nLeftColumns) {
- set =
- invokeGetColumnOrigins(
- rel.getLeft(),
- iOutputColumn);
+ set = mq.getColumnOrigins(rel.getLeft(), iOutputColumn);
if (rel.getJoinType().generatesNullsOnLeft()) {
derived = true;
}
} else {
- set =
- invokeGetColumnOrigins(
- rel.getRight(),
- iOutputColumn - nLeftColumns);
+ set = mq.getColumnOrigins(rel.getRight(), iOutputColumn - nLeftColumns);
if (rel.getJoinType().generatesNullsOnRight()) {
derived = true;
}
@@ -119,15 +108,11 @@ public class RelMdColumnOrigins {
return set;
}
- public Set<RelColumnOrigin> getColumnOrigins(
- SetOp rel,
- int iOutputColumn) {
- Set<RelColumnOrigin> set = new HashSet<RelColumnOrigin>();
+ public Set<RelColumnOrigin> getColumnOrigins(SetOp rel,
+ RelMetadataQuery mq, int iOutputColumn) {
+ final Set<RelColumnOrigin> set = new HashSet<>();
for (RelNode input : rel.getInputs()) {
- Set<RelColumnOrigin> inputSet =
- invokeGetColumnOrigins(
- input,
- iOutputColumn);
+ Set<RelColumnOrigin> inputSet = mq.getColumnOrigins(input, iOutputColumn);
if (inputSet == null) {
return null;
}
@@ -136,30 +121,25 @@ public class RelMdColumnOrigins {
return set;
}
- public Set<RelColumnOrigin> getColumnOrigins(
- Project rel,
- int iOutputColumn) {
- final RelNode child = rel.getInput();
+ public Set<RelColumnOrigin> getColumnOrigins(Project rel,
+ final RelMetadataQuery mq, int iOutputColumn) {
+ final RelNode input = rel.getInput();
RexNode rexNode = rel.getProjects().get(iOutputColumn);
if (rexNode instanceof RexInputRef) {
// Direct reference: no derivation added.
RexInputRef inputRef = (RexInputRef) rexNode;
- return invokeGetColumnOrigins(
- child,
- inputRef.getIndex());
+ return mq.getColumnOrigins(input, inputRef.getIndex());
}
// Anything else is a derivation, possibly from multiple
// columns.
- final Set<RelColumnOrigin> set = new HashSet<RelColumnOrigin>();
+ final Set<RelColumnOrigin> set = new HashSet<>();
RexVisitor visitor =
new RexVisitorImpl<Void>(true) {
public Void visitInputRef(RexInputRef inputRef) {
Set<RelColumnOrigin> inputSet =
- invokeGetColumnOrigins(
- child,
- inputRef.getIndex());
+ mq.getColumnOrigins(input, inputRef.getIndex());
if (inputSet != null) {
set.addAll(inputSet);
}
@@ -171,34 +151,24 @@ public class RelMdColumnOrigins {
return createDerivedColumnOrigins(set);
}
- public Set<RelColumnOrigin> getColumnOrigins(
- Filter rel,
- int iOutputColumn) {
- return invokeGetColumnOrigins(
- rel.getInput(),
- iOutputColumn);
+ public Set<RelColumnOrigin> getColumnOrigins(Filter rel,
+ RelMetadataQuery mq, int iOutputColumn) {
+ return mq.getColumnOrigins(rel.getInput(), iOutputColumn);
}
- public Set<RelColumnOrigin> getColumnOrigins(
- Sort rel,
+ public Set<RelColumnOrigin> getColumnOrigins(Sort rel, RelMetadataQuery mq,
int iOutputColumn) {
- return invokeGetColumnOrigins(
- rel.getInput(),
- iOutputColumn);
+ return mq.getColumnOrigins(rel.getInput(), iOutputColumn);
}
- public Set<RelColumnOrigin> getColumnOrigins(
- Exchange rel,
- int iOutputColumn) {
- return invokeGetColumnOrigins(
- rel.getInput(),
- iOutputColumn);
+ public Set<RelColumnOrigin> getColumnOrigins(Exchange rel,
+ RelMetadataQuery mq, int iOutputColumn) {
+ return mq.getColumnOrigins(rel.getInput(), iOutputColumn);
}
- public Set<RelColumnOrigin> getColumnOrigins(
- TableFunctionScan rel,
- int iOutputColumn) {
- Set<RelColumnOrigin> set = new HashSet<RelColumnOrigin>();
+ public Set<RelColumnOrigin> getColumnOrigins(TableFunctionScan rel,
+ RelMetadataQuery mq, int iOutputColumn) {
+ final Set<RelColumnOrigin> set = new HashSet<>();
Set<RelColumnMapping> mappings = rel.getColumnMappings();
if (mappings == null) {
if (rel.getInputs().size() > 0) {
@@ -216,10 +186,9 @@ public class RelMdColumnOrigins {
if (mapping.iOutputColumn != iOutputColumn) {
continue;
}
- Set<RelColumnOrigin> origins =
- invokeGetColumnOrigins(
- rel.getInputs().get(mapping.iInputRel),
- mapping.iInputColumn);
+ final RelNode input = rel.getInputs().get(mapping.iInputRel);
+ final int column = mapping.iInputColumn;
+ Set<RelColumnOrigin> origins = mq.getColumnOrigins(input, column);
if (origins == null) {
return null;
}
@@ -232,9 +201,8 @@ public class RelMdColumnOrigins {
}
// Catch-all rule when none of the others apply.
- public Set<RelColumnOrigin> getColumnOrigins(
- RelNode rel,
- int iOutputColumn) {
+ public Set<RelColumnOrigin> getColumnOrigins(RelNode rel,
+ RelMetadataQuery mq, int iOutputColumn) {
// NOTE jvs 28-Mar-2006: We may get this wrong for a physical table
// expression which supports projections. In that case,
// it's up to the plugin writer to override with the
@@ -245,7 +213,7 @@ public class RelMdColumnOrigins {
return null;
}
- Set<RelColumnOrigin> set = new HashSet<RelColumnOrigin>();
+ final Set<RelColumnOrigin> set = new HashSet<>();
RelOptTable table = rel.getTable();
if (table == null) {
@@ -267,18 +235,12 @@ public class RelMdColumnOrigins {
return set;
}
- protected Set<RelColumnOrigin> invokeGetColumnOrigins(
- RelNode rel,
- int iOutputColumn) {
- return RelMetadataQuery.getColumnOrigins(rel, iOutputColumn);
- }
-
private Set<RelColumnOrigin> createDerivedColumnOrigins(
Set<RelColumnOrigin> inputSet) {
if (inputSet == null) {
return null;
}
- Set<RelColumnOrigin> set = new HashSet<RelColumnOrigin>();
+ final Set<RelColumnOrigin> set = new HashSet<>();
for (RelColumnOrigin rco : inputSet) {
RelColumnOrigin derived =
new RelColumnOrigin(