Beispiel #1
0
  /**
   * Applies a mapping to a collation list.
   *
   * @param mapping Mapping
   * @param collationList Collation list
   * @return collation list with mapping applied to each field
   */
  public static List<RelCollation> apply(
      Mappings.TargetMapping mapping, List<RelCollation> collationList) {
    final List<RelCollation> newCollationList = new ArrayList<RelCollation>();
    for (RelCollation collation : collationList) {
      final List<RelFieldCollation> newFieldCollationList = new ArrayList<RelFieldCollation>();
      for (RelFieldCollation fieldCollation : collation.getFieldCollations()) {
        final RelFieldCollation newFieldCollation = apply(mapping, fieldCollation);
        if (newFieldCollation == null) {
          // This field is not mapped. Stop here. The leading edge
          // of the collation is still valid (although it's useless
          // if it's empty).
          break;
        }
        newFieldCollationList.add(newFieldCollation);
      }
      // Truncation to collations to their leading edge creates empty
      // and duplicate collations. Ignore these.
      if (!newFieldCollationList.isEmpty()) {
        final RelCollationImpl newCollation = new RelCollationImpl(newFieldCollationList);
        if (!newCollationList.contains(newCollation)) {
          newCollationList.add(newCollation);
        }
      }
    }

    // REVIEW: There might be redundant collations in the list. For example,
    // in {(x), (x, y)}, (x) is redundant because it is a leading edge of
    // another collation in the list. Could remove redundant collations.

    return newCollationList;
  }
Beispiel #2
0
  /** Variant of {@link #trimFields(RelNode, BitSet, Set)} for {@link SortRel}. */
  public TrimResult trimFields(SortRel sort, BitSet fieldsUsed, Set<RelDataTypeField> extraFields) {
    final RelDataType rowType = sort.getRowType();
    final int fieldCount = rowType.getFieldCount();
    final RelCollation collation = sort.getCollation();
    final RelNode input = sort.getChild();

    // We use the fields used by the consumer, plus any fields used as sort
    // keys.
    BitSet inputFieldsUsed = (BitSet) fieldsUsed.clone();
    for (RelFieldCollation field : collation.getFieldCollations()) {
      inputFieldsUsed.set(field.getFieldIndex());
    }

    // Create input with trimmed columns.
    final Set<RelDataTypeField> inputExtraFields = Collections.emptySet();
    TrimResult trimResult = trimChild(sort, input, inputFieldsUsed, inputExtraFields);
    RelNode newInput = trimResult.left;
    final Mapping inputMapping = trimResult.right;

    // If the input is unchanged, and we need to project all columns,
    // there's nothing we can do.
    if (newInput == input && inputMapping.isIdentity() && fieldsUsed.cardinality() == fieldCount) {
      return new TrimResult(sort, Mappings.createIdentity(fieldCount));
    }

    final SortRel newSort =
        sort.copy(sort.getTraitSet(), newInput, RexUtil.apply(inputMapping, collation));
    assert newSort.getClass() == sort.getClass();

    // The result has the same mapping as the input gave us. Sometimes we
    // return fields that the consumer didn't ask for, because the filter
    // needs them for its condition.
    return new TrimResult(newSort, inputMapping);
  }
Beispiel #3
0
 /**
  * Checks that a collection of collations is valid.
  *
  * @param rowType Row type of the relational expression
  * @param collationList List of collations
  * @param fail Whether to fail if invalid
  * @return Whether valid
  */
 public static boolean isValid(
     RelDataType rowType, List<RelCollation> collationList, boolean fail) {
   final int fieldCount = rowType.getFieldCount();
   for (RelCollation collation : collationList) {
     for (RelFieldCollation fieldCollation : collation.getFieldCollations()) {
       final int index = fieldCollation.getFieldIndex();
       if (index < 0 || index >= fieldCount) {
         assert !fail;
         return false;
       }
     }
   }
   return true;
 }
Beispiel #4
0
 public RelWriter explainTerms(RelWriter pw) {
   super.explainTerms(pw);
   assert fieldExps.size() == collation.getFieldCollations().size();
   if (pw.nest()) {
     pw.item("collation", collation);
   } else {
     for (Ord<RexNode> ord : Ord.zip(fieldExps)) {
       pw.item("sort" + ord.i, ord.e);
     }
     for (Ord<RelFieldCollation> ord : Ord.zip(collation.getFieldCollations())) {
       pw.item("dir" + ord.i, ord.e.shortString());
     }
   }
   pw.itemIf("offset", offset, offset != null);
   pw.itemIf("fetch", fetch, fetch != null);
   return pw;
 }
Beispiel #5
0
 /** Returns the indexes of the field collations in a given collation. */
 public static List<Integer> ordinals(RelCollation collation) {
   return Lists.transform(
       collation.getFieldCollations(),
       new Function<RelFieldCollation, Integer>() {
         public Integer apply(RelFieldCollation input) {
           return input.getFieldIndex();
         }
       });
 }
Beispiel #6
0
  /**
   * Creates a sorter.
   *
   * @param cluster Cluster this relational expression belongs to
   * @param traits Traits
   * @param child input relational expression
   * @param collation array of sort specifications
   * @param offset Expression for number of rows to discard before returning first row
   * @param fetch Expression for number of rows to fetch
   */
  public SortRel(
      RelOptCluster cluster,
      RelTraitSet traits,
      RelNode child,
      RelCollation collation,
      RexNode offset,
      RexNode fetch) {
    super(cluster, traits, child);
    this.collation = collation;
    this.offset = offset;
    this.fetch = fetch;

    assert traits.containsIfApplicable(collation) : "traits=" + traits + ", collation=" + collation;
    assert !(fetch == null && offset == null && collation.getFieldCollations().isEmpty())
        : "trivial sort";
    ImmutableList.Builder<RexNode> builder = ImmutableList.builder();
    for (RelFieldCollation field : collation.getFieldCollations()) {
      int index = field.getFieldIndex();
      builder.add(cluster.getRexBuilder().makeInputRef(child, index));
    }
    fieldExps = builder.build();
  }