Search in sources :

Example 1 with NullTreatment

use of io.trino.sql.tree.FunctionCall.NullTreatment 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 NullTreatment

use of io.trino.sql.tree.FunctionCall.NullTreatment 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 NullTreatment

use of io.trino.sql.tree.FunctionCall.NullTreatment in project trino by trinodb.

the class AstBuilder method visitFunctionCall.

@Override
public Node visitFunctionCall(SqlBaseParser.FunctionCallContext context) {
    Optional<Expression> filter = visitIfPresent(context.filter(), Expression.class);
    Optional<Window> window = visitIfPresent(context.over(), Window.class);
    Optional<OrderBy> orderBy = Optional.empty();
    if (context.ORDER() != null) {
        orderBy = Optional.of(new OrderBy(visit(context.sortItem(), SortItem.class)));
    }
    QualifiedName name = getQualifiedName(context.qualifiedName());
    boolean distinct = isDistinct(context.setQuantifier());
    SqlBaseParser.NullTreatmentContext nullTreatment = context.nullTreatment();
    SqlBaseParser.ProcessingModeContext processingMode = context.processingMode();
    if (name.toString().equalsIgnoreCase("if")) {
        check(context.expression().size() == 2 || context.expression().size() == 3, "Invalid number of arguments for 'if' function", context);
        check(!window.isPresent(), "OVER clause not valid for 'if' function", context);
        check(!distinct, "DISTINCT not valid for 'if' function", context);
        check(nullTreatment == null, "Null treatment clause not valid for 'if' function", context);
        check(processingMode == null, "Running or final semantics not valid for 'if' function", context);
        check(!filter.isPresent(), "FILTER not valid for 'if' function", context);
        Expression elseExpression = null;
        if (context.expression().size() == 3) {
            elseExpression = (Expression) visit(context.expression(2));
        }
        return new IfExpression(getLocation(context), (Expression) visit(context.expression(0)), (Expression) visit(context.expression(1)), elseExpression);
    }
    if (name.toString().equalsIgnoreCase("nullif")) {
        check(context.expression().size() == 2, "Invalid number of arguments for 'nullif' function", context);
        check(!window.isPresent(), "OVER clause not valid for 'nullif' function", context);
        check(!distinct, "DISTINCT not valid for 'nullif' function", context);
        check(nullTreatment == null, "Null treatment clause not valid for 'nullif' function", context);
        check(processingMode == null, "Running or final semantics not valid for 'nullif' function", context);
        check(!filter.isPresent(), "FILTER not valid for 'nullif' function", context);
        return new NullIfExpression(getLocation(context), (Expression) visit(context.expression(0)), (Expression) visit(context.expression(1)));
    }
    if (name.toString().equalsIgnoreCase("coalesce")) {
        check(context.expression().size() >= 2, "The 'coalesce' function must have at least two arguments", context);
        check(!window.isPresent(), "OVER clause not valid for 'coalesce' function", context);
        check(!distinct, "DISTINCT not valid for 'coalesce' function", context);
        check(nullTreatment == null, "Null treatment clause not valid for 'coalesce' function", context);
        check(processingMode == null, "Running or final semantics not valid for 'coalesce' function", context);
        check(!filter.isPresent(), "FILTER not valid for 'coalesce' function", context);
        return new CoalesceExpression(getLocation(context), visit(context.expression(), Expression.class));
    }
    if (name.toString().equalsIgnoreCase("try")) {
        check(context.expression().size() == 1, "The 'try' function must have exactly one argument", context);
        check(!window.isPresent(), "OVER clause not valid for 'try' function", context);
        check(!distinct, "DISTINCT not valid for 'try' function", context);
        check(nullTreatment == null, "Null treatment clause not valid for 'try' function", context);
        check(processingMode == null, "Running or final semantics not valid for 'try' function", context);
        check(!filter.isPresent(), "FILTER not valid for 'try' function", context);
        return new TryExpression(getLocation(context), (Expression) visit(getOnlyElement(context.expression())));
    }
    if (name.toString().equalsIgnoreCase("format")) {
        check(context.expression().size() >= 2, "The 'format' function must have at least two arguments", context);
        check(!window.isPresent(), "OVER clause not valid for 'format' function", context);
        check(!distinct, "DISTINCT not valid for 'format' function", context);
        check(nullTreatment == null, "Null treatment clause not valid for 'format' function", context);
        check(processingMode == null, "Running or final semantics not valid for 'format' function", context);
        check(!filter.isPresent(), "FILTER not valid for 'format' function", context);
        return new Format(getLocation(context), visit(context.expression(), Expression.class));
    }
    if (name.toString().equalsIgnoreCase("$internal$bind")) {
        check(context.expression().size() >= 1, "The '$internal$bind' function must have at least one arguments", context);
        check(!window.isPresent(), "OVER clause not valid for '$internal$bind' function", context);
        check(!distinct, "DISTINCT not valid for '$internal$bind' function", context);
        check(nullTreatment == null, "Null treatment clause not valid for '$internal$bind' function", context);
        check(processingMode == null, "Running or final semantics not valid for '$internal$bind' function", context);
        check(!filter.isPresent(), "FILTER not valid for '$internal$bind' function", context);
        int numValues = context.expression().size() - 1;
        List<Expression> arguments = context.expression().stream().map(this::visit).map(Expression.class::cast).collect(toImmutableList());
        return new BindExpression(getLocation(context), arguments.subList(0, numValues), arguments.get(numValues));
    }
    Optional<NullTreatment> nulls = Optional.empty();
    if (nullTreatment != null) {
        if (nullTreatment.IGNORE() != null) {
            nulls = Optional.of(NullTreatment.IGNORE);
        } else if (nullTreatment.RESPECT() != null) {
            nulls = Optional.of(NullTreatment.RESPECT);
        }
    }
    Optional<ProcessingMode> mode = Optional.empty();
    if (processingMode != null) {
        if (processingMode.RUNNING() != null) {
            mode = Optional.of(new ProcessingMode(getLocation(processingMode), RUNNING));
        } else if (processingMode.FINAL() != null) {
            mode = Optional.of(new ProcessingMode(getLocation(processingMode), FINAL));
        }
    }
    List<Expression> arguments = visit(context.expression(), Expression.class);
    if (context.label != null) {
        arguments = ImmutableList.of(new DereferenceExpression(getLocation(context.label), (Identifier) visit(context.label)));
    }
    return new FunctionCall(Optional.of(getLocation(context)), name, window, filter, orderBy, distinct, nulls, mode, arguments);
}
Also used : ProcessingMode(io.trino.sql.tree.ProcessingMode) SortItem(io.trino.sql.tree.SortItem) Format(io.trino.sql.tree.Format) ExplainFormat(io.trino.sql.tree.ExplainFormat) FunctionCall(io.trino.sql.tree.FunctionCall) Window(io.trino.sql.tree.Window) OrderBy(io.trino.sql.tree.OrderBy) NullIfExpression(io.trino.sql.tree.NullIfExpression) IfExpression(io.trino.sql.tree.IfExpression) DereferenceExpression(io.trino.sql.tree.DereferenceExpression) QualifiedName(io.trino.sql.tree.QualifiedName) TryExpression(io.trino.sql.tree.TryExpression) NullTreatment(io.trino.sql.tree.FunctionCall.NullTreatment) DereferenceExpression(io.trino.sql.tree.DereferenceExpression) LogicalExpression(io.trino.sql.tree.LogicalExpression) SearchedCaseExpression(io.trino.sql.tree.SearchedCaseExpression) BindExpression(io.trino.sql.tree.BindExpression) CoalesceExpression(io.trino.sql.tree.CoalesceExpression) QuantifiedComparisonExpression(io.trino.sql.tree.QuantifiedComparisonExpression) SimpleCaseExpression(io.trino.sql.tree.SimpleCaseExpression) SubqueryExpression(io.trino.sql.tree.SubqueryExpression) LambdaExpression(io.trino.sql.tree.LambdaExpression) SubscriptExpression(io.trino.sql.tree.SubscriptExpression) NullIfExpression(io.trino.sql.tree.NullIfExpression) ArithmeticUnaryExpression(io.trino.sql.tree.ArithmeticUnaryExpression) InListExpression(io.trino.sql.tree.InListExpression) NotExpression(io.trino.sql.tree.NotExpression) ArithmeticBinaryExpression(io.trino.sql.tree.ArithmeticBinaryExpression) TryExpression(io.trino.sql.tree.TryExpression) ComparisonExpression(io.trino.sql.tree.ComparisonExpression) IfExpression(io.trino.sql.tree.IfExpression) Expression(io.trino.sql.tree.Expression) BindExpression(io.trino.sql.tree.BindExpression) NullIfExpression(io.trino.sql.tree.NullIfExpression) CoalesceExpression(io.trino.sql.tree.CoalesceExpression)

