Search in sources :

Example 16 with FunctionCall

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

the class TestSimplifyFilterPredicate method testSimplifyIfExpression.

@Test
public void testSimplifyIfExpression() {
    // true result iff the condition is true
    tester().assertThat(new SimplifyFilterPredicate(tester().getMetadata())).on(p -> p.filter(expression("IF(a, true, false)"), p.values(p.symbol("a")))).matches(filter("a", values("a")));
    // true result iff the condition is true
    tester().assertThat(new SimplifyFilterPredicate(tester().getMetadata())).on(p -> p.filter(expression("IF(a, true)"), p.values(p.symbol("a")))).matches(filter("a", values("a")));
    // true result iff the condition is null or false
    tester().assertThat(new SimplifyFilterPredicate(tester().getMetadata())).on(p -> p.filter(expression("IF(a, false, true)"), p.values(p.symbol("a")))).matches(filter("a IS NULL OR NOT a", values("a")));
    // true result iff the condition is null or false
    tester().assertThat(new SimplifyFilterPredicate(tester().getMetadata())).on(p -> p.filter(expression("IF(a, null, true)"), p.values(p.symbol("a")))).matches(filter("a IS NULL OR NOT a", values("a")));
    // always true
    tester().assertThat(new SimplifyFilterPredicate(tester().getMetadata())).on(p -> p.filter(expression("IF(a, true, true)"), p.values(p.symbol("a")))).matches(filter("true", values("a")));
    // always false
    tester().assertThat(new SimplifyFilterPredicate(tester().getMetadata())).on(p -> p.filter(expression("IF(a, false, false)"), p.values(p.symbol("a")))).matches(filter("false", values("a")));
    // both results equal
    tester().assertThat(new SimplifyFilterPredicate(tester().getMetadata())).on(p -> p.filter(expression("IF(a, b > 0, b > 0)"), p.values(p.symbol("a"), p.symbol("b")))).matches(filter("b > 0", values("a", "b")));
    // both results are equal non-deterministic expressions
    FunctionCall randomFunction = new FunctionCall(tester().getMetadata().resolveFunction(tester().getSession(), QualifiedName.of("random"), ImmutableList.of()).toQualifiedName(), ImmutableList.of());
    tester().assertThat(new SimplifyFilterPredicate(tester().getMetadata())).on(p -> p.filter(new IfExpression(expression("a"), new ComparisonExpression(EQUAL, randomFunction, new LongLiteral("0")), new ComparisonExpression(EQUAL, randomFunction, new LongLiteral("0"))), p.values(p.symbol("a")))).doesNotFire();
    // always null (including the default) -> simplified to FALSE
    tester().assertThat(new SimplifyFilterPredicate(tester().getMetadata())).on(p -> p.filter(expression("IF(a, null)"), p.values(p.symbol("a")))).matches(filter("false", values("a")));
    // condition is true -> first branch
    tester().assertThat(new SimplifyFilterPredicate(tester().getMetadata())).on(p -> p.filter(expression("IF(true, a, NOT a)"), p.values(p.symbol("a")))).matches(filter("a", values("a")));
    // condition is true -> second branch
    tester().assertThat(new SimplifyFilterPredicate(tester().getMetadata())).on(p -> p.filter(expression("IF(false, a, NOT a)"), p.values(p.symbol("a")))).matches(filter("NOT a", values("a")));
    // condition is true, no second branch -> the result is null, simplified to FALSE
    tester().assertThat(new SimplifyFilterPredicate(tester().getMetadata())).on(p -> p.filter(expression("IF(false, a)"), p.values(p.symbol("a")))).matches(filter("false", values("a")));
    // not known result (`b`) - cannot optimize
    tester().assertThat(new SimplifyFilterPredicate(tester().getMetadata())).on(p -> p.filter(expression("IF(a, true, b)"), p.values(p.symbol("a"), p.symbol("b")))).doesNotFire();
}
Also used : QualifiedName(io.trino.sql.tree.QualifiedName) EQUAL(io.trino.sql.tree.ComparisonExpression.Operator.EQUAL) IfExpression(io.trino.sql.tree.IfExpression) ImmutableList(com.google.common.collect.ImmutableList) BaseRuleTest(io.trino.sql.planner.iterative.rule.test.BaseRuleTest) LongLiteral(io.trino.sql.tree.LongLiteral) Test(org.testng.annotations.Test) PlanMatchPattern.filter(io.trino.sql.planner.assertions.PlanMatchPattern.filter) PlanMatchPattern.values(io.trino.sql.planner.assertions.PlanMatchPattern.values) FunctionCall(io.trino.sql.tree.FunctionCall) PlanBuilder.expression(io.trino.sql.planner.iterative.rule.test.PlanBuilder.expression) ComparisonExpression(io.trino.sql.tree.ComparisonExpression) IfExpression(io.trino.sql.tree.IfExpression) ComparisonExpression(io.trino.sql.tree.ComparisonExpression) LongLiteral(io.trino.sql.tree.LongLiteral) FunctionCall(io.trino.sql.tree.FunctionCall) BaseRuleTest(io.trino.sql.planner.iterative.rule.test.BaseRuleTest) Test(org.testng.annotations.Test)

