Search in sources :

Example 1 with OrderingScheme

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

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

the class TestReplaceWindowWithRowNumber method testDoNotFire.

@Test
public void testDoNotFire() {
    ResolvedFunction rank = tester().getMetadata().resolveFunction(tester().getSession(), QualifiedName.of("rank"), fromTypes());
    tester().assertThat(new ReplaceWindowWithRowNumber(tester().getMetadata())).on(p -> {
        Symbol a = p.symbol("a");
        Symbol rank1 = p.symbol("rank_1");
        return p.window(new WindowNode.Specification(ImmutableList.of(a), Optional.empty()), ImmutableMap.of(rank1, newWindowNodeFunction(rank)), p.values(a));
    }).doesNotFire();
    ResolvedFunction rowNumber = tester().getMetadata().resolveFunction(tester().getSession(), QualifiedName.of("row_number"), fromTypes());
    tester().assertThat(new ReplaceWindowWithRowNumber(tester().getMetadata())).on(p -> {
        Symbol a = p.symbol("a");
        Symbol rowNumber1 = p.symbol("row_number_1");
        Symbol rank1 = p.symbol("rank_1");
        return p.window(new WindowNode.Specification(ImmutableList.of(a), Optional.empty()), ImmutableMap.of(rowNumber1, newWindowNodeFunction(rowNumber), rank1, newWindowNodeFunction(rank)), p.values(a));
    }).doesNotFire();
    tester().assertThat(new ReplaceWindowWithRowNumber(tester().getMetadata())).on(p -> {
        Symbol a = p.symbol("a");
        OrderingScheme orderingScheme = new OrderingScheme(ImmutableList.of(a), ImmutableMap.of(a, SortOrder.ASC_NULLS_FIRST));
        Symbol rowNumber1 = p.symbol("row_number_1");
        return p.window(new WindowNode.Specification(ImmutableList.of(a), Optional.of(orderingScheme)), ImmutableMap.of(rowNumber1, newWindowNodeFunction(rowNumber)), p.values(a));
    }).doesNotFire();
}
Also used : Symbol(io.trino.sql.planner.Symbol) ImmutableMap(com.google.common.collect.ImmutableMap) BaseRuleTest(io.trino.sql.planner.iterative.rule.test.BaseRuleTest) ResolvedFunction(io.trino.metadata.ResolvedFunction) TypeSignatureProvider.fromTypes(io.trino.sql.analyzer.TypeSignatureProvider.fromTypes) Test(org.testng.annotations.Test) PlanMatchPattern.values(io.trino.sql.planner.assertions.PlanMatchPattern.values) OrderingScheme(io.trino.sql.planner.OrderingScheme) DEFAULT_FRAME(io.trino.sql.planner.plan.WindowNode.Frame.DEFAULT_FRAME) SortOrder(io.trino.spi.connector.SortOrder) QualifiedName(io.trino.sql.tree.QualifiedName) ImmutableList(com.google.common.collect.ImmutableList) Optional(java.util.Optional) WindowNode(io.trino.sql.planner.plan.WindowNode) PlanMatchPattern.rowNumber(io.trino.sql.planner.assertions.PlanMatchPattern.rowNumber) OrderingScheme(io.trino.sql.planner.OrderingScheme) ResolvedFunction(io.trino.metadata.ResolvedFunction) Symbol(io.trino.sql.planner.Symbol) BaseRuleTest(io.trino.sql.planner.iterative.rule.test.BaseRuleTest) Test(org.testng.annotations.Test)

Example 3 with OrderingScheme

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

the class TestPushdownLimitIntoWindow method testConvertToTopNRowNumber.

