Search in sources :

Example 1 with SubscriptExpression

use of io.trino.sql.tree.SubscriptExpression in project trino by trinodb.

the class InlineProjections method extractInliningTargets.

private static Set<Symbol> extractInliningTargets(PlannerContext plannerContext, ProjectNode parent, ProjectNode child, Session session, TypeAnalyzer typeAnalyzer, TypeProvider types) {
    // candidates for inlining are
    // 1. references to simple constants or symbol references
    // 2. references to complex expressions that
    // a. are not inputs to try() expressions
    // b. appear only once across all expressions
    // c. are not identity projections
    // which come from the child, as opposed to an enclosing scope.
    Set<Symbol> childOutputSet = ImmutableSet.copyOf(child.getOutputSymbols());
    Map<Symbol, Long> dependencies = parent.getAssignments().getExpressions().stream().flatMap(expression -> SymbolsExtractor.extractAll(expression).stream()).filter(childOutputSet::contains).collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
    // find references to simple constants or symbol references
    Set<Symbol> basicReferences = dependencies.keySet().stream().filter(input -> isEffectivelyLiteral(plannerContext, session, child.getAssignments().get(input)) || child.getAssignments().get(input) instanceof SymbolReference).filter(// skip identities, otherwise, this rule will keep firing forever
    input -> !child.getAssignments().isIdentity(input)).collect(toSet());
    // exclude any complex inputs to TRY expressions. Inlining them would potentially
    // change the semantics of those expressions
    Set<Symbol> tryArguments = parent.getAssignments().getExpressions().stream().flatMap(expression -> extractTryArguments(expression).stream()).collect(toSet());
    Set<Symbol> singletons = dependencies.entrySet().stream().filter(// reference appears just once across all expressions in parent project node
    entry -> entry.getValue() == 1).filter(// they are not inputs to TRY. Otherwise, inlining might change semantics
    entry -> !tryArguments.contains(entry.getKey())).filter(// skip identities, otherwise, this rule will keep firing forever
    entry -> !child.getAssignments().isIdentity(entry.getKey())).filter(entry -> {
        // skip dereferences, otherwise, inlining can cause conflicts with PushdownDereferences
        Expression assignment = child.getAssignments().get(entry.getKey());
        if (assignment instanceof SubscriptExpression) {
            if (typeAnalyzer.getType(session, types, ((SubscriptExpression) assignment).getBase()) instanceof RowType) {
                return false;
            }
        }
        return true;
    }).map(Map.Entry::getKey).collect(toSet());
    return Sets.union(singletons, basicReferences);
}
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) SubscriptExpression(io.trino.sql.tree.SubscriptExpression) TryExpression(io.trino.sql.tree.TryExpression) Expression(io.trino.sql.tree.Expression) Symbol(io.trino.sql.planner.Symbol) SymbolReference(io.trino.sql.tree.SymbolReference) SubscriptExpression(io.trino.sql.tree.SubscriptExpression) RowType(io.trino.spi.type.RowType) Map(java.util.Map)

Example 2 with SubscriptExpression

use of io.trino.sql.tree.SubscriptExpression in project trino by trinodb.

the class PushDownDereferencesThroughWindow method apply.

