Search in sources :

Example 16 with TableScanNode

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

the class TestPushJoinIntoTableScan method testPushJoinIntoTableScanDoesNotFireForDifferentCatalogs.

@Test
public void testPushJoinIntoTableScanDoesNotFireForDifferentCatalogs() {
    try (RuleTester ruleTester = defaultRuleTester()) {
        MockConnectorFactory connectorFactory = createMockConnectorFactory((session, applyJoinType, left, right, joinConditions, leftAssignments, rightAssignments) -> {
            throw new IllegalStateException("applyJoin should not be called!");
        });
        ruleTester.getQueryRunner().createCatalog(MOCK_CATALOG, connectorFactory, ImmutableMap.of());
        ruleTester.getQueryRunner().createCatalog("another_catalog", "mock", ImmutableMap.of());
        TableHandle tableBHandleAnotherCatalog = createTableHandle(new MockConnectorTableHandle(new SchemaTableName(SCHEMA, TABLE_B)), "another_catalog");
        ruleTester.assertThat(new PushJoinIntoTableScan(ruleTester.getMetadata())).on(p -> {
            Symbol columnA1Symbol = p.symbol(COLUMN_A1);
            Symbol columnA2Symbol = p.symbol(COLUMN_A2);
            Symbol columnB1Symbol = p.symbol(COLUMN_B1);
            TableScanNode left = p.tableScan(TABLE_A_HANDLE, ImmutableList.of(columnA1Symbol, columnA2Symbol), ImmutableMap.of(columnA1Symbol, COLUMN_A1_HANDLE, columnA2Symbol, COLUMN_A2_HANDLE));
            TableScanNode right = p.tableScan(tableBHandleAnotherCatalog, ImmutableList.of(columnB1Symbol), ImmutableMap.of(columnB1Symbol, COLUMN_B1_HANDLE));
            return p.join(INNER, left, right, new JoinNode.EquiJoinClause(columnA1Symbol, columnB1Symbol));
        }).withSession(MOCK_SESSION).doesNotFire();
    }
}
Also used : MockConnectorFactory(io.trino.connector.MockConnectorFactory) TableScanNode(io.trino.sql.planner.plan.TableScanNode) RuleTester.defaultRuleTester(io.trino.sql.planner.iterative.rule.test.RuleTester.defaultRuleTester) RuleTester(io.trino.sql.planner.iterative.rule.test.RuleTester) MockConnectorTableHandle(io.trino.connector.MockConnectorTableHandle) Symbol(io.trino.sql.planner.Symbol) JoinNode(io.trino.sql.planner.plan.JoinNode) ConnectorTableHandle(io.trino.spi.connector.ConnectorTableHandle) MockConnectorTableHandle(io.trino.connector.MockConnectorTableHandle) TableHandle(io.trino.metadata.TableHandle) SchemaTableName(io.trino.spi.connector.SchemaTableName) Test(org.testng.annotations.Test)

Example 17 with TableScanNode

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

the class TableScanStatsRule method doCalculate.

