Search in sources :

Example 6 with FilterNode

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

the class PushPredicateIntoTableScan method arePlansSame.

private boolean arePlansSame(FilterNode filter, TableScanNode tableScan, PlanNode rewritten) {
    if (!(rewritten instanceof FilterNode)) {
        return false;
    }
    FilterNode rewrittenFilter = (FilterNode) rewritten;
    if (!Objects.equals(filter.getPredicate(), rewrittenFilter.getPredicate())) {
        return false;
    }
    if (!(rewrittenFilter.getSource() instanceof TableScanNode)) {
        return false;
    }
    TableScanNode rewrittenTableScan = (TableScanNode) rewrittenFilter.getSource();
    return Objects.equals(tableScan.getEnforcedConstraint(), rewrittenTableScan.getEnforcedConstraint()) && Objects.equals(tableScan.getTable(), rewrittenTableScan.getTable());
}
Also used : TableScanNode(io.trino.sql.planner.plan.TableScanNode) FilterNode(io.trino.sql.planner.plan.FilterNode)

Example 7 with FilterNode

use of io.trino.sql.planner.plan.FilterNode 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)

Example 8 with FilterNode

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

the class SimplifyFilterPredicate method apply.

@Override
public Result apply(FilterNode node, Captures captures, Context context) {
    List<Expression> conjuncts = extractConjuncts(node.getPredicate());
    ImmutableList.Builder<Expression> newConjuncts = ImmutableList.builder();
    boolean simplified = false;
    for (Expression conjunct : conjuncts) {
        Optional<Expression> simplifiedConjunct = simplifyFilterExpression(conjunct);
        if (simplifiedConjunct.isPresent()) {
            simplified = true;
            newConjuncts.add(simplifiedConjunct.get());
        } else {
            newConjuncts.add(conjunct);
        }
    }
    if (!simplified) {
        return Result.empty();
    }
    return Result.ofPlanNode(new FilterNode(node.getId(), node.getSource(), combineConjuncts(metadata, newConjuncts.build())));
}
Also used : SimpleCaseExpression(io.trino.sql.tree.SimpleCaseExpression) NullIfExpression(io.trino.sql.tree.NullIfExpression) SearchedCaseExpression(io.trino.sql.tree.SearchedCaseExpression) NotExpression(io.trino.sql.tree.NotExpression) IfExpression(io.trino.sql.tree.IfExpression) LogicalExpression(io.trino.sql.tree.LogicalExpression) Expression(io.trino.sql.tree.Expression) ImmutableList(com.google.common.collect.ImmutableList) ImmutableList.toImmutableList(com.google.common.collect.ImmutableList.toImmutableList) FilterNode(io.trino.sql.planner.plan.FilterNode)

Example 9 with FilterNode

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

the class ReplaceRedundantJoinWithSource method apply.

@Override
public Result apply(JoinNode node, Captures captures, Context context) {
    if (isAtMost(node.getLeft(), context.getLookup(), 0) || isAtMost(node.getRight(), context.getLookup(), 0)) {
        return Result.empty();
    }
    boolean leftSourceScalarWithNoOutputs = node.getLeft().getOutputSymbols().isEmpty() && isScalar(node.getLeft(), context.getLookup());
    boolean rightSourceScalarWithNoOutputs = node.getRight().getOutputSymbols().isEmpty() && isScalar(node.getRight(), context.getLookup());
    switch(node.getType()) {
        case INNER:
            PlanNode source;
            List<Symbol> sourceOutputs;
            if (leftSourceScalarWithNoOutputs) {
                source = node.getRight();
                sourceOutputs = node.getRightOutputSymbols();
            } else if (rightSourceScalarWithNoOutputs) {
                source = node.getLeft();
                sourceOutputs = node.getLeftOutputSymbols();
            } else {
                return Result.empty();
            }
            if (node.getFilter().isPresent()) {
                source = new FilterNode(context.getIdAllocator().getNextId(), source, node.getFilter().get());
            }
            return Result.ofPlanNode(restrictOutputs(context.getIdAllocator(), source, ImmutableSet.copyOf(sourceOutputs)).orElse(source));
        case LEFT:
            if (rightSourceScalarWithNoOutputs) {
                return Result.ofPlanNode(restrictOutputs(context.getIdAllocator(), node.getLeft(), ImmutableSet.copyOf(node.getLeftOutputSymbols())).orElse(node.getLeft()));
            }
            break;
        case RIGHT:
            if (leftSourceScalarWithNoOutputs) {
                return Result.ofPlanNode(restrictOutputs(context.getIdAllocator(), node.getRight(), ImmutableSet.copyOf(node.getRightOutputSymbols())).orElse(node.getRight()));
            }
            break;
        case FULL:
            if (leftSourceScalarWithNoOutputs && isAtLeastScalar(node.getRight(), context.getLookup())) {
                return Result.ofPlanNode(restrictOutputs(context.getIdAllocator(), node.getRight(), ImmutableSet.copyOf(node.getRightOutputSymbols())).orElse(node.getRight()));
            }
            if (rightSourceScalarWithNoOutputs && isAtLeastScalar(node.getLeft(), context.getLookup())) {
                return Result.ofPlanNode(restrictOutputs(context.getIdAllocator(), node.getLeft(), ImmutableSet.copyOf(node.getLeftOutputSymbols())).orElse(node.getLeft()));
            }
    }
    return Result.empty();
}
Also used : PlanNode(io.trino.sql.planner.plan.PlanNode) Symbol(io.trino.sql.planner.Symbol) FilterNode(io.trino.sql.planner.plan.FilterNode)

