private static boolean isSymbolToSymbolProjection(ProjectNode project) { return project.getAssignments().getExpressions().stream().allMatch(e -> e instanceof SymbolReference); }
@Override public Void visitProject(ProjectNode node, ImmutableList.Builder<Expression> context) { context.addAll(node.getAssignments().getExpressions()); return super.visitProject(node, context); }
@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); }
@Override public PlanWithProperties visitProject(ProjectNode node, PreferredProperties preferredProperties) { Map<Symbol, Symbol> identities = computeIdentityTranslations(node.getAssignments()); PreferredProperties translatedPreferred = preferredProperties.translate(symbol -> Optional.ofNullable(identities.get(symbol))); return rebaseAndDeriveProperties(node, planChild(node, translatedPreferred)); }
@Override public Void visitProject(ProjectNode node, Void context) { StringBuilder builder = new StringBuilder(); for (Map.Entry<Symbol, Expression> entry : node.getAssignments().entrySet()) { if ((entry.getValue() instanceof SymbolReference) && ((SymbolReference) entry.getValue()).getName().equals(entry.getKey().getName())) { // skip identity assignments continue; } builder.append(format("%s := %s\\n", entry.getKey(), entry.getValue())); } printNode(node, "Project", builder.toString(), NODE_COLORS.get(NodeType.PROJECT)); return node.getSource().accept(this, context); }
@Override public Expression visitProject(ProjectNode node, Void context) { // TODO: add simple algebraic solver for projection translation (right now only considers identity projections) Expression underlyingPredicate = node.getSource().accept(this, context); List<Expression> projectionEqualities = node.getAssignments().entrySet().stream() .filter(SYMBOL_MATCHES_EXPRESSION.negate()) .map(ENTRY_TO_EQUALITY) .collect(toImmutableList()); return pullExpressionThroughSymbols(combineConjuncts( ImmutableList.<Expression>builder() .addAll(projectionEqualities) .add(underlyingPredicate) .build()), node.getOutputSymbols()); }
@Override public PlanNode visitProject(ProjectNode node, RewriteContext<Context> context) { // Rewrite the lookup symbols in terms of only the pre-projected symbols that have direct translations Set<Symbol> newLookupSymbols = context.get().getLookupSymbols().stream() .map(node.getAssignments()::get) .filter(SymbolReference.class::isInstance) .map(Symbol::from) .collect(toImmutableSet()); if (newLookupSymbols.isEmpty()) { return node; } return context.defaultRewrite(node, new Context(newLookupSymbols, context.get().getSuccess())); }
@Override public Result apply(ProjectNode parent, Captures captures, Context context) { N targetNode = captures.get(targetCapture); return pruneInputs(targetNode.getOutputSymbols(), parent.getAssignments().getExpressions()) .flatMap(prunedOutputs -> this.pushDownProjectOff(context.getIdAllocator(), targetNode, prunedOutputs)) .map(newChild -> parent.replaceChildren(ImmutableList.of(newChild))) .map(Result::ofPlanNode) .orElse(Result.empty()); }
@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))); } }
public static Function<PlanNode, Set<Symbol>> actualAssignments() { return node -> ((ProjectNode) node).getAssignments().getSymbols(); }
@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 protected Optional<PlanNodeStatsEstimate> doCalculate(ProjectNode node, StatsProvider statsProvider, Lookup lookup, Session session, TypeProvider types) { PlanNodeStatsEstimate sourceStats = statsProvider.getStats(node.getSource()); PlanNodeStatsEstimate.Builder calculatedStats = PlanNodeStatsEstimate.builder() .setOutputRowCount(sourceStats.getOutputRowCount()); for (Map.Entry<Symbol, Expression> entry : node.getAssignments().entrySet()) { calculatedStats.addSymbolStatistics(entry.getKey(), scalarStatsCalculator.calculate(entry.getValue(), sourceStats, session, types)); } return Optional.of(calculatedStats.build()); } }
@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()); }
@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 Void visitProject(ProjectNode node, Set<Symbol> boundSymbols) { PlanNode source = node.getSource(); source.accept(this, boundSymbols); // visit child Set<Symbol> inputs = createInputs(source, boundSymbols); for (Expression expression : node.getAssignments().getExpressions()) { Set<Symbol> dependencies = SymbolsExtractor.extractUnique(expression); checkDependencies(inputs, dependencies, "Invalid node. Expression dependencies (%s) not in source plan output (%s)", dependencies, inputs); } return null; }
@Override public PlanNode visitProject(ProjectNode node, RewriteContext<Void> context) { ProjectNode rewrittenNode = (ProjectNode) context.defaultRewrite(node); Assignments assignments = rewrittenNode.getAssignments() .rewrite(expression -> replaceExpression(expression, mapping)); return new ProjectNode(idAllocator.getNextId(), rewrittenNode.getSource(), assignments); }
@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); }
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 MatchResult visitProject(ProjectNode node, PlanMatchPattern pattern) { MatchResult result = super.visitProject(node, pattern); if (!result.isMatch()) { return result; } return match(result.getAliases().replaceAssignments(node.getAssignments())); }