Skip to content

Commit 61242ee

Browse files
branch-4.0: [fix](date time comparison) fix date time compare with low scale literal #59630 (#59659)
Cherry-picked from #59630 Co-authored-by: yujun <[email protected]>
1 parent b32e528 commit 61242ee

File tree

3 files changed

+24
-62
lines changed

3 files changed

+24
-62
lines changed

fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/SimplifyComparisonPredicate.java

Lines changed: 9 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -255,47 +255,17 @@ private static Expression processDateTimeLikeComparisonPredicateDateTimeV2Litera
255255
}
256256
Expression newRight = leftType instanceof DateTimeType ? migrateToDateTime(right) : right;
257257
return comparisonPredicate.withChildren(left, newRight);
258-
} else if (toScale > rightType.getScale()) {
259-
// when toScale > right's scale, then left must be datetimev2, not datetimev1
260-
Preconditions.checkArgument(leftType instanceof DateTimeV2Type, leftType);
261-
262-
// for expression cast(left as datetime(2)) = '2020-12-20 01:02:03.45'
263-
// then left scale is 5, right = '2020-12-20 01:02:03.45", right scale is 2,
264-
// then left >= '2020-12-20 01:02:03.45000' && left <= '2020-12-20 01:02:03.45999'
265-
// for low bound, it add (5-2) '0' to the origin right's tail
266-
// for up bound, it add (5-2) '9' to the origin right's tail
267-
// when roundFloor to high scale, its microsecond shouldn't change, only change its data type.
268-
DateTimeV2Literal lowBound = right.roundFloor(toScale);
269-
long upMicroSecond = 0;
270-
for (int i = 0; i < toScale - rightType.getScale(); i++) {
271-
upMicroSecond = 10 * upMicroSecond + 9;
272-
}
273-
upMicroSecond *= (int) Math.pow(10, 6 - toScale);
274-
upMicroSecond += lowBound.getMicroSecond();
275-
// left must be a datetimev2
276-
DateTimeV2Literal upBound = new DateTimeV2Literal((DateTimeV2Type) leftType,
277-
right.getYear(), right.getMonth(), right.getDay(),
278-
right.getHour(), right.getMinute(), right.getSecond(), upMicroSecond);
279-
280-
if (comparisonPredicate instanceof GreaterThanEqual || comparisonPredicate instanceof LessThan) {
281-
return comparisonPredicate.withChildren(left, lowBound);
282-
}
283-
284-
if (comparisonPredicate instanceof GreaterThan || comparisonPredicate instanceof LessThanEqual) {
285-
return comparisonPredicate.withChildren(left, upBound);
286-
}
287-
288-
if (comparisonPredicate instanceof EqualTo || comparisonPredicate instanceof NullSafeEqual) {
289-
List<Expression> conjunctions = Lists.newArrayListWithExpectedSize(3);
290-
conjunctions.add(new GreaterThanEqual(left, lowBound));
291-
conjunctions.add(new LessThanEqual(left, upBound));
292-
if (left.nullable() && comparisonPredicate instanceof NullSafeEqual) {
293-
conjunctions.add(new Not(new IsNull(left)));
294-
}
295-
return new And(conjunctions);
296-
}
297258
}
298259