@Override
public Result apply(ProjectNode projectNode, Captures captures, Context context) {
    WindowNode windowNode = captures.get(CHILD);
    // Extract dereferences for pushdown
    Set<SubscriptExpression> dereferences = extractRowSubscripts(ImmutableList.<Expression>builder().addAll(projectNode.getAssignments().getExpressions()).addAll(windowNode.getWindowFunctions().values().stream().flatMap(function -> function.getArguments().stream()).collect(toImmutableList())).build(), false, context.getSession(), typeAnalyzer, context.getSymbolAllocator().getTypes());
    WindowNode.Specification specification = windowNode.getSpecification();
    dereferences = dereferences.stream().filter(expression -> {
        Symbol symbol = getBase(expression);
        // Exclude partitionBy, orderBy and synthesized symbols
        return !specification.getPartitionBy().contains(symbol) && !specification.getOrderingScheme().map(OrderingScheme::getOrderBy).orElse(ImmutableList.of()).contains(symbol) && !windowNode.getCreatedSymbols().contains(symbol);
    }).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 newAssignments = projectNode.getAssignments().rewrite(expression -> replaceExpression(expression, mappings));
    return Result.ofPlanNode(new ProjectNode(context.getIdAllocator().getNextId(), new WindowNode(windowNode.getId(), new ProjectNode(context.getIdAllocator().getNextId(), windowNode.getSource(), Assignments.builder().putIdentities(windowNode.getSource().getOutputSymbols()).putAll(dereferenceAssignments).build()), windowNode.getSpecification(), // Replace dereference expressions in functions
    windowNode.getWindowFunctions().entrySet().stream().collect(toImmutableMap(Map.Entry::getKey, entry -> {
        WindowNode.Function oldFunction = entry.getValue();
        return new WindowNode.Function(oldFunction.getResolvedFunction(), oldFunction.getArguments().stream().map(expression -> replaceExpression(expression, mappings)).collect(toImmutableList()), oldFunction.getFrame(), oldFunction.isIgnoreNulls());
    })), windowNode.getHashSymbol(), windowNode.getPrePartitionedInputs(), windowNode.getPreSortedOrderPrefix()), newAssignments));
}
Also used : Capture.newCapture(io.trino.matching.Capture.newCapture) DereferencePushdown.getBase(io.trino.sql.planner.iterative.rule.DereferencePushdown.getBase) 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) Symbol(io.trino.sql.planner.Symbol) ImmutableList.toImmutableList(com.google.common.collect.ImmutableList.toImmutableList) Assignments(io.trino.sql.planner.plan.Assignments) Set(java.util.Set) OrderingScheme(io.trino.sql.planner.OrderingScheme) 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.window(io.trino.sql.planner.plan.Patterns.window) 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) WindowNode(io.trino.sql.planner.plan.WindowNode) WindowNode(io.trino.sql.planner.plan.WindowNode) Symbol(io.trino.sql.planner.Symbol) SymbolReference(io.trino.sql.tree.SymbolReference) Assignments(io.trino.sql.planner.plan.Assignments) SubscriptExpression(io.trino.sql.tree.SubscriptExpression) ExpressionNodeInliner.replaceExpression(io.trino.sql.planner.ExpressionNodeInliner.replaceExpression) Expression(io.trino.sql.tree.Expression) 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)

Example 3 with SubscriptExpression

use of io.trino.sql.tree.SubscriptExpression in project trino by trinodb.

the class PushDownDereferencesThroughAssignUniqueId method apply.

@Override
public Result apply(ProjectNode projectNode, Captures captures, Context context) {
    AssignUniqueId assignUniqueId = 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());
    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 newAssignments = projectNode.getAssignments().rewrite(expression -> replaceExpression(expression, mappings));
    return Result.ofPlanNode(new ProjectNode(context.getIdAllocator().getNextId(), assignUniqueId.replaceChildren(ImmutableList.of(new ProjectNode(context.getIdAllocator().getNextId(), assignUniqueId.getSource(), Assignments.builder().putIdentities(assignUniqueId.getSource().getOutputSymbols()).putAll(dereferenceAssignments).build()))), newAssignments));
}
Also used : Patterns.assignUniqueId(io.trino.sql.planner.plan.Patterns.assignUniqueId) Assignments(io.trino.sql.planner.plan.Assignments) Set(java.util.Set) Capture.newCapture(io.trino.matching.Capture.newCapture) Capture(io.trino.matching.Capture) 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) ImmutableList(com.google.common.collect.ImmutableList) 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) 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) AssignUniqueId(io.trino.sql.planner.plan.AssignUniqueId) ProjectNode(io.trino.sql.planner.plan.ProjectNode) AssignUniqueId(io.trino.sql.planner.plan.AssignUniqueId) 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 4 with SubscriptExpression

use of io.trino.sql.tree.SubscriptExpression in project trino by trinodb.

the class PushDownDereferencesThroughSort method apply.