@Override
protected Optional<PlanNodeStatsEstimate> doCalculate(TableScanNode node, StatsProvider sourceStats, Lookup lookup, Session session, TypeProvider types) {
    if (isStatisticsPrecalculationForPushdownEnabled(session) && node.getStatistics().isPresent()) {
        return node.getStatistics();
    }
    // TODO Construct predicate like AddExchanges's LayoutConstraintEvaluator
    Constraint constraint = new Constraint(TupleDomain.all());
    TableStatistics tableStatistics = metadata.getTableStatistics(session, node.getTable(), constraint);
    Map<Symbol, SymbolStatsEstimate> outputSymbolStats = new HashMap<>();
    for (Map.Entry<Symbol, ColumnHandle> entry : node.getAssignments().entrySet()) {
        Symbol symbol = entry.getKey();
        Optional<ColumnStatistics> columnStatistics = Optional.ofNullable(tableStatistics.getColumnStatistics().get(entry.getValue()));
        SymbolStatsEstimate symbolStatistics = columnStatistics.map(statistics -> toSymbolStatistics(tableStatistics, statistics, types.get(symbol))).orElse(SymbolStatsEstimate.unknown());
        outputSymbolStats.put(symbol, symbolStatistics);
    }
    return Optional.of(PlanNodeStatsEstimate.builder().setOutputRowCount(tableStatistics.getRowCount().getValue()).addSymbolStatistics(outputSymbolStats).build());
}
Also used : ColumnStatistics(io.trino.spi.statistics.ColumnStatistics) Symbol(io.trino.sql.planner.Symbol) Constraint(io.trino.spi.connector.Constraint) Lookup(io.trino.sql.planner.iterative.Lookup) ColumnStatistics(io.trino.spi.statistics.ColumnStatistics) Type(io.trino.spi.type.Type) HashMap(java.util.HashMap) TupleDomain(io.trino.spi.predicate.TupleDomain) Patterns.tableScan(io.trino.sql.planner.plan.Patterns.tableScan) SystemSessionProperties.isStatisticsPrecalculationForPushdownEnabled(io.trino.SystemSessionProperties.isStatisticsPrecalculationForPushdownEnabled) Pattern(io.trino.matching.Pattern) NaN(java.lang.Double.NaN) FixedWidthType(io.trino.spi.type.FixedWidthType) Map(java.util.Map) Objects.requireNonNull(java.util.Objects.requireNonNull) Metadata(io.trino.metadata.Metadata) ColumnHandle(io.trino.spi.connector.ColumnHandle) TableStatistics(io.trino.spi.statistics.TableStatistics) TypeProvider(io.trino.sql.planner.TypeProvider) Optional(java.util.Optional) TableScanNode(io.trino.sql.planner.plan.TableScanNode) Session(io.trino.Session) ColumnHandle(io.trino.spi.connector.ColumnHandle) Constraint(io.trino.spi.connector.Constraint) HashMap(java.util.HashMap) Symbol(io.trino.sql.planner.Symbol) TableStatistics(io.trino.spi.statistics.TableStatistics) HashMap(java.util.HashMap) Map(java.util.Map)

Example 18 with TableScanNode

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

the class PlanPrinter method textDistributedPlan.

