http://git-wip-us.apache.org/repos/asf/calcite/blob/cabdcf44/core/src/main/java/org/apache/calcite/rel/metadata/RelMdColumnUniqueness.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdColumnUniqueness.java b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdColumnUniqueness.java index 2a6431d..c872075 100644 --- a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdColumnUniqueness.java +++ b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdColumnUniqueness.java @@ -44,7 +44,6 @@ import org.apache.calcite.sql.fun.SqlStdOperatorTable; import org.apache.calcite.util.BuiltInMethod; import org.apache.calcite.util.ImmutableBitSet; -import com.google.common.base.Predicate; import com.google.common.collect.ImmutableList; import java.util.ArrayList; @@ -67,55 +66,53 @@ public class RelMdColumnUniqueness { //~ Methods ---------------------------------------------------------------- - public Boolean areColumnsUnique( - TableScan rel, - ImmutableBitSet columns, - boolean ignoreNulls) { + public Boolean areColumnsUnique(TableScan rel, RelMetadataQuery mq, + ImmutableBitSet columns, boolean ignoreNulls) { return rel.getTable().isKey(columns); } - public Boolean areColumnsUnique( - Filter rel, - ImmutableBitSet columns, - boolean ignoreNulls) { - return RelMetadataQuery.areColumnsUnique( - rel.getInput(), - columns, - ignoreNulls); + public Boolean areColumnsUnique(Filter rel, RelMetadataQuery mq, + ImmutableBitSet columns, boolean ignoreNulls) { + return mq.areColumnsUnique(rel.getInput(), columns, ignoreNulls); } - public Boolean areColumnsUnique( - Sort rel, - ImmutableBitSet columns, - boolean ignoreNulls) { - return RelMetadataQuery.areColumnsUnique( - rel.getInput(), - columns, - ignoreNulls); + /** Catch-all implementation for + * {@link BuiltInMetadata.ColumnUniqueness#areColumnsUnique(ImmutableBitSet, boolean)}, + * invoked using reflection, for any relational expression not + * handled by a more specific method. + * + * @param rel Relational expression + * @param mq Metadata query + * @param columns column mask representing the subset of columns for which + * uniqueness will be determined + * @param ignoreNulls if true, ignore null values when determining column + * uniqueness + * @return whether the columns are unique, or + * null if not enough information is available to make that determination + * + * @see org.apache.calcite.rel.metadata.RelMetadataQuery#areColumnsUnique(RelNode, ImmutableBitSet, boolean) + */ + public Boolean areColumnsUnique(RelNode rel, RelMetadataQuery mq, + ImmutableBitSet columns, boolean ignoreNulls) { + // no information available + return null; } - public Boolean areColumnsUnique( - SetOp rel, - ImmutableBitSet columns, - boolean ignoreNulls) { + public Boolean areColumnsUnique(SetOp rel, RelMetadataQuery mq, + ImmutableBitSet columns, boolean ignoreNulls) { // If not ALL then the rows are distinct. // Therefore the set of all columns is a key. return !rel.all && columns.nextClearBit(0) >= rel.getRowType().getFieldCount(); } - public Boolean areColumnsUnique( - Intersect rel, - ImmutableBitSet columns, - boolean ignoreNulls) { - if (areColumnsUnique((SetOp) rel, columns, ignoreNulls)) { + public Boolean areColumnsUnique(Intersect rel, RelMetadataQuery mq, + ImmutableBitSet columns, boolean ignoreNulls) { + if (areColumnsUnique((SetOp) rel, mq, columns, ignoreNulls)) { return true; } for (RelNode input : rel.getInputs()) { - Boolean b = RelMetadataQuery.areColumnsUnique( - input, - columns, - ignoreNulls); + Boolean b = mq.areColumnsUnique(input, columns, ignoreNulls); if (b != null && b) { return true; } @@ -123,43 +120,31 @@ public class RelMdColumnUniqueness { return false; } - public Boolean areColumnsUnique( - Minus rel, - ImmutableBitSet columns, - boolean ignoreNulls) { - if (areColumnsUnique((SetOp) rel, columns, ignoreNulls)) { + public Boolean areColumnsUnique(Minus rel, RelMetadataQuery mq, + ImmutableBitSet columns, boolean ignoreNulls) { + if (areColumnsUnique((SetOp) rel, mq, columns, ignoreNulls)) { return true; } - return RelMetadataQuery.areColumnsUnique( - rel.getInput(0), - columns, - ignoreNulls); + return mq.areColumnsUnique(rel.getInput(0), columns, ignoreNulls); } - public Boolean areColumnsUnique( - Exchange rel, - ImmutableBitSet columns, - boolean ignoreNulls) { - return RelMetadataQuery.areColumnsUnique( - rel.getInput(), - columns, - ignoreNulls); + public Boolean areColumnsUnique(Sort rel, RelMetadataQuery mq, + ImmutableBitSet columns, boolean ignoreNulls) { + return mq.areColumnsUnique(rel.getInput(), columns, ignoreNulls); } - public Boolean areColumnsUnique( - Correlate rel, - ImmutableBitSet columns, - boolean ignoreNulls) { - return RelMetadataQuery.areColumnsUnique( - rel.getLeft(), - columns, - ignoreNulls); + public Boolean areColumnsUnique(Exchange rel, RelMetadataQuery mq, + ImmutableBitSet columns, boolean ignoreNulls) { + return mq.areColumnsUnique(rel.getInput(), columns, ignoreNulls); + } + + public Boolean areColumnsUnique(Correlate rel, RelMetadataQuery mq, + ImmutableBitSet columns, boolean ignoreNulls) { + return mq.areColumnsUnique(rel.getLeft(), columns, ignoreNulls); } - public Boolean areColumnsUnique( - Project rel, - ImmutableBitSet columns, - boolean ignoreNulls) { + public Boolean areColumnsUnique(Project rel, RelMetadataQuery mq, + ImmutableBitSet columns, 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 @@ -211,16 +196,12 @@ public class RelMdColumnUniqueness { return null; } - return RelMetadataQuery.areColumnsUnique( - rel.getInput(), - childColumns.build(), + return mq.areColumnsUnique(rel.getInput(), childColumns.build(), ignoreNulls); } - public Boolean areColumnsUnique( - Join rel, - ImmutableBitSet columns, - boolean ignoreNulls) { + public Boolean areColumnsUnique(Join rel, RelMetadataQuery mq, + ImmutableBitSet columns, boolean ignoreNulls) { if (columns.cardinality() == 0) { return false; } @@ -245,11 +226,9 @@ public class RelMdColumnUniqueness { // right hand side, then the columns are unique if and only if they're // unique for their respective join inputs final ImmutableBitSet leftColumns = leftBuilder.build(); - Boolean leftUnique = - RelMetadataQuery.areColumnsUnique(left, leftColumns, ignoreNulls); + Boolean leftUnique = mq.areColumnsUnique(left, leftColumns, ignoreNulls); final ImmutableBitSet rightColumns = rightBuilder.build(); - Boolean rightUnique = - RelMetadataQuery.areColumnsUnique(right, rightColumns, ignoreNulls); + Boolean rightUnique = mq.areColumnsUnique(right, rightColumns, ignoreNulls); if ((leftColumns.cardinality() > 0) && (rightColumns.cardinality() > 0)) { if ((leftUnique == null) || (rightUnique == null)) { @@ -271,8 +250,7 @@ public class RelMdColumnUniqueness { return false; } Boolean rightJoinColsUnique = - RelMetadataQuery.areColumnsUnique(right, joinInfo.rightSet(), - ignoreNulls); + mq.areColumnsUnique(right, joinInfo.rightSet(), ignoreNulls); if ((rightJoinColsUnique == null) || (leftUnique == null)) { return null; } @@ -282,8 +260,7 @@ public class RelMdColumnUniqueness { return false; } Boolean leftJoinColsUnique = - RelMetadataQuery.areColumnsUnique(left, joinInfo.leftSet(), - ignoreNulls); + mq.areColumnsUnique(left, joinInfo.leftSet(), ignoreNulls); if ((leftJoinColsUnique == null) || (rightUnique == null)) { return null; } @@ -293,56 +270,28 @@ public class RelMdColumnUniqueness { throw new AssertionError(); } - public Boolean areColumnsUnique( - SemiJoin rel, - ImmutableBitSet columns, - boolean ignoreNulls) { + public Boolean areColumnsUnique(SemiJoin rel, RelMetadataQuery mq, + ImmutableBitSet columns, boolean ignoreNulls) { // only return the unique keys from the LHS since a semijoin only // returns the LHS - return RelMetadataQuery.areColumnsUnique( - rel.getLeft(), - columns, - ignoreNulls); + return mq.areColumnsUnique(rel.getLeft(), columns, ignoreNulls); } - public Boolean areColumnsUnique( - Aggregate rel, - ImmutableBitSet columns, - boolean ignoreNulls) { + public Boolean areColumnsUnique(Aggregate rel, RelMetadataQuery mq, + ImmutableBitSet columns, boolean ignoreNulls) { // group by keys form a unique key ImmutableBitSet groupKey = ImmutableBitSet.range(rel.getGroupCount()); return columns.contains(groupKey); } - // Catch-all rule when none of the others apply. - public Boolean areColumnsUnique( - RelNode rel, - ImmutableBitSet columns, - boolean ignoreNulls) { - // no information available - return null; - } - - public Boolean areColumnsUnique( - Converter rel, - ImmutableBitSet columns, - boolean ignoreNulls) { - return RelMetadataQuery.areColumnsUnique( - rel.getInput(), - columns, - ignoreNulls); - } - - public Boolean areColumnsUnique( - Values rel, - RelMetadataQuery query, - boolean ignoreNulls) { - if (rel.getTuples().size() < 2) { + public Boolean areColumnsUnique(Values rel, RelMetadataQuery mq, + ImmutableBitSet columns, boolean ignoreNulls) { + if (rel.tuples.size() < 2) { return true; } final Set<List<Comparable>> set = new HashSet<>(); final List<Comparable> values = new ArrayList<>(); - for (ImmutableList<RexLiteral> tuple : rel.getTuples()) { + for (ImmutableList<RexLiteral> tuple : rel.tuples) { for (RexLiteral literal : tuple) { values.add(NullSentinel.mask(literal.getValue())); } @@ -354,36 +303,64 @@ public class RelMdColumnUniqueness { return true; } - public Boolean areColumnsUnique( + public Boolean areColumnsUnique(Converter rel, RelMetadataQuery mq, + ImmutableBitSet columns, boolean ignoreNulls) { + return mq.areColumnsUnique(rel.getInput(), columns, ignoreNulls); + } + + public Boolean areColumnsUnique(HepRelVertex rel, RelMetadataQuery mq, boolean dummy, // prevent method from being used - HepRelVertex rel, - ImmutableBitSet columns, - boolean ignoreNulls) { - return RelMetadataQuery.areColumnsUnique( - rel.getCurrentRel(), - columns, - ignoreNulls); + ImmutableBitSet columns, boolean ignoreNulls) { + return mq.areColumnsUnique(rel.getCurrentRel(), columns, ignoreNulls); } - public Boolean areColumnsUnique( - RelSubset rel, - ImmutableBitSet columns, - boolean ignoreNulls) { - final RelNode best = rel.getBest(); - if (best == null) { - return null; - } else { - return RelMetadataQuery.areColumnsUnique(best, columns, ignoreNulls); + public Boolean areColumnsUnique(RelSubset rel, RelMetadataQuery mq, + ImmutableBitSet columns, boolean ignoreNulls) { + int nullCount = 0; + for (RelNode rel2 : rel.getRels()) { + if (rel2 instanceof Aggregate + || rel2 instanceof Filter + || rel2 instanceof Values + || rel2 instanceof TableScan + || simplyProjects(rel2, columns)) { + try { + final Boolean unique = mq.areColumnsUnique(rel2, columns, ignoreNulls); + if (unique != null) { + if (unique) { + return true; + } + } else { + ++nullCount; + } + } catch (CyclicMetadataException e) { + // Ignore this relational expression; there will be non-cyclic ones + // in this set. + } + } } + return nullCount == 0 ? false : null; } - /** Aggregate and Calc are "safe" children of a RelSubset to delve into. */ - private static final Predicate<RelNode> SAFE_REL = - new Predicate<RelNode>() { - public boolean apply(RelNode r) { - return r instanceof Aggregate || r instanceof Project; - } - }; + private boolean simplyProjects(RelNode rel, ImmutableBitSet columns) { + if (!(rel instanceof Project)) { + return false; + } + Project project = (Project) rel; + final List<RexNode> projects = project.getProjects(); + for (int column : columns) { + if (column >= projects.size()) { + return false; + } + if (!(projects.get(column) instanceof RexInputRef)) { + return false; + } + final RexInputRef ref = (RexInputRef) projects.get(column); + if (ref.getIndex() != column) { + return false; + } + } + return true; + } } // End RelMdColumnUniqueness.java
http://git-wip-us.apache.org/repos/asf/calcite/blob/cabdcf44/core/src/main/java/org/apache/calcite/rel/metadata/RelMdDistinctRowCount.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdDistinctRowCount.java b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdDistinctRowCount.java index 2fb2b25..eef245e 100644 --- a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdDistinctRowCount.java +++ b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdDistinctRowCount.java @@ -17,6 +17,7 @@ package org.apache.calcite.rel.metadata; import org.apache.calcite.plan.RelOptUtil; +import org.apache.calcite.plan.volcano.RelSubset; import org.apache.calcite.rel.RelNode; import org.apache.calcite.rel.core.Aggregate; import org.apache.calcite.rel.core.Exchange; @@ -31,6 +32,7 @@ import org.apache.calcite.rex.RexBuilder; import org.apache.calcite.rex.RexNode; import org.apache.calcite.rex.RexUtil; import org.apache.calcite.sql.fun.SqlStdOperatorTable; +import org.apache.calcite.util.Bug; import org.apache.calcite.util.BuiltInMethod; import org.apache.calcite.util.ImmutableBitSet; import org.apache.calcite.util.NumberUtil; @@ -54,10 +56,27 @@ public class RelMdDistinctRowCount { //~ Methods ---------------------------------------------------------------- - public Double getDistinctRowCount( - Union rel, - ImmutableBitSet groupKey, - RexNode predicate) { + /** Catch-all implementation for + * {@link BuiltInMetadata.DistinctRowCount#getDistinctRowCount(ImmutableBitSet, RexNode)}, + * invoked using reflection. + * + * @see org.apache.calcite.rel.metadata.RelMetadataQuery#getDistinctRowCount(RelNode, ImmutableBitSet, RexNode) + */ + public Double getDistinctRowCount(RelNode rel, RelMetadataQuery mq, + ImmutableBitSet groupKey, RexNode predicate) { + // REVIEW zfong 4/19/06 - Broadbase code does not take into + // consideration selectivity of predicates passed in. Also, they + // assume the rows are unique even if the table is not + boolean uniq = RelMdUtil.areColumnsDefinitelyUnique(mq, rel, groupKey); + if (uniq) { + return NumberUtil.multiply(mq.getRowCount(rel), + mq.getSelectivity(rel, predicate)); + } + return null; + } + + public Double getDistinctRowCount(Union rel, RelMetadataQuery mq, + ImmutableBitSet groupKey, RexNode predicate) { Double rowCount = 0.0; int[] adjustments = new int[rel.getRowType().getFieldCount()]; RexBuilder rexBuilder = rel.getCluster().getRexBuilder(); @@ -76,10 +95,7 @@ public class RelMdDistinctRowCount { adjustments)); } Double partialRowCount = - RelMetadataQuery.getDistinctRowCount( - input, - groupKey, - modifiedPred); + mq.getDistinctRowCount(input, groupKey, modifiedPred); if (partialRowCount == null) { return null; } @@ -88,30 +104,18 @@ public class RelMdDistinctRowCount { return rowCount; } - public Double getDistinctRowCount( - Sort rel, - ImmutableBitSet groupKey, - RexNode predicate) { - return RelMetadataQuery.getDistinctRowCount( - rel.getInput(), - groupKey, - predicate); + public Double getDistinctRowCount(Sort rel, RelMetadataQuery mq, + ImmutableBitSet groupKey, RexNode predicate) { + return mq.getDistinctRowCount(rel.getInput(), groupKey, predicate); } - public Double getDistinctRowCount( - Exchange rel, - ImmutableBitSet groupKey, - RexNode predicate) { - return RelMetadataQuery.getDistinctRowCount( - rel.getInput(), - groupKey, - predicate); + public Double getDistinctRowCount(Exchange rel, RelMetadataQuery mq, + ImmutableBitSet groupKey, RexNode predicate) { + return mq.getDistinctRowCount(rel.getInput(), groupKey, predicate); } - public Double getDistinctRowCount( - Filter rel, - ImmutableBitSet groupKey, - RexNode predicate) { + public Double getDistinctRowCount(Filter rel, RelMetadataQuery mq, + ImmutableBitSet groupKey, RexNode predicate) { if (predicate == null || predicate.isAlwaysTrue()) { if (groupKey.isEmpty()) { return 1D; @@ -126,33 +130,22 @@ public class RelMdDistinctRowCount { predicate, rel.getCondition()); - return RelMetadataQuery.getDistinctRowCount( - rel.getInput(), - groupKey, - unionPreds); + return mq.getDistinctRowCount(rel.getInput(), groupKey, unionPreds); } - public Double getDistinctRowCount( - Join rel, - ImmutableBitSet groupKey, - RexNode predicate) { + public Double getDistinctRowCount(Join rel, RelMetadataQuery mq, + ImmutableBitSet groupKey, RexNode predicate) { if (predicate == null || predicate.isAlwaysTrue()) { if (groupKey.isEmpty()) { return 1D; } } - return RelMdUtil.getJoinDistinctRowCount( - rel, - rel.getJoinType(), - groupKey, - predicate, - false); + return RelMdUtil.getJoinDistinctRowCount(mq, rel, rel.getJoinType(), + groupKey, predicate, false); } - public Double getDistinctRowCount( - SemiJoin rel, - ImmutableBitSet groupKey, - RexNode predicate) { + public Double getDistinctRowCount(SemiJoin rel, RelMetadataQuery mq, + ImmutableBitSet groupKey, RexNode predicate) { if (predicate == null || predicate.isAlwaysTrue()) { if (groupKey.isEmpty()) { return 1D; @@ -160,7 +153,7 @@ public class RelMdDistinctRowCount { } // create a RexNode representing the selectivity of the // semijoin filter and pass it to getDistinctRowCount - RexNode newPred = RelMdUtil.makeSemiJoinSelectivityRexNode(rel); + RexNode newPred = RelMdUtil.makeSemiJoinSelectivityRexNode(mq, rel); if (predicate != null) { RexBuilder rexBuilder = rel.getCluster().getRexBuilder(); newPred = @@ -170,16 +163,11 @@ public class RelMdDistinctRowCount { predicate); } - return RelMetadataQuery.getDistinctRowCount( - rel.getLeft(), - groupKey, - newPred); + return mq.getDistinctRowCount(rel.getLeft(), groupKey, newPred); } - public Double getDistinctRowCount( - Aggregate rel, - ImmutableBitSet groupKey, - RexNode predicate) { + public Double getDistinctRowCount(Aggregate rel, RelMetadataQuery mq, + ImmutableBitSet groupKey, RexNode predicate) { if (predicate == null || predicate.isAlwaysTrue()) { if (groupKey.isEmpty()) { return 1D; @@ -187,8 +175,8 @@ public class RelMdDistinctRowCount { } // determine which predicates can be applied on the child of the // aggregate - List<RexNode> notPushable = new ArrayList<RexNode>(); - List<RexNode> pushable = new ArrayList<RexNode>(); + final List<RexNode> notPushable = new ArrayList<>(); + final List<RexNode> pushable = new ArrayList<>(); RelOptUtil.splitFilters( rel.getGroupSet(), predicate, @@ -203,10 +191,7 @@ public class RelMdDistinctRowCount { RelMdUtil.setAggChildKeys(groupKey, rel, childKey); Double distinctRowCount = - RelMetadataQuery.getDistinctRowCount( - rel.getInput(), - childKey.build(), - childPreds); + mq.getDistinctRowCount(rel.getInput(), childKey.build(), childPreds); if (distinctRowCount == null) { return null; } else if (notPushable.isEmpty()) { @@ -218,10 +203,8 @@ public class RelMdDistinctRowCount { } } - public Double getDistinctRowCount( - Values rel, - ImmutableBitSet groupKey, - RexNode predicate) { + public Double getDistinctRowCount(Values rel, RelMetadataQuery mq, + ImmutableBitSet groupKey, RexNode predicate) { if (predicate == null || predicate.isAlwaysTrue()) { if (groupKey.isEmpty()) { return 1D; @@ -230,14 +213,12 @@ public class RelMdDistinctRowCount { Double selectivity = RelMdUtil.guessSelectivity(predicate); // assume half the rows are duplicates - Double nRows = rel.getRows() / 2; + Double nRows = rel.estimateRowCount(mq) / 2; return RelMdUtil.numDistinctVals(nRows, nRows * selectivity); } - public Double getDistinctRowCount( - Project rel, - ImmutableBitSet groupKey, - RexNode predicate) { + public Double getDistinctRowCount(Project rel, RelMetadataQuery mq, + ImmutableBitSet groupKey, RexNode predicate) { if (predicate == null || predicate.isAlwaysTrue()) { if (groupKey.isEmpty()) { return 1D; @@ -248,8 +229,8 @@ public class RelMdDistinctRowCount { List<RexNode> projExprs = rel.getProjects(); RelMdUtil.splitCols(projExprs, groupKey, baseCols, projCols); - List<RexNode> notPushable = new ArrayList<RexNode>(); - List<RexNode> pushable = new ArrayList<RexNode>(); + final List<RexNode> notPushable = new ArrayList<>(); + final List<RexNode> pushable = new ArrayList<>(); RelOptUtil.splitFilters( ImmutableBitSet.range(rel.getRowType().getFieldCount()), predicate, @@ -269,9 +250,7 @@ public class RelMdDistinctRowCount { modifiedPred = RelOptUtil.pushPastProject(childPred, rel); } Double distinctRowCount = - RelMetadataQuery.getDistinctRowCount( - rel.getInput(), - baseCols.build(), + mq.getDistinctRowCount(rel.getInput(), baseCols.build(), modifiedPred); if (distinctRowCount == null) { @@ -291,38 +270,36 @@ public class RelMdDistinctRowCount { // multiply by the cardinality of the non-child projection expressions for (int bit : projCols.build()) { Double subRowCount = - RelMdUtil.cardOfProjExpr(rel, projExprs.get(bit)); + RelMdUtil.cardOfProjExpr(mq, rel, projExprs.get(bit)); if (subRowCount == null) { return null; } distinctRowCount *= subRowCount; } - return RelMdUtil.numDistinctVals( - distinctRowCount, - RelMetadataQuery.getRowCount(rel)); + return RelMdUtil.numDistinctVals(distinctRowCount, mq.getRowCount(rel)); } - // Catch-all rule when none of the others apply. - public Double getDistinctRowCount( - RelNode rel, - ImmutableBitSet groupKey, - RexNode predicate) { - if (predicate == null || predicate.isAlwaysTrue()) { - if (groupKey.isEmpty()) { - return 1D; - } + public Double getDistinctRowCount(RelSubset rel, RelMetadataQuery mq, + ImmutableBitSet groupKey, RexNode predicate) { + final RelNode best = rel.getBest(); + if (best != null) { + return mq.getDistinctRowCount(best, groupKey, predicate); } - // REVIEW zfong 4/19/06 - Broadbase code does not take into - // consideration selectivity of predicates passed in. Also, they - // assume the rows are unique even if the table is not - boolean uniq = RelMdUtil.areColumnsDefinitelyUnique(rel, groupKey); - if (uniq) { - return NumberUtil.multiply( - RelMetadataQuery.getRowCount(rel), - RelMetadataQuery.getSelectivity(rel, predicate)); + if (!Bug.CALCITE_1048_FIXED) { + return getDistinctRowCount((RelNode) rel, mq, groupKey, predicate); } - return null; + Double d = null; + for (RelNode r2 : rel.getRels()) { + try { + Double d2 = mq.getDistinctRowCount(r2, groupKey, predicate); + d = NumberUtil.min(d, d2); + } catch (CyclicMetadataException e) { + // Ignore this relational expression; there will be non-cyclic ones + // in this set. + } + } + return d; } } http://git-wip-us.apache.org/repos/asf/calcite/blob/cabdcf44/core/src/main/java/org/apache/calcite/rel/metadata/RelMdDistribution.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdDistribution.java b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdDistribution.java index 67ac6a2..f7b5c83 100644 --- a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdDistribution.java +++ b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdDistribution.java @@ -63,40 +63,40 @@ public class RelMdDistribution { * @param rel Relational expression * @return Relational expression's distribution */ - public RelDistribution distribution(RelNode rel) { + public RelDistribution distribution(RelMetadataQuery mq, RelNode rel) { return RelDistributions.SINGLETON; } - public RelDistribution distribution(SingleRel rel) { - return RelMetadataQuery.distribution(rel.getInput()); + public RelDistribution distribution(RelMetadataQuery mq, SingleRel rel) { + return mq.distribution(rel.getInput()); } - public RelDistribution distribution(BiRel rel) { - return RelMetadataQuery.distribution(rel.getLeft()); + public RelDistribution distribution(RelMetadataQuery mq, BiRel rel) { + return mq.distribution(rel.getLeft()); } - public RelDistribution distribution(SetOp rel) { - return RelMetadataQuery.distribution(rel.getInputs().get(0)); + public RelDistribution distribution(RelMetadataQuery mq, SetOp rel) { + return mq.distribution(rel.getInputs().get(0)); } - public RelDistribution distribution(TableScan scan) { + public RelDistribution distribution(RelMetadataQuery mq, TableScan scan) { return table(scan.getTable()); } - public RelDistribution distribution(Project project) { - return project(project.getInput(), project.getProjects()); + public RelDistribution distribution(RelMetadataQuery mq, Project project) { + return project(mq, project.getInput(), project.getProjects()); } - public RelDistribution distribution(Values values) { + public RelDistribution distribution(RelMetadataQuery mq, Values values) { return values(values.getRowType(), values.getTuples()); } - public RelDistribution distribution(Exchange exchange) { + public RelDistribution distribution(RelMetadataQuery mq, Exchange exchange) { return exchange(exchange.distribution); } - public RelDistribution distribution(HepRelVertex rel) { - return RelMetadataQuery.distribution(rel.getCurrentRel()); + public RelDistribution distribution(RelMetadataQuery mq, HepRelVertex rel) { + return mq.distribution(rel.getCurrentRel()); } // Helper methods @@ -109,34 +109,33 @@ public class RelMdDistribution { /** Helper method to determine a * {@link Sort}'s distribution. */ - public static RelDistribution sort(RelNode input) { - return RelMetadataQuery.distribution(input); + public static RelDistribution sort(RelMetadataQuery mq, RelNode input) { + return mq.distribution(input); } /** Helper method to determine a * {@link Filter}'s distribution. */ - public static RelDistribution filter(RelNode input) { - return RelMetadataQuery.distribution(input); + public static RelDistribution filter(RelMetadataQuery mq, RelNode input) { + return mq.distribution(input); } /** Helper method to determine a * limit's distribution. */ - public static RelDistribution limit(RelNode input) { - return RelMetadataQuery.distribution(input); + public static RelDistribution limit(RelMetadataQuery mq, RelNode input) { + return mq.distribution(input); } /** Helper method to determine a * {@link org.apache.calcite.rel.core.Calc}'s distribution. */ - public static RelDistribution calc(RelNode input, + public static RelDistribution calc(RelMetadataQuery mq, RelNode input, RexProgram program) { throw new AssertionError(); // TODO: } /** Helper method to determine a {@link Project}'s collation. */ - public static RelDistribution project(RelNode input, + public static RelDistribution project(RelMetadataQuery mq, RelNode input, List<? extends RexNode> projects) { - final RelDistribution inputDistribution = - RelMetadataQuery.distribution(input); + final RelDistribution inputDistribution = mq.distribution(input); final Mappings.TargetMapping mapping = Project.getPartialMapping(input.getRowType().getFieldCount(), projects); http://git-wip-us.apache.org/repos/asf/calcite/blob/cabdcf44/core/src/main/java/org/apache/calcite/rel/metadata/RelMdExplainVisibility.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdExplainVisibility.java b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdExplainVisibility.java index b0d926e..bf51f2f 100644 --- a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdExplainVisibility.java +++ b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdExplainVisibility.java @@ -36,8 +36,14 @@ public class RelMdExplainVisibility { //~ Methods ---------------------------------------------------------------- - // Catch-all rule when none of the others apply. - public Boolean isVisibleInExplain(RelNode rel, SqlExplainLevel explainLevel) { + /** Catch-all implementation for + * {@link BuiltInMetadata.ExplainVisibility#isVisibleInExplain(SqlExplainLevel)}, + * invoked using reflection. + * + * @see org.apache.calcite.rel.metadata.RelMetadataQuery#isVisibleInExplain(RelNode, SqlExplainLevel) + */ + public Boolean isVisibleInExplain(RelNode rel, RelMetadataQuery mq, + SqlExplainLevel explainLevel) { // 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/RelMdMaxRowCount.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdMaxRowCount.java b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdMaxRowCount.java index 1d2a378..ab9739f 100644 --- a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdMaxRowCount.java +++ b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdMaxRowCount.java @@ -16,6 +16,7 @@ */ package org.apache.calcite.rel.metadata; +import org.apache.calcite.adapter.enumerable.EnumerableLimit; import org.apache.calcite.plan.volcano.RelSubset; import org.apache.calcite.rel.RelNode; import org.apache.calcite.rel.core.Aggregate; @@ -29,7 +30,9 @@ import org.apache.calcite.rel.core.TableScan; import org.apache.calcite.rel.core.Union; import org.apache.calcite.rel.core.Values; import org.apache.calcite.rex.RexLiteral; +import org.apache.calcite.util.Bug; import org.apache.calcite.util.BuiltInMethod; +import org.apache.calcite.util.Util; /** * RelMdMaxRowCount supplies a default implementation of @@ -42,10 +45,10 @@ public class RelMdMaxRowCount { //~ Methods ---------------------------------------------------------------- - public Double getMaxRowCount(Union rel) { + public Double getMaxRowCount(Union rel, RelMetadataQuery mq) { double rowCount = 0.0; for (RelNode input : rel.getInputs()) { - Double partialRowCount = RelMetadataQuery.getMaxRowCount(input); + Double partialRowCount = mq.getMaxRowCount(input); if (partialRowCount == null) { return null; } @@ -54,11 +57,11 @@ public class RelMdMaxRowCount { return rowCount; } - public Double getMaxRowCount(Intersect rel) { + public Double getMaxRowCount(Intersect rel, RelMetadataQuery mq) { // max row count is the smallest of the inputs Double rowCount = null; for (RelNode input : rel.getInputs()) { - Double partialRowCount = RelMetadataQuery.getMaxRowCount(input); + Double partialRowCount = mq.getMaxRowCount(input); if (rowCount == null || partialRowCount != null && partialRowCount < rowCount) { rowCount = partialRowCount; @@ -67,22 +70,39 @@ public class RelMdMaxRowCount { return rowCount; } - public Double getMaxRowCount(Minus rel) { - return RelMetadataQuery.getMaxRowCount(rel.getInput(0)); + public Double getMaxRowCount(Minus rel, RelMetadataQuery mq) { + return mq.getMaxRowCount(rel.getInput(0)); } - public Double getMaxRowCount(Filter rel) { - return RelMetadataQuery.getMaxRowCount(rel.getInput()); + public Double getMaxRowCount(Filter rel, RelMetadataQuery mq) { + return mq.getMaxRowCount(rel.getInput()); } - public Double getMaxRowCount(Project rel) { - return RelMetadataQuery.getMaxRowCount(rel.getInput()); + public Double getMaxRowCount(Project rel, RelMetadataQuery mq) { + return mq.getMaxRowCount(rel.getInput()); } - public Double getMaxRowCount(Sort rel) { - Double rowCount = RelMetadataQuery.getMaxRowCount(rel.getInput()); + public Double getMaxRowCount(Sort rel, RelMetadataQuery mq) { + Double rowCount = mq.getMaxRowCount(rel.getInput()); if (rowCount == null) { - return null; + rowCount = Double.POSITIVE_INFINITY; + } + final int offset = rel.offset == null ? 0 : RexLiteral.intValue(rel.offset); + rowCount = Math.max(rowCount - offset, 0D); + + if (rel.fetch != null) { + final int limit = RexLiteral.intValue(rel.fetch); + if (limit < rowCount) { + return (double) limit; + } + } + return rowCount; + } + + public Double getMaxRowCount(EnumerableLimit rel, RelMetadataQuery mq) { + Double rowCount = mq.getMaxRowCount(rel.getInput()); + if (rowCount == null) { + rowCount = Double.POSITIVE_INFINITY; } final int offset = rel.offset == null ? 0 : RexLiteral.intValue(rel.offset); rowCount = Math.max(rowCount - offset, 0D); @@ -96,21 +116,21 @@ public class RelMdMaxRowCount { return rowCount; } - public Double getMaxRowCount(Aggregate rel) { + public Double getMaxRowCount(Aggregate rel, RelMetadataQuery mq) { if (rel.getGroupSet().isEmpty()) { // Aggregate with no GROUP BY always returns 1 row (even on empty table). return 1D; } - final Double rowCount = RelMetadataQuery.getMaxRowCount(rel.getInput()); + final Double rowCount = mq.getMaxRowCount(rel.getInput()); if (rowCount == null) { return null; } return rowCount * rel.getGroupSets().size(); } - public Double getMaxRowCount(Join rel) { - Double left = RelMetadataQuery.getMaxRowCount(rel.getLeft()); - Double right = RelMetadataQuery.getMaxRowCount(rel.getRight()); + public Double getMaxRowCount(Join rel, RelMetadataQuery mq) { + Double left = mq.getMaxRowCount(rel.getLeft()); + Double right = mq.getMaxRowCount(rel.getRight()); if (left == null || right == null) { return null; } @@ -123,20 +143,21 @@ public class RelMdMaxRowCount { return left * right; } - public Double getMaxRowCount(TableScan rel) { + public Double getMaxRowCount(TableScan rel, RelMetadataQuery mq) { // For typical tables, there is no upper bound to the number of rows. return Double.POSITIVE_INFINITY; } - public Double getMaxRowCount(Values values) { + public Double getMaxRowCount(Values values, RelMetadataQuery mq) { // For Values, the maximum row count is the actual row count. // This is especially useful if Values is empty. return (double) values.getTuples().size(); } - public Double getMaxRowCount(RelSubset rel) { - // FIXME This is a short-term fix for CALCITE-1018. A complete - // solution will come with CALCITE-794. + public Double getMaxRowCount(RelSubset rel, RelMetadataQuery mq) { + // FIXME This is a short-term fix for [CALCITE-1018]. A complete + // solution will come with [CALCITE-1048]. + Util.discard(Bug.CALCITE_1048_FIXED); for (RelNode node : rel.getRels()) { if (node instanceof Sort) { Sort sort = (Sort) node; @@ -150,7 +171,7 @@ public class RelMdMaxRowCount { } // Catch-all rule when none of the others apply. - public Double getMaxRowCount(RelNode rel) { + public Double getMaxRowCount(RelNode rel, RelMetadataQuery mq) { return null; } } http://git-wip-us.apache.org/repos/asf/calcite/blob/cabdcf44/core/src/main/java/org/apache/calcite/rel/metadata/RelMdMemory.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdMemory.java b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdMemory.java index be53b5c..c760b0e 100644 --- a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdMemory.java +++ b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdMemory.java @@ -43,34 +43,34 @@ public class RelMdMemory { //~ Methods ---------------------------------------------------------------- /** Catch-all implementation for - * {@link org.apache.calcite.rel.metadata.BuiltInMetadata.Memory#memory()}, + * {@link BuiltInMetadata.Memory#memory()}, * invoked using reflection. * * @see org.apache.calcite.rel.metadata.RelMetadataQuery#memory */ - public Double memory(RelNode rel) { + public Double memory(RelNode rel, RelMetadataQuery mq) { return null; } /** Catch-all implementation for - * {@link org.apache.calcite.rel.metadata.BuiltInMetadata.Memory#cumulativeMemoryWithinPhase()}, + * {@link BuiltInMetadata.Memory#cumulativeMemoryWithinPhase()}, * invoked using reflection. * * @see org.apache.calcite.rel.metadata.RelMetadataQuery#memory */ - public Double cumulativeMemoryWithinPhase(RelNode rel) { - Double nullable = RelMetadataQuery.memory(rel); + public Double cumulativeMemoryWithinPhase(RelNode rel, RelMetadataQuery mq) { + Double nullable = mq.memory(rel); if (nullable == null) { return null; } - Boolean isPhaseTransition = RelMetadataQuery.isPhaseTransition(rel); + Boolean isPhaseTransition = mq.isPhaseTransition(rel); if (isPhaseTransition == null) { return null; } double d = nullable; if (!isPhaseTransition) { for (RelNode input : rel.getInputs()) { - nullable = RelMetadataQuery.cumulativeMemoryWithinPhase(input); + nullable = mq.cumulativeMemoryWithinPhase(input); if (nullable == null) { return null; } @@ -81,15 +81,15 @@ public class RelMdMemory { } /** Catch-all implementation for - * {@link org.apache.calcite.rel.metadata.BuiltInMetadata.Memory#cumulativeMemoryWithinPhaseSplit()}, + * {@link BuiltInMetadata.Memory#cumulativeMemoryWithinPhaseSplit()}, * invoked using reflection. * * @see org.apache.calcite.rel.metadata.RelMetadataQuery#cumulativeMemoryWithinPhaseSplit */ - public Double cumulativeMemoryWithinPhaseSplit(RelNode rel) { - final Double memoryWithinPhase = - RelMetadataQuery.cumulativeMemoryWithinPhase(rel); - final Integer splitCount = RelMetadataQuery.splitCount(rel); + public Double cumulativeMemoryWithinPhaseSplit(RelNode rel, + RelMetadataQuery mq) { + final Double memoryWithinPhase = mq.cumulativeMemoryWithinPhase(rel); + final Integer splitCount = mq.splitCount(rel); if (memoryWithinPhase == null || splitCount == null) { return null; } http://git-wip-us.apache.org/repos/asf/calcite/blob/cabdcf44/core/src/main/java/org/apache/calcite/rel/metadata/RelMdParallelism.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdParallelism.java b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdParallelism.java index ca9c244..dcd69f1 100644 --- a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdParallelism.java +++ b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdParallelism.java @@ -45,34 +45,34 @@ public class RelMdParallelism { //~ Methods ---------------------------------------------------------------- /** Catch-all implementation for - * {@link org.apache.calcite.rel.metadata.BuiltInMetadata.Parallelism#isPhaseTransition()}, + * {@link BuiltInMetadata.Parallelism#isPhaseTransition()}, * invoked using reflection. * * @see org.apache.calcite.rel.metadata.RelMetadataQuery#isPhaseTransition */ - public Boolean isPhaseTransition(RelNode rel) { + public Boolean isPhaseTransition(RelNode rel, RelMetadataQuery mq) { return false; } - public Boolean isPhaseTransition(TableScan rel) { + public Boolean isPhaseTransition(TableScan rel, RelMetadataQuery mq) { return true; } - public Boolean isPhaseTransition(Values rel) { + public Boolean isPhaseTransition(Values rel, RelMetadataQuery mq) { return true; } - public Boolean isPhaseTransition(Exchange rel) { + public Boolean isPhaseTransition(Exchange rel, RelMetadataQuery mq) { return true; } /** Catch-all implementation for - * {@link org.apache.calcite.rel.metadata.BuiltInMetadata.Parallelism#splitCount()}, + * {@link BuiltInMetadata.Parallelism#splitCount()}, * invoked using reflection. * * @see org.apache.calcite.rel.metadata.RelMetadataQuery#splitCount */ - public Integer splitCount(RelNode rel) { + public Integer splitCount(RelNode rel, RelMetadataQuery mq) { return 1; } } http://git-wip-us.apache.org/repos/asf/calcite/blob/cabdcf44/core/src/main/java/org/apache/calcite/rel/metadata/RelMdPercentageOriginalRows.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdPercentageOriginalRows.java b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdPercentageOriginalRows.java index 991a488..bde07a9 100644 --- a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdPercentageOriginalRows.java +++ b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdPercentageOriginalRows.java @@ -53,16 +53,14 @@ public class RelMdPercentageOriginalRows { private RelMdPercentageOriginalRows() {} - public Double getPercentageOriginalRows(Aggregate rel) { + public Double getPercentageOriginalRows(Aggregate rel, RelMetadataQuery mq) { // REVIEW jvs 28-Mar-2006: The assumption here seems to be that // aggregation does not apply any filtering, so it does not modify the // percentage. That's very much oversimplified. - - return RelMetadataQuery.getPercentageOriginalRows( - rel.getInput()); + return mq.getPercentageOriginalRows(rel.getInput()); } - public Double getPercentageOriginalRows(Union rel) { + public Double getPercentageOriginalRows(Union rel, RelMetadataQuery mq) { double numerator = 0.0; double denominator = 0.0; @@ -77,9 +75,8 @@ public class RelMdPercentageOriginalRows { // case where a huge table has been completely filtered away. for (RelNode input : rel.getInputs()) { - double rowCount = RelMetadataQuery.getRowCount(input); - double percentage = - RelMetadataQuery.getPercentageOriginalRows(input); + double rowCount = mq.getRowCount(input); + double percentage = mq.getPercentageOriginalRows(input); if (percentage != 0.0) { denominator += rowCount / percentage; numerator += rowCount; @@ -89,7 +86,7 @@ public class RelMdPercentageOriginalRows { return quotientForPercentage(numerator, denominator); } - public Double getPercentageOriginalRows(Join rel) { + public Double getPercentageOriginalRows(Join rel, RelMetadataQuery mq) { // Assume any single-table filter conditions have already // been pushed down. @@ -98,16 +95,13 @@ public class RelMdPercentageOriginalRows { // REVIEW jvs 28-Mar-2006: need any special casing for SemiJoin? - double left = RelMetadataQuery.getPercentageOriginalRows(rel.getLeft()); - - double right = - RelMetadataQuery.getPercentageOriginalRows(rel.getRight()); - + double left = mq.getPercentageOriginalRows(rel.getLeft()); + double right = mq.getPercentageOriginalRows(rel.getRight()); return left * right; } // Catch-all rule when none of the others apply. - public Double getPercentageOriginalRows(RelNode rel) { + public Double getPercentageOriginalRows(RelNode rel, RelMetadataQuery mq) { if (rel.getInputs().size() > 1) { // No generic formula available for multiple inputs. return null; @@ -120,8 +114,7 @@ public class RelMdPercentageOriginalRows { RelNode child = rel.getInputs().get(0); - Double childPercentage = - RelMetadataQuery.getPercentageOriginalRows(child); + Double childPercentage = mq.getPercentageOriginalRows(child); if (childPercentage == null) { return null; } @@ -130,9 +123,7 @@ public class RelMdPercentageOriginalRows { // filtering is the effect of single-table filters) with the percentage // filtering performed by the child. Double relPercentage = - quotientForPercentage( - RelMetadataQuery.getRowCount(rel), - RelMetadataQuery.getRowCount(child)); + quotientForPercentage(mq.getRowCount(rel), mq.getRowCount(child)); if (relPercentage == null) { return null; } @@ -147,22 +138,23 @@ public class RelMdPercentageOriginalRows { } // Ditto for getNonCumulativeCost - public RelOptCost getCumulativeCost(RelNode rel) { - RelOptCost cost = RelMetadataQuery.getNonCumulativeCost(rel); + public RelOptCost getCumulativeCost(RelNode rel, RelMetadataQuery mq) { + RelOptCost cost = mq.getNonCumulativeCost(rel); List<RelNode> inputs = rel.getInputs(); for (RelNode input : inputs) { - cost = cost.plus(RelMetadataQuery.getCumulativeCost(input)); + cost = cost.plus(mq.getCumulativeCost(input)); } return cost; } - public RelOptCost getCumulativeCost(EnumerableInterpreter rel) { - return RelMetadataQuery.getNonCumulativeCost(rel); + public RelOptCost getCumulativeCost(EnumerableInterpreter rel, + RelMetadataQuery mq) { + return mq.getNonCumulativeCost(rel); } // Ditto for getNonCumulativeCost - public RelOptCost getNonCumulativeCost(RelNode rel) { - return rel.computeSelfCost(rel.getCluster().getPlanner()); + public RelOptCost getNonCumulativeCost(RelNode rel, RelMetadataQuery mq) { + return rel.computeSelfCost(rel.getCluster().getPlanner(), mq); } private static Double quotientForPercentage( http://git-wip-us.apache.org/repos/asf/calcite/blob/cabdcf44/core/src/main/java/org/apache/calcite/rel/metadata/RelMdPopulationSize.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdPopulationSize.java b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdPopulationSize.java index 47c0fcc..180883f 100644 --- a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdPopulationSize.java +++ b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdPopulationSize.java @@ -47,28 +47,26 @@ public class RelMdPopulationSize { //~ Methods ---------------------------------------------------------------- - public Double getPopulationSize(Filter rel, ImmutableBitSet groupKey) { - return RelMetadataQuery.getPopulationSize( - rel.getInput(), - groupKey); + public Double getPopulationSize(Filter rel, RelMetadataQuery mq, + ImmutableBitSet groupKey) { + return mq.getPopulationSize(rel.getInput(), groupKey); } - public Double getPopulationSize(Sort rel, ImmutableBitSet groupKey) { - return RelMetadataQuery.getPopulationSize( - rel.getInput(), - groupKey); + public Double getPopulationSize(Sort rel, RelMetadataQuery mq, + ImmutableBitSet groupKey) { + return mq.getPopulationSize(rel.getInput(), groupKey); } - public Double getPopulationSize(Exchange rel, ImmutableBitSet groupKey) { - return RelMetadataQuery.getPopulationSize( - rel.getInput(), - groupKey); + public Double getPopulationSize(Exchange rel, RelMetadataQuery mq, + ImmutableBitSet groupKey) { + return mq.getPopulationSize(rel.getInput(), groupKey); } - public Double getPopulationSize(Union rel, ImmutableBitSet groupKey) { + public Double getPopulationSize(Union rel, RelMetadataQuery mq, + ImmutableBitSet groupKey) { Double population = 0.0; for (RelNode input : rel.getInputs()) { - Double subPop = RelMetadataQuery.getPopulationSize(input, groupKey); + Double subPop = mq.getPopulationSize(input, groupKey); if (subPop == null) { return null; } @@ -77,35 +75,38 @@ public class RelMdPopulationSize { return population; } - public Double getPopulationSize(Join rel, ImmutableBitSet groupKey) { - return RelMdUtil.getJoinPopulationSize(rel, groupKey); + public Double getPopulationSize(Join rel, RelMetadataQuery mq, + ImmutableBitSet groupKey) { + return RelMdUtil.getJoinPopulationSize(mq, rel, groupKey); } - public Double getPopulationSize(SemiJoin rel, ImmutableBitSet groupKey) { - return RelMetadataQuery.getPopulationSize(rel.getLeft(), groupKey); + public Double getPopulationSize(SemiJoin rel, RelMetadataQuery mq, + ImmutableBitSet groupKey) { + return mq.getPopulationSize(rel.getLeft(), groupKey); } - public Double getPopulationSize(Aggregate rel, ImmutableBitSet groupKey) { + public Double getPopulationSize(Aggregate rel, RelMetadataQuery mq, + ImmutableBitSet groupKey) { ImmutableBitSet.Builder childKey = ImmutableBitSet.builder(); RelMdUtil.setAggChildKeys(groupKey, rel, childKey); - return RelMetadataQuery.getPopulationSize(rel.getInput(), childKey.build()); + return mq.getPopulationSize(rel.getInput(), childKey.build()); } - public Double getPopulationSize(Values rel, ImmutableBitSet groupKey) { + public Double getPopulationSize(Values rel, RelMetadataQuery mq, + ImmutableBitSet groupKey) { // assume half the rows are duplicates - return rel.getRows() / 2; + return rel.estimateRowCount(mq) / 2; } - public Double getPopulationSize(Project rel, ImmutableBitSet groupKey) { + public Double getPopulationSize(Project rel, RelMetadataQuery mq, + ImmutableBitSet groupKey) { ImmutableBitSet.Builder baseCols = ImmutableBitSet.builder(); ImmutableBitSet.Builder projCols = ImmutableBitSet.builder(); List<RexNode> projExprs = rel.getProjects(); RelMdUtil.splitCols(projExprs, groupKey, baseCols, projCols); Double population = - RelMetadataQuery.getPopulationSize( - rel.getInput(), - baseCols.build()); + mq.getPopulationSize(rel.getInput(), baseCols.build()); if (population == null) { return null; } @@ -118,7 +119,7 @@ public class RelMdPopulationSize { for (int bit : projCols.build()) { Double subRowCount = - RelMdUtil.cardOfProjExpr(rel, projExprs.get(bit)); + RelMdUtil.cardOfProjExpr(mq, rel, projExprs.get(bit)); if (subRowCount == null) { return null; } @@ -128,22 +129,26 @@ public class RelMdPopulationSize { // REVIEW zfong 6/22/06 - Broadbase did not have the call to // numDistinctVals. This is needed; otherwise, population can be // larger than the number of rows in the RelNode. - return RelMdUtil.numDistinctVals( - population, - RelMetadataQuery.getRowCount(rel)); + return RelMdUtil.numDistinctVals(population, mq.getRowCount(rel)); } - // Catch-all rule when none of the others apply. - public Double getPopulationSize(RelNode rel, ImmutableBitSet groupKey) { + /** Catch-all implementation for + * {@link BuiltInMetadata.PopulationSize#getPopulationSize(ImmutableBitSet)}, + * invoked using reflection. + * + * @see org.apache.calcite.rel.metadata.RelMetadataQuery#getPopulationSize(RelNode, ImmutableBitSet) + */ + public Double getPopulationSize(RelNode rel, RelMetadataQuery mq, + ImmutableBitSet groupKey) { // if the keys are unique, return the row count; otherwise, we have // no further information on which to return any legitimate value // REVIEW zfong 4/11/06 - Broadbase code returns the product of each // unique key, which would result in the population being larger // than the total rows in the relnode - boolean uniq = RelMdUtil.areColumnsDefinitelyUnique(rel, groupKey); + boolean uniq = RelMdUtil.areColumnsDefinitelyUnique(mq, rel, groupKey); if (uniq) { - return RelMetadataQuery.getRowCount(rel); + return mq.getRowCount(rel); } return null; http://git-wip-us.apache.org/repos/asf/calcite/blob/cabdcf44/core/src/main/java/org/apache/calcite/rel/metadata/RelMdPredicates.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdPredicates.java b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdPredicates.java index 2119abf..4b1a894 100644 --- a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdPredicates.java +++ b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdPredicates.java @@ -21,6 +21,7 @@ import org.apache.calcite.linq4j.Ord; import org.apache.calcite.linq4j.function.Predicate1; import org.apache.calcite.plan.RelOptPredicateList; import org.apache.calcite.plan.RelOptUtil; +import org.apache.calcite.plan.hep.HepRelVertex; import org.apache.calcite.plan.volcano.RelSubset; import org.apache.calcite.rel.RelNode; import org.apache.calcite.rel.core.Aggregate; @@ -120,15 +121,26 @@ public class RelMdPredicates { private static final List<RexNode> EMPTY_LIST = ImmutableList.of(); - // Catch-all rule when none of the others apply. - public RelOptPredicateList getPredicates(RelNode rel) { + /** Catch-all implementation for + * {@link BuiltInMetadata.Predicates#getPredicates()}, + * invoked using reflection. + * + * @see org.apache.calcite.rel.metadata.RelMetadataQuery#getPulledUpPredicates(RelNode) + */ + public RelOptPredicateList getPredicates(RelNode rel, RelMetadataQuery mq) { return RelOptPredicateList.EMPTY; } + public RelOptPredicateList getPredicates(HepRelVertex rel, + RelMetadataQuery mq) { + return mq.getPulledUpPredicates(rel.getCurrentRel()); + } + /** * Infers predicates for a table scan. */ - public RelOptPredicateList getPredicates(TableScan table) { + public RelOptPredicateList getPredicates(TableScan table, + RelMetadataQuery mq) { return RelOptPredicateList.EMPTY; } @@ -144,24 +156,23 @@ public class RelMdPredicates { * is not in the projection list. * * <pre> - * childPullUpExprs: {a > 7, b + c < 10, a + e = 9} + * inputPullUpExprs: {a > 7, b + c < 10, a + e = 9} * projectionExprs: {a, b, c, e / 2} * projectionPullupExprs: {a > 7, b + c < 10} * </pre> * * </ol> */ - public RelOptPredicateList getPredicates(Project project) { - RelNode child = project.getInput(); + public RelOptPredicateList getPredicates(Project project, + RelMetadataQuery mq) { + final RelNode input = project.getInput(); final RexBuilder rexBuilder = project.getCluster().getRexBuilder(); - RelOptPredicateList childInfo = - RelMetadataQuery.getPulledUpPredicates(child); - - List<RexNode> projectPullUpPredicates = new ArrayList<RexNode>(); + final RelOptPredicateList inputInfo = mq.getPulledUpPredicates(input); + final List<RexNode> projectPullUpPredicates = new ArrayList<>(); ImmutableBitSet.Builder columnsMappedBuilder = ImmutableBitSet.builder(); Mapping m = Mappings.create(MappingType.PARTIAL_FUNCTION, - child.getRowType().getFieldCount(), + input.getRowType().getFieldCount(), project.getRowType().getFieldCount()); for (Ord<RexNode> o : Ord.zip(project.getProjects())) { @@ -175,10 +186,10 @@ public class RelMdPredicates { // Go over childPullUpPredicates. If a predicate only contains columns in // 'columnsMapped' construct a new predicate based on mapping. final ImmutableBitSet columnsMapped = columnsMappedBuilder.build(); - for (RexNode r : childInfo.pulledUpPredicates) { + for (RexNode r : inputInfo.pulledUpPredicates) { ImmutableBitSet rCols = RelOptUtil.InputFinder.bits(r); if (columnsMapped.contains(rCols)) { - r = r.accept(new RexPermuteInputsShuttle(m, child)); + r = r.accept(new RexPermuteInputsShuttle(m, input)); projectPullUpPredicates.add(r); } } @@ -203,29 +214,27 @@ public class RelMdPredicates { } /** - * Add the Filter condition to the pulledPredicates list from the child. + * Add the Filter condition to the pulledPredicates list from the input. */ - public RelOptPredicateList getPredicates(Filter filter) { - RelNode child = filter.getInput(); - RelOptPredicateList childInfo = - RelMetadataQuery.getPulledUpPredicates(child); + public RelOptPredicateList getPredicates(Filter filter, RelMetadataQuery mq) { + final RelNode input = filter.getInput(); + final RelOptPredicateList inputInfo = mq.getPulledUpPredicates(input); - return Util.first(childInfo, RelOptPredicateList.EMPTY) + return Util.first(inputInfo, RelOptPredicateList.EMPTY) .union( RelOptPredicateList.of( RelOptUtil.conjunctions(filter.getCondition()))); } /** Infers predicates for a {@link org.apache.calcite.rel.core.SemiJoin}. */ - public RelOptPredicateList getPredicates(SemiJoin semiJoin) { + public RelOptPredicateList getPredicates(SemiJoin semiJoin, + RelMetadataQuery mq) { RexBuilder rB = semiJoin.getCluster().getRexBuilder(); - RelNode left = semiJoin.getInput(0); - RelNode right = semiJoin.getInput(1); + final RelNode left = semiJoin.getInput(0); + final RelNode right = semiJoin.getInput(1); - RelOptPredicateList leftInfo = - RelMetadataQuery.getPulledUpPredicates(left); - RelOptPredicateList rightInfo = - RelMetadataQuery.getPulledUpPredicates(right); + final RelOptPredicateList leftInfo = mq.getPulledUpPredicates(left); + final RelOptPredicateList rightInfo = mq.getPulledUpPredicates(right); JoinConditionBasedPredicateInference jI = new JoinConditionBasedPredicateInference(semiJoin, @@ -236,15 +245,13 @@ public class RelMdPredicates { } /** Infers predicates for a {@link org.apache.calcite.rel.core.Join}. */ - public RelOptPredicateList getPredicates(Join join) { + public RelOptPredicateList getPredicates(Join join, RelMetadataQuery mq) { RexBuilder rB = join.getCluster().getRexBuilder(); RelNode left = join.getInput(0); RelNode right = join.getInput(1); - RelOptPredicateList leftInfo = - RelMetadataQuery.getPulledUpPredicates(left); - RelOptPredicateList rightInfo = - RelMetadataQuery.getPulledUpPredicates(right); + final RelOptPredicateList leftInfo = mq.getPulledUpPredicates(left); + final RelOptPredicateList rightInfo = mq.getPulledUpPredicates(right); JoinConditionBasedPredicateInference jI = new JoinConditionBasedPredicateInference(join, @@ -262,31 +269,29 @@ public class RelMdPredicates { * GroupSet. For e.g. * * <pre> - * childPullUpExprs : { a > 7, b + c < 10, a + e = 9} + * inputPullUpExprs : { a > 7, b + c < 10, a + e = 9} * groupSet : { a, b} * pulledUpExprs : { a > 7} * </pre> */ - public RelOptPredicateList getPredicates(Aggregate agg) { - RelNode child = agg.getInput(); - RelOptPredicateList childInfo = - RelMetadataQuery.getPulledUpPredicates(child); - - List<RexNode> aggPullUpPredicates = new ArrayList<RexNode>(); + public RelOptPredicateList getPredicates(Aggregate agg, RelMetadataQuery mq) { + final RelNode input = agg.getInput(); + final RelOptPredicateList inputInfo = mq.getPulledUpPredicates(input); + final List<RexNode> aggPullUpPredicates = new ArrayList<>(); ImmutableBitSet groupKeys = agg.getGroupSet(); Mapping m = Mappings.create(MappingType.PARTIAL_FUNCTION, - child.getRowType().getFieldCount(), agg.getRowType().getFieldCount()); + input.getRowType().getFieldCount(), agg.getRowType().getFieldCount()); int i = 0; for (int j : groupKeys) { m.set(j, i++); } - for (RexNode r : childInfo.pulledUpPredicates) { + for (RexNode r : inputInfo.pulledUpPredicates) { ImmutableBitSet rCols = RelOptUtil.InputFinder.bits(r); if (groupKeys.contains(rCols)) { - r = r.accept(new RexPermuteInputsShuttle(m, child)); + r = r.accept(new RexPermuteInputsShuttle(m, input)); aggPullUpPredicates.add(r); } } @@ -298,11 +303,11 @@ public class RelMdPredicates { * * <p>The pulled up expression is a disjunction of its children's predicates. */ - public RelOptPredicateList getPredicates(Union union) { + public RelOptPredicateList getPredicates(Union union, RelMetadataQuery mq) { RexBuilder rB = union.getCluster().getRexBuilder(); List<RexNode> orList = Lists.newArrayList(); for (RelNode input : union.getInputs()) { - RelOptPredicateList info = RelMetadataQuery.getPulledUpPredicates(input); + RelOptPredicateList info = mq.getPulledUpPredicates(input); if (info.pulledUpPredicates.isEmpty()) { return RelOptPredicateList.EMPTY; } @@ -321,27 +326,29 @@ public class RelMdPredicates { /** * Infers predicates for a Sort. */ - public RelOptPredicateList getPredicates(Sort sort) { - RelNode child = sort.getInput(); - return RelMetadataQuery.getPulledUpPredicates(child); + public RelOptPredicateList getPredicates(Sort sort, RelMetadataQuery mq) { + RelNode input = sort.getInput(); + return mq.getPulledUpPredicates(input); } /** * Infers predicates for an Exchange. */ - public RelOptPredicateList getPredicates(Exchange exchange) { - RelNode child = exchange.getInput(); - return RelMetadataQuery.getPulledUpPredicates(child); + public RelOptPredicateList getPredicates(Exchange exchange, + RelMetadataQuery mq) { + RelNode input = exchange.getInput(); + return mq.getPulledUpPredicates(input); } /** @see RelMetadataQuery#getPulledUpPredicates(RelNode) */ - public RelOptPredicateList getPredicates(RelSubset r) { - if (!Bug.CALCITE_794_FIXED) { + public RelOptPredicateList getPredicates(RelSubset r, + RelMetadataQuery mq) { + if (!Bug.CALCITE_1048_FIXED) { return RelOptPredicateList.EMPTY; } RelOptPredicateList list = null; for (RelNode r2 : r.getRels()) { - RelOptPredicateList list2 = RelMetadataQuery.getPulledUpPredicates(r2); + RelOptPredicateList list2 = mq.getPulledUpPredicates(r2); if (list2 != null) { list = list == null ? list2 : list.union(list2); } @@ -409,7 +416,7 @@ public class RelMdPredicates { nSysFields + nFieldsLeft + nFieldsRight); exprFields = Maps.newHashMap(); - allExprsDigests = new HashSet<String>(); + allExprsDigests = new HashSet<>(); if (lPreds == null) { leftChildPredicates = null; @@ -440,7 +447,7 @@ public class RelMdPredicates { } equivalence = Maps.newTreeMap(); - equalityPredicates = new HashSet<String>(); + equalityPredicates = new HashSet<>(); for (int i = 0; i < nSysFields + nFieldsLeft + nFieldsRight; i++) { equivalence.put(i, BitSets.of(i)); } @@ -454,11 +461,13 @@ public class RelMdPredicates { compose(rexBuilder, ImmutableList.of(joinRel.getCondition()))); final EquivalenceFinder eF = new EquivalenceFinder(); - new ArrayList<Void>(Lists.transform(exprs, new Function<RexNode, Void>() { - public Void apply(RexNode input) { - return input.accept(eF); - } - })); + new ArrayList<>( + Lists.transform(exprs, + new Function<RexNode, Void>() { + public Void apply(RexNode input) { + return input.accept(eF); + } + })); equivalence = BitSets.closure(equivalence); } @@ -478,8 +487,8 @@ public class RelMdPredicates { */ public RelOptPredicateList inferPredicates( boolean includeEqualityInference) { - List<RexNode> inferredPredicates = new ArrayList<RexNode>(); - Set<String> allExprsDigests = new HashSet<String>(this.allExprsDigests); + final List<RexNode> inferredPredicates = new ArrayList<>(); + final Set<String> allExprsDigests = new HashSet<>(this.allExprsDigests); final JoinRelType joinType = joinRel.getJoinType(); switch (joinType) { case INNER: @@ -509,9 +518,8 @@ public class RelMdPredicates { nSysFields + nFieldsLeft, 0, nSysFields, nFieldsLeft); final RexPermuteInputsShuttle leftPermute = new RexPermuteInputsShuttle(leftMapping, joinRel); - - List<RexNode> leftInferredPredicates = new ArrayList<RexNode>(); - List<RexNode> rightInferredPredicates = new ArrayList<RexNode>(); + final List<RexNode> leftInferredPredicates = new ArrayList<>(); + final List<RexNode> rightInferredPredicates = new ArrayList<>(); for (RexNode iP : inferredPredicates) { ImmutableBitSet iPBitSet = RelOptUtil.InputFinder.bits(iP); http://git-wip-us.apache.org/repos/asf/calcite/blob/cabdcf44/core/src/main/java/org/apache/calcite/rel/metadata/RelMdRowCount.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdRowCount.java b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdRowCount.java index aac3aae..ea647a6 100644 --- a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdRowCount.java +++ b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdRowCount.java @@ -16,20 +16,29 @@ */ package org.apache.calcite.rel.metadata; +import org.apache.calcite.adapter.enumerable.EnumerableLimit; +import org.apache.calcite.plan.volcano.RelSubset; import org.apache.calcite.rel.RelNode; +import org.apache.calcite.rel.SingleRel; import org.apache.calcite.rel.core.Aggregate; +import org.apache.calcite.rel.core.Calc; import org.apache.calcite.rel.core.Filter; import org.apache.calcite.rel.core.Intersect; +import org.apache.calcite.rel.core.Join; 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.Sort; +import org.apache.calcite.rel.core.TableScan; import org.apache.calcite.rel.core.Union; +import org.apache.calcite.rel.core.Values; import org.apache.calcite.rex.RexLiteral; import org.apache.calcite.rex.RexNode; +import org.apache.calcite.util.Bug; import org.apache.calcite.util.BuiltInMethod; import org.apache.calcite.util.ImmutableBitSet; import org.apache.calcite.util.NumberUtil; +import org.apache.calcite.util.Util; /** * RelMdRowCount supplies a default implementation of @@ -42,10 +51,37 @@ public class RelMdRowCount { //~ Methods ---------------------------------------------------------------- - public Double getRowCount(Union rel) { - double rowCount = 0D; + /** Catch-all implementation for + * {@link BuiltInMetadata.RowCount#getRowCount()}, + * invoked using reflection. + * + * @see org.apache.calcite.rel.metadata.RelMetadataQuery#getRowCount(RelNode) + */ + public Double getRowCount(RelNode rel, RelMetadataQuery mq) { + return rel.estimateRowCount(mq); + } + + public Double getRowCount(RelSubset subset, RelMetadataQuery mq) { + if (!Bug.CALCITE_1048_FIXED) { + return mq.getRowCount(Util.first(subset.getBest(), subset.getOriginal())); + } + Double v = null; + for (RelNode r : subset.getRels()) { + try { + v = NumberUtil.min(v, mq.getRowCount(r)); + } catch (CyclicMetadataException e) { + // ignore this rel; there will be other, non-cyclic ones + } catch (Throwable e) { + e.printStackTrace(); + } + } + return Util.first(v, 1e6d); // if set is empty, estimate large + } + + public Double getRowCount(Union rel, RelMetadataQuery mq) { + double rowCount = 0.0; for (RelNode input : rel.getInputs()) { - Double partialRowCount = RelMetadataQuery.getRowCount(input); + Double partialRowCount = mq.getRowCount(input); if (partialRowCount == null) { return null; } @@ -54,10 +90,10 @@ public class RelMdRowCount { return rowCount; } - public Double getRowCount(Intersect rel) { + public Double getRowCount(Intersect rel, RelMetadataQuery mq) { Double rowCount = null; for (RelNode input : rel.getInputs()) { - Double partialRowCount = RelMetadataQuery.getRowCount(input); + Double partialRowCount = mq.getRowCount(input); if (rowCount == null || partialRowCount != null && partialRowCount < rowCount) { rowCount = partialRowCount; @@ -66,10 +102,10 @@ public class RelMdRowCount { return rowCount; } - public Double getRowCount(Minus rel) { + public Double getRowCount(Minus rel, RelMetadataQuery mq) { Double rowCount = null; for (RelNode input : rel.getInputs()) { - Double partialRowCount = RelMetadataQuery.getRowCount(input); + Double partialRowCount = mq.getRowCount(input); if (rowCount == null || partialRowCount != null && partialRowCount < rowCount) { rowCount = partialRowCount; @@ -78,20 +114,21 @@ public class RelMdRowCount { return rowCount; } - public Double getRowCount(Filter rel) { - return NumberUtil.multiply( - RelMetadataQuery.getSelectivity( - rel.getInput(), - rel.getCondition()), - RelMetadataQuery.getRowCount(rel.getInput())); + public Double getRowCount(Filter rel, RelMetadataQuery mq) { + return RelMdUtil.estimateFilteredRows(rel.getInput(), rel.getCondition(), + mq); } - public Double getRowCount(Project rel) { - return RelMetadataQuery.getRowCount(rel.getInput()); + public Double getRowCount(Calc rel, RelMetadataQuery mq) { + return RelMdUtil.estimateFilteredRows(rel.getInput(), rel.getProgram(), mq); } - public Double getRowCount(Sort rel) { - Double rowCount = RelMetadataQuery.getRowCount(rel.getInput()); + public Double getRowCount(Project rel, RelMetadataQuery mq) { + return mq.getRowCount(rel.getInput()); + } + + public Double getRowCount(Sort rel, RelMetadataQuery mq) { + Double rowCount = mq.getRowCount(rel.getInput()); if (rowCount == null) { return null; } @@ -107,30 +144,51 @@ public class RelMdRowCount { return rowCount; } - public Double getRowCount(SemiJoin rel) { + public Double getRowCount(EnumerableLimit rel, RelMetadataQuery mq) { + Double rowCount = mq.getRowCount(rel.getInput()); + if (rowCount == null) { + return null; + } + final int offset = rel.offset == null ? 0 : RexLiteral.intValue(rel.offset); + rowCount = Math.max(rowCount - offset, 0D); + + if (rel.fetch != null) { + final int limit = RexLiteral.intValue(rel.fetch); + if (limit < rowCount) { + return (double) limit; + } + } + return rowCount; + } + + // Covers Converter, Interpreter + public Double getRowCount(SingleRel rel, RelMetadataQuery mq) { + return mq.getRowCount(rel.getInput()); + } + + public Double getRowCount(Join rel, RelMetadataQuery mq) { + return RelMdUtil.getJoinRowCount(mq, rel, rel.getCondition()); + } + + public Double getRowCount(SemiJoin rel, RelMetadataQuery mq) { // create a RexNode representing the selectivity of the // semijoin filter and pass it to getSelectivity RexNode semiJoinSelectivity = - RelMdUtil.makeSemiJoinSelectivityRexNode(rel); + RelMdUtil.makeSemiJoinSelectivityRexNode(mq, rel); return NumberUtil.multiply( - RelMetadataQuery.getSelectivity( - rel.getLeft(), - semiJoinSelectivity), - RelMetadataQuery.getRowCount(rel.getLeft())); + mq.getSelectivity(rel.getLeft(), semiJoinSelectivity), + mq.getRowCount(rel.getLeft())); } - public Double getRowCount(Aggregate rel) { - ImmutableBitSet groupKey = rel.getGroupSet(); + public Double getRowCount(Aggregate rel, RelMetadataQuery mq) { + ImmutableBitSet groupKey = rel.getGroupSet(); // .range(rel.getGroupCount()); - // rowcount is the cardinality of the group by columns + // rowCount is the cardinality of the group by columns Double distinctRowCount = - RelMetadataQuery.getDistinctRowCount( - rel.getInput(), - groupKey, - null); + mq.getDistinctRowCount(rel.getInput(), groupKey, null); if (distinctRowCount == null) { - distinctRowCount = RelMetadataQuery.getRowCount(rel.getInput()) / 10D; + distinctRowCount = mq.getRowCount(rel.getInput()) / 10; } // Grouping sets multiply @@ -139,9 +197,12 @@ public class RelMdRowCount { return distinctRowCount; } - // Catch-all rule when none of the others apply. - public Double getRowCount(RelNode rel) { - return rel.getRows(); + public Double getRowCount(TableScan rel, RelMetadataQuery mq) { + return rel.estimateRowCount(mq); + } + + public Double getRowCount(Values rel, RelMetadataQuery mq) { + return rel.estimateRowCount(mq); } } http://git-wip-us.apache.org/repos/asf/calcite/blob/cabdcf44/core/src/main/java/org/apache/calcite/rel/metadata/RelMdSelectivity.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdSelectivity.java b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdSelectivity.java index c59a005..b7ffcdd 100644 --- a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdSelectivity.java +++ b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdSelectivity.java @@ -50,7 +50,8 @@ public class RelMdSelectivity { //~ Methods ---------------------------------------------------------------- - public Double getSelectivity(Union rel, RexNode predicate) { + public Double getSelectivity(Union rel, RelMetadataQuery mq, + RexNode predicate) { if ((rel.getInputs().size() == 0) || (predicate == null)) { return 1.0; } @@ -60,7 +61,7 @@ public class RelMdSelectivity { int[] adjustments = new int[rel.getRowType().getFieldCount()]; RexBuilder rexBuilder = rel.getCluster().getRexBuilder(); for (RelNode input : rel.getInputs()) { - Double nRows = RelMetadataQuery.getRowCount(input); + Double nRows = mq.getRowCount(input); if (nRows == null) { return null; } @@ -73,7 +74,7 @@ public class RelMdSelectivity { null, input.getRowType().getFieldList(), adjustments)); - double sel = RelMetadataQuery.getSelectivity(input, modifiedPred); + double sel = mq.getSelectivity(input, modifiedPred); sumRows += nRows; sumSelectedRows += nRows * sel; @@ -85,36 +86,34 @@ public class RelMdSelectivity { return sumSelectedRows / sumRows; } - public Double getSelectivity(Sort rel, RexNode predicate) { - return RelMetadataQuery.getSelectivity( - rel.getInput(), - predicate); + public Double getSelectivity(Sort rel, RelMetadataQuery mq, + RexNode predicate) { + return mq.getSelectivity(rel.getInput(), predicate); } - public Double getSelectivity(Filter rel, RexNode predicate) { + public Double getSelectivity(Filter rel, RelMetadataQuery mq, + RexNode predicate) { // Take the difference between the predicate passed in and the // predicate in the filter's condition, so we don't apply the // selectivity of the filter twice. If no predicate is passed in, // use the filter's condition. if (predicate != null) { - return RelMetadataQuery.getSelectivity( - rel.getInput(), + return mq.getSelectivity(rel.getInput(), RelMdUtil.minusPreds( rel.getCluster().getRexBuilder(), predicate, rel.getCondition())); } else { - return RelMetadataQuery.getSelectivity( - rel.getInput(), - rel.getCondition()); + return mq.getSelectivity(rel.getInput(), rel.getCondition()); } } - public Double getSelectivity(SemiJoin rel, RexNode predicate) { + public Double getSelectivity(SemiJoin rel, RelMetadataQuery mq, + RexNode predicate) { // create a RexNode representing the selectivity of the // semijoin filter and pass it to getSelectivity RexBuilder rexBuilder = rel.getCluster().getRexBuilder(); - RexNode newPred = RelMdUtil.makeSemiJoinSelectivityRexNode(rel); + RexNode newPred = RelMdUtil.makeSemiJoinSelectivityRexNode(mq, rel); if (predicate != null) { newPred = rexBuilder.makeCall( @@ -123,14 +122,13 @@ public class RelMdSelectivity { predicate); } - return RelMetadataQuery.getSelectivity( - rel.getLeft(), - newPred); + return mq.getSelectivity(rel.getLeft(), newPred); } - public Double getSelectivity(Aggregate rel, RexNode predicate) { - List<RexNode> notPushable = new ArrayList<RexNode>(); - List<RexNode> pushable = new ArrayList<RexNode>(); + public Double getSelectivity(Aggregate rel, RelMetadataQuery mq, + RexNode predicate) { + final List<RexNode> notPushable = new ArrayList<>(); + final List<RexNode> pushable = new ArrayList<>(); RelOptUtil.splitFilters( rel.getGroupSet(), predicate, @@ -140,10 +138,7 @@ public class RelMdSelectivity { RexNode childPred = RexUtil.composeConjunction(rexBuilder, pushable, true); - Double selectivity = - RelMetadataQuery.getSelectivity( - rel.getInput(), - childPred); + Double selectivity = mq.getSelectivity(rel.getInput(), childPred); if (selectivity == null) { return null; } else { @@ -153,9 +148,10 @@ public class RelMdSelectivity { } } - public Double getSelectivity(Project rel, RexNode predicate) { - List<RexNode> notPushable = new ArrayList<RexNode>(); - List<RexNode> pushable = new ArrayList<RexNode>(); + public Double getSelectivity(Project rel, RelMetadataQuery mq, + RexNode predicate) { + final List<RexNode> notPushable = new ArrayList<>(); + final List<RexNode> pushable = new ArrayList<>(); RelOptUtil.splitFilters( ImmutableBitSet.range(rel.getRowType().getFieldCount()), predicate, @@ -171,10 +167,7 @@ public class RelMdSelectivity { } else { modifiedPred = RelOptUtil.pushPastProject(childPred, rel); } - Double selectivity = - RelMetadataQuery.getSelectivity( - rel.getInput(), - modifiedPred); + Double selectivity = mq.getSelectivity(rel.getInput(), modifiedPred); if (selectivity == null) { return null; } else { @@ -185,7 +178,8 @@ public class RelMdSelectivity { } // Catch-all rule when none of the others apply. - public Double getSelectivity(RelNode rel, RexNode predicate) { + public Double getSelectivity(RelNode rel, RelMetadataQuery mq, + RexNode predicate) { return RelMdUtil.guessSelectivity(predicate); } } http://git-wip-us.apache.org/repos/asf/calcite/blob/cabdcf44/core/src/main/java/org/apache/calcite/rel/metadata/RelMdSize.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdSize.java b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdSize.java index af60e73..8c2502e 100644 --- a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdSize.java +++ b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdSize.java @@ -74,14 +74,13 @@ public class RelMdSize { //~ Methods ---------------------------------------------------------------- /** Catch-all implementation for - * {@link org.apache.calcite.rel.metadata.BuiltInMetadata.Size#averageRowSize()}, + * {@link BuiltInMetadata.Size#averageRowSize()}, * invoked using reflection. * * @see org.apache.calcite.rel.metadata.RelMetadataQuery#getAverageRowSize */ - public Double averageRowSize(RelNode rel) { - final List<Double> averageColumnSizes = - RelMetadataQuery.getAverageColumnSizes(rel); + public Double averageRowSize(RelNode rel, RelMetadataQuery mq) { + final List<Double> averageColumnSizes = mq.getAverageColumnSizes(rel); if (averageColumnSizes == null) { return null; } @@ -99,30 +98,30 @@ public class RelMdSize { } /** Catch-all implementation for - * {@link org.apache.calcite.rel.metadata.BuiltInMetadata.Size#averageColumnSizes()}, + * {@link BuiltInMetadata.Size#averageColumnSizes()}, * invoked using reflection. * * @see org.apache.calcite.rel.metadata.RelMetadataQuery#getAverageColumnSizes */ - public List<Double> averageColumnSizes(RelNode rel) { + public List<Double> averageColumnSizes(RelNode rel, RelMetadataQuery mq) { return null; // absolutely no idea } - public List<Double> averageColumnSizes(Filter rel) { - return RelMetadataQuery.getAverageColumnSizes(rel.getInput()); + public List<Double> averageColumnSizes(Filter rel, RelMetadataQuery mq) { + return mq.getAverageColumnSizes(rel.getInput()); } - public List<Double> averageColumnSizes(Sort rel) { - return RelMetadataQuery.getAverageColumnSizes(rel.getInput()); + public List<Double> averageColumnSizes(Sort rel, RelMetadataQuery mq) { + return mq.getAverageColumnSizes(rel.getInput()); } - public List<Double> averageColumnSizes(Exchange rel) { - return RelMetadataQuery.getAverageColumnSizes(rel.getInput()); + public List<Double> averageColumnSizes(Exchange rel, RelMetadataQuery mq) { + return mq.getAverageColumnSizes(rel.getInput()); } - public List<Double> averageColumnSizes(Project rel) { + public List<Double> averageColumnSizes(Project rel, RelMetadataQuery mq) { final List<Double> inputColumnSizes = - RelMetadataQuery.getAverageColumnSizesNotNull(rel.getInput()); + mq.getAverageColumnSizesNotNull(rel.getInput()); final ImmutableNullableList.Builder<Double> sizes = ImmutableNullableList.builder(); for (RexNode project : rel.getProjects()) { @@ -131,7 +130,7 @@ public class RelMdSize { return sizes.build(); } - public List<Double> averageColumnSizes(Values rel) { + public List<Double> averageColumnSizes(Values rel, RelMetadataQuery mq) { final List<RelDataTypeField> fields = rel.getRowType().getFieldList(); final ImmutableList.Builder<Double> list = ImmutableList.builder(); for (int i = 0; i < fields.size(); i++) { @@ -151,7 +150,7 @@ public class RelMdSize { return list.build(); } - public List<Double> averageColumnSizes(TableScan rel) { + public List<Double> averageColumnSizes(TableScan rel, RelMetadataQuery mq) { final List<RelDataTypeField> fields = rel.getRowType().getFieldList(); final ImmutableList.Builder<Double> list = ImmutableList.builder(); for (RelDataTypeField field : fields) { @@ -160,9 +159,9 @@ public class RelMdSize { return list.build(); } - public List<Double> averageColumnSizes(Aggregate rel) { + public List<Double> averageColumnSizes(Aggregate rel, RelMetadataQuery mq) { final List<Double> inputColumnSizes = - RelMetadataQuery.getAverageColumnSizesNotNull(rel.getInput()); + mq.getAverageColumnSizesNotNull(rel.getInput()); final ImmutableList.Builder<Double> list = ImmutableList.builder(); for (int key : rel.getGroupSet()) { list.add(inputColumnSizes.get(key)); @@ -173,21 +172,21 @@ public class RelMdSize { return list.build(); } - public List<Double> averageColumnSizes(SemiJoin rel) { - return averageJoinColumnSizes(rel, true); + public List<Double> averageColumnSizes(SemiJoin rel, RelMetadataQuery mq) { + return averageJoinColumnSizes(rel, mq, true); } - public List<Double> averageColumnSizes(Join rel) { - return averageJoinColumnSizes(rel, false); + public List<Double> averageColumnSizes(Join rel, RelMetadataQuery mq) { + return averageJoinColumnSizes(rel, mq, false); } - private List<Double> averageJoinColumnSizes(Join rel, boolean semijoin) { + private List<Double> averageJoinColumnSizes(Join rel, RelMetadataQuery mq, + boolean semijoin) { final RelNode left = rel.getLeft(); final RelNode right = rel.getRight(); - final List<Double> lefts = - RelMetadataQuery.getAverageColumnSizes(left); - final List<Double> rights = semijoin - ? null : RelMetadataQuery.getAverageColumnSizes(right); + final List<Double> lefts = mq.getAverageColumnSizes(left); + final List<Double> rights = + semijoin ? null : mq.getAverageColumnSizes(right); if (lefts == null && rights == null) { return null; } @@ -205,20 +204,19 @@ public class RelMdSize { return ImmutableNullableList.copyOf(sizes); } - public List<Double> averageColumnSizes(Intersect rel) { - return RelMetadataQuery.getAverageColumnSizes(rel.getInput(0)); + public List<Double> averageColumnSizes(Intersect rel, RelMetadataQuery mq) { + return mq.getAverageColumnSizes(rel.getInput(0)); } - public List<Double> averageColumnSizes(Minus rel) { - return RelMetadataQuery.getAverageColumnSizes(rel.getInput(0)); + public List<Double> averageColumnSizes(Minus rel, RelMetadataQuery mq) { + return mq.getAverageColumnSizes(rel.getInput(0)); } - public List<Double> averageColumnSizes(Union rel) { + public List<Double> averageColumnSizes(Union rel, RelMetadataQuery mq) { final int fieldCount = rel.getRowType().getFieldCount(); List<List<Double>> inputColumnSizeList = Lists.newArrayList(); for (RelNode input : rel.getInputs()) { - final List<Double> inputSizes = - RelMetadataQuery.getAverageColumnSizes(input); + final List<Double> inputSizes = mq.getAverageColumnSizes(input); if (inputSizes != null) { inputColumnSizeList.add(inputSizes); }
