Search in sources :

Example 21 with Symbol

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

the class PushPredicateIntoTableScan method pushFilterIntoTableScan.

public static Optional<PlanNode> pushFilterIntoTableScan(FilterNode filterNode, TableScanNode node, boolean pruneWithPredicateExpression, Session session, SymbolAllocator symbolAllocator, PlannerContext plannerContext, TypeAnalyzer typeAnalyzer, StatsProvider statsProvider, DomainTranslator domainTranslator) {
    if (!isAllowPushdownIntoConnectors(session)) {
        return Optional.empty();
    }
    SplitExpression splitExpression = splitExpression(plannerContext, filterNode.getPredicate());
    DomainTranslator.ExtractionResult decomposedPredicate = DomainTranslator.getExtractionResult(plannerContext, session, splitExpression.getDeterministicPredicate(), symbolAllocator.getTypes());
    TupleDomain<ColumnHandle> newDomain = decomposedPredicate.getTupleDomain().transformKeys(node.getAssignments()::get).intersect(node.getEnforcedConstraint());
    Map<NodeRef<Expression>, Type> remainingExpressionTypes = typeAnalyzer.getTypes(session, symbolAllocator.getTypes(), decomposedPredicate.getRemainingExpression());
    Optional<ConnectorExpression> connectorExpression = new ConnectorExpressionTranslator.SqlToConnectorExpressionTranslator(session, remainingExpressionTypes, plannerContext).process(decomposedPredicate.getRemainingExpression());
    Map<String, ColumnHandle> connectorExpressionAssignments = connectorExpression.map(ignored -> node.getAssignments().entrySet().stream().collect(toImmutableMap(entry -> entry.getKey().getName(), Map.Entry::getValue))).orElse(ImmutableMap.of());
    Map<ColumnHandle, Symbol> assignments = ImmutableBiMap.copyOf(node.getAssignments()).inverse();
    Constraint constraint;
    // use evaluator only when there is some predicate which could not be translated into tuple domain
    if (pruneWithPredicateExpression && !TRUE_LITERAL.equals(decomposedPredicate.getRemainingExpression())) {
        LayoutConstraintEvaluator evaluator = new LayoutConstraintEvaluator(plannerContext, typeAnalyzer, session, symbolAllocator.getTypes(), node.getAssignments(), combineConjuncts(plannerContext.getMetadata(), splitExpression.getDeterministicPredicate(), // which would be expensive to evaluate in the call to isCandidate below.
        domainTranslator.toPredicate(session, newDomain.simplify().transformKeys(assignments::get))));
        constraint = new Constraint(newDomain, connectorExpression.orElse(TRUE), connectorExpressionAssignments, evaluator::isCandidate, evaluator.getArguments());
    } else {
        // Currently, invoking the expression interpreter is very expensive.
        // TODO invoke the interpreter unconditionally when the interpreter becomes cheap enough.
        constraint = new Constraint(newDomain, connectorExpression.orElse(TRUE), connectorExpressionAssignments);
    }
    // check if new domain is wider than domain already provided by table scan
    if (constraint.predicate().isEmpty() && // TODO do we need to track enforced ConnectorExpression in TableScanNode?
    TRUE.equals(connectorExpression.orElse(TRUE)) && newDomain.contains(node.getEnforcedConstraint())) {
        Expression resultingPredicate = createResultingPredicate(plannerContext, session, symbolAllocator, typeAnalyzer, splitExpression.getDynamicFilter(), TRUE_LITERAL, splitExpression.getNonDeterministicPredicate(), decomposedPredicate.getRemainingExpression());
        if (!TRUE_LITERAL.equals(resultingPredicate)) {
            return Optional.of(new FilterNode(filterNode.getId(), node, resultingPredicate));
        }
        return Optional.of(node);
    }
    if (newDomain.isNone()) {
        // to turn the subtree into a Values node
        return Optional.of(new ValuesNode(node.getId(), node.getOutputSymbols(), ImmutableList.of()));
    }
    Optional<ConstraintApplicationResult<TableHandle>> result = plannerContext.getMetadata().applyFilter(session, node.getTable(), constraint);
    if (result.isEmpty()) {
        return Optional.empty();
    }
    TableHandle newTable = result.get().getHandle();
    TableProperties newTableProperties = plannerContext.getMetadata().getTableProperties(session, newTable);
    Optional<TablePartitioning> newTablePartitioning = newTableProperties.getTablePartitioning();
    if (newTableProperties.getPredicate().isNone()) {
        return Optional.of(new ValuesNode(node.getId(), node.getOutputSymbols(), ImmutableList.of()));
    }
    TupleDomain<ColumnHandle> remainingFilter = result.get().getRemainingFilter();
    Optional<ConnectorExpression> remainingConnectorExpression = result.get().getRemainingExpression();
    boolean precalculateStatistics = result.get().isPrecalculateStatistics();
    verifyTablePartitioning(session, plannerContext.getMetadata(), node, newTablePartitioning);
    TableScanNode tableScan = new TableScanNode(node.getId(), newTable, node.getOutputSymbols(), node.getAssignments(), computeEnforced(newDomain, remainingFilter), // TODO (https://github.com/trinodb/trino/issues/8144) distinguish between predicate pushed down and remaining
    deriveTableStatisticsForPushdown(statsProvider, session, precalculateStatistics, filterNode), node.isUpdateTarget(), node.getUseConnectorNodePartitioning());
    Expression remainingDecomposedPredicate;
    if (remainingConnectorExpression.isEmpty() || remainingConnectorExpression.equals(connectorExpression)) {
        remainingDecomposedPredicate = decomposedPredicate.getRemainingExpression();
    } else {
        Map<String, Symbol> variableMappings = assignments.values().stream().collect(toImmutableMap(Symbol::getName, Function.identity()));
        Expression translatedExpression = ConnectorExpressionTranslator.translate(session, remainingConnectorExpression.get(), plannerContext, variableMappings, new LiteralEncoder(plannerContext));
        if (connectorExpression.isEmpty()) {
            remainingDecomposedPredicate = ExpressionUtils.combineConjuncts(plannerContext.getMetadata(), translatedExpression, decomposedPredicate.getRemainingExpression());
        } else {
            remainingDecomposedPredicate = translatedExpression;
        }
    }
    Expression resultingPredicate = createResultingPredicate(plannerContext, session, symbolAllocator, typeAnalyzer, splitExpression.getDynamicFilter(), domainTranslator.toPredicate(session, remainingFilter.transformKeys(assignments::get)), splitExpression.getNonDeterministicPredicate(), remainingDecomposedPredicate);
    if (!TRUE_LITERAL.equals(resultingPredicate)) {
        return Optional.of(new FilterNode(filterNode.getId(), tableScan, resultingPredicate));
    }
    return Optional.of(tableScan);
}
Also used : LayoutConstraintEvaluator(io.trino.sql.planner.LayoutConstraintEvaluator) SymbolAllocator(io.trino.sql.planner.SymbolAllocator) FilterNode(io.trino.sql.planner.plan.FilterNode) PlanNode(io.trino.sql.planner.plan.PlanNode) Preconditions.checkArgument(com.google.common.base.Preconditions.checkArgument) DeterminismEvaluator.isDeterministic(io.trino.sql.planner.DeterminismEvaluator.isDeterministic) Map(java.util.Map) TableScanNode(io.trino.sql.planner.plan.TableScanNode) Rules.deriveTableStatisticsForPushdown(io.trino.sql.planner.iterative.rule.Rules.deriveTableStatisticsForPushdown) TRUE(io.trino.spi.expression.Constant.TRUE) ImmutableMap(com.google.common.collect.ImmutableMap) Domain(io.trino.spi.predicate.Domain) ConnectorExpressionTranslator(io.trino.sql.planner.ConnectorExpressionTranslator) Patterns.tableScan(io.trino.sql.planner.plan.Patterns.tableScan) StatsProvider(io.trino.cost.StatsProvider) Objects(java.util.Objects) List(java.util.List) ImmutableMap.toImmutableMap(com.google.common.collect.ImmutableMap.toImmutableMap) Pattern(io.trino.matching.Pattern) SystemSessionProperties.isAllowPushdownIntoConnectors(io.trino.SystemSessionProperties.isAllowPushdownIntoConnectors) Optional(java.util.Optional) Expression(io.trino.sql.tree.Expression) ExpressionUtils.extractConjuncts(io.trino.sql.ExpressionUtils.extractConjuncts) ValuesNode(io.trino.sql.planner.plan.ValuesNode) ExpressionUtils.combineConjuncts(io.trino.sql.ExpressionUtils.combineConjuncts) Session(io.trino.Session) PlannerContext(io.trino.sql.PlannerContext) Constraint(io.trino.spi.connector.Constraint) LiteralEncoder(io.trino.sql.planner.LiteralEncoder) Type(io.trino.spi.type.Type) Patterns.filter(io.trino.sql.planner.plan.Patterns.filter) TableProperties(io.trino.metadata.TableProperties) Function(java.util.function.Function) Capture.newCapture(io.trino.matching.Capture.newCapture) ArrayList(java.util.ArrayList) ImmutableBiMap(com.google.common.collect.ImmutableBiMap) ImmutableList(com.google.common.collect.ImmutableList) Verify.verify(com.google.common.base.Verify.verify) NodeRef(io.trino.sql.tree.NodeRef) Objects.requireNonNull(java.util.Objects.requireNonNull) ColumnHandle(io.trino.spi.connector.ColumnHandle) Rule(io.trino.sql.planner.iterative.Rule) DomainTranslator(io.trino.sql.planner.DomainTranslator) TablePartitioning(io.trino.metadata.TableProperties.TablePartitioning) ExpressionUtils(io.trino.sql.ExpressionUtils) Symbol(io.trino.sql.planner.Symbol) ConstraintApplicationResult(io.trino.spi.connector.ConstraintApplicationResult) TRUE_LITERAL(io.trino.sql.tree.BooleanLiteral.TRUE_LITERAL) TupleDomain(io.trino.spi.predicate.TupleDomain) Capture(io.trino.matching.Capture) TableHandle(io.trino.metadata.TableHandle) ConnectorExpression(io.trino.spi.expression.ConnectorExpression) TypeAnalyzer(io.trino.sql.planner.TypeAnalyzer) Patterns.source(io.trino.sql.planner.plan.Patterns.source) DynamicFilters.isDynamicFilter(io.trino.sql.DynamicFilters.isDynamicFilter) Captures(io.trino.matching.Captures) Metadata(io.trino.metadata.Metadata) ValuesNode(io.trino.sql.planner.plan.ValuesNode) Constraint(io.trino.spi.connector.Constraint) ConnectorExpression(io.trino.spi.expression.ConnectorExpression) Symbol(io.trino.sql.planner.Symbol) FilterNode(io.trino.sql.planner.plan.FilterNode) NodeRef(io.trino.sql.tree.NodeRef) TablePartitioning(io.trino.metadata.TableProperties.TablePartitioning) LiteralEncoder(io.trino.sql.planner.LiteralEncoder) DomainTranslator(io.trino.sql.planner.DomainTranslator) ConstraintApplicationResult(io.trino.spi.connector.ConstraintApplicationResult) ColumnHandle(io.trino.spi.connector.ColumnHandle) Type(io.trino.spi.type.Type) TableScanNode(io.trino.sql.planner.plan.TableScanNode) Expression(io.trino.sql.tree.Expression) ConnectorExpression(io.trino.spi.expression.ConnectorExpression) ConnectorExpressionTranslator(io.trino.sql.planner.ConnectorExpressionTranslator) TableHandle(io.trino.metadata.TableHandle) Map(java.util.Map) ImmutableMap(com.google.common.collect.ImmutableMap) ImmutableMap.toImmutableMap(com.google.common.collect.ImmutableMap.toImmutableMap) ImmutableBiMap(com.google.common.collect.ImmutableBiMap) TableProperties(io.trino.metadata.TableProperties) LayoutConstraintEvaluator(io.trino.sql.planner.LayoutConstraintEvaluator)

