Search in sources :

Example 16 with TypeAnalyzer

use of io.trino.sql.planner.TypeAnalyzer in project trino by trinodb.

the class InlineProjections method inlineProjections.

static Optional<ProjectNode> inlineProjections(PlannerContext plannerContext, ProjectNode parent, ProjectNode child, Session session, TypeAnalyzer typeAnalyzer, TypeProvider types) {
    // squash identity projections
    if (parent.isIdentity() && child.isIdentity()) {
        return Optional.of((ProjectNode) parent.replaceChildren(ImmutableList.of(child.getSource())));
    }
    Set<Symbol> targets = extractInliningTargets(plannerContext, parent, child, session, typeAnalyzer, types);
    if (targets.isEmpty()) {
        return Optional.empty();
    }
    // inline the expressions
    Assignments assignments = child.getAssignments().filter(targets::contains);
    Map<Symbol, Expression> parentAssignments = parent.getAssignments().entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, entry -> inlineReferences(entry.getValue(), assignments)));
    // Synthesize identity assignments for the inputs of expressions that were inlined
    // to place in the child projection.
    Set<Symbol> inputs = child.getAssignments().entrySet().stream().filter(entry -> targets.contains(entry.getKey())).map(Map.Entry::getValue).flatMap(entry -> SymbolsExtractor.extractAll(entry).stream()).collect(toSet());
    Assignments.Builder newChildAssignmentsBuilder = Assignments.builder();
    for (Map.Entry<Symbol, Expression> assignment : child.getAssignments().entrySet()) {
        if (!targets.contains(assignment.getKey())) {
            newChildAssignmentsBuilder.put(assignment);
        }
    }
    for (Symbol input : inputs) {
        newChildAssignmentsBuilder.putIdentity(input);
    }
    Assignments newChildAssignments = newChildAssignmentsBuilder.build();
    PlanNode newChild;
    if (newChildAssignments.isIdentity()) {
        newChild = child.getSource();
    } else {
        newChild = new ProjectNode(child.getId(), child.getSource(), newChildAssignments);
    }
    return Optional.of(new ProjectNode(parent.getId(), newChild, Assignments.copyOf(parentAssignments)));
}
Also used : Function(java.util.function.Function) Capture.newCapture(io.trino.matching.Capture.newCapture) PlanNode(io.trino.sql.planner.plan.PlanNode) SubscriptExpression(io.trino.sql.tree.SubscriptExpression) ExpressionSymbolInliner.inlineSymbols(io.trino.sql.planner.ExpressionSymbolInliner.inlineSymbols) ImmutableList(com.google.common.collect.ImmutableList) Map(java.util.Map) Objects.requireNonNull(java.util.Objects.requireNonNull) Rule(io.trino.sql.planner.iterative.Rule) SymbolsExtractor(io.trino.sql.planner.SymbolsExtractor) TryExpression(io.trino.sql.tree.TryExpression) ProjectNode(io.trino.sql.planner.plan.ProjectNode) Collectors.toSet(java.util.stream.Collectors.toSet) Symbol(io.trino.sql.planner.Symbol) RowType(io.trino.spi.type.RowType) ImmutableSet(com.google.common.collect.ImmutableSet) Assignments(io.trino.sql.planner.plan.Assignments) Set(java.util.Set) Collectors(java.util.stream.Collectors) Sets(com.google.common.collect.Sets) Capture(io.trino.matching.Capture) ExpressionUtils.isEffectivelyLiteral(io.trino.sql.ExpressionUtils.isEffectivelyLiteral) Pattern(io.trino.matching.Pattern) TypeAnalyzer(io.trino.sql.planner.TypeAnalyzer) AstUtils(io.trino.sql.util.AstUtils) Patterns.source(io.trino.sql.planner.plan.Patterns.source) SymbolReference(io.trino.sql.tree.SymbolReference) Captures(io.trino.matching.Captures) TypeProvider(io.trino.sql.planner.TypeProvider) Optional(java.util.Optional) Expression(io.trino.sql.tree.Expression) Patterns.project(io.trino.sql.planner.plan.Patterns.project) Session(io.trino.Session) PlannerContext(io.trino.sql.PlannerContext) Symbol(io.trino.sql.planner.Symbol) Assignments(io.trino.sql.planner.plan.Assignments) PlanNode(io.trino.sql.planner.plan.PlanNode) SubscriptExpression(io.trino.sql.tree.SubscriptExpression) TryExpression(io.trino.sql.tree.TryExpression) Expression(io.trino.sql.tree.Expression) ProjectNode(io.trino.sql.planner.plan.ProjectNode) Map(java.util.Map)

