public Double getPercentageOriginalRows(UnionRelBase rel) {
    double numerator = 0.0;
    double denominator = 0.0;

    // Ignore rel.isDistinct() because it's the same as an aggregate.

    // REVIEW jvs 28-Mar-2006: The original Broadbase formula was broken.
    // It was multiplying percentage into the numerator term rather than
    // than dividing it out of the denominator term, which would be OK if
    // there weren't summation going on.  Probably the cause of the error
    // was the desire to avoid division by zero, which I don't know how to
    // handle so I punt, meaning we return a totally wrong answer in the
    // 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);
      if (percentage != 0.0) {
        denominator += rowCount / percentage;
        numerator += rowCount;
      }
    }

    return quotientForPercentage(numerator, denominator);
  }
 // Ditto for getNonCumulativeCost
 public RelOptCost getCumulativeCost(RelNode rel) {
   RelOptCost cost = RelMetadataQuery.getNonCumulativeCost(rel);
   List<RelNode> inputs = rel.getInputs();
   for (RelNode input : inputs) {
     cost = cost.plus(RelMetadataQuery.getCumulativeCost(input));
   }
   return cost;
 }
  public Double getPercentageOriginalRows(JoinRelBase rel) {
    // Assume any single-table filter conditions have already
    // been pushed down.

    // REVIEW jvs 28-Mar-2006: As with aggregation, this is
    // oversimplified.

    // REVIEW jvs 28-Mar-2006:  need any special casing for SemiJoinRel?

    double left = RelMetadataQuery.getPercentageOriginalRows(rel.getLeft());

    double right = RelMetadataQuery.getPercentageOriginalRows(rel.getRight());

    return left * right;
  }
  public Double getPercentageOriginalRows(AggregateRelBase rel) {
    // 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.getChild());
  }
  public Boolean areColumnsUnique(ProjectRelBase rel, BitSet columns, boolean ignoreNulls) {
    // ProjectRel 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
    // info from the child of a project when the mapping is f(a) => a.
    //
    // Also need to map the input column set to the corresponding child
    // references

    List<RexNode> projExprs = rel.getProjects();
    BitSet childColumns = new BitSet();
    for (int bit : BitSets.toIter(columns)) {
      RexNode projExpr = projExprs.get(bit);
      if (projExpr instanceof RexInputRef) {
        childColumns.set(((RexInputRef) projExpr).getIndex());
      } else if (projExpr instanceof RexCall && ignoreNulls) {
        // If the expression is a cast such that the types are the same
        // except for the nullability, then if we're ignoring nulls,
        // it doesn't matter whether the underlying column reference
        // is nullable.  Check that the types are the same by making a
        // nullable copy of both types and then comparing them.
        RexCall call = (RexCall) projExpr;
        if (call.getOperator() != SqlStdOperatorTable.CAST) {
          continue;
        }
        RexNode castOperand = call.getOperands().get(0);
        if (!(castOperand instanceof RexInputRef)) {
          continue;
        }
        RelDataTypeFactory typeFactory = rel.getCluster().getTypeFactory();
        RelDataType castType = typeFactory.createTypeWithNullability(projExpr.getType(), true);
        RelDataType origType = typeFactory.createTypeWithNullability(castOperand.getType(), true);
        if (castType.equals(origType)) {
          childColumns.set(((RexInputRef) castOperand).getIndex());
        }
      } else {
        // If the expression will not influence uniqueness of the
        // projection, then skip it.
        continue;
      }
    }

    // If no columns can affect uniqueness, then return unknown
    if (childColumns.cardinality() == 0) {
      return null;
    }

    return RelMetadataQuery.areColumnsUnique(rel.getChild(), childColumns, ignoreNulls);
  }
  // Catch-all rule when none of the others apply.
  public Double getPercentageOriginalRows(RelNode rel) {
    if (rel.getInputs().size() > 1) {
      // No generic formula available for multiple inputs.
      return null;
    }

    if (rel.getInputs().size() == 0) {
      // Assume no filtering happening at leaf.
      return 1.0;
    }

    RelNode child = rel.getInputs().get(0);

    Double childPercentage = RelMetadataQuery.getPercentageOriginalRows(child);
    if (childPercentage == null) {
      return null;
    }

    // Compute product of percentage filtering from this rel (assuming any
    // 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));
    if (relPercentage == null) {
      return null;
    }
    double percent = relPercentage * childPercentage;

    // this check is needed in cases where this method is called on a
    // physical rel
    if ((percent < 0.0) || (percent > 1.0)) {
      return null;
    }
    return relPercentage * childPercentage;
  }
