Search in sources :

Example 11 with Assignments

use of io.trino.sql.planner.plan.Assignments in project trino by trinodb.

the class PushProjectionThroughJoin method pushProjectionThroughJoin.

public static Optional<PlanNode> pushProjectionThroughJoin(PlannerContext plannerContext, ProjectNode projectNode, Lookup lookup, PlanNodeIdAllocator planNodeIdAllocator, Session session, TypeAnalyzer typeAnalyzer, TypeProvider types) {
    if (!projectNode.getAssignments().getExpressions().stream().allMatch(expression -> isDeterministic(expression, plannerContext.getMetadata()))) {
        return Optional.empty();
    }
    PlanNode child = lookup.resolve(projectNode.getSource());
    if (!(child instanceof JoinNode)) {
        return Optional.empty();
    }
    JoinNode joinNode = (JoinNode) child;
    PlanNode leftChild = joinNode.getLeft();
    PlanNode rightChild = joinNode.getRight();
    if (joinNode.getType() != INNER) {
        return Optional.empty();
    }
    Assignments.Builder leftAssignmentsBuilder = Assignments.builder();
    Assignments.Builder rightAssignmentsBuilder = Assignments.builder();
    for (Map.Entry<Symbol, Expression> assignment : projectNode.getAssignments().entrySet()) {
        Expression expression = assignment.getValue();
        Set<Symbol> symbols = extractUnique(expression);
        if (leftChild.getOutputSymbols().containsAll(symbols)) {
            // expression is satisfied with left child symbols
            leftAssignmentsBuilder.put(assignment.getKey(), expression);
        } else if (rightChild.getOutputSymbols().containsAll(symbols)) {
            // expression is satisfied with right child symbols
            rightAssignmentsBuilder.put(assignment.getKey(), expression);
        } else {
            // expression is using symbols from both join sides
            return Optional.empty();
        }
    }
    // add projections for symbols required by the join itself
    Set<Symbol> joinRequiredSymbols = getJoinRequiredSymbols(joinNode);
    for (Symbol requiredSymbol : joinRequiredSymbols) {
        if (leftChild.getOutputSymbols().contains(requiredSymbol)) {
            leftAssignmentsBuilder.putIdentity(requiredSymbol);
        } else {
            checkState(rightChild.getOutputSymbols().contains(requiredSymbol));
            rightAssignmentsBuilder.putIdentity(requiredSymbol);
        }
    }
    Assignments leftAssignments = leftAssignmentsBuilder.build();
    Assignments rightAssignments = rightAssignmentsBuilder.build();
    List<Symbol> leftOutputSymbols = leftAssignments.getOutputs().stream().filter(ImmutableSet.copyOf(projectNode.getOutputSymbols())::contains).collect(toImmutableList());
    List<Symbol> rightOutputSymbols = rightAssignments.getOutputs().stream().filter(ImmutableSet.copyOf(projectNode.getOutputSymbols())::contains).collect(toImmutableList());
    return Optional.of(new JoinNode(joinNode.getId(), joinNode.getType(), inlineProjections(plannerContext, new ProjectNode(planNodeIdAllocator.getNextId(), leftChild, leftAssignments), lookup, session, typeAnalyzer, types), inlineProjections(plannerContext, new ProjectNode(planNodeIdAllocator.getNextId(), rightChild, rightAssignments), lookup, session, typeAnalyzer, types), joinNode.getCriteria(), leftOutputSymbols, rightOutputSymbols, joinNode.isMaySkipOutputDuplicates(), joinNode.getFilter(), joinNode.getLeftHashSymbol(), joinNode.getRightHashSymbol(), joinNode.getDistributionType(), joinNode.isSpillable(), joinNode.getDynamicFilters(), joinNode.getReorderJoinStatsAndCost()));
}
Also used : SymbolsExtractor.extractUnique(io.trino.sql.planner.SymbolsExtractor.extractUnique) INNER(io.trino.sql.planner.plan.JoinNode.Type.INNER) PlanNode(io.trino.sql.planner.plan.PlanNode) DeterminismEvaluator.isDeterministic(io.trino.sql.planner.DeterminismEvaluator.isDeterministic) Map(java.util.Map) ImmutableSet.toImmutableSet(com.google.common.collect.ImmutableSet.toImmutableSet) SymbolsExtractor(io.trino.sql.planner.SymbolsExtractor) JoinNode(io.trino.sql.planner.plan.JoinNode) ProjectNode(io.trino.sql.planner.plan.ProjectNode) Symbol(io.trino.sql.planner.Symbol) ImmutableSet(com.google.common.collect.ImmutableSet) Lookup(io.trino.sql.planner.iterative.Lookup) ImmutableList.toImmutableList(com.google.common.collect.ImmutableList.toImmutableList) Assignments(io.trino.sql.planner.plan.Assignments) Set(java.util.Set) Streams(com.google.common.collect.Streams) Preconditions.checkState(com.google.common.base.Preconditions.checkState) List(java.util.List) TypeAnalyzer(io.trino.sql.planner.TypeAnalyzer) TypeProvider(io.trino.sql.planner.TypeProvider) Optional(java.util.Optional) Expression(io.trino.sql.tree.Expression) PlanNodeIdAllocator(io.trino.sql.planner.PlanNodeIdAllocator) Session(io.trino.Session) PlannerContext(io.trino.sql.PlannerContext) PlanNode(io.trino.sql.planner.plan.PlanNode) Expression(io.trino.sql.tree.Expression) JoinNode(io.trino.sql.planner.plan.JoinNode) Symbol(io.trino.sql.planner.Symbol) Assignments(io.trino.sql.planner.plan.Assignments) ProjectNode(io.trino.sql.planner.plan.ProjectNode) Map(java.util.Map)

