Search in sources :

Example 1 with WindowFrame

use of io.trino.sql.tree.WindowFrame in project trino by trinodb.

the class QueryPlanner method planWindow.

private PlanBuilder planWindow(PlanBuilder subPlan, FunctionCall windowFunction, ResolvedWindow window, PlanAndMappings coercions, Optional<Symbol> frameStartSymbol, Optional<Symbol> sortKeyCoercedForFrameStartComparison, Optional<Symbol> frameEndSymbol, Optional<Symbol> sortKeyCoercedForFrameEndComparison) {
    WindowFrame.Type frameType = WindowFrame.Type.RANGE;
    FrameBound.Type frameStartType = FrameBound.Type.UNBOUNDED_PRECEDING;
    FrameBound.Type frameEndType = FrameBound.Type.CURRENT_ROW;
    Optional<Expression> frameStartExpression = Optional.empty();
    Optional<Expression> frameEndExpression = Optional.empty();
    if (window.getFrame().isPresent()) {
        WindowFrame frame = window.getFrame().get();
        frameType = frame.getType();
        frameStartType = frame.getStart().getType();
        frameStartExpression = frame.getStart().getValue();
        if (frame.getEnd().isPresent()) {
            frameEndType = frame.getEnd().get().getType();
            frameEndExpression = frame.getEnd().get().getValue();
        }
    }
    WindowNode.Specification specification = planWindowSpecification(window.getPartitionBy(), window.getOrderBy(), coercions::get);
    // Rewrite frame bounds in terms of pre-projected inputs
    WindowNode.Frame frame = new WindowNode.Frame(frameType, frameStartType, frameStartSymbol, sortKeyCoercedForFrameStartComparison, frameEndType, frameEndSymbol, sortKeyCoercedForFrameEndComparison, frameStartExpression, frameEndExpression);
    Symbol newSymbol = symbolAllocator.newSymbol(windowFunction, analysis.getType(windowFunction));
    NullTreatment nullTreatment = windowFunction.getNullTreatment().orElse(NullTreatment.RESPECT);
    WindowNode.Function function = new WindowNode.Function(analysis.getResolvedFunction(windowFunction), windowFunction.getArguments().stream().map(argument -> {
        if (argument instanceof LambdaExpression) {
            return subPlan.rewrite(argument);
        }
        return coercions.get(argument).toSymbolReference();
    }).collect(toImmutableList()), frame, nullTreatment == NullTreatment.IGNORE);
    // create window node
    return new PlanBuilder(subPlan.getTranslations().withAdditionalMappings(ImmutableMap.of(scopeAwareKey(windowFunction, analysis, subPlan.getScope()), newSymbol)), new WindowNode(idAllocator.getNextId(), subPlan.getRoot(), specification, ImmutableMap.of(newSymbol, function), Optional.empty(), ImmutableSet.of(), 0));
}
Also used : WindowNode(io.trino.sql.planner.plan.WindowNode) WindowFrame(io.trino.sql.tree.WindowFrame) FrameBound(io.trino.sql.tree.FrameBound) PlanBuilder.newPlanBuilder(io.trino.sql.planner.PlanBuilder.newPlanBuilder) NullTreatment(io.trino.sql.tree.FunctionCall.NullTreatment) ResolvedFunction(io.trino.metadata.ResolvedFunction) Function(java.util.function.Function) WindowFrame(io.trino.sql.tree.WindowFrame) SelectExpression(io.trino.sql.analyzer.Analysis.SelectExpression) ComparisonExpression(io.trino.sql.tree.ComparisonExpression) IfExpression(io.trino.sql.tree.IfExpression) Expression(io.trino.sql.tree.Expression) LambdaExpression(io.trino.sql.tree.LambdaExpression) LambdaExpression(io.trino.sql.tree.LambdaExpression)

Example 2 with WindowFrame

use of io.trino.sql.tree.WindowFrame in project trino by trinodb.

the class QueryPlanner method planPatternRecognition.

