private Function<Symbol, Optional<Symbol>> translateGroupIdSymbols(GroupIdNode node) { return symbol -> { if (node.getAggregationArguments().contains(symbol)) { return Optional.of(symbol); } if (node.getCommonGroupingColumns().contains(symbol)) { return Optional.of(node.getGroupingColumns().get(symbol)); } return Optional.empty(); }; }
@Override public ActualProperties visitGroupId(GroupIdNode node, List<ActualProperties> inputProperties) { Map<Symbol, Symbol> inputToOutputMappings = new HashMap<>(); for (Map.Entry<Symbol, Symbol> setMapping : node.getGroupingColumns().entrySet()) { if (node.getCommonGroupingColumns().contains(setMapping.getKey())) { // TODO: Add support for translating a property on a single column to multiple columns // when GroupIdNode is copying a single input grouping column into multiple output grouping columns (i.e. aliases), this is basically picking one arbitrarily inputToOutputMappings.putIfAbsent(setMapping.getValue(), setMapping.getKey()); } } // TODO: Add support for translating a property on a single column to multiple columns // this is deliberately placed after the grouping columns, because preserving properties has a bigger perf impact for (Symbol argument : node.getAggregationArguments()) { inputToOutputMappings.putIfAbsent(argument, argument); } return Iterables.getOnlyElement(inputProperties).translate(column -> Optional.ofNullable(inputToOutputMappings.get(column))); }
@Override public StreamProperties visitGroupId(GroupIdNode node, List<StreamProperties> inputProperties) { Map<Symbol, Symbol> inputToOutputMappings = new HashMap<>(); for (Map.Entry<Symbol, Symbol> setMapping : node.getGroupingColumns().entrySet()) { if (node.getCommonGroupingColumns().contains(setMapping.getKey())) { // TODO: Add support for translating a property on a single column to multiple columns // when GroupIdNode is copying a single input grouping column into multiple output grouping columns (i.e. aliases), this is basically picking one arbitrarily inputToOutputMappings.putIfAbsent(setMapping.getValue(), setMapping.getKey()); } } // TODO: Add support for translating a property on a single column to multiple columns // this is deliberately placed after the grouping columns, because preserving properties has a bigger perf impact for (Symbol argument : node.getAggregationArguments()) { inputToOutputMappings.putIfAbsent(argument, argument); } return Iterables.getOnlyElement(inputProperties).translate(column -> Optional.ofNullable(inputToOutputMappings.get(column))); }
@Override public PlanNode visitGroupId(GroupIdNode node, RewriteContext<Expression> context) { Map<Symbol, SymbolReference> commonGroupingSymbolMapping = node.getGroupingColumns().entrySet().stream() .filter(entry -> node.getCommonGroupingColumns().contains(entry.getKey())) .collect(Collectors.toMap(Map.Entry::getKey, entry -> entry.getValue().toSymbolReference())); Predicate<Expression> pushdownEligiblePredicate = conjunct -> SymbolsExtractor.extractUnique(conjunct).stream() .allMatch(commonGroupingSymbolMapping.keySet()::contains); Map<Boolean, List<Expression>> conjuncts = extractConjuncts(context.get()).stream().collect(Collectors.partitioningBy(pushdownEligiblePredicate)); // Push down conjuncts from the inherited predicate that apply to common grouping symbols PlanNode rewrittenNode = context.defaultRewrite(node, inlineSymbols(commonGroupingSymbolMapping, combineConjuncts(conjuncts.get(true)))); // All other conjuncts, if any, will be in the filter node. if (!conjuncts.get(false).isEmpty()) { rewrittenNode = new FilterNode(idAllocator.getNextId(), rewrittenNode, combineConjuncts(conjuncts.get(false))); } return rewrittenNode; }