This is an automated email from the ASF dual-hosted git repository.
yiguolei pushed a commit to branch branch-4.1
in repository https://gitbox.apache.org/repos/asf/doris.git
The following commit(s) were added to refs/heads/branch-4.1 by this push:
new f04008b56d2 branch-4.1: [fix](expr opt) Preserve cast-induced
nullability in comparisons #67730 (#67843)
f04008b56d2 is described below
commit f04008b56d26768f4419f7b7d69209cbcb417b9b
Author: github-actions[bot]
<41898282+github-actions[bot]@users.noreply.github.com>
AuthorDate: Sat Sep 12 00:50:06 2026 +0800
branch-4.1: [fix](expr opt) Preserve cast-induced nullability in
comparisons #67730 (#67843)
Cherry-picked from #67730
Co-authored-by: morrySnow <[email protected]>
---
.../rules/SimplifyComparisonPredicate.java | 25 ++++++++++--------
.../rules/SimplifyComparisonPredicateTest.java | 30 ++++++++++++++++++++++
2 files changed, 45 insertions(+), 10 deletions(-)
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/SimplifyComparisonPredicate.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/SimplifyComparisonPredicate.java
index 335fe783071..6e3a53bc4cd 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/SimplifyComparisonPredicate.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/SimplifyComparisonPredicate.java
@@ -486,6 +486,7 @@ public class SimplifyComparisonPredicate implements
ExpressionPatternRuleFactory
private static Expression
processTypeRangeLimitComparison(ComparisonPredicate cp, Expression left,
NumericLiteral right) {
+ Expression nullabilityExpression = left;
BigDecimal typeMinValue = null;
BigDecimal typeMaxValue = null;
// cmp float like have lost precision, for example float.max_value +
0.01 still eval to float.max_value
@@ -501,7 +502,11 @@ public class SimplifyComparisonPredicate implements
ExpressionPatternRuleFactory
// cast(child as dataType2) range should be:
// [ max(childDataType.min_value, dataType2.min_value),
min(childDataType.max_value, dataType2.max_value)]
if (left instanceof Cast) {
- left = ((Cast) left).child();
+ Cast cast = (Cast) left;
+ left = cast.child();
+ if (!Cast.castNullable(false, left.getDataType(),
cast.getDataType())) {
+ nullabilityExpression = left;
+ }
if (left.getDataType().isIntegerLikeType() ||
left.getDataType().isDecimalV3Type()) {
Optional<Pair<BigDecimal, BigDecimal>> minMaxOpt =
TypeCoercionUtils.getDataTypeMinMaxValue(left.getDataType());
@@ -524,7 +529,7 @@ public class SimplifyComparisonPredicate implements
ExpressionPatternRuleFactory
int cmpMax = literal.compareTo(typeMaxValue);
if (cp instanceof EqualTo) {
if (cmpMin < 0 || cmpMax > 0) {
- return ExpressionUtils.falseOrNull(left);
+ return ExpressionUtils.falseOrNull(nullabilityExpression);
}
} else if (cp instanceof NullSafeEqual) {
if (cmpMin < 0 || cmpMax > 0) {
@@ -532,37 +537,37 @@ public class SimplifyComparisonPredicate implements
ExpressionPatternRuleFactory
}
} else if (cp instanceof GreaterThan) {
if (cmpMin < 0) {
- return ExpressionUtils.trueOrNull(left);
+ return ExpressionUtils.trueOrNull(nullabilityExpression);
}
if (cmpMax >= 0) {
- return ExpressionUtils.falseOrNull(left);
+ return ExpressionUtils.falseOrNull(nullabilityExpression);
}
} else if (cp instanceof GreaterThanEqual) {
if (cmpMin <= 0) {
- return ExpressionUtils.trueOrNull(left);
+ return ExpressionUtils.trueOrNull(nullabilityExpression);
}
if (cmpMax == 0) {
return new EqualTo(cp.left(), cp.right());
}
if (cmpMax > 0) {
- return ExpressionUtils.falseOrNull(left);
+ return ExpressionUtils.falseOrNull(nullabilityExpression);
}
} else if (cp instanceof LessThan) {
if (cmpMin <= 0) {
- return ExpressionUtils.falseOrNull(left);
+ return ExpressionUtils.falseOrNull(nullabilityExpression);
}
if (cmpMax > 0) {
- return ExpressionUtils.trueOrNull(left);
+ return ExpressionUtils.trueOrNull(nullabilityExpression);
}
} else if (cp instanceof LessThanEqual) {
if (cmpMin < 0) {
- return ExpressionUtils.falseOrNull(left);
+ return ExpressionUtils.falseOrNull(nullabilityExpression);
}
if (cmpMin == 0) {
return new EqualTo(cp.left(), cp.right());
}
if (cmpMax >= 0) {
- return ExpressionUtils.trueOrNull(left);
+ return ExpressionUtils.trueOrNull(nullabilityExpression);
}
}
return cp;
diff --git
a/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/expression/rules/SimplifyComparisonPredicateTest.java
b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/expression/rules/SimplifyComparisonPredicateTest.java
index 7d6967e6b3b..21f98158e4e 100644
---
a/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/expression/rules/SimplifyComparisonPredicateTest.java
+++
b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/expression/rules/SimplifyComparisonPredicateTest.java
@@ -33,6 +33,7 @@ import
org.apache.doris.nereids.trees.expressions.LessThanEqual;
import org.apache.doris.nereids.trees.expressions.Not;
import org.apache.doris.nereids.trees.expressions.NullSafeEqual;
import org.apache.doris.nereids.trees.expressions.SlotReference;
+import org.apache.doris.nereids.trees.expressions.TryCast;
import org.apache.doris.nereids.trees.expressions.literal.BigIntLiteral;
import org.apache.doris.nereids.trees.expressions.literal.BooleanLiteral;
import org.apache.doris.nereids.trees.expressions.literal.DateLiteral;
@@ -928,6 +929,35 @@ class SimplifyComparisonPredicateTest extends
ExpressionRewriteTestHelper {
NO_CHANGE_CP // no change cmp type
}
+ @Test
+ void testTypeRangeLimitPreservesCastNullability() {
+ executor = new ExpressionRuleExecutor(ImmutableList.of(
+ bottomUp(SimplifyComparisonPredicate.INSTANCE)
+ ));
+
+ SlotReference nonNullableBigInt = new SlotReference("bigint_slot",
BigIntType.INSTANCE, false);
+ List<Cast> nullableCasts = ImmutableList.of(
+ new Cast(nonNullableBigInt, TinyIntType.INSTANCE),
+ new TryCast(nonNullableBigInt, TinyIntType.INSTANCE));
+ for (Cast nullableCast : nullableCasts) {
+ assertRewrite(new GreaterThan(nullableCast, new
TinyIntLiteral((byte) 127)),
+ ExpressionUtils.falseOrNull(nullableCast));
+ assertRewrite(new LessThan(nullableCast, new TinyIntLiteral((byte)
-128)),
+ ExpressionUtils.falseOrNull(nullableCast));
+ assertRewrite(new LessThanEqual(nullableCast, new
TinyIntLiteral((byte) 127)),
+ ExpressionUtils.trueOrNull(nullableCast));
+ }
+
+ SlotReference nonNullableTinyInt = new SlotReference("tinyint_slot",
TinyIntType.INSTANCE, false);
+ List<Cast> safeCasts = ImmutableList.of(
+ new Cast(nonNullableTinyInt, SmallIntType.INSTANCE),
+ new TryCast(nonNullableTinyInt, SmallIntType.INSTANCE));
+ for (Cast safeCast : safeCasts) {
+ assertRewrite(new GreaterThan(safeCast, new
SmallIntLiteral((short) 127)),
+ BooleanLiteral.FALSE);
+ }
+ }
+
@Test
void testTypeRangeLimit() {
executor = new ExpressionRuleExecutor(ImmutableList.of(
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]