@Override
public Result apply(ProjectNode projectNode, Captures captures, Context context) {
    SortNode sortNode = 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());
    // Exclude dereferences on symbols used in ordering scheme to avoid replication of data
    dereferences = dereferences.stream().filter(expression -> !sortNode.getOrderingScheme().getOrderBy().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 newAssignments = projectNode.getAssignments().rewrite(expression -> replaceExpression(expression, mappings));
    return Result.ofPlanNode(new ProjectNode(context.getIdAllocator().getNextId(), sortNode.replaceChildren(ImmutableList.of(new ProjectNode(context.getIdAllocator().getNextId(), sortNode.getSource(), Assignments.builder().putIdentities(sortNode.getSource().getOutputSymbols()).putAll(dereferenceAssignments).build()))), newAssignments));
}
Also used : Patterns.sort(io.trino.sql.planner.plan.Patterns.sort) SortNode(io.trino.sql.planner.plan.SortNode) Capture.newCapture(io.trino.matching.Capture.newCapture) DereferencePushdown.getBase(io.trino.sql.planner.iterative.rule.DereferencePushdown.getBase) 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) 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) SortNode(io.trino.sql.planner.plan.SortNode) 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)

Example 5 with SubscriptExpression

use of io.trino.sql.tree.SubscriptExpression in project trino by trinodb.

the class PushDownDereferenceThroughFilter method apply.

@Override
public Result apply(ProjectNode node, Captures captures, Rule.Context context) {
    FilterNode filterNode = captures.get(CHILD);
    // Pushdown superset of dereference expressions from projections and filtering predicate
    List<Expression> expressions = ImmutableList.<Expression>builder().addAll(node.getAssignments().getExpressions()).add(filterNode.getPredicate()).build();
    // Extract dereferences from project node assignments for pushdown
    Set<SubscriptExpression> dereferences = extractRowSubscripts(expressions, false, context.getSession(), typeAnalyzer, context.getSymbolAllocator().getTypes());
    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));
    PlanNode source = filterNode.getSource();
    return Result.ofPlanNode(new ProjectNode(context.getIdAllocator().getNextId(), new FilterNode(context.getIdAllocator().getNextId(), new ProjectNode(context.getIdAllocator().getNextId(), source, Assignments.builder().putIdentities(source.getOutputSymbols()).putAll(dereferenceAssignments).build()), replaceExpression(filterNode.getPredicate(), mappings)), assignments));
}
Also used : Patterns.filter(io.trino.sql.planner.plan.Patterns.filter) Capture.newCapture(io.trino.matching.Capture.newCapture) FilterNode(io.trino.sql.planner.plan.FilterNode) 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) 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) Capture(io.trino.matching.Capture) DereferencePushdown.extractRowSubscripts(io.trino.sql.planner.iterative.rule.DereferencePushdown.extractRowSubscripts) HashBiMap(com.google.common.collect.HashBiMap) List(java.util.List) 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) FilterNode(io.trino.sql.planner.plan.FilterNode) 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)

Aggregations

SubscriptExpression (io.trino.sql.tree.SubscriptExpression)28 Expression (io.trino.sql.tree.Expression)23 SymbolReference (io.trino.sql.tree.SymbolReference)22 Assignments (io.trino.sql.planner.plan.Assignments)20 ImmutableList (com.google.common.collect.ImmutableList)19 Map (java.util.Map)17 TypeAnalyzer (io.trino.sql.planner.TypeAnalyzer)16 Objects.requireNonNull (java.util.Objects.requireNonNull)16 Set (java.util.Set)16 ImmutableMap.toImmutableMap (com.google.common.collect.ImmutableMap.toImmutableMap)15 Capture (io.trino.matching.Capture)15 Capture.newCapture (io.trino.matching.Capture.newCapture)15 Captures (io.trino.matching.Captures)15 Pattern (io.trino.matching.Pattern)15 Rule (io.trino.sql.planner.iterative.Rule)15 Patterns.source (io.trino.sql.planner.plan.Patterns.source)15 ProjectNode (io.trino.sql.planner.plan.ProjectNode)15 HashBiMap (com.google.common.collect.HashBiMap)14 ExpressionNodeInliner.replaceExpression (io.trino.sql.planner.ExpressionNodeInliner.replaceExpression)14 DereferencePushdown.extractRowSubscripts (io.trino.sql.planner.iterative.rule.DereferencePushdown.extractRowSubscripts)14