Example 17 with TypeAnalyzer

use of io.trino.sql.planner.TypeAnalyzer in project trino by trinodb.

the class PropertyDerivations method deriveProperties.

public static ActualProperties deriveProperties(PlanNode node, List<ActualProperties> inputProperties, PlannerContext plannerContext, Session session, TypeProvider types, TypeAnalyzer typeAnalyzer) {
    ActualProperties output = node.accept(new Visitor(plannerContext, session, types, typeAnalyzer), inputProperties);
    output.getNodePartitioning().ifPresent(partitioning -> verify(node.getOutputSymbols().containsAll(partitioning.getColumns()), "Node-level partitioning properties contain columns not present in node's output"));
    verify(node.getOutputSymbols().containsAll(output.getConstants().keySet()), "Node-level constant properties contain columns not present in node's output");
    Set<Symbol> localPropertyColumns = output.getLocalProperties().stream().flatMap(property -> property.getColumns().stream()).collect(Collectors.toSet());
    verify(node.getOutputSymbols().containsAll(localPropertyColumns), "Node-level local properties contain columns not present in node's output");
    return output;
}
Also used : GroupingProperty(io.trino.spi.connector.GroupingProperty) ARBITRARY_DISTRIBUTION(io.trino.sql.planner.SystemPartitioningHandle.ARBITRARY_DISTRIBUTION) IndexSourceNode(io.trino.sql.planner.plan.IndexSourceNode) TableWriterNode(io.trino.sql.planner.plan.TableWriterNode) CorrelatedJoinNode(io.trino.sql.planner.plan.CorrelatedJoinNode) FilterNode(io.trino.sql.planner.plan.FilterNode) PlanNode(io.trino.sql.planner.plan.PlanNode) Preconditions.checkArgument(com.google.common.base.Preconditions.checkArgument) TableDeleteNode(io.trino.sql.planner.plan.TableDeleteNode) ONE(io.trino.sql.tree.PatternRecognitionRelation.RowsPerMatch.ONE) Collectors.toMap(java.util.stream.Collectors.toMap) Map(java.util.Map) LOCAL(io.trino.sql.planner.plan.ExchangeNode.Scope.LOCAL) SpatialJoinNode(io.trino.sql.planner.plan.SpatialJoinNode) OutputNode(io.trino.sql.planner.plan.OutputNode) DeleteNode(io.trino.sql.planner.plan.DeleteNode) WINDOW(io.trino.sql.tree.PatternRecognitionRelation.RowsPerMatch.WINDOW) JoinNode(io.trino.sql.planner.plan.JoinNode) AssignUniqueId(io.trino.sql.planner.plan.AssignUniqueId) TableScanNode(io.trino.sql.planner.plan.TableScanNode) TupleDomain.extractFixedValues(io.trino.spi.predicate.TupleDomain.extractFixedValues) ExplainAnalyzeNode(io.trino.sql.planner.plan.ExplainAnalyzeNode) MarkDistinctNode(io.trino.sql.planner.plan.MarkDistinctNode) Global.partitionedOn(io.trino.sql.planner.optimizations.ActualProperties.Global.partitionedOn) ImmutableSet(com.google.common.collect.ImmutableSet) ImmutableMap(com.google.common.collect.ImmutableMap) EnforceSingleRowNode(io.trino.sql.planner.plan.EnforceSingleRowNode) StatisticsWriterNode(io.trino.sql.planner.plan.StatisticsWriterNode) Collection(java.util.Collection) ImmutableList.toImmutableList(com.google.common.collect.ImmutableList.toImmutableList) ExpressionInterpreter(io.trino.sql.planner.ExpressionInterpreter) IndexJoinNode(io.trino.sql.planner.plan.IndexJoinNode) Set(java.util.Set) PAST_LAST(io.trino.sql.tree.SkipTo.Position.PAST_LAST) SemiJoinNode(io.trino.sql.planner.plan.SemiJoinNode) PatternRecognitionNode(io.trino.sql.planner.plan.PatternRecognitionNode) Collectors(java.util.stream.Collectors) Sets(com.google.common.collect.Sets) Preconditions.checkState(com.google.common.base.Preconditions.checkState) CoalesceExpression(io.trino.sql.tree.CoalesceExpression) List(java.util.List) GATHER(io.trino.sql.planner.plan.ExchangeNode.Type.GATHER) SymbolReference(io.trino.sql.tree.SymbolReference) FIXED_PASSTHROUGH_DISTRIBUTION(io.trino.sql.planner.SystemPartitioningHandle.FIXED_PASSTHROUGH_DISTRIBUTION) ApplyNode(io.trino.sql.planner.plan.ApplyNode) TopNRankingNode(io.trino.sql.planner.plan.TopNRankingNode) Optional(java.util.Optional) Global.arbitraryPartition(io.trino.sql.planner.optimizations.ActualProperties.Global.arbitraryPartition) ExchangeNode(io.trino.sql.planner.plan.ExchangeNode) Expression(io.trino.sql.tree.Expression) ValuesNode(io.trino.sql.planner.plan.ValuesNode) WindowNode(io.trino.sql.planner.plan.WindowNode) Session(io.trino.Session) PlannerContext(io.trino.sql.PlannerContext) TableExecuteNode(io.trino.sql.planner.plan.TableExecuteNode) Iterables(com.google.common.collect.Iterables) ConstantProperty(io.trino.spi.connector.ConstantProperty) Global(io.trino.sql.planner.optimizations.ActualProperties.Global) NullableValue(io.trino.spi.predicate.NullableValue) LimitNode(io.trino.sql.planner.plan.LimitNode) Type(io.trino.spi.type.Type) NoOpSymbolResolver(io.trino.sql.planner.NoOpSymbolResolver) Global.singleStreamPartition(io.trino.sql.planner.optimizations.ActualProperties.Global.singleStreamPartition) HashMap(java.util.HashMap) TableProperties(io.trino.metadata.TableProperties) SortNode(io.trino.sql.planner.plan.SortNode) ImmutableBiMap(com.google.common.collect.ImmutableBiMap) ImmutableList(com.google.common.collect.ImmutableList) RowNumberNode(io.trino.sql.planner.plan.RowNumberNode) Verify.verify(com.google.common.base.Verify.verify) NodeRef(io.trino.sql.tree.NodeRef) Objects.requireNonNull(java.util.Objects.requireNonNull) SystemSessionProperties(io.trino.SystemSessionProperties) RefreshMaterializedViewNode(io.trino.sql.planner.plan.RefreshMaterializedViewNode) ColumnHandle(io.trino.spi.connector.ColumnHandle) AggregationNode(io.trino.sql.planner.plan.AggregationNode) ImmutableSet.toImmutableSet(com.google.common.collect.ImmutableSet.toImmutableSet) ProjectNode(io.trino.sql.planner.plan.ProjectNode) DomainTranslator(io.trino.sql.planner.DomainTranslator) TablePartitioning(io.trino.metadata.TableProperties.TablePartitioning) Symbol(io.trino.sql.planner.Symbol) Global.coordinatorSingleStreamPartition(io.trino.sql.planner.optimizations.ActualProperties.Global.coordinatorSingleStreamPartition) PlanVisitor(io.trino.sql.planner.plan.PlanVisitor) TopNNode(io.trino.sql.planner.plan.TopNNode) OrderingScheme(io.trino.sql.planner.OrderingScheme) UnnestNode(io.trino.sql.planner.plan.UnnestNode) UpdateNode(io.trino.sql.planner.plan.UpdateNode) Global.streamPartitionedOn(io.trino.sql.planner.optimizations.ActualProperties.Global.streamPartitionedOn) LocalProperty(io.trino.spi.connector.LocalProperty) TypeAnalyzer(io.trino.sql.planner.TypeAnalyzer) REMOTE(io.trino.sql.planner.plan.ExchangeNode.Scope.REMOTE) GroupIdNode(io.trino.sql.planner.plan.GroupIdNode) DistinctLimitNode(io.trino.sql.planner.plan.DistinctLimitNode) TypeProvider(io.trino.sql.planner.TypeProvider) TableFinishNode(io.trino.sql.planner.plan.TableFinishNode) SampleNode(io.trino.sql.planner.plan.SampleNode) PlanVisitor(io.trino.sql.planner.plan.PlanVisitor) Symbol(io.trino.sql.planner.Symbol)