Example 12 with Assignments

use of io.trino.sql.planner.plan.Assignments in project trino by trinodb.

the class PushProjectionThroughUnion method apply.

@Override
public Result apply(ProjectNode parent, Captures captures, Context context) {
    UnionNode source = captures.get(CHILD);
    // OutputLayout of the resultant Union, will be same as the layout of the Project
    List<Symbol> outputLayout = parent.getOutputSymbols();
    // Mapping from the output symbol to ordered list of symbols from each of the sources
    ImmutableListMultimap.Builder<Symbol, Symbol> mappings = ImmutableListMultimap.builder();
    // sources for the resultant UnionNode
    ImmutableList.Builder<PlanNode> outputSources = ImmutableList.builder();
    for (int i = 0; i < source.getSources().size(); i++) {
        // Map: output of union -> input of this source to the union
        Map<Symbol, SymbolReference> outputToInput = source.sourceSymbolMap(i);
        // assignments for the new ProjectNode
        Assignments.Builder assignments = Assignments.builder();
        // mapping from current ProjectNode to new ProjectNode, used to identify the output layout
        Map<Symbol, Symbol> projectSymbolMapping = new HashMap<>();
        // Translate the assignments in the ProjectNode using symbols of the source of the UnionNode
        for (Map.Entry<Symbol, Expression> entry : parent.getAssignments().entrySet()) {
            Expression translatedExpression = inlineSymbols(outputToInput, entry.getValue());
            Type type = context.getSymbolAllocator().getTypes().get(entry.getKey());
            Symbol symbol = context.getSymbolAllocator().newSymbol(translatedExpression, type);
            assignments.put(symbol, translatedExpression);
            projectSymbolMapping.put(entry.getKey(), symbol);
        }
        outputSources.add(new ProjectNode(context.getIdAllocator().getNextId(), source.getSources().get(i), assignments.build()));
        outputLayout.forEach(symbol -> mappings.put(symbol, projectSymbolMapping.get(symbol)));
    }
    return Result.ofPlanNode(new UnionNode(parent.getId(), outputSources.build(), mappings.build(), ImmutableList.copyOf(mappings.build().keySet())));
}
Also used : HashMap(java.util.HashMap) Symbol(io.trino.sql.planner.Symbol) ImmutableList(com.google.common.collect.ImmutableList) SymbolReference(io.trino.sql.tree.SymbolReference) Assignments(io.trino.sql.planner.plan.Assignments) Type(io.trino.spi.type.Type) PlanNode(io.trino.sql.planner.plan.PlanNode) UnionNode(io.trino.sql.planner.plan.UnionNode) Expression(io.trino.sql.tree.Expression) ImmutableListMultimap(com.google.common.collect.ImmutableListMultimap) ProjectNode(io.trino.sql.planner.plan.ProjectNode) HashMap(java.util.HashMap) Map(java.util.Map)

