This is an automated email from the ASF dual-hosted git repository.

yiguolei pushed a commit to branch branch-2.1
in repository https://gitbox.apache.org/repos/asf/doris.git

commit d94d2c65f662428b0e8a26e06fece0a2f0d9367c
Author: morrySnow <101034200+morrys...@users.noreply.github.com>
AuthorDate: Tue Mar 5 19:39:24 2024 +0800

    [fix](Nereids) let OrToIn rewritten result have stable order (#31731)
---
 .../apache/doris/nereids/rules/expression/rules/OrToIn.java | 13 +++++++------
 .../doris/nereids/rules/expression/rules/SimplifyRange.java |  2 +-
 .../apache/doris/nereids/trees/plans/algebra/Filter.java    |  4 +---
 .../org/apache/doris/nereids/rules/rewrite/OrToInTest.java  | 10 ++++++++++
 4 files changed, 19 insertions(+), 10 deletions(-)

diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/OrToIn.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/OrToIn.java
index 6df68e47a04..b085f70da6e 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/OrToIn.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/OrToIn.java
@@ -32,8 +32,7 @@ import com.google.common.collect.ImmutableList;
 import com.google.common.collect.Maps;
 
 import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.HashSet;
+import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -60,7 +59,7 @@ public class OrToIn extends 
DefaultExpressionRewriter<ExpressionRewriteContext>
 
     public static final OrToIn INSTANCE = new OrToIn();
 
-    private static final int REWRITE_OR_TO_IN_PREDICATE_THRESHOLD = 2;
+    public static final int REWRITE_OR_TO_IN_PREDICATE_THRESHOLD = 2;
 
     @Override
     public Expression rewrite(Expression expr, ExpressionRewriteContext ctx) {
@@ -69,9 +68,11 @@ public class OrToIn extends 
DefaultExpressionRewriter<ExpressionRewriteContext>
 
     @Override
     public Expression visitOr(Or or, ExpressionRewriteContext ctx) {
-        Map<NamedExpression, Set<Literal>> slotNameToLiteral = new HashMap<>();
+        // NOTICE: use linked hash map to avoid unstable order or entry.
+        //  unstable order entry lead to dead loop since return expression 
always un-equals to original one.
+        Map<NamedExpression, Set<Literal>> slotNameToLiteral = 
Maps.newLinkedHashMap();
+        Map<Expression, NamedExpression> disConjunctToSlot = 
Maps.newLinkedHashMap();
         List<Expression> expressions = ExpressionUtils.extractDisjunction(or);
-        Map<Expression, NamedExpression> disConjunctToSlot = Maps.newHashMap();
         for (Expression expression : expressions) {
             if (expression instanceof EqualTo) {
                 handleEqualTo((EqualTo) expression, slotNameToLiteral, 
disConjunctToSlot);
@@ -128,7 +129,7 @@ public class OrToIn extends 
DefaultExpressionRewriter<ExpressionRewriteContext>
 
     public void addSlotToLiteral(NamedExpression namedExpression, Literal 
literal,
             Map<NamedExpression, Set<Literal>> slotNameToLiteral) {
-        Set<Literal> literals = 
slotNameToLiteral.computeIfAbsent(namedExpression, k -> new HashSet<>());
+        Set<Literal> literals = 
slotNameToLiteral.computeIfAbsent(namedExpression, k -> new LinkedHashSet<>());
         literals.add(literal);
     }
 
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/SimplifyRange.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/SimplifyRange.java
index 13666405bb9..6c4fcc3edd1 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/SimplifyRange.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/SimplifyRange.java
@@ -417,7 +417,7 @@ public class SimplifyRange extends 
AbstractExpressionRewriteRule {
             // They are same processes, so must change synchronously.
             if (values.size() == 1) {
                 return new EqualTo(reference, values.iterator().next());
-            } else if (values.size() == 2) {
+            } else if (values.size() <= 
OrToIn.REWRITE_OR_TO_IN_PREDICATE_THRESHOLD) {
                 Iterator<Literal> iterator = values.iterator();
                 return new Or(new EqualTo(reference, iterator.next()), new 
EqualTo(reference, iterator.next()));
             } else {
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/algebra/Filter.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/algebra/Filter.java
index 626ee2d6b2e..80d614a4c11 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/algebra/Filter.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/algebra/Filter.java
@@ -20,8 +20,6 @@ package org.apache.doris.nereids.trees.plans.algebra;
 import org.apache.doris.nereids.trees.expressions.Expression;
 import org.apache.doris.nereids.util.ExpressionUtils;
 
-import com.google.common.base.Suppliers;
-
 import java.util.Set;
 
 /**
@@ -31,6 +29,6 @@ public interface Filter {
     Set<Expression> getConjuncts();
 
     default Expression getPredicate() {
-        return Suppliers.memoize(() -> 
ExpressionUtils.and(getConjuncts().toArray(new Expression[0]))).get();
+        return ExpressionUtils.and(getConjuncts());
     }
 }
diff --git 
a/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/rewrite/OrToInTest.java
 
b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/rewrite/OrToInTest.java
index 7440f51a8e0..f92e6794113 100644
--- 
a/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/rewrite/OrToInTest.java
+++ 
b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/rewrite/OrToInTest.java
@@ -133,4 +133,14 @@ class OrToInTest extends ExpressionRewriteTestHelper {
         Assertions.assertEquals("((col = 1) OR ((col = 2) AND col IN ('4', 3, 
5.0)))",
                 rewritten.toSql());
     }
+
+    @Test
+    void testEnsureOrder() {
+        // ensure not rewrite to col2 in (1, 2) or  cor 1 in (1, 2)
+        String expr = "col1 IN (1, 2) OR col2 IN (1, 2)";
+        Expression expression = PARSER.parseExpression(expr);
+        Expression rewritten = new OrToIn().rewrite(expression, new 
ExpressionRewriteContext(null));
+        Assertions.assertEquals("(col1 IN (1, 2) OR col2 IN (1, 2))",
+                rewritten.toSql());
+    }
 }


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

Reply via email to