@Test
public void testConvertToTopNRowNumber() {
    ResolvedFunction ranking = tester().getMetadata().resolveFunction(tester().getSession(), QualifiedName.of("row_number"), fromTypes());
    tester().assertThat(new PushdownLimitIntoWindow()).on(p -> {
        Symbol a = p.symbol("a");
        Symbol rowNumberSymbol = p.symbol("row_number_1");
        OrderingScheme orderingScheme = new OrderingScheme(ImmutableList.of(a), ImmutableMap.of(a, SortOrder.ASC_NULLS_FIRST));
        return p.limit(3, p.window(new WindowNode.Specification(ImmutableList.of(), Optional.of(orderingScheme)), ImmutableMap.of(rowNumberSymbol, newWindowNodeFunction(ranking, a)), p.values(a)));
    }).matches(topNRanking(pattern -> pattern.specification(ImmutableList.of(), ImmutableList.of("a"), ImmutableMap.of("a", SortOrder.ASC_NULLS_FIRST)).maxRankingPerPartition(3).partial(false), values("a")));
}
Also used : Symbol(io.trino.sql.planner.Symbol) ImmutableMap(com.google.common.collect.ImmutableMap) BaseRuleTest(io.trino.sql.planner.iterative.rule.test.BaseRuleTest) PlanMatchPattern.topNRanking(io.trino.sql.planner.assertions.PlanMatchPattern.topNRanking) ResolvedFunction(io.trino.metadata.ResolvedFunction) TypeSignatureProvider.fromTypes(io.trino.sql.analyzer.TypeSignatureProvider.fromTypes) Test(org.testng.annotations.Test) PlanMatchPattern.values(io.trino.sql.planner.assertions.PlanMatchPattern.values) OrderingScheme(io.trino.sql.planner.OrderingScheme) DEFAULT_FRAME(io.trino.sql.planner.plan.WindowNode.Frame.DEFAULT_FRAME) SortOrder(io.trino.spi.connector.SortOrder) QualifiedName(io.trino.sql.tree.QualifiedName) PlanMatchPattern.limit(io.trino.sql.planner.assertions.PlanMatchPattern.limit) ImmutableList(com.google.common.collect.ImmutableList) Optional(java.util.Optional) WindowNode(io.trino.sql.planner.plan.WindowNode) OrderingScheme(io.trino.sql.planner.OrderingScheme) WindowNode(io.trino.sql.planner.plan.WindowNode) ResolvedFunction(io.trino.metadata.ResolvedFunction) Symbol(io.trino.sql.planner.Symbol) BaseRuleTest(io.trino.sql.planner.iterative.rule.test.BaseRuleTest) Test(org.testng.annotations.Test)

Example 4 with OrderingScheme

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

the class TestPushdownLimitIntoWindow method assertLimitAboveWindow.

private void assertLimitAboveWindow(String rankingFunctionName) {
    ResolvedFunction ranking = tester().getMetadata().resolveFunction(tester().getSession(), QualifiedName.of(rankingFunctionName), fromTypes());
    tester().assertThat(new PushdownLimitIntoWindow()).on(p -> {
        Symbol a = p.symbol("a");
        Symbol rowNumberSymbol = p.symbol("row_number_1");
        OrderingScheme orderingScheme = new OrderingScheme(ImmutableList.of(a), ImmutableMap.of(a, SortOrder.ASC_NULLS_FIRST));
        return p.limit(3, p.window(new WindowNode.Specification(ImmutableList.of(a), Optional.of(orderingScheme)), ImmutableMap.of(rowNumberSymbol, newWindowNodeFunction(ranking, a)), p.values(a)));
    }).matches(limit(3, topNRanking(pattern -> pattern.specification(ImmutableList.of("a"), ImmutableList.of("a"), ImmutableMap.of("a", SortOrder.ASC_NULLS_FIRST)).maxRankingPerPartition(3).partial(false), values("a"))));
}
Also used : Symbol(io.trino.sql.planner.Symbol) ImmutableMap(com.google.common.collect.ImmutableMap) BaseRuleTest(io.trino.sql.planner.iterative.rule.test.BaseRuleTest) PlanMatchPattern.topNRanking(io.trino.sql.planner.assertions.PlanMatchPattern.topNRanking) ResolvedFunction(io.trino.metadata.ResolvedFunction) TypeSignatureProvider.fromTypes(io.trino.sql.analyzer.TypeSignatureProvider.fromTypes) Test(org.testng.annotations.Test) PlanMatchPattern.values(io.trino.sql.planner.assertions.PlanMatchPattern.values) OrderingScheme(io.trino.sql.planner.OrderingScheme) DEFAULT_FRAME(io.trino.sql.planner.plan.WindowNode.Frame.DEFAULT_FRAME) SortOrder(io.trino.spi.connector.SortOrder) QualifiedName(io.trino.sql.tree.QualifiedName) PlanMatchPattern.limit(io.trino.sql.planner.assertions.PlanMatchPattern.limit) ImmutableList(com.google.common.collect.ImmutableList) Optional(java.util.Optional) WindowNode(io.trino.sql.planner.plan.WindowNode) OrderingScheme(io.trino.sql.planner.OrderingScheme) WindowNode(io.trino.sql.planner.plan.WindowNode) ResolvedFunction(io.trino.metadata.ResolvedFunction) Symbol(io.trino.sql.planner.Symbol)

