presto-main/src/main/java/io/prestosql/sql/planner/optimizations/PlanNodeDecorrelator.java/PlanNodeDecorrelator/visitAggregation
class PlanNodeDecorrelator:        @Override
        public Optional<DecorrelationResult> visitAggregation(AggregationNode node, Void context)
        {
            if (node.hasEmptyGroupingSet()) {
                return Optional.empty();
            }

            if (node.getGroupingSetCount() != 1) {
                return Optional.empty();
            }

            Optional<DecorrelationResult> childDecorrelationResultOptional = node.getSource().accept(this, null);
            if (!childDecorrelationResultOptional.isPresent()) {
                return Optional.empty();
            }

            DecorrelationResult childDecorrelationResult = childDecorrelationResultOptional.get();
            Set<Symbol> constantSymbols = childDecorrelationResult.getConstantSymbols();

            AggregationNode decorrelatedAggregation = childDecorrelationResult.getCorrelatedSymbolMapper()
                    .map(node, childDecorrelationResult.node);

            Set<Symbol> groupingKeys = ImmutableSet.copyOf(node.getGroupingKeys());
            List<Symbol> symbolsToAdd = childDecorrelationResult.symbolsToPropagate.stream()
                    .filter(symbol -> !groupingKeys.contains(symbol))
                    .collect(toImmutableList());

            if (!constantSymbols.containsAll(symbolsToAdd)) {
                return Optional.empty();
            }

            AggregationNode newAggregation = new AggregationNode(
                    decorrelatedAggregation.getId(),
                    decorrelatedAggregation.getSource(),
                    decorrelatedAggregation.getAggregations(),
                    AggregationNode.singleGroupingSet(ImmutableList.<Symbol>builder()
                            .addAll(node.getGroupingKeys())
                            .addAll(symbolsToAdd)
                            .build()),
                    ImmutableList.of(),
                    decorrelatedAggregation.getStep(),
                    decorrelatedAggregation.getHashSymbol(),
                    decorrelatedAggregation.getGroupIdSymbol());

            return Optional.of(new DecorrelationResult(
                    newAggregation,
                    childDecorrelationResult.symbolsToPropagate,
                    childDecorrelationResult.correlatedPredicates,
                    childDecorrelationResult.correlatedSymbolsMapping,
                    constantSymbols.containsAll(newAggregation.getGroupingKeys())));
        }