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

morrysnow pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/doris.git


The following commit(s) were added to refs/heads/master by this push:
     new 3fffc6178f2 [Fix](Nereids) fix floor/round/ceil/truncate functions 
type compute precision problem (#43422)
3fffc6178f2 is described below

commit 3fffc6178f266b612b15687a361b22d101b63ed6
Author: LiBinfeng <libinf...@selectdb.com>
AuthorDate: Tue Nov 12 20:18:51 2024 +0800

    [Fix](Nereids) fix floor/round/ceil/truncate functions type compute 
precision problem (#43422)
    
    - Problem
    function like ```select floor(300.343, 2)``` precision should be 5 and
    scale should be 2, but now is (6, 2) after compute precision, but after
    folding const on fe, it changed to (5, 2) but upper level of plan still
    expect the output of child to be (6, 2). So it would rise an exception
    when executing.
    
    - How it was fixed
    fix folding constant precision of floor/round/ceil/truncate functions
    from (5, 2) to (6, 2) in upper case
    
    - Notion
    when second value is negative and it absolute value >= precision -
    value, it can not be expressed in fe which result is zero with decimal
    type (3, 0). like 000. So just let it go back and no using folding
    constant by fe.
    
    - Related PR: #40744
    
    - Release note
        Fix floor/round/ceil functions precision problem in folding constant
---
 .../functions/executable/NumericArithmetic.java    | 34 +++++++++-------------
 .../fold_constant_numeric_arithmatic.groovy        | 25 ++++++++++++++++
 2 files changed, 39 insertions(+), 20 deletions(-)

diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/executable/NumericArithmetic.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/executable/NumericArithmetic.java
index 325e676fc04..a9acfeb2d60 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/executable/NumericArithmetic.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/executable/NumericArithmetic.java
@@ -694,12 +694,17 @@ public class NumericArithmetic {
         return input;
     }
 
+    private static Expression castDecimalV3Literal(DecimalV3Literal literal, 
int precision) {
+        return new 
DecimalV3Literal(DecimalV3Type.createDecimalV3Type(precision, 
literal.getValue().scale()),
+                literal.getValue());
+    }
+
     /**
      * round
      */
     @ExecFunction(name = "round")
     public static Expression round(DecimalV3Literal first) {
-        return first.round(0);
+        return castDecimalV3Literal(first.round(0), 
first.getValue().precision());
     }
 
     /**
@@ -707,7 +712,7 @@ public class NumericArithmetic {
      */
     @ExecFunction(name = "round")
     public static Expression round(DecimalV3Literal first, IntegerLiteral 
second) {
-        return first.round(second.getValue());
+        return castDecimalV3Literal(first.round(second.getValue()), 
first.getValue().precision());
     }
 
     /**
@@ -733,7 +738,7 @@ public class NumericArithmetic {
      */
     @ExecFunction(name = "ceil")
     public static Expression ceil(DecimalV3Literal first) {
-        return first.roundCeiling(0);
+        return castDecimalV3Literal(first.roundCeiling(0), 
first.getValue().precision());
     }
 
     /**
@@ -741,7 +746,7 @@ public class NumericArithmetic {
      */
     @ExecFunction(name = "ceil")
     public static Expression ceil(DecimalV3Literal first, IntegerLiteral 
second) {
-        return first.roundCeiling(second.getValue());
+        return castDecimalV3Literal(first.roundCeiling(second.getValue()), 
first.getValue().precision());
     }
 
     /**
@@ -767,7 +772,7 @@ public class NumericArithmetic {
      */
     @ExecFunction(name = "floor")
     public static Expression floor(DecimalV3Literal first) {
-        return first.roundFloor(0);
+        return castDecimalV3Literal(first.roundFloor(0), 
first.getValue().precision());
     }
 
     /**
@@ -775,7 +780,7 @@ public class NumericArithmetic {
      */
     @ExecFunction(name = "floor")
     public static Expression floor(DecimalV3Literal first, IntegerLiteral 
second) {
-        return first.roundFloor(second.getValue());
+        return castDecimalV3Literal(first.roundFloor(second.getValue()), 
first.getValue().precision());
     }
 
     /**
@@ -1136,21 +1141,10 @@ public class NumericArithmetic {
     public static Expression truncate(DecimalV3Literal first, IntegerLiteral 
second) {
         if (first.getValue().compareTo(BigDecimal.ZERO) == 0) {
             return first;
+        } else if (first.getValue().compareTo(BigDecimal.ZERO) < 0) {
+            return castDecimalV3Literal(first.roundCeiling(second.getValue()), 
first.getValue().precision());
         } else {
-            if (first.getValue().scale() < second.getValue()) {
-                return first;
-            }
-            if (second.getValue() < 0) {
-                double factor = Math.pow(10, Math.abs(second.getValue()));
-                return new DecimalV3Literal(
-                    
DecimalV3Type.createDecimalV3Type(first.getValue().precision(), 0),
-                    BigDecimal.valueOf(Math.floor(first.getDouble() / factor) 
* factor));
-            }
-            if (first.getValue().compareTo(BigDecimal.ZERO) == -1) {
-                return first.roundCeiling(second.getValue());
-            } else {
-                return first.roundFloor(second.getValue());
-            }
+            return castDecimalV3Literal(first.roundFloor(second.getValue()), 
first.getValue().precision());
         }
     }
 
diff --git 
a/regression-test/suites/nereids_p0/expression/fold_constant/fold_constant_numeric_arithmatic.groovy
 
b/regression-test/suites/nereids_p0/expression/fold_constant/fold_constant_numeric_arithmatic.groovy
index 5f728651267..dbfd3fad7bf 100644
--- 
a/regression-test/suites/nereids_p0/expression/fold_constant/fold_constant_numeric_arithmatic.groovy
+++ 
b/regression-test/suites/nereids_p0/expression/fold_constant/fold_constant_numeric_arithmatic.groovy
@@ -409,4 +409,29 @@ test {
 
 //Additional cases for Xor, Conv, and other mathematical functions
     testFoldConst("SELECT CONV(-10, 10, 2) AS conv_invalid_base") //Conv with 
negative input (may be undefined)
+
+    // fix floor/ceil/round function return type with DecimalV3 input
+    testFoldConst("with cte as (select floor(300.343) order by 1 limit 1) 
select * from cte")
+    testFoldConst("with cte as (select round(300.343) order by 1 limit 1) 
select * from cte")
+    testFoldConst("with cte as (select ceil(300.343) order by 1 limit 1) 
select * from cte")
+
+    testFoldConst("with cte as (select floor(300.343, 2) order by 1 limit 1) 
select * from cte")
+    testFoldConst("with cte as (select round(300.343, 2) order by 1 limit 1) 
select * from cte")
+    testFoldConst("with cte as (select ceil(300.343, 2) order by 1 limit 1) 
select * from cte")
+    testFoldConst("with cte as (select truncate(300.343, 2) order by 1 limit 
1) select * from cte")
+
+    testFoldConst("with cte as (select floor(300.343, 0) order by 1 limit 1) 
select * from cte")
+    testFoldConst("with cte as (select round(300.343, 0) order by 1 limit 1) 
select * from cte")
+    testFoldConst("with cte as (select ceil(300.343, 0) order by 1 limit 1) 
select * from cte")
+    testFoldConst("with cte as (select truncate(300.343, 0) order by 1 limit 
1) select * from cte")
+
+    testFoldConst("with cte as (select floor(300.343, -1) order by 1 limit 1) 
select * from cte")
+    testFoldConst("with cte as (select round(300.343, -1) order by 1 limit 1) 
select * from cte")
+    testFoldConst("with cte as (select ceil(300.343, -1) order by 1 limit 1) 
select * from cte")
+    testFoldConst("with cte as (select truncate(300.343, -1) order by 1 limit 
1) select * from cte")
+
+    testFoldConst("with cte as (select floor(300.343, -4) order by 1 limit 1) 
select * from cte")
+    testFoldConst("with cte as (select round(300.343, -4) order by 1 limit 1) 
select * from cte")
+    testFoldConst("with cte as (select ceil(300.343, -4) order by 1 limit 1) 
select * from cte")
+    testFoldConst("with cte as (select truncate(300.343, -4) order by 1 limit 
1) select * from cte")
 }


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

Reply via email to