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


The following commit(s) were added to refs/heads/branch-2.1 by this push:
     new 4979d706127 branch-2.1: [fix](nereids) Add unique id to non foldable 
expression #48103 (#48456)
4979d706127 is described below

commit 4979d706127044598b1af853d1c2d69ab3f2cebb
Author: yujun <yu...@selectdb.com>
AuthorDate: Sat Mar 1 08:51:29 2025 +0800

    branch-2.1: [fix](nereids) Add unique id to non foldable expression #48103 
(#48456)
    
    cherry pick from #48103
---
 .../trees/expressions/functions/scalar/Random.java |  61 ++++++++++++++++++---
 .../expressions/functions/scalar/RandomBytes.java  |  39 ++++++++++++-
 .../trees/expressions/functions/scalar/Uuid.java   |  36 ++++++++++++
 .../expressions/functions/scalar/UuidNumeric.java  |  36 ++++++++++++
 .../rules/expression/ExpressionRewriteTest.java    |  11 ++++
 .../rules/expression/SimplifyRangeTest.java        |  14 ++++-
 .../functions/NonfoldableFunctionTest.java         |  58 ++++++++++++++++++++
 .../data/nereids_rules_p0/test_nonfoldable.out     | Bin 2819 -> 2891 bytes
 8 files changed, 243 insertions(+), 12 deletions(-)

diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/Random.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/Random.java
index 82cd56118f8..6101c7f510a 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/Random.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/Random.java
@@ -19,9 +19,12 @@ package 
org.apache.doris.nereids.trees.expressions.functions.scalar;
 
 import org.apache.doris.catalog.FunctionSignature;
 import org.apache.doris.nereids.exceptions.AnalysisException;
+import org.apache.doris.nereids.trees.expressions.ExprId;
 import org.apache.doris.nereids.trees.expressions.Expression;
+import org.apache.doris.nereids.trees.expressions.StatementScopeIdGenerator;
 import 
org.apache.doris.nereids.trees.expressions.functions.ExplicitlyCastableSignature;
 import org.apache.doris.nereids.trees.expressions.literal.Literal;
+import org.apache.doris.nereids.trees.expressions.literal.NumericLiteral;
 import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor;
 import org.apache.doris.nereids.types.BigIntType;
 import org.apache.doris.nereids.types.DoubleType;
@@ -43,27 +46,44 @@ public class Random extends ScalarFunction
             
FunctionSignature.ret(BigIntType.INSTANCE).args(BigIntType.INSTANCE, 
BigIntType.INSTANCE)
     );
 
