@Override public PlanNode visitUnion(UnionNode node, RewriteContext<Expression> context) { boolean modified = false; ImmutableList.Builder<PlanNode> builder = ImmutableList.builder(); for (int i = 0; i < node.getSources().size(); i++) { Expression sourcePredicate = inlineSymbols(node.sourceSymbolMap(i), context.get()); PlanNode source = node.getSources().get(i); PlanNode rewrittenSource = context.rewrite(source, sourcePredicate); if (rewrittenSource != source) { modified = true; } builder.add(rewrittenSource); } if (modified) { return new UnionNode(node.getId(), builder.build(), node.getSymbolMapping(), node.getOutputSymbols()); } return node; }
Map<Symbol, SymbolReference> outputToInput = source.sourceSymbolMap(i); // Map: output of union -> input of this source to the union
private PlanNode pushProjectionThrough(ProjectNode node, UnionNode source) { // OutputLayout of the resultant Union, will be same as the layout of the Project List<Symbol> outputLayout = node.getOutputSymbols(); // Mapping from the output symbol to ordered list of symbols from each of the sources ImmutableListMultimap.Builder<Symbol, Symbol> mappings = ImmutableListMultimap.builder(); // sources for the resultant UnionNode ImmutableList.Builder<PlanNode> outputSources = ImmutableList.builder(); for (int i = 0; i < source.getSources().size(); i++) { Map<Symbol, QualifiedNameReference> outputToInput = source.sourceSymbolMap(i); // Map: output of union -> input of this source to the union ImmutableMap.Builder<Symbol, Expression> assignments = ImmutableMap.builder(); // assignments for the new ProjectNode // mapping from current ProjectNode to new ProjectNode, used to identify the output layout Map<Symbol, Symbol> projectSymbolMapping = new HashMap<>(); // Translate the assignments in the ProjectNode using symbols of the source of the UnionNode for (Map.Entry<Symbol, Expression> entry : node.getAssignments().entrySet()) { Expression translatedExpression = translateExpression(entry.getValue(), outputToInput); Type type = symbolAllocator.getTypes().get(entry.getKey()); Symbol symbol = symbolAllocator.newSymbol(translatedExpression, type); assignments.put(symbol, translatedExpression); projectSymbolMapping.put(entry.getKey(), symbol); } outputSources.add(new ProjectNode(idAllocator.getNextId(), source.getSources().get(i), assignments.build())); outputLayout.forEach(symbol -> mappings.put(symbol, projectSymbolMapping.get(symbol))); } return new UnionNode(node.getId(), outputSources.build(), mappings.build(), ImmutableList.copyOf(mappings.build().keySet())); }
@Override public PlanNode visitUnion(UnionNode node, RewriteContext<Expression> context) { boolean modified = false; ImmutableList.Builder<PlanNode> builder = ImmutableList.builder(); for (int i = 0; i < node.getSources().size(); i++) { Expression sourcePredicate = ExpressionTreeRewriter.rewriteWith(new ExpressionSymbolInliner(node.sourceSymbolMap(i)), context.get()); PlanNode source = node.getSources().get(i); PlanNode rewrittenSource = context.rewrite(source, sourcePredicate); if (rewrittenSource != source) { modified = true; } builder.add(rewrittenSource); } if (modified) { return new UnionNode(node.getId(), builder.build(), node.getSymbolMapping(), node.getOutputSymbols()); } return node; }