public static String textDistributedPlan(StageInfo outputStageInfo, QueryStats queryStats, ValuePrinter valuePrinter, boolean verbose) {
    Map<PlanNodeId, TableInfo> tableInfos = getAllStages(Optional.of(outputStageInfo)).stream().map(StageInfo::getTables).map(Map::entrySet).flatMap(Collection::stream).collect(toImmutableMap(Entry::getKey, Entry::getValue));
    StringBuilder builder = new StringBuilder();
    List<StageInfo> allStages = getAllStages(Optional.of(outputStageInfo));
    List<PlanFragment> allFragments = allStages.stream().map(StageInfo::getPlan).collect(toImmutableList());
    Map<PlanNodeId, PlanNodeStats> aggregatedStats = aggregateStageStats(allStages);
    Map<DynamicFilterId, DynamicFilterDomainStats> dynamicFilterDomainStats = queryStats.getDynamicFiltersStats().getDynamicFilterDomainStats().stream().collect(toImmutableMap(DynamicFilterDomainStats::getDynamicFilterId, identity()));
    TypeProvider typeProvider = getTypeProvider(allFragments);
    for (StageInfo stageInfo : allStages) {
        builder.append(formatFragment(tableScanNode -> tableInfos.get(tableScanNode.getId()), dynamicFilterDomainStats, valuePrinter, stageInfo.getPlan(), Optional.of(stageInfo), Optional.of(aggregatedStats), verbose, typeProvider));
    }
    return builder.toString();
}
Also used : PlanFragment(io.trino.sql.planner.PlanFragment) Scope(io.trino.sql.planner.plan.ExchangeNode.Scope) ColumnStatisticMetadata(io.trino.spi.statistics.ColumnStatisticMetadata) AggregationValuePointer(io.trino.sql.planner.rowpattern.AggregationValuePointer) CorrelatedJoinNode(io.trino.sql.planner.plan.CorrelatedJoinNode) PlanNode(io.trino.sql.planner.plan.PlanNode) RemoteSourceNode(io.trino.sql.planner.plan.RemoteSourceNode) TypedSymbol(io.trino.sql.planner.planprinter.NodeRepresentation.TypedSymbol) DynamicFilters(io.trino.sql.DynamicFilters) PlanNodeId(io.trino.sql.planner.plan.PlanNodeId) Map(java.util.Map) TextRenderer.formatPositions(io.trino.sql.planner.planprinter.TextRenderer.formatPositions) OutputNode(io.trino.sql.planner.plan.OutputNode) TableScanNode(io.trino.sql.planner.plan.TableScanNode) PlanNodeStatsEstimate(io.trino.cost.PlanNodeStatsEstimate) ExplainAnalyzeNode(io.trino.sql.planner.plan.ExplainAnalyzeNode) Range(io.trino.spi.predicate.Range) Domain(io.trino.spi.predicate.Domain) StatisticsWriterNode(io.trino.sql.planner.plan.StatisticsWriterNode) ImmutableList.toImmutableList(com.google.common.collect.ImmutableList.toImmutableList) Assignments(io.trino.sql.planner.plan.Assignments) Set(java.util.Set) SemiJoinNode(io.trino.sql.planner.plan.SemiJoinNode) MILLISECONDS(java.util.concurrent.TimeUnit.MILLISECONDS) Collectors.joining(java.util.stream.Collectors.joining) IntersectNode(io.trino.sql.planner.plan.IntersectNode) ImmutableMap.toImmutableMap(com.google.common.collect.ImmutableMap.toImmutableMap) Stream(java.util.stream.Stream) SubPlan(io.trino.sql.planner.SubPlan) SymbolReference(io.trino.sql.tree.SymbolReference) TopNRankingNode(io.trino.sql.planner.plan.TopNRankingNode) PlanFragmentId(io.trino.sql.planner.plan.PlanFragmentId) ValuesNode(io.trino.sql.planner.plan.ValuesNode) Position(io.trino.sql.tree.SkipTo.Position) Joiner(com.google.common.base.Joiner) Session(io.trino.Session) TableExecuteNode(io.trino.sql.planner.plan.TableExecuteNode) NullableValue(io.trino.spi.predicate.NullableValue) LimitNode(io.trino.sql.planner.plan.LimitNode) StageStats(io.trino.execution.StageStats) PlanCostEstimate(io.trino.cost.PlanCostEstimate) StatsAndCosts(io.trino.cost.StatsAndCosts) DynamicFilterId(io.trino.sql.planner.plan.DynamicFilterId) ArrayList(java.util.ArrayList) RowNumberNode(io.trino.sql.planner.plan.RowNumberNode) ColumnHandle(io.trino.spi.connector.ColumnHandle) AggregationNode(io.trino.sql.planner.plan.AggregationNode) StageExecutionDescriptor.ungroupedExecution(io.trino.operator.StageExecutionDescriptor.ungroupedExecution) TextRenderer.formatDouble(io.trino.sql.planner.planprinter.TextRenderer.formatDouble) StageInfo.getAllStages(io.trino.execution.StageInfo.getAllStages) StageExecutionDescriptor(io.trino.operator.StageExecutionDescriptor) IrLabel(io.trino.sql.planner.rowpattern.ir.IrLabel) UnnestNode(io.trino.sql.planner.plan.UnnestNode) TableHandle(io.trino.metadata.TableHandle) ExceptNode(io.trino.sql.planner.plan.ExceptNode) GroupIdNode(io.trino.sql.planner.plan.GroupIdNode) OffsetNode(io.trino.sql.planner.plan.OffsetNode) TableFinishNode(io.trino.sql.planner.plan.TableFinishNode) SampleNode(io.trino.sql.planner.plan.SampleNode) IndexSourceNode(io.trino.sql.planner.plan.IndexSourceNode) GroupReference(io.trino.sql.planner.iterative.GroupReference) Aggregation(io.trino.sql.planner.plan.AggregationNode.Aggregation) TableWriterNode(io.trino.sql.planner.plan.TableWriterNode) DynamicFilters.extractDynamicFilters(io.trino.sql.DynamicFilters.extractDynamicFilters) DynamicFilterDomainStats(io.trino.server.DynamicFilterService.DynamicFilterDomainStats) Math.abs(java.lang.Math.abs) FilterNode(io.trino.sql.planner.plan.FilterNode) Duration(io.airlift.units.Duration) Preconditions.checkArgument(com.google.common.base.Preconditions.checkArgument) TableDeleteNode(io.trino.sql.planner.plan.TableDeleteNode) TextRenderer.indentString(io.trino.sql.planner.planprinter.TextRenderer.indentString) SpatialJoinNode(io.trino.sql.planner.plan.SpatialJoinNode) DeleteNode(io.trino.sql.planner.plan.DeleteNode) LogicalIndexPointer(io.trino.sql.planner.rowpattern.LogicalIndexPointer) SINGLE_DISTRIBUTION(io.trino.sql.planner.SystemPartitioningHandle.SINGLE_DISTRIBUTION) WINDOW(io.trino.sql.tree.PatternRecognitionRelation.RowsPerMatch.WINDOW) JoinNode(io.trino.sql.planner.plan.JoinNode) AssignUniqueId(io.trino.sql.planner.plan.AssignUniqueId) FunctionCall(io.trino.sql.tree.FunctionCall) PlanNodeStatsSummarizer.aggregateStageStats(io.trino.sql.planner.planprinter.PlanNodeStatsSummarizer.aggregateStageStats) MarkDistinctNode(io.trino.sql.planner.plan.MarkDistinctNode) ImmutableSet(com.google.common.collect.ImmutableSet) ImmutableMap(com.google.common.collect.ImmutableMap) EnforceSingleRowNode(io.trino.sql.planner.plan.EnforceSingleRowNode) ExpressionTreeRewriter(io.trino.sql.tree.ExpressionTreeRewriter) Collection(java.util.Collection) IndexJoinNode(io.trino.sql.planner.plan.IndexJoinNode) Streams(com.google.common.collect.Streams) PatternRecognitionNode(io.trino.sql.planner.plan.PatternRecognitionNode) Collectors(java.util.stream.Collectors) ComparisonExpression(io.trino.sql.tree.ComparisonExpression) String.format(java.lang.String.format) Preconditions.checkState(com.google.common.base.Preconditions.checkState) Objects(java.util.Objects) List(java.util.List) StatisticAggregationsDescriptor(io.trino.sql.planner.plan.StatisticAggregationsDescriptor) TableInfo(io.trino.execution.TableInfo) Entry(java.util.Map.Entry) Function.identity(java.util.function.Function.identity) ApplyNode(io.trino.sql.planner.plan.ApplyNode) Optional(java.util.Optional) ExchangeNode(io.trino.sql.planner.plan.ExchangeNode) Expression(io.trino.sql.tree.Expression) TableStatisticType(io.trino.spi.statistics.TableStatisticType) WindowNode(io.trino.sql.planner.plan.WindowNode) Arrays.stream(java.util.Arrays.stream) UnionNode(io.trino.sql.planner.plan.UnionNode) INNER(io.trino.sql.planner.plan.JoinNode.Type.INNER) Type(io.trino.spi.type.Type) Measure(io.trino.sql.planner.plan.PatternRecognitionNode.Measure) StatisticAggregations(io.trino.sql.planner.plan.StatisticAggregations) Partitioning(io.trino.sql.planner.Partitioning) PartitioningScheme(io.trino.sql.planner.PartitioningScheme) SortNode(io.trino.sql.planner.plan.SortNode) Function(java.util.function.Function) ImmutableList(com.google.common.collect.ImmutableList) Verify.verify(com.google.common.base.Verify.verify) Objects.requireNonNull(java.util.Objects.requireNonNull) RefreshMaterializedViewNode(io.trino.sql.planner.plan.RefreshMaterializedViewNode) ExpressionRewriter(io.trino.sql.tree.ExpressionRewriter) LinkedList(java.util.LinkedList) ProjectNode(io.trino.sql.planner.plan.ProjectNode) ExpressionAndValuePointers(io.trino.sql.planner.rowpattern.LogicalIndexExtractor.ExpressionAndValuePointers) StageInfo(io.trino.execution.StageInfo) Symbol(io.trino.sql.planner.Symbol) ExpressionUtils.combineConjunctsWithDuplicates(io.trino.sql.ExpressionUtils.combineConjunctsWithDuplicates) RowsPerMatch(io.trino.sql.tree.PatternRecognitionRelation.RowsPerMatch) CaseFormat(com.google.common.base.CaseFormat) PlanVisitor(io.trino.sql.planner.plan.PlanVisitor) TopNNode(io.trino.sql.planner.plan.TopNNode) ScalarValuePointer(io.trino.sql.planner.rowpattern.ScalarValuePointer) TRUE_LITERAL(io.trino.sql.tree.BooleanLiteral.TRUE_LITERAL) TupleDomain(io.trino.spi.predicate.TupleDomain) OrderingScheme(io.trino.sql.planner.OrderingScheme) PlanNodeStatsAndCostSummary(io.trino.cost.PlanNodeStatsAndCostSummary) FunctionManager(io.trino.metadata.FunctionManager) UpdateNode(io.trino.sql.planner.plan.UpdateNode) QualifiedName(io.trino.sql.tree.QualifiedName) UPPER_UNDERSCORE(com.google.common.base.CaseFormat.UPPER_UNDERSCORE) Collectors.toList(java.util.stream.Collectors.toList) QueryStats(io.trino.execution.QueryStats) DistinctLimitNode(io.trino.sql.planner.plan.DistinctLimitNode) ValuePointer(io.trino.sql.planner.rowpattern.ValuePointer) Row(io.trino.sql.tree.Row) Metadata(io.trino.metadata.Metadata) TypeProvider(io.trino.sql.planner.TypeProvider) ResolvedFunction.extractFunctionName(io.trino.metadata.ResolvedFunction.extractFunctionName) StageInfo(io.trino.execution.StageInfo) TypeProvider(io.trino.sql.planner.TypeProvider) PlanFragment(io.trino.sql.planner.PlanFragment) PlanNodeId(io.trino.sql.planner.plan.PlanNodeId) DynamicFilterDomainStats(io.trino.server.DynamicFilterService.DynamicFilterDomainStats) TableInfo(io.trino.execution.TableInfo) Map(java.util.Map) ImmutableMap.toImmutableMap(com.google.common.collect.ImmutableMap.toImmutableMap) ImmutableMap(com.google.common.collect.ImmutableMap) DynamicFilterId(io.trino.sql.planner.plan.DynamicFilterId)

