public TrimResult trimFields(
          HiveSortExchange exchange,
          ImmutableBitSet fieldsUsed,
          Set<RelDataTypeField> extraFields) {
    final RelDataType rowType = exchange.getRowType();
    final int fieldCount = rowType.getFieldCount();
    final RelCollation collation = exchange.getCollation();
    final RelDistribution distribution = exchange.getDistribution();
    final RelNode input = exchange.getInput();

    // We use the fields used by the consumer, plus any fields used as exchange
    // keys.
    final ImmutableBitSet.Builder inputFieldsUsed = fieldsUsed.rebuild();
    for (RelFieldCollation field : collation.getFieldCollations()) {
      inputFieldsUsed.set(field.getFieldIndex());
    }
    for (int keyIndex : distribution.getKeys()) {
      inputFieldsUsed.set(keyIndex);
    }

    // Create input with trimmed columns.
    final Set<RelDataTypeField> inputExtraFields = Collections.emptySet();
    TrimResult trimResult =
            trimChild(exchange, input, inputFieldsUsed.build(), 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 result(exchange, Mappings.createIdentity(fieldCount));
    }

    final RelBuilder relBuilder = REL_BUILDER.get();
    relBuilder.push(newInput);
    RelCollation newCollation = RexUtil.apply(inputMapping, collation);
    RelDistribution newDistribution = distribution.apply(inputMapping);
    relBuilder.sortExchange(newDistribution, newCollation);

    return result(relBuilder.build(), inputMapping);
  }
This method can be called at startup time to pre-register all the
Hive classes that may be visited during the planning phase.
ql/src/java/org/apache/hadoop/hive/ql/optimizer/calcite/rules/HiveRelFieldTrimmer.java