private PlanBuilder planPatternRecognition(PlanBuilder subPlan, FunctionCall windowFunction, ResolvedWindow window, PlanAndMappings coercions, Optional<Symbol> frameEndSymbol) {
    WindowNode.Specification specification = planWindowSpecification(window.getPartitionBy(), window.getOrderBy(), coercions::get);
    // in window frame with pattern recognition, the frame extent is specified as `ROWS BETWEEN CURRENT ROW AND ... `
    WindowFrame frame = window.getFrame().orElseThrow();
    FrameBound frameEnd = frame.getEnd().orElseThrow();
    WindowNode.Frame baseFrame = new WindowNode.Frame(WindowFrame.Type.ROWS, FrameBound.Type.CURRENT_ROW, Optional.empty(), Optional.empty(), frameEnd.getType(), frameEndSymbol, Optional.empty(), Optional.empty(), frameEnd.getValue());
    Symbol newSymbol = symbolAllocator.newSymbol(windowFunction, analysis.getType(windowFunction));
    NullTreatment nullTreatment = windowFunction.getNullTreatment().orElse(NullTreatment.RESPECT);
    WindowNode.Function function = new WindowNode.Function(analysis.getResolvedFunction(windowFunction), windowFunction.getArguments().stream().map(argument -> {
        if (argument instanceof LambdaExpression) {
            return subPlan.rewrite(argument);
        }
        return coercions.get(argument).toSymbolReference();
    }).collect(toImmutableList()), baseFrame, nullTreatment == NullTreatment.IGNORE);
    PatternRecognitionComponents components = new RelationPlanner(analysis, symbolAllocator, idAllocator, lambdaDeclarationToSymbolMap, plannerContext, outerContext, session, recursiveSubqueries).planPatternRecognitionComponents(subPlan::rewrite, frame.getSubsets(), ImmutableList.of(), frame.getAfterMatchSkipTo(), frame.getPatternSearchMode(), frame.getPattern().orElseThrow(), frame.getVariableDefinitions());
    // create pattern recognition node
    return new PlanBuilder(subPlan.getTranslations().withAdditionalMappings(ImmutableMap.of(scopeAwareKey(windowFunction, analysis, subPlan.getScope()), newSymbol)), new PatternRecognitionNode(idAllocator.getNextId(), subPlan.getRoot(), specification, Optional.empty(), ImmutableSet.of(), 0, ImmutableMap.of(newSymbol, function), components.getMeasures(), Optional.of(baseFrame), RowsPerMatch.WINDOW, components.getSkipToLabel(), components.getSkipToPosition(), components.isInitial(), components.getPattern(), components.getSubsets(), components.getVariableDefinitions()));
}
Also used : WindowNode(io.trino.sql.planner.plan.WindowNode) WindowFrame(io.trino.sql.tree.WindowFrame) FrameBound(io.trino.sql.tree.FrameBound) PlanBuilder.newPlanBuilder(io.trino.sql.planner.PlanBuilder.newPlanBuilder) NullTreatment(io.trino.sql.tree.FunctionCall.NullTreatment) ResolvedFunction(io.trino.metadata.ResolvedFunction) Function(java.util.function.Function) PatternRecognitionNode(io.trino.sql.planner.plan.PatternRecognitionNode) WindowFrame(io.trino.sql.tree.WindowFrame) LambdaExpression(io.trino.sql.tree.LambdaExpression) PatternRecognitionComponents(io.trino.sql.planner.RelationPlanner.PatternRecognitionComponents)

Example 3 with WindowFrame

use of io.trino.sql.tree.WindowFrame in project trino by trinodb.

the class QueryPlanner method planPatternRecognition.

