Search in sources :

Example 6 with CoalesceExpression

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

Example 7 with CoalesceExpression

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

the class TestSqlToRowExpressionTranslator method testPossibleExponentialOptimizationTime.

@Test(timeOut = 10_000)
public void testPossibleExponentialOptimizationTime() {
    Expression expression = new LongLiteral("1");
    ImmutableMap.Builder<NodeRef<Expression>, Type> types = ImmutableMap.builder();
    types.put(NodeRef.of(expression), BIGINT);
    for (int i = 0; i < 100; i++) {
        expression = new CoalesceExpression(expression, new LongLiteral("2"));
        types.put(NodeRef.of(expression), BIGINT);
    }
    translateAndOptimize(expression, types.buildOrThrow());
}
Also used : NodeRef(io.trino.sql.tree.NodeRef) DecimalType.createDecimalType(io.trino.spi.type.DecimalType.createDecimalType) Type(io.trino.spi.type.Type) CoalesceExpression(io.trino.sql.tree.CoalesceExpression) RowExpression(io.trino.sql.relational.RowExpression) Expression(io.trino.sql.tree.Expression) LongLiteral(io.trino.sql.tree.LongLiteral) CoalesceExpression(io.trino.sql.tree.CoalesceExpression) ImmutableMap(com.google.common.collect.ImmutableMap) Test(org.testng.annotations.Test)

Example 8 with CoalesceExpression

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

the class RelationPlanner method planJoinUsing.

