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();
}
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)));
}
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);
}
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;
}
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));
}
Aggregations