+    private final ExprId exprId;
+
     /**
      * constructor with 0 argument.
      */
     public Random() {
-        super("random");
+        this(StatementScopeIdGenerator.newExprId());
     }
 
     /**
      * constructor with 1 argument.
      */
     public Random(Expression arg) {
-        super("random", arg);
-        // align with original planner behavior, refer to: 
org/apache/doris/analysis/Expr.getBuiltinFunction()
-        Preconditions.checkState(arg instanceof Literal, "The param of rand 
function must be literal");
+        this(StatementScopeIdGenerator.newExprId(), arg);
     }
 
     /**
      * constructor with 2 argument.
      */
     public Random(Expression lchild, Expression rchild) {
+        this(StatementScopeIdGenerator.newExprId(), lchild, rchild);
+    }
+
+    public Random(ExprId exprId) {
+        super("random");
+        this.exprId = exprId;
+    }
+
+    public Random(ExprId exprId, Expression arg) {
+        super("random", arg);
+        this.exprId = exprId;
+        // align with original planner behavior, refer to: 
org/apache/doris/analysis/Expr.getBuiltinFunction()
+        Preconditions.checkState(arg instanceof Literal, "The param of rand 
function must be literal");
+    }
+
+    public Random(ExprId exprId, Expression lchild, Expression rchild) {
         super("random", lchild, rchild);
+        this.exprId = exprId;
     }
 
     @Override
@@ -94,12 +114,20 @@ public class Random extends ScalarFunction
      */
     @Override
     public Random withChildren(List<Expression> children) {
+        ExprId newExprId = exprId;
+        List<Expression> myChildren = this.children();
+        if (myChildren.stream().allMatch(arg -> arg instanceof NumericLiteral)
+                && children.stream().allMatch(arg -> arg instanceof 
NumericLiteral)
+                && !children.equals(myChildren)) {
+            newExprId = StatementScopeIdGenerator.newExprId();
+        }
+
         if (children.isEmpty()) {
-            return new Random();
+            return new Random(newExprId);
         } else if (children.size() == 1) {
-            return new Random(children.get(0));
+            return new Random(newExprId, children.get(0));
         } else if (children.size() == 2) {
-            return new Random(children.get(0), children.get(1));
+            return new Random(newExprId, children.get(0), children.get(1));
         }
         throw new AnalysisException("random function only accept 0-2 
arguments");
     }
@@ -123,4 +151,23 @@ public class Random extends ScalarFunction
     public boolean foldable() {
         return false;
     }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (o == null || getClass() != o.getClass()) {
+            return false;
+        }
+        Random other = (Random) o;
+        return exprId.equals(other.exprId);
+    }
+
+    // The contains method needs to use hashCode, so similar to equals, it 
only compares exprId
+    @Override
+    public int computeHashCode() {
+        // direct return exprId to speed up
+        return exprId.asInt();
+    }
 }
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/RandomBytes.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/RandomBytes.java
index 000b83bbc34..156e0024e64 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/RandomBytes.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/RandomBytes.java
@@ -18,9 +18,12 @@
 package org.apache.doris.nereids.trees.expressions.functions.scalar;
 
 import org.apache.doris.catalog.FunctionSignature;
+import org.apache.doris.nereids.trees.expressions.ExprId;
 import org.apache.doris.nereids.trees.expressions.Expression;
+import org.apache.doris.nereids.trees.expressions.StatementScopeIdGenerator;
 import 
org.apache.doris.nereids.trees.expressions.functions.ExplicitlyCastableSignature;
 import org.apache.doris.nereids.trees.expressions.functions.PropagateNullable;
+import org.apache.doris.nereids.trees.expressions.literal.NumericLiteral;
 import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor;
 import org.apache.doris.nereids.types.IntegerType;
 import org.apache.doris.nereids.types.StringType;
@@ -42,13 +45,19 @@ public class RandomBytes extends ScalarFunction
             
FunctionSignature.ret(VarcharType.SYSTEM_DEFAULT).args(IntegerType.INSTANCE)
     );
 
+    private final ExprId exprId;
+
     /**
      * constructor with 1 argument.
      */
     public RandomBytes(Expression arg0) {
-        super("random_bytes", arg0);
+        this(StatementScopeIdGenerator.newExprId(), arg0);
     }
 
