[fix](nereids)SimplifyRange didn't process NULL value correctly (#33296)
This commit is contained in:
@ -98,6 +98,16 @@ public class SimplifyRange extends AbstractExpressionRewriteRule {
|
||||
private ValueDesc buildRange(ComparisonPredicate predicate) {
|
||||
Expression rewrite = ExpressionRuleExecutor.normalize(predicate);
|
||||
Expression right = rewrite.child(1);
|
||||
if (right.isNullLiteral()) {
|
||||
// it's safe to return empty value if >, >=, <, <= and = with null
|
||||
if ((predicate instanceof GreaterThan || predicate instanceof GreaterThanEqual
|
||||
|| predicate instanceof LessThan || predicate instanceof LessThanEqual
|
||||
|| predicate instanceof EqualTo)) {
|
||||
return new EmptyValue(rewrite.child(0), rewrite);
|
||||
} else {
|
||||
return new UnknownValue(predicate);
|
||||
}
|
||||
}
|
||||
// only handle `NumericType` and `DateLikeType`
|
||||
if (right.isLiteral() && (right.getDataType().isNumericType() || right.getDataType().isDateLikeType())) {
|
||||
return ValueDesc.range((ComparisonPredicate) rewrite);
|
||||
|
||||
@ -21,6 +21,7 @@ import org.apache.doris.nereids.CascadesContext;
|
||||
import org.apache.doris.nereids.analyzer.UnboundRelation;
|
||||
import org.apache.doris.nereids.analyzer.UnboundSlot;
|
||||
import org.apache.doris.nereids.parser.NereidsParser;
|
||||
import org.apache.doris.nereids.rules.expression.rules.FunctionBinder;
|
||||
import org.apache.doris.nereids.rules.expression.rules.SimplifyRange;
|
||||
import org.apache.doris.nereids.trees.expressions.Expression;
|
||||
import org.apache.doris.nereids.trees.expressions.Slot;
|
||||
@ -60,6 +61,16 @@ public class SimplifyRangeTest {
|
||||
public void testSimplify() {
|
||||
executor = new ExpressionRuleExecutor(ImmutableList.of(SimplifyRange.INSTANCE));
|
||||
assertRewrite("TA", "TA");
|
||||
assertRewrite("TA > 3 or TA > null", "TA > 3");
|
||||
assertRewrite("TA > 3 or TA < null", "TA > 3");
|
||||
assertRewrite("TA > 3 or TA = null", "TA > 3");
|
||||
assertRewrite("TA > 3 or TA <> null", "TA > 3 or TA <> null");
|
||||
assertRewrite("TA > 3 or TA <=> null", "TA > 3 or TA <=> null");
|
||||
assertRewrite("TA > 3 and TA > null", "false");
|
||||
assertRewrite("TA > 3 and TA < null", "false");
|
||||
assertRewrite("TA > 3 and TA = null", "false");
|
||||
assertRewrite("TA > 3 and TA <> null", "TA > 3 and TA <> null");
|
||||
assertRewrite("TA > 3 and TA <=> null", "TA > 3 and TA <=> null");
|
||||
assertRewrite("(TA >= 1 and TA <=3 ) or (TA > 5 and TA < 7)", "(TA >= 1 and TA <=3 ) or (TA > 5 and TA < 7)");
|
||||
assertRewrite("(TA > 3 and TA < 1) or (TA > 7 and TA < 5)", "FALSE");
|
||||
assertRewrite("TA > 3 and TA < 1", "FALSE");
|
||||
@ -176,7 +187,7 @@ public class SimplifyRangeTest {
|
||||
"TA > date '2024-01-05' or TA < date '2024-01-01'");
|
||||
assertRewrite("TA > date '2024-01-05' or TA > date '2024-01-01' or TA > date '2024-01-10'",
|
||||
"TA > date '2024-01-01'");
|
||||
assertRewrite("TA > date '2024-01-05' or TA > date '2024-01-01' or TA < date '2024-01-10'", "TA IS NOT NULL");
|
||||
assertRewrite("TA > date '2024-01-05' or TA > date '2024-01-01' or TA < date '2024-01-10'", "cast(TA as date) IS NOT NULL");
|
||||
assertRewriteNotNull("TA > date '2024-01-05' or TA > date '2024-01-01' or TA < date '2024-01-10'", "TRUE");
|
||||
assertRewrite("TA > date '2024-01-05' and TA > date '2024-01-01' and TA > date '2024-01-10'",
|
||||
"TA > date '2024-01-10'");
|
||||
@ -184,7 +195,7 @@ public class SimplifyRangeTest {
|
||||
"TA > date '2024-01-05' and TA < date '2024-01-10'");
|
||||
assertRewrite("TA > date '2024-01-05' or TA < date '2024-01-05'",
|
||||
"TA > date '2024-01-05' or TA < date '2024-01-05'");
|
||||
assertRewrite("TA > date '2024-01-01' or TA < date '2024-01-10'", "TA IS NOT NULL");
|
||||
assertRewrite("TA > date '2024-01-01' or TA < date '2024-01-10'", "cast(TA as date) IS NOT NULL");
|
||||
assertRewriteNotNull("TA > date '2024-01-01' or TA < date '2024-01-10'", "TRUE");
|
||||
assertRewrite("TA > date '2024-01-05' and TA < date '2024-01-10'",
|
||||
"TA > date '2024-01-05' and TA < date '2024-01-10'");
|
||||
@ -242,7 +253,7 @@ public class SimplifyRangeTest {
|
||||
"TA > timestamp '2024-01-05 00:00:10' or TA < timestamp '2024-01-01 00:00:10'");
|
||||
assertRewrite("TA > timestamp '2024-01-05 00:00:10' or TA > timestamp '2024-01-01 00:00:10' or TA > timestamp '2024-01-10 00:00:10'",
|
||||
"TA > timestamp '2024-01-01 00:00:10'");
|
||||
assertRewrite("TA > timestamp '2024-01-05 00:00:10' or TA > timestamp '2024-01-01 00:00:10' or TA < timestamp '2024-01-10 00:00:10'", "TA IS NOT NULL");
|
||||
assertRewrite("TA > timestamp '2024-01-05 00:00:10' or TA > timestamp '2024-01-01 00:00:10' or TA < timestamp '2024-01-10 00:00:10'", "cast(TA as datetime) IS NOT NULL");
|
||||
assertRewriteNotNull("TA > timestamp '2024-01-05 00:00:10' or TA > timestamp '2024-01-01 00:00:10' or TA < timestamp '2024-01-10 00:00:10'", "TRUE");
|
||||
assertRewrite("TA > timestamp '2024-01-05 00:00:10' and TA > timestamp '2024-01-01 00:00:10' and TA > timestamp '2024-01-10 00:00:15'",
|
||||
"TA > timestamp '2024-01-10 00:00:15'");
|
||||
@ -250,7 +261,7 @@ public class SimplifyRangeTest {
|
||||
"TA > timestamp '2024-01-05 00:00:10' and TA < timestamp '2024-01-10 00:00:10'");
|
||||
assertRewrite("TA > timestamp '2024-01-05 00:00:10' or TA < timestamp '2024-01-05 00:00:10'",
|
||||
"TA > timestamp '2024-01-05 00:00:10' or TA < timestamp '2024-01-05 00:00:10'");
|
||||
assertRewrite("TA > timestamp '2024-01-01 00:02:10' or TA < timestamp '2024-01-10 00:02:10'", "TA IS NOT NULL");
|
||||
assertRewrite("TA > timestamp '2024-01-01 00:02:10' or TA < timestamp '2024-01-10 00:02:10'", "cast(TA as datetime) IS NOT NULL");
|
||||
assertRewriteNotNull("TA > timestamp '2024-01-01 00:00:00' or TA < timestamp '2024-01-10 00:00:00'", "TRUE");
|
||||
assertRewrite("TA > timestamp '2024-01-05 01:00:00' and TA < timestamp '2024-01-10 01:00:00'",
|
||||
"TA > timestamp '2024-01-05 01:00:00' and TA < timestamp '2024-01-10 01:00:00'");
|
||||
@ -295,7 +306,9 @@ public class SimplifyRangeTest {
|
||||
private void assertRewrite(String expression, String expected) {
|
||||
Map<String, Slot> mem = Maps.newHashMap();
|
||||
Expression needRewriteExpression = replaceUnboundSlot(PARSER.parseExpression(expression), mem);
|
||||
needRewriteExpression = typeCoercion(needRewriteExpression);
|
||||
Expression expectedExpression = replaceUnboundSlot(PARSER.parseExpression(expected), mem);
|
||||
expectedExpression = typeCoercion(expectedExpression);
|
||||
Expression rewrittenExpression = executor.rewrite(needRewriteExpression, context);
|
||||
Assertions.assertEquals(expectedExpression, rewrittenExpression);
|
||||
}
|
||||
@ -344,6 +357,10 @@ public class SimplifyRangeTest {
|
||||
return hasNewChildren ? expression.withChildren(children) : expression;
|
||||
}
|
||||
|
||||
protected Expression typeCoercion(Expression expression) {
|
||||
return FunctionBinder.INSTANCE.rewrite(expression, null);
|
||||
}
|
||||
|
||||
private DataType getType(char t) {
|
||||
switch (t) {
|
||||
case 'T':
|
||||
|
||||
Reference in New Issue
Block a user