public boolean isIdentity() { for (Map.Entry<Symbol, Expression> entry : assignments.entrySet()) { Expression expression = entry.getValue(); Symbol symbol = entry.getKey(); if (!(expression instanceof SymbolReference && ((SymbolReference) expression).getName().equals(symbol.getName()))) { return false; } } return true; }
@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<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; }
@Override public Void visitProject(ProjectNode node, Void context) { visitPlan(node, context); for (Map.Entry<Symbol, Expression> entry : node.getAssignments().entrySet()) { Type expectedType = types.get(entry.getKey()); if (entry.getValue() instanceof SymbolReference) { SymbolReference symbolReference = (SymbolReference) entry.getValue(); verifyTypeSignature(entry.getKey(), expectedType.getTypeSignature(), types.get(Symbol.from(symbolReference)).getTypeSignature()); continue; } Map<NodeRef<Expression>, Type> expressionTypes = getExpressionTypes(session, metadata, sqlParser, types, entry.getValue(), emptyList(), warningCollector); Type actualType = expressionTypes.get(NodeRef.of(entry.getValue())); verifyTypeSignature(entry.getKey(), expectedType.getTypeSignature(), actualType.getTypeSignature()); } return null; }
@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()); } }
for (Map.Entry<Symbol, Expression> assignment : node.getAssignments().entrySet()) { Expression expression = assignment.getValue();
.entrySet().stream() .collect(Collectors.toMap( Map.Entry::getKey, .entrySet().stream() .filter(entry -> targets.contains(entry.getKey())) .map(Map.Entry::getValue) for (Map.Entry<Symbol, Expression> assignment : child.getAssignments().entrySet()) { if (!targets.contains(assignment.getKey())) { childAssignments.put(assignment);
for (Map.Entry<Symbol, Expression> entry : parent.getAssignments().entrySet()) { Expression translatedExpression = inlineSymbols(outputToInput, entry.getValue()); Type type = context.getSymbolAllocator().getTypes().get(entry.getKey());
for (Map.Entry<Symbol, Expression> projection : project.getAssignments().entrySet()) { Expression translatedExpression = inlineSymbols(outputToInputMap, projection.getValue()); Type type = context.getSymbolAllocator().getTypes().get(projection.getKey()); .forEach(outputBuilder::add); for (Map.Entry<Symbol, Expression> projection : project.getAssignments().entrySet()) { outputBuilder.add(projection.getKey());