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