Example 13 with Assignments

use of io.trino.sql.planner.plan.Assignments in project trino by trinodb.

the class SetOperationNodeTranslator method appendMarkers.

private static PlanNode appendMarkers(PlanNodeIdAllocator idAllocator, SymbolAllocator symbolAllocator, PlanNode source, int markerIndex, List<Symbol> markers, Map<Symbol, SymbolReference> projections) {
    Assignments.Builder assignments = Assignments.builder();
    // add existing intersect symbols to projection
    for (Map.Entry<Symbol, SymbolReference> entry : projections.entrySet()) {
        Symbol symbol = symbolAllocator.newSymbol(entry.getKey().getName(), symbolAllocator.getTypes().get(entry.getKey()));
        assignments.put(symbol, entry.getValue());
    }
    // add extra marker fields to the projection
    for (int i = 0; i < markers.size(); ++i) {
        Expression expression = (i == markerIndex) ? TRUE_LITERAL : new Cast(new NullLiteral(), toSqlType(BOOLEAN));
        assignments.put(symbolAllocator.newSymbol(markers.get(i).getName(), BOOLEAN), expression);
    }
    return new ProjectNode(idAllocator.getNextId(), source, assignments.build());
}
Also used : Cast(io.trino.sql.tree.Cast) Expression(io.trino.sql.tree.Expression) Symbol(io.trino.sql.planner.Symbol) SymbolReference(io.trino.sql.tree.SymbolReference) Assignments(io.trino.sql.planner.plan.Assignments) ProjectNode(io.trino.sql.planner.plan.ProjectNode) Map(java.util.Map) ImmutableMap(com.google.common.collect.ImmutableMap) NullLiteral(io.trino.sql.tree.NullLiteral)

Example 14 with Assignments

use of io.trino.sql.planner.plan.Assignments in project trino by trinodb.

the class TransformCorrelatedSingleRowSubqueryToProject method apply.

@Override
public Result apply(CorrelatedJoinNode 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());
    }
    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();
}
Also used : PlanNodeSearcher.searchFrom(io.trino.sql.planner.optimizations.PlanNodeSearcher.searchFrom) Assignments(io.trino.sql.planner.plan.Assignments) TRUE_LITERAL(io.trino.sql.tree.BooleanLiteral.TRUE_LITERAL) CorrelatedJoinNode(io.trino.sql.planner.plan.CorrelatedJoinNode) PlanNode(io.trino.sql.planner.plan.PlanNode) CorrelatedJoin.filter(io.trino.sql.planner.plan.Patterns.CorrelatedJoin.filter) List(java.util.List) Pattern(io.trino.matching.Pattern) Captures(io.trino.matching.Captures) Rule(io.trino.sql.planner.iterative.Rule) ValuesNode(io.trino.sql.planner.plan.ValuesNode) ProjectNode(io.trino.sql.planner.plan.ProjectNode) Patterns.correlatedJoin(io.trino.sql.planner.plan.Patterns.correlatedJoin) ValuesNode(io.trino.sql.planner.plan.ValuesNode) Assignments(io.trino.sql.planner.plan.Assignments) ProjectNode(io.trino.sql.planner.plan.ProjectNode)