Example 17 with FunctionCall

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

the class LogicalPlanner method noTruncationCast.

/*
    According to the standard, for the purpose of store assignment (INSERT),
    no non-space characters of a character string, and no non-zero octets
    of a binary string must be lost when the inserted value is truncated to
    fit in the target column type.
    The following method returns a cast from source type to target type
    with a guarantee of no illegal truncation.
    TODO Once BINARY and parametric VARBINARY types are supported, they should be handled here.
    TODO This workaround is insufficient to handle structural types
     */
private Expression noTruncationCast(Expression expression, Type fromType, Type toType) {
    if (fromType instanceof UnknownType || (!(toType instanceof VarcharType) && !(toType instanceof CharType))) {
        return new Cast(expression, toSqlType(toType));
    }
    int targetLength;
    if (toType instanceof VarcharType) {
        if (((VarcharType) toType).isUnbounded()) {
            return new Cast(expression, toSqlType(toType));
        }
        targetLength = ((VarcharType) toType).getBoundedLength();
    } else {
        targetLength = ((CharType) toType).getLength();
    }
    checkState(fromType instanceof VarcharType || fromType instanceof CharType, "inserting non-character value to column of character type");
    ResolvedFunction spaceTrimmedLength = metadata.resolveFunction(session, QualifiedName.of("$space_trimmed_length"), fromTypes(VARCHAR));
    ResolvedFunction fail = metadata.resolveFunction(session, QualifiedName.of("fail"), fromTypes(VARCHAR));
    return new IfExpression(// check if the trimmed value fits in the target type
    new ComparisonExpression(GREATER_THAN_OR_EQUAL, new GenericLiteral("BIGINT", Integer.toString(targetLength)), new CoalesceExpression(new FunctionCall(spaceTrimmedLength.toQualifiedName(), ImmutableList.of(new Cast(expression, toSqlType(VARCHAR)))), new GenericLiteral("BIGINT", "0"))), new Cast(expression, toSqlType(toType)), new Cast(new FunctionCall(fail.toQualifiedName(), ImmutableList.of(new Cast(new StringLiteral(format("Cannot truncate non-space characters when casting from %s to %s on INSERT", fromType.getDisplayName(), toType.getDisplayName())), toSqlType(VARCHAR)))), toSqlType(toType)));
}
Also used : UnknownType(io.trino.type.UnknownType) Cast(io.trino.sql.tree.Cast) IfExpression(io.trino.sql.tree.IfExpression) ComparisonExpression(io.trino.sql.tree.ComparisonExpression) StringLiteral(io.trino.sql.tree.StringLiteral) VarcharType(io.trino.spi.type.VarcharType) ResolvedFunction(io.trino.metadata.ResolvedFunction) CharType(io.trino.spi.type.CharType) FunctionCall(io.trino.sql.tree.FunctionCall) CoalesceExpression(io.trino.sql.tree.CoalesceExpression) GenericLiteral(io.trino.sql.tree.GenericLiteral)