Example 19 with TableScanNode

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

the class TestDetermineJoinDistributionType method testGetSourceTablesSizeInBytes.

@Test
public void testGetSourceTablesSizeInBytes() {
    PlanBuilder planBuilder = new PlanBuilder(new PlanNodeIdAllocator(), tester.getMetadata(), tester.getSession());
    Symbol symbol = planBuilder.symbol("col");
    Symbol sourceSymbol1 = planBuilder.symbol("source1");
    Symbol sourceSymbol2 = planBuilder.symbol("soruce2");
    // missing source stats
    assertEquals(getSourceTablesSizeInBytes(planBuilder.values(symbol), noLookup(), node -> PlanNodeStatsEstimate.unknown(), planBuilder.getTypes()), NaN);
    // two source plan nodes
    PlanNodeStatsEstimate sourceStatsEstimate1 = PlanNodeStatsEstimate.builder().setOutputRowCount(10).build();
    PlanNodeStatsEstimate sourceStatsEstimate2 = PlanNodeStatsEstimate.builder().setOutputRowCount(20).build();
    assertEquals(getSourceTablesSizeInBytes(planBuilder.union(ImmutableListMultimap.<Symbol, Symbol>builder().put(symbol, sourceSymbol1).put(symbol, sourceSymbol2).build(), ImmutableList.of(planBuilder.tableScan(ImmutableList.of(sourceSymbol1), ImmutableMap.of(sourceSymbol1, new TestingColumnHandle("col"))), planBuilder.values(new PlanNodeId("valuesNode"), sourceSymbol2))), noLookup(), node -> {
        if (node instanceof TableScanNode) {
            return sourceStatsEstimate1;
        }
        if (node instanceof ValuesNode) {
            return sourceStatsEstimate2;
        }
        return PlanNodeStatsEstimate.unknown();
    }, planBuilder.getTypes()), 270.0);
    // join node
    assertEquals(getSourceTablesSizeInBytes(planBuilder.join(INNER, planBuilder.values(sourceSymbol1), planBuilder.values(sourceSymbol2)), noLookup(), node -> sourceStatsEstimate1, planBuilder.getTypes()), NaN);
}
Also used : PARTITIONED(io.trino.sql.planner.plan.JoinNode.DistributionType.PARTITIONED) INNER(io.trino.sql.planner.plan.JoinNode.Type.INNER) VarcharType.createUnboundedVarcharType(io.trino.spi.type.VarcharType.createUnboundedVarcharType) Assert.assertEquals(org.testng.Assert.assertEquals) Test(org.testng.annotations.Test) PlanMatchPattern.filter(io.trino.sql.planner.assertions.PlanMatchPattern.filter) REPLICATED(io.trino.sql.planner.plan.JoinNode.DistributionType.REPLICATED) Lookup.noLookup(io.trino.sql.planner.iterative.Lookup.noLookup) VarcharType(io.trino.spi.type.VarcharType) LEFT(io.trino.sql.planner.plan.JoinNode.Type.LEFT) RuleAssert(io.trino.sql.planner.iterative.rule.test.RuleAssert) Type(io.trino.sql.planner.plan.JoinNode.Type) PlanBuilder.expressions(io.trino.sql.planner.iterative.rule.test.PlanBuilder.expressions) ImmutableList(com.google.common.collect.ImmutableList) NaN(java.lang.Double.NaN) DistributionType(io.trino.sql.planner.plan.JoinNode.DistributionType) PlanNodeId(io.trino.sql.planner.plan.PlanNodeId) PlanBuilder(io.trino.sql.planner.iterative.rule.test.PlanBuilder) PlanMatchPattern.equiJoinClause(io.trino.sql.planner.assertions.PlanMatchPattern.equiJoinClause) JoinNode(io.trino.sql.planner.plan.JoinNode) TableScanNode(io.trino.sql.planner.plan.TableScanNode) PlanMatchPattern.join(io.trino.sql.planner.assertions.PlanMatchPattern.join) PlanNodeStatsEstimate(io.trino.cost.PlanNodeStatsEstimate) JOIN_MAX_BROADCAST_TABLE_SIZE(io.trino.SystemSessionProperties.JOIN_MAX_BROADCAST_TABLE_SIZE) TaskCountEstimator(io.trino.cost.TaskCountEstimator) Symbol(io.trino.sql.planner.Symbol) AfterClass(org.testng.annotations.AfterClass) SymbolStatsEstimate(io.trino.cost.SymbolStatsEstimate) RuleTester.defaultRuleTester(io.trino.sql.planner.iterative.rule.test.RuleTester.defaultRuleTester) ImmutableMap(com.google.common.collect.ImmutableMap) BeforeClass(org.testng.annotations.BeforeClass) FULL(io.trino.sql.planner.plan.JoinNode.Type.FULL) RuleTester(io.trino.sql.planner.iterative.rule.test.RuleTester) PlanMatchPattern.values(io.trino.sql.planner.assertions.PlanMatchPattern.values) TRUE_LITERAL(io.trino.sql.tree.BooleanLiteral.TRUE_LITERAL) JoinDistributionType(io.trino.sql.planner.OptimizerConfig.JoinDistributionType) DetermineJoinDistributionType.getSourceTablesSizeInBytes(io.trino.sql.planner.iterative.rule.DetermineJoinDistributionType.getSourceTablesSizeInBytes) CostComparator(io.trino.cost.CostComparator) PlanMatchPattern.enforceSingleRow(io.trino.sql.planner.assertions.PlanMatchPattern.enforceSingleRow) BIGINT(io.trino.spi.type.BigintType.BIGINT) RIGHT(io.trino.sql.planner.plan.JoinNode.Type.RIGHT) JOIN_DISTRIBUTION_TYPE(io.trino.SystemSessionProperties.JOIN_DISTRIBUTION_TYPE) ImmutableListMultimap(com.google.common.collect.ImmutableListMultimap) Optional(java.util.Optional) ValuesNode(io.trino.sql.planner.plan.ValuesNode) TestingColumnHandle(io.trino.testing.TestingMetadata.TestingColumnHandle) PlanBuilder.expression(io.trino.sql.planner.iterative.rule.test.PlanBuilder.expression) PlanNodeIdAllocator(io.trino.sql.planner.PlanNodeIdAllocator) PlanNodeId(io.trino.sql.planner.plan.PlanNodeId) TestingColumnHandle(io.trino.testing.TestingMetadata.TestingColumnHandle) ValuesNode(io.trino.sql.planner.plan.ValuesNode) TableScanNode(io.trino.sql.planner.plan.TableScanNode) PlanNodeIdAllocator(io.trino.sql.planner.PlanNodeIdAllocator) PlanNodeStatsEstimate(io.trino.cost.PlanNodeStatsEstimate) Symbol(io.trino.sql.planner.Symbol) PlanBuilder(io.trino.sql.planner.iterative.rule.test.PlanBuilder) Test(org.testng.annotations.Test)