Example 18 with TypeAnalyzer

use of io.trino.sql.planner.TypeAnalyzer in project trino by trinodb.

the class PushProjectionIntoTableScan method apply.

@Override
public Result apply(ProjectNode project, Captures captures, Context context) {
    TableScanNode tableScan = captures.get(TABLE_SCAN);
    // Extract translatable components from projection expressions. Prepare a mapping from these internal
    // expression nodes to corresponding ConnectorExpression translations.
    Map<NodeRef<Expression>, ConnectorExpression> partialTranslations = project.getAssignments().getMap().entrySet().stream().flatMap(expression -> extractPartialTranslations(expression.getValue(), context.getSession(), typeAnalyzer, context.getSymbolAllocator().getTypes(), plannerContext).entrySet().stream()).collect(toImmutableMap(Map.Entry::getKey, Map.Entry::getValue, (first, ignore) -> first));
    List<NodeRef<Expression>> nodesForPartialProjections = ImmutableList.copyOf(partialTranslations.keySet());
    List<ConnectorExpression> connectorPartialProjections = ImmutableList.copyOf(partialTranslations.values());
    Map<String, Symbol> inputVariableMappings = tableScan.getAssignments().keySet().stream().collect(toImmutableMap(Symbol::getName, identity()));
    Map<String, ColumnHandle> assignments = inputVariableMappings.entrySet().stream().collect(toImmutableMap(Entry::getKey, entry -> tableScan.getAssignments().get(entry.getValue())));
    Optional<ProjectionApplicationResult<TableHandle>> result = plannerContext.getMetadata().applyProjection(context.getSession(), tableScan.getTable(), connectorPartialProjections, assignments);
    if (result.isEmpty()) {
        return Result.empty();
    }
    List<ConnectorExpression> newConnectorPartialProjections = result.get().getProjections();
    checkState(newConnectorPartialProjections.size() == connectorPartialProjections.size(), "Mismatch between input and output projections from the connector: expected %s but got %s", connectorPartialProjections.size(), newConnectorPartialProjections.size());
    List<Symbol> newScanOutputs = new ArrayList<>();
    Map<Symbol, ColumnHandle> newScanAssignments = new HashMap<>();
    Map<String, Symbol> variableMappings = new HashMap<>();
    for (Assignment assignment : result.get().getAssignments()) {
        Symbol symbol = context.getSymbolAllocator().newSymbol(assignment.getVariable(), assignment.getType());
        newScanOutputs.add(symbol);
        newScanAssignments.put(symbol, assignment.getColumn());
        variableMappings.put(assignment.getVariable(), symbol);
    }
    // Translate partial connector projections back to new partial projections
    List<Expression> newPartialProjections = newConnectorPartialProjections.stream().map(expression -> ConnectorExpressionTranslator.translate(context.getSession(), expression, plannerContext, variableMappings, new LiteralEncoder(plannerContext))).collect(toImmutableList());
    // Map internal node references to new partial projections
    ImmutableMap.Builder<NodeRef<Expression>, Expression> nodesToNewPartialProjectionsBuilder = ImmutableMap.builder();
    for (int i = 0; i < nodesForPartialProjections.size(); i++) {
        nodesToNewPartialProjectionsBuilder.put(nodesForPartialProjections.get(i), newPartialProjections.get(i));
    }
    Map<NodeRef<Expression>, Expression> nodesToNewPartialProjections = nodesToNewPartialProjectionsBuilder.buildOrThrow();
    // Stitch partial translations to form new complete projections
    Assignments.Builder newProjectionAssignments = Assignments.builder();
    project.getAssignments().entrySet().forEach(entry -> {
        newProjectionAssignments.put(entry.getKey(), replaceExpression(entry.getValue(), nodesToNewPartialProjections));
    });
    Optional<PlanNodeStatsEstimate> newStatistics = tableScan.getStatistics().map(statistics -> {
        PlanNodeStatsEstimate.Builder builder = PlanNodeStatsEstimate.builder();
        builder.setOutputRowCount(statistics.getOutputRowCount());
        for (int i = 0; i < connectorPartialProjections.size(); i++) {
            ConnectorExpression inputConnectorExpression = connectorPartialProjections.get(i);
            ConnectorExpression resultConnectorExpression = newConnectorPartialProjections.get(i);
            if (!(resultConnectorExpression instanceof Variable)) {
                continue;
            }
            String resultVariableName = ((Variable) resultConnectorExpression).getName();
            Expression inputExpression = ConnectorExpressionTranslator.translate(context.getSession(), inputConnectorExpression, plannerContext, inputVariableMappings, new LiteralEncoder(plannerContext));
            SymbolStatsEstimate symbolStatistics = scalarStatsCalculator.calculate(inputExpression, statistics, context.getSession(), context.getSymbolAllocator().getTypes());
            builder.addSymbolStatistics(variableMappings.get(resultVariableName), symbolStatistics);
        }
        return builder.build();
    });
    verifyTablePartitioning(context, tableScan, result.get().getHandle());
    return Result.ofPlanNode(new ProjectNode(context.getIdAllocator().getNextId(), new TableScanNode(tableScan.getId(), result.get().getHandle(), newScanOutputs, newScanAssignments, TupleDomain.all(), newStatistics, tableScan.isUpdateTarget(), tableScan.getUseConnectorNodePartitioning()), newProjectionAssignments.build()));
}
Also used : LiteralEncoder(io.trino.sql.planner.LiteralEncoder) HashMap(java.util.HashMap) Variable(io.trino.spi.expression.Variable) Capture.newCapture(io.trino.matching.Capture.newCapture) ArrayList(java.util.ArrayList) ImmutableList(com.google.common.collect.ImmutableList) Verify.verify(com.google.common.base.Verify.verify) NodeRef(io.trino.sql.tree.NodeRef) Map(java.util.Map) Objects.requireNonNull(java.util.Objects.requireNonNull) ColumnHandle(io.trino.spi.connector.ColumnHandle) ProjectionApplicationResult(io.trino.spi.connector.ProjectionApplicationResult) Rule(io.trino.sql.planner.iterative.Rule) ReferenceAwareExpressionNodeInliner.replaceExpression(io.trino.sql.planner.ReferenceAwareExpressionNodeInliner.replaceExpression) ProjectNode(io.trino.sql.planner.plan.ProjectNode) TableScanNode(io.trino.sql.planner.plan.TableScanNode) PlanNodeStatsEstimate(io.trino.cost.PlanNodeStatsEstimate) TablePartitioning(io.trino.metadata.TableProperties.TablePartitioning) Symbol(io.trino.sql.planner.Symbol) SymbolStatsEstimate(io.trino.cost.SymbolStatsEstimate) ImmutableMap(com.google.common.collect.ImmutableMap) ImmutableList.toImmutableList(com.google.common.collect.ImmutableList.toImmutableList) PartialTranslator.extractPartialTranslations(io.trino.sql.planner.PartialTranslator.extractPartialTranslations) ConnectorExpressionTranslator(io.trino.sql.planner.ConnectorExpressionTranslator) Assignments(io.trino.sql.planner.plan.Assignments) TupleDomain(io.trino.spi.predicate.TupleDomain) Patterns.tableScan(io.trino.sql.planner.plan.Patterns.tableScan) ScalarStatsCalculator(io.trino.cost.ScalarStatsCalculator) Capture(io.trino.matching.Capture) Preconditions.checkState(com.google.common.base.Preconditions.checkState) List(java.util.List) ImmutableMap.toImmutableMap(com.google.common.collect.ImmutableMap.toImmutableMap) Pattern(io.trino.matching.Pattern) TableHandle(io.trino.metadata.TableHandle) ConnectorExpression(io.trino.spi.expression.ConnectorExpression) TypeAnalyzer(io.trino.sql.planner.TypeAnalyzer) SystemSessionProperties.isAllowPushdownIntoConnectors(io.trino.SystemSessionProperties.isAllowPushdownIntoConnectors) Patterns.source(io.trino.sql.planner.plan.Patterns.source) Captures(io.trino.matching.Captures) Assignment(io.trino.spi.connector.Assignment) Entry(java.util.Map.Entry) Function.identity(java.util.function.Function.identity) Optional(java.util.Optional) Expression(io.trino.sql.tree.Expression) Patterns.project(io.trino.sql.planner.plan.Patterns.project) Session(io.trino.Session) PlannerContext(io.trino.sql.PlannerContext) Variable(io.trino.spi.expression.Variable) HashMap(java.util.HashMap) PlanNodeStatsEstimate(io.trino.cost.PlanNodeStatsEstimate) ConnectorExpression(io.trino.spi.expression.ConnectorExpression) Symbol(io.trino.sql.planner.Symbol) ArrayList(java.util.ArrayList) Assignments(io.trino.sql.planner.plan.Assignments) SymbolStatsEstimate(io.trino.cost.SymbolStatsEstimate) Assignment(io.trino.spi.connector.Assignment) NodeRef(io.trino.sql.tree.NodeRef) LiteralEncoder(io.trino.sql.planner.LiteralEncoder) ColumnHandle(io.trino.spi.connector.ColumnHandle) ProjectionApplicationResult(io.trino.spi.connector.ProjectionApplicationResult) ImmutableMap(com.google.common.collect.ImmutableMap) ImmutableMap.toImmutableMap(com.google.common.collect.ImmutableMap.toImmutableMap) TableScanNode(io.trino.sql.planner.plan.TableScanNode) ReferenceAwareExpressionNodeInliner.replaceExpression(io.trino.sql.planner.ReferenceAwareExpressionNodeInliner.replaceExpression) ConnectorExpression(io.trino.spi.expression.ConnectorExpression) Expression(io.trino.sql.tree.Expression) ProjectNode(io.trino.sql.planner.plan.ProjectNode) HashMap(java.util.HashMap) Map(java.util.Map) ImmutableMap(com.google.common.collect.ImmutableMap) ImmutableMap.toImmutableMap(com.google.common.collect.ImmutableMap.toImmutableMap)

