Skip to content

Commit

Permalink
Fix ClassCastException in DomainTranslator
Browse files Browse the repository at this point in the history
When theres's an expression such as:

    CAST('2022-01-01') AS date) BETWEEN CAST(start_date AS date) AND CAST(end_date AS date)

There's a call to visitComparisonExpression with the term:

    DATE '2022-01-01' >= CAST(start_date AS date)

Inside that method, the expression is normalized to have the symbol on the
left and the constant on the right. However, the createVarcharCastToDateComparisonExtractionResult
pulls the elements from the unnormalized ComparisonExpression node and expects the left
subexpression to be cast, which results in a failure due to ClassCastException
  • Loading branch information
martint committed Nov 14, 2022
1 parent da11011 commit b4ce895
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -512,10 +512,10 @@ protected ExtractionResult visitComparisonExpression(ComparisonExpression node,
Type castTargetType = requireNonNull(expressionTypes.get(NodeRef.of(castExpression)), "No type for Cast target expression");
if (castSourceType instanceof VarcharType && castTargetType == DATE && !castExpression.isSafe()) {
Optional<ExtractionResult> result = createVarcharCastToDateComparisonExtractionResult(
node,
normalized,
(VarcharType) castSourceType,
normalized.getValue(),
complement);
complement,
node);
if (result.isPresent()) {
return result.get();
}
Expand Down Expand Up @@ -604,15 +604,14 @@ private Map<NodeRef<Expression>, Type> analyzeExpression(Expression expression)
}

private Optional<ExtractionResult> createVarcharCastToDateComparisonExtractionResult(
ComparisonExpression node,
NormalizedSimpleComparison comparison,
VarcharType sourceType,
NullableValue value,
boolean complement)
boolean complement,
ComparisonExpression originalExpression)
{
Cast castExpression = (Cast) node.getLeft();
Expression sourceExpression = castExpression.getExpression();
ComparisonExpression.Operator comparisonOperator = node.getOperator();
requireNonNull(value, "value is null");
Expression sourceExpression = ((Cast) comparison.getSymbolExpression()).getExpression();
ComparisonExpression.Operator operator = comparison.getComparisonOperator();
NullableValue value = comparison.getValue();

if (complement || value.isNull()) {
return Optional.empty();
Expand All @@ -638,7 +637,7 @@ private Optional<ExtractionResult> createVarcharCastToDateComparisonExtractionRe
ValueSet valueSet;
boolean nullAllowed = false;

switch (comparisonOperator) {
switch (operator) {
case EQUAL:
valueSet = dateStringRanges(date, sourceType);
break;
Expand All @@ -649,7 +648,7 @@ private Optional<ExtractionResult> createVarcharCastToDateComparisonExtractionRe
return Optional.empty();
}
valueSet = ValueSet.all(sourceType).subtract(dateStringRanges(date, sourceType));
nullAllowed = (comparisonOperator == IS_DISTINCT_FROM);
nullAllowed = (operator == IS_DISTINCT_FROM);
break;
case LESS_THAN:
case LESS_THAN_OR_EQUAL:
Expand All @@ -670,7 +669,7 @@ private Optional<ExtractionResult> createVarcharCastToDateComparisonExtractionRe

return Optional.of(new ExtractionResult(
TupleDomain.withColumnDomains(ImmutableMap.of(sourceSymbol, Domain.create(valueSet, nullAllowed))),
node));
originalExpression));
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1072,6 +1072,17 @@ public void testPredicateWithVarcharCastToDate()
Range.greaterThan(VARCHAR, utf8Slice("2004"))),
false)));

// Regression test for https://github.com/trinodb/trino/issues/14954
assertPredicateTranslates(
greaterThan(new GenericLiteral("DATE", "2001-01-31"), cast(C_VARCHAR, DATE)),
tupleDomain(
C_VARCHAR,
Domain.create(ValueSet.ofRanges(
Range.lessThan(VARCHAR, utf8Slice("2002")),
Range.greaterThan(VARCHAR, utf8Slice("9"))),
false)),
greaterThan(new GenericLiteral("DATE", "2001-01-31"), cast(C_VARCHAR, DATE)));

// BETWEEN
assertPredicateTranslates(
between(cast(C_VARCHAR, DATE), new GenericLiteral("DATE", "2001-01-31"), new GenericLiteral("DATE", "2005-09-10")),
Expand All @@ -1083,6 +1094,24 @@ public void testPredicateWithVarcharCastToDate()
and(
greaterThanOrEqual(cast(C_VARCHAR, DATE), new GenericLiteral("DATE", "2001-01-31")),
lessThanOrEqual(cast(C_VARCHAR, DATE), new GenericLiteral("DATE", "2005-09-10"))));

// Regression test for https://github.com/trinodb/trino/issues/14954
assertPredicateTranslates(
between(new GenericLiteral("DATE", "2001-01-31"), cast(C_VARCHAR, DATE), cast(C_VARCHAR_1, DATE)),
tupleDomain(
C_VARCHAR,
Domain.create(ValueSet.ofRanges(
Range.lessThan(VARCHAR, utf8Slice("2002")),
Range.greaterThan(VARCHAR, utf8Slice("9"))),
false),
C_VARCHAR_1,
Domain.create(ValueSet.ofRanges(
Range.lessThan(VARCHAR, utf8Slice("1")),
Range.greaterThan(VARCHAR, utf8Slice("2000"))),
false)),
and(
greaterThanOrEqual(new GenericLiteral("DATE", "2001-01-31"), cast(C_VARCHAR, DATE)),
lessThanOrEqual(new GenericLiteral("DATE", "2001-01-31"), cast(C_VARCHAR_1, DATE))));
}

@Test
Expand Down

0 comments on commit b4ce895

Please sign in to comment.