RelNode sortExchange() throws SemanticException {
      genOBProject();

      if (fieldCollations.isEmpty() && hiveRelDistribution.getKeys().isEmpty()) {
        return endGenOBLogicalPlan(obInputRel);
      }

      RelCollation canonizedCollation = RelCollations.of(fieldCollations);
      ImmutableList.Builder<RexNode> builder = ImmutableList.builder();
      for (RelFieldCollation relFieldCollation : canonizedCollation.getFieldCollations()) {
        int index = relFieldCollation.getFieldIndex();
        builder.add(calcitePlannerAction.cluster.getRexBuilder().makeInputRef(obInputRel, index));
      }
      ImmutableList<RexNode> keys = builder.build();
      RelNode sortRel = HiveSortExchange.create(obInputRel, hiveRelDistribution, canonizedCollation, keys);
      return endGenOBLogicalPlan(sortRel);
    }
This method can be called at startup time to pre-register all the
additional Hive classes (compared to Calcite core classes) that may
be visited during the planning phase in the metadata providers
and the field trimmer.
ql/src/java/org/apache/hadoop/hive/ql/parse/CalcitePlanner.java