private static Map<Symbol, Symbol> computeIdentityTranslations(Assignments assignments) { Map<Symbol, Symbol> outputToInput = new HashMap<>(); for (Map.Entry<Symbol, Expression> assignment : assignments.getMap().entrySet()) { if (assignment.getValue() instanceof SymbolReference) { outputToInput.put(assignment.getKey(), Symbol.from(assignment.getValue())); } } return outputToInput; }
public Builder putAll(Assignments assignments) { return putAll(assignments.getMap()); }
private void printAssignments(Assignments assignments, int indent) { for (Map.Entry<Symbol, Expression> entry : assignments.getMap().entrySet()) { if (entry.getValue() instanceof SymbolReference && ((SymbolReference) entry.getValue()).getName().equals(entry.getKey().getName())) { // skip identity assignments continue; } print(indent, "%s := %s", entry.getKey(), entry.getValue()); } }
@Override public StreamProperties visitProject(ProjectNode node, List<StreamProperties> inputProperties) { StreamProperties properties = Iterables.getOnlyElement(inputProperties); // We can describe properties in terms of inputs that are projected unmodified (i.e., identity projections) Map<Symbol, Symbol> identities = computeIdentityTranslations(node.getAssignments().getMap()); return properties.translate(column -> Optional.ofNullable(identities.get(column))); }
@Override public Map<Symbol, Symbol> visitProject(ProjectNode node, Set<Symbol> lookupSymbols) { // Map from output Symbols to source Symbols Map<Symbol, Symbol> directSymbolTranslationOutputMap = Maps.transformValues(Maps.filterValues(node.getAssignments().getMap(), SymbolReference.class::isInstance), Symbol::from); Map<Symbol, Symbol> outputToSourceMap = lookupSymbols.stream() .filter(directSymbolTranslationOutputMap.keySet()::contains) .collect(toImmutableMap(identity(), directSymbolTranslationOutputMap::get)); checkState(!outputToSourceMap.isEmpty(), "No lookup symbols were able to pass through the projection"); // Map from source Symbols to underlying index source Symbols Map<Symbol, Symbol> sourceToIndexMap = node.getSource().accept(this, ImmutableSet.copyOf(outputToSourceMap.values())); // Generate the Map the connects lookup symbols to underlying index source symbols Map<Symbol, Symbol> outputToIndexMap = Maps.transformValues(Maps.filterValues(outputToSourceMap, in(sourceToIndexMap.keySet())), Functions.forMap(sourceToIndexMap)); return ImmutableMap.copyOf(outputToIndexMap); }
private static Map<Symbol, Expression> getAssignments(PlanNode node) { if (node instanceof ProjectNode) { ProjectNode projectNode = (ProjectNode) node; return projectNode.getAssignments().getMap(); } else if (node instanceof ApplyNode) { ApplyNode applyNode = (ApplyNode) node; return applyNode.getSubqueryAssignments().getMap(); } else { return null; } }
@Override public PlanNode visitProject(ProjectNode node, RewriteContext<Expression> context) { Set<Symbol> deterministicSymbols = node.getAssignments().entrySet().stream() .filter(entry -> DeterminismEvaluator.isDeterministic(entry.getValue())) .map(Map.Entry::getKey) .collect(Collectors.toSet()); Predicate<Expression> deterministic = conjunct -> SymbolsExtractor.extractUnique(conjunct).stream() .allMatch(deterministicSymbols::contains); Map<Boolean, List<Expression>> conjuncts = extractConjuncts(context.get()).stream().collect(Collectors.partitioningBy(deterministic)); // Push down conjuncts from the inherited predicate that only depend on deterministic assignments with // certain limitations. List<Expression> deterministicConjuncts = conjuncts.get(true); // We partition the expressions in the deterministicConjuncts into two lists, and only inline the // expressions that are in the inlining targets list. Map<Boolean, List<Expression>> inlineConjuncts = deterministicConjuncts.stream() .collect(Collectors.partitioningBy(expression -> isInliningCandidate(expression, node))); List<Expression> inlinedDeterministicConjuncts = inlineConjuncts.get(true).stream() .map(entry -> inlineSymbols(node.getAssignments().getMap(), entry)) .collect(Collectors.toList()); PlanNode rewrittenNode = context.defaultRewrite(node, combineConjuncts(inlinedDeterministicConjuncts)); // All deterministic conjuncts that contains non-inlining targets, and non-deterministic conjuncts, // if any, will be in the filter node. List<Expression> nonInliningConjuncts = inlineConjuncts.get(false); nonInliningConjuncts.addAll(conjuncts.get(false)); if (!nonInliningConjuncts.isEmpty()) { rewrittenNode = new FilterNode(idAllocator.getNextId(), rewrittenNode, combineConjuncts(nonInliningConjuncts)); } return rewrittenNode; }
for (Map.Entry<Symbol, Expression> entry : oldAssignments.getMap().entrySet()) { Expression expression = canonicalize(entry.getValue());
project.getAssignments().getMap(), output -> !(project.getAssignments().isIdentity(output) && targetOutputs.contains(output)));
for (Map.Entry<Symbol, Expression> entry : node.getSubqueryAssignments().getMap().entrySet()) { Symbol output = entry.getKey(); Expression expression = entry.getValue();
private Map<String, SymbolReference> getUpdatedAssignments(Assignments assignments) { ImmutableMap.Builder<String, SymbolReference> mapUpdate = ImmutableMap.builder(); for (Map.Entry<Symbol, Expression> assignment : assignments.getMap().entrySet()) { for (Map.Entry<String, SymbolReference> existingAlias : map.entrySet()) { if (assignment.getValue().equals(existingAlias.getValue())) { // Simple symbol rename mapUpdate.put(existingAlias.getKey(), assignment.getKey().toSymbolReference()); } else if (assignment.getKey().toSymbolReference().equals(existingAlias.getValue())) { /* * Special case for nodes that can alias symbols in the node's assignment map. * In this case, we've already added the alias in the map, but we won't include it * as a simple rename as covered above. Add the existing alias to the result if * the LHS of the assignment matches the symbol reference of the existing alias. * * This comes up when we alias expressions in project nodes for use further up the tree. * At the beginning for the function, map contains { NEW_ALIAS: SymbolReference("expr_2" } * and the assignments map contains { expr_2 := <some expression> }. */ mapUpdate.put(existingAlias.getKey(), existingAlias.getValue()); } } } return mapUpdate.build(); }
@Override public JoinGraph visitProject(ProjectNode node, Context context) { if (node.isIdentity()) { JoinGraph graph = node.getSource().accept(this, context); return graph.withAssignments(node.getAssignments().getMap()); } return visitPlan(node, context); }
@Override public PlanWithProperties visitProject(ProjectNode node, HashComputationSet parentPreference) { Map<Symbol, Symbol> outputToInputMapping = computeIdentityTranslations(node.getAssignments().getMap()); HashComputationSet sourceContext = parentPreference.translate(symbol -> Optional.ofNullable(outputToInputMapping.get(symbol))); PlanWithProperties child = plan(node.getSource(), sourceContext); // create a new project node with all assignments from the original node Assignments.Builder newAssignments = Assignments.builder(); newAssignments.putAll(node.getAssignments()); // and all hash symbols that could be translated to the source symbols Map<HashComputation, Symbol> allHashSymbols = new HashMap<>(); for (HashComputation hashComputation : sourceContext.getHashes()) { Symbol hashSymbol = child.getHashSymbols().get(hashComputation); Expression hashExpression; if (hashSymbol == null) { hashSymbol = symbolAllocator.newHashSymbol(); hashExpression = hashComputation.getHashExpression(); } else { hashExpression = hashSymbol.toSymbolReference(); } newAssignments.put(hashSymbol, hashExpression); allHashSymbols.put(hashComputation, hashSymbol); } return new PlanWithProperties(new ProjectNode(node.getId(), child.getNode(), newAssignments.build()), allHashSymbols); }