use of io.trino.sql.tree.ComparisonExpression in project trino by trinodb.
the class TestRemoveUnreferencedScalarSubqueries method testDoNotRemoveInputOfLeftOrFullJoinWhenSubqueryPotentiallyEmpty.
@Test
public void testDoNotRemoveInputOfLeftOrFullJoinWhenSubqueryPotentiallyEmpty() {
tester().assertThat(new RemoveUnreferencedScalarSubqueries()).on(p -> {
Symbol b = p.symbol("b");
return p.correlatedJoin(emptyList(), p.values(emptyList(), ImmutableList.of(emptyList())), LEFT, TRUE_LITERAL, p.filter(new ComparisonExpression(LESS_THAN, b.toSymbolReference(), new LongLiteral("3")), p.values(2, b)));
}).doesNotFire();
tester().assertThat(new RemoveUnreferencedScalarSubqueries()).on(p -> {
Symbol b = p.symbol("b");
return p.correlatedJoin(emptyList(), p.values(emptyList(), ImmutableList.of(emptyList())), FULL, TRUE_LITERAL, p.filter(new ComparisonExpression(LESS_THAN, b.toSymbolReference(), new LongLiteral("3")), p.values(2, b)));
}).doesNotFire();
}
use of io.trino.sql.tree.ComparisonExpression 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.ComparisonExpression in project trino by trinodb.
the class TestTransformCorrelatedJoinToJoin method testRewriteInnerCorrelatedJoin.
@Test
public void testRewriteInnerCorrelatedJoin() {
tester().assertThat(new TransformCorrelatedJoinToJoin(tester().getPlannerContext())).on(p -> {
Symbol a = p.symbol("a");
Symbol b = p.symbol("b");
return p.correlatedJoin(ImmutableList.of(a), p.values(a), p.filter(new ComparisonExpression(GREATER_THAN, b.toSymbolReference(), a.toSymbolReference()), p.values(b)));
}).matches(join(JoinNode.Type.INNER, ImmutableList.of(), Optional.of("b > a"), values("a"), filter(TRUE_LITERAL, values("b"))));
tester().assertThat(new TransformCorrelatedJoinToJoin(tester().getPlannerContext())).on(p -> {
Symbol a = p.symbol("a");
Symbol b = p.symbol("b");
return p.correlatedJoin(ImmutableList.of(a), p.values(a), INNER, new ComparisonExpression(LESS_THAN, b.toSymbolReference(), new LongLiteral("3")), p.filter(new ComparisonExpression(GREATER_THAN, b.toSymbolReference(), a.toSymbolReference()), p.values(b)));
}).matches(join(JoinNode.Type.INNER, ImmutableList.of(), Optional.of("b > a AND b < 3"), values("a"), filter(TRUE_LITERAL, values("b"))));
}
use of io.trino.sql.tree.ComparisonExpression 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.ComparisonExpression in project trino by trinodb.
the class TestFilterStatsRule method testUnestimatableFunction.
@Test
public void testUnestimatableFunction() {
// can't estimate function and default filter factor is turned off
ComparisonExpression unestimatableExpression = new ComparisonExpression(Operator.EQUAL, new TestingFunctionResolution().functionCallBuilder(QualifiedName.of("sin")).addArgument(DOUBLE, new SymbolReference("i1")).build(), new DoubleLiteral("1"));
tester().assertStatsFor(pb -> pb.filter(unestimatableExpression, pb.values(pb.symbol("i1"), pb.symbol("i2"), pb.symbol("i3")))).withSourceStats(0, PlanNodeStatsEstimate.builder().setOutputRowCount(10).addSymbolStatistics(new Symbol("i1"), SymbolStatsEstimate.builder().setLowValue(1).setHighValue(10).setDistinctValuesCount(5).setNullsFraction(0).build()).addSymbolStatistics(new Symbol("i2"), SymbolStatsEstimate.builder().setLowValue(0).setHighValue(3).setDistinctValuesCount(4).setNullsFraction(0).build()).addSymbolStatistics(new Symbol("i3"), SymbolStatsEstimate.builder().setLowValue(10).setHighValue(15).setDistinctValuesCount(4).setNullsFraction(0.1).build()).build()).check(PlanNodeStatsAssertion::outputRowsCountUnknown);
// can't estimate function, but default filter factor is turned on
defaultFilterTester.assertStatsFor(pb -> pb.filter(unestimatableExpression, pb.values(pb.symbol("i1"), pb.symbol("i2"), pb.symbol("i3")))).withSourceStats(0, PlanNodeStatsEstimate.builder().setOutputRowCount(10).addSymbolStatistics(new Symbol("i1"), SymbolStatsEstimate.builder().setLowValue(1).setHighValue(10).setDistinctValuesCount(5).setNullsFraction(0).build()).addSymbolStatistics(new Symbol("i2"), SymbolStatsEstimate.builder().setLowValue(0).setHighValue(3).setDistinctValuesCount(4).setNullsFraction(0).build()).addSymbolStatistics(new Symbol("i3"), SymbolStatsEstimate.builder().setLowValue(10).setHighValue(15).setDistinctValuesCount(4).setNullsFraction(0.1).build()).build()).check(check -> check.outputRowsCount(9).symbolStats("i1", assertion -> assertion.lowValue(1).highValue(10).dataSizeUnknown().distinctValuesCount(5).nullsFraction(0)).symbolStats("i2", assertion -> assertion.lowValue(0).highValue(3).dataSizeUnknown().distinctValuesCount(4).nullsFraction(0)).symbolStats("i3", assertion -> assertion.lowValue(10).highValue(15).dataSizeUnknown().distinctValuesCount(4).nullsFraction(0.1)));
}
Aggregations