260+
// if toScale > rightType.scale, don't try to rewrite it like
261+
// "A > '2020-12-20 01:02:03.23450' and A < '2020-12-20 01:02:03.23459'"
262+
// because the cast will use rounding, not truncating.
263+
// and the rounding may generate null result.
264+
// for example: for expression E = "cast(A as datetime(4))) > '2020-12-20 01:02:03.23456'"
265+
// if one row for A is '9999-12-31 23:59:59.99995', then 'cast(A as datetime(4))' will be null
266+
// (because the cast result will exceed year 9999),
267+
// so this row for E will be null too.
268+
299269
if (leftType instanceof DateTimeType) {
300270
return comparisonPredicate.withChildren(left, migrateToDateTime(right));
301271
} else {

fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/LessThanEqual.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ public LessThanEqual(Expression left, Expression right) {
4141
}
4242

4343
public LessThanEqual(Expression left, Expression right, boolean inferred) {
44-
super(ImmutableList.of(left, right), "<=", inferred);
44+
this(ImmutableList.of(left, right), inferred);
4545
}
4646

4747
private LessThanEqual(List<Expression> children) {

fe/fe-core/src/test/java/org/apache/doris/nereids/rules/expression/rules/SimplifyComparisonPredicateTest.java

Lines changed: 14 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -397,40 +397,32 @@ void testDateTimeV2CmpDateTimeV2() {
397397
new GreaterThanEqual(datetime2, new DateTimeV2Literal(DateTimeV2Type.of(2), "9999-12-31 00:00:00.00")),
398398
new LessThanEqual(datetime2, new DateTimeV2Literal(DateTimeV2Type.of(2), "9999-12-31 23:59:59.99")),
399399
new Not(new IsNull(datetime2)))));
400+
401+
// when cast from high scale datetime to low scale datetime, don't change anything because the cast may generate null
400402
assertRewrite(new GreaterThan(new Cast(datetime2, DateTimeV2Type.of(0)), new DateTimeV2Literal(DateTimeV2Type.of(0), "9999-12-31 12:34:56")),
401-
new GreaterThan(datetime2, new DateTimeV2Literal(DateTimeV2Type.of(2), "9999-12-31 12:34:56.99")));
403+
new GreaterThan(new Cast(datetime2, DateTimeV2Type.of(0)), new DateTimeV2Literal(DateTimeV2Type.of(0), "9999-12-31 12:34:56")));
402404
assertRewrite(new GreaterThanEqual(new Cast(datetime2, DateTimeV2Type.of(0)), new DateTimeV2Literal(DateTimeV2Type.of(0), "9999-12-31 12:34:56")),
403-
new GreaterThanEqual(datetime2, new DateTimeV2Literal(DateTimeV2Type.of(2), "9999-12-31 12:34:56.00")));
405+
new GreaterThanEqual(new Cast(datetime2, DateTimeV2Type.of(0)), new DateTimeV2Literal(DateTimeV2Type.of(0), "9999-12-31 12:34:56")));
404406
assertRewrite(new LessThan(new Cast(datetime2, DateTimeV2Type.of(0)), new DateTimeV2Literal(DateTimeV2Type.of(0), "9999-12-31 12:34:56")),
405-
new LessThan(datetime2, new DateTimeV2Literal(DateTimeV2Type.of(2), "9999-12-31 12:34:56.00")));
407+
new LessThan(new Cast(datetime2, DateTimeV2Type.of(0)), new DateTimeV2Literal(DateTimeV2Type.of(0), "9999-12-31 12:34:56")));
406408
assertRewrite(new LessThanEqual(new Cast(datetime2, DateTimeV2Type.of(0)), new DateTimeV2Literal(DateTimeV2Type.of(0), "9999-12-31 12:34:56")),
407-
new LessThanEqual(datetime2, new DateTimeV2Literal(DateTimeV2Type.of(2), "9999-12-31 12:34:56.99")));
409+
new LessThanEqual(new Cast(datetime2, DateTimeV2Type.of(0)), new DateTimeV2Literal(DateTimeV2Type.of(0), "9999-12-31 12:34:56")));
408410
assertRewrite(new EqualTo(new Cast(datetime2, DateTimeV2Type.of(0)), new DateTimeV2Literal(DateTimeV2Type.of(0), "9999-12-31 12:34:56")),
409-
new And(
410-
new GreaterThanEqual(datetime2, new DateTimeV2Literal(DateTimeV2Type.of(2), "9999-12-31 12:34:56.00")),
411-
new LessThanEqual(datetime2, new DateTimeV2Literal(DateTimeV2Type.of(2), "9999-12-31 12:34:56.99"))));
411+
new EqualTo(new Cast(datetime2, DateTimeV2Type.of(0)), new DateTimeV2Literal(DateTimeV2Type.of(0), "9999-12-31 12:34:56")));
412412
assertRewrite(new NullSafeEqual(new Cast(datetime2, DateTimeV2Type.of(0)), new DateTimeV2Literal(DateTimeV2Type.of(0), "9999-12-31 12:34:56")),
413-
new And(ImmutableList.of(
414-
new GreaterThanEqual(datetime2, new DateTimeV2Literal(DateTimeV2Type.of(2), "9999-12-31 12:34:56.00")),
415-
new LessThanEqual(datetime2, new DateTimeV2Literal(DateTimeV2Type.of(2), "9999-12-31 12:34:56.99")),
416-
new Not(new IsNull(datetime2)))));
413+
new NullSafeEqual(new Cast(datetime2, DateTimeV2Type.of(0)), new DateTimeV2Literal(DateTimeV2Type.of(0), "9999-12-31 12:34:56")));
417414
assertRewrite(new GreaterThan(new Cast(datetime2, DateTimeV2Type.of(1)), new DateTimeV2Literal(DateTimeV2Type.of(1), "9999-12-31 12:34:56.7")),
418-
new GreaterThan(datetime2, new DateTimeV2Literal(DateTimeV2Type.of(2), "9999-12-31 12:34:56.79")));
415+
new GreaterThan(new Cast(datetime2, DateTimeV2Type.of(1)), new DateTimeV2Literal(DateTimeV2Type.of(1), "9999-12-31 12:34:56.7")));
419416
assertRewrite(new GreaterThanEqual(new Cast(datetime2, DateTimeV2Type.of(1)), new DateTimeV2Literal(DateTimeV2Type.of(1), "9999-12-31 12:34:56.7")),
420-
new GreaterThanEqual(datetime2, new DateTimeV2Literal(DateTimeV2Type.of(2), "9999-12-31 12:34:56.70")));
417+
new GreaterThanEqual(new Cast(datetime2, DateTimeV2Type.of(1)), new DateTimeV2Literal(DateTimeV2Type.of(1), "9999-12-31 12:34:56.7")));
421418
assertRewrite(new LessThan(new Cast(datetime2, DateTimeV2Type.of(1)), new DateTimeV2Literal(DateTimeV2Type.of(1), "9999-12-31 12:34:56.7")),
422-
new LessThan(datetime2, new DateTimeV2Literal(DateTimeV2Type.of(2), "9999-12-31 12:34:56.70")));
419+
new LessThan(new Cast(datetime2, DateTimeV2Type.of(1)), new DateTimeV2Literal(DateTimeV2Type.of(1), "9999-12-31 12:34:56.7")));
423420
assertRewrite(new LessThanEqual(new Cast(datetime2, DateTimeV2Type.of(1)), new DateTimeV2Literal(DateTimeV2Type.of(1), "9999-12-31 12:34:56.7")),
424-
new LessThanEqual(datetime2, new DateTimeV2Literal(DateTimeV2Type.of(2), "9999-12-31 12:34:56.79")));
421+
new LessThanEqual(new Cast(datetime2, DateTimeV2Type.of(1)), new DateTimeV2Literal(DateTimeV2Type.of(1), "9999-12-31 12:34:56.7")));
425422
assertRewrite(new EqualTo(new Cast(datetime2, DateTimeV2Type.of(1)), new DateTimeV2Literal(DateTimeV2Type.of(1), "9999-12-31 12:34:56.7")),
426-
new And(
427-
new GreaterThanEqual(datetime2, new DateTimeV2Literal(DateTimeV2Type.of(2), "9999-12-31 12:34:56.70")),
428-
new LessThanEqual(datetime2, new DateTimeV2Literal(DateTimeV2Type.of(2), "9999-12-31 12:34:56.79"))));
423+
new EqualTo(new Cast(datetime2, DateTimeV2Type.of(1)), new DateTimeV2Literal(DateTimeV2Type.of(1), "9999-12-31 12:34:56.7")));
429424
assertRewrite(new NullSafeEqual(new Cast(datetime2, DateTimeV2Type.of(1)), new DateTimeV2Literal(DateTimeV2Type.of(1), "9999-12-31 12:34:56.7")),
430-
new And(ImmutableList.of(
431-
new GreaterThanEqual(datetime2, new DateTimeV2Literal(DateTimeV2Type.of(2), "9999-12-31 12:34:56.70")),
432-
new LessThanEqual(datetime2, new DateTimeV2Literal(DateTimeV2Type.of(2), "9999-12-31 12:34:56.79")),
433-
new Not(new IsNull(datetime2)))));
425+
new NullSafeEqual(new Cast(datetime2, DateTimeV2Type.of(1)), new DateTimeV2Literal(DateTimeV2Type.of(1), "9999-12-31 12:34:56.7")));
434426

435427
assertRewrite(new EqualTo(new Cast(datetime0, DateTimeV2Type.of(1)), new DateTimeV2Literal("9999-12-31 23:59:59.1")),
436428
ExpressionUtils.falseOrNull(datetime0));

0 commit comments

Comments
 (0)