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(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)); }