private PlanBuilder planPatternRecognition(PlanBuilder subPlan, WindowOperation windowMeasure, ResolvedWindow window, Optional<Symbol> frameEndSymbol) {
    WindowNode.Specification specification = planWindowSpecification(window.getPartitionBy(), window.getOrderBy(), subPlan::translate);
    // in window frame with pattern recognition, the frame extent is specified as `ROWS BETWEEN CURRENT ROW AND ... `
    WindowFrame frame = window.getFrame().orElseThrow();
    FrameBound frameEnd = frame.getEnd().orElseThrow();
    WindowNode.Frame baseFrame = new WindowNode.Frame(WindowFrame.Type.ROWS, FrameBound.Type.CURRENT_ROW, Optional.empty(), Optional.empty(), frameEnd.getType(), frameEndSymbol, Optional.empty(), Optional.empty(), frameEnd.getValue());
    PatternRecognitionComponents components = new RelationPlanner(analysis, symbolAllocator, idAllocator, lambdaDeclarationToSymbolMap, plannerContext, outerContext, session, recursiveSubqueries).planPatternRecognitionComponents(subPlan::rewrite, frame.getSubsets(), ImmutableList.of(analysis.getMeasureDefinition(windowMeasure)), frame.getAfterMatchSkipTo(), frame.getPatternSearchMode(), frame.getPattern().orElseThrow(), frame.getVariableDefinitions());
    Symbol measureSymbol = getOnlyElement(components.getMeasures().keySet());
    // create pattern recognition node
    return new PlanBuilder(subPlan.getTranslations().withAdditionalMappings(ImmutableMap.of(scopeAwareKey(windowMeasure, analysis, subPlan.getScope()), measureSymbol)), new PatternRecognitionNode(idAllocator.getNextId(), subPlan.getRoot(), specification, Optional.empty(), ImmutableSet.of(), 0, ImmutableMap.of(), components.getMeasures(), Optional.of(baseFrame), RowsPerMatch.WINDOW, components.getSkipToLabel(), components.getSkipToPosition(), components.isInitial(), components.getPattern(), components.getSubsets(), components.getVariableDefinitions()));
}
Also used : WindowNode(io.trino.sql.planner.plan.WindowNode) WindowFrame(io.trino.sql.tree.WindowFrame) PatternRecognitionNode(io.trino.sql.planner.plan.PatternRecognitionNode) WindowFrame(io.trino.sql.tree.WindowFrame) FrameBound(io.trino.sql.tree.FrameBound) PatternRecognitionComponents(io.trino.sql.planner.RelationPlanner.PatternRecognitionComponents) PlanBuilder.newPlanBuilder(io.trino.sql.planner.PlanBuilder.newPlanBuilder)

Example 4 with WindowFrame

use of io.trino.sql.tree.WindowFrame in project trino by trinodb.

the class TestSqlParser method testWindowSpecification.

@Test
public void testWindowSpecification() {
    assertExpression("rank() OVER someWindow", new FunctionCall(Optional.empty(), QualifiedName.of("rank"), Optional.of(new WindowReference(new Identifier("someWindow"))), Optional.empty(), Optional.empty(), false, Optional.empty(), Optional.empty(), ImmutableList.of()));
    assertExpression("rank() OVER (someWindow PARTITION BY x ORDER BY y ROWS CURRENT ROW)", new FunctionCall(Optional.empty(), QualifiedName.of("rank"), Optional.of(new WindowSpecification(Optional.of(new Identifier("someWindow")), ImmutableList.of(new Identifier("x")), Optional.of(new OrderBy(ImmutableList.of(new SortItem(new Identifier("y"), ASCENDING, UNDEFINED)))), Optional.of(new WindowFrame(ROWS, new FrameBound(CURRENT_ROW), Optional.empty(), ImmutableList.of(), Optional.empty(), Optional.empty(), Optional.empty(), ImmutableList.of(), ImmutableList.of())))), Optional.empty(), Optional.empty(), false, Optional.empty(), Optional.empty(), ImmutableList.of()));
    assertExpression("rank() OVER (PARTITION BY x ORDER BY y ROWS CURRENT ROW)", new FunctionCall(Optional.empty(), QualifiedName.of("rank"), Optional.of(new WindowSpecification(Optional.empty(), ImmutableList.of(new Identifier("x")), Optional.of(new OrderBy(ImmutableList.of(new SortItem(new Identifier("y"), ASCENDING, UNDEFINED)))), Optional.of(new WindowFrame(ROWS, new FrameBound(CURRENT_ROW), Optional.empty(), ImmutableList.of(), Optional.empty(), Optional.empty(), Optional.empty(), ImmutableList.of(), ImmutableList.of())))), Optional.empty(), Optional.empty(), false, Optional.empty(), Optional.empty(), ImmutableList.of()));
}
Also used : OrderBy(io.trino.sql.tree.OrderBy) SortItem(io.trino.sql.tree.SortItem) QueryUtil.quotedIdentifier(io.trino.sql.QueryUtil.quotedIdentifier) Identifier(io.trino.sql.tree.Identifier) WindowFrame(io.trino.sql.tree.WindowFrame) FrameBound(io.trino.sql.tree.FrameBound) WindowSpecification(io.trino.sql.tree.WindowSpecification) FunctionCall(io.trino.sql.tree.FunctionCall) WindowReference(io.trino.sql.tree.WindowReference) Test(org.junit.jupiter.api.Test)

