private DistributionTrait convertDist(DistributionTrait srcDist, Map<Integer, Integer> inToOut) { List<DistributionField> newFields = Lists.newArrayList(); for (DistributionField field : srcDist.getFields()) { if (inToOut.containsKey(field.getFieldId())) { newFields.add(new DistributionField(inToOut.get(field.getFieldId()))); } } // After the projection, if the new distribution fields is empty, or new distribution fields is a subset of // original distribution field, we should replace with either SINGLETON or RANDOM_DISTRIBUTED. if (newFields.isEmpty() || newFields.size() < srcDist.getFields().size()) { if (srcDist.getType() != DistributionType.SINGLETON) { return DistributionTrait.ANY; } else { return DistributionTrait.SINGLETON; } } else { return new DistributionTrait(srcDist.getType(), ImmutableList.copyOf(newFields)); } }
@Override public RelNode visit(final RelNode other) { if (other instanceof WriterPrel) { for (RelTrait trait : other.getTraitSet()) { if (trait instanceof DistributionTrait) { List<DistributionField> distributionFieldList = ((DistributionTrait) trait).getFields(); if (distributionFieldList.size() != 1) { continue; } int fieldId = distributionFieldList.get(0).getFieldId(); String fieldName = ((WriterPrel) other).getInput().getRowType().getFieldNames().get(fieldId); if ("position".equals(fieldName)) { hashDistributedWriter.set(true); } } } } return super.visit(other); } });
@Override public RelNode convert( RelOptPlanner planner, RelNode rel, DistributionTrait toDist, boolean allowInfiniteCostConverters) { switch(toDist.getType()){ // UnionExchange, HashToRandomExchange, OrderedPartitionExchange and BroadcastExchange destroy the ordering property, // therefore RelCollation is set to default, which is EMPTY. case SINGLETON: return new UnionExchangePrel(rel.getCluster(), planner.emptyTraitSet().plus(Prel.PHYSICAL).plus(toDist), rel); case HASH_DISTRIBUTED: return new HashToRandomExchangePrel(rel.getCluster(), planner.emptyTraitSet().plus(Prel.PHYSICAL).plus(toDist), rel, toDist.getFields()); case RANGE_DISTRIBUTED: return new OrderedPartitionExchangePrel(rel.getCluster(), planner.emptyTraitSet().plus(Prel.PHYSICAL).plus(toDist), rel); case BROADCAST_DISTRIBUTED: return new BroadcastExchangePrel(rel.getCluster(), planner.emptyTraitSet().plus(Prel.PHYSICAL).plus(toDist), rel); case ROUND_ROBIN_DISTRIBUTED: return new RoundRobinExchangePrel(rel.getCluster(), planner.emptyTraitSet().plus(Prel.PHYSICAL).plus(toDist), rel); case ANY: // If target is "any", any input would satisfy "any". Return input directly. return rel; default: return null; } }