Example 19 with TypeAnalyzer

use of io.trino.sql.planner.TypeAnalyzer in project trino by trinodb.

the class PushDownDereferenceThroughProject method apply.

@Override
public Result apply(ProjectNode node, Captures captures, Context context) {
    ProjectNode child = captures.get(CHILD);
    // Extract dereferences from project node assignments for pushdown
    Set<SubscriptExpression> dereferences = extractRowSubscripts(node.getAssignments().getExpressions(), false, context.getSession(), typeAnalyzer, context.getSymbolAllocator().getTypes());
    // Exclude dereferences on symbols being synthesized within child
    dereferences = dereferences.stream().filter(expression -> child.getSource().getOutputSymbols().contains(getBase(expression))).collect(toImmutableSet());
    if (dereferences.isEmpty()) {
        return Result.empty();
    }
    // Create new symbols for dereference expressions
    Assignments dereferenceAssignments = Assignments.of(dereferences, context.getSession(), context.getSymbolAllocator(), typeAnalyzer);
    // Rewrite project node assignments using new symbols for dereference expressions
    Map<Expression, SymbolReference> mappings = HashBiMap.create(dereferenceAssignments.getMap()).inverse().entrySet().stream().collect(toImmutableMap(Map.Entry::getKey, entry -> entry.getValue().toSymbolReference()));
    Assignments assignments = node.getAssignments().rewrite(expression -> replaceExpression(expression, mappings));
    return Result.ofPlanNode(new ProjectNode(context.getIdAllocator().getNextId(), new ProjectNode(context.getIdAllocator().getNextId(), child.getSource(), Assignments.builder().putAll(child.getAssignments()).putAll(dereferenceAssignments).build()), assignments));
}
Also used : Assignments(io.trino.sql.planner.plan.Assignments) Set(java.util.Set) Capture.newCapture(io.trino.matching.Capture.newCapture) Capture(io.trino.matching.Capture) DereferencePushdown.getBase(io.trino.sql.planner.iterative.rule.DereferencePushdown.getBase) SubscriptExpression(io.trino.sql.tree.SubscriptExpression) DereferencePushdown.extractRowSubscripts(io.trino.sql.planner.iterative.rule.DereferencePushdown.extractRowSubscripts) HashBiMap(com.google.common.collect.HashBiMap) ImmutableMap.toImmutableMap(com.google.common.collect.ImmutableMap.toImmutableMap) Pattern(io.trino.matching.Pattern) TypeAnalyzer(io.trino.sql.planner.TypeAnalyzer) Patterns.source(io.trino.sql.planner.plan.Patterns.source) SymbolReference(io.trino.sql.tree.SymbolReference) Captures(io.trino.matching.Captures) Map(java.util.Map) Objects.requireNonNull(java.util.Objects.requireNonNull) ImmutableSet.toImmutableSet(com.google.common.collect.ImmutableSet.toImmutableSet) ExpressionNodeInliner.replaceExpression(io.trino.sql.planner.ExpressionNodeInliner.replaceExpression) Rule(io.trino.sql.planner.iterative.Rule) Expression(io.trino.sql.tree.Expression) Patterns.project(io.trino.sql.planner.plan.Patterns.project) ProjectNode(io.trino.sql.planner.plan.ProjectNode) SubscriptExpression(io.trino.sql.tree.SubscriptExpression) ExpressionNodeInliner.replaceExpression(io.trino.sql.planner.ExpressionNodeInliner.replaceExpression) Expression(io.trino.sql.tree.Expression) SymbolReference(io.trino.sql.tree.SymbolReference) Assignments(io.trino.sql.planner.plan.Assignments) SubscriptExpression(io.trino.sql.tree.SubscriptExpression) ProjectNode(io.trino.sql.planner.plan.ProjectNode) HashBiMap(com.google.common.collect.HashBiMap) ImmutableMap.toImmutableMap(com.google.common.collect.ImmutableMap.toImmutableMap) Map(java.util.Map)

