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