Example 18 with FunctionCall

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

the class FunctionCallProvider method getExpectedValue.

@Override
public FunctionCall getExpectedValue(SymbolAliases aliases) {
    List<Expression> symbolReferences = toSymbolReferences(args, aliases);
    if (isWindowFunction) {
        verify(!distinct, "window does not support distinct");
        verify(orderBy.isEmpty(), "window does not support order by");
        return new ExpectedWindowFunctionCall(symbolReferences);
    }
    Optional<OrderBy> orderByClause = Optional.empty();
    if (!orderBy.isEmpty()) {
        orderByClause = Optional.of(new OrderBy(orderBy.stream().map(item -> new SortItem(Symbol.from(aliases.get(item.getField())).toSymbolReference(), item.getOrdering(), item.getNullOrdering())).collect(Collectors.toList())));
    }
    return new FunctionCall(Optional.empty(), name, Optional.empty(), filter.map(symbol -> symbol.toSymbol(aliases).toSymbolReference()), orderByClause, distinct, Optional.empty(), Optional.empty(), symbolReferences);
}
Also used : OrderBy(io.trino.sql.tree.OrderBy) Symbol(io.trino.sql.planner.Symbol) SortItem(io.trino.sql.tree.SortItem) Collectors(java.util.stream.Collectors) String.format(java.lang.String.format) QualifiedName(io.trino.sql.tree.QualifiedName) Objects(java.util.Objects) PlanMatchPattern.toSymbolReferences(io.trino.sql.planner.assertions.PlanMatchPattern.toSymbolReferences) List(java.util.List) ImmutableList(com.google.common.collect.ImmutableList) Verify.verify(com.google.common.base.Verify.verify) Objects.requireNonNull(java.util.Objects.requireNonNull) WindowFrame(io.trino.sql.tree.WindowFrame) Optional(java.util.Optional) Expression(io.trino.sql.tree.Expression) FunctionCall(io.trino.sql.tree.FunctionCall) OrderBy(io.trino.sql.tree.OrderBy) Joiner(com.google.common.base.Joiner) WindowSpecification(io.trino.sql.tree.WindowSpecification) SortItem(io.trino.sql.tree.SortItem) Expression(io.trino.sql.tree.Expression) FunctionCall(io.trino.sql.tree.FunctionCall)

Example 19 with FunctionCall

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

the class WindowFunctionMatcher method getAssignedSymbol.

@Override
public Optional<Symbol> getAssignedSymbol(PlanNode node, Session session, Metadata metadata, SymbolAliases symbolAliases) {
    Optional<Symbol> result = Optional.empty();
    Map<Symbol, Function> assignments;
    if (node instanceof WindowNode) {
        assignments = ((WindowNode) node).getWindowFunctions();
    } else if (node instanceof PatternRecognitionNode) {
        assignments = ((PatternRecognitionNode) node).getWindowFunctions();
    } else {
        return result;
    }
    FunctionCall expectedCall = callMaker.getExpectedValue(symbolAliases);
    Optional<WindowNode.Frame> expectedFrame = frameMaker.map(maker -> maker.getExpectedValue(symbolAliases));
    for (Map.Entry<Symbol, Function> assignment : assignments.entrySet()) {
        Function function = assignment.getValue();
        boolean signatureMatches = resolvedFunction.map(assignment.getValue().getResolvedFunction()::equals).orElse(true);
        if (signatureMatches && windowFunctionMatches(function, expectedCall, expectedFrame)) {
            checkState(result.isEmpty(), "Ambiguous function calls in %s", node);
            result = Optional.of(assignment.getKey());
        }
    }
    return result;
}
Also used : ResolvedFunction(io.trino.metadata.ResolvedFunction) Function(io.trino.sql.planner.plan.WindowNode.Function) WindowNode(io.trino.sql.planner.plan.WindowNode) PatternRecognitionNode(io.trino.sql.planner.plan.PatternRecognitionNode) Symbol(io.trino.sql.planner.Symbol) FunctionCall(io.trino.sql.tree.FunctionCall) Map(java.util.Map)