Example 20 with TableScanNode

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

the class RemoveRedundantPredicateAboveTableScan method apply.

@Override
public Result apply(FilterNode filterNode, Captures captures, Context context) {
    Session session = context.getSession();
    TableScanNode node = captures.get(TABLE_SCAN);
    Expression predicate = filterNode.getPredicate();
    Expression deterministicPredicate = filterDeterministicConjuncts(plannerContext.getMetadata(), predicate);
    Expression nonDeterministicPredicate = filterNonDeterministicConjuncts(plannerContext.getMetadata(), predicate);
    ExtractionResult decomposedPredicate = getFullyExtractedPredicates(session, deterministicPredicate, context.getSymbolAllocator().getTypes());
    if (decomposedPredicate.getTupleDomain().isAll()) {
        // no conjunct could be fully converted to tuple domain
        return Result.empty();
    }
    TupleDomain<ColumnHandle> predicateDomain = decomposedPredicate.getTupleDomain().transformKeys(node.getAssignments()::get);
    if (predicateDomain.isNone()) {
        // to turn the subtree into a Values node
        return Result.ofPlanNode(new ValuesNode(node.getId(), node.getOutputSymbols(), ImmutableList.of()));
    }
    if (node.getEnforcedConstraint().isNone()) {
        // table scans with none domain should be converted to ValuesNode
        return Result.ofPlanNode(new ValuesNode(node.getId(), node.getOutputSymbols(), ImmutableList.of()));
    }
    // is not NONE
    Map<ColumnHandle, Domain> enforcedColumnDomains = node.getEnforcedConstraint().getDomains().orElseThrow();
    TupleDomain<ColumnHandle> unenforcedDomain = predicateDomain.transformDomains((columnHandle, predicateColumnDomain) -> {
        Type type = predicateColumnDomain.getType();
        Domain enforcedColumnDomain = Optional.ofNullable(enforcedColumnDomains.get(columnHandle)).orElseGet(() -> Domain.all(type));
        if (predicateColumnDomain.contains(enforcedColumnDomain)) {
            // full enforced
            return Domain.all(type);
        }
        return predicateColumnDomain.intersect(enforcedColumnDomain);
    });
    if (unenforcedDomain.equals(predicateDomain)) {
        // no change in filter predicate
        return Result.empty();
    }
    Map<ColumnHandle, Symbol> assignments = ImmutableBiMap.copyOf(node.getAssignments()).inverse();
    Expression resultingPredicate = createResultingPredicate(plannerContext, session, context.getSymbolAllocator(), typeAnalyzer, // Dynamic filters are included in decomposedPredicate.getRemainingExpression()
    TRUE_LITERAL, new DomainTranslator(plannerContext).toPredicate(session, unenforcedDomain.transformKeys(assignments::get)), nonDeterministicPredicate, decomposedPredicate.getRemainingExpression());
    if (!TRUE_LITERAL.equals(resultingPredicate)) {
        return Result.ofPlanNode(new FilterNode(context.getIdAllocator().getNextId(), node, resultingPredicate));
    }
    return Result.ofPlanNode(node);
}
Also used : ColumnHandle(io.trino.spi.connector.ColumnHandle) ValuesNode(io.trino.sql.planner.plan.ValuesNode) Symbol(io.trino.sql.planner.Symbol) FilterNode(io.trino.sql.planner.plan.FilterNode) Type(io.trino.spi.type.Type) TableScanNode(io.trino.sql.planner.plan.TableScanNode) Expression(io.trino.sql.tree.Expression) DomainTranslator(io.trino.sql.planner.DomainTranslator) ExtractionResult(io.trino.sql.planner.DomainTranslator.ExtractionResult) Domain(io.trino.spi.predicate.Domain) TupleDomain(io.trino.spi.predicate.TupleDomain) Session(io.trino.Session)