Example 15 with Assignments

use of io.trino.sql.planner.plan.Assignments in project trino by trinodb.

the class TransformExistsApplyToCorrelatedJoin method rewriteToNonDefaultAggregation.

private Optional<PlanNode> rewriteToNonDefaultAggregation(ApplyNode applyNode, Context context) {
    checkState(applyNode.getSubquery().getOutputSymbols().isEmpty(), "Expected subquery output symbols to be pruned");
    Symbol subqueryTrue = context.getSymbolAllocator().newSymbol("subqueryTrue", BOOLEAN);
    PlanNode subquery = new ProjectNode(context.getIdAllocator().getNextId(), new LimitNode(context.getIdAllocator().getNextId(), applyNode.getSubquery(), 1L, false), Assignments.of(subqueryTrue, TRUE_LITERAL));
    PlanNodeDecorrelator decorrelator = new PlanNodeDecorrelator(plannerContext, context.getSymbolAllocator(), context.getLookup());
    if (decorrelator.decorrelateFilters(subquery, applyNode.getCorrelation()).isEmpty()) {
        return Optional.empty();
    }
    Symbol exists = getOnlyElement(applyNode.getSubqueryAssignments().getSymbols());
    Assignments.Builder assignments = Assignments.builder().putIdentities(applyNode.getInput().getOutputSymbols()).put(exists, new CoalesceExpression(ImmutableList.of(subqueryTrue.toSymbolReference(), BooleanLiteral.FALSE_LITERAL)));
    return Optional.of(new ProjectNode(context.getIdAllocator().getNextId(), new CorrelatedJoinNode(applyNode.getId(), applyNode.getInput(), subquery, applyNode.getCorrelation(), LEFT, TRUE_LITERAL, applyNode.getOriginSubquery()), assignments.build()));
}
Also used : PlanNodeDecorrelator(io.trino.sql.planner.optimizations.PlanNodeDecorrelator) PlanNode(io.trino.sql.planner.plan.PlanNode) LimitNode(io.trino.sql.planner.plan.LimitNode) Symbol(io.trino.sql.planner.Symbol) CorrelatedJoinNode(io.trino.sql.planner.plan.CorrelatedJoinNode) Assignments(io.trino.sql.planner.plan.Assignments) ProjectNode(io.trino.sql.planner.plan.ProjectNode) CoalesceExpression(io.trino.sql.tree.CoalesceExpression)

Aggregations

Assignments (io.trino.sql.planner.plan.Assignments)61 ProjectNode (io.trino.sql.planner.plan.ProjectNode)50 Symbol (io.trino.sql.planner.Symbol)39 Expression (io.trino.sql.tree.Expression)39 ImmutableList (com.google.common.collect.ImmutableList)36 Map (java.util.Map)33 PlanNode (io.trino.sql.planner.plan.PlanNode)26 SymbolReference (io.trino.sql.tree.SymbolReference)26 Captures (io.trino.matching.Captures)23 Pattern (io.trino.matching.Pattern)23 Rule (io.trino.sql.planner.iterative.Rule)23 ImmutableMap.toImmutableMap (com.google.common.collect.ImmutableMap.toImmutableMap)21 Objects.requireNonNull (java.util.Objects.requireNonNull)21 Set (java.util.Set)21 Capture (io.trino.matching.Capture)20 Capture.newCapture (io.trino.matching.Capture.newCapture)20 TypeAnalyzer (io.trino.sql.planner.TypeAnalyzer)19 Patterns.source (io.trino.sql.planner.plan.Patterns.source)19 SubscriptExpression (io.trino.sql.tree.SubscriptExpression)18 ImmutableMap (com.google.common.collect.ImmutableMap)17