Example 22 with Symbol

use of io.trino.sql.planner.Symbol 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 23 with Symbol

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

the class PushDownProjectionsFromPatternRecognition method apply.

@Override
public Result apply(PatternRecognitionNode node, Captures captures, Context context) {
    Assignments.Builder assignments = Assignments.builder();
    Map<IrLabel, ExpressionAndValuePointers> rewrittenVariableDefinitions = rewriteVariableDefinitions(node.getVariableDefinitions(), assignments, context);
    Map<Symbol, Measure> rewrittenMeasureDefinitions = rewriteMeasureDefinitions(node.getMeasures(), assignments, context);
    if (assignments.build().isEmpty()) {
        return Result.empty();
    }
    assignments.putIdentities(node.getSource().getOutputSymbols());
    ProjectNode projectNode = new ProjectNode(context.getIdAllocator().getNextId(), node.getSource(), assignments.build());
    PatternRecognitionNode patternRecognitionNode = new PatternRecognitionNode(node.getId(), projectNode, node.getSpecification(), node.getHashSymbol(), node.getPrePartitionedInputs(), node.getPreSortedOrderPrefix(), node.getWindowFunctions(), rewrittenMeasureDefinitions, node.getCommonBaseFrame(), node.getRowsPerMatch(), node.getSkipToLabel(), node.getSkipToPosition(), node.isInitial(), node.getPattern(), node.getSubsets(), rewrittenVariableDefinitions);
    return Result.ofPlanNode(restrictOutputs(context.getIdAllocator(), patternRecognitionNode, ImmutableSet.copyOf(node.getOutputSymbols())).orElse(patternRecognitionNode));
}
Also used : IrLabel(io.trino.sql.planner.rowpattern.ir.IrLabel) PatternRecognitionNode(io.trino.sql.planner.plan.PatternRecognitionNode) Symbol(io.trino.sql.planner.Symbol) ExpressionAndValuePointers(io.trino.sql.planner.rowpattern.LogicalIndexExtractor.ExpressionAndValuePointers) Assignments(io.trino.sql.planner.plan.Assignments) Measure(io.trino.sql.planner.plan.PatternRecognitionNode.Measure) ProjectNode(io.trino.sql.planner.plan.ProjectNode)

