@Override public PlanNode replaceChildren(List<PlanNode> newChildren) { return new ProjectNode(getId(), Iterables.getOnlyElement(newChildren), assignments); } }
@Override public Void visitProject(ProjectNode node, Integer indent) { if (node.getSource() instanceof FilterNode) { return visitScanFilterAndProjectInfo(node.getId(), Optional.of((FilterNode) node.getSource()), Optional.of(node), indent); } return visitScanFilterAndProjectInfo(node.getId(), Optional.empty(), Optional.of(node), indent); }
@Override protected Optional<PlanNode> pushDownProjectOff( PlanNodeIdAllocator idAllocator, ProjectNode childProjectNode, Set<Symbol> referencedOutputs) { return Optional.of( new ProjectNode( childProjectNode.getId(), childProjectNode.getSource(), childProjectNode.getAssignments().filter(referencedOutputs))); } }
@Override public PlanNode visitProject(ProjectNode node, RewriteContext<Void> context) { PlanNode source = context.rewrite(node.getSource()); return new ProjectNode(node.getId(), source, canonicalize(node.getAssignments())); }
@Override public PlanNode visitProject(ProjectNode node, RewriteContext<Set<Symbol>> context) { ImmutableSet.Builder<Symbol> expectedInputs = ImmutableSet.builder(); Assignments.Builder builder = Assignments.builder(); node.getAssignments().forEach((symbol, expression) -> { if (context.get().contains(symbol)) { expectedInputs.addAll(SymbolsExtractor.extractUnique(expression)); builder.put(symbol, expression); } }); PlanNode source = context.rewrite(node.getSource(), expectedInputs.build()); return new ProjectNode(node.getId(), source, builder.build()); }
newTargetChild = new ProjectNode(project.getId(), newTargetChild, newAssignments);
@Override public Optional<Decorrelated> visitProject(ProjectNode node, PlanNode reference) { if (isCorrelatedShallowly(node)) { // TODO: handle correlated projection return Optional.empty(); } Optional<Decorrelated> result = decorrelate(node.getSource()); return result.map(decorrelated -> { Assignments.Builder assignments = Assignments.builder() .putAll(node.getAssignments()); // Pull up all symbols used by a filter (except correlation) decorrelated.getCorrelatedPredicates().stream() .flatMap(AstUtils::preOrder) .filter(SymbolReference.class::isInstance) .map(SymbolReference.class::cast) .filter(symbolReference -> !correlation.contains(Symbol.from(symbolReference))) .forEach(symbolReference -> assignments.putIdentity(Symbol.from(symbolReference))); return new Decorrelated( decorrelated.getCorrelatedPredicates(), new ProjectNode( node.getId(), // FIXME should I reuse or not? decorrelated.getDecorrelatedNode(), assignments.build())); }); }
@Override public PhysicalOperation visitProject(ProjectNode node, LocalExecutionPlanContext context) { PlanNode sourceNode; Optional<Expression> filterExpression = Optional.empty(); if (node.getSource() instanceof FilterNode) { FilterNode filterNode = (FilterNode) node.getSource(); sourceNode = filterNode.getSource(); filterExpression = Optional.of(filterNode.getPredicate()); } else { sourceNode = node.getSource(); } List<Symbol> outputSymbols = node.getOutputSymbols(); return visitScanFilterAndProject(context, node.getId(), sourceNode, filterExpression, node.getAssignments(), outputSymbols); }
return Result.ofPlanNode(new UnionNode(parent.getId(), outputSources.build(), mappings.build(), ImmutableList.copyOf(mappings.build().keySet())));
@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); }
@Override public Result apply(ProjectNode projectNode, Captures captures, Context context) { Assignments assignments = projectNode.getAssignments().rewrite(x -> rewriter.rewrite(x, context)); if (projectNode.getAssignments().equals(assignments)) { return Result.empty(); } return Result.ofPlanNode(new ProjectNode(projectNode.getId(), projectNode.getSource(), assignments)); } }
@Override public PlanNode visitProject(ProjectNode node, List<PlanNode> newChildren) { return new ProjectNode(node.getId(), Iterables.getOnlyElement(newChildren), node.getAssignments()); }
@Override public PlanNode visitProject(ProjectNode node, RewriteContext<Void> context) { PlanNode source = context.rewrite(node.getSource()); Map<Symbol, Expression> assignments = ImmutableMap.copyOf(Maps.transformValues(node.getAssignments(), this::simplifyExpression)); return new ProjectNode(node.getId(), source, assignments); }
@Override public PlanNode visitProject(ProjectNode node, RewriteContext<Set<Symbol>> context) { ImmutableSet.Builder<Symbol> expectedInputs = ImmutableSet.builder(); ImmutableMap.Builder<Symbol, Expression> builder = ImmutableMap.builder(); for (int i = 0; i < node.getOutputSymbols().size(); i++) { Symbol output = node.getOutputSymbols().get(i); Expression expression = node.getAssignments().get(output); if (context.get().contains(output)) { expectedInputs.addAll(DependencyExtractor.extractUnique(expression)); builder.put(output, expression); } } PlanNode source = context.rewrite(node.getSource(), expectedInputs.build()); return new ProjectNode(node.getId(), source, builder.build()); }
@Override public PlanNode visitProject(ProjectNode node, RewriteContext<Void> context) { PlanNode source = context.rewrite(node.getSource()); Map<Symbol, Expression> assignments = ImmutableMap.copyOf(Maps.transformValues(node.getAssignments(), CanonicalizeExpressions::canonicalizeExpression)); return new ProjectNode(node.getId(), source, assignments); }
@Override public PlanNode visitProject(ProjectNode node, RewriteContext<Void> context) { PlanNode source = context.rewrite(node.getSource()); Map<Symbol, Expression> assignments = ImmutableMap.copyOf(Maps.transformValues(node.getAssignments(), this::desugar)); return new ProjectNode(node.getId(), source, assignments); }
@Override public PlanNode visitProject(ProjectNode node, RewriteContext<Void> context) { PlanNode source = context.rewrite(node.getSource()); // only merge if the source is completely deterministic // todo perform partial merge, pushing down expressions that have deterministic sources if (source instanceof ProjectNode && ((ProjectNode) source).getAssignments().values().stream().allMatch(DeterminismEvaluator::isDeterministic)) { ImmutableMap.Builder<Symbol, Expression> projections = ImmutableMap.builder(); for (Map.Entry<Symbol, Expression> projection : node.getAssignments().entrySet()) { Expression inlined = ExpressionTreeRewriter.rewriteWith(new ExpressionSymbolInliner(((ProjectNode) source).getAssignments()), projection.getValue()); projections.put(projection.getKey(), inlined); } return new ProjectNode(node.getId(), ((ProjectNode) source).getSource(), projections.build()); } return replaceChildren(node, ImmutableList.of(source)); } }
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 PhysicalOperation visitProject(ProjectNode node, LocalExecutionPlanContext context) { PlanNode sourceNode; Expression filterExpression; if (node.getSource() instanceof FilterNode) { FilterNode filterNode = (FilterNode) node.getSource(); sourceNode = filterNode.getSource(); filterExpression = filterNode.getPredicate(); } else { sourceNode = node.getSource(); filterExpression = BooleanLiteral.TRUE_LITERAL; } List<Symbol> outputSymbols = node.getOutputSymbols(); return visitScanFilterAndProject(context, node.getId(), sourceNode, filterExpression, node.getAssignments(), outputSymbols); }