private Collector<Entry<Symbol, Expression>, Builder, Assignments> toAssignments() { return Collector.of( Assignments::builder, (builder, entry) -> builder.put(entry.getKey(), entry.getValue()), (left, right) -> { left.putAll(right.build()); return left; }, Assignments.Builder::build); }
private Collector<Entry<Symbol, Expression>, Builder, Assignments> toAssignments() { return Collector.of( Assignments::builder, (builder, entry) -> builder.put(entry.getKey(), entry.getValue()), (left, right) -> { left.putAll(right.build()); return left; }, Assignments.Builder::build); }
@Override public Optional<DecorrelationResult> visitProject(ProjectNode node, Void context) { Optional<DecorrelationResult> childDecorrelationResultOptional = lookup.resolve(node.getSource()).accept(this, null); if (!childDecorrelationResultOptional.isPresent()) { return Optional.empty(); } DecorrelationResult childDecorrelationResult = childDecorrelationResultOptional.get(); Set<Symbol> nodeOutputSymbols = ImmutableSet.copyOf(node.getOutputSymbols()); List<Symbol> symbolsToAdd = childDecorrelationResult.symbolsToPropagate.stream() .filter(symbol -> !nodeOutputSymbols.contains(symbol)) .collect(toImmutableList()); Assignments assignments = Assignments.builder() .putAll(node.getAssignments()) .putIdentities(symbolsToAdd) .build(); return Optional.of(new DecorrelationResult( new ProjectNode(idAllocator.getNextId(), childDecorrelationResult.node, assignments), childDecorrelationResult.symbolsToPropagate, childDecorrelationResult.correlatedPredicates, childDecorrelationResult.correlatedSymbolsMapping, childDecorrelationResult.atMostSingleRow)); }
@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 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 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 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())); }); }
private PlanBuilder explicitCoercionFields(PlanBuilder subPlan, Iterable<Expression> alreadyCoerced, Iterable<? extends Expression> uncoerced) { TranslationMap translations = new TranslationMap(subPlan.getRelationPlan(), analysis, lambdaDeclarationToSymbolMap); Assignments.Builder projections = Assignments.builder(); projections.putAll(coerce(uncoerced, subPlan, translations)); for (Expression expression : alreadyCoerced) { if (expression instanceof SymbolReference) { // If this is an identity projection, no need to rewrite it // This is needed because certain synthetic identity expressions such as "group id" introduced when planning GROUPING // don't have a corresponding analysis, so the code below doesn't work for them projections.put(Symbol.from(expression), expression); continue; } Symbol symbol = symbolAllocator.newSymbol(expression, analysis.getType(expression)); Expression rewritten = subPlan.rewrite(expression); projections.put(symbol, rewritten); translations.put(expression, symbol); } return new PlanBuilder(translations, new ProjectNode( idAllocator.getNextId(), subPlan.getRoot(), projections.build()), analysis.getParameters()); }
@Override public Optional<DecorrelationResult> visitProject(ProjectNode node, Void context) { Optional<DecorrelationResult> childDecorrelationResultOptional = lookup.resolve(node.getSource()).accept(this, null); if (!childDecorrelationResultOptional.isPresent()) { return Optional.empty(); } DecorrelationResult childDecorrelationResult = childDecorrelationResultOptional.get(); Set<Symbol> nodeOutputSymbols = ImmutableSet.copyOf(node.getOutputSymbols()); List<Symbol> symbolsToAdd = childDecorrelationResult.symbolsToPropagate.stream() .filter(symbol -> !nodeOutputSymbols.contains(symbol)) .collect(toImmutableList()); Assignments assignments = Assignments.builder() .putAll(node.getAssignments()) .putIdentities(symbolsToAdd) .build(); return Optional.of(new DecorrelationResult( new ProjectNode(idAllocator.getNextId(), childDecorrelationResult.node, assignments), childDecorrelationResult.symbolsToPropagate, childDecorrelationResult.correlatedPredicates, childDecorrelationResult.correlatedSymbolsMapping, childDecorrelationResult.atMostSingleRow)); }
@Override public Result apply(LateralJoinNode parent, Captures captures, Context context) { List<ValuesNode> values = searchFrom(parent.getSubquery(), context.getLookup()) .recurseOnlyWhen(ProjectNode.class::isInstance) .where(ValuesNode.class::isInstance) .findAll(); if (values.size() != 1 || !isSingleRowValuesWithNoColumns(values.get(0))) { return Result.empty(); } List<ProjectNode> subqueryProjections = searchFrom(parent.getSubquery(), context.getLookup()) .where(node -> node instanceof ProjectNode && !node.getOutputSymbols().equals(parent.getCorrelation())) .findAll(); if (subqueryProjections.size() == 0) { return Result.ofPlanNode(parent.getInput()); } else if (subqueryProjections.size() == 1) { Assignments assignments = Assignments.builder() .putIdentities(parent.getInput().getOutputSymbols()) .putAll(subqueryProjections.get(0).getAssignments()) .build(); return Result.ofPlanNode(projectNode(parent.getInput(), assignments, context)); } return Result.empty(); }
@Override public Result apply(LateralJoinNode parent, Captures captures, Context context) { List<ValuesNode> values = searchFrom(parent.getSubquery(), context.getLookup()) .recurseOnlyWhen(ProjectNode.class::isInstance) .where(ValuesNode.class::isInstance) .findAll(); if (values.size() != 1 || !isSingleRowValuesWithNoColumns(values.get(0))) { return Result.empty(); } List<ProjectNode> subqueryProjections = searchFrom(parent.getSubquery(), context.getLookup()) .where(node -> node instanceof ProjectNode && !node.getOutputSymbols().equals(parent.getCorrelation())) .findAll(); if (subqueryProjections.size() == 0) { return Result.ofPlanNode(parent.getInput()); } else if (subqueryProjections.size() == 1) { Assignments assignments = Assignments.builder() .putIdentities(parent.getInput().getOutputSymbols()) .putAll(subqueryProjections.get(0).getAssignments()) .build(); return Result.ofPlanNode(projectNode(parent.getInput(), assignments, context)); } return Result.empty(); }
private PlanBuilder explicitCoercionFields(PlanBuilder subPlan, Iterable<Expression> alreadyCoerced, Iterable<? extends Expression> uncoerced) { TranslationMap translations = new TranslationMap(subPlan.getRelationPlan(), analysis, lambdaDeclarationToSymbolMap); Assignments.Builder projections = Assignments.builder(); projections.putAll(coerce(uncoerced, subPlan, translations)); for (Expression expression : alreadyCoerced) { if (expression instanceof SymbolReference) { // If this is an identity projection, no need to rewrite it // This is needed because certain synthetic identity expressions such as "group id" introduced when planning GROUPING // don't have a corresponding analysis, so the code below doesn't work for them projections.put(Symbol.from(expression), expression); continue; } Symbol symbol = symbolAllocator.newSymbol(expression, analysis.getType(expression)); Expression rewritten = subPlan.rewrite(expression); projections.put(symbol, rewritten); translations.put(expression, symbol); } return new PlanBuilder(translations, new ProjectNode( idAllocator.getNextId(), subPlan.getRoot(), projections.build()), analysis.getParameters()); }
private PlanBuilder explicitCoercionSymbols(PlanBuilder subPlan, Iterable<Symbol> alreadyCoerced, Iterable<? extends Expression> uncoerced) { TranslationMap translations = subPlan.copyTranslations(); Assignments assignments = Assignments.builder() .putAll(coerce(uncoerced, subPlan, translations)) .putIdentities(alreadyCoerced) .build(); return new PlanBuilder(translations, new ProjectNode( idAllocator.getNextId(), subPlan.getRoot(), assignments), analysis.getParameters()); }
public Builder putAll(Assignments assignments) { return putAll(assignments.getMap()); }
private ProjectNode projectExpressions(PlanNode input, Assignments subqueryAssignments) { Assignments assignments = Assignments.builder() .putIdentities(input.getOutputSymbols()) .putAll(subqueryAssignments) .build(); return new ProjectNode( idAllocator.getNextId(), input, assignments); } }
public static Assignments copyOf(Map<Symbol, Expression> assignments) { return builder() .putAll(assignments) .build(); }
public Builder putAll(Assignments assignments) { return putAll(assignments.getMap()); }
private PlanBuilder explicitCoercionSymbols(PlanBuilder subPlan, Iterable<Symbol> alreadyCoerced, Iterable<? extends Expression> uncoerced) { TranslationMap translations = subPlan.copyTranslations(); Assignments assignments = Assignments.builder() .putAll(coerce(uncoerced, subPlan, translations)) .putIdentities(alreadyCoerced) .build(); return new PlanBuilder(translations, new ProjectNode( idAllocator.getNextId(), subPlan.getRoot(), assignments), analysis.getParameters()); }
private ProjectNode projectExpressions(PlanNode input, Assignments subqueryAssignments) { Assignments assignments = Assignments.builder() .putIdentities(input.getOutputSymbols()) .putAll(subqueryAssignments) .build(); return new ProjectNode( idAllocator.getNextId(), input, assignments); } }
public static Assignments copyOf(Map<Symbol, Expression> assignments) { return builder() .putAll(assignments) .build(); }