Search in sources :

Example 1 with Window

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

the class AstBuilder method visitListagg.

/**
 * Returns the corresponding {@link FunctionCall} for the `LISTAGG` primary expression.
 * <p>
 * Although the syntax tree should represent the structure of the original parsed query
 * as closely as possible and any semantic interpretation should be part of the
 * analysis/planning phase, in case of `LISTAGG` aggregation function it is more pragmatic
 * now to create a synthetic {@link FunctionCall} expression during the parsing of the syntax tree.
 *
 * @param context `LISTAGG` expression context
 */
@Override
public Node visitListagg(SqlBaseParser.ListaggContext context) {
    Optional<Window> window = Optional.empty();
    OrderBy orderBy = new OrderBy(visit(context.sortItem(), SortItem.class));
    boolean distinct = isDistinct(context.setQuantifier());
    Expression expression = (Expression) visit(context.expression());
    StringLiteral separator = context.string() == null ? new StringLiteral(getLocation(context), "") : (StringLiteral) (visit(context.string()));
    BooleanLiteral overflowError = new BooleanLiteral(getLocation(context), "true");
    StringLiteral overflowFiller = new StringLiteral(getLocation(context), "...");
    BooleanLiteral showOverflowEntryCount = new BooleanLiteral(getLocation(context), "false");
    SqlBaseParser.ListAggOverflowBehaviorContext overflowBehavior = context.listAggOverflowBehavior();
    if (overflowBehavior != null) {
        if (overflowBehavior.ERROR() != null) {
            overflowError = new BooleanLiteral(getLocation(context), "true");
        } else if (overflowBehavior.TRUNCATE() != null) {
            overflowError = new BooleanLiteral(getLocation(context), "false");
            if (overflowBehavior.string() != null) {
                overflowFiller = (StringLiteral) (visit(overflowBehavior.string()));
            }
            SqlBaseParser.ListaggCountIndicationContext listaggCountIndicationContext = overflowBehavior.listaggCountIndication();
            if (listaggCountIndicationContext.WITH() != null) {
                showOverflowEntryCount = new BooleanLiteral(getLocation(context), "true");
            } else if (listaggCountIndicationContext.WITHOUT() != null) {
                showOverflowEntryCount = new BooleanLiteral(getLocation(context), "false");
            }
        }
    }
    List<Expression> arguments = ImmutableList.of(expression, separator, overflowError, overflowFiller, showOverflowEntryCount);
    // TODO model this as a ListAgg node in the AST
    return new FunctionCall(Optional.of(getLocation(context)), QualifiedName.of("LISTAGG"), window, Optional.empty(), Optional.of(orderBy), distinct, Optional.empty(), Optional.empty(), arguments);
}
Also used : Window(io.trino.sql.tree.Window) OrderBy(io.trino.sql.tree.OrderBy) BooleanLiteral(io.trino.sql.tree.BooleanLiteral) SortItem(io.trino.sql.tree.SortItem) StringLiteral(io.trino.sql.tree.StringLiteral) 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) FunctionCall(io.trino.sql.tree.FunctionCall)

Example 2 with Window

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

ArithmeticBinaryExpression (io.trino.sql.tree.ArithmeticBinaryExpression)2 ArithmeticUnaryExpression (io.trino.sql.tree.ArithmeticUnaryExpression)2 BindExpression (io.trino.sql.tree.BindExpression)2 CoalesceExpression (io.trino.sql.tree.CoalesceExpression)2 ComparisonExpression (io.trino.sql.tree.ComparisonExpression)2 DereferenceExpression (io.trino.sql.tree.DereferenceExpression)2 Expression (io.trino.sql.tree.Expression)2 FunctionCall (io.trino.sql.tree.FunctionCall)2 IfExpression (io.trino.sql.tree.IfExpression)2 InListExpression (io.trino.sql.tree.InListExpression)2 LambdaExpression (io.trino.sql.tree.LambdaExpression)2 LogicalExpression (io.trino.sql.tree.LogicalExpression)2 NotExpression (io.trino.sql.tree.NotExpression)2 NullIfExpression (io.trino.sql.tree.NullIfExpression)2 OrderBy (io.trino.sql.tree.OrderBy)2 QuantifiedComparisonExpression (io.trino.sql.tree.QuantifiedComparisonExpression)2 SearchedCaseExpression (io.trino.sql.tree.SearchedCaseExpression)2 SimpleCaseExpression (io.trino.sql.tree.SimpleCaseExpression)2 SortItem (io.trino.sql.tree.SortItem)2 SubqueryExpression (io.trino.sql.tree.SubqueryExpression)2