Example 5 with OrderingScheme

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

the class TestPushdownLimitIntoWindow method testLimitWithPreSortedInputs.

@Test
public void testLimitWithPreSortedInputs() {
    // We can push Limit with pre-sorted inputs into WindowNode if ordering scheme is satisfied
    // We don't do it currently to avoid relying on LocalProperties outside of AddExchanges/AddLocalExchanges
    ResolvedFunction ranking = tester().getMetadata().resolveFunction(tester().getSession(), QualifiedName.of("row_number"), fromTypes());
    tester().assertThat(new PushdownLimitIntoWindow()).on(p -> {
        Symbol a = p.symbol("a");
        Symbol rowNumberSymbol = p.symbol("row_number_1");
        OrderingScheme orderingScheme = new OrderingScheme(ImmutableList.of(a), ImmutableMap.of(a, SortOrder.ASC_NULLS_FIRST));
        return p.limit(3, false, ImmutableList.of(a), p.window(new WindowNode.Specification(ImmutableList.of(), Optional.of(orderingScheme)), ImmutableMap.of(rowNumberSymbol, newWindowNodeFunction(ranking, a)), p.values(a)));
    }).doesNotFire();
}
Also used : Symbol(io.trino.sql.planner.Symbol) ImmutableMap(com.google.common.collect.ImmutableMap) BaseRuleTest(io.trino.sql.planner.iterative.rule.test.BaseRuleTest) PlanMatchPattern.topNRanking(io.trino.sql.planner.assertions.PlanMatchPattern.topNRanking) ResolvedFunction(io.trino.metadata.ResolvedFunction) TypeSignatureProvider.fromTypes(io.trino.sql.analyzer.TypeSignatureProvider.fromTypes) Test(org.testng.annotations.Test) PlanMatchPattern.values(io.trino.sql.planner.assertions.PlanMatchPattern.values) OrderingScheme(io.trino.sql.planner.OrderingScheme) DEFAULT_FRAME(io.trino.sql.planner.plan.WindowNode.Frame.DEFAULT_FRAME) SortOrder(io.trino.spi.connector.SortOrder) QualifiedName(io.trino.sql.tree.QualifiedName) PlanMatchPattern.limit(io.trino.sql.planner.assertions.PlanMatchPattern.limit) ImmutableList(com.google.common.collect.ImmutableList) Optional(java.util.Optional) WindowNode(io.trino.sql.planner.plan.WindowNode) OrderingScheme(io.trino.sql.planner.OrderingScheme) WindowNode(io.trino.sql.planner.plan.WindowNode) ResolvedFunction(io.trino.metadata.ResolvedFunction) Symbol(io.trino.sql.planner.Symbol) BaseRuleTest(io.trino.sql.planner.iterative.rule.test.BaseRuleTest) Test(org.testng.annotations.Test)

Aggregations

OrderingScheme (io.trino.sql.planner.OrderingScheme)18 ImmutableList (com.google.common.collect.ImmutableList)15 Symbol (io.trino.sql.planner.Symbol)15 WindowNode (io.trino.sql.planner.plan.WindowNode)13 ImmutableMap (com.google.common.collect.ImmutableMap)11 ResolvedFunction (io.trino.metadata.ResolvedFunction)10 QualifiedName (io.trino.sql.tree.QualifiedName)10 Optional (java.util.Optional)10 Test (org.testng.annotations.Test)10 SortOrder (io.trino.spi.connector.SortOrder)9 TypeSignatureProvider.fromTypes (io.trino.sql.analyzer.TypeSignatureProvider.fromTypes)9 PlanMatchPattern.values (io.trino.sql.planner.assertions.PlanMatchPattern.values)9 BaseRuleTest (io.trino.sql.planner.iterative.rule.test.BaseRuleTest)9 DEFAULT_FRAME (io.trino.sql.planner.plan.WindowNode.Frame.DEFAULT_FRAME)9 PlanMatchPattern.topNRanking (io.trino.sql.planner.assertions.PlanMatchPattern.topNRanking)7 ImmutableMap.toImmutableMap (com.google.common.collect.ImmutableMap.toImmutableMap)5 Assignments (io.trino.sql.planner.plan.Assignments)5 SymbolReference (io.trino.sql.tree.SymbolReference)5 ImmutableList.toImmutableList (com.google.common.collect.ImmutableList.toImmutableList)4 BIGINT (io.trino.spi.type.BigintType.BIGINT)4