Skip to content

Commit

Permalink
[bug](function) fix conv function get wrong result as parse overflow (a…
Browse files Browse the repository at this point in the history
…pache#38001)

```
mysql> select conv('ffffffffffffff', 24, 2);
+------------------------------------------------------------------+
| conv('ffffffffffffff', 24, 2)                                    |
+------------------------------------------------------------------+
| 1111111111111111111111111111111111111111111111111111111111111111 |
+------------------------------------------------------------------+

before get wrong result as 'ffffffffffffff' have beyond the max value of int64, so get max value: std::numeric_limits<int64_t>::max()


mysql> select conv('ffffffffffffff', 24, 2);
+------------------------------------------------------------------+
| conv('ffffffffffffff', 24, 2)                                    |
+------------------------------------------------------------------+
| 1011111001100011011111100110111101001101111010011011110100110111 |
+------------------------------------------------------------------+
now change it to parse as uint64_t could get result.
But if the value is still overflow, will get max value of uint64_t
```
  • Loading branch information
zhangstar333 committed Jul 24, 2024
1 parent ef00dad commit 8ce38b7
Show file tree
Hide file tree
Showing 3 changed files with 18 additions and 1 deletion.
6 changes: 5 additions & 1 deletion be/src/vec/functions/function_conv.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -206,8 +206,12 @@ struct ConvStringImpl {
size_t index) {
StringRef str = data_column->get_data_at(index);
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<int64_t>::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<int64_t>(str.data, str.size, src_base, &parse_res);
StringParser::string_to_int<uint64_t>(str.data, str.size, src_base, &parse_res);
if (src_base < 0 && decimal_num >= 0) {
result_null_map[index] = true;
result_column->insert_default();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,12 @@
-- !select --
1111

-- !select2 --
1011111001100011011111100110111101001101111010011011110100110111

-- !select3 --
1111111111111111111111111111111111111111111111111111111010001001

-- !select4 --
18446744073709551615

Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,9 @@ suite("test_conv") {
sql "SET enable_nereids_planner=true"
sql "SET enable_fallback_to_original_planner=false"
qt_select "SELECT CONV(15,10,2)"
qt_select2 "select conv('ffffffffffffff', 24, 2);"
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);"
}

0 comments on commit 8ce38b7

Please sign in to comment.