This is an automated email from the ASF dual-hosted git repository.
morrysnow pushed a commit to branch branch-3.1
in repository https://gitbox.apache.org/repos/asf/doris.git
The following commit(s) were added to refs/heads/branch-3.1 by this push:
new 092dab7a5ac branch-3.1: [fix](core) Fix format round would core under
boundary conditions. #53660 (#53857)
092dab7a5ac is described below
commit 092dab7a5acb1c8ea7dac1b95a019c4eca9c9511
Author: Mryange <[email protected]>
AuthorDate: Fri Jul 25 15:54:37 2025 +0800
branch-3.1: [fix](core) Fix format round would core under boundary
conditions. #53660 (#53857)
picked from #53660
---
be/src/exprs/math_functions.cpp | 2 +-
be/src/vec/functions/function_string.h | 50 +++++++++++-
be/test/exprs/math_functions_test.cpp | 87 +++++++++++++++++++++
.../math_functions/test_format_round.out | Bin 791 -> 11591 bytes
.../math_functions/test_format_round.groovy | 58 ++++++++++++++
5 files changed, 193 insertions(+), 4 deletions(-)
diff --git a/be/src/exprs/math_functions.cpp b/be/src/exprs/math_functions.cpp
index 202a6eabea3..93e28efb733 100644
--- a/be/src/exprs/math_functions.cpp
+++ b/be/src/exprs/math_functions.cpp
@@ -83,7 +83,7 @@ double MathFunctions::my_double_round(double value, int64_t
dec, bool dec_unsign
if (dec_negative && std::isinf(tmp)) {
tmp2 = 0.0;
- } else if (!dec_negative && std::isinf(value_mul_tmp)) {
+ } else if (!dec_negative && !std::isfinite(value_mul_tmp)) {
tmp2 = value;
} else if (truncate) {
if (value >= 0.0) {
diff --git a/be/src/vec/functions/function_string.h
b/be/src/vec/functions/function_string.h
index 09122aaf51c..97c950d97b7 100644
--- a/be/src/vec/functions/function_string.h
+++ b/be/src/vec/functions/function_string.h
@@ -3365,6 +3365,44 @@ struct FormatRoundDoubleImpl {
return {std::make_shared<DataTypeFloat64>(),
std::make_shared<vectorized::DataTypeInt32>()};
}
+ static std::string add_thousands_separator(const std::string&
formatted_num) {
+ // Find the position of the decimal point
+ size_t dot_pos = formatted_num.find('.');
+ if (dot_pos == std::string::npos) {
+ dot_pos = formatted_num.size();
+ }
+
+ // Handle the integer part
+ int start = (formatted_num[0] == '-') ? 1 : 0;
+ int digit_count = dot_pos - start;
+
+ // There is no need to add commas.
+ if (digit_count <= 3) {
+ return formatted_num;
+ }
+
+ std::string result;
+
+ if (start == 1) result += '-';
+
+ // Add the integer part (with comma)
+ int first_group = digit_count % 3;
+ if (first_group == 0) first_group = 3;
+ result.append(formatted_num, start, first_group);
+
+ for (size_t i = start + first_group; i < dot_pos; i += 3) {
+ result += ',';
+ result.append(formatted_num, i, 3);
+ }
+
+ // Add the decimal part (keep as it is)
+ if (dot_pos != formatted_num.size()) {
+ result.append(formatted_num, dot_pos);
+ }
+
+ return result;
+ }
+
template <bool is_const>
static Status execute(FunctionContext* context, ColumnString*
result_column,
const ColumnPtr col_ptr, ColumnPtr
decimal_places_col_ptr,
@@ -3382,9 +3420,15 @@ struct FormatRoundDoubleImpl {
// round to `decimal_places` decimal places
double value =
MathFunctions::my_double_round(data_column->get_element(i),
decimal_places,
false, false);
- StringRef str = FormatRound::do_format_round(
- context, fmt::format("{:.{}f}", value, decimal_places),
decimal_places);
- result_column->insert_data(str.data, str.size);
+ std::string formatted_value = fmt::format("{:.{}f}", value,
decimal_places);
+ if (std::isfinite(value)) {
+ auto res_str = add_thousands_separator(formatted_value);
+ result_column->insert_data(res_str.data(), res_str.size());
+ } else {
+ // if value is not finite, we just insert the original
formatted value
+ // e.g. "inf", "-inf", "nan"
+ result_column->insert_data(formatted_value.data(),
formatted_value.size());
+ }
}
return Status::OK();
}
diff --git a/be/test/exprs/math_functions_test.cpp
b/be/test/exprs/math_functions_test.cpp
new file mode 100644
index 00000000000..ce0fc635d64
--- /dev/null
+++ b/be/test/exprs/math_functions_test.cpp
@@ -0,0 +1,87 @@
+// 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.
+
+#include "exprs/math_functions.h"
+
+#include <gtest/gtest.h>
+
+#include <cmath>
+#include <limits>
+namespace doris {
+
+struct MathFunctionsTest : public ::testing::Test {};
+
+// Regular rounding test (truncate = false)
+TEST_F(MathFunctionsTest, DoubleRoundBasic) {
+ // Positive number rounding
+ EXPECT_DOUBLE_EQ(123.46, MathFunctions::my_double_round(123.456, 2, false,
false));
+ EXPECT_DOUBLE_EQ(123.45, MathFunctions::my_double_round(123.454, 2, false,
false));
+
+ // Negative number rounding
+ EXPECT_DOUBLE_EQ(-123.46, MathFunctions::my_double_round(-123.456, 2,
false, false));
+ EXPECT_DOUBLE_EQ(-123.45, MathFunctions::my_double_round(-123.454, 2,
false, false));
+
+ // Integer place rounding
+ EXPECT_DOUBLE_EQ(100.0,
+ MathFunctions::my_double_round(123.456, -2, false,
false)); // Hundreds place
+ EXPECT_DOUBLE_EQ(120.0,
+ MathFunctions::my_double_round(123.456, -1, false,
false)); // Tens place
+ EXPECT_DOUBLE_EQ(-100.0, MathFunctions::my_double_round(
+ -123.456, -2, false, false)); // Negative
number hundreds place
+}
+
+// Truncation mode test (truncate = true)
+TEST_F(MathFunctionsTest, DoubleRoundTruncate) {
+ // Positive number truncation
+ EXPECT_DOUBLE_EQ(123.45, MathFunctions::my_double_round(123.456, 2, false,
true));
+ EXPECT_DOUBLE_EQ(123.0, MathFunctions::my_double_round(123.789, 0, false,
true));
+
+ // Negative number truncation (towards zero)
+ EXPECT_DOUBLE_EQ(-123.45, MathFunctions::my_double_round(-123.456, 2,
false, true));
+ EXPECT_DOUBLE_EQ(-100.0, MathFunctions::my_double_round(-123.456, -2,
false, true));
+}
+
+// Special value handling (Infinity, NaN)
+TEST_F(MathFunctionsTest, DoubleRoundSpecialValues) {
+ const double inf = std::numeric_limits<double>::infinity();
+ const double nan = std::numeric_limits<double>::quiet_NaN();
+
+ // Infinity remains unchanged
+ EXPECT_DOUBLE_EQ(inf, MathFunctions::my_double_round(inf, 2, false,
false));
+ EXPECT_DOUBLE_EQ(-inf, MathFunctions::my_double_round(-inf, -3, true,
true));
+
+ // NaN returns NaN
+ EXPECT_TRUE(std::isnan(MathFunctions::my_double_round(nan, 2, false,
false)));
+
+ // Large precision causing overflow
+ EXPECT_DOUBLE_EQ(0.0, MathFunctions::my_double_round(123.456, -1000,
false, false));
+ EXPECT_DOUBLE_EQ(123.456, MathFunctions::my_double_round(123.456, -1000,
true,
+ false)); //
dec_unsigned handling
+}
+
+// Zero and boundary precision test
+TEST_F(MathFunctionsTest, DoubleRoundEdgeCases) {
+ // Zero value handling
+ EXPECT_DOUBLE_EQ(0.0, MathFunctions::my_double_round(0.0, 3, false,
false));
+ EXPECT_DOUBLE_EQ(0.0, MathFunctions::my_double_round(-0.0, 2, true, true));
+
+ // Zero precision
+ EXPECT_DOUBLE_EQ(123.0, MathFunctions::my_double_round(123.456, 0, false,
false));
+ EXPECT_DOUBLE_EQ(124.0, MathFunctions::my_double_round(123.789, 0, false,
false)); // Rounding
+}
+
+}; // namespace doris
\ No newline at end of file
diff --git
a/regression-test/data/query_p0/sql_functions/math_functions/test_format_round.out
b/regression-test/data/query_p0/sql_functions/math_functions/test_format_round.out
index aa9ccc5aa30..9a5e2caa452 100644
Binary files
a/regression-test/data/query_p0/sql_functions/math_functions/test_format_round.out
and
b/regression-test/data/query_p0/sql_functions/math_functions/test_format_round.out
differ
diff --git
a/regression-test/suites/query_p0/sql_functions/math_functions/test_format_round.groovy
b/regression-test/suites/query_p0/sql_functions/math_functions/test_format_round.groovy
index 1af614f6aac..0c106563493 100644
---
a/regression-test/suites/query_p0/sql_functions/math_functions/test_format_round.groovy
+++
b/regression-test/suites/query_p0/sql_functions/math_functions/test_format_round.groovy
@@ -62,4 +62,62 @@ suite("test_format_round", "p0") {
exception "it can not be less than 0"
}
+ order_qt_format_round_14 """ SELECT format_round(9876.54321, 0) AS result;
"""
+ order_qt_format_round_15 """ SELECT format_round(0.0000001, 7) AS result;
"""
+ order_qt_format_round_16 """ SELECT format_round(999999999.999999, 6) AS
result; """
+ order_qt_format_round_17 """ SELECT format_round(-123.456789, 3) AS
result; """
+ order_qt_format_round_18 """ SELECT format_round(1.23456789, 10) AS
result; """
+ order_qt_format_round_19 """ SELECT format_round(0.0, 2) AS result; """
+ order_qt_format_round_20 """ SELECT format_round(1234567890.123456789, 9)
AS result; """
+ order_qt_format_round_21 """ SELECT format_round(0.0000000001, 10) AS
result; """
+ order_qt_format_round_22 """ SELECT format_round(-999999999.999999, 6) AS
result; """
+ order_qt_format_round_23 """ SELECT format_round(123.456789, 1) AS result;
"""
+ order_qt_format_round_24 """ SELECT format_round(123.456789, 20) AS
result; """
+ order_qt_format_round_25 """ SELECT format_round(1.7976931348623157E+308,
2) AS result; """
+ order_qt_format_round_26 """ SELECT format_round(2.2250738585072014E-308,
20) AS result; """
+ order_qt_format_round_27 """ SELECT format_round(0.0, 0) AS result; """
+ order_qt_format_round_28 """ SELECT format_round(0.0, 10) AS result; """
+ order_qt_format_round_29 """ SELECT format_round(1.0, 0) AS result; """
+ order_qt_format_round_30 """ SELECT format_round(1.0, 10) AS result; """
+ order_qt_format_round_31 """ SELECT
format_round(0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001,
324) AS result; """
+ order_qt_format_round_32 """ SELECT format_round(1.7976931348623157E+308,
0) AS result; """
+ order_qt_format_round_33 """ SELECT format_round(2.2250738585072014E-308,
0) AS result; """
+ order_qt_format_round_34 """ SELECT format_round(1.7976931348623157E+308,
10) AS result; """
+ order_qt_format_round_35 """ SELECT format_round(2.2250738585072014E-308,
10) AS result; """
+ order_qt_format_round_36 """ SELECT format_round(1.7976931348623157E+308,
324) AS result; """
+ order_qt_format_round_37 """ SELECT format_round(2.2250738585072014E-308,
324) AS result; """
+ order_qt_format_round_38 """ SELECT format_round(1.0, 324) AS result; """
+ order_qt_format_round_39 """ SELECT format_round(0.0, 324) AS result; """
+ order_qt_format_round_40 """ SELECT
format_round(0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001,
0) AS result; """
+ order_qt_format_round_41 """ SELECT
format_round(0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001,
10) AS result; """
+ order_qt_format_round_42 """ SELECT
format_round(0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001,
324) AS result; """
+ order_qt_format_round_43 """ SELECT format_round(1.0, 0) AS result; """
+ order_qt_format_round_44 """ SELECT format_round(1.0, 10) AS result; """
+ order_qt_format_round_45 """ SELECT format_round(1.0, 324) AS result; """
+ order_qt_format_round_46 """ SELECT format_round(0.0, 0) AS result; """
+ order_qt_format_round_47 """ SELECT format_round(0.0, 10) AS result; """
+ order_qt_format_round_48 """ SELECT format_round(0.0, 324) AS result; """
+ order_qt_format_round_49 """ SELECT format_round(1.7976931348623157E+308,
0) AS result; """
+ order_qt_format_round_50 """ SELECT format_round(1.7976931348623157E+308,
10) AS result; """
+ order_qt_format_round_51 """ SELECT format_round(1.7976931348623157E+308,
324) AS result; """
+ order_qt_format_round_52 """ SELECT format_round(2.2250738585072014E-308,
0) AS result; """
+ order_qt_format_round_53 """ SELECT format_round(2.2250738585072014E-308,
10) AS result; """
+ order_qt_format_round_54 """ SELECT format_round(2.2250738585072014E-308,
324) AS result; """
+ order_qt_format_round_55 """ SELECT
format_round(0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001,
0) AS result; """
+ order_qt_format_round_56 """ SELECT
format_round(0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001,
10) AS result; """
+ order_qt_format_round_57 """ SELECT
format_round(0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001,
324) AS result; """
+ order_qt_format_round_58 """ SELECT format_round(1.0, 0) AS result; """
+ order_qt_format_round_59 """ SELECT format_round(1.0, 10) AS result; """
+ order_qt_format_round_60 """ SELECT format_round(1.0, 324) AS result; """
+ order_qt_format_round_61 """ SELECT format_round(0.0, 0) AS result; """
+ order_qt_format_round_62 """ SELECT format_round(0.0, 10) AS result; """
+ order_qt_format_round_63 """ SELECT format_round(0.0, 324) AS result; """
+ order_qt_format_round_64 """ SELECT format_round(1.7976931348623157E+308,
0) AS result; """
+ order_qt_format_round_65 """ SELECT format_round(1.7976931348623157E+308,
10) AS result; """
+ order_qt_format_round_66 """ SELECT format_round(1.7976931348623157E+308,
324) AS result; """
+ order_qt_format_round_67 """ SELECT format_round(2.2250738585072014E-308,
0) AS result; """
+ order_qt_format_round_68 """ SELECT format_round(2.2250738585072014E-308,
10) AS result; """
+ order_qt_format_round_69 """ SELECT format_round(2.2250738585072014E-308,
324) AS result; """
+ order_qt_format_round_70 """ SELECT
format_round(0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001,
0) AS result; """
+ order_qt_format_round_71 """ SELECT
format_round(0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001,
10) AS result; """
}
\ No newline at end of file
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]