Skip to content

Commit 67e72e1

Browse files
authored
[fix](function) Handle case-insensitive auto partition arguments (#67121)
`AUTO_PARTITION_NAME` accepted case-insensitive `list` and `range` arguments in FE, but BE compared them case-sensitively. Uppercase `LIST` was incorrectly routed to the range implementation and could access a missing third argument, causing a BE core. The BE now normalizes partition type and range granularity arguments before dispatch, with unit coverage for mixed-case inputs.
1 parent 8bf231e commit 67e72e1

2 files changed

Lines changed: 41 additions & 9 deletions

File tree

be/src/exprs/function/function_string_misc.cpp

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include <algorithm>
2626
#include <bit>
2727
#include <boost/locale.hpp>
28+
#include <cctype>
2829
#include <climits>
2930
#include <cstddef>
3031
#include <cstdint>
@@ -141,9 +142,11 @@ class FunctionAutoPartitionName : public IFunction {
141142
auto& res_offset = res->get_offsets();
142143
res_offset.resize(input_rows_count);
143144

144-
const char* partition_type = chars_list[0]->raw_data();
145+
std::string partition_type(chars_list[0]->raw_data(), (*offsets_list[0])[0]);
146+
std::transform(partition_type.begin(), partition_type.end(), partition_type.begin(),
147+
[](unsigned char c) { return static_cast<char>(std::tolower(c)); });
145148
// partition type is list|range
146-
if (std::strncmp(partition_type, "list", 4) == 0) {
149+
if (partition_type == "list") {
147150
return _auto_partition_type_of_list(chars_list, offsets_list, is_const_args, null_list,
148151
res_data, res_offset, input_rows_count,
149152
argument_size, block, result, res);
@@ -256,7 +259,9 @@ class FunctionAutoPartitionName : public IFunction {
256259
auto& res_offset, size_t input_rows_count,
257260
size_t argument_size, Block& block, uint32_t result,
258261
auto& res) const {
259-
const char* range_type = chars_list[1]->raw_data();
262+
std::string range_type(chars_list[1]->raw_data(), (*offsets_list[1])[0]);
263+
std::transform(range_type.begin(), range_type.end(), range_type.begin(),
264+
[](unsigned char c) { return static_cast<char>(std::tolower(c)); });
260265

261266
res_data.resize(15 * input_rows_count);
262267
for (int i = 0; i < input_rows_count; i++) {
@@ -292,21 +297,21 @@ class FunctionAutoPartitionName : public IFunction {
292297
// minute => 2022 12 11 30 00
293298
// second => 2022 12 12 12 30 20
294299

295-
if (!strncmp(range_type, "year", 4)) {
300+
if (range_type == "year") {
296301
curr_len += _copy_date_str_of_len_to_res_data(res_data, res_offset, date_str, i, 1);
297302
memcpy(&res_data[res_offset[i - 1]] + curr_len, "0101", 4);
298303
curr_len += 4;
299-
} else if (!strncmp(range_type, "month", 5)) {
304+
} else if (range_type == "month") {
300305
curr_len += _copy_date_str_of_len_to_res_data(res_data, res_offset, date_str, i, 2);
301306
memcpy(&res_data[res_offset[i - 1]] + curr_len, "01", 2);
302307
curr_len += 2;
303-
} else if (!strncmp(range_type, "day", 3)) {
308+
} else if (range_type == "day") {
304309
curr_len += _copy_date_str_of_len_to_res_data(res_data, res_offset, date_str, i, 3);
305-
} else if (!strncmp(range_type, "hour", 4)) {
310+
} else if (range_type == "hour") {
306311
curr_len += _copy_date_str_of_len_to_res_data(res_data, res_offset, date_str, i, 4);
307-
} else if (!strncmp(range_type, "minute", 6)) {
312+
} else if (range_type == "minute") {
308313
curr_len += _copy_date_str_of_len_to_res_data(res_data, res_offset, date_str, i, 5);
309-
} else if (!strncmp(range_type, "second", 6)) {
314+
} else if (range_type == "second") {
310315
curr_len += _copy_date_str_of_len_to_res_data(res_data, res_offset, date_str, i, 6);
311316
}
312317

be/test/exprs/function/function_string_test.cpp

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,33 @@ DataSet make_md5_varbinary_dataset(const std::vector<std::string>& inputs) {
8181

8282
} // namespace
8383

84+
TEST(function_string_test, function_auto_partition_name_case_insensitive_test) {
85+
const InputTypeSet list_input_types = {Consted {PrimitiveType::TYPE_VARCHAR},
86+
Consted {PrimitiveType::TYPE_VARCHAR}};
87+
const DataSet list_data_set = {
88+
{{std::string("LIST"), std::string("edc_server2")}, std::string("pedc5fserver211")},
89+
{{std::string("LiSt"), std::string("edc_server2")}, std::string("pedc5fserver211")},
90+
};
91+
for (const auto& data : list_data_set) {
92+
ASSERT_TRUE(check_function<DataTypeString>("auto_partition_name", list_input_types, {data})
93+
.ok());
94+
}
95+
96+
const InputTypeSet range_input_types = {Consted {PrimitiveType::TYPE_VARCHAR},
97+
Consted {PrimitiveType::TYPE_VARCHAR},
98+
Consted {PrimitiveType::TYPE_VARCHAR}};
99+
const DataSet range_data_set = {
100+
{{std::string("RANGE"), std::string("MONTH"), std::string("2022-12-12 19:20:30")},
101+
std::string("p20221201000000")},
102+
{{std::string("rAnGe"), std::string("dAy"), std::string("2022-12-12 19:20:30")},
103+
std::string("p20221212000000")},
104+
};
105+
for (const auto& data : range_data_set) {
106+
ASSERT_TRUE(check_function<DataTypeString>("auto_partition_name", range_input_types, {data})
107+
.ok());
108+
}
109+
}
110+
84111
TEST(function_string_test, function_string_substr_test) {
85112
std::string func_name = "substr";
86113

0 commit comments

Comments
 (0)