Aggregations

NullTreatment (io.trino.sql.tree.FunctionCall.NullTreatment)3 LambdaExpression (io.trino.sql.tree.LambdaExpression)3 ResolvedFunction (io.trino.metadata.ResolvedFunction)2 PlanBuilder.newPlanBuilder (io.trino.sql.planner.PlanBuilder.newPlanBuilder)2 WindowNode (io.trino.sql.planner.plan.WindowNode)2 ComparisonExpression (io.trino.sql.tree.ComparisonExpression)2 Expression (io.trino.sql.tree.Expression)2 FrameBound (io.trino.sql.tree.FrameBound)2 IfExpression (io.trino.sql.tree.IfExpression)2 WindowFrame (io.trino.sql.tree.WindowFrame)2 Function (java.util.function.Function)2 SelectExpression (io.trino.sql.analyzer.Analysis.SelectExpression)1 PatternRecognitionComponents (io.trino.sql.planner.RelationPlanner.PatternRecognitionComponents)1 PatternRecognitionNode (io.trino.sql.planner.plan.PatternRecognitionNode)1 ArithmeticBinaryExpression (io.trino.sql.tree.ArithmeticBinaryExpression)1 ArithmeticUnaryExpression (io.trino.sql.tree.ArithmeticUnaryExpression)1 BindExpression (io.trino.sql.tree.BindExpression)1 CoalesceExpression (io.trino.sql.tree.CoalesceExpression)1 DereferenceExpression (io.trino.sql.tree.DereferenceExpression)1 ExplainFormat (io.trino.sql.tree.ExplainFormat)1