Example 20 with FunctionCall

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

the class TestSqlParser method testAnalyze.

@Test
public void testAnalyze() {
    QualifiedName table = QualifiedName.of("foo");
    assertStatement("ANALYZE foo", new Analyze(table, ImmutableList.of()));
    assertStatement("ANALYZE foo WITH ( \"string\" = 'bar', \"long\" = 42, computed = concat('ban', 'ana'), a = ARRAY[ 'v1', 'v2' ] )", new Analyze(table, ImmutableList.of(new Property(new Identifier("string"), new StringLiteral("bar")), new Property(new Identifier("long"), new LongLiteral("42")), new Property(new Identifier("computed"), new FunctionCall(QualifiedName.of("concat"), ImmutableList.of(new StringLiteral("ban"), new StringLiteral("ana")))), new Property(new Identifier("a"), new ArrayConstructor(ImmutableList.of(new StringLiteral("v1"), new StringLiteral("v2")))))));
    assertStatement("EXPLAIN ANALYZE foo", new Explain(new Analyze(table, ImmutableList.of()), ImmutableList.of()));
    assertStatement("EXPLAIN ANALYZE ANALYZE foo", new ExplainAnalyze(new Analyze(table, ImmutableList.of()), false));
}
Also used : QueryUtil.quotedIdentifier(io.trino.sql.QueryUtil.quotedIdentifier) Identifier(io.trino.sql.tree.Identifier) StringLiteral(io.trino.sql.tree.StringLiteral) LongLiteral(io.trino.sql.tree.LongLiteral) ExplainAnalyze(io.trino.sql.tree.ExplainAnalyze) QualifiedName(io.trino.sql.tree.QualifiedName) Explain(io.trino.sql.tree.Explain) ArrayConstructor(io.trino.sql.tree.ArrayConstructor) FunctionCall(io.trino.sql.tree.FunctionCall) Property(io.trino.sql.tree.Property) ExplainAnalyze(io.trino.sql.tree.ExplainAnalyze) Analyze(io.trino.sql.tree.Analyze) Test(org.junit.jupiter.api.Test)

Aggregations

FunctionCall (io.trino.sql.tree.FunctionCall)69 Test (org.testng.annotations.Test)32 StringLiteral (io.trino.sql.tree.StringLiteral)31 ImmutableList (com.google.common.collect.ImmutableList)29 QualifiedName (io.trino.sql.tree.QualifiedName)29 ComparisonExpression (io.trino.sql.tree.ComparisonExpression)25 Expression (io.trino.sql.tree.Expression)25 LongLiteral (io.trino.sql.tree.LongLiteral)25 Optional (java.util.Optional)22 ImmutableMap (com.google.common.collect.ImmutableMap)21 Identifier (io.trino.sql.tree.Identifier)19 TypeSignatureProvider.fromTypes (io.trino.sql.analyzer.TypeSignatureProvider.fromTypes)18 ResolvedFunction (io.trino.metadata.ResolvedFunction)17 Assignments (io.trino.sql.planner.plan.Assignments)16 Cast (io.trino.sql.tree.Cast)15 TypeSignatureTranslator.toSqlType (io.trino.sql.analyzer.TypeSignatureTranslator.toSqlType)14 BIGINT (io.trino.spi.type.BigintType.BIGINT)13 PlanMatchPattern.project (io.trino.sql.planner.assertions.PlanMatchPattern.project)13 PlanMatchPattern.values (io.trino.sql.planner.assertions.PlanMatchPattern.values)13 MetadataManager.createTestMetadataManager (io.trino.metadata.MetadataManager.createTestMetadataManager)12