@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 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 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 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); }
private ProjectNode project(PlanNode node, List<Symbol> columns) { return new ProjectNode( idAllocator.getNextId(), node, Assignments.identity(columns)); } }
@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); }
ProjectNode leftCoercion = new ProjectNode(idAllocator.getNextId(), left.getRoot(), leftCoercions.build()); ProjectNode rightCoercion = new ProjectNode(idAllocator.getNextId(), right.getRoot(), rightCoercions.build()); clauses.build(), ImmutableList.<Symbol>builder() .addAll(leftCoercion.getOutputSymbols()) .addAll(rightCoercion.getOutputSymbols()) .build(), Optional.empty(), new ProjectNode(idAllocator.getNextId(), join, assignments.build()), analysis.getScope(node), outputs.build());
@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 Result apply(ProjectNode project, Captures captures, Context context) { if (isIdentityProjection(project)) { return Result.ofPlanNode(project.getSource()); } PlanNode projectNode = new ProjectNode(context.getIdAllocator().getNextId(), project, Assignments.identity(project.getOutputSymbols())); return Result.ofPlanNode(projectNode); }
private static boolean isSymbolToSymbolProjection(ProjectNode project) { return project.getAssignments().getExpressions().stream().allMatch(e -> e instanceof SymbolReference); }
for (Map.Entry<Symbol, Expression> projection : project.getAssignments().entrySet()) { Expression translatedExpression = inlineSymbols(outputToInputMap, projection.getValue()); Type type = context.getSymbolAllocator().getTypes().get(projection.getKey()); inputs.add(symbol); newSourceBuilder.add(new ProjectNode(context.getIdAllocator().getNextId(), exchange.getSources().get(i), projections.build())); inputsBuilder.add(inputs.build()); .forEach(outputBuilder::add); for (Map.Entry<Symbol, Expression> projection : project.getAssignments().entrySet()) { outputBuilder.add(projection.getKey()); return Result.ofPlanNode(restrictOutputs(context.getIdAllocator(), result, ImmutableSet.copyOf(project.getOutputSymbols())).orElse(result));
private static boolean outputsSameAsSource(ProjectNode node) { return ImmutableSet.copyOf(node.getOutputSymbols()).equals(ImmutableSet.copyOf(node.getSource().getOutputSymbols())); }
private boolean isInliningCandidate(Expression expression, ProjectNode node) { // TryExpressions should not be pushed down. However they are now being handled as lambda // passed to a FunctionCall now and should not affect predicate push down. So we want to make // sure the conjuncts are not TryExpressions. verify(AstUtils.preOrder(expression).noneMatch(TryExpression.class::isInstance)); // candidate symbols for inlining are // 1. references to simple constants // 2. references to complex expressions that appear only once // which come from the node, as opposed to an enclosing scope. Set<Symbol> childOutputSet = ImmutableSet.copyOf(node.getOutputSymbols()); Map<Symbol, Long> dependencies = SymbolsExtractor.extractAll(expression).stream() .filter(childOutputSet::contains) .collect(Collectors.groupingBy(Function.identity(), Collectors.counting())); return dependencies.entrySet().stream() .allMatch(entry -> entry.getValue() == 1 || node.getAssignments().get(entry.getKey()) instanceof Literal); }
@Override public PlanNode visitProject(ProjectNode node, List<PlanNode> newChildren) { return new ProjectNode(node.getId(), Iterables.getOnlyElement(newChildren), node.getAssignments()); }
@Override public Map<PlanNodeId, SplitSource> visitProject(ProjectNode node, Void context) { return node.getSource().accept(this, context); }
Assignments assignments = Assignments.builder() .putIdentities(aggregationOutputSymbols) .putAll(subqueryProjection.get().getAssignments()) .build(); return new ProjectNode( idAllocator.getNextId(), aggregationNode.get(), return new ProjectNode( idAllocator.getNextId(), aggregationNode.get(),
@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<PlanNodeStatsEstimate> doCalculate(FilterNode node, StatsProvider sourceStats, Lookup lookup, Session session, TypeProvider types) { PlanNode nodeSource = lookup.resolve(node.getSource()); SemiJoinNode semiJoinNode; if (nodeSource instanceof ProjectNode) { ProjectNode projectNode = (ProjectNode) nodeSource; if (!projectNode.isIdentity()) { return Optional.empty(); } PlanNode projectNodeSource = lookup.resolve(projectNode.getSource()); if (!(projectNodeSource instanceof SemiJoinNode)) { return Optional.empty(); } semiJoinNode = (SemiJoinNode) projectNodeSource; } else if (nodeSource instanceof SemiJoinNode) { semiJoinNode = (SemiJoinNode) nodeSource; } else { return Optional.empty(); } return calculate(node, semiJoinNode, sourceStats, session, types); }
private static JoinNode leftOuterJoin(PlanNodeIdAllocator idAllocator, AssignUniqueId probeSide, ProjectNode buildSide, Expression joinExpression) { return new JoinNode( idAllocator.getNextId(), JoinNode.Type.LEFT, probeSide, buildSide, ImmutableList.of(), ImmutableList.<Symbol>builder() .addAll(probeSide.getOutputSymbols()) .addAll(buildSide.getOutputSymbols()) .build(), Optional.of(joinExpression), Optional.empty(), Optional.empty(), Optional.empty()); }