This is an automated email from the ASF dual-hosted git repository.
kxiao pushed a commit to branch branch-2.0
in repository https://gitbox.apache.org/repos/asf/doris.git
The following commit(s) were added to refs/heads/branch-2.0 by this push:
new 474f516991b [FIX](decimalv3)Fix decimalv3 with dot string #26072
(#26371)
474f516991b is described below
commit 474f516991b242f7c7175966c456f0af4b2d34e1
Author: amory <[email protected]>
AuthorDate: Fri Nov 3 16:25:45 2023 +0800
[FIX](decimalv3)Fix decimalv3 with dot string #26072 (#26371)
---
be/src/util/string_parser.hpp | 43 +++++++++++++++-------
regression-test/data/query_p0/cast/test_cast.out | 15 ++++++++
.../suites/query_p0/cast/test_cast.groovy | 16 ++++++++
3 files changed, 60 insertions(+), 14 deletions(-)
diff --git a/be/src/util/string_parser.hpp b/be/src/util/string_parser.hpp
index f85faf2377e..d1726202e46 100644
--- a/be/src/util/string_parser.hpp
+++ b/be/src/util/string_parser.hpp
@@ -599,11 +599,9 @@ T StringParser::string_to_decimal(const char* s, int len,
int type_precision, in
}
// Ignore leading zeros.
- bool leading_zero = false;
bool found_value = false;
while (len > 0 && UNLIKELY(*s == '0')) {
found_value = true;
- leading_zero = true;
++s;
--len;
}
@@ -627,6 +625,7 @@ T StringParser::string_to_decimal(const char* s, int len,
int type_precision, in
int precision = 0;
int max_digit = type_precision - type_scale;
+ int cur_digit = 0;
bool found_exponent = false;
int8_t exponent = 0;
T value = 0;
@@ -682,31 +681,37 @@ T StringParser::string_to_decimal(const char* s, int len,
int type_precision, in
}
} else {
// decimalv3
+ bool has_round = false;
for (int i = 0; i < len; ++i) {
const char& c = s[i];
- // keep a rounding precision to round the decimal value
- if (LIKELY('0' <= c && c <= '9') &&
- ((!leading_zero && LIKELY(type_precision >= precision)) ||
- (leading_zero && type_precision > precision))) {
+ if (LIKELY('0' <= c && c <= '9')) {
found_value = true;
// Ignore digits once the type's precision limit is reached.
This avoids
// overflowing the underlying storage while handling a string
like
// 10000000000e-10 into a DECIMAL(1, 0). Adjustments for
ignored digits and
// an exponent will be made later.
- ++precision;
- scale += found_dot;
- // decimalv3 should make sure the type_scale and type_precision
- if (!found_dot && max_digit < (precision - scale)) {
- // parse_overflow should only happen when the digit part
reached the max
+ if (LIKELY(type_precision > precision) && !has_round) {
+ value = (value * 10) + (c - '0'); // Benchmarks are faster
with parenthesis...
+ ++precision;
+ scale += found_dot;
+ cur_digit = precision - scale;
+ } else if (!found_dot && max_digit < (precision - scale)) {
*result = StringParser::PARSE_OVERFLOW;
value = is_negative ?
vectorized::min_decimal_value<vectorized::Decimal<T>>(
type_precision)
:
vectorized::max_decimal_value<vectorized::Decimal<T>>(
type_precision);
return value;
+ } else if (found_dot && scale >= type_scale && !has_round) {
+ // make rounding cases
+ if (c > '4') {
+ value += 1;
+ }
+ has_round = true;
+ continue;
+ } else if (!found_dot) {
+ ++cur_digit;
}
- // keep a rounding precision to round the decimal value
- value = (value * 10) + (c - '0'); // Benchmarks are faster
with parenthesis...
DCHECK(value >= 0); // For some reason //DCHECK_GE doesn't
work with __int128.
} else if (c == '.' && LIKELY(!found_dot)) {
found_dot = 1;
@@ -721,7 +726,6 @@ T StringParser::string_to_decimal(const char* s, int len,
int type_precision, in
}
break;
} else {
- // jump to here: should handle the wrong character of decimal
if (value == 0) {
*result = StringParser::PARSE_FAILURE;
return 0;
@@ -734,9 +738,20 @@ T StringParser::string_to_decimal(const char* s, int len,
int type_precision, in
// the E/e character because we make right user-given
type_precision
// not max number type_precision
if (!is_numeric_ascii(c)) {
+ if (cur_digit > type_precision) {
+ *result = StringParser::PARSE_OVERFLOW;
+ value = is_negative
+ ?
vectorized::min_decimal_value<vectorized::Decimal<T>>(
+ type_precision)
+ :
vectorized::max_decimal_value<vectorized::Decimal<T>>(
+ type_precision);
+ return value;
+ }
return is_negative ? T(-value) : T(value);
}
}
+
+ return is_negative ? T(-value) : T(value);
}
}
}
diff --git a/regression-test/data/query_p0/cast/test_cast.out
b/regression-test/data/query_p0/cast/test_cast.out
index 89b29cc663d..b5d75ca4ee0 100644
--- a/regression-test/data/query_p0/cast/test_cast.out
+++ b/regression-test/data/query_p0/cast/test_cast.out
@@ -1,4 +1,19 @@
-- This file is automatically generated. You should know what you did if you
want to edit this
+-- !sql_1 --
+123456789
+
+-- !sql_2 --
+999999999
+
+-- !sql_3 --
+123456790
+
+-- !sql_4 --
+926895541712428044
+
+-- !sql_5 --
+99999999999999999.9
+
-- !sql_decimalv3 --
0
diff --git a/regression-test/suites/query_p0/cast/test_cast.groovy
b/regression-test/suites/query_p0/cast/test_cast.groovy
index c39f89b645e..a7ce1c41fa2 100644
--- a/regression-test/suites/query_p0/cast/test_cast.groovy
+++ b/regression-test/suites/query_p0/cast/test_cast.groovy
@@ -47,6 +47,22 @@ suite('test_cast') {
result([[-9.9]])
}
+ // round
+ //result([[123456789]])
+ qt_sql_1 " select cast('123456789.0' as DECIMALV3(9, 0)) "
+
+ // result([[999999999]])
+ qt_sql_2 " select cast('999999999.0' as DECIMALV3(9, 0)) "
+
+ // result([[123456790]])
+ qt_sql_3 " select cast('123456789.9' as DECIMALV3(9, 0)) "
+
+ // result([[926895541712428044]])
+ qt_sql_4 " select cast('926895541712428044.1' as DECIMALV3(18,0)); "
+
+ // result([[99999999999999999.9]])
+ qt_sql_5 " select cast('926895541712428044.1' as DECIMAL(18,1)); "
+
// leading-zeros
qt_sql_decimalv3 """select CAST('0.29401599228723063' AS DECIMALV3)"""
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]