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 98be2cedcf7 branch-2.1: [fix](constant fold)Make sure FE cast double 
to varchar generate identical result with BE. #50425 (#50548)
98be2cedcf7 is described below

commit 98be2cedcf7577cacef7037b1a5410e010cae6c7
Author: github-actions[bot] 
<41898282+github-actions[bot]@users.noreply.github.com>
AuthorDate: Wed Apr 30 09:17:47 2025 +0800

    branch-2.1: [fix](constant fold)Make sure FE cast double to varchar 
generate identical result with BE. #50425 (#50548)
    
    Cherry-picked from #50425
    
    Co-authored-by: James <lijib...@selectdb.com>
---
 .../expression/rules/FoldConstantRuleOnFE.java     | 23 +++++
 .../trees/expressions/literal/DoubleLiteral.java   | 30 +++++++
 .../expressions/literal/DoubleLiteralTest.java     | 49 +++++++++++
 .../fold_constant_string_arithmatic.groovy         | 98 ++++++++++++++++++++++
 4 files changed, 200 insertions(+)

diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/FoldConstantRuleOnFE.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/FoldConstantRuleOnFE.java
index 6014cbbcf35..0f1e3edb2a9 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/FoldConstantRuleOnFE.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/FoldConstantRuleOnFE.java
@@ -78,6 +78,7 @@ import 
org.apache.doris.nereids.trees.expressions.literal.DateLiteral;
 import org.apache.doris.nereids.trees.expressions.literal.DateTimeLiteral;
 import org.apache.doris.nereids.trees.expressions.literal.DateTimeV2Literal;
 import org.apache.doris.nereids.trees.expressions.literal.DateV2Literal;
+import org.apache.doris.nereids.trees.expressions.literal.DoubleLiteral;
 import org.apache.doris.nereids.trees.expressions.literal.Literal;
 import org.apache.doris.nereids.trees.expressions.literal.NullLiteral;
 import org.apache.doris.nereids.trees.expressions.literal.StringLikeLiteral;
@@ -448,6 +449,9 @@ public class FoldConstantRuleOnFE extends 
AbstractExpressionRewriteRule
         }
         Expression child = cast.child();
         DataType dataType = cast.getDataType();
+        if (!safeToCast(cast)) {
+            return cast;
+        }
         // todo: process other null case
         if (child.isNullLiteral()) {
             return new NullLiteral(dataType);
@@ -473,6 +477,25 @@ public class FoldConstantRuleOnFE extends 
AbstractExpressionRewriteRule
         }
     }
 
