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 7dc9ddcb3971ef..78e817cf4f813a 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 @@ -18,6 +18,7 @@ package org.apache.doris.nereids.rules.expression.rules; import org.apache.doris.common.Pair; +import org.apache.doris.nereids.exceptions.AnalysisException; import org.apache.doris.nereids.rules.expression.AbstractExpressionRewriteRule; import org.apache.doris.nereids.rules.expression.ExpressionPatternMatcher; import org.apache.doris.nereids.rules.expression.ExpressionPatternRuleFactory; @@ -171,8 +172,13 @@ private static Expression processDateLikeTypeCoercion(ComparisonPredicate cp, Ex if (cast.child().getDataType() instanceof DateTimeType || cast.child().getDataType() instanceof DateTimeV2Type) { if (right instanceof DateTimeV2Literal) { - return processDateTimeLikeComparisonPredicateDateTimeV2Literal( - cp, cast.child(), (DateTimeV2Literal) right); + try { + return processDateTimeLikeComparisonPredicateDateTimeV2Literal( + cp, cast.child(), (DateTimeV2Literal) right); + } catch (AnalysisException e) { + // '9999-12-31 23:59:59.9'.roundCeiling(0) overflow + return cp; + } } } @@ -188,7 +194,12 @@ private static Expression processDateLikeTypeCoercion(ComparisonPredicate cp, Ex } else if (cp instanceof NullSafeEqual) { return BooleanLiteral.FALSE; } else if (cp instanceof GreaterThanEqual || cp instanceof LessThan) { - right = ((DateV2Literal) right).plusDays(1); + // '9999-12-31' + 1 will overflow + Expression tomorrow = ((DateV2Literal) right).plusDays(1); + if (tomorrow.isNullLiteral()) { + return cp; + } + right = tomorrow; } } if (cast.child().getDataType() instanceof DateV2Type) { diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/DateTimeV2Literal.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/DateTimeV2Literal.java index c6ec4b99d4f4b0..69a75e001ab9eb 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/DateTimeV2Literal.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/DateTimeV2Literal.java @@ -250,7 +250,12 @@ public DateTimeV2Literal roundCeiling(int newScale) { } if (newMicroSecond > MAX_MICROSECOND) { newMicroSecond %= newMicroSecond; - DateTimeV2Literal result = (DateTimeV2Literal) this.plusSeconds(1); + Expression plus1Second = this.plusSeconds(1); + if (plus1Second.isNullLiteral()) { + throw new AnalysisException("round ceil datetime literal (" + toString() + ", " + + newScale + ") is out of range"); + } + DateTimeV2Literal result = (DateTimeV2Literal) plus1Second; newSecond = result.second; newMinute = result.minute; newHour = result.hour; 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 9a36fb59b9f18d..7696c50b39441d 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 @@ -263,6 +263,62 @@ void testDateTimeV2CmpDateTimeV2() { new LessThan(datetime2, new DateTimeV2Literal("2020-01-01 00:00:00.13"))); assertRewrite(new LessThanEqual(new Cast(datetime2, DateTimeV2Type.of(3)), new DateTimeV2Literal("2020-01-01 00:00:00.123")), new LessThanEqual(datetime2, new DateTimeV2Literal("2020-01-01 00:00:00.12"))); + + // test with low bound + assertRewrite(new LessThan(new Cast(date, DateTimeType.INSTANCE), new DateTimeLiteral("0000-01-01 00:00:00")), + new LessThan(date, new DateV2Literal("0000-01-01"))); + assertRewrite(new LessThan(new Cast(date, DateTimeV2Type.SYSTEM_DEFAULT), new DateTimeV2Literal("0000-01-01 00:00:00")), + new LessThan(date, new DateV2Literal("0000-01-01"))); + assertRewrite(new LessThan(new Cast(datev1, DateTimeType.INSTANCE), new DateTimeLiteral("0000-01-01 00:00:00")), + new LessThan(datev1, new DateLiteral("0000-01-01"))); + assertRewrite(new LessThan(new Cast(datev1, DateTimeV2Type.SYSTEM_DEFAULT), new DateTimeV2Literal("0000-01-01 00:00:00")), + new LessThan(datev1, new DateLiteral("0000-01-01"))); + assertRewrite(new LessThan(new Cast(datetime0, DateTimeV2Type.of(1)), new DateTimeV2Literal("0000-01-01 00:00:00.1")), + new LessThan(datetime0, new DateTimeV2Literal("0000-01-01 00:00:01"))); + assertRewrite(new LessThan(new Cast(datetime2, DateTimeV2Type.of(3)), new DateTimeV2Literal("0000-01-01 00:00:00.991")), + new LessThan(datetime2, new DateTimeV2Literal(DateTimeV2Type.of(2), "0000-01-01 00:00:01.00"))); + assertRewrite(new LessThan(new Cast(datetime2, DateTimeV2Type.of(6)), new DateTimeV2Literal("0000-01-01 00:00:00.999999")), + new LessThan(datetime2, new DateTimeV2Literal(DateTimeV2Type.of(2), "0000-01-01 00:00:01.00"))); + assertRewrite(new LessThan(new Cast(datetimev1, DateTimeV2Type.of(1)), new DateTimeV2Literal(DateTimeV2Type.of(1), "0000-01-01 00:00:00.0")), + new LessThan(datetimev1, new DateTimeLiteral("0000-01-01 00:00:00"))); + assertRewrite(new LessThan(new Cast(datetimev1, DateTimeV2Type.of(1)), new DateTimeV2Literal("0000-01-01 00:00:00.1")), + new LessThan(datetimev1, new DateTimeLiteral("0000-01-01 00:00:01"))); + assertRewrite(new GreaterThan(new Cast(date, DateTimeType.INSTANCE), new DateTimeLiteral("0000-01-01 00:00:00")), + new GreaterThan(date, new DateV2Literal("0000-01-01"))); + assertRewrite(new GreaterThan(new Cast(date, DateTimeV2Type.SYSTEM_DEFAULT), new DateTimeV2Literal("0000-01-01 00:00:00")), + new GreaterThan(date, new DateV2Literal("0000-01-01"))); + assertRewrite(new GreaterThan(new Cast(datev1, DateTimeType.INSTANCE), new DateTimeLiteral("0000-01-01 00:00:00")), + new GreaterThan(datev1, new DateLiteral("0000-01-01"))); + assertRewrite(new GreaterThan(new Cast(datev1, DateTimeV2Type.SYSTEM_DEFAULT), new DateTimeV2Literal("0000-01-01 00:00:00")), + new GreaterThan(datev1, new DateLiteral("0000-01-01"))); + assertRewrite(new GreaterThan(new Cast(datetime0, DateTimeV2Type.of(1)), new DateTimeV2Literal("0000-01-01 00:00:00.1")), + new GreaterThan(datetime0, new DateTimeV2Literal("0000-01-01 00:00:00"))); + assertRewrite(new GreaterThan(new Cast(datetime2, DateTimeV2Type.of(3)), new DateTimeV2Literal("0000-01-01 00:00:00.991")), + new GreaterThan(datetime2, new DateTimeV2Literal("0000-01-01 00:00:00.99"))); + assertRewrite(new GreaterThan(new Cast(datetime2, DateTimeV2Type.of(6)), new DateTimeV2Literal("0000-01-01 00:00:00.999999")), + new GreaterThan(datetime2, new DateTimeV2Literal("0000-01-01 00:00:00.99"))); + assertRewrite(new GreaterThan(new Cast(datetimev1, DateTimeV2Type.of(1)), new DateTimeV2Literal(DateTimeV2Type.of(1), "0000-01-01 00:00:00.0")), + new GreaterThan(datetimev1, new DateTimeLiteral("0000-01-01 00:00:00"))); + assertRewrite(new GreaterThan(new Cast(datetimev1, DateTimeV2Type.of(1)), new DateTimeV2Literal("0000-01-01 00:00:00.1")), + new GreaterThan(datetimev1, new DateTimeLiteral("0000-01-01 00:00:00"))); + + // test overflow, not cast + assertRewrite(new LessThan(new Cast(date, DateTimeType.INSTANCE), new DateTimeLiteral("9999-12-31 23:59:59")), + new LessThan(new Cast(date, DateTimeType.INSTANCE), new DateTimeLiteral("9999-12-31 23:59:59"))); + assertRewrite(new LessThan(new Cast(date, DateTimeV2Type.SYSTEM_DEFAULT), new DateTimeV2Literal("9999-12-31 23:59:59")), + new LessThan(new Cast(date, DateTimeV2Type.SYSTEM_DEFAULT), new DateTimeV2Literal("9999-12-31 23:59:59"))); + assertRewrite(new LessThan(new Cast(datev1, DateTimeType.INSTANCE), new DateTimeLiteral("9999-12-31 23:59:59")), + new LessThan(new Cast(datev1, DateTimeType.INSTANCE), new DateTimeLiteral("9999-12-31 23:59:59"))); + assertRewrite(new LessThan(new Cast(datev1, DateTimeV2Type.SYSTEM_DEFAULT), new DateTimeV2Literal("9999-12-31 23:59:59")), + new LessThan(new Cast(datev1, DateTimeV2Type.SYSTEM_DEFAULT), new DateTimeV2Literal("9999-12-31 23:59:59"))); + assertRewrite(new LessThan(new Cast(datetime0, DateTimeV2Type.of(1)), new DateTimeV2Literal("9999-12-31 23:59:59.1")), + new LessThan(new Cast(datetime0, DateTimeV2Type.of(1)), new DateTimeV2Literal("9999-12-31 23:59:59.1"))); + assertRewrite(new LessThan(new Cast(datetime2, DateTimeV2Type.of(3)), new DateTimeV2Literal("9999-12-31 23:59:59.991")), + new LessThan(new Cast(datetime2, DateTimeV2Type.of(3)), new DateTimeV2Literal("9999-12-31 23:59:59.991"))); + assertRewrite(new LessThan(new Cast(datetime2, DateTimeV2Type.of(6)), new DateTimeV2Literal("9999-12-31 23:59:59.999999")), + new LessThan(new Cast(datetime2, DateTimeV2Type.of(6)), new DateTimeV2Literal("9999-12-31 23:59:59.999999"))); + assertRewrite(new LessThan(new Cast(datetimev1, DateTimeV2Type.of(1)), new DateTimeV2Literal("9999-12-31 23:59:59.1")), + new LessThan(new Cast(datetimev1, DateTimeV2Type.of(1)), new DateTimeV2Literal("9999-12-31 23:59:59.1"))); } @Test @@ -485,6 +541,17 @@ void testIntCmpDecimalV3Literal() { new LessThan(bigIntSlot, new BigIntLiteral(13L))); assertRewrite(new LessThanEqual(new Cast(bigIntSlot, DecimalV3Type.createDecimalV3Type(3, 1)), new DecimalV3Literal(new BigDecimal("12.3"))), new LessThanEqual(bigIntSlot, new BigIntLiteral(12L))); + + assertRewrite(new LessThan(new Cast(bigIntSlot, DecimalV3Type.createDecimalV3Type(20, 1)), new DecimalV3Literal(new BigDecimal("-9223372036854775808.1"))), + ExpressionUtils.falseOrNull(bigIntSlot)); + assertRewrite(new GreaterThanEqual(new Cast(bigIntSlot, DecimalV3Type.createDecimalV3Type(20, 1)), new DecimalV3Literal(new BigDecimal("-9223372036854775808.1"))), + ExpressionUtils.trueOrNull(bigIntSlot)); + assertRewrite(new LessThan(new Cast(bigIntSlot, DecimalV3Type.createDecimalV3Type(20, 1)), new DecimalV3Literal(new BigDecimal("-9223372036854775807.1"))), + new LessThan(bigIntSlot, new BigIntLiteral(-9223372036854775807L))); + assertRewrite(new GreaterThanEqual(new Cast(bigIntSlot, DecimalV3Type.createDecimalV3Type(20, 1)), new DecimalV3Literal(new BigDecimal("9223372036854775807.1"))), + ExpressionUtils.falseOrNull(bigIntSlot)); + assertRewrite(new LessThan(new Cast(bigIntSlot, DecimalV3Type.createDecimalV3Type(20, 1)), new DecimalV3Literal(new BigDecimal("9223372036854775806.1"))), + new LessThan(bigIntSlot, new BigIntLiteral(9223372036854775807L))); } @Test