Example 24 with Symbol

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

the class PushJoinIntoTableScan method getPushableJoinCondition.

private Optional<JoinCondition> getPushableJoinCondition(Expression conjunct, Set<Symbol> leftSymbols, Set<Symbol> rightSymbols, Context context) {
    if (!(conjunct instanceof ComparisonExpression)) {
        return Optional.empty();
    }
    ComparisonExpression comparison = (ComparisonExpression) conjunct;
    if (!(comparison.getLeft() instanceof SymbolReference) || !(comparison.getRight() instanceof SymbolReference)) {
        return Optional.empty();
    }
    Symbol left = Symbol.from(comparison.getLeft());
    Symbol right = Symbol.from(comparison.getRight());
    ComparisonExpression.Operator operator = comparison.getOperator();
    if (!leftSymbols.contains(left)) {
        // lets try with flipped expression
        Symbol tmp = left;
        left = right;
        right = tmp;
        operator = operator.flip();
    }
    if (leftSymbols.contains(left) && rightSymbols.contains(right)) {
        return Optional.of(new JoinCondition(joinConditionOperator(operator), new Variable(left.getName(), context.getSymbolAllocator().getTypes().get(left)), new Variable(right.getName(), context.getSymbolAllocator().getTypes().get(right))));
    }
    return Optional.empty();
}
Also used : ComparisonExpression(io.trino.sql.tree.ComparisonExpression) Variable(io.trino.spi.expression.Variable) SymbolReference(io.trino.sql.tree.SymbolReference) Symbol(io.trino.sql.planner.Symbol) JoinCondition(io.trino.spi.connector.JoinCondition)

