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

Reply via email to