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

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


The following commit(s) were added to refs/heads/branch-1.2-lts by this push:
     new 8bc2a5d5b4 [fix](type) Data precision is lost when converting DOUBLE 
type data to DECIMAL (#17191) (#17562) (#18952)
8bc2a5d5b4 is described below

commit 8bc2a5d5b4118a1119767cd2ee476a06f6d723b4
Author: Gabriel <[email protected]>
AuthorDate: Sun Apr 23 18:12:17 2023 +0800

    [fix](type) Data precision is lost when converting DOUBLE type data to 
DECIMAL (#17191) (#17562) (#18952)
    
    1. Fix bug when converting DOUBLE to DECIMAL;
    2. Fix bug when converting DOUBLE to DECIMALV3;
    
    Co-authored-by: herry2038 <[email protected]>
---
 be/src/runtime/decimalv2_value.cpp                 | 26 ++++++++++++--
 be/src/vec/core/types.h                            | 13 +++++--
 be/test/runtime/decimalv2_value_test.cpp           |  8 ++---
 .../test_cast_double_to_decimal.out                | 17 +++++++++
 .../test_cast_double_to_decimal.groovy             | 40 ++++++++++++++++++++++
 5 files changed, 96 insertions(+), 8 deletions(-)

diff --git a/be/src/runtime/decimalv2_value.cpp 
b/be/src/runtime/decimalv2_value.cpp
index bc3934d3b7..a21bc5a1d1 100644
--- a/be/src/runtime/decimalv2_value.cpp
+++ b/be/src/runtime/decimalv2_value.cpp
@@ -373,7 +373,18 @@ std::string DecimalV2Value::to_string(int scale) const {
             }
         }
     } else {
-        frac_val = frac_val / SCALE_TRIM_ARRAY[scale];
+        // roundup to FIX 17191
+        if (scale < SCALE) {
+            int32_t frac_val_tmp = frac_val / SCALE_TRIM_ARRAY[scale];
+            if (frac_val / SCALE_TRIM_ARRAY[scale + 1] % 10 >= 5) {
+                frac_val_tmp++;
+                if (frac_val_tmp >= SCALE_TRIM_ARRAY[9 - scale]) {
+                    frac_val_tmp = 0;
+                    _value >= 0 ? int_val++ : int_val--;
+                }
+            }
+            frac_val = frac_val_tmp;
+        }
     }
     auto f_int = fmt::format_int(int_val);
     if (scale == 0) {
@@ -414,7 +425,18 @@ int32_t DecimalV2Value::to_buffer(char* buffer, int scale) 
const {
             }
         }
     } else {
-        frac_val = frac_val / SCALE_TRIM_ARRAY[scale];
+        // roundup to FIX 17191
+        if (scale < SCALE) {
+            int32_t frac_val_tmp = frac_val / SCALE_TRIM_ARRAY[scale];
+            if (frac_val / SCALE_TRIM_ARRAY[scale + 1] % 10 >= 5) {
+                frac_val_tmp++;
+                if (frac_val_tmp >= SCALE_TRIM_ARRAY[9 - scale]) {
+                    frac_val_tmp = 0;
+                    _value >= 0 ? int_val++ : int_val--;
+                }
+            }
+            frac_val = frac_val_tmp;
+        }
     }
     int extra_sign_size = 0;
     if (_value < 0 && int_val == 0 && frac_val != 0) {
diff --git a/be/src/vec/core/types.h b/be/src/vec/core/types.h
index 332d310d57..b27292103d 100644
--- a/be/src/vec/core/types.h
+++ b/be/src/vec/core/types.h
@@ -284,9 +284,18 @@ struct Decimal {
     DECLARE_NUMERIC_CTOR(Int64)
     DECLARE_NUMERIC_CTOR(UInt32)
     DECLARE_NUMERIC_CTOR(UInt64)
-    DECLARE_NUMERIC_CTOR(Float32)
-    DECLARE_NUMERIC_CTOR(Float64)
+
 #undef DECLARE_NUMERIC_CTOR
+    Decimal(const Float32& value_) : value(value_) {
+        if constexpr (std::is_integral<T>::value) {
+            value = round(value_);
+        }
+    }
+    Decimal(const Float64& value_) : value(value_) {
+        if constexpr (std::is_integral<T>::value) {
+            value = round(value_);
+        }
+    }
 
     static Decimal double_to_decimal(double value_) {
         DecimalV2Value decimal_value;
diff --git a/be/test/runtime/decimalv2_value_test.cpp 
b/be/test/runtime/decimalv2_value_test.cpp
index 5ebf69974e..fad5cf0401 100644
--- a/be/test/runtime/decimalv2_value_test.cpp
+++ b/be/test/runtime/decimalv2_value_test.cpp
@@ -81,18 +81,18 @@ TEST_F(DecimalV2ValueTest, string_to_decimal) {
     EXPECT_EQ("0", std::string(buffer, len));
 
     DecimalV2Value value6(std::string("999999999999999999.999999999"));
-    EXPECT_EQ("999999999999999999.999", value6.to_string(3));
+    EXPECT_EQ("1000000000000000000.000", value6.to_string(3));
     EXPECT_EQ("999999999999999999.999999999", value6.to_string());
     len = value6.to_buffer(buffer, 3);
-    EXPECT_EQ("999999999999999999.999", std::string(buffer, len));
+    EXPECT_EQ("1000000000000000000.000", std::string(buffer, len));
     len = value6.to_buffer(buffer, -1);
     EXPECT_EQ("999999999999999999.999999999", std::string(buffer, len));
 
     DecimalV2Value value7(std::string("-999999999999999999.999999999"));
-    EXPECT_EQ("-999999999999999999.999", value7.to_string(3));
+    EXPECT_EQ("-1000000000000000000.000", value7.to_string(3));
     EXPECT_EQ("-999999999999999999.999999999", value7.to_string());
     len = value7.to_buffer(buffer, 3);
-    EXPECT_EQ("-999999999999999999.999", std::string(buffer, len));
+    EXPECT_EQ("-1000000000000000000.000", std::string(buffer, len));
     len = value7.to_buffer(buffer, -1);
     EXPECT_EQ("-999999999999999999.999999999", std::string(buffer, len));
 
diff --git 
a/regression-test/data/cast_double_to_decimal/test_cast_double_to_decimal.out 
b/regression-test/data/cast_double_to_decimal/test_cast_double_to_decimal.out
new file mode 100644
index 0000000000..bf7354800a
--- /dev/null
+++ 
b/regression-test/data/cast_double_to_decimal/test_cast_double_to_decimal.out
@@ -0,0 +1,17 @@
+-- This file is automatically generated. You should know what you did if you 
want to edit this
+-- !select --
+15.025 15.025  15.02500000     15.02500000
+15.025 15.025  15.02500000     15.02500000
+15.330 15.330  15.33000000     15.33000000
+16.000 16.000  16.00000000     16.00000000
+16.000 16.000  15.99990000     15.99990000
+1.000  1.000   0.99990000      0.99990000
+15.025 15.025  15.02450000     15.02450000
+-15.025        -15.025 -15.02500000    -15.02500000
+-15.025        -15.025 -15.02500000    -15.02500000
+-15.330        -15.330 -15.33000000    -15.33000000
+-16.000        -16.000 -16.00000000    -16.00000000
+-16.000        -16.000 -15.99990000    -15.99990000
+-1.000 -1.000  -0.99990000     -0.99990000
+-15.025        -15.025 -15.02450000    -15.02450000
+
diff --git 
a/regression-test/suites/cast_double_to_decimal/test_cast_double_to_decimal.groovy
 
b/regression-test/suites/cast_double_to_decimal/test_cast_double_to_decimal.groovy
new file mode 100644
index 0000000000..f81446dab6
--- /dev/null
+++ 
b/regression-test/suites/cast_double_to_decimal/test_cast_double_to_decimal.groovy
@@ -0,0 +1,40 @@
+// 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.
+
+suite("test_cast_double_to_decimal") {
+       def tableName = "tbl_test_double_to_decimal"    
+       sql "DROP TABLE IF EXISTS ${tableName}"
+       sql "CREATE  TABLE if NOT EXISTS ${tableName} (id int, d double) 
ENGINE=OLAP UNIQUE KEY(id) COMMENT 'OLAP' DISTRIBUTED BY HASH(id) BUCKETS 1 
PROPERTIES ( 'replication_allocation' = 'tag.location.default: 1' ) "
+       sql """insert into ${tableName} values  (1,15.025),
+                                                                               
        (2,15.024999999999),
+                                                                               
        (3,15.33),
+                                                                               
        (4,15.999999995),
+                                                                               
        (5,15.9999),
+                                                                               
        (6,0.9999),
+                                                                               
        (7,15.0245),
+                                                                               
        (11,-15.025),
+                                                                               
        (12,-15.024999999999),
+                                                                               
        (13,-15.33),
+                                                                               
        (14,-15.999999995),
+                                                                               
        (15,-15.9999),
+                                                                               
        (16,-0.9999),
+                                                                               
        (17,-15.0245)"""
+       
+       qt_select "select cast(d as decimal(10,3)), cast(d as decimalv3(10,3)), 
cast(d as decimal(10,8)), cast(d as decimalv3(10,8)) from ${tableName} order by 
id"
+
+       sql "DROP TABLE IF EXISTS ${tableName}"
+}


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to