From 0ed5540208720cb27ec16fe3b42bc95180413fe9 Mon Sep 17 00:00:00 2001 From: zhangstar333 <87313068+zhangstar333@users.noreply.github.com> Date: Fri, 13 Sep 2024 14:18:54 +0800 Subject: [PATCH] [Bug](conv) fix conv function parser string failure return wrong result (#40530) ## Proposed changes Issue Number: close #39618 --- be/src/vec/functions/function_conv.cpp | 9 ++++++++- .../sql_functions/math_functions/test_conv.out | 3 +++ .../sql_functions/math_functions/test_conv.groovy | 10 ++++++++++ 3 files changed, 21 insertions(+), 1 deletion(-) diff --git a/be/src/vec/functions/function_conv.cpp b/be/src/vec/functions/function_conv.cpp index 78abad9f342ecf..9db79b89993a91 100644 --- a/be/src/vec/functions/function_conv.cpp +++ b/be/src/vec/functions/function_conv.cpp @@ -205,13 +205,20 @@ struct ConvStringImpl { ColumnString* result_column, NullMap& result_null_map, size_t index) { StringRef str = data_column->get_data_at(index); + auto new_size = str.size; + // eg: select conv('1.464868',10,2); the result should be return 1. + // But StringParser::string_to_int will PARSE_FAILURE and return 0, + // so should handle the point part of number firstly if need convert '1.464868' to number 1 + if (auto pos = str.to_string_view().find_first_of('.'); pos != std::string::npos) { + new_size = pos; + } StringParser::ParseResult parse_res; // select conv('ffffffffffffff', 24, 2); // if 'ffffffffffffff' parse as int64_t will be overflow, will be get max value: std::numeric_limits::max() // so change it parse as uint64_t, and return value could still use int64_t, in function decimal_to_base could handle it. // But if the value is still overflow in uint64_t, will get max value of uint64_t int64_t decimal_num = - StringParser::string_to_int(str.data, str.size, src_base, &parse_res); + StringParser::string_to_int(str.data, new_size, src_base, &parse_res); if (src_base < 0 && decimal_num >= 0) { result_null_map[index] = true; result_column->insert_default(); diff --git a/regression-test/data/nereids_p0/sql_functions/math_functions/test_conv.out b/regression-test/data/nereids_p0/sql_functions/math_functions/test_conv.out index e05c1a3437ae86..95e67e726d6ac5 100644 --- a/regression-test/data/nereids_p0/sql_functions/math_functions/test_conv.out +++ b/regression-test/data/nereids_p0/sql_functions/math_functions/test_conv.out @@ -11,3 +11,6 @@ -- !select4 -- 18446744073709551615 +-- !select5 -- +1 1.464868 + diff --git a/regression-test/suites/nereids_p0/sql_functions/math_functions/test_conv.groovy b/regression-test/suites/nereids_p0/sql_functions/math_functions/test_conv.groovy index 214e65ff4bdb16..b46aee62ba3928 100644 --- a/regression-test/suites/nereids_p0/sql_functions/math_functions/test_conv.groovy +++ b/regression-test/suites/nereids_p0/sql_functions/math_functions/test_conv.groovy @@ -23,5 +23,15 @@ suite("test_conv") { qt_select3 "select conv('-ff', 24, 2);" // if beyond the max value of uint64, use max_uint64 as res qt_select4 "select conv('fffffffffffffffffffffffffffffffff', 24, 10);" + + sql """DROP TABLE IF EXISTS `test_tb`; """ + sql """ create table test_tb(int_1 int, float_2 float) PROPERTIES ( + "replication_num" = "1" + ); + """ + + sql """ insert into test_tb values(1, 1.464868); """ + + qt_select5 """ select conv(float_2,10,2),float_2 from test_tb; """ }