englefly commented on code in PR #25180:
URL: https://github.com/apache/doris/pull/25180#discussion_r1354594753


##########
fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/SimplifyArithmeticComparisonRule.java:
##########
@@ -40,68 +58,90 @@
 public class SimplifyArithmeticComparisonRule extends 
AbstractExpressionRewriteRule {
     public static final SimplifyArithmeticComparisonRule INSTANCE = new 
SimplifyArithmeticComparisonRule();
 
-    @Override
-    public Expression visit(Expression expr, ExpressionRewriteContext context) 
{
-        return expr;
-    }
+    // don't rearrange multiplication because divide may loss precision
+    final Map<Class<? extends Expression>, Class<? extends Expression>> 
rearrangementMap = ImmutableMap
+            .<Class<? extends Expression>, Class<? extends 
Expression>>builder()
+            .put(Add.class, Subtract.class)
+            .put(Subtract.class, Add.class)
+            .put(Divide.class, Multiply.class)
+            .put(YearsSub.class, YearsAdd.class)
+            .put(YearsAdd.class, YearsSub.class)
+            .put(MonthsSub.class, MonthsAdd.class)
+            .put(MonthsAdd.class, MonthsSub.class)
+            .put(WeeksSub.class, WeeksAdd.class)
+            .put(WeeksAdd.class, WeeksSub.class)
+            .put(DaysSub.class, DaysAdd.class)
+            .put(DaysAdd.class, DaysSub.class)
+            .put(HoursSub.class, HoursAdd.class)
+            .put(HoursAdd.class, HoursSub.class)
+            .put(MinutesSub.class, MinutesAdd.class)
+            .put(MinutesAdd.class, MinutesSub.class)
+            .put(SecondsSub.class, SecondsAdd.class)
+            .put(SecondsAdd.class, SecondsSub.class)
+            .build();
 
-    private Expression process(ComparisonPredicate predicate) {
-        Expression left = predicate.left();
-        Expression right = predicate.right();
-        if (TypeUtils.isAddOrSubtract(left)) {
-            Expression p = left.child(1);
-            if (p.isConstant()) {
-                if (TypeUtils.isAdd(left)) {
-                    right = new Subtract(right, p);
-                }
-                if (TypeUtils.isSubtract(left)) {
-                    right = new Add(right, p);
-                }
-                left = left.child(0);
+    @Override
+    public Expression visitComparisonPredicate(ComparisonPredicate comparison, 
ExpressionRewriteContext context) {
+        ComparisonPredicate newComparison = comparison;
+        if (couldRearrange(comparison)) {
+            newComparison = normalize(comparison);
+            if (newComparison == null) {
+                return comparison;
             }
-        }
-        if (TypeUtils.isDivide(left)) {
-            Expression p = left.child(1);
-            if (p.isLiteral()) {
-                right = new Multiply(right, p);
-                left = left.child(0);
-                if (p.toString().startsWith("-")) {
-                    Expression tmp = right;
-                    right = left;
-                    left = tmp;
-                }
+            try {
+                List<Expression> children = 
tryRearrangeChildren(newComparison.left(), newComparison.right());
+                newComparison = (ComparisonPredicate) 
newComparison.withChildren(children);
+            } catch (Exception e) {
+                return comparison;
             }
         }
-        if (left != predicate.left() || right != predicate.right()) {
-            predicate = (ComparisonPredicate) predicate.withChildren(left, 
right);
-            return TypeCoercionUtils.processComparisonPredicate(predicate);
-        } else {
-            return predicate;
-        }
+        return TypeCoercionUtils.processComparisonPredicate(newComparison);
     }
 
-    @Override
-    public Expression visitGreaterThan(GreaterThan greaterThan, 
ExpressionRewriteContext context) {
-        return process(greaterThan);
+    private boolean couldRearrange(ComparisonPredicate cmp) {
+        return rearrangementMap.containsKey(cmp.left().getClass())
+                && !cmp.left().isConstant()
+                && 
cmp.left().children().stream().anyMatch(Expression::isConstant);
     }
 
-    @Override
-    public Expression visitGreaterThanEqual(GreaterThanEqual greaterThanEqual, 
ExpressionRewriteContext context) {
-        return process(greaterThanEqual);
-    }
+    private List<Expression> tryRearrangeChildren(Expression left, Expression 
right) throws Exception {
+        if (!left.child(1).isLiteral()) {
+            throw new RuntimeException(String.format("Expected literal when 
arranging children for Expr %s", left));
+        }
+        Literal leftLiteral = (Literal) left.child(1);
+        Expression leftExpr = left.child(0);
 
-    @Override
-    public Expression visitEqualTo(EqualTo equalTo, ExpressionRewriteContext 
context) {
-        return process(equalTo);
-    }
+        Class<? extends Expression> oppositeOperator = 
rearrangementMap.get(left.getClass());
+        Expression newChild = 
oppositeOperator.getConstructor(Expression.class, Expression.class)
+                .newInstance(right, leftLiteral);
 
-    @Override
-    public Expression visitLessThan(LessThan lessThan, 
ExpressionRewriteContext context) {
-        return process(lessThan);
+        if (left instanceof Divide && leftLiteral.compareTo(new 
IntegerLiteral(0)) < 0) {
+            // Multiplying by a negative number will change the operator.
+            return Arrays.asList(newChild, leftExpr);
+        }
+        return Arrays.asList(leftExpr, newChild);
     }
 
-    @Override
-    public Expression visitLessThanEqual(LessThanEqual lessThanEqual, 
ExpressionRewriteContext context) {
-        return process(lessThanEqual);
+    // Ensure that the second child must be Literal, such as
+    private @Nullable ComparisonPredicate normalize(ComparisonPredicate 
comparison) {

Review Comment:
   It would be better to make it public, because we could use it to generate 
more effecient Runtime filter.
   PostProcessor need this function



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscr...@doris.apache.org

For queries about this service, please contact Infrastructure at:
us...@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscr...@doris.apache.org
For additional commands, e-mail: commits-h...@doris.apache.org

Reply via email to