private RelationPlan planJoinUsing(Join node, RelationPlan left, RelationPlan right) {
    /* Given: l JOIN r USING (k1, ..., kn)

           produces:

            - project
                    coalesce(l.k1, r.k1)
                    ...,
                    coalesce(l.kn, r.kn)
                    l.v1,
                    ...,
                    l.vn,
                    r.v1,
                    ...,
                    r.vn
              - join (l.k1 = r.k1 and ... l.kn = r.kn)
                    - project
                        cast(l.k1 as commonType(l.k1, r.k1))
                        ...
                    - project
                        cast(rl.k1 as commonType(l.k1, r.k1))

            If casts are redundant (due to column type and common type being equal),
            they will be removed by optimization passes.
        */
    List<Identifier> joinColumns = ((JoinUsing) node.getCriteria().orElseThrow()).getColumns();
    Analysis.JoinUsingAnalysis joinAnalysis = analysis.getJoinUsing(node);
    ImmutableList.Builder<JoinNode.EquiJoinClause> clauses = ImmutableList.builder();
    Map<Identifier, Symbol> leftJoinColumns = new HashMap<>();
    Map<Identifier, Symbol> rightJoinColumns = new HashMap<>();
    Assignments.Builder leftCoercions = Assignments.builder();
    Assignments.Builder rightCoercions = Assignments.builder();
    leftCoercions.putIdentities(left.getRoot().getOutputSymbols());
    rightCoercions.putIdentities(right.getRoot().getOutputSymbols());
    for (int i = 0; i < joinColumns.size(); i++) {
        Identifier identifier = joinColumns.get(i);
        Type type = analysis.getType(identifier);
        // compute the coercion for the field on the left to the common supertype of left & right
        Symbol leftOutput = symbolAllocator.newSymbol(identifier, type);
        int leftField = joinAnalysis.getLeftJoinFields().get(i);
        leftCoercions.put(leftOutput, new Cast(left.getSymbol(leftField).toSymbolReference(), toSqlType(type), false, typeCoercion.isTypeOnlyCoercion(left.getDescriptor().getFieldByIndex(leftField).getType(), type)));
        leftJoinColumns.put(identifier, leftOutput);
        // compute the coercion for the field on the right to the common supertype of left & right
        Symbol rightOutput = symbolAllocator.newSymbol(identifier, type);
        int rightField = joinAnalysis.getRightJoinFields().get(i);
        rightCoercions.put(rightOutput, new Cast(right.getSymbol(rightField).toSymbolReference(), toSqlType(type), false, typeCoercion.isTypeOnlyCoercion(right.getDescriptor().getFieldByIndex(rightField).getType(), type)));
        rightJoinColumns.put(identifier, rightOutput);
        clauses.add(new JoinNode.EquiJoinClause(leftOutput, rightOutput));
    }
    ProjectNode leftCoercion = new ProjectNode(idAllocator.getNextId(), left.getRoot(), leftCoercions.build());
    ProjectNode rightCoercion = new ProjectNode(idAllocator.getNextId(), right.getRoot(), rightCoercions.build());
    JoinNode join = new JoinNode(idAllocator.getNextId(), JoinNode.Type.typeConvert(node.getType()), leftCoercion, rightCoercion, clauses.build(), leftCoercion.getOutputSymbols(), rightCoercion.getOutputSymbols(), false, Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(), ImmutableMap.of(), Optional.empty());
    // Add a projection to produce the outputs of the columns in the USING clause,
    // which are defined as coalesce(l.k, r.k)
    Assignments.Builder assignments = Assignments.builder();
    ImmutableList.Builder<Symbol> outputs = ImmutableList.builder();
    for (Identifier column : joinColumns) {
        Symbol output = symbolAllocator.newSymbol(column, analysis.getType(column));
        outputs.add(output);
        assignments.put(output, new CoalesceExpression(leftJoinColumns.get(column).toSymbolReference(), rightJoinColumns.get(column).toSymbolReference()));
    }
    for (int field : joinAnalysis.getOtherLeftFields()) {
        Symbol symbol = left.getFieldMappings().get(field);
        outputs.add(symbol);
        assignments.put(symbol, symbol.toSymbolReference());
    }
    for (int field : joinAnalysis.getOtherRightFields()) {
        Symbol symbol = right.getFieldMappings().get(field);
        outputs.add(symbol);
        assignments.put(symbol, symbol.toSymbolReference());
    }
    return new RelationPlan(new ProjectNode(idAllocator.getNextId(), join, assignments.build()), analysis.getScope(node), outputs.build(), outerContext);
}
Also used : Cast(io.trino.sql.tree.Cast) LinkedHashMap(java.util.LinkedHashMap) HashMap(java.util.HashMap) ImmutableList.toImmutableList(com.google.common.collect.ImmutableList.toImmutableList) ImmutableList(com.google.common.collect.ImmutableList) CorrelatedJoinNode(io.trino.sql.planner.plan.CorrelatedJoinNode) JoinNode(io.trino.sql.planner.plan.JoinNode) Assignments(io.trino.sql.planner.plan.Assignments) JoinUsing(io.trino.sql.tree.JoinUsing) RelationType(io.trino.sql.analyzer.RelationType) RowType(io.trino.spi.type.RowType) TypeSignatureTranslator.toSqlType(io.trino.sql.analyzer.TypeSignatureTranslator.toSqlType) Type(io.trino.spi.type.Type) Identifier(io.trino.sql.tree.Identifier) UnnestAnalysis(io.trino.sql.analyzer.Analysis.UnnestAnalysis) Analysis(io.trino.sql.analyzer.Analysis) ProjectNode(io.trino.sql.planner.plan.ProjectNode) CoalesceExpression(io.trino.sql.tree.CoalesceExpression)

Aggregations

CoalesceExpression (io.trino.sql.tree.CoalesceExpression)8 Symbol (io.trino.sql.planner.Symbol)3 Assignments (io.trino.sql.planner.plan.Assignments)3 ProjectNode (io.trino.sql.planner.plan.ProjectNode)3 Expression (io.trino.sql.tree.Expression)3 LongLiteral (io.trino.sql.tree.LongLiteral)3 Type (io.trino.spi.type.Type)2 CorrelatedJoinNode (io.trino.sql.planner.plan.CorrelatedJoinNode)2 JoinNode (io.trino.sql.planner.plan.JoinNode)2 Cast (io.trino.sql.tree.Cast)2 ComparisonExpression (io.trino.sql.tree.ComparisonExpression)2 FunctionCall (io.trino.sql.tree.FunctionCall)2 GenericLiteral (io.trino.sql.tree.GenericLiteral)2 IfExpression (io.trino.sql.tree.IfExpression)2 ImmutableList (com.google.common.collect.ImmutableList)1 ImmutableList.toImmutableList (com.google.common.collect.ImmutableList.toImmutableList)1 ImmutableMap (com.google.common.collect.ImmutableMap)1 ResolvedFunction (io.trino.metadata.ResolvedFunction)1 CharType (io.trino.spi.type.CharType)1 DecimalType.createDecimalType (io.trino.spi.type.DecimalType.createDecimalType)1