+    public RandomBytes(ExprId exprId, Expression arg0) {
+        super("random_bytes", arg0);
+        this.exprId = exprId;
+    }
 
     /**
      * withChildren.
@@ -56,7 +65,14 @@ public class RandomBytes extends ScalarFunction
     @Override
     public RandomBytes withChildren(List<Expression> children) {
         Preconditions.checkArgument(children.size() == 1);
-        return new RandomBytes(children.get(0));
+        ExprId newExprId = exprId;
+        List<Expression> myChildren = this.children();
+        if (children.stream().allMatch(arg -> arg instanceof NumericLiteral)
+                && myChildren.stream().allMatch(arg -> arg instanceof 
NumericLiteral)
+                && !children.equals(myChildren)) {
+            newExprId = StatementScopeIdGenerator.newExprId();
+        }
+        return new RandomBytes(newExprId, children.get(0));
     }
 
     @Override
@@ -78,4 +94,23 @@ public class RandomBytes extends ScalarFunction
     public <R, C> R accept(ExpressionVisitor<R, C> visitor, C context) {
         return visitor.visitRandomBytes(this, context);
     }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (o == null || getClass() != o.getClass()) {
+            return false;
+        }
+        RandomBytes other = (RandomBytes) o;
+        return exprId.equals(other.exprId);
+    }
+
+    // The contains method needs to use hashCode, so similar to equals, it 
only compares exprId
+    @Override
+    public int computeHashCode() {
+        // direct return exprId to speed up
+        return exprId.asInt();
+    }
 }
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/Uuid.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/Uuid.java
index 1df31219697..fd715875346 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/Uuid.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/Uuid.java
@@ -18,12 +18,16 @@
 package org.apache.doris.nereids.trees.expressions.functions.scalar;
 
 import org.apache.doris.catalog.FunctionSignature;
+import org.apache.doris.nereids.trees.expressions.ExprId;
+import org.apache.doris.nereids.trees.expressions.Expression;
+import org.apache.doris.nereids.trees.expressions.StatementScopeIdGenerator;
 import org.apache.doris.nereids.trees.expressions.functions.AlwaysNotNullable;
 import 
org.apache.doris.nereids.trees.expressions.functions.ExplicitlyCastableSignature;
 import org.apache.doris.nereids.trees.expressions.shape.LeafExpression;
 import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor;
 import org.apache.doris.nereids.types.VarcharType;
 
+import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableList;
 
 import java.util.List;
@@ -38,11 +42,24 @@ public class Uuid extends ScalarFunction
             FunctionSignature.ret(VarcharType.SYSTEM_DEFAULT).args()
     );
 
+    private final ExprId exprId;
+
     /**
      * constructor with 0 argument.
      */
     public Uuid() {
+        this(StatementScopeIdGenerator.newExprId());
+    }
+
+    public Uuid(ExprId exprId) {
         super("uuid");
+        this.exprId = exprId;
+    }
+
+    @Override
+    public Uuid withChildren(List<Expression> children) {
+        Preconditions.checkArgument(children.isEmpty());
+        return new Uuid(exprId);
     }
 
     @Override
@@ -64,4 +81,23 @@ public class Uuid extends ScalarFunction
     public boolean isDeterministic() {
         return false;
     }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (o == null || getClass() != o.getClass()) {
+            return false;
+        }
+        Uuid other = (Uuid) o;
+        return exprId.equals(other.exprId);
+    }
+
+    // The contains method needs to use hashCode, so similar to equals, it 
only compares exprId
+    @Override
+    public int computeHashCode() {
+        // direct return exprId to speed up
+        return exprId.asInt();
+    }
 }
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/UuidNumeric.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/UuidNumeric.java
index 141d64bb418..37bf709a622 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/UuidNumeric.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/UuidNumeric.java
@@ -18,12 +18,16 @@
 package org.apache.doris.nereids.trees.expressions.functions.scalar;
 
 import org.apache.doris.catalog.FunctionSignature;
+import org.apache.doris.nereids.trees.expressions.ExprId;
+import org.apache.doris.nereids.trees.expressions.Expression;
+import org.apache.doris.nereids.trees.expressions.StatementScopeIdGenerator;
 import org.apache.doris.nereids.trees.expressions.functions.AlwaysNotNullable;
 import 
org.apache.doris.nereids.trees.expressions.functions.ExplicitlyCastableSignature;
 import org.apache.doris.nereids.trees.expressions.shape.LeafExpression;
 import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor;
 import org.apache.doris.nereids.types.LargeIntType;
 
+import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableList;
 
 import java.util.List;
@@ -38,11 +42,24 @@ public class UuidNumeric extends ScalarFunction
             FunctionSignature.ret(LargeIntType.INSTANCE).args()
     );
 