Example 20 with TypeAnalyzer

use of io.trino.sql.planner.TypeAnalyzer in project trino by trinodb.

the class PushDownDereferenceThroughSemiJoin method apply.

@Override
public Result apply(ProjectNode projectNode, Captures captures, Context context) {
    SemiJoinNode semiJoinNode = captures.get(CHILD);
    // Extract dereferences from project node assignments for pushdown
    Set<SubscriptExpression> dereferences = extractRowSubscripts(projectNode.getAssignments().getExpressions(), false, context.getSession(), typeAnalyzer, context.getSymbolAllocator().getTypes());
    // All dereferences can be assumed on the symbols coming from source, since filteringSource output is not propagated,
    // and semiJoinOutput is of type boolean. We exclude pushdown of dereferences on sourceJoinSymbol.
    dereferences = dereferences.stream().filter(expression -> !getBase(expression).equals(semiJoinNode.getSourceJoinSymbol())).collect(toImmutableSet());
    if (dereferences.isEmpty()) {
        return Result.empty();
    }
    // Create new symbols for dereference expressions
    Assignments dereferenceAssignments = Assignments.of(dereferences, context.getSession(), context.getSymbolAllocator(), typeAnalyzer);
    // Rewrite project node assignments using new symbols for dereference expressions
    Map<Expression, SymbolReference> mappings = HashBiMap.create(dereferenceAssignments.getMap()).inverse().entrySet().stream().collect(toImmutableMap(Map.Entry::getKey, entry -> entry.getValue().toSymbolReference()));
    Assignments assignments = projectNode.getAssignments().rewrite(expression -> replaceExpression(expression, mappings));
    PlanNode newSource = new ProjectNode(context.getIdAllocator().getNextId(), semiJoinNode.getSource(), Assignments.builder().putIdentities(semiJoinNode.getSource().getOutputSymbols()).putAll(dereferenceAssignments).build());
    PlanNode newSemiJoin = semiJoinNode.replaceChildren(ImmutableList.of(newSource, semiJoinNode.getFilteringSource()));
    return Result.ofPlanNode(new ProjectNode(context.getIdAllocator().getNextId(), newSemiJoin, assignments));
}
Also used : Capture.newCapture(io.trino.matching.Capture.newCapture) DereferencePushdown.getBase(io.trino.sql.planner.iterative.rule.DereferencePushdown.getBase) PlanNode(io.trino.sql.planner.plan.PlanNode) SubscriptExpression(io.trino.sql.tree.SubscriptExpression) ImmutableList(com.google.common.collect.ImmutableList) Map(java.util.Map) Objects.requireNonNull(java.util.Objects.requireNonNull) ImmutableSet.toImmutableSet(com.google.common.collect.ImmutableSet.toImmutableSet) Rule(io.trino.sql.planner.iterative.Rule) ProjectNode(io.trino.sql.planner.plan.ProjectNode) Assignments(io.trino.sql.planner.plan.Assignments) Set(java.util.Set) Patterns.semiJoin(io.trino.sql.planner.plan.Patterns.semiJoin) SemiJoinNode(io.trino.sql.planner.plan.SemiJoinNode) Capture(io.trino.matching.Capture) DereferencePushdown.extractRowSubscripts(io.trino.sql.planner.iterative.rule.DereferencePushdown.extractRowSubscripts) HashBiMap(com.google.common.collect.HashBiMap) ImmutableMap.toImmutableMap(com.google.common.collect.ImmutableMap.toImmutableMap) Pattern(io.trino.matching.Pattern) TypeAnalyzer(io.trino.sql.planner.TypeAnalyzer) Patterns.source(io.trino.sql.planner.plan.Patterns.source) SymbolReference(io.trino.sql.tree.SymbolReference) Captures(io.trino.matching.Captures) ExpressionNodeInliner.replaceExpression(io.trino.sql.planner.ExpressionNodeInliner.replaceExpression) Expression(io.trino.sql.tree.Expression) Patterns.project(io.trino.sql.planner.plan.Patterns.project) PlanNode(io.trino.sql.planner.plan.PlanNode) SubscriptExpression(io.trino.sql.tree.SubscriptExpression) ExpressionNodeInliner.replaceExpression(io.trino.sql.planner.ExpressionNodeInliner.replaceExpression) Expression(io.trino.sql.tree.Expression) SymbolReference(io.trino.sql.tree.SymbolReference) Assignments(io.trino.sql.planner.plan.Assignments) SubscriptExpression(io.trino.sql.tree.SubscriptExpression) ProjectNode(io.trino.sql.planner.plan.ProjectNode) Map(java.util.Map) HashBiMap(com.google.common.collect.HashBiMap) ImmutableMap.toImmutableMap(com.google.common.collect.ImmutableMap.toImmutableMap) SemiJoinNode(io.trino.sql.planner.plan.SemiJoinNode)

Aggregations

TypeAnalyzer (io.trino.sql.planner.TypeAnalyzer)30 Expression (io.trino.sql.tree.Expression)24 Map (java.util.Map)24 Assignments (io.trino.sql.planner.plan.Assignments)22 ProjectNode (io.trino.sql.planner.plan.ProjectNode)22 ImmutableList (com.google.common.collect.ImmutableList)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 Captures (io.trino.matching.Captures)20 Pattern (io.trino.matching.Pattern)20 Rule (io.trino.sql.planner.iterative.Rule)20 Patterns.source (io.trino.sql.planner.plan.Patterns.source)20 SymbolReference (io.trino.sql.tree.SymbolReference)20 ImmutableMap.toImmutableMap (com.google.common.collect.ImmutableMap.toImmutableMap)17 SubscriptExpression (io.trino.sql.tree.SubscriptExpression)17 ExpressionNodeInliner.replaceExpression (io.trino.sql.planner.ExpressionNodeInliner.replaceExpression)16 Patterns.project (io.trino.sql.planner.plan.Patterns.project)16 Symbol (io.trino.sql.planner.Symbol)15