Example 10 with FilterNode

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

the class TransformCorrelatedScalarSubquery method apply.

@Override
public Result apply(CorrelatedJoinNode correlatedJoinNode, Captures captures, Context context) {
    PlanNode subquery = context.getLookup().resolve(correlatedJoinNode.getSubquery());
    if (!searchFrom(subquery, context.getLookup()).where(EnforceSingleRowNode.class::isInstance).recurseOnlyWhen(ProjectNode.class::isInstance).matches()) {
        return Result.empty();
    }
    PlanNode rewrittenSubquery = searchFrom(subquery, context.getLookup()).where(EnforceSingleRowNode.class::isInstance).recurseOnlyWhen(ProjectNode.class::isInstance).removeFirst();
    Range<Long> subqueryCardinality = extractCardinality(rewrittenSubquery, context.getLookup());
    boolean producesAtMostOneRow = Range.closed(0L, 1L).encloses(subqueryCardinality);
    if (producesAtMostOneRow) {
        boolean producesSingleRow = Range.singleton(1L).encloses(subqueryCardinality);
        return Result.ofPlanNode(new CorrelatedJoinNode(context.getIdAllocator().getNextId(), correlatedJoinNode.getInput(), rewrittenSubquery, correlatedJoinNode.getCorrelation(), producesSingleRow ? correlatedJoinNode.getType() : LEFT, correlatedJoinNode.getFilter(), correlatedJoinNode.getOriginSubquery()));
    }
    Symbol unique = context.getSymbolAllocator().newSymbol("unique", BigintType.BIGINT);
    CorrelatedJoinNode rewrittenCorrelatedJoinNode = new CorrelatedJoinNode(context.getIdAllocator().getNextId(), new AssignUniqueId(context.getIdAllocator().getNextId(), correlatedJoinNode.getInput(), unique), rewrittenSubquery, correlatedJoinNode.getCorrelation(), LEFT, correlatedJoinNode.getFilter(), correlatedJoinNode.getOriginSubquery());
    Symbol isDistinct = context.getSymbolAllocator().newSymbol("is_distinct", BOOLEAN);
    MarkDistinctNode markDistinctNode = new MarkDistinctNode(context.getIdAllocator().getNextId(), rewrittenCorrelatedJoinNode, isDistinct, rewrittenCorrelatedJoinNode.getInput().getOutputSymbols(), Optional.empty());
    FilterNode filterNode = new FilterNode(context.getIdAllocator().getNextId(), markDistinctNode, new SimpleCaseExpression(isDistinct.toSymbolReference(), ImmutableList.of(new WhenClause(TRUE_LITERAL, TRUE_LITERAL)), Optional.of(new Cast(FunctionCallBuilder.resolve(context.getSession(), metadata).setName(QualifiedName.of("fail")).addArgument(INTEGER, new LongLiteral(Integer.toString(SUBQUERY_MULTIPLE_ROWS.toErrorCode().getCode()))).addArgument(VARCHAR, new StringLiteral("Scalar sub-query has returned multiple rows")).build(), toSqlType(BOOLEAN)))));
    return Result.ofPlanNode(new ProjectNode(context.getIdAllocator().getNextId(), filterNode, Assignments.identity(correlatedJoinNode.getOutputSymbols())));
}
Also used : Cast(io.trino.sql.tree.Cast) MarkDistinctNode(io.trino.sql.planner.plan.MarkDistinctNode) LongLiteral(io.trino.sql.tree.LongLiteral) CorrelatedJoinNode(io.trino.sql.planner.plan.CorrelatedJoinNode) Symbol(io.trino.sql.planner.Symbol) FilterNode(io.trino.sql.planner.plan.FilterNode) SimpleCaseExpression(io.trino.sql.tree.SimpleCaseExpression) WhenClause(io.trino.sql.tree.WhenClause) PlanNode(io.trino.sql.planner.plan.PlanNode) AssignUniqueId(io.trino.sql.planner.plan.AssignUniqueId) StringLiteral(io.trino.sql.tree.StringLiteral) EnforceSingleRowNode(io.trino.sql.planner.plan.EnforceSingleRowNode) ProjectNode(io.trino.sql.planner.plan.ProjectNode)

Aggregations

FilterNode (io.trino.sql.planner.plan.FilterNode)46 Expression (io.trino.sql.tree.Expression)33 PlanNode (io.trino.sql.planner.plan.PlanNode)20 ProjectNode (io.trino.sql.planner.plan.ProjectNode)20 Symbol (io.trino.sql.planner.Symbol)19 TableScanNode (io.trino.sql.planner.plan.TableScanNode)19 ComparisonExpression (io.trino.sql.tree.ComparisonExpression)19 ImmutableList (com.google.common.collect.ImmutableList)16 JoinNode (io.trino.sql.planner.plan.JoinNode)14 ImmutableList.toImmutableList (com.google.common.collect.ImmutableList.toImmutableList)13 Session (io.trino.Session)11 ColumnHandle (io.trino.spi.connector.ColumnHandle)11 Test (org.testng.annotations.Test)10 SemiJoinNode (io.trino.sql.planner.plan.SemiJoinNode)9 NotExpression (io.trino.sql.tree.NotExpression)9 Map (java.util.Map)9 ValuesNode (io.trino.sql.planner.plan.ValuesNode)8 DomainTranslator (io.trino.sql.planner.DomainTranslator)7 List (java.util.List)7 InListExpression (io.trino.sql.tree.InListExpression)6