Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit ecdd44e

Browse filesBrowse files
authored
branch-3.0: [fix](nereids) fix compare with date like literal #45382 (#45596)
cherry pick from #45382
1 parent aaaf59f commit ecdd44e
Copy full SHA for ecdd44e

File tree

5 files changed

+184
-90
lines changed
Filter options

5 files changed

+184
-90
lines changed

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

Copy file name to clipboardExpand all lines: fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/SimplifyComparisonPredicate.java
+66-86Lines changed: 66 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,12 @@
2121
import org.apache.doris.nereids.rules.expression.ExpressionPatternMatcher;
2222
import org.apache.doris.nereids.rules.expression.ExpressionPatternRuleFactory;
2323
import org.apache.doris.nereids.rules.expression.ExpressionRewriteContext;
24-
import org.apache.doris.nereids.trees.expressions.And;
2524
import org.apache.doris.nereids.trees.expressions.Cast;
2625
import org.apache.doris.nereids.trees.expressions.ComparisonPredicate;
2726
import org.apache.doris.nereids.trees.expressions.EqualTo;
2827
import org.apache.doris.nereids.trees.expressions.Expression;
2928
import org.apache.doris.nereids.trees.expressions.GreaterThan;
3029
import org.apache.doris.nereids.trees.expressions.GreaterThanEqual;
31-
import org.apache.doris.nereids.trees.expressions.IsNull;
3230
import org.apache.doris.nereids.trees.expressions.LessThan;
3331
import org.apache.doris.nereids.trees.expressions.LessThanEqual;
3432
import org.apache.doris.nereids.trees.expressions.NullSafeEqual;
@@ -44,16 +42,16 @@
4442
import org.apache.doris.nereids.trees.expressions.literal.IntegerLikeLiteral;
4543
import org.apache.doris.nereids.trees.expressions.literal.IntegerLiteral;
4644
import org.apache.doris.nereids.trees.expressions.literal.Literal;
47-
import org.apache.doris.nereids.trees.expressions.literal.NullLiteral;
4845
import org.apache.doris.nereids.trees.expressions.literal.SmallIntLiteral;
4946
import org.apache.doris.nereids.trees.expressions.literal.TinyIntLiteral;
50-
import org.apache.doris.nereids.types.BooleanType;
47+
import org.apache.doris.nereids.types.DataType;
5148
import org.apache.doris.nereids.types.DateTimeType;
5249
import org.apache.doris.nereids.types.DateTimeV2Type;
5350
import org.apache.doris.nereids.types.DateType;
5451
import org.apache.doris.nereids.types.DateV2Type;
5552
import org.apache.doris.nereids.types.DecimalV3Type;
5653
import org.apache.doris.nereids.types.coercion.DateLikeType;
54+
import org.apache.doris.nereids.util.ExpressionUtils;
5755
import org.apache.doris.nereids.util.TypeCoercionUtils;
5856

