Search in sources :

Example 1 with RankingType

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

the class PushdownFilterIntoWindow method apply.

@Override
public Result apply(FilterNode node, Captures captures, Context context) {
    Session session = context.getSession();
    TypeProvider types = context.getSymbolAllocator().getTypes();
    WindowNode windowNode = captures.get(childCapture);
    DomainTranslator.ExtractionResult extractionResult = DomainTranslator.getExtractionResult(plannerContext, session, node.getPredicate(), types);
    TupleDomain<Symbol> tupleDomain = extractionResult.getTupleDomain();
    Optional<RankingType> rankingType = toTopNRankingType(windowNode);
    Symbol rankingSymbol = getOnlyElement(windowNode.getWindowFunctions().keySet());
    OptionalInt upperBound = extractUpperBound(tupleDomain, rankingSymbol);
    if (upperBound.isEmpty()) {
        return Result.empty();
    }
    if (upperBound.getAsInt() <= 0) {
        return Result.ofPlanNode(new ValuesNode(node.getId(), node.getOutputSymbols(), ImmutableList.of()));
    }
    TopNRankingNode newSource = new TopNRankingNode(windowNode.getId(), windowNode.getSource(), windowNode.getSpecification(), rankingType.get(), rankingSymbol, upperBound.getAsInt(), false, Optional.empty());
    if (!allRowNumberValuesInDomain(tupleDomain, rankingSymbol, upperBound.getAsInt())) {
        return Result.ofPlanNode(new FilterNode(node.getId(), newSource, node.getPredicate()));
    }
    // Remove the row number domain because it is absorbed into the node
    TupleDomain<Symbol> newTupleDomain = tupleDomain.filter((symbol, domain) -> !symbol.equals(rankingSymbol));
    Expression newPredicate = ExpressionUtils.combineConjuncts(plannerContext.getMetadata(), extractionResult.getRemainingExpression(), new DomainTranslator(plannerContext).toPredicate(session, newTupleDomain));
    if (newPredicate.equals(BooleanLiteral.TRUE_LITERAL)) {
        return Result.ofPlanNode(newSource);
    }
    return Result.ofPlanNode(new FilterNode(node.getId(), newSource, newPredicate));
}
Also used : WindowNode(io.trino.sql.planner.plan.WindowNode) Util.toTopNRankingType(io.trino.sql.planner.iterative.rule.Util.toTopNRankingType) RankingType(io.trino.sql.planner.plan.TopNRankingNode.RankingType) ValuesNode(io.trino.sql.planner.plan.ValuesNode) Symbol(io.trino.sql.planner.Symbol) FilterNode(io.trino.sql.planner.plan.FilterNode) TypeProvider(io.trino.sql.planner.TypeProvider) OptionalInt(java.util.OptionalInt) TopNRankingNode(io.trino.sql.planner.plan.TopNRankingNode) Expression(io.trino.sql.tree.Expression) DomainTranslator(io.trino.sql.planner.DomainTranslator) Session(io.trino.Session)

Example 2 with RankingType

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

the class TestWindowFilterPushDown method assertFilterAboveWindow.