Example 25 with Symbol

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

the class PushJoinIntoTableScan method apply.

@Override
public Result apply(JoinNode joinNode, Captures captures, Context context) {
    if (joinNode.isCrossJoin()) {
        return Result.empty();
    }
    TableScanNode left = captures.get(LEFT_TABLE_SCAN);
    TableScanNode right = captures.get(RIGHT_TABLE_SCAN);
    verify(!left.isUpdateTarget() && !right.isUpdateTarget(), "Unexpected Join over for-update table scan");
    Expression effectiveFilter = getEffectiveFilter(joinNode);
    FilterSplitResult filterSplitResult = splitFilter(effectiveFilter, left.getOutputSymbols(), right.getOutputSymbols(), context);
    if (!filterSplitResult.getRemainingFilter().equals(BooleanLiteral.TRUE_LITERAL)) {
        // TODO add extra filter node above join
        return Result.empty();
    }
    if (left.getEnforcedConstraint().isNone() || right.getEnforcedConstraint().isNone()) {
        // enforced constraint harder below.
        return Result.empty();
    }
    Map<String, ColumnHandle> leftAssignments = left.getAssignments().entrySet().stream().collect(toImmutableMap(entry -> entry.getKey().getName(), Map.Entry::getValue));
    Map<String, ColumnHandle> rightAssignments = right.getAssignments().entrySet().stream().collect(toImmutableMap(entry -> entry.getKey().getName(), Map.Entry::getValue));
    /*
         * We are (lazily) computing estimated statistics for join node and left and right table
         * and passing those to connector via applyJoin.
         *
         * There are a couple reasons for this approach:
         * - the engine knows how to estimate join and connector may not
         * - the engine may have cached stats for the table scans (within context.getStatsProvider()), so can be able to provide information more inexpensively
         * - in the future, the engine may be able to provide stats for table scan even in case when connector no longer can (see https://github.com/trinodb/trino/issues/6998)
         * - the pushdown feasibility assessment logic may be different (or configured differently) for different connectors/catalogs.
         */
    JoinStatistics joinStatistics = getJoinStatistics(joinNode, left, right, context);
    Optional<JoinApplicationResult<TableHandle>> joinApplicationResult = metadata.applyJoin(context.getSession(), getJoinType(joinNode), left.getTable(), right.getTable(), filterSplitResult.getPushableConditions(), // TODO we could pass only subset of assignments here, those which are needed to resolve filterSplitResult.getPushableConditions
    leftAssignments, rightAssignments, joinStatistics);
    if (joinApplicationResult.isEmpty()) {
        return Result.empty();
    }
    TableHandle handle = joinApplicationResult.get().getTableHandle();
    Map<ColumnHandle, ColumnHandle> leftColumnHandlesMapping = joinApplicationResult.get().getLeftColumnHandles();
    Map<ColumnHandle, ColumnHandle> rightColumnHandlesMapping = joinApplicationResult.get().getRightColumnHandles();
    ImmutableMap.Builder<Symbol, ColumnHandle> assignmentsBuilder = ImmutableMap.builder();
    assignmentsBuilder.putAll(left.getAssignments().entrySet().stream().collect(toImmutableMap(Map.Entry::getKey, entry -> leftColumnHandlesMapping.get(entry.getValue()))));
    assignmentsBuilder.putAll(right.getAssignments().entrySet().stream().collect(toImmutableMap(Map.Entry::getKey, entry -> rightColumnHandlesMapping.get(entry.getValue()))));
    Map<Symbol, ColumnHandle> assignments = assignmentsBuilder.buildOrThrow();
    // convert enforced constraint
    JoinNode.Type joinType = joinNode.getType();
    TupleDomain<ColumnHandle> leftConstraint = deriveConstraint(left.getEnforcedConstraint(), leftColumnHandlesMapping, joinType == RIGHT || joinType == FULL);
    TupleDomain<ColumnHandle> rightConstraint = deriveConstraint(right.getEnforcedConstraint(), rightColumnHandlesMapping, joinType == LEFT || joinType == FULL);
    TupleDomain<ColumnHandle> newEnforcedConstraint = TupleDomain.withColumnDomains(ImmutableMap.<ColumnHandle, Domain>builder().putAll(leftConstraint.getDomains().orElseThrow()).putAll(rightConstraint.getDomains().orElseThrow()).buildOrThrow());
    return Result.ofPlanNode(new ProjectNode(context.getIdAllocator().getNextId(), new TableScanNode(joinNode.getId(), handle, ImmutableList.copyOf(assignments.keySet()), assignments, newEnforcedConstraint, deriveTableStatisticsForPushdown(context.getStatsProvider(), context.getSession(), joinApplicationResult.get().isPrecalculateStatistics(), joinNode), false, Optional.empty()), Assignments.identity(joinNode.getOutputSymbols())));
}
Also used : PlanNode(io.trino.sql.planner.plan.PlanNode) LEFT(io.trino.sql.planner.plan.JoinNode.Type.LEFT) BooleanLiteral(io.trino.sql.tree.BooleanLiteral) Map(java.util.Map) JoinNode(io.trino.sql.planner.plan.JoinNode) TableScanNode(io.trino.sql.planner.plan.TableScanNode) PlanNodeStatsEstimate(io.trino.cost.PlanNodeStatsEstimate) Rules.deriveTableStatisticsForPushdown(io.trino.sql.planner.iterative.rule.Rules.deriveTableStatisticsForPushdown) ImmutableSet(com.google.common.collect.ImmutableSet) ImmutableMap(com.google.common.collect.ImmutableMap) Domain(io.trino.spi.predicate.Domain) ImmutableList.toImmutableList(com.google.common.collect.ImmutableList.toImmutableList) Assignments(io.trino.sql.planner.plan.Assignments) Set(java.util.Set) BasicRelationStatistics(io.trino.spi.connector.BasicRelationStatistics) Patterns.tableScan(io.trino.sql.planner.plan.Patterns.tableScan) ComparisonExpression(io.trino.sql.tree.ComparisonExpression) List(java.util.List) ImmutableMap.toImmutableMap(com.google.common.collect.ImmutableMap.toImmutableMap) Pattern(io.trino.matching.Pattern) SystemSessionProperties.isAllowPushdownIntoConnectors(io.trino.SystemSessionProperties.isAllowPushdownIntoConnectors) RIGHT(io.trino.sql.planner.plan.JoinNode.Type.RIGHT) SymbolReference(io.trino.sql.tree.SymbolReference) Optional(java.util.Optional) Expression(io.trino.sql.tree.Expression) ExpressionUtils.extractConjuncts(io.trino.sql.ExpressionUtils.extractConjuncts) Session(io.trino.Session) JoinCondition(io.trino.spi.connector.JoinCondition) Patterns(io.trino.sql.planner.plan.Patterns) Variable(io.trino.spi.expression.Variable) Capture.newCapture(io.trino.matching.Capture.newCapture) JoinStatistics(io.trino.spi.connector.JoinStatistics) ImmutableList(com.google.common.collect.ImmutableList) JoinType(io.trino.spi.connector.JoinType) Verify.verify(com.google.common.base.Verify.verify) Objects.requireNonNull(java.util.Objects.requireNonNull) ColumnHandle(io.trino.spi.connector.ColumnHandle) Rule(io.trino.sql.planner.iterative.Rule) Join.left(io.trino.sql.planner.plan.Patterns.Join.left) ProjectNode(io.trino.sql.planner.plan.ProjectNode) ExpressionUtils(io.trino.sql.ExpressionUtils) Symbol(io.trino.sql.planner.Symbol) FULL(io.trino.sql.planner.plan.JoinNode.Type.FULL) TupleDomain(io.trino.spi.predicate.TupleDomain) Capture(io.trino.matching.Capture) JoinApplicationResult(io.trino.spi.connector.JoinApplicationResult) TableHandle(io.trino.metadata.TableHandle) Join.right(io.trino.sql.planner.plan.Patterns.Join.right) ExpressionUtils.and(io.trino.sql.ExpressionUtils.and) Double.isNaN(java.lang.Double.isNaN) Captures(io.trino.matching.Captures) Metadata(io.trino.metadata.Metadata) TypeProvider(io.trino.sql.planner.TypeProvider) Domain.onlyNull(io.trino.spi.predicate.Domain.onlyNull) ColumnHandle(io.trino.spi.connector.ColumnHandle) Symbol(io.trino.sql.planner.Symbol) JoinNode(io.trino.sql.planner.plan.JoinNode) JoinApplicationResult(io.trino.spi.connector.JoinApplicationResult) ImmutableMap(com.google.common.collect.ImmutableMap) ImmutableMap.toImmutableMap(com.google.common.collect.ImmutableMap.toImmutableMap) JoinStatistics(io.trino.spi.connector.JoinStatistics) TableScanNode(io.trino.sql.planner.plan.TableScanNode) ComparisonExpression(io.trino.sql.tree.ComparisonExpression) Expression(io.trino.sql.tree.Expression) TableHandle(io.trino.metadata.TableHandle) ProjectNode(io.trino.sql.planner.plan.ProjectNode) Domain(io.trino.spi.predicate.Domain) TupleDomain(io.trino.spi.predicate.TupleDomain) Map(java.util.Map) ImmutableMap(com.google.common.collect.ImmutableMap) ImmutableMap.toImmutableMap(com.google.common.collect.ImmutableMap.toImmutableMap)

