Search in sources :

Example 1 with ExceptNode

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());
}
Also used : Symbol(io.trino.sql.planner.Symbol) PlanNode(io.trino.sql.planner.plan.PlanNode) UnionNode(io.trino.sql.planner.plan.UnionNode) ExceptNode(io.trino.sql.planner.plan.ExceptNode) ImmutableListMultimap(com.google.common.collect.ImmutableListMultimap) Lookup(io.trino.sql.planner.iterative.Lookup) IntersectNode(io.trino.sql.planner.plan.IntersectNode)

Example 2 with ExceptNode

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);
}
Also used : PlanNode(io.trino.sql.planner.plan.PlanNode) ExceptNode(io.trino.sql.planner.plan.ExceptNode)

Example 3 with ExceptNode

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()));
}
Also used : ValuesNode(io.trino.sql.planner.plan.ValuesNode) ImmutableList(com.google.common.collect.ImmutableList) Symbol(io.trino.sql.planner.Symbol) Assignments(io.trino.sql.planner.plan.Assignments) AggregationNode(io.trino.sql.planner.plan.AggregationNode) PlanNode(io.trino.sql.planner.plan.PlanNode) ExceptNode(io.trino.sql.planner.plan.ExceptNode) ImmutableListMultimap(com.google.common.collect.ImmutableListMultimap) ProjectNode(io.trino.sql.planner.plan.ProjectNode)

Example 4 with ExceptNode

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);
}
Also used : ValuesNode(io.trino.sql.planner.plan.ValuesNode) ExceptNode(io.trino.sql.planner.plan.ExceptNode) Symbol(io.trino.sql.planner.Symbol)

Aggregations

ExceptNode (io.trino.sql.planner.plan.ExceptNode)4 Symbol (io.trino.sql.planner.Symbol)3 PlanNode (io.trino.sql.planner.plan.PlanNode)3 ImmutableListMultimap (com.google.common.collect.ImmutableListMultimap)2 ValuesNode (io.trino.sql.planner.plan.ValuesNode)2 ImmutableList (com.google.common.collect.ImmutableList)1 Lookup (io.trino.sql.planner.iterative.Lookup)1 AggregationNode (io.trino.sql.planner.plan.AggregationNode)1 Assignments (io.trino.sql.planner.plan.Assignments)1 IntersectNode (io.trino.sql.planner.plan.IntersectNode)1 ProjectNode (io.trino.sql.planner.plan.ProjectNode)1 UnionNode (io.trino.sql.planner.plan.UnionNode)1