use of io.trino.sql.planner.plan.ExceptNode in project trino by trinodb.
the class SetOperationMerge method mergeFirstSource.
/**
* Only merge first source node. This method is assumed to be used for EXCEPT, which is a non-associative set operation.
* Provides a correct plan transformation also for associative set operations: UNION and INTERSECT.
*
* @return Merged plan node if applied.
*/
public Optional<SetOperationNode> mergeFirstSource() {
Lookup lookup = context.getLookup();
List<PlanNode> sources = node.getSources().stream().flatMap(lookup::resolveGroup).collect(Collectors.toList());
PlanNode child = sources.get(0);
// Determine if set operations can be merged and whether the resulting set operation is quantified DISTINCT or ALL
Optional<Boolean> mergedQuantifier = mergedQuantifierIsDistinct(node, child);
if (mergedQuantifier.isEmpty()) {
return Optional.empty();
}
ImmutableListMultimap.Builder<Symbol, Symbol> newMappingsBuilder = ImmutableListMultimap.builder();
// Merge all sources of the first source.
addMergedMappings((SetOperationNode) child, 0, newMappingsBuilder);
// Keep remaining as it is
for (int i = 1; i < sources.size(); i++) {
PlanNode source = sources.get(i);
addOriginalMappings(source, i, newMappingsBuilder);
}
if (node instanceof UnionNode) {
return Optional.of(new UnionNode(node.getId(), newSources, newMappingsBuilder.build(), node.getOutputSymbols()));
}
if (node instanceof IntersectNode) {
return Optional.of(new IntersectNode(node.getId(), newSources, newMappingsBuilder.build(), node.getOutputSymbols(), mergedQuantifier.get()));
}
if (node instanceof ExceptNode) {
return Optional.of(new ExceptNode(node.getId(), newSources, newMappingsBuilder.build(), node.getOutputSymbols(), mergedQuantifier.get()));
}
throw new IllegalArgumentException("unexpected node type: " + node.getClass().getSimpleName());
}
use of io.trino.sql.planner.plan.ExceptNode in project trino by trinodb.
the class RelationPlanner method visitExcept.
@Override
protected RelationPlan visitExcept(Except node, Void context) {
checkArgument(!node.getRelations().isEmpty(), "No relations specified for EXCEPT");
SetOperationPlan setOperationPlan = process(node);
PlanNode planNode = new ExceptNode(idAllocator.getNextId(), setOperationPlan.getSources(), setOperationPlan.getSymbolMapping(), ImmutableList.copyOf(setOperationPlan.getSymbolMapping().keySet()), node.isDistinct());
return new RelationPlan(planNode, analysis.getScope(node), planNode.getOutputSymbols(), outerContext);
}
use of io.trino.sql.planner.plan.ExceptNode in project trino by trinodb.
the class RemoveEmptyExceptBranches method apply.
@Override
public Result apply(ExceptNode node, Captures captures, Context context) {
if (isEmpty(node.getSources().get(0), context.getLookup())) {
return Result.ofPlanNode(new ValuesNode(node.getId(), node.getOutputSymbols(), ImmutableList.of()));
}
boolean hasEmptyBranches = node.getSources().stream().skip(// first source is the set we're excluding rows from, so ignore it
1).anyMatch(source -> isEmpty(source, context.getLookup()));
if (!hasEmptyBranches) {
return Result.empty();
}
ImmutableList.Builder<PlanNode> newSourcesBuilder = ImmutableList.builder();
ImmutableListMultimap.Builder<Symbol, Symbol> outputsToInputsBuilder = ImmutableListMultimap.builder();
for (int i = 0; i < node.getSources().size(); i++) {
PlanNode source = node.getSources().get(i);
if (i == 0 || !isEmpty(source, context.getLookup())) {
newSourcesBuilder.add(source);
for (Symbol column : node.getOutputSymbols()) {
outputsToInputsBuilder.put(column, node.getSymbolMapping().get(column).get(i));
}
}
}
List<PlanNode> newSources = newSourcesBuilder.build();
ListMultimap<Symbol, Symbol> outputsToInputs = outputsToInputsBuilder.build();
if (newSources.size() == 1) {
Assignments.Builder assignments = Assignments.builder();
outputsToInputs.entries().stream().forEach(entry -> assignments.put(entry.getKey(), entry.getValue().toSymbolReference()));
if (node.isDistinct()) {
return Result.ofPlanNode(new AggregationNode(node.getId(), new ProjectNode(context.getIdAllocator().getNextId(), newSources.get(0), assignments.build()), ImmutableMap.of(), singleGroupingSet(node.getOutputSymbols()), ImmutableList.of(), Step.SINGLE, Optional.empty(), Optional.empty()));
}
return Result.ofPlanNode(new ProjectNode(node.getId(), newSources.get(0), assignments.build()));
}
return Result.ofPlanNode(new ExceptNode(node.getId(), newSources, outputsToInputs, node.getOutputSymbols(), node.isDistinct()));
}
use of io.trino.sql.planner.plan.ExceptNode in project trino by trinodb.
the class TestMergeExcept method buildNestedExcept.
private PlanNode buildNestedExcept(PlanBuilder builder, boolean sourceDistinct, boolean parentDistinct) {
Symbol v1 = builder.symbol("v_1");
Symbol v2 = builder.symbol("v_2");
Symbol a = builder.symbol("a");
Symbol b = builder.symbol("b");
Symbol c = builder.symbol("c");
ExceptNode child1 = builder.except(ImmutableListMultimap.of(a, v1, a, v2), ImmutableList.of(builder.values(v1), builder.values(v2)), sourceDistinct);
ValuesNode child2 = builder.values(b);
return builder.except(ImmutableListMultimap.of(c, a, c, b), ImmutableList.of(child1, child2), parentDistinct);
}
Aggregations