private void assertFilterAboveWindow(String rankingFunction, RankingType rankingType) {
    @Language("SQL") String sql = format("SELECT * FROM " + "(SELECT %s() OVER (PARTITION BY suppkey ORDER BY orderkey) partition_ranking FROM lineitem) " + "WHERE partition_ranking < 10", rankingFunction);
    assertPlanWithSession(sql, optimizeTopNRanking(true), true, anyTree(anyNot(FilterNode.class, topNRanking(pattern -> pattern.rankingType(rankingType).maxRankingPerPartition(9), anyTree(tableScan("lineitem"))))));
    assertPlanWithSession(sql, optimizeTopNRanking(false), true, anyTree(node(FilterNode.class, anyTree(node(WindowNode.class, anyTree(tableScan("lineitem")))))));
    // remove subplan if predicate on row number symbol can't be satisfied
    assertPlanWithSession(format("SELECT * FROM (SELECT name, %s() OVER(ORDER BY name) FROM nation) t(name, ranking) WHERE ranking < 0", rankingFunction), optimizeTopNRanking(true), true, output(ImmutableList.of("name", "ranking"), values("name", "ranking")));
    // optimize to TopNRanking on the basis of predicate; remove filter because predicate is satisfied
    assertPlanWithSession(format("SELECT * FROM (SELECT name, %s() OVER(ORDER BY name) FROM nation) t(name, ranking) WHERE ranking > 0 AND ranking < 2", rankingFunction), optimizeTopNRanking(true), true, output(ImmutableList.of("name", "ranking"), topNRanking(pattern -> pattern.rankingType(rankingType).maxRankingPerPartition(1).specification(ImmutableList.of(), ImmutableList.of("name"), ImmutableMap.of("name", ASC_NULLS_LAST)), any(tableScan("nation", ImmutableMap.of("name", "name")))).withAlias("ranking", new TopNRankingSymbolMatcher())));
    // optimize to TopNRanking on the basis of predicate; remove filter because predicate is satisfied
    assertPlanWithSession(format("SELECT * FROM (SELECT name, %s() OVER(ORDER BY name) FROM nation) t(name, ranking) WHERE ranking <= 1", rankingFunction), optimizeTopNRanking(true), true, output(ImmutableList.of("name", "ranking"), topNRanking(pattern -> pattern.rankingType(rankingType).maxRankingPerPartition(1).specification(ImmutableList.of(), ImmutableList.of("name"), ImmutableMap.of("name", ASC_NULLS_LAST)), any(tableScan("nation", ImmutableMap.of("name", "name")))).withAlias("ranking", new TopNRankingSymbolMatcher())));
    // optimize to TopNRanking on the basis of predicate; remove filter because predicate is satisfied
    assertPlanWithSession(format("SELECT * FROM (SELECT name, %s() OVER(ORDER BY name) FROM nation) t(name, ranking) WHERE ranking <= 1 AND ranking > -10", rankingFunction), optimizeTopNRanking(true), true, output(ImmutableList.of("name", "ranking"), topNRanking(pattern -> pattern.rankingType(rankingType).maxRankingPerPartition(1).specification(ImmutableList.of(), ImmutableList.of("name"), ImmutableMap.of("name", ASC_NULLS_LAST)), any(tableScan("nation", ImmutableMap.of("name", "name")))).withAlias("ranking", new TopNRankingSymbolMatcher())));
    // optimize to TopNRanking on the basis of predicate; cannot remove filter because predicate is not satisfied
    assertPlanWithSession(format("SELECT * FROM (SELECT name, %s() OVER(ORDER BY name) FROM nation) t(name, ranking) WHERE ranking > 1 AND ranking < 3", rankingFunction), optimizeTopNRanking(true), true, output(ImmutableList.of("name", "ranking"), filter("(ranking > BIGINT '1') AND (ranking < BIGINT '3')", topNRanking(pattern -> pattern.rankingType(rankingType).maxRankingPerPartition(2).specification(ImmutableList.of(), ImmutableList.of("name"), ImmutableMap.of("name", ASC_NULLS_LAST)), any(tableScan("nation", ImmutableMap.of("name", "name")))).withAlias("ranking", new TopNRankingSymbolMatcher()))));
}
Also used : ROW_NUMBER(io.trino.sql.planner.plan.TopNRankingNode.RankingType.ROW_NUMBER) PlanMatchPattern.any(io.trino.sql.planner.assertions.PlanMatchPattern.any) TopNRankingSymbolMatcher(io.trino.sql.planner.assertions.TopNRankingSymbolMatcher) Test(org.testng.annotations.Test) PlanMatchPattern.filter(io.trino.sql.planner.assertions.PlanMatchPattern.filter) FilterNode(io.trino.sql.planner.plan.FilterNode) PlanMatchPattern.limit(io.trino.sql.planner.assertions.PlanMatchPattern.limit) ImmutableList(com.google.common.collect.ImmutableList) BasePlanTest(io.trino.sql.planner.assertions.BasePlanTest) RowNumberSymbolMatcher(io.trino.sql.planner.assertions.RowNumberSymbolMatcher) ImmutableMap(com.google.common.collect.ImmutableMap) Language(org.intellij.lang.annotations.Language) PlanMatchPattern.topNRanking(io.trino.sql.planner.assertions.PlanMatchPattern.topNRanking) RANK(io.trino.sql.planner.plan.TopNRankingNode.RankingType.RANK) PlanMatchPattern.values(io.trino.sql.planner.assertions.PlanMatchPattern.values) String.format(java.lang.String.format) OPTIMIZE_TOP_N_RANKING(io.trino.SystemSessionProperties.OPTIMIZE_TOP_N_RANKING) PlanMatchPattern.node(io.trino.sql.planner.assertions.PlanMatchPattern.node) ASC_NULLS_LAST(io.trino.spi.connector.SortOrder.ASC_NULLS_LAST) PlanMatchPattern.anyTree(io.trino.sql.planner.assertions.PlanMatchPattern.anyTree) PlanMatchPattern.project(io.trino.sql.planner.assertions.PlanMatchPattern.project) RankingType(io.trino.sql.planner.plan.TopNRankingNode.RankingType) Optional(java.util.Optional) WindowNode(io.trino.sql.planner.plan.WindowNode) PlanMatchPattern.output(io.trino.sql.planner.assertions.PlanMatchPattern.output) PlanMatchPattern.rowNumber(io.trino.sql.planner.assertions.PlanMatchPattern.rowNumber) PlanMatchPattern.tableScan(io.trino.sql.planner.assertions.PlanMatchPattern.tableScan) Session(io.trino.Session) PlanMatchPattern.anyNot(io.trino.sql.planner.assertions.PlanMatchPattern.anyNot) TopNRankingSymbolMatcher(io.trino.sql.planner.assertions.TopNRankingSymbolMatcher) Language(org.intellij.lang.annotations.Language)

