use of io.trino.sql.planner.plan.IntersectNode 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.IntersectNode in project trino by trinodb.
the class TestMergeIntersect method buildNestedIntersect.
private PlanNode buildNestedIntersect(PlanBuilder builder, boolean lefSourceDistinct, boolean rightSourceDistinct, boolean parentDistinct) {
Symbol v1 = builder.symbol("v_1");
Symbol v2 = builder.symbol("v_2");
Symbol v3 = builder.symbol("v_3");
Symbol v4 = builder.symbol("v_4");
Symbol a = builder.symbol("a");
Symbol b = builder.symbol("b");
Symbol c = builder.symbol("c");
IntersectNode child1 = builder.intersect(ImmutableListMultimap.of(a, v1, a, v2), ImmutableList.of(builder.values(v1), builder.values(v2)), lefSourceDistinct);
IntersectNode child2 = builder.intersect(ImmutableListMultimap.of(b, v3, b, v4), ImmutableList.of(builder.values(v3), builder.values(v4)), rightSourceDistinct);
return builder.intersect(ImmutableListMultimap.of(c, a, c, b), ImmutableList.of(child1, child2), parentDistinct);
}
use of io.trino.sql.planner.plan.IntersectNode in project trino by trinodb.
the class RelationPlanner method visitIntersect.
@Override
protected RelationPlan visitIntersect(Intersect node, Void context) {
checkArgument(!node.getRelations().isEmpty(), "No relations specified for INTERSECT");
SetOperationPlan setOperationPlan = process(node);
PlanNode planNode = new IntersectNode(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.IntersectNode in project trino by trinodb.
the class SetOperationMerge method merge.
/**
* Merge all matching source nodes. This method is assumed to be used only for associative set operations: UNION and INTERSECT.
*
* @return Merged plan node if applied.
*/
public Optional<SetOperationNode> merge() {
checkState(node instanceof UnionNode || node instanceof IntersectNode, "unexpected node type: %s", node.getClass().getSimpleName());
Lookup lookup = context.getLookup();
List<PlanNode> sources = node.getSources().stream().flatMap(lookup::resolveGroup).collect(Collectors.toList());
ImmutableListMultimap.Builder<Symbol, Symbol> newMappingsBuilder = ImmutableListMultimap.builder();
boolean resultIsDistinct = false;
boolean rewritten = false;
for (int i = 0; i < sources.size(); i++) {
PlanNode source = sources.get(i);
// Determine if set operations can be merged and whether the resulting set operation is quantified DISTINCT or ALL
Optional<Boolean> mergedQuantifier = mergedQuantifierIsDistinct(node, source);
if (mergedQuantifier.isPresent()) {
addMergedMappings((SetOperationNode) source, i, newMappingsBuilder);
resultIsDistinct |= mergedQuantifier.get();
rewritten = true;
} else {
// Keep mapping as it is
addOriginalMappings(source, i, newMappingsBuilder);
}
}
if (!rewritten) {
return Optional.empty();
}
if (node instanceof UnionNode) {
return Optional.of(new UnionNode(node.getId(), newSources, newMappingsBuilder.build(), node.getOutputSymbols()));
}
return Optional.of(new IntersectNode(node.getId(), newSources, newMappingsBuilder.build(), node.getOutputSymbols(), resultIsDistinct));
}
Aggregations