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<Set<Symbol>> context) { ImmutableSet.Builder<Symbol> expectedInputs = ImmutableSet.builder(); List<Symbol> newAggregationArguments = node.getAggregationArguments().stream() .filter(context.get()::contains) .collect(Collectors.toList()); expectedInputs.addAll(newAggregationArguments); ImmutableList.Builder<List<Symbol>> newGroupingSets = ImmutableList.builder(); Map<Symbol, Symbol> newGroupingMapping = new HashMap<>(); for (List<Symbol> groupingSet : node.getGroupingSets()) { ImmutableList.Builder<Symbol> newGroupingSet = ImmutableList.builder(); for (Symbol output : groupingSet) { if (context.get().contains(output)) { newGroupingSet.add(output); newGroupingMapping.putIfAbsent(output, node.getGroupingColumns().get(output)); expectedInputs.add(node.getGroupingColumns().get(output)); } } newGroupingSets.add(newGroupingSet.build()); } PlanNode source = context.rewrite(node.getSource(), expectedInputs.build()); return new GroupIdNode(node.getId(), source, newGroupingSets.build(), newGroupingMapping, newAggregationArguments, node.getGroupIdSymbol()); }
for (Symbol output : node.getAggregationArguments()) { int inputChannel = source.getLayout().get(output);
@Override public PlanNode visitGroupId(GroupIdNode node, RewriteContext<Void> context) { PlanNode source = context.rewrite(node.getSource()); Map<Symbol, Symbol> newGroupingMappings = new HashMap<>(); ImmutableList.Builder<List<Symbol>> newGroupingSets = ImmutableList.builder(); for (List<Symbol> groupingSet : node.getGroupingSets()) { ImmutableList.Builder<Symbol> newGroupingSet = ImmutableList.builder(); for (Symbol output : groupingSet) { newGroupingMappings.putIfAbsent(canonicalize(output), canonicalize(node.getGroupingColumns().get(output))); newGroupingSet.add(canonicalize(output)); } newGroupingSets.add(newGroupingSet.build()); } return new GroupIdNode(node.getId(), source, newGroupingSets.build(), newGroupingMappings, canonicalizeAndDistinct(node.getAggregationArguments()), canonicalize(node.getGroupIdSymbol())); }
@Override public MatchResult detailMatches(PlanNode node, StatsProvider stats, Session session, Metadata metadata, SymbolAliases symbolAliases) { checkState(shapeMatches(node), "Plan testing framework error: shapeMatches returned false in detailMatches in %s", this.getClass().getName()); GroupIdNode groudIdNode = (GroupIdNode) node; List<List<Symbol>> actualGroups = groudIdNode.getGroupingSets(); List<Symbol> actualAggregationArguments = groudIdNode.getAggregationArguments(); if (actualGroups.size() != groups.size()) { return NO_MATCH; } for (int i = 0; i < actualGroups.size(); i++) { if (!AggregationMatcher.matches(groups.get(i), actualGroups.get(i), symbolAliases)) { return NO_MATCH; } } if (!AggregationMatcher.matches(identityMappings.keySet(), actualAggregationArguments, symbolAliases)) { return NO_MATCH; } return match(groupIdAlias, groudIdNode.getGroupIdSymbol().toSymbolReference()); }