Example 3 with RankingType

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

the class PushPredicateThroughProjectIntoWindow method apply.

@Override
public Result apply(FilterNode filter, Captures captures, Context context) {
    ProjectNode project = captures.get(PROJECT);
    WindowNode window = captures.get(WINDOW);
    Symbol rankingSymbol = getOnlyElement(window.getWindowFunctions().keySet());
    if (!project.getAssignments().getSymbols().contains(rankingSymbol)) {
        return Result.empty();
    }
    DomainTranslator.ExtractionResult extractionResult = DomainTranslator.getExtractionResult(plannerContext, context.getSession(), filter.getPredicate(), context.getSymbolAllocator().getTypes());
    TupleDomain<Symbol> tupleDomain = extractionResult.getTupleDomain();
    OptionalInt upperBound = extractUpperBound(tupleDomain, rankingSymbol);
    if (upperBound.isEmpty()) {
        return Result.empty();
    }
    if (upperBound.getAsInt() <= 0) {
        return Result.ofPlanNode(new ValuesNode(filter.getId(), filter.getOutputSymbols(), ImmutableList.of()));
    }
    RankingType rankingType = toTopNRankingType(window).orElseThrow();
    project = (ProjectNode) project.replaceChildren(ImmutableList.of(new TopNRankingNode(window.getId(), window.getSource(), window.getSpecification(), rankingType, rankingSymbol, upperBound.getAsInt(), false, Optional.empty())));
    if (!allRankingValuesInDomain(tupleDomain, rankingSymbol, upperBound.getAsInt())) {
        return Result.ofPlanNode(filter.replaceChildren(ImmutableList.of(project)));
    }
    // Remove the ranking domain because it is absorbed into the node
    TupleDomain<Symbol> newTupleDomain = tupleDomain.filter((symbol, domain) -> !symbol.equals(rankingSymbol));
    Expression newPredicate = ExpressionUtils.combineConjuncts(plannerContext.getMetadata(), extractionResult.getRemainingExpression(), new DomainTranslator(plannerContext).toPredicate(context.getSession(), newTupleDomain));
    if (newPredicate.equals(TRUE_LITERAL)) {
        return Result.ofPlanNode(project);
    }
    return Result.ofPlanNode(new FilterNode(filter.getId(), project, newPredicate));
}
Also used : WindowNode(io.trino.sql.planner.plan.WindowNode) ValuesNode(io.trino.sql.planner.plan.ValuesNode) Util.toTopNRankingType(io.trino.sql.planner.iterative.rule.Util.toTopNRankingType) RankingType(io.trino.sql.planner.plan.TopNRankingNode.RankingType) TopNRankingNode(io.trino.sql.planner.plan.TopNRankingNode) Expression(io.trino.sql.tree.Expression) Symbol(io.trino.sql.planner.Symbol) FilterNode(io.trino.sql.planner.plan.FilterNode) DomainTranslator(io.trino.sql.planner.DomainTranslator) ProjectNode(io.trino.sql.planner.plan.ProjectNode) OptionalInt(java.util.OptionalInt)