Example #7
0
 public RelOptCost computeSelfCost(RelOptPlanner planner) {
   double dRows = RelMetadataQuery.getRowCount(this);
   double dCpu = RelMetadataQuery.getRowCount(getChild()) * program.getExprCount();
   double dIo = 0;
   return planner.makeCost(dRows, dCpu, dIo);
 }
 public Boolean areColumnsUnique(CorrelatorRel rel, BitSet columns, boolean ignoreNulls) {
   return RelMetadataQuery.areColumnsUnique(rel.getLeft(), columns, ignoreNulls);
 }
 public Boolean areColumnsUnique(SortRel rel, BitSet columns, boolean ignoreNulls) {
   return RelMetadataQuery.areColumnsUnique(rel.getChild(), columns, ignoreNulls);
 }
 public Boolean areColumnsUnique(SemiJoinRel rel, BitSet 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);
 }
  public Boolean areColumnsUnique(JoinRelBase rel, BitSet columns, boolean ignoreNulls) {
    if (columns.cardinality() == 0) {
      return false;
    }

    final RelNode left = rel.getLeft();
    final RelNode right = rel.getRight();

    // Divide up the input column mask into column masks for the left and
    // right sides of the join
    BitSet leftColumns = new BitSet();
    BitSet rightColumns = new BitSet();
    int nLeftColumns = left.getRowType().getFieldCount();
    for (int bit : BitSets.toIter(columns)) {
      if (bit < nLeftColumns) {
        leftColumns.set(bit);
      } else {
        rightColumns.set(bit - nLeftColumns);
      }
    }

    // If the original column mask contains columns from both the left and
    // right hand side, then the columns are unique if and only if they're
    // unique for their respective join inputs
    Boolean leftUnique = RelMetadataQuery.areColumnsUnique(left, leftColumns, ignoreNulls);
    Boolean rightUnique = RelMetadataQuery.areColumnsUnique(right, rightColumns, ignoreNulls);
    if ((leftColumns.cardinality() > 0) && (rightColumns.cardinality() > 0)) {
      if ((leftUnique == null) || (rightUnique == null)) {
        return null;
      } else {
        return leftUnique && rightUnique;
      }
    }

    // If we're only trying to determine uniqueness for columns that
    // originate from one join input, then determine if the equijoin
    // columns from the other join input are unique.  If they are, then
    // the columns are unique for the entire join if they're unique for
    // the corresponding join input, provided that input is not null
    // generating.
    final JoinInfo joinInfo = rel.analyzeCondition();
    if (leftColumns.cardinality() > 0) {
      if (rel.getJoinType().generatesNullsOnLeft()) {
        return false;
      }
      Boolean rightJoinColsUnique =
          RelMetadataQuery.areColumnsUnique(right, joinInfo.rightSet(), ignoreNulls);
      if ((rightJoinColsUnique == null) || (leftUnique == null)) {
        return null;
      }
      return rightJoinColsUnique && leftUnique;
    } else if (rightColumns.cardinality() > 0) {
      if (rel.getJoinType().generatesNullsOnRight()) {
        return false;
      }
      Boolean leftJoinColsUnique =
          RelMetadataQuery.areColumnsUnique(left, joinInfo.leftSet(), ignoreNulls);
      if ((leftJoinColsUnique == null) || (rightUnique == null)) {
        return null;
      }
      return leftJoinColsUnique && rightUnique;
    }

    throw new AssertionError();
  }