+    private final ExprId exprId;
+
     /**
      * constructor with 0 argument.
      */
     public UuidNumeric() {
+        this(StatementScopeIdGenerator.newExprId());
+    }
+
+    public UuidNumeric(ExprId exprId) {
         super("uuid_numeric");
+        this.exprId = exprId;
+    }
+
+    @Override
+    public UuidNumeric withChildren(List<Expression> children) {
+        Preconditions.checkArgument(children.isEmpty());
+        return new UuidNumeric(exprId);
     }
 
     @Override
@@ -64,4 +81,23 @@ public class UuidNumeric extends ScalarFunction
     public boolean isDeterministic() {
         return false;
     }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (o == null || getClass() != o.getClass()) {
+            return false;
+        }
+        UuidNumeric other = (UuidNumeric) o;
+        return exprId.equals(other.exprId);
+    }
+
+    // The contains method needs to use hashCode, so similar to equals, it 
only compares exprId
+    @Override
+    public int computeHashCode() {
+        // direct return exprId to speed up
+        return exprId.asInt();
+    }
 }
diff --git 
a/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/expression/ExpressionRewriteTest.java
 
b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/expression/ExpressionRewriteTest.java
index c5f69b1edbb..0f270978225 100644
--- 
a/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/expression/ExpressionRewriteTest.java
+++ 
b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/expression/ExpressionRewriteTest.java
@@ -81,6 +81,17 @@ class ExpressionRewriteTest extends 
ExpressionRewriteTestHelper {
 
     }
 
+    @Test
+    void testSimplifyRange() {
+        executor = new ExpressionRuleExecutor(ImmutableList.of(
+                ExpressionRewrite.bottomUp(SimplifyRange.INSTANCE)
+        ));
+
+        // random is non-foldable expression, the two RANDOM are not equals
+        assertRewriteAfterTypeCoercion("a + random(1, 10) > 20 and a + 
random(1, 10) < 10",
+                "a + random(1, 10) > 20 and a + random(1, 10) < 10");
+    }
+
     @Test
     void testNormalizeExpressionRewrite() {
         executor = new ExpressionRuleExecutor(ImmutableList.of(
diff --git 
a/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/expression/SimplifyRangeTest.java
 
b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/expression/SimplifyRangeTest.java
index 79906880f53..3ce4bb9bff4 100644
--- 
a/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/expression/SimplifyRangeTest.java
+++ 
b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/expression/SimplifyRangeTest.java
@@ -197,6 +197,9 @@ public class SimplifyRangeTest extends ExpressionRewrite {
 
         assertRewrite("(TA + TC > 3 OR TA < 1) AND TB = 2) AND IA =1", "(TA + 
TC > 3 OR TA < 1) AND TB = 2) AND IA =1");
 
+        // random is non-foldable, so the two random(1, 10) are distinct, 
cann't merge range for them.
+        Expression expr = rewrite("TA + random(1, 10) > 10 AND  TA + random(1, 
10) < 1", Maps.newHashMap());
+        Assertions.assertEquals("(((TA + random(1, 10)) > 10) AND ((TA + 
random(1, 10)) < 1))", expr.toSql());
     }
 
     @Test