Aggregations

Symbol (io.trino.sql.planner.Symbol)366 Test (org.testng.annotations.Test)171 ImmutableList (com.google.common.collect.ImmutableList)124 ImmutableMap (com.google.common.collect.ImmutableMap)106 Optional (java.util.Optional)96 PlanNode (io.trino.sql.planner.plan.PlanNode)85 Expression (io.trino.sql.tree.Expression)85 Map (java.util.Map)66 Assignments (io.trino.sql.planner.plan.Assignments)65 JoinNode (io.trino.sql.planner.plan.JoinNode)64 ProjectNode (io.trino.sql.planner.plan.ProjectNode)61 PlanMatchPattern.values (io.trino.sql.planner.assertions.PlanMatchPattern.values)56 SymbolReference (io.trino.sql.tree.SymbolReference)55 BIGINT (io.trino.spi.type.BigintType.BIGINT)52 Type (io.trino.spi.type.Type)51 Session (io.trino.Session)46 List (java.util.List)46 RuleTester (io.trino.sql.planner.iterative.rule.test.RuleTester)43 RuleTester.defaultRuleTester (io.trino.sql.planner.iterative.rule.test.RuleTester.defaultRuleTester)43 PlanNodeId (io.trino.sql.planner.plan.PlanNodeId)43