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(