@@ -366,14 +369,19 @@ public class SimplifyRangeTest extends ExpressionRewrite {
 
     private void assertRewrite(String expression, String expected) {
         Map<String, Slot> mem = Maps.newHashMap();
-        Expression needRewriteExpression = 
replaceUnboundSlot(PARSER.parseExpression(expression), mem);
-        needRewriteExpression = typeCoercion(needRewriteExpression);
+        Expression rewrittenExpression = rewrite(expression, mem);
         Expression expectedExpression = 
replaceUnboundSlot(PARSER.parseExpression(expected), mem);
         expectedExpression = typeCoercion(expectedExpression);
-        Expression rewrittenExpression = 
sortChildren(executor.rewrite(needRewriteExpression, context));
         Assertions.assertEquals(expectedExpression, rewrittenExpression);
     }
 
+    private Expression rewrite(String expression, Map<String, Slot> mem) {
+        Expression rewriteExpression = 
replaceUnboundSlot(PARSER.parseExpression(expression), mem);
+        rewriteExpression = typeCoercion(rewriteExpression);
+        rewriteExpression = executor.rewrite(rewriteExpression, context);
+        return sortChildren(rewriteExpression);
+    }
+
     private void assertRewriteNotNull(String expression, String expected) {
         Map<String, Slot> mem = Maps.newHashMap();
         Expression needRewriteExpression = 
replaceNotNullUnboundSlot(PARSER.parseExpression(expression), mem);
diff --git 
a/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/expressions/functions/NonfoldableFunctionTest.java
 
b/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/expressions/functions/NonfoldableFunctionTest.java
new file mode 100644
index 00000000000..debd613226a
--- /dev/null
+++ 
b/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/expressions/functions/NonfoldableFunctionTest.java
@@ -0,0 +1,58 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package org.apache.doris.nereids.trees.expressions.functions;
+
+import org.apache.doris.nereids.trees.expressions.functions.scalar.Random;
+import org.apache.doris.nereids.trees.expressions.functions.scalar.RandomBytes;
+import org.apache.doris.nereids.trees.expressions.functions.scalar.Uuid;
+import org.apache.doris.nereids.trees.expressions.functions.scalar.UuidNumeric;
+import org.apache.doris.nereids.trees.expressions.literal.BigIntLiteral;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+class NonfoldableFunctionTest {
+
+    @Test
+    void testEquals() {
+        Random rand0 = new Random();
+        Random rand1 = new Random(new BigIntLiteral(10L));
+        Random rand2 = new Random(new BigIntLiteral(1L), new 
BigIntLiteral(10L));
+        Assertions.assertNotEquals(rand0, new Random());
+        Assertions.assertEquals(rand0, rand0.withChildren());
+        Assertions.assertNotEquals(rand0, rand0.withChildren(new 
BigIntLiteral(10L)));
+        Assertions.assertNotEquals(rand1, new Random(new BigIntLiteral(10L)));
+        Assertions.assertEquals(rand1, rand1.withChildren(new 
BigIntLiteral(10L)));
+        Assertions.assertNotEquals(rand1, rand1.withChildren(new 
BigIntLiteral(1L), new BigIntLiteral(10L)));
+        Assertions.assertNotEquals(rand2, new Random(new BigIntLiteral(1L), 
new BigIntLiteral(10L)));
+        Assertions.assertEquals(rand2, rand2.withChildren(new 
BigIntLiteral(1L), new BigIntLiteral(10L)));
+
+        RandomBytes randb = new RandomBytes(new BigIntLiteral(10L));
+        Assertions.assertNotEquals(randb, new RandomBytes(new 
BigIntLiteral(10L)));
+        Assertions.assertEquals(randb, randb.withChildren(new 
BigIntLiteral(10L)));
+        Assertions.assertNotEquals(randb, randb.withChildren(new 
BigIntLiteral(1L)));
+
+        Uuid uuid = new Uuid();
+        Assertions.assertNotEquals(uuid, new Uuid());
+        Assertions.assertEquals(uuid, uuid.withChildren());
+
+        UuidNumeric uuidNum = new UuidNumeric();
+        Assertions.assertNotEquals(uuidNum, new UuidNumeric());
+        Assertions.assertEquals(uuidNum, uuidNum.withChildren());
+    }
+}
diff --git a/regression-test/data/nereids_rules_p0/test_nonfoldable.out 
b/regression-test/data/nereids_rules_p0/test_nonfoldable.out
index 3c96406efb6..656331679d6 100644
Binary files a/regression-test/data/nereids_rules_p0/test_nonfoldable.out and 
b/regression-test/data/nereids_rules_p0/test_nonfoldable.out differ


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

Reply via email to