Example 5 with WindowFrame

use of io.trino.sql.tree.WindowFrame in project trino by trinodb.

the class TestMergeWindows method testMergeDifferentFramesWithDefault.

@Test
public void testMergeDifferentFramesWithDefault() {
    Optional<WindowFrame> frameD = Optional.of(new WindowFrame(WindowFrame.Type.ROWS, new FrameBound(FrameBound.Type.CURRENT_ROW), Optional.of(new FrameBound(FrameBound.Type.UNBOUNDED_FOLLOWING)), ImmutableList.of(), Optional.empty(), Optional.empty(), Optional.empty(), ImmutableList.of(), ImmutableList.of()));
    ExpectedValueProvider<WindowNode.Specification> specificationD = specification(ImmutableList.of(SUPPKEY_ALIAS), ImmutableList.of(ORDERKEY_ALIAS), ImmutableMap.of(ORDERKEY_ALIAS, SortOrder.ASC_NULLS_LAST));
    @Language("SQL") String sql = "SELECT " + "SUM(quantity) OVER (PARTITION BY suppkey ORDER BY orderkey) sum_quantity_C, " + "AVG(quantity) OVER (PARTITION BY suppkey ORDER BY orderkey ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING) avg_quantity_D, " + "SUM(discount) OVER (PARTITION BY suppkey ORDER BY orderkey) sum_discount_C " + "FROM lineitem";
    assertUnitPlan(sql, anyTree(window(windowMatcherBuilder -> windowMatcherBuilder.specification(specificationD).addFunction(functionCall("avg", frameD, ImmutableList.of(QUANTITY_ALIAS))).addFunction(functionCall("sum", UNSPECIFIED_FRAME, ImmutableList.of(DISCOUNT_ALIAS))).addFunction(functionCall("sum", UNSPECIFIED_FRAME, ImmutableList.of(QUANTITY_ALIAS))), LINEITEM_TABLESCAN_DOQS)));
}
Also used : WindowFrame(io.trino.sql.tree.WindowFrame) Language(org.intellij.lang.annotations.Language) FrameBound(io.trino.sql.tree.FrameBound) Test(org.testng.annotations.Test) BasePlanTest(io.trino.sql.planner.assertions.BasePlanTest)

Aggregations

WindowFrame (io.trino.sql.tree.WindowFrame)8 FrameBound (io.trino.sql.tree.FrameBound)7 LambdaExpression (io.trino.sql.tree.LambdaExpression)4 SelectExpression (io.trino.sql.analyzer.Analysis.SelectExpression)3 PlanBuilder.newPlanBuilder (io.trino.sql.planner.PlanBuilder.newPlanBuilder)3 WindowNode (io.trino.sql.planner.plan.WindowNode)3 ComparisonExpression (io.trino.sql.tree.ComparisonExpression)3 Expression (io.trino.sql.tree.Expression)3 IfExpression (io.trino.sql.tree.IfExpression)3 SortItem (io.trino.sql.tree.SortItem)3 ImmutableList (com.google.common.collect.ImmutableList)2 ImmutableList.toImmutableList (com.google.common.collect.ImmutableList.toImmutableList)2 ResolvedFunction (io.trino.metadata.ResolvedFunction)2 ResolvedWindow (io.trino.sql.analyzer.Analysis.ResolvedWindow)2 PatternRecognitionComponents (io.trino.sql.planner.RelationPlanner.PatternRecognitionComponents)2 BasePlanTest (io.trino.sql.planner.assertions.BasePlanTest)2 PatternRecognitionNode (io.trino.sql.planner.plan.PatternRecognitionNode)2 FunctionCall (io.trino.sql.tree.FunctionCall)2 NullTreatment (io.trino.sql.tree.FunctionCall.NullTreatment)2 Function (java.util.function.Function)2