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/21 23:39:07 UTC
[30/50] [abbrv] 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/metadata/RelMdUniqueKeys.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdUniqueKeys.java b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdUniqueKeys.java
index d77ca13..cb1de64 100644
--- a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdUniqueKeys.java
+++ b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdUniqueKeys.java
@@ -54,20 +54,23 @@ public class RelMdUniqueKeys {
//~ Methods ----------------------------------------------------------------
- public Set<ImmutableBitSet> getUniqueKeys(Filter rel, boolean ignoreNulls) {
- return RelMetadataQuery.getUniqueKeys(rel.getInput(), ignoreNulls);
+ public Set<ImmutableBitSet> getUniqueKeys(Filter rel, RelMetadataQuery mq,
+ boolean ignoreNulls) {
+ return mq.getUniqueKeys(rel.getInput(), ignoreNulls);
}
- public Set<ImmutableBitSet> getUniqueKeys(Sort rel, boolean ignoreNulls) {
- return RelMetadataQuery.getUniqueKeys(rel.getInput(), ignoreNulls);
+ public Set<ImmutableBitSet> getUniqueKeys(Sort rel, RelMetadataQuery mq,
+ boolean ignoreNulls) {
+ return mq.getUniqueKeys(rel.getInput(), ignoreNulls);
}
- public Set<ImmutableBitSet> getUniqueKeys(Correlate rel,
+ public Set<ImmutableBitSet> getUniqueKeys(Correlate rel, RelMetadataQuery mq,
boolean ignoreNulls) {
- return RelMetadataQuery.getUniqueKeys(rel.getLeft(), ignoreNulls);
+ return mq.getUniqueKeys(rel.getLeft(), ignoreNulls);
}
- public Set<ImmutableBitSet> getUniqueKeys(Project rel, boolean ignoreNulls) {
+ public Set<ImmutableBitSet> getUniqueKeys(Project rel, RelMetadataQuery mq,
+ boolean ignoreNulls) {
// LogicalProject maps a set of rows to a different set;
// Without knowledge of the mapping function(whether it
// preserves uniqueness), it is only safe to derive uniqueness
@@ -75,11 +78,9 @@ public class RelMdUniqueKeys {
//
// Further more, the unique bitset coming from the child needs
// to be mapped to match the output of the project.
- Map<Integer, Integer> mapInToOutPos = new HashMap<>();
-
- List<RexNode> projExprs = rel.getProjects();
-
- Set<ImmutableBitSet> projUniqueKeySet = new HashSet<>();
+ final Map<Integer, Integer> mapInToOutPos = new HashMap<>();
+ final List<RexNode> projExprs = rel.getProjects();
+ final Set<ImmutableBitSet> projUniqueKeySet = new HashSet<>();
// Build an input to output position map.
for (int i = 0; i < projExprs.size(); i++) {
@@ -96,7 +97,7 @@ public class RelMdUniqueKeys {
}
Set<ImmutableBitSet> childUniqueKeySet =
- RelMetadataQuery.getUniqueKeys(rel.getInput(), ignoreNulls);
+ mq.getUniqueKeys(rel.getInput(), ignoreNulls);
if (childUniqueKeySet != null) {
// Now add to the projUniqueKeySet the child keys that are fully
@@ -123,7 +124,8 @@ public class RelMdUniqueKeys {
return projUniqueKeySet;
}
- public Set<ImmutableBitSet> getUniqueKeys(Join rel, boolean ignoreNulls) {
+ public Set<ImmutableBitSet> getUniqueKeys(Join rel, RelMetadataQuery mq,
+ boolean ignoreNulls) {
final RelNode left = rel.getLeft();
final RelNode right = rel.getRight();
@@ -136,13 +138,11 @@ public class RelMdUniqueKeys {
// that is undesirable, use RelMetadataQuery.areColumnsUnique() as
// an alternative way of getting unique key information.
- Set<ImmutableBitSet> retSet = new HashSet<>();
- Set<ImmutableBitSet> leftSet =
- RelMetadataQuery.getUniqueKeys(left, ignoreNulls);
+ final Set<ImmutableBitSet> retSet = new HashSet<>();
+ final Set<ImmutableBitSet> leftSet = mq.getUniqueKeys(left, ignoreNulls);
Set<ImmutableBitSet> rightSet = null;
- Set<ImmutableBitSet> tmpRightSet =
- RelMetadataQuery.getUniqueKeys(right, ignoreNulls);
+ final Set<ImmutableBitSet> tmpRightSet = mq.getUniqueKeys(right, ignoreNulls);
int nFieldsOnLeft = left.getRowType().getFieldCount();
if (tmpRightSet != null) {
@@ -169,12 +169,10 @@ public class RelMdUniqueKeys {
// determine if either or both the LHS and RHS are unique on the
// equijoin columns
- Boolean leftUnique =
- RelMetadataQuery.areColumnsUnique(left, joinInfo.leftSet(),
- ignoreNulls);
- Boolean rightUnique =
- RelMetadataQuery.areColumnsUnique(right, joinInfo.rightSet(),
- ignoreNulls);
+ final Boolean leftUnique =
+ mq.areColumnsUnique(left, joinInfo.leftSet(), ignoreNulls);
+ final Boolean rightUnique =
+ mq.areColumnsUnique(right, joinInfo.rightSet(), ignoreNulls);
// if the right hand side is unique on its equijoin columns, then we can
// add the unique keys from left if the left hand side is not null
@@ -197,19 +195,20 @@ public class RelMdUniqueKeys {
return retSet;
}
- public Set<ImmutableBitSet> getUniqueKeys(SemiJoin rel, boolean ignoreNulls) {
+ public Set<ImmutableBitSet> getUniqueKeys(SemiJoin rel, RelMetadataQuery mq,
+ boolean ignoreNulls) {
// only return the unique keys from the LHS since a semijoin only
// returns the LHS
- return RelMetadataQuery.getUniqueKeys(rel.getLeft(), ignoreNulls);
+ return mq.getUniqueKeys(rel.getLeft(), ignoreNulls);
}
- public Set<ImmutableBitSet> getUniqueKeys(Aggregate rel,
+ public Set<ImmutableBitSet> getUniqueKeys(Aggregate rel, RelMetadataQuery mq,
boolean ignoreNulls) {
// group by keys form a unique key
return ImmutableSet.of(rel.getGroupSet());
}
- public Set<ImmutableBitSet> getUniqueKeys(SetOp rel,
+ public Set<ImmutableBitSet> getUniqueKeys(SetOp rel, RelMetadataQuery mq,
boolean ignoreNulls) {
if (!rel.all) {
return ImmutableSet.of(
@@ -219,7 +218,8 @@ public class RelMdUniqueKeys {
}
// Catch-all rule when none of the others apply.
- public Set<ImmutableBitSet> getUniqueKeys(RelNode rel, boolean ignoreNulls) {
+ public Set<ImmutableBitSet> getUniqueKeys(RelNode rel, RelMetadataQuery mq,
+ boolean ignoreNulls) {
// no information available
return null;
}
http://git-wip-us.apache.org/repos/asf/calcite/blob/cabdcf44/core/src/main/java/org/apache/calcite/rel/metadata/RelMdUtil.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdUtil.java b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdUtil.java
index dc1ea3e..5435979 100644
--- a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdUtil.java
+++ b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdUtil.java
@@ -26,11 +26,14 @@ import org.apache.calcite.rel.core.JoinRelType;
import org.apache.calcite.rel.core.Minus;
import org.apache.calcite.rel.core.Project;
import org.apache.calcite.rel.core.SemiJoin;
+import org.apache.calcite.rel.core.Union;
import org.apache.calcite.rex.RexBuilder;
import org.apache.calcite.rex.RexCall;
import org.apache.calcite.rex.RexInputRef;
import org.apache.calcite.rex.RexLiteral;
+import org.apache.calcite.rex.RexLocalRef;
import org.apache.calcite.rex.RexNode;
+import org.apache.calcite.rex.RexProgram;
import org.apache.calcite.rex.RexUtil;
import org.apache.calcite.rex.RexVisitorImpl;
import org.apache.calcite.sql.SqlFunction;
@@ -77,13 +80,11 @@ public class RelMdUtil {
* @param rel the semijoin of interest
* @return constructed rexnode
*/
- public static RexNode makeSemiJoinSelectivityRexNode(SemiJoin rel) {
+ public static RexNode makeSemiJoinSelectivityRexNode(RelMetadataQuery mq,
+ SemiJoin rel) {
RexBuilder rexBuilder = rel.getCluster().getRexBuilder();
double selectivity =
- computeSemiJoinSelectivity(
- rel.getLeft(),
- rel.getRight(),
- rel);
+ computeSemiJoinSelectivity(mq, rel.getLeft(), rel.getRight(), rel);
RexNode selec =
rexBuilder.makeApproxLiteral(new BigDecimal(selectivity));
return rexBuilder.makeCall(ARTIFICIAL_SELECTIVITY_FUNC, selec);
@@ -113,12 +114,10 @@ public class RelMdUtil {
* @param rel semijoin rel
* @return calculated selectivity
*/
- public static double computeSemiJoinSelectivity(SemiJoin rel) {
- return computeSemiJoinSelectivity(
- rel.getLeft(),
- rel.getRight(),
- rel.getLeftKeys(),
- rel.getRightKeys());
+ public static double computeSemiJoinSelectivity(RelMetadataQuery mq,
+ SemiJoin rel) {
+ return computeSemiJoinSelectivity(mq, rel.getLeft(), rel.getRight(),
+ rel.getLeftKeys(), rel.getRightKeys());
}
/**
@@ -132,14 +131,9 @@ public class RelMdUtil {
* @param rel semijoin rel
* @return calculated selectivity
*/
- public static double computeSemiJoinSelectivity(
- RelNode factRel,
- RelNode dimRel,
- SemiJoin rel) {
- return computeSemiJoinSelectivity(
- factRel,
- dimRel,
- rel.getLeftKeys(),
+ public static double computeSemiJoinSelectivity(RelMetadataQuery mq,
+ RelNode factRel, RelNode dimRel, SemiJoin rel) {
+ return computeSemiJoinSelectivity(mq, factRel, dimRel, rel.getLeftKeys(),
rel.getRightKeys());
}
@@ -155,10 +149,8 @@ public class RelMdUtil {
* @param dimKeyList RHS keys used in the filter
* @return calculated selectivity
*/
- public static double computeSemiJoinSelectivity(
- RelNode factRel,
- RelNode dimRel,
- List<Integer> factKeyList,
+ public static double computeSemiJoinSelectivity(RelMetadataQuery mq,
+ RelNode factRel, RelNode dimRel, List<Integer> factKeyList,
List<Integer> dimKeyList) {
ImmutableBitSet.Builder factKeys = ImmutableBitSet.builder();
for (int factCol : factKeyList) {
@@ -170,20 +162,19 @@ public class RelMdUtil {
}
final ImmutableBitSet dimKeys = dimKeyBuilder.build();
- Double factPop =
- RelMetadataQuery.getPopulationSize(factRel, factKeys.build());
+ Double factPop = mq.getPopulationSize(factRel, factKeys.build());
if (factPop == null) {
// use the dimension population if the fact population is
// unavailable; since we're filtering the fact table, that's
// the population we ideally want to use
- factPop = RelMetadataQuery.getPopulationSize(dimRel, dimKeys);
+ factPop = mq.getPopulationSize(dimRel, dimKeys);
}
// if cardinality and population are available, use them; otherwise
// use percentage original rows
Double selectivity;
Double dimCard =
- RelMetadataQuery.getDistinctRowCount(
+ mq.getDistinctRowCount(
dimRel,
dimKeys,
null);
@@ -194,7 +185,7 @@ public class RelMdUtil {
}
selectivity = dimCard / factPop;
} else {
- selectivity = RelMetadataQuery.getPercentageOriginalRows(dimRel);
+ selectivity = mq.getPercentageOriginalRows(dimRel);
}
if (selectivity == null) {
@@ -220,26 +211,24 @@ public class RelMdUtil {
* @return true if bit mask represents a unique column set; false if not (or
* if no metadata is available)
*/
- public static boolean areColumnsDefinitelyUnique(
- RelNode rel,
- ImmutableBitSet colMask) {
- Boolean b = RelMetadataQuery.areColumnsUnique(rel, colMask, false);
+ public static boolean areColumnsDefinitelyUnique(RelMetadataQuery mq,
+ RelNode rel, ImmutableBitSet colMask) {
+ Boolean b = mq.areColumnsUnique(rel, colMask, false);
return b != null && b;
}
- public static Boolean areColumnsUnique(
- RelNode rel,
+ public static Boolean areColumnsUnique(RelMetadataQuery mq, RelNode rel,
List<RexInputRef> columnRefs) {
ImmutableBitSet.Builder colMask = ImmutableBitSet.builder();
for (RexInputRef columnRef : columnRefs) {
colMask.set(columnRef.getIndex());
}
- return RelMetadataQuery.areColumnsUnique(rel, colMask.build());
+ return mq.areColumnsUnique(rel, colMask.build());
}
- public static boolean areColumnsDefinitelyUnique(RelNode rel,
- List<RexInputRef> columnRefs) {
- Boolean b = areColumnsUnique(rel, columnRefs);
+ public static boolean areColumnsDefinitelyUnique(RelMetadataQuery mq,
+ RelNode rel, List<RexInputRef> columnRefs) {
+ Boolean b = areColumnsUnique(mq, rel, columnRefs);
return b != null && b;
}
@@ -255,31 +244,29 @@ public class RelMdUtil {
* @return true if bit mask represents a unique column set; false if not (or
* if no metadata is available)
*/
- public static boolean areColumnsDefinitelyUniqueWhenNullsFiltered(RelNode rel,
- ImmutableBitSet colMask) {
- Boolean b = RelMetadataQuery.areColumnsUnique(rel, colMask, true);
+ public static boolean areColumnsDefinitelyUniqueWhenNullsFiltered(
+ RelMetadataQuery mq, RelNode rel, ImmutableBitSet colMask) {
+ Boolean b = mq.areColumnsUnique(rel, colMask, true);
if (b == null) {
return false;
}
return b;
}
- public static Boolean areColumnsUniqueWhenNullsFiltered(
- RelNode rel,
- List<RexInputRef> columnRefs) {
+ public static Boolean areColumnsUniqueWhenNullsFiltered(RelMetadataQuery mq,
+ RelNode rel, List<RexInputRef> columnRefs) {
ImmutableBitSet.Builder colMask = ImmutableBitSet.builder();
for (RexInputRef columnRef : columnRefs) {
colMask.set(columnRef.getIndex());
}
- return RelMetadataQuery.areColumnsUnique(rel, colMask.build(), true);
+ return mq.areColumnsUnique(rel, colMask.build(), true);
}
public static boolean areColumnsDefinitelyUniqueWhenNullsFiltered(
- RelNode rel,
- List<RexInputRef> columnRefs) {
- Boolean b = areColumnsUniqueWhenNullsFiltered(rel, columnRefs);
+ RelMetadataQuery mq, RelNode rel, List<RexInputRef> columnRefs) {
+ Boolean b = areColumnsUniqueWhenNullsFiltered(mq, rel, columnRefs);
if (b == null) {
return false;
}
@@ -476,9 +463,9 @@ public class RelMdUtil {
RexBuilder rexBuilder,
RexNode pred1,
RexNode pred2) {
- List<RexNode> list1 = RelOptUtil.conjunctions(pred1);
- List<RexNode> list2 = RelOptUtil.conjunctions(pred2);
- List<RexNode> minusList = new ArrayList<>();
+ final List<RexNode> list1 = RelOptUtil.conjunctions(pred1);
+ final List<RexNode> list2 = RelOptUtil.conjunctions(pred2);
+ final List<RexNode> minusList = new ArrayList<>();
for (RexNode rex1 : list1) {
boolean add = true;
@@ -550,14 +537,15 @@ public class RelMdUtil {
/**
* Computes the cardinality of a particular expression from the projection
- * list
+ * list.
*
* @param rel RelNode corresponding to the project
* @param expr projection expression
* @return cardinality
*/
- public static Double cardOfProjExpr(Project rel, RexNode expr) {
- return expr.accept(new CardOfProjExpr(rel));
+ public static Double cardOfProjExpr(RelMetadataQuery mq, Project rel,
+ RexNode expr) {
+ return expr.accept(new CardOfProjExpr(mq, rel));
}
/**
@@ -567,9 +555,8 @@ public class RelMdUtil {
* @param groupKey keys to compute the population for
* @return computed population size
*/
- public static Double getJoinPopulationSize(
- RelNode joinRel,
- ImmutableBitSet groupKey) {
+ public static Double getJoinPopulationSize(RelMetadataQuery mq,
+ RelNode joinRel, ImmutableBitSet groupKey) {
ImmutableBitSet.Builder leftMask = ImmutableBitSet.builder();
ImmutableBitSet.Builder rightMask = ImmutableBitSet.builder();
RelNode left = joinRel.getInputs().get(0);
@@ -577,23 +564,14 @@ public class RelMdUtil {
// separate the mask into masks for the left and right
RelMdUtil.setLeftRightBitmaps(
- groupKey,
- leftMask,
- rightMask,
- left.getRowType().getFieldCount());
+ groupKey, leftMask, rightMask, left.getRowType().getFieldCount());
Double population =
NumberUtil.multiply(
- RelMetadataQuery.getPopulationSize(
- left,
- leftMask.build()),
- RelMetadataQuery.getPopulationSize(
- right,
- rightMask.build()));
+ mq.getPopulationSize(left, leftMask.build()),
+ mq.getPopulationSize(right, rightMask.build()));
- return RelMdUtil.numDistinctVals(
- population,
- RelMetadataQuery.getRowCount(joinRel));
+ return numDistinctVals(population, mq.getRowCount(joinRel));
}
/**
@@ -608,12 +586,9 @@ public class RelMdUtil {
* otherwise use <code>left NDV * right NDV</code>.
* @return number of distinct rows
*/
- public static Double getJoinDistinctRowCount(
- RelNode joinRel,
- JoinRelType joinType,
- ImmutableBitSet groupKey,
- RexNode predicate,
- boolean useMaxNdv) {
+ public static Double getJoinDistinctRowCount(RelMetadataQuery mq,
+ RelNode joinRel, JoinRelType joinType, ImmutableBitSet groupKey,
+ RexNode predicate, boolean useMaxNdv) {
Double distRowCount;
ImmutableBitSet.Builder leftMask = ImmutableBitSet.builder();
ImmutableBitSet.Builder rightMask = ImmutableBitSet.builder();
@@ -630,10 +605,10 @@ public class RelMdUtil {
RexNode leftPred = null;
RexNode rightPred = null;
if (predicate != null) {
- List<RexNode> leftFilters = new ArrayList<>();
- List<RexNode> rightFilters = new ArrayList<>();
- List<RexNode> joinFilters = new ArrayList<>();
- List<RexNode> predList = RelOptUtil.conjunctions(predicate);
+ final List<RexNode> leftFilters = new ArrayList<>();
+ final List<RexNode> rightFilters = new ArrayList<>();
+ final List<RexNode> joinFilters = new ArrayList<>();
+ final List<RexNode> predList = RelOptUtil.conjunctions(predicate);
RelOptUtil.classifyFilters(
joinRel,
@@ -655,35 +630,35 @@ public class RelMdUtil {
if (useMaxNdv) {
distRowCount = Math.max(
- RelMetadataQuery.getDistinctRowCount(left, leftMask.build(),
- leftPred),
- RelMetadataQuery.getDistinctRowCount(right, rightMask.build(),
- rightPred));
+ mq.getDistinctRowCount(left, leftMask.build(), leftPred),
+ mq.getDistinctRowCount(right, rightMask.build(), rightPred));
} else {
distRowCount =
NumberUtil.multiply(
- RelMetadataQuery.getDistinctRowCount(
- left,
- leftMask.build(),
- leftPred),
- RelMetadataQuery.getDistinctRowCount(
- right,
- rightMask.build(),
- rightPred));
+ mq.getDistinctRowCount(left, leftMask.build(), leftPred),
+ mq.getDistinctRowCount(right, rightMask.build(), rightPred));
}
- return RelMdUtil.numDistinctVals(
- distRowCount,
- RelMetadataQuery.getRowCount(joinRel));
+ return RelMdUtil.numDistinctVals(distRowCount, mq.getRowCount(joinRel));
+ }
+
+ /** Returns an estimate of the number of rows returned by a {@link Union}
+ * (before duplicates are eliminated). */
+ public static double getUnionAllRowCount(RelMetadataQuery mq, Union rel) {
+ double rowCount = 0;
+ for (RelNode input : rel.getInputs()) {
+ rowCount += mq.getRowCount(input);
+ }
+ return rowCount;
}
/** Returns an estimate of the number of rows returned by a {@link Minus}. */
- public static double getMinusRowCount(Minus minus) {
+ public static double getMinusRowCount(RelMetadataQuery mq, Minus minus) {
// REVIEW jvs 30-May-2005: I just pulled this out of a hat.
final List<RelNode> inputs = minus.getInputs();
- double dRows = RelMetadataQuery.getRowCount(inputs.get(0));
+ double dRows = mq.getRowCount(inputs.get(0));
for (int i = 1; i < inputs.size(); i++) {
- dRows -= 0.5 * RelMetadataQuery.getRowCount(inputs.get(i));
+ dRows -= 0.5 * mq.getRowCount(inputs.get(i));
}
if (dRows < 0) {
dRows = 0;
@@ -692,16 +667,17 @@ public class RelMdUtil {
}
/** Returns an estimate of the number of rows returned by a {@link Join}. */
- public static Double getJoinRowCount(Join join, RexNode condition) {
+ public static Double getJoinRowCount(RelMetadataQuery mq, Join join,
+ RexNode condition) {
// Row count estimates of 0 will be rounded up to 1.
// So, use maxRowCount where the product is very small.
- final Double left = RelMetadataQuery.getRowCount(join.getLeft());
- final Double right = RelMetadataQuery.getRowCount(join.getRight());
+ final Double left = mq.getRowCount(join.getLeft());
+ final Double right = mq.getRowCount(join.getRight());
if (left == null || right == null) {
return null;
}
if (left <= 1D || right <= 1D) {
- Double max = RelMetadataQuery.getMaxRowCount(join);
+ Double max = mq.getMaxRowCount(join);
if (max != null && max <= 1D) {
return max;
}
@@ -709,30 +685,51 @@ public class RelMdUtil {
double product = left * right;
// TODO: correlation factor
- return product * RelMetadataQuery.getSelectivity(join, condition);
+ return product * mq.getSelectivity(join, condition);
}
/** Returns an estimate of the number of rows returned by a
* {@link SemiJoin}. */
- public static Double getSemiJoinRowCount(RelNode left, RelNode right,
- JoinRelType joinType, RexNode condition) {
+ public static Double getSemiJoinRowCount(RelMetadataQuery mq, RelNode left,
+ RelNode right, JoinRelType joinType, RexNode condition) {
// TODO: correlation factor
- final Double leftCount = RelMetadataQuery.getRowCount(left);
+ final Double leftCount = mq.getRowCount(left);
if (leftCount == null) {
return null;
}
return leftCount * RexUtil.getSelectivity(condition);
}
+ public static double estimateFilteredRows(RelNode child, RexProgram program,
+ RelMetadataQuery mq) {
+ // 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, mq);
+ }
+
+ public static double estimateFilteredRows(RelNode child, RexNode condition,
+ RelMetadataQuery mq) {
+ return mq.getRowCount(child)
+ * mq.getSelectivity(child, condition);
+ }
+
//~ Inner Classes ----------------------------------------------------------
/** Visitor that walks over a scalar expression and computes the
* cardinality of its result. */
private static class CardOfProjExpr extends RexVisitorImpl<Double> {
+ private final RelMetadataQuery mq;
private Project rel;
- public CardOfProjExpr(Project rel) {
+ public CardOfProjExpr(RelMetadataQuery mq, Project rel) {
super(true);
+ this.mq = mq;
this.rel = rel;
}
@@ -740,57 +737,45 @@ public class RelMdUtil {
int index = var.getIndex();
ImmutableBitSet col = ImmutableBitSet.of(index);
Double distinctRowCount =
- RelMetadataQuery.getDistinctRowCount(
- rel.getInput(),
- col,
- null);
+ mq.getDistinctRowCount(rel.getInput(), col, null);
if (distinctRowCount == null) {
return null;
} else {
- return RelMdUtil.numDistinctVals(
- distinctRowCount,
- RelMetadataQuery.getRowCount(rel));
+ return numDistinctVals(distinctRowCount, mq.getRowCount(rel));
}
}
public Double visitLiteral(RexLiteral literal) {
- return RelMdUtil.numDistinctVals(
- 1.0,
- RelMetadataQuery.getRowCount(rel));
+ return numDistinctVals(1.0, mq.getRowCount(rel));
}
public Double visitCall(RexCall call) {
Double distinctRowCount;
- Double rowCount = RelMetadataQuery.getRowCount(rel);
+ Double rowCount = mq.getRowCount(rel);
if (call.isA(SqlKind.MINUS_PREFIX)) {
- distinctRowCount =
- cardOfProjExpr(rel, call.getOperands().get(0));
+ distinctRowCount = cardOfProjExpr(mq, rel, call.getOperands().get(0));
} else if (call.isA(ImmutableList.of(SqlKind.PLUS, SqlKind.MINUS))) {
- Double card0 = cardOfProjExpr(rel, call.getOperands().get(0));
+ Double card0 = cardOfProjExpr(mq, rel, call.getOperands().get(0));
if (card0 == null) {
return null;
}
- Double card1 = cardOfProjExpr(rel, call.getOperands().get(1));
+ Double card1 = cardOfProjExpr(mq, rel, call.getOperands().get(1));
if (card1 == null) {
return null;
}
distinctRowCount = Math.max(card0, card1);
- } else if (call.isA(
- ImmutableList.of(SqlKind.TIMES, SqlKind.DIVIDE))) {
+ } else if (call.isA(ImmutableList.of(SqlKind.TIMES, SqlKind.DIVIDE))) {
distinctRowCount =
NumberUtil.multiply(
- cardOfProjExpr(rel, call.getOperands().get(0)),
- cardOfProjExpr(rel, call.getOperands().get(1)));
+ cardOfProjExpr(mq, rel, call.getOperands().get(0)),
+ cardOfProjExpr(mq, rel, call.getOperands().get(1)));
// TODO zfong 6/21/06 - Broadbase has code to handle date
// functions like year, month, day; E.g., cardinality of Month()
// is 12
} else {
if (call.getOperands().size() == 1) {
- distinctRowCount =
- cardOfProjExpr(
- rel,
- call.getOperands().get(0));
+ distinctRowCount = cardOfProjExpr(mq, rel, call.getOperands().get(0));
} else {
distinctRowCount = rowCount / 10;
}
@@ -805,13 +790,11 @@ public class RelMdUtil {
*
* <p>If this is the case, it is safe to push down a
* {@link org.apache.calcite.rel.core.Sort} with limit and optional offset. */
- public static boolean checkInputForCollationAndLimit(RelNode input,
- RelCollation collation, RexNode offset, RexNode fetch) {
+ public static boolean checkInputForCollationAndLimit(RelMetadataQuery mq,
+ RelNode input, RelCollation collation, RexNode offset, RexNode fetch) {
// Check if the input is already sorted
- ImmutableList<RelCollation> inputCollations =
- RelMetadataQuery.collations(input);
boolean alreadySorted = false;
- for (RelCollation inputCollation : inputCollations) {
+ for (RelCollation inputCollation : mq.collations(input)) {
if (inputCollation.satisfies(collation)) {
alreadySorted = true;
break;
@@ -819,7 +802,7 @@ public class RelMdUtil {
}
// Check if we are not reducing the number of tuples
boolean alreadySmaller = true;
- final Double rowCount = RelMetadataQuery.getMaxRowCount(input);
+ final Double rowCount = mq.getMaxRowCount(input);
if (rowCount != null && fetch != null) {
final int offsetVal = offset == null ? 0 : RexLiteral.intValue(offset);
final int limit = RexLiteral.intValue(fetch);
http://git-wip-us.apache.org/repos/asf/calcite/blob/cabdcf44/core/src/main/java/org/apache/calcite/rel/metadata/RelMetadataProvider.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rel/metadata/RelMetadataProvider.java b/core/src/main/java/org/apache/calcite/rel/metadata/RelMetadataProvider.java
index 0e1bf4f..a2fd272 100644
--- a/core/src/main/java/org/apache/calcite/rel/metadata/RelMetadataProvider.java
+++ b/core/src/main/java/org/apache/calcite/rel/metadata/RelMetadataProvider.java
@@ -18,8 +18,6 @@ package org.apache.calcite.rel.metadata;
import org.apache.calcite.rel.RelNode;
-import com.google.common.base.Function;
-
/**
* RelMetadataProvider defines an interface for obtaining metadata about
* relational expressions. This interface is weakly-typed and is not intended to
@@ -56,9 +54,9 @@ public interface RelMetadataProvider {
* @return Function that will field a metadata instance; or null if this
* provider cannot supply metadata of this type
*/
- Function<RelNode, Metadata> apply(
- Class<? extends RelNode> relClass,
- Class<? extends Metadata> metadataClass);
+ <M extends Metadata> UnboundMetadata<M>
+ apply(Class<? extends RelNode> relClass,
+ Class<? extends M> metadataClass);
}
// End RelMetadataProvider.java
http://git-wip-us.apache.org/repos/asf/calcite/blob/cabdcf44/core/src/main/java/org/apache/calcite/rel/metadata/RelMetadataQuery.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rel/metadata/RelMetadataQuery.java b/core/src/main/java/org/apache/calcite/rel/metadata/RelMetadataQuery.java
index 44d0724..f4eb748 100644
--- a/core/src/main/java/org/apache/calcite/rel/metadata/RelMetadataQuery.java
+++ b/core/src/main/java/org/apache/calcite/rel/metadata/RelMetadataQuery.java
@@ -30,6 +30,7 @@ import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import java.util.Collections;
+import java.util.HashSet;
import java.util.List;
import java.util.Set;
@@ -64,14 +65,26 @@ import java.util.Set;
* custom providers for the standard queries in order to handle additional
* relational expressions (either logical or physical). In either case, the
* process is the same: write a reflective provider and chain it on to an
- * instance of {@link DefaultRelMetadataProvider}, prepending it to the default
+ * instance of {@link DefaultRelMetadataProvider}, pre-pending it to the default
* providers. Then supply that instance to the planner via the appropriate
* plugin mechanism.
*/
public abstract class RelMetadataQuery {
+ /** Set of active metadata queries. */
+ public final Set<List> set = new HashSet<>();
+
//~ Methods ----------------------------------------------------------------
/**
+ * Returns an instance of RelMetadataQuery. It ensures that cycles do not
+ * occur while computing metadata.
+ */
+ public static RelMetadataQuery instance() {
+ return new RelMetadataQuery() {
+ };
+ }
+
+ /**
* Returns the
* {@link BuiltInMetadata.RowCount#getRowCount()}
* statistic.
@@ -80,9 +93,9 @@ public abstract class RelMetadataQuery {
* @return estimated row count, or null if no reliable estimate can be
* determined
*/
- public static Double getRowCount(RelNode rel) {
+ public Double getRowCount(RelNode rel) {
final BuiltInMetadata.RowCount metadata =
- rel.metadata(BuiltInMetadata.RowCount.class);
+ rel.metadata(BuiltInMetadata.RowCount.class, this);
Double result = metadata.getRowCount();
return validateResult(result);
}
@@ -95,9 +108,9 @@ public abstract class RelMetadataQuery {
* @param rel the relational expression
* @return max row count
*/
- public static Double getMaxRowCount(RelNode rel) {
+ public Double getMaxRowCount(RelNode rel) {
final BuiltInMetadata.MaxRowCount metadata =
- rel.metadata(BuiltInMetadata.MaxRowCount.class);
+ rel.metadata(BuiltInMetadata.MaxRowCount.class, this);
return metadata.getMaxRowCount();
}
@@ -109,9 +122,9 @@ public abstract class RelMetadataQuery {
* @param rel the relational expression
* @return estimated cost, or null if no reliable estimate can be determined
*/
- public static RelOptCost getCumulativeCost(RelNode rel) {
+ public RelOptCost getCumulativeCost(RelNode rel) {
final BuiltInMetadata.CumulativeCost metadata =
- rel.metadata(BuiltInMetadata.CumulativeCost.class);
+ rel.metadata(BuiltInMetadata.CumulativeCost.class, this);
return metadata.getCumulativeCost();
}
@@ -123,9 +136,9 @@ public abstract class RelMetadataQuery {
* @param rel the relational expression
* @return estimated cost, or null if no reliable estimate can be determined
*/
- public static RelOptCost getNonCumulativeCost(RelNode rel) {
+ public RelOptCost getNonCumulativeCost(RelNode rel) {
final BuiltInMetadata.NonCumulativeCost metadata =
- rel.metadata(BuiltInMetadata.NonCumulativeCost.class);
+ rel.metadata(BuiltInMetadata.NonCumulativeCost.class, this);
return metadata.getNonCumulativeCost();
}
@@ -138,9 +151,9 @@ public abstract class RelMetadataQuery {
* @return estimated percentage (between 0.0 and 1.0), or null if no
* reliable estimate can be determined
*/
- public static Double getPercentageOriginalRows(RelNode rel) {
+ public Double getPercentageOriginalRows(RelNode rel) {
final BuiltInMetadata.PercentageOriginalRows metadata =
- rel.metadata(BuiltInMetadata.PercentageOriginalRows.class);
+ rel.metadata(BuiltInMetadata.PercentageOriginalRows.class, this);
Double result = metadata.getPercentageOriginalRows();
assert isPercentage(result, true);
return result;
@@ -157,9 +170,9 @@ public abstract class RelMetadataQuery {
* determined (whereas empty set indicates definitely no origin columns at
* all)
*/
- public static Set<RelColumnOrigin> getColumnOrigins(RelNode rel, int column) {
+ public Set<RelColumnOrigin> getColumnOrigins(RelNode rel, int column) {
final BuiltInMetadata.ColumnOrigin metadata =
- rel.metadata(BuiltInMetadata.ColumnOrigin.class);
+ rel.metadata(BuiltInMetadata.ColumnOrigin.class, this);
return metadata.getColumnOrigins(column);
}
@@ -176,7 +189,7 @@ public abstract class RelMetadataQuery {
* @return the origin of a column provided it's a simple column; otherwise,
* returns null
*/
- public static RelColumnOrigin getColumnOrigin(RelNode rel, int column) {
+ public RelColumnOrigin getColumnOrigin(RelNode rel, int column) {
final Set<RelColumnOrigin> origins = getColumnOrigins(rel, column);
if (origins == null || origins.size() != 1) {
return null;
@@ -193,12 +206,11 @@ public abstract class RelMetadataQuery {
*
* @return the table, if the RelNode is a simple table; otherwise null
*/
- public static RelOptTable getTableOrigin(RelNode rel) {
+ public RelOptTable getTableOrigin(RelNode rel) {
// Determine the simple origin of the first column in the
// RelNode. If it's simple, then that means that the underlying
// table is also simple, even if the column itself is derived.
- final Set<RelColumnOrigin> colOrigins =
- getColumnOrigins(rel, 0);
+ final Set<RelColumnOrigin> colOrigins = getColumnOrigins(rel, 0);
if (colOrigins == null || colOrigins.size() == 0) {
return null;
}
@@ -212,13 +224,13 @@ public abstract class RelMetadataQuery {
*
* @param rel the relational expression
* @param predicate predicate whose selectivity is to be estimated against
- * rel's output
+ * {@code rel}'s output
* @return estimated selectivity (between 0.0 and 1.0), or null if no
* reliable estimate can be determined
*/
- public static Double getSelectivity(RelNode rel, RexNode predicate) {
+ public Double getSelectivity(RelNode rel, RexNode predicate) {
final BuiltInMetadata.Selectivity metadata =
- rel.metadata(BuiltInMetadata.Selectivity.class);
+ rel.metadata(BuiltInMetadata.Selectivity.class, this);
Double result = metadata.getSelectivity(predicate);
assert isPercentage(result, true);
return result;
@@ -233,9 +245,9 @@ public abstract class RelMetadataQuery {
* @return set of keys, or null if this information cannot be determined
* (whereas empty set indicates definitely no keys at all)
*/
- public static Set<ImmutableBitSet> getUniqueKeys(RelNode rel) {
+ public Set<ImmutableBitSet> getUniqueKeys(RelNode rel) {
final BuiltInMetadata.UniqueKeys metadata =
- rel.metadata(BuiltInMetadata.UniqueKeys.class);
+ rel.metadata(BuiltInMetadata.UniqueKeys.class, this);
return metadata.getUniqueKeys(false);
}
@@ -247,13 +259,14 @@ public abstract class RelMetadataQuery {
* @param rel the relational expression
* @param ignoreNulls if true, ignore null values when determining
* whether the keys are unique
+ *
* @return set of keys, or null if this information cannot be determined
* (whereas empty set indicates definitely no keys at all)
*/
- public static Set<ImmutableBitSet> getUniqueKeys(RelNode rel,
+ public Set<ImmutableBitSet> getUniqueKeys(RelNode rel,
boolean ignoreNulls) {
final BuiltInMetadata.UniqueKeys metadata =
- rel.metadata(BuiltInMetadata.UniqueKeys.class);
+ rel.metadata(BuiltInMetadata.UniqueKeys.class, this);
return metadata.getUniqueKeys(ignoreNulls);
}
@@ -264,12 +277,13 @@ public abstract class RelMetadataQuery {
* statistic over all columns.
*
* @param rel the relational expression
+ *
* @return true or false depending on whether the rows are unique, or
* null if not enough information is available to make that determination
*/
- public static Boolean areRowsUnique(RelNode rel) {
+ public Boolean areRowsUnique(RelNode rel) {
final BuiltInMetadata.ColumnUniqueness metadata =
- rel.metadata(BuiltInMetadata.ColumnUniqueness.class);
+ rel.metadata(BuiltInMetadata.ColumnUniqueness.class, this);
final ImmutableBitSet columns =
ImmutableBitSet.range(rel.getRowType().getFieldCount());
return metadata.areColumnsUnique(columns, false);
@@ -277,24 +291,25 @@ public abstract class RelMetadataQuery {
/**
* Returns the
- * {@link BuiltInMetadata.ColumnUniqueness#areColumnsUnique(org.apache.calcite.util.ImmutableBitSet, boolean)}
+ * {@link BuiltInMetadata.ColumnUniqueness#areColumnsUnique(ImmutableBitSet, boolean)}
* statistic.
*
* @param rel the relational expression
* @param columns column mask representing the subset of columns for which
* uniqueness will be determined
+ *
* @return true or false depending on whether the columns are unique, or
* null if not enough information is available to make that determination
*/
- public static Boolean areColumnsUnique(RelNode rel, ImmutableBitSet columns) {
+ public Boolean areColumnsUnique(RelNode rel, ImmutableBitSet columns) {
final BuiltInMetadata.ColumnUniqueness metadata =
- rel.metadata(BuiltInMetadata.ColumnUniqueness.class);
+ rel.metadata(BuiltInMetadata.ColumnUniqueness.class, this);
return metadata.areColumnsUnique(columns, false);
}
/**
* Returns the
- * {@link BuiltInMetadata.ColumnUniqueness#areColumnsUnique(org.apache.calcite.util.ImmutableBitSet, boolean)}
+ * {@link BuiltInMetadata.ColumnUniqueness#areColumnsUnique(ImmutableBitSet, boolean)}
* statistic.
*
* @param rel the relational expression
@@ -305,46 +320,46 @@ public abstract class RelMetadataQuery {
* @return true or false depending on whether the columns are unique, or
* null if not enough information is available to make that determination
*/
- public static Boolean areColumnsUnique(RelNode rel, ImmutableBitSet columns,
+ public Boolean areColumnsUnique(RelNode rel, ImmutableBitSet columns,
boolean ignoreNulls) {
final BuiltInMetadata.ColumnUniqueness metadata =
- rel.metadata(BuiltInMetadata.ColumnUniqueness.class);
+ rel.metadata(BuiltInMetadata.ColumnUniqueness.class, this);
return metadata.areColumnsUnique(columns, ignoreNulls);
}
/**
* Returns the
- * {@link org.apache.calcite.rel.metadata.BuiltInMetadata.Collation#collations()}
+ * {@link BuiltInMetadata.Collation#collations()}
* statistic.
*
* @param rel the relational expression
* @return List of sorted column combinations, or
* null if not enough information is available to make that determination
*/
- public static ImmutableList<RelCollation> collations(RelNode rel) {
+ public ImmutableList<RelCollation> collations(RelNode rel) {
final BuiltInMetadata.Collation metadata =
- rel.metadata(BuiltInMetadata.Collation.class);
+ rel.metadata(BuiltInMetadata.Collation.class, this);
return metadata.collations();
}
/**
* Returns the
- * {@link org.apache.calcite.rel.metadata.BuiltInMetadata.Distribution#distribution()}
+ * {@link BuiltInMetadata.Distribution#distribution()}
* statistic.
*
* @param rel the relational expression
* @return List of sorted column combinations, or
* null if not enough information is available to make that determination
*/
- public static RelDistribution distribution(RelNode rel) {
+ public RelDistribution distribution(RelNode rel) {
final BuiltInMetadata.Distribution metadata =
- rel.metadata(BuiltInMetadata.Distribution.class);
+ rel.metadata(BuiltInMetadata.Distribution.class, this);
return metadata.distribution();
}
/**
* Returns the
- * {@link BuiltInMetadata.PopulationSize#getPopulationSize(org.apache.calcite.util.ImmutableBitSet)}
+ * {@link BuiltInMetadata.PopulationSize#getPopulationSize(ImmutableBitSet)}
* statistic.
*
* @param rel the relational expression
@@ -354,31 +369,31 @@ public abstract class RelMetadataQuery {
* estimate can be determined
*
*/
- public static Double getPopulationSize(RelNode rel,
+ public Double getPopulationSize(RelNode rel,
ImmutableBitSet groupKey) {
final BuiltInMetadata.PopulationSize metadata =
- rel.metadata(BuiltInMetadata.PopulationSize.class);
+ rel.metadata(BuiltInMetadata.PopulationSize.class, this);
Double result = metadata.getPopulationSize(groupKey);
return validateResult(result);
}
/**
* Returns the
- * {@link org.apache.calcite.rel.metadata.BuiltInMetadata.Size#averageRowSize()}
+ * {@link BuiltInMetadata.Size#averageRowSize()}
* statistic.
*
* @param rel the relational expression
* @return average size of a row, in bytes, or null if not known
*/
- public static Double getAverageRowSize(RelNode rel) {
+ public Double getAverageRowSize(RelNode rel) {
final BuiltInMetadata.Size metadata =
- rel.metadata(BuiltInMetadata.Size.class);
+ rel.metadata(BuiltInMetadata.Size.class, this);
return metadata.averageRowSize();
}
/**
* Returns the
- * {@link org.apache.calcite.rel.metadata.BuiltInMetadata.Size#averageColumnSizes()}
+ * {@link BuiltInMetadata.Size#averageColumnSizes()}
* statistic.
*
* @param rel the relational expression
@@ -386,17 +401,17 @@ public abstract class RelMetadataQuery {
* value, in bytes. Each value or the entire list may be null if the
* metadata is not available
*/
- public static List<Double> getAverageColumnSizes(RelNode rel) {
+ public List<Double> getAverageColumnSizes(RelNode rel) {
final BuiltInMetadata.Size metadata =
- rel.metadata(BuiltInMetadata.Size.class);
+ rel.metadata(BuiltInMetadata.Size.class, this);
return metadata.averageColumnSizes();
}
/** As {@link #getAverageColumnSizes(org.apache.calcite.rel.RelNode)} but
* never returns a null list, only ever a list of nulls. */
- public static List<Double> getAverageColumnSizesNotNull(RelNode rel) {
+ public List<Double> getAverageColumnSizesNotNull(RelNode rel) {
final BuiltInMetadata.Size metadata =
- rel.metadata(BuiltInMetadata.Size.class);
+ rel.metadata(BuiltInMetadata.Size.class, this);
final List<Double> averageColumnSizes = metadata.averageColumnSizes();
return averageColumnSizes == null
? Collections.<Double>nCopies(rel.getRowType().getFieldCount(), null)
@@ -405,7 +420,7 @@ public abstract class RelMetadataQuery {
/**
* Returns the
- * {@link org.apache.calcite.rel.metadata.BuiltInMetadata.Parallelism#isPhaseTransition()}
+ * {@link BuiltInMetadata.Parallelism#isPhaseTransition()}
* statistic.
*
* @param rel the relational expression
@@ -413,29 +428,29 @@ public abstract class RelMetadataQuery {
* expression belongs to a different process than its inputs, or null if not
* known
*/
- public static Boolean isPhaseTransition(RelNode rel) {
+ public Boolean isPhaseTransition(RelNode rel) {
final BuiltInMetadata.Parallelism metadata =
- rel.metadata(BuiltInMetadata.Parallelism.class);
+ rel.metadata(BuiltInMetadata.Parallelism.class, this);
return metadata.isPhaseTransition();
}
/**
* Returns the
- * {@link org.apache.calcite.rel.metadata.BuiltInMetadata.Parallelism#splitCount()}
+ * {@link BuiltInMetadata.Parallelism#splitCount()}
* statistic.
*
* @param rel the relational expression
* @return the number of distinct splits of the data, or null if not known
*/
- public static Integer splitCount(RelNode rel) {
+ public Integer splitCount(RelNode rel) {
final BuiltInMetadata.Parallelism metadata =
- rel.metadata(BuiltInMetadata.Parallelism.class);
+ rel.metadata(BuiltInMetadata.Parallelism.class, this);
return metadata.splitCount();
}
/**
* Returns the
- * {@link org.apache.calcite.rel.metadata.BuiltInMetadata.Memory#memory()}
+ * {@link BuiltInMetadata.Memory#memory()}
* statistic.
*
* @param rel the relational expression
@@ -443,15 +458,15 @@ public abstract class RelMetadataQuery {
* operator implementing this relational expression, across all splits,
* or null if not known
*/
- public static Double memory(RelNode rel) {
+ public Double memory(RelNode rel) {
final BuiltInMetadata.Memory metadata =
- rel.metadata(BuiltInMetadata.Memory.class);
+ rel.metadata(BuiltInMetadata.Memory.class, this);
return metadata.memory();
}
/**
* Returns the
- * {@link org.apache.calcite.rel.metadata.BuiltInMetadata.Memory#cumulativeMemoryWithinPhase()}
+ * {@link BuiltInMetadata.Memory#cumulativeMemoryWithinPhase()}
* statistic.
*
* @param rel the relational expression
@@ -459,15 +474,15 @@ public abstract class RelMetadataQuery {
* physical operator implementing this relational expression, and all other
* operators within the same phase, across all splits, or null if not known
*/
- public static Double cumulativeMemoryWithinPhase(RelNode rel) {
+ public Double cumulativeMemoryWithinPhase(RelNode rel) {
final BuiltInMetadata.Memory metadata =
- rel.metadata(BuiltInMetadata.Memory.class);
+ rel.metadata(BuiltInMetadata.Memory.class, this);
return metadata.cumulativeMemoryWithinPhase();
}
/**
* Returns the
- * {@link org.apache.calcite.rel.metadata.BuiltInMetadata.Memory#cumulativeMemoryWithinPhaseSplit()}
+ * {@link BuiltInMetadata.Memory#cumulativeMemoryWithinPhaseSplit()}
* statistic.
*
* @param rel the relational expression
@@ -475,15 +490,15 @@ public abstract class RelMetadataQuery {
* the physical operator implementing this relational expression, and all
* operators within the same phase, within each split, or null if not known
*/
- public static Double cumulativeMemoryWithinPhaseSplit(RelNode rel) {
+ public Double cumulativeMemoryWithinPhaseSplit(RelNode rel) {
final BuiltInMetadata.Memory metadata =
- rel.metadata(BuiltInMetadata.Memory.class);
+ rel.metadata(BuiltInMetadata.Memory.class, this);
return metadata.cumulativeMemoryWithinPhaseSplit();
}
/**
* Returns the
- * {@link BuiltInMetadata.DistinctRowCount#getDistinctRowCount(org.apache.calcite.util.ImmutableBitSet, org.apache.calcite.rex.RexNode)}
+ * {@link BuiltInMetadata.DistinctRowCount#getDistinctRowCount(ImmutableBitSet, RexNode)}
* statistic.
*
* @param rel the relational expression
@@ -492,27 +507,27 @@ public abstract class RelMetadataQuery {
* @return distinct row count for groupKey, filtered by predicate, or null
* if no reliable estimate can be determined
*/
- public static Double getDistinctRowCount(
+ public Double getDistinctRowCount(
RelNode rel,
ImmutableBitSet groupKey,
RexNode predicate) {
final BuiltInMetadata.DistinctRowCount metadata =
- rel.metadata(BuiltInMetadata.DistinctRowCount.class);
+ rel.metadata(BuiltInMetadata.DistinctRowCount.class, this);
Double result = metadata.getDistinctRowCount(groupKey, predicate);
return validateResult(result);
}
/**
* Returns the
- * {@link org.apache.calcite.rel.metadata.BuiltInMetadata.Predicates#getPredicates()}
+ * {@link BuiltInMetadata.Predicates#getPredicates()}
* statistic.
*
* @param rel the relational expression
* @return Predicates that can be pulled above this RelNode
*/
- public static RelOptPredicateList getPulledUpPredicates(RelNode rel) {
+ public RelOptPredicateList getPulledUpPredicates(RelNode rel) {
final BuiltInMetadata.Predicates metadata =
- rel.metadata(BuiltInMetadata.Predicates.class);
+ rel.metadata(BuiltInMetadata.Predicates.class, this);
return metadata.getPredicates();
}
@@ -526,10 +541,10 @@ public abstract class RelMetadataQuery {
* @return true for visible, false for invisible; if no metadata is available,
* defaults to true
*/
- public static boolean isVisibleInExplain(RelNode rel,
+ public boolean isVisibleInExplain(RelNode rel,
SqlExplainLevel explainLevel) {
final BuiltInMetadata.ExplainVisibility metadata =
- rel.metadata(BuiltInMetadata.ExplainVisibility.class);
+ rel.metadata(BuiltInMetadata.ExplainVisibility.class, this);
Boolean b = metadata.isVisibleInExplain(explainLevel);
return b == null || b;
}
http://git-wip-us.apache.org/repos/asf/calcite/blob/cabdcf44/core/src/main/java/org/apache/calcite/rel/metadata/UnboundMetadata.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rel/metadata/UnboundMetadata.java b/core/src/main/java/org/apache/calcite/rel/metadata/UnboundMetadata.java
new file mode 100644
index 0000000..ef8dc4a
--- /dev/null
+++ b/core/src/main/java/org/apache/calcite/rel/metadata/UnboundMetadata.java
@@ -0,0 +1,31 @@
+/*
+ * 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;
+
+import org.apache.calcite.rel.RelNode;
+
+/**
+ * Metadata that needs to be bound to a {@link RelNode} and
+ * {@link RelMetadataQuery} before it can be used.
+ *
+ * @param <M> Metadata type
+ */
+public interface UnboundMetadata<M extends Metadata> {
+ M bind(RelNode rel, RelMetadataQuery mq);
+}
+
+// End UnboundMetadata.java
http://git-wip-us.apache.org/repos/asf/calcite/blob/cabdcf44/core/src/main/java/org/apache/calcite/rel/rules/AggregateFilterTransposeRule.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rel/rules/AggregateFilterTransposeRule.java b/core/src/main/java/org/apache/calcite/rel/rules/AggregateFilterTransposeRule.java
index 52b5497..b2ebf84 100644
--- a/core/src/main/java/org/apache/calcite/rel/rules/AggregateFilterTransposeRule.java
+++ b/core/src/main/java/org/apache/calcite/rel/rules/AggregateFilterTransposeRule.java
@@ -72,8 +72,8 @@ public class AggregateFilterTransposeRule extends RelOptRule {
final ImmutableBitSet newGroupSet =
aggregate.getGroupSet().union(filterColumns);
final RelNode input = filter.getInput();
- final Boolean unique =
- RelMetadataQuery.areColumnsUnique(input, newGroupSet);
+ final RelMetadataQuery mq = RelMetadataQuery.instance();
+ final Boolean unique = mq.areColumnsUnique(input, newGroupSet);
if (unique != null && unique) {
// The input is already unique on the grouping columns, so there's little
// advantage of aggregating again. More important, without this check,
http://git-wip-us.apache.org/repos/asf/calcite/blob/cabdcf44/core/src/main/java/org/apache/calcite/rel/rules/AggregateJoinTransposeRule.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rel/rules/AggregateJoinTransposeRule.java b/core/src/main/java/org/apache/calcite/rel/rules/AggregateJoinTransposeRule.java
index 016e45a..6978e04 100644
--- a/core/src/main/java/org/apache/calcite/rel/rules/AggregateJoinTransposeRule.java
+++ b/core/src/main/java/org/apache/calcite/rel/rules/AggregateJoinTransposeRule.java
@@ -38,7 +38,9 @@ import org.apache.calcite.sql.SqlAggFunction;
import org.apache.calcite.sql.SqlSplittableAggFunction;
import org.apache.calcite.tools.RelBuilder;
import org.apache.calcite.tools.RelBuilderFactory;
+import org.apache.calcite.util.Bug;
import org.apache.calcite.util.ImmutableBitSet;
+import org.apache.calcite.util.Util;
import org.apache.calcite.util.mapping.Mapping;
import org.apache.calcite.util.mapping.Mappings;
@@ -153,8 +155,9 @@ public class AggregateJoinTransposeRule extends RelOptRule {
// Do the columns used by the join appear in the output of the aggregate?
final ImmutableBitSet aggregateColumns = aggregate.getGroupSet();
+ final RelMetadataQuery mq = RelMetadataQuery.instance();
final ImmutableBitSet keyColumns = keyColumns(aggregateColumns,
- RelMetadataQuery.getPulledUpPredicates(join).pulledUpPredicates);
+ mq.getPulledUpPredicates(join).pulledUpPredicates);
final ImmutableBitSet joinColumns =
RelOptUtil.InputFinder.bits(join.getCondition());
final boolean allColumnsInAggregate =
@@ -202,17 +205,18 @@ public class AggregateJoinTransposeRule extends RelOptRule {
// any functions experiencing a cartesian product effect.
//
// But finding out whether the input is already unique requires a call
- // to areColumnsUnique that currently (until [CALCITE-794] "Detect
- // cycles when computing statistics" is fixed) places a heavy load on
+ // to areColumnsUnique that currently (until [CALCITE-1048] "Make
+ // metadata more robust" is fixed) places a heavy load on
// the metadata system.
//
// So we choose to imagine the the input is already unique, which is
// untrue but harmless.
//
+ Util.discard(Bug.CALCITE_1048_FIXED);
unique = true;
} else {
final Boolean unique0 =
- RelMetadataQuery.areColumnsUnique(joinInput, belowAggregateKey);
+ mq.areColumnsUnique(joinInput, belowAggregateKey);
unique = unique0 != null && unique0;
}
if (unique) {
http://git-wip-us.apache.org/repos/asf/calcite/blob/cabdcf44/core/src/main/java/org/apache/calcite/rel/rules/AggregateProjectPullUpConstantsRule.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rel/rules/AggregateProjectPullUpConstantsRule.java b/core/src/main/java/org/apache/calcite/rel/rules/AggregateProjectPullUpConstantsRule.java
index a0ff130..bb7797e 100644
--- a/core/src/main/java/org/apache/calcite/rel/rules/AggregateProjectPullUpConstantsRule.java
+++ b/core/src/main/java/org/apache/calcite/rel/rules/AggregateProjectPullUpConstantsRule.java
@@ -109,8 +109,9 @@ public class AggregateProjectPullUpConstantsRule extends RelOptRule {
}
final RexBuilder rexBuilder = aggregate.getCluster().getRexBuilder();
+ final RelMetadataQuery mq = RelMetadataQuery.instance();
final RelOptPredicateList predicates =
- RelMetadataQuery.getPulledUpPredicates(aggregate.getInput());
+ mq.getPulledUpPredicates(aggregate.getInput());
if (predicates == null) {
return;
}
http://git-wip-us.apache.org/repos/asf/calcite/blob/cabdcf44/core/src/main/java/org/apache/calcite/rel/rules/AggregateRemoveRule.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rel/rules/AggregateRemoveRule.java b/core/src/main/java/org/apache/calcite/rel/rules/AggregateRemoveRule.java
index aa74448..b98ba64 100644
--- a/core/src/main/java/org/apache/calcite/rel/rules/AggregateRemoveRule.java
+++ b/core/src/main/java/org/apache/calcite/rel/rules/AggregateRemoveRule.java
@@ -57,10 +57,11 @@ public class AggregateRemoveRule extends RelOptRule {
public void onMatch(RelOptRuleCall call) {
final LogicalAggregate aggregate = call.rel(0);
final RelNode input = call.rel(1);
- if (!aggregate.getAggCallList().isEmpty()
- || aggregate.indicator
- || !SqlFunctions.isTrue(
- RelMetadataQuery.areColumnsUnique(input, aggregate.getGroupSet()))) {
+ if (!aggregate.getAggCallList().isEmpty() || aggregate.indicator) {
+ return;
+ }
+ final RelMetadataQuery mq = RelMetadataQuery.instance();
+ if (!SqlFunctions.isTrue(mq.areColumnsUnique(input, aggregate.getGroupSet()))) {
return;
}
// Distinct is "GROUP BY c1, c2" (where c1, c2 are a set of columns on
http://git-wip-us.apache.org/repos/asf/calcite/blob/cabdcf44/core/src/main/java/org/apache/calcite/rel/rules/AggregateStarTableRule.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rel/rules/AggregateStarTableRule.java b/core/src/main/java/org/apache/calcite/rel/rules/AggregateStarTableRule.java
index 7464a0f..3945924 100644
--- a/core/src/main/java/org/apache/calcite/rel/rules/AggregateStarTableRule.java
+++ b/core/src/main/java/org/apache/calcite/rel/rules/AggregateStarTableRule.java
@@ -33,6 +33,7 @@ import org.apache.calcite.rel.RelNode;
import org.apache.calcite.rel.core.Aggregate;
import org.apache.calcite.rel.core.AggregateCall;
import org.apache.calcite.rel.core.Project;
+import org.apache.calcite.rel.metadata.RelMetadataQuery;
import org.apache.calcite.rel.type.RelDataType;
import org.apache.calcite.schema.Table;
import org.apache.calcite.schema.impl.StarTable;
@@ -115,7 +116,8 @@ public class AggregateStarTableRule extends RelOptRule {
final RelBuilder relBuilder = call.builder();
final CalciteSchema.TableEntry tableEntry = pair.left;
final TileKey tileKey = pair.right;
- final double rowCount = aggregate.getRows();
+ final RelMetadataQuery mq = RelMetadataQuery.instance();
+ final double rowCount = aggregate.estimateRowCount(mq);
final Table aggregateTable = tableEntry.getTable();
final RelDataType aggregateTableRowType =
aggregateTable.getRowType(cluster.getTypeFactory());
http://git-wip-us.apache.org/repos/asf/calcite/blob/cabdcf44/core/src/main/java/org/apache/calcite/rel/rules/AggregateUnionTransposeRule.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rel/rules/AggregateUnionTransposeRule.java b/core/src/main/java/org/apache/calcite/rel/rules/AggregateUnionTransposeRule.java
index 2a2ef98..12300d9 100644
--- a/core/src/main/java/org/apache/calcite/rel/rules/AggregateUnionTransposeRule.java
+++ b/core/src/main/java/org/apache/calcite/rel/rules/AggregateUnionTransposeRule.java
@@ -27,6 +27,7 @@ import org.apache.calcite.rel.core.Union;
import org.apache.calcite.rel.logical.LogicalAggregate;
import org.apache.calcite.rel.logical.LogicalUnion;
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.sql.SqlAggFunction;
import org.apache.calcite.sql.fun.SqlCountAggFunction;
@@ -115,10 +116,10 @@ public class AggregateUnionTransposeRule extends RelOptRule {
// create corresponding aggregates on top of each union child
final RelBuilder relBuilder = call.builder();
int transformCount = 0;
+ final RelMetadataQuery mq = RelMetadataQuery.instance();
for (RelNode input : union.getInputs()) {
boolean alreadyUnique =
- RelMdUtil.areColumnsDefinitelyUnique(
- input,
+ RelMdUtil.areColumnsDefinitelyUnique(mq, input,
aggRel.getGroupSet());
relBuilder.push(input);
http://git-wip-us.apache.org/repos/asf/calcite/blob/cabdcf44/core/src/main/java/org/apache/calcite/rel/rules/JoinPushTransitivePredicatesRule.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rel/rules/JoinPushTransitivePredicatesRule.java b/core/src/main/java/org/apache/calcite/rel/rules/JoinPushTransitivePredicatesRule.java
index 1d375c6..0b020c7 100644
--- a/core/src/main/java/org/apache/calcite/rel/rules/JoinPushTransitivePredicatesRule.java
+++ b/core/src/main/java/org/apache/calcite/rel/rules/JoinPushTransitivePredicatesRule.java
@@ -59,7 +59,8 @@ public class JoinPushTransitivePredicatesRule extends RelOptRule {
@Override public void onMatch(RelOptRuleCall call) {
Join join = call.rel(0);
- RelOptPredicateList preds = RelMetadataQuery.getPulledUpPredicates(join);
+ final RelMetadataQuery mq = RelMetadataQuery.instance();
+ RelOptPredicateList preds = mq.getPulledUpPredicates(join);
if (preds.leftInferredPredicates.isEmpty()
&& preds.rightInferredPredicates.isEmpty()) {
http://git-wip-us.apache.org/repos/asf/calcite/blob/cabdcf44/core/src/main/java/org/apache/calcite/rel/rules/LoptMultiJoin.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rel/rules/LoptMultiJoin.java b/core/src/main/java/org/apache/calcite/rel/rules/LoptMultiJoin.java
index a41e1aa..ee4eeaa 100644
--- a/core/src/main/java/org/apache/calcite/rel/rules/LoptMultiJoin.java
+++ b/core/src/main/java/org/apache/calcite/rel/rules/LoptMultiJoin.java
@@ -192,7 +192,7 @@ public class LoptMultiJoin {
joinFilters =
Lists.newArrayList(RelOptUtil.conjunctions(multiJoin.getJoinFilter()));
- allJoinFilters = new ArrayList<RexNode>(joinFilters);
+ allJoinFilters = new ArrayList<>(joinFilters);
List<RexNode> outerJoinFilters = multiJoin.getOuterJoinConditions();
for (int i = 0; i < nJoinFactors; i++) {
allJoinFilters.addAll(RelOptUtil.conjunctions(outerJoinFilters.get(i)));
@@ -235,8 +235,8 @@ public class LoptMultiJoin {
joinRemovalFactors = new Integer[nJoinFactors];
joinRemovalSemiJoins = new SemiJoin[nJoinFactors];
- removableOuterJoinFactors = new HashSet<Integer>();
- removableSelfJoinPairs = new HashMap<Integer, RemovableSelfJoin>();
+ removableOuterJoinFactors = new HashSet<>();
+ removableSelfJoinPairs = new HashMap<>();
}
//~ Methods ----------------------------------------------------------------
@@ -695,15 +695,15 @@ public class LoptMultiJoin {
// Compute a column mapping such that if a column from the right
// factor is also referenced in the left factor, we will map the
// right reference to the left to avoid redundant references.
- Map<Integer, Integer> columnMapping = new HashMap<Integer, Integer>();
+ final Map<Integer, Integer> columnMapping = new HashMap<>();
// First, locate the originating column for all simple column
// references in the left factor.
- RelNode left = getJoinFactor(leftFactor);
- Map<Integer, Integer> leftFactorColMapping =
- new HashMap<Integer, Integer>();
+ final RelNode left = getJoinFactor(leftFactor);
+ final RelMetadataQuery mq = RelMetadataQuery.instance();
+ final Map<Integer, Integer> leftFactorColMapping = new HashMap<>();
for (int i = 0; i < left.getRowType().getFieldCount(); i++) {
- RelColumnOrigin colOrigin = RelMetadataQuery.getColumnOrigin(left, i);
+ final RelColumnOrigin colOrigin = mq.getColumnOrigin(left, i);
if (colOrigin != null) {
leftFactorColMapping.put(
colOrigin.getOriginColumnOrdinal(),
@@ -717,8 +717,7 @@ public class LoptMultiJoin {
// factor.
RelNode right = getJoinFactor(rightFactor);
for (int i = 0; i < right.getRowType().getFieldCount(); i++) {
- final RelColumnOrigin colOrigin =
- RelMetadataQuery.getColumnOrigin(right, i);
+ final RelColumnOrigin colOrigin = mq.getColumnOrigin(right, i);
if (colOrigin == null) {
continue;
}
http://git-wip-us.apache.org/repos/asf/calcite/blob/cabdcf44/core/src/main/java/org/apache/calcite/rel/rules/LoptOptimizeJoinRule.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rel/rules/LoptOptimizeJoinRule.java b/core/src/main/java/org/apache/calcite/rel/rules/LoptOptimizeJoinRule.java
index 66ae671..e522ade 100644
--- a/core/src/main/java/org/apache/calcite/rel/rules/LoptOptimizeJoinRule.java
+++ b/core/src/main/java/org/apache/calcite/rel/rules/LoptOptimizeJoinRule.java
@@ -209,9 +209,9 @@ public class LoptOptimizeJoinRule extends RelOptRule {
// part of an equality join condition, nulls are filtered out
// by the join. So, it's ok if there are nulls in the join
// keys.
- if (RelMdUtil.areColumnsDefinitelyUniqueWhenNullsFiltered(
- multiJoin.getJoinFactor(factIdx),
- joinKeys)) {
+ final RelMetadataQuery mq = RelMetadataQuery.instance();
+ if (RelMdUtil.areColumnsDefinitelyUniqueWhenNullsFiltered(mq,
+ multiJoin.getJoinFactor(factIdx), joinKeys)) {
multiJoin.addRemovableOuterJoinFactor(factIdx);
// Since we are no longer joining this factor,
@@ -319,7 +319,7 @@ public class LoptOptimizeJoinRule extends RelOptRule {
// the appropriate join condition between the two factors that will
// allow the join to be removed.
for (Integer factor1 : selfJoinPairs.keySet()) {
- int factor2 = selfJoinPairs.get(factor1);
+ final int factor2 = selfJoinPairs.get(factor1);
final List<RexNode> selfJoinFilters = new ArrayList<>();
for (RexNode filter : multiJoin.getJoinFilters()) {
ImmutableBitSet joinFactors =
@@ -361,13 +361,14 @@ public class LoptOptimizeJoinRule extends RelOptRule {
if (multiJoin.getMultiJoinRel().isFullOuterJoin()) {
return returnList;
}
+ final RelMetadataQuery mq = RelMetadataQuery.instance();
for (int factIdx = 0; factIdx < multiJoin.getNumJoinFactors(); factIdx++) {
if (multiJoin.isNullGenerating(factIdx)
|| (multiJoin.getJoinRemovalFactor(factIdx) != null)) {
continue;
}
final RelNode rel = multiJoin.getJoinFactor(factIdx);
- final RelOptTable table = RelMetadataQuery.getTableOrigin(rel);
+ final RelOptTable table = mq.getTableOrigin(rel);
if (table != null) {
returnList.put(factIdx, table);
}
@@ -421,7 +422,8 @@ public class LoptOptimizeJoinRule extends RelOptRule {
rightRel.getRowType().getFieldList(),
adjustments));
- return areSelfJoinKeysUnique(leftRel, rightRel, joinFilters);
+ final RelMetadataQuery mq = RelMetadataQuery.instance();
+ return areSelfJoinKeysUnique(mq, leftRel, rightRel, joinFilters);
}
/**
@@ -439,7 +441,7 @@ public class LoptOptimizeJoinRule extends RelOptRule {
RelOptRuleCall call) {
final List<RelNode> plans = new ArrayList<>();
- List<String> fieldNames =
+ final List<String> fieldNames =
multiJoin.getMultiJoinRel().getRowType().getFieldNames();
// generate the N join orderings
@@ -603,10 +605,9 @@ public class LoptOptimizeJoinRule extends RelOptRule {
if (joinKeys.isEmpty()) {
return null;
} else {
- return RelMetadataQuery.getDistinctRowCount(
- semiJoinOpt.getChosenSemiJoin(factor),
- joinKeys.build(),
- null);
+ final RelMetadataQuery mq = semiJoinOpt.mq;
+ return mq.getDistinctRowCount(semiJoinOpt.getChosenSemiJoin(factor),
+ joinKeys.build(), null);
}
}
@@ -671,9 +672,9 @@ public class LoptOptimizeJoinRule extends RelOptRule {
LoptSemiJoinOptimizer semiJoinOpt,
int firstFactor) {
LoptJoinTree joinTree = null;
- int nJoinFactors = multiJoin.getNumJoinFactors();
- BitSet factorsToAdd = BitSets.range(0, nJoinFactors);
- BitSet factorsAdded = new BitSet(nJoinFactors);
+ final int nJoinFactors = multiJoin.getNumJoinFactors();
+ final BitSet factorsToAdd = BitSets.range(0, nJoinFactors);
+ final BitSet factorsAdded = new BitSet(nJoinFactors);
final List<RexNode> filtersToAdd =
new ArrayList<>(multiJoin.getJoinFilters());
@@ -867,6 +868,8 @@ public class LoptOptimizeJoinRule extends RelOptRule {
BitSet factorsNeeded,
List<RexNode> filtersToAdd,
boolean selfJoin) {
+ final RelMetadataQuery mq = semiJoinOpt.mq;
+
// if the factor corresponds to the null generating factor in an outer
// join that can be removed, then create a replacement join
if (multiJoin.isRemovableOuterJoinFactor(factorToAdd)) {
@@ -935,11 +938,10 @@ public class LoptOptimizeJoinRule extends RelOptRule {
RelOptCost costPushDown = null;
RelOptCost costTop = null;
if (pushDownTree != null) {
- costPushDown =
- RelMetadataQuery.getCumulativeCost(pushDownTree.getJoinTree());
+ costPushDown = mq.getCumulativeCost(pushDownTree.getJoinTree());
}
if (topTree != null) {
- costTop = RelMetadataQuery.getCumulativeCost(topTree.getJoinTree());
+ costTop = mq.getCumulativeCost(topTree.getJoinTree());
}
if (pushDownTree == null) {
@@ -1337,7 +1339,7 @@ public class LoptOptimizeJoinRule extends RelOptRule {
int factorAdded,
List<Integer> origJoinOrder,
List<RelDataTypeField> origFields) {
- List<Integer> newJoinOrder = new ArrayList<>();
+ final List<Integer> newJoinOrder = new ArrayList<>();
left.getTreeOrder(newJoinOrder);
right.getTreeOrder(newJoinOrder);
@@ -1858,8 +1860,9 @@ public class LoptOptimizeJoinRule extends RelOptRule {
((LoptJoinTree.Leaf) left.getFactorTree()).getId());
}
- Double leftRowCount = RelMetadataQuery.getRowCount(left.getJoinTree());
- Double rightRowCount = RelMetadataQuery.getRowCount(right.getJoinTree());
+ final RelMetadataQuery mq = RelMetadataQuery.instance();
+ final Double leftRowCount = mq.getRowCount(left.getJoinTree());
+ final Double rightRowCount = mq.getRowCount(right.getJoinTree());
// The left side is smaller than the right if it has fewer rows,
// or if it has the same number of rows as the right (excluding
@@ -1990,11 +1993,12 @@ public class LoptOptimizeJoinRule extends RelOptRule {
}
// Make sure the join is between the same simple factor
- final RelOptTable leftTable = RelMetadataQuery.getTableOrigin(left);
+ final RelMetadataQuery mq = RelMetadataQuery.instance();
+ final RelOptTable leftTable = mq.getTableOrigin(left);
if (leftTable == null) {
return false;
}
- final RelOptTable rightTable = RelMetadataQuery.getTableOrigin(right);
+ final RelOptTable rightTable = mq.getTableOrigin(right);
if (rightTable == null) {
return false;
}
@@ -2003,35 +2007,34 @@ public class LoptOptimizeJoinRule extends RelOptRule {
}
// Determine if the join keys are identical and unique
- return areSelfJoinKeysUnique(left, right, joinRel.getCondition());
+ return areSelfJoinKeysUnique(mq, left, right, joinRel.getCondition());
}
/**
* Determines if the equality portion of a self-join condition is between
* identical keys that are unique.
*
+ * @param mq Metadata query
* @param leftRel left side of the join
* @param rightRel right side of the join
* @param joinFilters the join condition
*
* @return true if the equality join keys are the same and unique
*/
- private static boolean areSelfJoinKeysUnique(
- RelNode leftRel,
- RelNode rightRel,
- RexNode joinFilters) {
+ private static boolean areSelfJoinKeysUnique(RelMetadataQuery mq,
+ RelNode leftRel, RelNode rightRel, RexNode joinFilters) {
final JoinInfo joinInfo = JoinInfo.of(leftRel, rightRel, joinFilters);
// Make sure each key on the left maps to the same simple column as the
// corresponding key on the right
for (IntPair pair : joinInfo.pairs()) {
final RelColumnOrigin leftOrigin =
- RelMetadataQuery.getColumnOrigin(leftRel, pair.source);
+ mq.getColumnOrigin(leftRel, pair.source);
if (leftOrigin == null) {
return false;
}
final RelColumnOrigin rightOrigin =
- RelMetadataQuery.getColumnOrigin(rightRel, pair.target);
+ mq.getColumnOrigin(rightRel, pair.target);
if (rightOrigin == null) {
return false;
}
@@ -2045,7 +2048,7 @@ public class LoptOptimizeJoinRule extends RelOptRule {
// are unique. When removing self-joins, if needed, we'll later add an
// IS NOT NULL filter on the join keys that are nullable. Therefore,
// it's ok if there are nulls in the unique key.
- return RelMdUtil.areColumnsDefinitelyUniqueWhenNullsFiltered(leftRel,
+ return RelMdUtil.areColumnsDefinitelyUniqueWhenNullsFiltered(mq, leftRel,
joinInfo.leftSet());
}
}
http://git-wip-us.apache.org/repos/asf/calcite/blob/cabdcf44/core/src/main/java/org/apache/calcite/rel/rules/LoptSemiJoinOptimizer.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rel/rules/LoptSemiJoinOptimizer.java b/core/src/main/java/org/apache/calcite/rel/rules/LoptSemiJoinOptimizer.java
index 080cb9c..308091e 100644
--- a/core/src/main/java/org/apache/calcite/rel/rules/LoptSemiJoinOptimizer.java
+++ b/core/src/main/java/org/apache/calcite/rel/rules/LoptSemiJoinOptimizer.java
@@ -58,10 +58,11 @@ public class LoptSemiJoinOptimizer {
//~ Instance fields --------------------------------------------------------
- /**
- * RexBuilder for constructing new RexNodes
- */
- private RexBuilder rexBuilder;
+ private final RexBuilder rexBuilder;
+
+ /** Not thread-safe. But should be OK, because an optimizer is only used
+ * from within one thread.*/
+ final RelMetadataQuery mq = RelMetadataQuery.instance();
/**
* Semijoins corresponding to each join factor, if they are going to be
@@ -406,7 +407,7 @@ public class LoptSemiJoinOptimizer {
while (keyIter.hasNext()) {
boolean removeKey = false;
final RelColumnOrigin colOrigin =
- RelMetadataQuery.getColumnOrigin(factRel, keyIter.next());
+ mq.getColumnOrigin(factRel, keyIter.next());
// can't use the rid column as a semijoin key
if ((colOrigin == null)
@@ -635,13 +636,13 @@ public class LoptSemiJoinOptimizer {
// a middle ground based on testing that was done with a large
// data set.
final ImmutableBitSet dimCols = ImmutableBitSet.of(semiJoin.getRightKeys());
- double selectivity =
- RelMdUtil.computeSemiJoinSelectivity(factRel, dimRel, semiJoin);
+ final double selectivity =
+ RelMdUtil.computeSemiJoinSelectivity(mq, factRel, dimRel, semiJoin);
if (selectivity > .5) {
return 0;
}
- RelOptCost factCost = RelMetadataQuery.getCumulativeCost(factRel);
+ final RelOptCost factCost = mq.getCumulativeCost(factRel);
// if not enough information, return a low score
if (factCost == null) {
@@ -654,9 +655,8 @@ public class LoptSemiJoinOptimizer {
// Additional savings if the dimension columns are unique. We can
// ignore nulls since they will be filtered out by the semijoin.
boolean uniq =
- RelMdUtil.areColumnsDefinitelyUniqueWhenNullsFiltered(
- dimRel,
- dimCols);
+ RelMdUtil.areColumnsDefinitelyUniqueWhenNullsFiltered(mq,
+ dimRel, dimCols);
if (uniq) {
savings *= 2.0;
}
@@ -664,9 +664,9 @@ public class LoptSemiJoinOptimizer {
// compute the cost of doing an extra scan on the dimension table,
// including the distinct sort on top of the scan; if the dimension
// columns are already unique, no need to add on the dup removal cost
- Double dimSortCost = RelMetadataQuery.getRowCount(dimRel);
- Double dupRemCost = uniq ? 0 : dimSortCost;
- RelOptCost dimCost = RelMetadataQuery.getCumulativeCost(dimRel);
+ final Double dimSortCost = mq.getRowCount(dimRel);
+ final Double dupRemCost = uniq ? 0 : dimSortCost;
+ final RelOptCost dimCost = mq.getCumulativeCost(dimRel);
if ((dimSortCost == null)
|| (dupRemCost == null)
|| (dimCost == null)) {
@@ -708,9 +708,8 @@ public class LoptSemiJoinOptimizer {
// Check if the semijoin keys corresponding to the dimension table
// are unique. The semijoin will filter out the nulls.
final ImmutableBitSet dimKeys = ImmutableBitSet.of(semiJoin.getRightKeys());
- RelNode dimRel = multiJoin.getJoinFactor(dimIdx);
- if (!RelMdUtil.areColumnsDefinitelyUniqueWhenNullsFiltered(
- dimRel,
+ final RelNode dimRel = multiJoin.getJoinFactor(dimIdx);
+ if (!RelMdUtil.areColumnsDefinitelyUniqueWhenNullsFiltered(mq, dimRel,
dimKeys)) {
return;
}
@@ -800,14 +799,14 @@ public class LoptSemiJoinOptimizer {
//~ Inner Classes ----------------------------------------------------------
- /** . */
+ /** Compares factors. */
private class FactorCostComparator
implements Comparator<Integer> {
public int compare(Integer rel1Idx, Integer rel2Idx) {
RelOptCost c1 =
- RelMetadataQuery.getCumulativeCost(chosenSemiJoins[rel1Idx]);
+ mq.getCumulativeCost(chosenSemiJoins[rel1Idx]);
RelOptCost c2 =
- RelMetadataQuery.getCumulativeCost(chosenSemiJoins[rel2Idx]);
+ mq.getCumulativeCost(chosenSemiJoins[rel2Idx]);
// nulls are arbitrarily sorted
if ((c1 == null) || (c2 == null)) {
http://git-wip-us.apache.org/repos/asf/calcite/blob/cabdcf44/core/src/main/java/org/apache/calcite/rel/rules/MultiJoinOptimizeBushyRule.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rel/rules/MultiJoinOptimizeBushyRule.java b/core/src/main/java/org/apache/calcite/rel/rules/MultiJoinOptimizeBushyRule.java
index 477b74a..b0b372d 100644
--- a/core/src/main/java/org/apache/calcite/rel/rules/MultiJoinOptimizeBushyRule.java
+++ b/core/src/main/java/org/apache/calcite/rel/rules/MultiJoinOptimizeBushyRule.java
@@ -87,6 +87,7 @@ public class MultiJoinOptimizeBushyRule extends RelOptRule {
final MultiJoin multiJoinRel = call.rel(0);
final RexBuilder rexBuilder = multiJoinRel.getCluster().getRexBuilder();
final RelBuilder relBuilder = call.builder();
+ final RelMetadataQuery mq = RelMetadataQuery.instance();
final LoptMultiJoin multiJoin = new LoptMultiJoin(multiJoinRel);
@@ -94,7 +95,7 @@ public class MultiJoinOptimizeBushyRule extends RelOptRule {
int x = 0;
for (int i = 0; i < multiJoin.getNumJoinFactors(); i++) {
final RelNode rel = multiJoin.getJoinFactor(i);
- double cost = RelMetadataQuery.getRowCount(rel);
+ double cost = mq.getRowCount(rel);
vertexes.add(new LeafVertex(i, rel, cost, x));
x += rel.getRowType().getFieldCount();
}
http://git-wip-us.apache.org/repos/asf/calcite/blob/cabdcf44/core/src/main/java/org/apache/calcite/rel/rules/ReduceExpressionsRule.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rel/rules/ReduceExpressionsRule.java b/core/src/main/java/org/apache/calcite/rel/rules/ReduceExpressionsRule.java
index 759748c..3fce8a6 100644
--- a/core/src/main/java/org/apache/calcite/rel/rules/ReduceExpressionsRule.java
+++ b/core/src/main/java/org/apache/calcite/rel/rules/ReduceExpressionsRule.java
@@ -140,8 +140,9 @@ public abstract class ReduceExpressionsRule extends RelOptRule {
Lists.newArrayList(filter.getCondition());
RexNode newConditionExp;
boolean reduced;
+ final RelMetadataQuery mq = RelMetadataQuery.instance();
final RelOptPredicateList predicates =
- RelMetadataQuery.getPulledUpPredicates(filter.getInput());
+ mq.getPulledUpPredicates(filter.getInput());
if (reduceExpressions(filter, expList, predicates)) {
assert expList.size() == 1;
newConditionExp = expList.get(0);
@@ -229,9 +230,10 @@ public abstract class ReduceExpressionsRule extends RelOptRule {
}
@Override public void onMatch(RelOptRuleCall call) {
- Project project = call.rel(0);
+ final Project project = call.rel(0);
+ final RelMetadataQuery mq = RelMetadataQuery.instance();
final RelOptPredicateList predicates =
- RelMetadataQuery.getPulledUpPredicates(project.getInput());
+ mq.getPulledUpPredicates(project.getInput());
final List<RexNode> expList =
Lists.newArrayList(project.getProjects());
if (reduceExpressions(project, expList, predicates)) {
@@ -261,10 +263,11 @@ public abstract class ReduceExpressionsRule extends RelOptRule {
final Join join = call.rel(0);
final List<RexNode> expList = Lists.newArrayList(join.getCondition());
final int fieldCount = join.getLeft().getRowType().getFieldCount();
+ final RelMetadataQuery mq = RelMetadataQuery.instance();
final RelOptPredicateList leftPredicates =
- RelMetadataQuery.getPulledUpPredicates(join.getLeft());
+ mq.getPulledUpPredicates(join.getLeft());
final RelOptPredicateList rightPredicates =
- RelMetadataQuery.getPulledUpPredicates(join.getRight());
+ mq.getPulledUpPredicates(join.getRight());
final RelOptPredicateList predicates =
leftPredicates.union(rightPredicates.shift(fieldCount));
if (!reduceExpressions(join, expList, predicates)) {
http://git-wip-us.apache.org/repos/asf/calcite/blob/cabdcf44/core/src/main/java/org/apache/calcite/rel/rules/SortJoinTransposeRule.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rel/rules/SortJoinTransposeRule.java b/core/src/main/java/org/apache/calcite/rel/rules/SortJoinTransposeRule.java
index 66b0afb..2da9a35 100644
--- a/core/src/main/java/org/apache/calcite/rel/rules/SortJoinTransposeRule.java
+++ b/core/src/main/java/org/apache/calcite/rel/rules/SortJoinTransposeRule.java
@@ -29,6 +29,7 @@ import org.apache.calcite.rel.core.Sort;
import org.apache.calcite.rel.logical.LogicalJoin;
import org.apache.calcite.rel.logical.LogicalSort;
import org.apache.calcite.rel.metadata.RelMdUtil;
+import org.apache.calcite.rel.metadata.RelMetadataQuery;
/**
@@ -99,11 +100,12 @@ public class SortJoinTransposeRule extends RelOptRule {
// We create a new sort operator on the corresponding input
final RelNode newLeftInput;
final RelNode newRightInput;
+ final RelMetadataQuery mq = RelMetadataQuery.instance();
if (join.getJoinType() == JoinRelType.LEFT) {
// If the input is already sorted and we are not reducing the number of tuples,
// we bail out
- if (RelMdUtil.checkInputForCollationAndLimit(join.getLeft(), sort.getCollation(),
- sort.offset, sort.fetch)) {
+ if (RelMdUtil.checkInputForCollationAndLimit(mq, join.getLeft(),
+ sort.getCollation(), sort.offset, sort.fetch)) {
return;
}
newLeftInput = sort.copy(sort.getTraitSet(), join.getLeft(), sort.getCollation(),
@@ -116,8 +118,8 @@ public class SortJoinTransposeRule extends RelOptRule {
-join.getLeft().getRowType().getFieldCount()));
// If the input is already sorted and we are not reducing the number of tuples,
// we bail out
- if (RelMdUtil.checkInputForCollationAndLimit(join.getRight(), rightCollation,
- sort.offset, sort.fetch)) {
+ if (RelMdUtil.checkInputForCollationAndLimit(mq, join.getRight(),
+ rightCollation, sort.offset, sort.fetch)) {
return;
}
newLeftInput = join.getLeft();
http://git-wip-us.apache.org/repos/asf/calcite/blob/cabdcf44/core/src/main/java/org/apache/calcite/rel/rules/SortUnionTransposeRule.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rel/rules/SortUnionTransposeRule.java b/core/src/main/java/org/apache/calcite/rel/rules/SortUnionTransposeRule.java
index b195e3f..26d2106 100644
--- a/core/src/main/java/org/apache/calcite/rel/rules/SortUnionTransposeRule.java
+++ b/core/src/main/java/org/apache/calcite/rel/rules/SortUnionTransposeRule.java
@@ -23,6 +23,7 @@ import org.apache.calcite.rel.core.RelFactories;
import org.apache.calcite.rel.core.Sort;
import org.apache.calcite.rel.core.Union;
import org.apache.calcite.rel.metadata.RelMdUtil;
+import org.apache.calcite.rel.metadata.RelMetadataQuery;
import org.apache.calcite.tools.RelBuilderFactory;
import java.util.ArrayList;
@@ -93,9 +94,10 @@ public class SortUnionTransposeRule extends RelOptRule {
// Thus we use 'ret' as a flag to identify if we have finished pushing the
// sort past a union.
boolean ret = true;
+ final RelMetadataQuery mq = RelMetadataQuery.instance();
for (RelNode input : union.getInputs()) {
- if (!RelMdUtil.checkInputForCollationAndLimit(input, sort.getCollation(),
- sort.offset, sort.fetch)) {
+ if (!RelMdUtil.checkInputForCollationAndLimit(mq, input,
+ sort.getCollation(), sort.offset, sort.fetch)) {
ret = false;
Sort branchSort = sort.copy(sort.getTraitSet(), input,
sort.getCollation(), sort.offset, sort.fetch);
http://git-wip-us.apache.org/repos/asf/calcite/blob/cabdcf44/core/src/main/java/org/apache/calcite/rel/rules/SubQueryRemoveRule.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rel/rules/SubQueryRemoveRule.java b/core/src/main/java/org/apache/calcite/rel/rules/SubQueryRemoveRule.java
index c3daf49..56b362d 100644
--- a/core/src/main/java/org/apache/calcite/rel/rules/SubQueryRemoveRule.java
+++ b/core/src/main/java/org/apache/calcite/rel/rules/SubQueryRemoveRule.java
@@ -148,7 +148,8 @@ public abstract class SubQueryRemoveRule extends RelOptRule {
switch (e.getKind()) {
case SCALAR_QUERY:
builder.push(e.rel);
- final Boolean unique = RelMetadataQuery.areColumnsUnique(builder.peek(),
+ final RelMetadataQuery mq = RelMetadataQuery.instance();
+ final Boolean unique = mq.areColumnsUnique(builder.peek(),
ImmutableBitSet.of());
if (unique == null || !unique) {
builder.aggregate(builder.groupKey(),