21
21
import org .apache .doris .nereids .rules .expression .ExpressionPatternMatcher ;
22
22
import org .apache .doris .nereids .rules .expression .ExpressionPatternRuleFactory ;
23
23
import org .apache .doris .nereids .rules .expression .ExpressionRewriteContext ;
24
- import org .apache .doris .nereids .trees .expressions .And ;
25
24
import org .apache .doris .nereids .trees .expressions .Cast ;
26
25
import org .apache .doris .nereids .trees .expressions .ComparisonPredicate ;
27
26
import org .apache .doris .nereids .trees .expressions .EqualTo ;
28
27
import org .apache .doris .nereids .trees .expressions .Expression ;
29
28
import org .apache .doris .nereids .trees .expressions .GreaterThan ;
30
29
import org .apache .doris .nereids .trees .expressions .GreaterThanEqual ;
31
- import org .apache .doris .nereids .trees .expressions .IsNull ;
32
30
import org .apache .doris .nereids .trees .expressions .LessThan ;
33
31
import org .apache .doris .nereids .trees .expressions .LessThanEqual ;
34
32
import org .apache .doris .nereids .trees .expressions .NullSafeEqual ;
44
42
import org .apache .doris .nereids .trees .expressions .literal .IntegerLikeLiteral ;
45
43
import org .apache .doris .nereids .trees .expressions .literal .IntegerLiteral ;
46
44
import org .apache .doris .nereids .trees .expressions .literal .Literal ;
47
- import org .apache .doris .nereids .trees .expressions .literal .NullLiteral ;
48
45
import org .apache .doris .nereids .trees .expressions .literal .SmallIntLiteral ;
49
46
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 ;
51
48
import org .apache .doris .nereids .types .DateTimeType ;
52
49
import org .apache .doris .nereids .types .DateTimeV2Type ;
53
50
import org .apache .doris .nereids .types .DateType ;
54
51
import org .apache .doris .nereids .types .DateV2Type ;
55
52
import org .apache .doris .nereids .types .DecimalV3Type ;
56
53
import org .apache .doris .nereids .types .coercion .DateLikeType ;
54
+ import org .apache .doris .nereids .util .ExpressionUtils ;
57
55
import org .apache .doris .nereids .util .TypeCoercionUtils ;
58
56
59
57
import com .google .common .base .Preconditions ;
71
69
public class SimplifyComparisonPredicate extends AbstractExpressionRewriteRule implements ExpressionPatternRuleFactory {
72
70
public static SimplifyComparisonPredicate INSTANCE = new SimplifyComparisonPredicate ();
73
71
74
- enum AdjustType {
75
- LOWER ,
76
- UPPER ,
77
- NONE
78
- }
79
-
80
72
@ Override
81
73
public List <ExpressionPatternMatcher <? extends Expression >> buildRules () {
82
74
return ImmutableList .of (
@@ -116,77 +108,83 @@ public static Expression simplify(ComparisonPredicate cp) {
116
108
return cp ;
117
109
}
118
110
119
- private static Expression processComparisonPredicateDateTimeV2Literal (
111
+ private static Expression processDateTimeLikeComparisonPredicateDateTimeV2Literal (
120
112
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
+ }
122
122
DateTimeV2Type rightType = right .getDataType ();
123
- if (leftType .getScale () < rightType .getScale ()) {
124
- int toScale = leftType .getScale ();
123
+ if (toScale < rightType .getScale ()) {
125
124
if (comparisonPredicate instanceof EqualTo ) {
126
125
long originValue = right .getMicroSecond ();
127
126
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 );
142
135
}
143
136
} else if (comparisonPredicate instanceof NullSafeEqual ) {
144
137
long originValue = right .getMicroSecond ();
145
138
right = right .roundCeiling (toScale );
146
- if (right .getMicroSecond () == originValue ) {
147
- return comparisonPredicate .withChildren (left , right );
148
- } else {
139
+ if (right .getMicroSecond () != originValue ) {
149
140
return BooleanLiteral .of (false );
150
141
}
151
142
} else if (comparisonPredicate instanceof GreaterThan
152
143
|| comparisonPredicate instanceof LessThanEqual ) {
153
- return comparisonPredicate . withChildren ( left , right .roundFloor (toScale ) );
144
+ right = right .roundFloor (toScale );
154
145
} else if (comparisonPredicate instanceof LessThan
155
146
|| 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 ;
157
158
}
158
159
}
159
- return comparisonPredicate ;
160
160
}
161
161
162
162
private static Expression processDateLikeTypeCoercion (ComparisonPredicate cp , Expression left , Expression right ) {
163
163
if (left instanceof Cast && right instanceof DateLiteral ) {
164
164
Cast cast = (Cast ) left ;
165
- if (cast .child ().getDataType () instanceof DateTimeType ) {
165
+ if (cast .child ().getDataType () instanceof DateTimeType
166
+ || cast .child ().getDataType () instanceof DateTimeV2Type ) {
166
167
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 );
175
170
}
176
171
}
172
+
177
173
// datetime to datev2
178
174
if (cast .child ().getDataType () instanceof DateType || cast .child ().getDataType () instanceof DateV2Type ) {
179
175
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
+ }
188
187
}
189
- right = migrateToDateV2 ((DateTimeLiteral ) right , type );
190
188
if (cast .child ().getDataType () instanceof DateV2Type ) {
191
189
left = cast .child ();
192
190
}
@@ -239,18 +237,13 @@ private static Expression processDecimalV3TypeCoercion(ComparisonPredicate compa
239
237
comparisonPredicate .withChildren (left , new DecimalV3Literal (
240
238
literal .getValue ().setScale (toScale , RoundingMode .UNNECESSARY ))));
241
239
} 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 );
254
247
}
255
248
} else if (comparisonPredicate instanceof NullSafeEqual ) {
256
249
try {
@@ -286,17 +279,13 @@ private static Expression processIntegerDecimalLiteralComparison(
286
279
literal = literal .stripTrailingZeros ();
287
280
if (literal .scale () > 0 ) {
288
281
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 );
300
289
} else if (comparisonPredicate instanceof NullSafeEqual ) {
301
290
return BooleanLiteral .of (false );
302
291
} else if (comparisonPredicate instanceof GreaterThan
@@ -342,17 +331,8 @@ private static Expression migrateToDateTime(DateTimeV2Literal l) {
342
331
return new DateTimeLiteral (l .getYear (), l .getMonth (), l .getDay (), l .getHour (), l .getMinute (), l .getSecond ());
343
332
}
344
333
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 ());
356
336
}
357
337
358
338
private static Expression migrateToDate (DateV2Literal l ) {
0 commit comments