cambyzju commented on code in PR #50151: URL: https://github.com/apache/doris/pull/50151#discussion_r2053885099
########## be/src/vec/functions/function_jsonb.cpp: ########## @@ -1936,25 +2038,387 @@ class FunctionJsonSearch : public IFunction { col_search->get_name()); } if (search_is_const) { - CheckNullFun search_null_check = always_not_null; + JsonSearchUtil::CheckNullFun search_null_check = JsonSearchUtil::always_not_null; if (col_search->is_null_at(0)) { - search_null_check = always_null; + search_null_check = JsonSearchUtil::always_null; } - RETURN_IF_ERROR(execute_vector<true>( + RETURN_IF_ERROR(JsonSearchUtil::execute_vector<true>( block, input_rows_count, json_null_check, get_json_fun, one_null_check, one_check, search_null_check, col_search_string, context, result)); } else { - CheckNullFun search_null_check = [col_search](size_t i) { + JsonSearchUtil::CheckNullFun search_null_check = [col_search](size_t i) { return col_search->is_null_at(i); }; - RETURN_IF_ERROR(execute_vector<false>( + RETURN_IF_ERROR(JsonSearchUtil::execute_vector<false>( block, input_rows_count, json_null_check, get_json_fun, one_null_check, one_check, search_null_check, col_search_string, context, result)); } return Status::OK(); } }; +struct JsonSearchEscape { + static DataTypes get_variadic_argument_types() { + return { + std::make_shared<DataTypeString>(), + std::make_shared<DataTypeString>(), + std::make_shared<DataTypeString>(), + std::make_shared<DataTypeString>(), + }; + } + + static Status execute_impl(FunctionContext* context, Block& block, + const ColumnNumbers& arguments, uint32_t result, + size_t input_rows_count) { + if (arguments.size() != 4) { + return Status::InvalidArgument("wrong arguments for function json_search"); + } + + JsonSearchUtil::CheckNullFun json_null_check = JsonSearchUtil::always_not_null; + JsonSearchUtil::GetJsonStringRefFun get_json_fun; + ColumnPtr col_json; + bool json_is_const = false; + // prepare jsonb data column + std::tie(col_json, json_is_const) = + unpack_if_const(block.get_by_position(arguments[0]).column); + const auto* col_json_string = check_and_get_column<ColumnString>(col_json.get()); + if (const auto* nullable = check_and_get_column<ColumnNullable>(col_json.get())) { + col_json_string = + check_and_get_column<ColumnString>(nullable->get_nested_column_ptr().get()); + } + + if (!col_json_string) { + return Status::RuntimeError("Illegal arg json {} should be ColumnString", + col_json->get_name()); + } + if (json_is_const) { + if (col_json->is_null_at(0)) { + json_null_check = JsonSearchUtil::always_null; + } else { + const auto& json_str = col_json_string->get_data_at(0); + get_json_fun = [json_str](size_t i) { return json_str; }; + } + } else { + json_null_check = [col_json](size_t i) { return col_json->is_null_at(i); }; + get_json_fun = [col_json_string](size_t i) { return col_json_string->get_data_at(i); }; + } + + JsonSearchUtil::CheckNullFun one_null_check = JsonSearchUtil::always_not_null; + JsonSearchUtil::OneFun one_check = JsonSearchUtil::always_one; + ColumnPtr col_one; + bool one_is_const = false; + // prepare jsonb data column + std::tie(col_one, one_is_const) = + unpack_if_const(block.get_by_position(arguments[1]).column); + const auto* col_one_string = check_and_get_column<ColumnString>(col_one.get()); + if (const auto* nullable = check_and_get_column<ColumnNullable>(col_one.get())) { + col_one_string = check_and_get_column<ColumnString>(*nullable->get_nested_column_ptr()); + } + if (!col_one_string) { + return Status::RuntimeError("Illegal arg one {} should be ColumnString", + col_one->get_name()); + } + if (one_is_const) { + if (col_one->is_null_at(0)) { + one_null_check = JsonSearchUtil::always_null; + } else { + const auto& one_or_all = col_one_string->get_data_at(0); + std::string one_or_all_str = one_or_all.to_string(); + if (strcasecmp(one_or_all_str.c_str(), JsonSearchUtil::all) == 0) { + one_check = JsonSearchUtil::always_all; + } else if (strcasecmp(one_or_all_str.c_str(), JsonSearchUtil::one) == 0) { + // nothing + } else { + // an error occurs if the one_or_all argument is not 'one' nor 'all'. + return Status::InvalidArgument( + "the one_or_all argument {} is not 'one' not 'all'", one_or_all_str); + } + } + } else { + one_null_check = [col_one](size_t i) { return col_one->is_null_at(i); }; + one_check = [col_one_string](size_t i, bool* is_one) { + const auto& one_or_all = col_one_string->get_data_at(i); + std::string one_or_all_str = one_or_all.to_string(); + if (strcasecmp(one_or_all_str.c_str(), JsonSearchUtil::all) == 0) { + *is_one = false; + } else if (strcasecmp(one_or_all_str.c_str(), JsonSearchUtil::one) == 0) { + *is_one = true; + } else { + // an error occurs if the one_or_all argument is not 'one' nor 'all'. + return Status::InvalidArgument( + "the one_or_all argument {} is not 'one' not 'all'", one_or_all_str); + } + return Status::OK(); + }; + } + + JsonSearchUtil::CheckNullFun start_null_check = JsonSearchUtil::always_null; + JsonSearchUtil::GetJsonStartFun get_start_path; + + JsonSearchUtil::CheckNullFun escape_null_check = JsonSearchUtil::always_null; + JsonSearchUtil::GetJsonEscapeFun get_escape_string; + + ColumnPtr col_escape; + bool escape_is_const = false; + + std::tie(col_escape, escape_is_const) = + unpack_if_const(block.get_by_position(arguments[3]).column); + + const auto* col_escape_string = check_and_get_column<ColumnString>(col_escape.get()); + if (const auto* nullable = check_and_get_column<ColumnNullable>(col_escape.get())) { + col_escape_string = + check_and_get_column<ColumnString>(*nullable->get_nested_column_ptr()); + } + if (!col_escape_string) { + return Status::RuntimeError("Illegal arg pattern {} should be ColumnString", + col_escape->get_name()); + } + if (escape_is_const) { + if (col_escape->is_null_at(0)) { + escape_null_check = JsonSearchUtil::always_null; + } + } else { + escape_null_check = [col_escape](size_t i) { return col_escape->is_null_at(i); }; + get_escape_string = [col_escape_string](size_t i, char* escape_char) { + auto escape_string = col_escape_string->get_data_at(i).to_string(); + if (escape_string.length() != 1) { + return Status::RuntimeError("Illegal arg pattern {} should be char", + col_escape_string->get_name()); + } + *escape_char = escape_string.at(0); + return Status::OK(); + }; + } + + ColumnPtr col_search; + bool search_is_const = false; + std::tie(col_search, search_is_const) = + unpack_if_const(block.get_by_position(arguments[2]).column); + + const auto* col_search_string = check_and_get_column<ColumnString>(col_search.get()); + if (const auto* nullable = check_and_get_column<ColumnNullable>(col_search.get())) { + col_search_string = + check_and_get_column<ColumnString>(*nullable->get_nested_column_ptr()); + } + if (!col_search_string) { + return Status::RuntimeError("Illegal arg pattern {} should be ColumnString", + col_search->get_name()); + } + if (search_is_const) { + JsonSearchUtil::CheckNullFun search_null_check = JsonSearchUtil::always_not_null; + if (col_search->is_null_at(0)) { + search_null_check = JsonSearchUtil::always_null; + } + RETURN_IF_ERROR(JsonSearchUtil::execute_vector<true>( + block, input_rows_count, json_null_check, get_json_fun, one_null_check, + one_check, search_null_check, col_search_string, context, result, + start_null_check, get_start_path, escape_null_check, get_escape_string)); + } else { + JsonSearchUtil::CheckNullFun search_null_check = [col_search](size_t i) { + return col_search->is_null_at(i); + }; + RETURN_IF_ERROR(JsonSearchUtil::execute_vector<false>( + block, input_rows_count, json_null_check, get_json_fun, one_null_check, + one_check, search_null_check, col_search_string, context, result, + start_null_check, get_start_path, escape_null_check, get_escape_string)); + } + return Status::OK(); + } +}; + +struct JsonSearchStartPath { Review Comment: please reuse codes in: `JsonSearchNormal JsonSearchEscape JsonSearchStartPath` -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: commits-unsubscr...@doris.apache.org For queries about this service, please contact Infrastructure at: us...@infra.apache.org --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@doris.apache.org For additional commands, e-mail: commits-h...@doris.apache.org