5957
import com.google.common.base.Preconditions;
@@ -71,12 +69,6 @@
7169
public class SimplifyComparisonPredicate extends AbstractExpressionRewriteRule implements ExpressionPatternRuleFactory {
7270
public static SimplifyComparisonPredicate INSTANCE = new SimplifyComparisonPredicate();
7371

74-
enum AdjustType {
75-
LOWER,
76-
UPPER,
77-
NONE
78-
}
79-
8072
@Override
8173
public List<ExpressionPatternMatcher<? extends Expression>> buildRules() {
8274
return ImmutableList.of(
@@ -116,77 +108,83 @@ public static Expression simplify(ComparisonPredicate cp) {
116108
return cp;
117109
}
118110

119-
private static Expression processComparisonPredicateDateTimeV2Literal(
111+
private static Expression processDateTimeLikeComparisonPredicateDateTimeV2Literal(
120112
ComparisonPredicate comparisonPredicate, Expression left, DateTimeV2Literal right) {
121-
DateTimeV2Type leftType = (DateTimeV2Type) left.getDataType();
113+
DataType leftType = left.getDataType();
114+
int toScale = 0;
115+
if (leftType instanceof DateTimeType) {
116+
toScale = 0;
117+
} else if (leftType instanceof DateTimeV2Type) {
118+
toScale = ((DateTimeV2Type) leftType).getScale();
119+
} else {
120+
return comparisonPredicate;
121+
}
122122
DateTimeV2Type rightType = right.getDataType();
123-
if (leftType.getScale() < rightType.getScale()) {
124-
int toScale = leftType.getScale();
123+
if (toScale < rightType.getScale()) {
125124
if (comparisonPredicate instanceof EqualTo) {
126125
long originValue = right.getMicroSecond();
127126
right = right.roundCeiling(toScale);
128-
if (right.getMicroSecond() == originValue) {
129-
return comparisonPredicate.withChildren(left, right);
130-
} else {
131-
if (left.nullable()) {
132-
// TODO: the ideal way is to return an If expr like:
133-
// return new If(new IsNull(left), new NullLiteral(BooleanType.INSTANCE),
134-
// BooleanLiteral.of(false));
135-
// but current fold constant rule can't handle such complex expr with null literal
136-
// before supporting complex conjuncts with null literal folding rules,
137-
// we use a trick way like this:
138-
return new And(new IsNull(left), new NullLiteral(BooleanType.INSTANCE));
139-
} else {
140-
return BooleanLiteral.of(false);
141-
}
127+
if (right.getMicroSecond() != originValue) {
128+
// TODO: the ideal way is to return an If expr like:
129+
// return new If(new IsNull(left), new NullLiteral(BooleanType.INSTANCE),
130+
// BooleanLiteral.of(false));
131+
// but current fold constant rule can't handle such complex expr with null literal
132+
// before supporting complex conjuncts with null literal folding rules,
133+
// we use a trick way like this:
134+
return ExpressionUtils.falseOrNull(left);
142135
}
143136
} else if (comparisonPredicate instanceof NullSafeEqual) {
144137
long originValue = right.getMicroSecond();
145138
right = right.roundCeiling(toScale);
146-
if (right.getMicroSecond() == originValue) {
147-
return comparisonPredicate.withChildren(left, right);
148-
} else {
139+
if (right.getMicroSecond() != originValue) {
149140
return BooleanLiteral.of(false);
150141
}
151142
} else if (comparisonPredicate instanceof GreaterThan
152143
|| comparisonPredicate instanceof LessThanEqual) {
153-
return comparisonPredicate.withChildren(left, right.roundFloor(toScale));
144+
right = right.roundFloor(toScale);
154145
} else if (comparisonPredicate instanceof LessThan
155146
|| comparisonPredicate instanceof GreaterThanEqual) {
156-
return comparisonPredicate.withChildren(left, right.roundCeiling(toScale));
147+
right = right.roundCeiling(toScale);
148+
} else {
149+
return comparisonPredicate;
150+
}
151+
Expression newRight = leftType instanceof DateTimeType ? migrateToDateTime(right) : right;
152+
return comparisonPredicate.withChildren(left, newRight);
153+
} else {
154+
if (leftType instanceof DateTimeType) {
155+
return comparisonPredicate.withChildren(left, migrateToDateTime(right));
156+
} else {
157+
return comparisonPredicate;
157158
}
158159
}
159-
return comparisonPredicate;
160160
}
161161

162162
private static Expression processDateLikeTypeCoercion(ComparisonPredicate cp, Expression left, Expression right) {
163163
if (left instanceof Cast && right instanceof DateLiteral) {
164164
Cast cast = (Cast) left;
165-
if (cast.child().getDataType() instanceof DateTimeType) {
165+
if (cast.child().getDataType() instanceof DateTimeType
166+
|| cast.child().getDataType() instanceof DateTimeV2Type) {
166167
if (right instanceof DateTimeV2Literal) {
167-
left = cast.child();
168-
right = migrateToDateTime((DateTimeV2Literal) right);
169-
}
170-
}
171-
if (cast.child().getDataType() instanceof DateTimeV2Type) {
172-
if (right instanceof DateTimeV2Literal) {
173-
left = cast.child();
174-
return processComparisonPredicateDateTimeV2Literal(cp, left, (DateTimeV2Literal) right);
168+
return processDateTimeLikeComparisonPredicateDateTimeV2Literal(
169+
cp, cast.child(), (DateTimeV2Literal) right);
175170
}
176171
}
172+
177173
// datetime to datev2
178174
if (cast.child().getDataType() instanceof DateType || cast.child().getDataType() instanceof DateV2Type) {
179175
if (right instanceof DateTimeLiteral) {
180-
if (cannotAdjust((DateTimeLiteral) right, cp)) {
181-
return cp;
182-
}
183-
AdjustType type = AdjustType.NONE;
184-
if (cp instanceof GreaterThanEqual || cp instanceof LessThan) {
185-
type = AdjustType.UPPER;
186-
} else if (cp instanceof GreaterThan || cp instanceof LessThanEqual) {
187-
type = AdjustType.LOWER;
176+
DateTimeLiteral dateTimeLiteral = (DateTimeLiteral) right;
177+
right = migrateToDateV2(dateTimeLiteral);
178+
if (dateTimeLiteral.getHour() != 0 || dateTimeLiteral.getMinute() != 0
179+
|| dateTimeLiteral.getSecond() != 0) {
180+
if (cp instanceof EqualTo) {
181+
return ExpressionUtils.falseOrNull(cast.child());
182+
} else if (cp instanceof NullSafeEqual) {
183+
return BooleanLiteral.FALSE;
184+
} else if (cp instanceof GreaterThanEqual || cp instanceof LessThan) {
185+
right = ((DateV2Literal) right).plusDays(1);
186+
}
188187
}
189-
right = migrateToDateV2((DateTimeLiteral) right, type);
190188
if (cast.child().getDataType() instanceof DateV2Type) {
191189
left = cast.child();
192190
}
@@ -239,18 +237,13 @@ private static Expression processDecimalV3TypeCoercion(ComparisonPredicate compa
239237
comparisonPredicate.withChildren(left, new DecimalV3Literal(
240238
literal.getValue().setScale(toScale, RoundingMode.UNNECESSARY))));
241239
} catch (ArithmeticException e) {
242-
if (left.nullable()) {
243-
// TODO: the ideal way is to return an If expr like:
244-
// return new If(new IsNull(left), new NullLiteral(BooleanType.INSTANCE),
245-
// BooleanLiteral.of(false));
246-
// but current fold constant rule can't handle such complex expr with null literal
247-
// before supporting complex conjuncts with null literal folding rules,
248-
// we use a trick way like this:
249-
return new And(new IsNull(left),
250-
new NullLiteral(BooleanType.INSTANCE));
251-
} else {
252-
return BooleanLiteral.of(false);
253-
}
240+
// TODO: the ideal way is to return an If expr like:
241+
// return new If(new IsNull(left), new NullLiteral(BooleanType.INSTANCE),
242+
// BooleanLiteral.of(false));
243+
// but current fold constant rule can't handle such complex expr with null literal
244+
// before supporting complex conjuncts with null literal folding rules,
245+
// we use a trick way like this:
246+
return ExpressionUtils.falseOrNull(left);
254247
}
255248
} else if (comparisonPredicate instanceof NullSafeEqual) {
256249
try {
@@ -286,17 +279,13 @@ private static Expression processIntegerDecimalLiteralComparison(
286279
literal = literal.stripTrailingZeros();
287280
if (literal.scale() > 0) {
288281
if (comparisonPredicate instanceof EqualTo) {
289-
if (left.nullable()) {
290-
// TODO: the ideal way is to return an If expr like:
291-
// return new If(new IsNull(left), new NullLiteral(BooleanType.INSTANCE),
292-
// BooleanLiteral.of(false));
293-
// but current fold constant rule can't handle such complex expr with null literal
294-
// before supporting complex conjuncts with null literal folding rules,
295-
// we use a trick way like this:
296-
return new And(new IsNull(left), new NullLiteral(BooleanType.INSTANCE));
297-
} else {
298-
return BooleanLiteral.of(false);
299-
}
282+
// TODO: the ideal way is to return an If expr like:
283+
// return new If(new IsNull(left), new NullLiteral(BooleanType.INSTANCE),
284+
// BooleanLiteral.of(false));
285+
// but current fold constant rule can't handle such complex expr with null literal
286+
// before supporting complex conjuncts with null literal folding rules,
287+
// we use a trick way like this:
288+
return ExpressionUtils.falseOrNull(left);
300289
} else if (comparisonPredicate instanceof NullSafeEqual) {
301290
return BooleanLiteral.of(false);
302291
} else if (comparisonPredicate instanceof GreaterThan
@@ -342,17 +331,8 @@ private static Expression migrateToDateTime(DateTimeV2Literal l) {
342331
return new DateTimeLiteral(l.getYear(), l.getMonth(), l.getDay(), l.getHour(), l.getMinute(), l.getSecond());
343332
}
344333

345-
private static boolean cannotAdjust(DateTimeLiteral l, ComparisonPredicate cp) {
346-
return cp instanceof EqualTo && (l.getHour() != 0 || l.getMinute() != 0 || l.getSecond() != 0);
347-
}
348-
349-
private static Expression migrateToDateV2(DateTimeLiteral l, AdjustType type) {
350-
DateV2Literal d = new DateV2Literal(l.getYear(), l.getMonth(), l.getDay());
351-
if (type == AdjustType.UPPER && (l.getHour() != 0 || l.getMinute() != 0 || l.getSecond() != 0)) {
352-
return d.plusDays(1);
353-
} else {
354-
return d;
355-
}
334+
private static Expression migrateToDateV2(DateTimeLiteral l) {
335+
return new DateV2Literal(l.getYear(), l.getMonth(), l.getDay());
356336
}
357337

358338
private static Expression migrateToDate(DateV2Literal l) {

‎fe/fe-core/src/main/java/org/apache/doris/nereids/util/ExpressionUtils.java

Copy file name to clipboardExpand all lines: fe/fe-core/src/main/java/org/apache/doris/nereids/util/ExpressionUtils.java
+16Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,22 @@ public static Expression or(Collection<Expression> expressions) {
198198
return combineAsLeftDeepTree(Or.class, expressions);
199199
}
200200

201+
public static Expression falseOrNull(Expression expression) {
202+
if (expression.nullable()) {
203+
return new And(new IsNull(expression), new NullLiteral(BooleanType.INSTANCE));
204+
} else {
205+
return BooleanLiteral.FALSE;
206+
}
207+
}
208+
209+
public static Expression trueOrNull(Expression expression) {
210+
if (expression.nullable()) {
211+
return new Or(new Not(new IsNull(expression)), new NullLiteral(BooleanType.INSTANCE));
212+
} else {
213+
return BooleanLiteral.TRUE;
214+
}
215+
}
216+
201217
/**
202218
* Use AND/OR to combine expressions together.
203219
*/

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.