public Double getDistinctRowCount(Aggregate rel, ImmutableBitSet groupKey, RexNode predicate) { if (predicate == null || predicate.isAlwaysTrue()) { if (groupKey.isEmpty()) { return 1D; } } // determine which predicates can be applied on the child of the // aggregate List<RexNode> notPushable = new ArrayList<RexNode>(); List<RexNode> pushable = new ArrayList<RexNode>(); RelOptUtil.splitFilters(rel.getGroupSet(), predicate, pushable, notPushable); final RexBuilder rexBuilder = rel.getCluster().getRexBuilder(); RexNode childPreds = RexUtil.composeConjunction(rexBuilder, pushable, true); // set the bits as they correspond to the child input ImmutableBitSet.Builder childKey = ImmutableBitSet.builder(); RelMdUtil.setAggChildKeys(groupKey, rel, childKey); Double distinctRowCount = RelMetadataQuery.getDistinctRowCount(rel.getInput(), childKey.build(), childPreds); if (distinctRowCount == null) { return null; } else if (notPushable.isEmpty()) { return distinctRowCount; } else { RexNode preds = RexUtil.composeConjunction(rexBuilder, notPushable, true); return distinctRowCount * RelMdUtil.guessSelectivity(preds); } }
public Double getDistinctRowCount(Join rel, ImmutableBitSet groupKey, RexNode predicate) { if (predicate == null || predicate.isAlwaysTrue()) { if (groupKey.isEmpty()) { return 1D; } } return RelMdUtil.getJoinDistinctRowCount(rel, rel.getJoinType(), groupKey, predicate, false); }
public Double getDistinctRowCount(Project rel, ImmutableBitSet groupKey, RexNode predicate) { if (predicate == null || predicate.isAlwaysTrue()) { if (groupKey.isEmpty()) { return 1D; } } ImmutableBitSet.Builder baseCols = ImmutableBitSet.builder(); ImmutableBitSet.Builder projCols = ImmutableBitSet.builder(); List<RexNode> projExprs = rel.getProjects(); RelMdUtil.splitCols(projExprs, groupKey, baseCols, projCols); List<RexNode> notPushable = new ArrayList<RexNode>(); List<RexNode> pushable = new ArrayList<RexNode>(); RelOptUtil.splitFilters( ImmutableBitSet.range(rel.getRowType().getFieldCount()), predicate, pushable, notPushable); final RexBuilder rexBuilder = rel.getCluster().getRexBuilder(); // get the distinct row count of the child input, passing in the // columns and filters that only reference the child; convert the // filter to reference the children projection expressions RexNode childPred = RexUtil.composeConjunction(rexBuilder, pushable, true); RexNode modifiedPred; if (childPred == null) { modifiedPred = null; } else { modifiedPred = RelOptUtil.pushPastProject(childPred, rel); } Double distinctRowCount = RelMetadataQuery.getDistinctRowCount(rel.getInput(), baseCols.build(), modifiedPred); if (distinctRowCount == null) { return null; } else if (!notPushable.isEmpty()) { RexNode preds = RexUtil.composeConjunction(rexBuilder, notPushable, true); distinctRowCount *= RelMdUtil.guessSelectivity(preds); } // No further computation required if the projection expressions // are all column references if (projCols.cardinality() == 0) { return distinctRowCount; } // multiply by the cardinality of the non-child projection expressions for (int bit : projCols.build()) { Double subRowCount = RelMdUtil.cardOfProjExpr(rel, projExprs.get(bit)); if (subRowCount == null) { return null; } distinctRowCount *= subRowCount; } return RelMdUtil.numDistinctVals(distinctRowCount, RelMetadataQuery.getRowCount(rel)); }
public Double getDistinctRowCount(Values rel, ImmutableBitSet groupKey, RexNode predicate) { if (predicate == null || predicate.isAlwaysTrue()) { if (groupKey.isEmpty()) { return 1D; } } Double selectivity = RelMdUtil.guessSelectivity(predicate); // assume half the rows are duplicates Double nRows = rel.getRows() / 2; return RelMdUtil.numDistinctVals(nRows, nRows * selectivity); }
/** * Computes the rollup of bit sets. * * <p>For example, <code>rollup({0}, {1})</code> returns <code>({0, 1}, {0}, {})</code>. * * <p>Bit sets are not necessarily singletons: <code>rollup({0, 2}, {3, 5})</code> returns <code> * ({0, 2, 3, 5}, {0, 2}, {})</code>. */ @VisibleForTesting public static ImmutableList<ImmutableBitSet> rollup(List<ImmutableBitSet> bitSets) { Set<ImmutableBitSet> builder = Sets.newLinkedHashSet(); for (; ; ) { final ImmutableBitSet union = ImmutableBitSet.union(bitSets); builder.add(union); if (union.isEmpty()) { break; } bitSets = bitSets.subList(0, bitSets.size() - 1); } return ImmutableList.copyOf(builder); }
public Double getDistinctRowCount(Filter rel, ImmutableBitSet groupKey, RexNode predicate) { if (predicate == null || predicate.isAlwaysTrue()) { if (groupKey.isEmpty()) { return 1D; } } // REVIEW zfong 4/18/06 - In the Broadbase code, duplicates are not // removed from the two filter lists. However, the code below is // doing so. RexNode unionPreds = RelMdUtil.unionPreds(rel.getCluster().getRexBuilder(), predicate, rel.getCondition()); return RelMetadataQuery.getDistinctRowCount(rel.getInput(), groupKey, unionPreds); }
// 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; } } // 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)); } return null; }
public Double getDistinctRowCount(SemiJoin rel, ImmutableBitSet groupKey, RexNode predicate) { if (predicate == null || predicate.isAlwaysTrue()) { if (groupKey.isEmpty()) { return 1D; } } // create a RexNode representing the selectivity of the // semijoin filter and pass it to getDistinctRowCount RexNode newPred = RelMdUtil.makeSemiJoinSelectivityRexNode(rel); if (predicate != null) { RexBuilder rexBuilder = rel.getCluster().getRexBuilder(); newPred = rexBuilder.makeCall(SqlStdOperatorTable.AND, newPred, predicate); } return RelMetadataQuery.getDistinctRowCount(rel.getLeft(), groupKey, newPred); }