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]