public RelNode convert(
      RelOptPlanner planner,
      RelNode rel,
      RelDistribution toDistribution,
      boolean allowInfiniteCostConverters) {
    if (toDistribution == RelDistributions.ANY) {
      return rel;
    }

    // Create a logical sort, then ask the planner to convert its remaining
    // traits (e.g. convert it to an EnumerableSortRel if rel is enumerable
    // convention)
    final Exchange exchange = LogicalExchange.create(rel, toDistribution);
    RelNode newRel = planner.register(exchange, rel);
    final RelTraitSet newTraitSet = rel.getTraitSet().replace(toDistribution);
    if (!newRel.getTraitSet().equals(newTraitSet)) {
      newRel = planner.changeTraits(newRel, newTraitSet);
    }
    return newRel;
  }