Source:
public Result apply(AggregationNode aggregationNode, Captures captures, Context context) { boolean decomposable = aggregationNode.isDecomposable(functionRegistry); if (!decomposable) { return Result.empty(); } if (aggregationNode.getStep().equals(SINGLE) && aggregationNode.hasEmptyGroupingSet() && aggregationNode.hasNonEmptyGroupingSet()) { return Result.ofPlanNode(split(aggregationNode, context)); } PlanNode childNode = context.getLookup().resolve(aggregationNode.getSource()); if (!(childNode instanceof ExchangeNode)) { return Result.empty(); } ExchangeNode exchangeNode = (ExchangeNode) childNode; if ((exchangeNode.getType() != GATHER && exchangeNode.getType() != REPARTITION) || exchangeNode.getPartitioningScheme().isReplicateNullsAndAny()) { return Result.empty(); } if (exchangeNode.getType() == REPARTITION) { List<Symbol> partitioningColumns = exchangeNode.getPartitioningScheme() .getPartitioning() .getArguments() .stream() .filter(Partitioning.ArgumentBinding::isVariable) .map(Partitioning.ArgumentBinding::getColumn) .collect(Collectors.toList()); if (!aggregationNode.getGroupingKeys().containsAll(partitioningColumns)) { return Result.empty(); } } if (aggregationNode.getHashSymbol().isPresent() || exchangeNode.getPartitioningScheme().getHashColumn().isPresent()) { return Result.empty(); } switch (aggregationNode.getStep()) { case SINGLE: return Result.ofPlanNode(split(aggregationNode, context)); case PARTIAL: return Result.ofPlanNode(pushPartial(aggregationNode, exchangeNode, context)); default: return Result.empty(); } }

Target:
public Result apply(AggregationNode aggregationNode, Captures captures, Context context) { PlanNode childNode = context.getLookup().resolve(aggregationNode.getSource()); if (!(childNode instanceof ExchangeNode)) { return Result.empty(); } ExchangeNode exchangeNode = (ExchangeNode) childNode; boolean decomposable = aggregationNode.isDecomposable(functionRegistry); if (aggregationNode.getStep().equals(SINGLE) && aggregationNode.hasEmptyGroupingSet() && aggregationNode.hasNonEmptyGroupingSet() && exchangeNode.getType() == REPARTITION) { checkState( decomposable, "Distributed aggregation with empty grouping set requires partial but functions are not decomposable"); return Result.ofPlanNode(split(aggregationNode, context)); } if (!decomposable) { return Result.empty(); } if ((exchangeNode.getType() != GATHER && exchangeNode.getType() != REPARTITION) || exchangeNode.getPartitioningScheme().isReplicateNullsAndAny()) { return Result.empty(); } if (exchangeNode.getType() == REPARTITION) { List<Symbol> partitioningColumns = exchangeNode.getPartitioningScheme() .getPartitioning() .getArguments() .stream() .filter(Partitioning.ArgumentBinding::isVariable) .map(Partitioning.ArgumentBinding::getColumn) .collect(Collectors.toList()); if (!aggregationNode.getGroupingKeys().containsAll(partitioningColumns)) { return Result.empty(); } } if (aggregationNode.getHashSymbol().isPresent() || exchangeNode.getPartitioningScheme().getHashColumn().isPresent()) { return Result.empty(); } switch (aggregationNode.getStep()) { case SINGLE: return Result.ofPlanNode(split(aggregationNode, context)); case PARTIAL: return Result.ofPlanNode(pushPartial(aggregationNode, exchangeNode, context)); default: return Result.empty(); } }