Example 4 with RankingType

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

the class PushdownLimitIntoWindow method apply.

@Override
public Result apply(LimitNode node, Captures captures, Context context) {
    WindowNode source = captures.get(childCapture);
    Optional<RankingType> rankingType = toTopNRankingType(source);
    int limit = toIntExact(node.getCount());
    TopNRankingNode topNRowNumberNode = new TopNRankingNode(source.getId(), source.getSource(), source.getSpecification(), rankingType.get(), getOnlyElement(source.getWindowFunctions().keySet()), limit, false, Optional.empty());
    if (rankingType.get() == ROW_NUMBER && source.getPartitionBy().isEmpty()) {
        return Result.ofPlanNode(topNRowNumberNode);
    }
    return Result.ofPlanNode(replaceChildren(node, ImmutableList.of(topNRowNumberNode)));
}
Also used : WindowNode(io.trino.sql.planner.plan.WindowNode) Util.toTopNRankingType(io.trino.sql.planner.iterative.rule.Util.toTopNRankingType) RankingType(io.trino.sql.planner.plan.TopNRankingNode.RankingType) TopNRankingNode(io.trino.sql.planner.plan.TopNRankingNode)

Aggregations

RankingType (io.trino.sql.planner.plan.TopNRankingNode.RankingType)4 WindowNode (io.trino.sql.planner.plan.WindowNode)4 Util.toTopNRankingType (io.trino.sql.planner.iterative.rule.Util.toTopNRankingType)3 FilterNode (io.trino.sql.planner.plan.FilterNode)3 TopNRankingNode (io.trino.sql.planner.plan.TopNRankingNode)3 Session (io.trino.Session)2 DomainTranslator (io.trino.sql.planner.DomainTranslator)2 Symbol (io.trino.sql.planner.Symbol)2 ValuesNode (io.trino.sql.planner.plan.ValuesNode)2 Expression (io.trino.sql.tree.Expression)2 OptionalInt (java.util.OptionalInt)2 ImmutableList (com.google.common.collect.ImmutableList)1 ImmutableMap (com.google.common.collect.ImmutableMap)1 OPTIMIZE_TOP_N_RANKING (io.trino.SystemSessionProperties.OPTIMIZE_TOP_N_RANKING)1 ASC_NULLS_LAST (io.trino.spi.connector.SortOrder.ASC_NULLS_LAST)1 TypeProvider (io.trino.sql.planner.TypeProvider)1 BasePlanTest (io.trino.sql.planner.assertions.BasePlanTest)1 PlanMatchPattern.any (io.trino.sql.planner.assertions.PlanMatchPattern.any)1 PlanMatchPattern.anyNot (io.trino.sql.planner.assertions.PlanMatchPattern.anyNot)1 PlanMatchPattern.anyTree (io.trino.sql.planner.assertions.PlanMatchPattern.anyTree)1