Aggregations

TableScanNode (io.trino.sql.planner.plan.TableScanNode)58 Test (org.testng.annotations.Test)34 Symbol (io.trino.sql.planner.Symbol)30 JoinNode (io.trino.sql.planner.plan.JoinNode)26 ColumnHandle (io.trino.spi.connector.ColumnHandle)24 PlanNode (io.trino.sql.planner.plan.PlanNode)21 Type (io.trino.spi.type.Type)18 FilterNode (io.trino.sql.planner.plan.FilterNode)17 PlanNodeId (io.trino.sql.planner.plan.PlanNodeId)17 Expression (io.trino.sql.tree.Expression)17 ImmutableList (com.google.common.collect.ImmutableList)14 TableHandle (io.trino.metadata.TableHandle)14 Session (io.trino.Session)13 TypeSignatureTranslator.toSqlType (io.trino.sql.analyzer.TypeSignatureTranslator.toSqlType)13 ComparisonExpression (io.trino.sql.tree.ComparisonExpression)13 ImmutableMap (com.google.common.collect.ImmutableMap)12 TestingColumnHandle (io.trino.testing.TestingMetadata.TestingColumnHandle)12 Optional (java.util.Optional)11 ImmutableList.toImmutableList (com.google.common.collect.ImmutableList.toImmutableList)10 TupleDomain (io.trino.spi.predicate.TupleDomain)10