+    // Check if the given literal value is safe to cast to the targetType.
+    // We need to guarantee FE cast result is identical with BE cast result.
+    // Otherwise, it's not safe.
+    protected boolean safeToCast(Cast cast) {
+        if (cast == null || cast.child() == null || cast.getDataType() == 
null) {
+            return true;
+        }
+        // Check double type.
+        if (cast.child() instanceof DoubleLiteral && 
cast.getDataType().isStringLikeType()) {
+            Double value = ((DoubleLiteral) cast.child()).getValue();
+            if (value.isInfinite() || value.isNaN()) {
+                return true;
+            }
+            return -1E16 < value && value < 1E16;
+        }
+        // Check other types if needed.
+        return true;
+    }
+
     @Override
     public Expression visitBoundFunction(BoundFunction boundFunction, 
ExpressionRewriteContext context) {
         if (!boundFunction.foldable()) {
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/DoubleLiteral.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/DoubleLiteral.java
index bc7b356c376..a18f2e377bb 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/DoubleLiteral.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/DoubleLiteral.java
@@ -49,4 +49,34 @@ public class DoubleLiteral extends FractionalLiteral {
     public LiteralExpr toLegacyLiteral() {
         return new FloatLiteral(value, Type.DOUBLE);
     }
+
+    @Override
+    public String getStringValue() {
+        Double num = getValue();
+        if (Double.isNaN(num)) {
+            return "nan";
+        } else if (Double.isInfinite(num)) {
+            return num > 0 ? "inf" : "-inf";
+        }
+
+        // Use %.17g to format the result,replace 'E' with 'e'
+        String formatted = String.format("%.17g", num).replace('E', 'e');
+
+        // Remove trailing .0 in scientific notation.
+        if (formatted.contains("e")) {
+            String[] parts = formatted.split("e");
+            String mantissa = parts[0];
+            String exponent = parts.length > 1 ? "e" + parts[1] : "";
+            mantissa = mantissa.replaceAll("\\.?0+$", "");
+            if (mantissa.isEmpty()) {
+                mantissa = "0";
+            }
+            formatted = mantissa + exponent;
+        } else if (formatted.contains(".")) {
+            // remove trailing .0 in fixed-point representation
+            formatted = formatted.replaceAll("\\.?0+$", "");
+        }
+
+        return formatted;
+    }
 }
diff --git 
a/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/expressions/literal/DoubleLiteralTest.java
 
b/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/expressions/literal/DoubleLiteralTest.java
new file mode 100644
index 00000000000..409815d5829
--- /dev/null
+++ 
b/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/expressions/literal/DoubleLiteralTest.java
@@ -0,0 +1,49 @@
+// 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.literal;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+class DoubleLiteralTest {
+
+    @Test
+    public void testGetStringValue() {
+        Assertions.assertEquals("0", new DoubleLiteral(0).getStringValue());
+        Assertions.assertEquals("0", new DoubleLiteral(0.0).getStringValue());
+        Assertions.assertEquals("0", new DoubleLiteral(-0).getStringValue());
+        Assertions.assertEquals("1", new DoubleLiteral(1).getStringValue());
+        Assertions.assertEquals("1", new DoubleLiteral(1.0).getStringValue());
+        Assertions.assertEquals("-1", new DoubleLiteral(-1).getStringValue());
+        Assertions.assertEquals("1.554", new 
DoubleLiteral(1.554).getStringValue());
+        Assertions.assertEquals("0.338", new 
DoubleLiteral(0.338).getStringValue());
+        Assertions.assertEquals("-1", new 
DoubleLiteral(-1.0).getStringValue());
+        Assertions.assertEquals("1e+100", new 
DoubleLiteral(1e100).getStringValue());
+        Assertions.assertEquals("1e-100", new 
DoubleLiteral(1e-100).getStringValue());
+        Assertions.assertEquals("10000000000000000", new 
DoubleLiteral(1.0E16).getStringValue());
+        Assertions.assertEquals("-10000000000000000", new 
DoubleLiteral(-1.0E16).getStringValue());
+        Assertions.assertEquals("1e+17", new 
DoubleLiteral(1.0E17).getStringValue());
+        Assertions.assertEquals("-1e+17", new 
DoubleLiteral(-1.0E17).getStringValue());
+        Assertions.assertEquals("0.0001", new 
DoubleLiteral(0.0001).getStringValue());
+        Assertions.assertEquals("1e+308", new 
DoubleLiteral(1e308).getStringValue());
+        Assertions.assertEquals("-1e+308", new 
DoubleLiteral(-1e308).getStringValue());
+        Assertions.assertEquals("inf", new 
DoubleLiteral(Double.POSITIVE_INFINITY).getStringValue());
+        Assertions.assertEquals("-inf", new 
DoubleLiteral(Double.NEGATIVE_INFINITY).getStringValue());
+        Assertions.assertEquals("nan", new 
DoubleLiteral(Double.NaN).getStringValue());
+    }
+}
diff --git 
a/regression-test/suites/nereids_p0/expression/fold_constant/fold_constant_string_arithmatic.groovy
 
b/regression-test/suites/nereids_p0/expression/fold_constant/fold_constant_string_arithmatic.groovy
index faf6f1022f5..7a064e5f0f8 100644
--- 
a/regression-test/suites/nereids_p0/expression/fold_constant/fold_constant_string_arithmatic.groovy
+++ 
b/regression-test/suites/nereids_p0/expression/fold_constant/fold_constant_string_arithmatic.groovy
@@ -394,6 +394,8 @@ suite("fold_constant_string_arithmatic") {
     testFoldConst("select left('上海天津北京杭州', 5)")
     testFoldConst("select left('上海天津北京杭州', -5)")
     testFoldConst("select left('上海天津北京杭州', 0)")
+    testFoldConst("select left('20250409'-10000, 6)")
+
 
     // length
     testFoldConst("select length('你')")
@@ -1726,4 +1728,100 @@ suite("fold_constant_string_arithmatic") {
     testFoldConst("select split_by_string('a😁a😁a', '')")
     testFoldConst("select character_length('a😁a😁a')")
     testFoldConst("select replace_empty('a😁a😁a', '', '2')")
+
+    // cast double to string like
+    testFoldConst("select cast(cast(0 as double) as varchar(65533))")
+    testFoldConst("select cast(cast(0 as double) as string)")
+    testFoldConst("select cast(cast(0.0 as double) as varchar(65533))")
+    testFoldConst("select cast(cast(0.0 as double) as string)")
+    testFoldConst("select cast(cast(1 as double) as varchar(65533))")
+    testFoldConst("select cast(cast(1 as double) as string)")
+    testFoldConst("select cast(cast(1.0 as double) as varchar(65533))")
+    testFoldConst("select cast(cast(1.0 as double) as string)")
+    testFoldConst("select cast(cast(0.1 as double) as varchar(65533))")
+    testFoldConst("select cast(cast(0.1 as double) as string)")
+    testFoldConst("select cast(cast(1.1 as double) as varchar(65533))")
+    testFoldConst("select cast(cast(1.1 as double) as string)")
+    testFoldConst("select cast(cast(100000 as double) as string)")
+    testFoldConst("select cast(cast(1000000000000000 as double) as string)")
+    testFoldConst("select cast(cast(10000000000000000 as double) as string)")
+    testFoldConst("select cast(cast(100000000000000000 as double) as string)")
+    testFoldConst("select cast(cast(1000000000000000000 as double) as string)")
+    testFoldConst("select cast(cast(1.888 as double) as string)")
+    testFoldConst("select cast(cast(1.888777888777888 as double) as string)")
+    testFoldConst("select cast(cast(1.8887778887778887 as double) as string)")
+    testFoldConst("select cast(cast(1.888777888777888777 as double) as 
string)")
+    testFoldConst("select cast(cast(55556666.888777888777888777 as double) as 
string)")
+    testFoldConst("select cast(cast(555566667777.888777888777888777 as double) 
as string)")
+    testFoldConst("select cast(cast(5555666677778888.888777888777888777 as 
double) as string)")
+    testFoldConst("select cast(cast(55556666777788889.888777888777888777 as 
double) as string)")
+    testFoldConst("select cast(cast(55556666777788889999.888777888777888777 as 
double) as string)")
+    testFoldConst("select cast(cast(0.001 as double) as string)")
+    testFoldConst("select cast(cast(0.0001 as double) as string)")
+    testFoldConst("select cast(cast(0.00001 as double) as string)")
+    testFoldConst("select cast(cast(0.000001 as double) as string)")
+    testFoldConst("select cast(cast(0.0000001 as double) as string)")
+    testFoldConst("select cast(cast(0.00000001 as double) as string)")
+    testFoldConst("select cast(cast(0.00000001 as double) as string)")
+    testFoldConst("select cast(cast(0.000000000000001 as double) as string)")
+    testFoldConst("select cast(cast(0.0000000000000001 as double) as string)")
+    testFoldConst("select cast(cast(0.00000000000000001 as double) as string)")
+    testFoldConst("select cast(cast(0.000000000000000001 as double) as 
string)")
+    testFoldConst("select cast(cast(0.0000000000000000001 as double) as 
string)")
+    testFoldConst("select cast(cast(1e308 as double) as string)")
+    testFoldConst("select cast(cast(1e309 as double) as string)")
+    testFoldConst("select cast(cast(1e-308 as double) as string)")
+    testFoldConst("select cast(cast(1e-309 as double) as string)")
+    testFoldConst("select cast(cast(10000000000000001 as double) as string)")
+    testFoldConst("select cast(cast(10000000000000010 as double) as string)")
+    testFoldConst("select cast(cast(10000000000000100 as double) as string)")
+
+    testFoldConst("select cast(cast(-0 as double) as varchar(65533))")
+    testFoldConst("select cast(cast(-0 as double) as string)")
+    testFoldConst("select cast(cast(-0.0 as double) as varchar(65533))")
+    testFoldConst("select cast(cast(-0.0 as double) as string)")
+    testFoldConst("select cast(cast(-1 as double) as varchar(65533))")
+    testFoldConst("select cast(cast(-1 as double) as string)")
+    testFoldConst("select cast(cast(-1.0 as double) as varchar(65533))")
+    testFoldConst("select cast(cast(-1.0 as double) as string)")
+    testFoldConst("select cast(cast(-0.1 as double) as varchar(65533))")
+    testFoldConst("select cast(cast(-0.1 as double) as string)")
+    testFoldConst("select cast(cast(-1.1 as double) as varchar(65533))")
+    testFoldConst("select cast(cast(-1.1 as double) as string)")
+    testFoldConst("select cast(cast(-100000 as double) as string)")
+    testFoldConst("select cast(cast(-1000000000000000 as double) as string)")
+    testFoldConst("select cast(cast(-10000000000000000 as double) as string)")
+    testFoldConst("select cast(cast(-100000000000000000 as double) as string)")
+    testFoldConst("select cast(cast(-1000000000000000000 as double) as 
string)")
+    testFoldConst("select cast(cast(-1.888 as double) as string)")
+    testFoldConst("select cast(cast(-1.888777888777888 as double) as string)")
+    testFoldConst("select cast(cast(-1.8887778887778887 as double) as string)")
+    testFoldConst("select cast(cast(-1.888777888777888777 as double) as 
string)")
+    testFoldConst("select cast(cast(-55556666.888777888777888777 as double) as 
string)")
+    testFoldConst("select cast(cast(-555566667777.888777888777888777 as 
double) as string)")
+    testFoldConst("select cast(cast(-5555666677778888.888777888777888777 as 
double) as string)")
+    testFoldConst("select cast(cast(-55556666777788889.888777888777888777 as 
double) as string)")
+    testFoldConst("select cast(cast(-55556666777788889999.888777888777888777 
as double) as string)")
+    testFoldConst("select cast(cast(-0.001 as double) as string)")
+    testFoldConst("select cast(cast(-0.0001 as double) as string)")
+    testFoldConst("select cast(cast(-0.00001 as double) as string)")
+    testFoldConst("select cast(cast(-0.000001 as double) as string)")
+    testFoldConst("select cast(cast(-0.0000001 as double) as string)")
+    testFoldConst("select cast(cast(-0.00000001 as double) as string)")
+    testFoldConst("select cast(cast(-0.00000001 as double) as string)")
+    testFoldConst("select cast(cast(-0.000000000000001 as double) as string)")
+    testFoldConst("select cast(cast(-0.0000000000000001 as double) as string)")
+    testFoldConst("select cast(cast(-0.00000000000000001 as double) as 
string)")
+    testFoldConst("select cast(cast(-0.000000000000000001 as double) as 
string)")
+    testFoldConst("select cast(cast(-0.0000000000000000001 as double) as 
string)")
+    testFoldConst("select cast(cast(-1e308 as double) as string)")
+    testFoldConst("select cast(cast(-1e309 as double) as string)")
+    testFoldConst("select cast(cast(-1e-308 as double) as string)")
+    testFoldConst("select cast(cast(-1e-309 as double) as string)")
+    testFoldConst("select cast(cast(-10000000000000001 as double) as string)")
+    testFoldConst("select cast(cast(-10000000000000010 as double) as string)")
+    testFoldConst("select cast(cast(-10000000000000100 as double) as string)")
+    testFoldConst("select cast(cast('nan' as double) as string)")
+    testFoldConst("select cast(cast('inf' as double) as string)")
+    testFoldConst("select cast(cast('-inf' as double) as string)")
 }


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

Reply via email to