You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@doris.apache.org by "github-actions[bot] (via GitHub)" <gi...@apache.org> on 2023/12/09 05:41:14 UTC

Re: [PR] [Feature-WIP][UDF][WASM] support wasm udf [doris]

github-actions[bot] commented on code in PR #24504:
URL: https://github.com/apache/doris/pull/24504#discussion_r1421268739


##########
be/src/util/wasm_manager.cpp:
##########
@@ -0,0 +1,97 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#include "util/wasm_manager.h"
+namespace doris {
+
+WasmFunctionManager::WasmFunctionManager() {
+    engine = new wasmtime::Engine;
+    store = new wasmtime::Store(*engine);
+}
+
+WasmFunctionManager::~WasmFunctionManager() {

Review Comment:
   warning: use '= default' to define a trivial destructor [modernize-use-equals-default]
   ```cpp
   WasmFunctionManager::~WasmFunctionManager() {
                        ^
   ```
   



##########
be/src/vec/functions/function_wasm.h:
##########
@@ -0,0 +1,104 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#pragma once
+
+#include <fmt/format.h>
+#include <stddef.h>
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "common/status.h"
+#include "udf/udf.h"
+#include "util/wasm_manager.h"
+#include "vec/core/block.h"
+#include "vec/core/column_numbers.h"
+#include "vec/core/column_with_type_and_name.h"
+#include "vec/core/columns_with_type_and_name.h"
+#include "vec/core/types.h"
+#include "vec/data_types/data_type.h"
+#include "vec/functions/function.h"
+
+namespace doris {} // namespace doris
+
+namespace doris::vectorized {
+
+class WasmFnImpl {
+public:
+    WasmFnImpl(const TFunction& fn, const DataTypes& argument_types,
+               const DataTypePtr& return_type);
+    ~WasmFnImpl() = default;
+    Status vec_call(FunctionContext* context, vectorized::Block& block,
+                    const std::vector<size_t>& arguments, size_t result, size_t input_rows_count);
+    bool available() { return _manager != nullptr; }
+
+private:
+    std::shared_ptr<WasmFunctionManager> _manager;
+    std::string _function_name;
+    std::string _signature;
+    TFunction _fn;
+    DataTypes _defined_argument_types;
+    DataTypePtr _return_type;
+};
+
+class FunctionWasm : public IFunctionBase {
+public:
+    FunctionWasm(const TFunction& fn, const DataTypes& argument_types,
+                 const DataTypePtr& return_type);
+
+    static FunctionBasePtr create(const TFunction& fn, const ColumnsWithTypeAndName& argument_types,
+                                  const DataTypePtr& return_type) {
+        DataTypes data_types(argument_types.size());
+        for (size_t i = 0; i < argument_types.size(); ++i) {
+            data_types[i] = argument_types[i].type;
+        }
+        return std::make_shared<FunctionWasm>(fn, data_types, return_type);
+    }
+
+    /// Get the main function name.
+    String get_name() const override {
+        return fmt::format("{}: [{}/{}]", _tfn.name.function_name, _tfn.hdfs_location,
+                           _tfn.scalar_fn.symbol);
+    }
+
+    const DataTypes& get_argument_types() const override { return _argument_types; }
+    const DataTypePtr& get_return_type() const override { return _return_type; }

Review Comment:
   warning: function 'get_return_type' should be marked [[nodiscard]] [modernize-use-nodiscard]
   
   ```suggestion
       [[nodiscard]] const DataTypePtr& get_return_type() const override { return _return_type; }
   ```
   



##########
function_json.cpp:
##########
@@ -0,0 +1,1320 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#include <rapidjson/allocators.h>
+#include <rapidjson/document.h>
+#include <rapidjson/encodings.h>
+#include <rapidjson/pointer.h>
+#include <rapidjson/rapidjson.h>
+#include <rapidjson/stringbuffer.h>
+#include <rapidjson/writer.h>
+#include <re2/re2.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <algorithm>
+#include <boost/iterator/iterator_facade.hpp>
+#include <boost/token_functions.hpp>
+#include <boost/tokenizer.hpp>
+#include <memory>
+#include <string>
+#include <string_view>
+#include <type_traits>
+#include <utility>
+#include <vector>
+
+// IWYU pragma: no_include <opentelemetry/common/threadlocal.h>
+#include "common/compiler_util.h" // IWYU pragma: keep
+#include "common/status.h"
+#include "exprs/json_functions.h"
+#ifdef __AVX2__
+#include "util/jsonb_parser_simd.h"
+#else
+#include "util/jsonb_parser.h"
+#endif
+#include "util/string_parser.hpp"
+#include "util/string_util.h"
+#include "vec/aggregate_functions/aggregate_function.h"
+#include "vec/columns/column.h"
+#include "vec/columns/column_nullable.h"
+#include "vec/columns/column_string.h"
+#include "vec/columns/column_vector.h"
+#include "vec/columns/columns_number.h"
+#include "vec/common/assert_cast.h"
+#include "vec/common/string_ref.h"
+#include "vec/core/block.h"
+#include "vec/core/column_numbers.h"
+#include "vec/core/column_with_type_and_name.h"
+#include "vec/core/types.h"
+#include "vec/data_types/data_type.h"
+#include "vec/data_types/data_type_nullable.h"
+#include "vec/data_types/data_type_number.h"
+#include "vec/data_types/data_type_string.h"
+#include "vec/functions/function.h"
+#include "vec/functions/function_string.h"
+#include "vec/functions/function_totype.h"
+#include "vec/functions/simple_function_factory.h"
+#include "vec/utils/template_helpers.hpp"
+
+namespace doris {
+class FunctionContext;
+} // namespace doris
+
+namespace doris::vectorized {
+static const re2::RE2 JSON_PATTERN("^([^\\\"\\[\\]]*)(?:\\[([0-9]+|\\*)\\])?");
+
+template <typename T, typename U>
+void char_split(std::vector<T>& res, const U& var, char p) {
+    int start = 0;
+    int pos = start;
+    int end = var.length();
+    while (pos < end) {
+        while (var[pos] != p && pos < end) {
+            pos++;
+        }
+        res.emplace_back(&var[start], pos - start);
+        pos++;
+        start = pos;
+    }
+}
+
+// T = std::vector<std::string>
+// TODO: update RE2 to support std::vector<std::string_view>
+template <typename T>
+void get_parsed_paths(const T& path_exprs, std::vector<JsonPath>* parsed_paths) {
+    if (path_exprs.empty()) {
+        return;
+    }
+
+    if (path_exprs[0] != "$") {
+        parsed_paths->emplace_back("", -1, false);
+    } else {
+        parsed_paths->emplace_back("$", -1, true);
+    }
+
+    for (int i = 1; i < path_exprs.size(); i++) {
+        std::string col;
+        std::string index;
+        if (UNLIKELY(!RE2::FullMatch(path_exprs[i], JSON_PATTERN, &col, &index))) {
+            parsed_paths->emplace_back("", -1, false);
+        } else {
+            int idx = -1;
+            if (!index.empty()) {
+                if (index == "*") {
+                    idx = -2;
+                } else {
+                    idx = atoi(index.c_str());
+                }
+            }
+            parsed_paths->emplace_back(col, idx, true);
+        }
+    }
+}
+
+rapidjson::Value* match_value(const std::vector<JsonPath>& parsed_paths, rapidjson::Value* document,
+                              rapidjson::Document::AllocatorType& mem_allocator,
+                              bool is_insert_null = false) {
+    rapidjson::Value* root = document;
+    rapidjson::Value* array_obj = nullptr;
+    for (int i = 1; i < parsed_paths.size(); i++) {
+        if (root == nullptr || root->IsNull()) {
+            return nullptr;
+        }
+
+        if (UNLIKELY(!parsed_paths[i].is_valid)) {
+            return nullptr;
+        }
+
+        const std::string& col = parsed_paths[i].key;
+        int index = parsed_paths[i].idx;
+        if (LIKELY(!col.empty())) {
+            if (root->IsArray()) {
+                array_obj = static_cast<rapidjson::Value*>(
+                        mem_allocator.Malloc(sizeof(rapidjson::Value)));
+                array_obj->SetArray();
+                bool is_null = true;
+
+                // if array ,loop the array,find out all Objects,then find the results from the objects
+                for (int j = 0; j < root->Size(); j++) {
+                    rapidjson::Value* json_elem = &((*root)[j]);
+
+                    if (json_elem->IsArray() || json_elem->IsNull()) {
+                        continue;
+                    } else {
+                        if (!json_elem->IsObject()) {
+                            continue;
+                        }
+                        if (!json_elem->HasMember(col.c_str())) {
+                            if (is_insert_null) { // not found item, then insert a null object.
+                                is_null = false;
+                                rapidjson::Value nullObject(rapidjson::kNullType);
+                                array_obj->PushBack(nullObject, mem_allocator);
+                            }
+                            continue;
+                        }
+                        rapidjson::Value* obj = &((*json_elem)[col.c_str()]);
+                        if (obj->IsArray()) {
+                            is_null = false;
+                            for (int k = 0; k < obj->Size(); k++) {
+                                array_obj->PushBack((*obj)[k], mem_allocator);
+                            }
+                        } else if (!obj->IsNull()) {
+                            is_null = false;
+                            array_obj->PushBack(*obj, mem_allocator);
+                        }
+                    }
+                }
+
+                root = is_null ? &(array_obj->SetNull()) : array_obj;
+            } else if (root->IsObject()) {
+                if (!root->HasMember(col.c_str())) {
+                    return nullptr;
+                } else {
+                    root = &((*root)[col.c_str()]);
+                }
+            } else {
+                // root is not a nested type, return NULL
+                return nullptr;
+            }
+        }
+
+        if (UNLIKELY(index != -1)) {
+            // judge the rapidjson:Value, which base the top's result,
+            // if not array return NULL;else get the index value from the array
+            if (root->IsArray()) {
+                if (root->IsNull()) {
+                    return nullptr;
+                } else if (index == -2) {
+                    // [*]
+                    array_obj = static_cast<rapidjson::Value*>(
+                            mem_allocator.Malloc(sizeof(rapidjson::Value)));
+                    array_obj->SetArray();
+
+                    for (int j = 0; j < root->Size(); j++) {
+                        rapidjson::Value v;
+                        v.CopyFrom((*root)[j], mem_allocator);
+                        array_obj->PushBack(v, mem_allocator);
+                    }
+                    root = array_obj;
+                } else if (index >= root->Size()) {
+                    return nullptr;
+                } else {
+                    root = &((*root)[index]);
+                }
+            } else {
+                return nullptr;
+            }
+        }
+    }
+    return root;
+}
+
+template <JsonFunctionType fntype>
+rapidjson::Value* get_json_object(std::string_view json_string, std::string_view path_string,
+                                  rapidjson::Document* document) {
+    std::vector<JsonPath>* parsed_paths;
+    std::vector<JsonPath> tmp_parsed_paths;
+
+#ifdef USE_LIBCPP
+    std::string s(path_string);
+    auto tok = get_json_token(s);
+#else
+    auto tok = get_json_token(path_string);
+#endif
+    std::vector<std::string> paths(tok.begin(), tok.end());
+    get_parsed_paths(paths, &tmp_parsed_paths);
+    if (tmp_parsed_paths.empty()) {
+        return document;
+    }
+
+    parsed_paths = &tmp_parsed_paths;
+
+    if (!(*parsed_paths)[0].is_valid) {
+        return document;
+    }
+
+    if (UNLIKELY((*parsed_paths).size() == 1)) {
+        if (fntype == JSON_FUN_STRING) {
+            document->SetString(json_string.data(), json_string.size(), document->GetAllocator());
+        } else {
+            return document;
+        }
+    }
+
+    document->Parse(json_string.data(), json_string.size());
+    if (UNLIKELY(document->HasParseError())) {
+        // VLOG_CRITICAL << "Error at offset " << document->GetErrorOffset() << ": "
+        //         << GetParseError_En(document->GetParseError());
+        document->SetNull();
+        return document;
+    }
+
+    return match_value(*parsed_paths, document, document->GetAllocator());
+}
+
+template <typename NumberType>
+struct GetJsonNumberType {
+    using ReturnType = typename NumberType::ReturnType;
+    using ColumnType = typename NumberType::ColumnType;
+    using Container = typename ColumnType::Container;
+
+    static void get_json_impl(rapidjson::Value*& root, const std::string_view& json_string,
+                              const std::string_view& path_string, rapidjson::Document& document,
+                              typename NumberType::T& res, UInt8& null_map) {
+        if constexpr (std::is_same_v<double, typename NumberType::T>) {
+            root = get_json_object<JSON_FUN_DOUBLE>(json_string, path_string, &document);
+            handle_result<double>(root, res, null_map);
+        } else if constexpr (std::is_same_v<int32_t, typename NumberType::T>) {
+            root = get_json_object<JSON_FUN_DOUBLE>(json_string, path_string, &document);
+            handle_result<int32_t>(root, res, null_map);
+        } else if constexpr (std::is_same_v<int64_t, typename NumberType::T>) {
+            root = get_json_object<JSON_FUN_DOUBLE>(json_string, path_string, &document);
+            handle_result<int64_t>(root, res, null_map);
+        }
+    }
+    static void vector_vector(FunctionContext* context, const ColumnString::Chars& ldata,
+                              const ColumnString::Offsets& loffsets,
+                              const ColumnString::Chars& rdata,
+                              const ColumnString::Offsets& roffsets, Container& res,
+                              NullMap& null_map) {
+        size_t size = loffsets.size();
+        res.resize(size);
+        for (size_t i = 0; i < size; ++i) {
+            const char* l_raw_str = reinterpret_cast<const char*>(&ldata[loffsets[i - 1]]);
+            int l_str_size = loffsets[i] - loffsets[i - 1];
+            const char* r_raw_str = reinterpret_cast<const char*>(&rdata[roffsets[i - 1]]);
+            int r_str_size = roffsets[i] - roffsets[i - 1];
+            if (null_map[i]) {
+                res[i] = 0;
+                continue;
+            }
+
+            std::string_view json_string(l_raw_str, l_str_size);
+            std::string_view path_string(r_raw_str, r_str_size);
+            rapidjson::Document document;
+            rapidjson::Value* root = nullptr;
+
+            get_json_impl(root, json_string, path_string, document, res[i], null_map[i]);
+        }
+    }
+    static void vector_scalar(FunctionContext* context, const ColumnString::Chars& ldata,
+                              const ColumnString::Offsets& loffsets, const StringRef& rdata,
+                              Container& res, NullMap& null_map) {
+        size_t size = loffsets.size();
+        res.resize(size);
+        std::string_view path_string(rdata.data, rdata.size);
+        for (size_t i = 0; i < size; ++i) {
+            const char* l_raw_str = reinterpret_cast<const char*>(&ldata[loffsets[i - 1]]);
+            int l_str_size = loffsets[i] - loffsets[i - 1];
+            if (null_map[i]) {
+                res[i] = 0;
+                continue;
+            }
+            std::string_view json_string(l_raw_str, l_str_size);
+
+            rapidjson::Document document;
+            rapidjson::Value* root = nullptr;
+
+            get_json_impl(root, json_string, path_string, document, res[i], null_map[i]);
+        }
+    }
+    static void scalar_vector(FunctionContext* context, const StringRef& ldata,
+                              const ColumnString::Chars& rdata,
+                              const ColumnString::Offsets& roffsets, Container& res,
+                              NullMap& null_map) {
+        size_t size = roffsets.size();
+        res.resize(size);
+        std::string_view json_string(ldata.data, ldata.size);
+        for (size_t i = 0; i < size; ++i) {
+            const char* r_raw_str = reinterpret_cast<const char*>(&rdata[roffsets[i - 1]]);
+            int r_str_size = roffsets[i] - roffsets[i - 1];
+            if (null_map[i]) {
+                res[i] = 0;
+                continue;
+            }
+            std::string_view path_string(r_raw_str, r_str_size);
+            rapidjson::Document document;
+            rapidjson::Value* root = nullptr;
+
+            get_json_impl(root, json_string, path_string, document, res[i], null_map[i]);
+        }
+    }
+
+    template <typename T, std::enable_if_t<std::is_same_v<double, T>, T>* = nullptr>
+    static void handle_result(rapidjson::Value* root, T& res, uint8_t& res_null) {
+        if (root == nullptr || root->IsNull()) {
+            res = 0;
+            res_null = 1;
+        } else if (root->IsInt()) {
+            res = root->GetInt();
+        } else if (root->IsInt64()) {
+            res = root->GetInt64();
+        } else if (root->IsDouble()) {
+            res = root->GetDouble();
+        } else {
+            res_null = 1;
+        }
+    }
+
+    template <typename T, std::enable_if_t<std::is_same_v<int32_t, T>, T>* = nullptr>
+    static void handle_result(rapidjson::Value* root, int32_t& res, uint8_t& res_null) {
+        if (root != nullptr && root->IsInt()) {
+            res = root->GetInt();
+        } else {
+            res_null = 1;
+        }
+    }
+
+    template <typename T, std::enable_if_t<std::is_same_v<int64_t, T>, T>* = nullptr>
+    static void handle_result(rapidjson::Value* root, int64_t& res, uint8_t& res_null) {
+        if (root != nullptr && root->IsInt64()) {
+            res = root->GetInt64();
+        } else {
+            res_null = 1;
+        }
+    }
+};
+
+// Helper Class
+struct JsonNumberTypeDouble {
+    using T = Float64;
+    using ReturnType = DataTypeFloat64;
+    using ColumnType = ColumnVector<T>;
+};
+
+struct JsonNumberTypeInt {
+    using T = int32_t;
+    using ReturnType = DataTypeInt32;
+    using ColumnType = ColumnVector<T>;
+};
+
+struct JsonNumberTypeBigInt {
+    using T = int64_t;
+    using ReturnType = DataTypeInt64;
+    using ColumnType = ColumnVector<T>;
+};
+
+struct GetJsonDouble : public GetJsonNumberType<JsonNumberTypeDouble> {
+    static constexpr auto name = "get_json_double";
+    using ReturnType = typename JsonNumberTypeDouble::ReturnType;
+    using ColumnType = typename JsonNumberTypeDouble::ColumnType;
+};
+
+struct GetJsonInt : public GetJsonNumberType<JsonNumberTypeInt> {
+    static constexpr auto name = "get_json_int";
+    using ReturnType = typename JsonNumberTypeInt::ReturnType;
+    using ColumnType = typename JsonNumberTypeInt::ColumnType;
+};
+
+struct GetJsonBigInt : public GetJsonNumberType<JsonNumberTypeBigInt> {
+    static constexpr auto name = "get_json_bigint";
+    using ReturnType = typename JsonNumberTypeBigInt::ReturnType;
+    using ColumnType = typename JsonNumberTypeBigInt::ColumnType;
+};
+
+struct GetJsonString {
+    static constexpr auto name = "get_json_string";
+    using ReturnType = DataTypeString;
+    using ColumnType = ColumnString;
+    using Chars = ColumnString::Chars;
+    using Offsets = ColumnString::Offsets;
+    static void vector_vector(FunctionContext* context, const Chars& ldata, const Offsets& loffsets,
+                              const Chars& rdata, const Offsets& roffsets, Chars& res_data,
+                              Offsets& res_offsets, NullMap& null_map) {
+        size_t input_rows_count = loffsets.size();
+        res_offsets.resize(input_rows_count);
+
+        for (size_t i = 0; i < input_rows_count; ++i) {
+            if (null_map[i]) {
+                StringOP::push_null_string(i, res_data, res_offsets, null_map);
+                continue;
+            }
+            int l_size = loffsets[i] - loffsets[i - 1];
+            const auto l_raw = reinterpret_cast<const char*>(&ldata[loffsets[i - 1]]);
+            int r_size = roffsets[i] - roffsets[i - 1];
+            const auto r_raw = reinterpret_cast<const char*>(&rdata[roffsets[i - 1]]);
+
+            std::string_view json_string(l_raw, l_size);
+            std::string_view path_string(r_raw, r_size);
+
+            execute_impl(json_string, path_string, res_data, res_offsets, null_map, i);
+        }
+    }
+    static void vector_scalar(FunctionContext* context, const Chars& ldata, const Offsets& loffsets,
+                              const StringRef& rdata, Chars& res_data, Offsets& res_offsets,
+                              NullMap& null_map) {
+        size_t input_rows_count = loffsets.size();
+        res_offsets.resize(input_rows_count);
+
+        for (size_t i = 0; i < input_rows_count; ++i) {
+            if (null_map[i]) {
+                StringOP::push_null_string(i, res_data, res_offsets, null_map);
+                continue;
+            }
+            int l_size = loffsets[i] - loffsets[i - 1];
+            const auto l_raw = reinterpret_cast<const char*>(&ldata[loffsets[i - 1]]);
+
+            std::string_view json_string(l_raw, l_size);
+            std::string_view path_string(rdata.data, rdata.size);
+
+            execute_impl(json_string, path_string, res_data, res_offsets, null_map, i);
+        }
+    }
+    static void scalar_vector(FunctionContext* context, const StringRef& ldata, const Chars& rdata,
+                              const Offsets& roffsets, Chars& res_data, Offsets& res_offsets,
+                              NullMap& null_map) {
+        size_t input_rows_count = roffsets.size();
+        res_offsets.resize(input_rows_count);
+
+        for (size_t i = 0; i < input_rows_count; ++i) {
+            if (null_map[i]) {
+                StringOP::push_null_string(i, res_data, res_offsets, null_map);
+                continue;
+            }
+            int r_size = roffsets[i] - roffsets[i - 1];
+            const auto r_raw = reinterpret_cast<const char*>(&rdata[roffsets[i - 1]]);
+
+            std::string_view json_string(ldata.data, ldata.size);
+            std::string_view path_string(r_raw, r_size);
+
+            execute_impl(json_string, path_string, res_data, res_offsets, null_map, i);
+        }
+    }
+
+    static void execute_impl(const std::string_view& json_string,
+                             const std::string_view& path_string, Chars& res_data,
+                             Offsets& res_offsets, NullMap& null_map, size_t index_now) {
+        rapidjson::Document document;
+        rapidjson::Value* root = nullptr;
+
+        root = get_json_object<JSON_FUN_STRING>(json_string, path_string, &document);
+        const int max_string_len = 65535;
+
+        if (root == nullptr || root->IsNull()) {
+            StringOP::push_null_string(index_now, res_data, res_offsets, null_map);
+        } else if (root->IsString()) {
+            const auto ptr = root->GetString();
+            size_t len = strnlen(ptr, max_string_len);
+            StringOP::push_value_string(std::string_view(ptr, len), index_now, res_data,
+                                        res_offsets);
+        } else {
+            rapidjson::StringBuffer buf;
+            rapidjson::Writer<rapidjson::StringBuffer> writer(buf);
+            root->Accept(writer);
+
+            const auto ptr = buf.GetString();
+            size_t len = strnlen(ptr, max_string_len);
+            StringOP::push_value_string(std::string_view(ptr, len), index_now, res_data,
+                                        res_offsets);
+        }
+    }
+};
+
+template <int flag>
+struct JsonParser {
+    //string
+    static void update_value(StringParser::ParseResult& result, rapidjson::Value& value,
+                             StringRef data, rapidjson::Document::AllocatorType& allocator) {
+        value.SetString(data.data, data.size, allocator);
+    }
+};
+
+template <>
+struct JsonParser<'0'> {
+    // null
+    static void update_value(StringParser::ParseResult& result, rapidjson::Value& value,
+                             StringRef data, rapidjson::Document::AllocatorType& allocator) {
+        value.SetNull();
+    }
+};
+
+template <>
+struct JsonParser<'1'> {
+    // bool
+    static void update_value(StringParser::ParseResult& result, rapidjson::Value& value,
+                             StringRef data, rapidjson::Document::AllocatorType& allocator) {
+        DCHECK(data.size == 1 || strncmp(data.data, "true", 4) == 0 ||
+               strncmp(data.data, "false", 5) == 0);
+        value.SetBool((*data.data == '1' || *data.data == 't') ? true : false);
+    }
+};
+
+template <>
+struct JsonParser<'2'> {
+    // int
+    static void update_value(StringParser::ParseResult& result, rapidjson::Value& value,
+                             StringRef data, rapidjson::Document::AllocatorType& allocator) {
+        value.SetInt(StringParser::string_to_int<int32_t>(data.data, data.size, &result));
+    }
+};
+
+template <>
+struct JsonParser<'3'> {
+    // double
+    static void update_value(StringParser::ParseResult& result, rapidjson::Value& value,
+                             StringRef data, rapidjson::Document::AllocatorType& allocator) {
+        value.SetDouble(StringParser::string_to_float<double>(data.data, data.size, &result));
+    }
+};
+
+template <>
+struct JsonParser<'4'> {
+    // time
+    static void update_value(StringParser::ParseResult& result, rapidjson::Value& value,
+                             StringRef data, rapidjson::Document::AllocatorType& allocator) {
+        // remove double quotes, "xxx" -> xxx
+        value.SetString(data.data + 1, data.size - 2, allocator);
+    }
+};
+
+template <>
+struct JsonParser<'5'> {
+    // bigint
+    static void update_value(StringParser::ParseResult& result, rapidjson::Value& value,
+                             StringRef data, rapidjson::Document::AllocatorType& allocator) {
+        value.SetInt64(StringParser::string_to_int<int64_t>(data.data, data.size, &result));
+    }
+};
+
+template <int flag, typename Impl>
+struct ExecuteReducer {
+    template <typename... TArgs>
+    static void run(TArgs&&... args) {
+        Impl::template execute_type<JsonParser<flag>>(std::forward<TArgs>(args)...);
+    }
+};
+
+struct FunctionJsonArrayImpl {
+    static constexpr auto name = "json_array";
+
+    template <int flag>
+    using Reducer = ExecuteReducer<flag, FunctionJsonArrayImpl>;
+
+    static void execute_parse(const std::string& type_flags,
+                              const std::vector<const ColumnString*>& data_columns,
+                              std::vector<rapidjson::Value>& objects,
+                              rapidjson::Document::AllocatorType& allocator,
+                              const std::vector<const ColumnUInt8*>& nullmaps) {
+        for (int i = 0; i < data_columns.size() - 1; i++) {
+            constexpr_int_match<'0', '6', Reducer>::run(type_flags[i], objects, allocator,
+                                                        data_columns[i], nullmaps[i]);
+        }
+    }
+
+    template <typename TypeImpl>
+    static void execute_type(std::vector<rapidjson::Value>& objects,
+                             rapidjson::Document::AllocatorType& allocator,
+                             const ColumnString* data_column, const ColumnUInt8* nullmap) {
+        StringParser::ParseResult result;
+        rapidjson::Value value;
+
+        for (int i = 0; i < objects.size(); i++) {
+            if (nullmap != nullptr && nullmap->get_data()[i]) {
+                JsonParser<'0'>::update_value(result, value, data_column->get_data_at(i),
+                                              allocator);
+            } else {
+                TypeImpl::update_value(result, value, data_column->get_data_at(i), allocator);
+            }
+            objects[i].PushBack(value, allocator);
+        }
+    }
+};
+
+struct FunctionJsonObjectImpl {
+    static constexpr auto name = "json_object";
+
+    template <int flag>
+    using Reducer = ExecuteReducer<flag, FunctionJsonObjectImpl>;
+
+    static void execute_parse(std::string type_flags,
+                              const std::vector<const ColumnString*>& data_columns,
+                              std::vector<rapidjson::Value>& objects,
+                              rapidjson::Document::AllocatorType& allocator,
+                              const std::vector<const ColumnUInt8*>& nullmaps) {
+        for (auto& array_object : objects) {
+            array_object.SetObject();
+        }
+
+        for (int i = 0; i + 1 < data_columns.size() - 1; i += 2) {
+            constexpr_int_match<'0', '6', Reducer>::run(type_flags[i + 1], objects, allocator,
+                                                        data_columns[i], data_columns[i + 1],
+                                                        nullmaps[i + 1]);
+        }
+    }
+
+    template <typename TypeImpl>
+    static void execute_type(std::vector<rapidjson::Value>& objects,
+                             rapidjson::Document::AllocatorType& allocator,
+                             const ColumnString* key_column, const ColumnString* value_column,
+                             const ColumnUInt8* nullmap) {
+        StringParser::ParseResult result;
+        rapidjson::Value key;
+        rapidjson::Value value;
+        for (int i = 0; i < objects.size(); i++) {
+            JsonParser<'6'>::update_value(result, key, key_column->get_data_at(i),
+                                          allocator); // key always is string
+            if (nullmap != nullptr && nullmap->get_data()[i]) {
+                JsonParser<'0'>::update_value(result, value, value_column->get_data_at(i),
+                                              allocator);
+            } else {
+                TypeImpl::update_value(result, value, value_column->get_data_at(i), allocator);
+            }
+            objects[i].AddMember(key, value, allocator);
+        }
+    }
+};
+
+template <typename SpecificImpl>
+class FunctionJsonAlwaysNotNullable : public IFunction {
+public:
+    using IFunction::execute;
+
+    static constexpr auto name = SpecificImpl::name;
+
+    static FunctionPtr create() {
+        return std::make_shared<FunctionJsonAlwaysNotNullable<SpecificImpl>>();
+    }
+
+    bool use_default_implementation_for_nulls() const override { return false; }
+
+    String get_name() const override { return name; }
+
+    size_t get_number_of_arguments() const override { return 0; }

Review Comment:
   warning: function 'get_number_of_arguments' should be marked [[nodiscard]] [modernize-use-nodiscard]
   
   ```suggestion
       [[nodiscard]] size_t get_number_of_arguments() const override { return 0; }
   ```
   



##########
function_json.cpp:
##########
@@ -0,0 +1,1320 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#include <rapidjson/allocators.h>
+#include <rapidjson/document.h>
+#include <rapidjson/encodings.h>
+#include <rapidjson/pointer.h>
+#include <rapidjson/rapidjson.h>
+#include <rapidjson/stringbuffer.h>
+#include <rapidjson/writer.h>
+#include <re2/re2.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <algorithm>
+#include <boost/iterator/iterator_facade.hpp>
+#include <boost/token_functions.hpp>
+#include <boost/tokenizer.hpp>
+#include <memory>
+#include <string>
+#include <string_view>
+#include <type_traits>
+#include <utility>
+#include <vector>
+
+// IWYU pragma: no_include <opentelemetry/common/threadlocal.h>
+#include "common/compiler_util.h" // IWYU pragma: keep
+#include "common/status.h"
+#include "exprs/json_functions.h"
+#ifdef __AVX2__
+#include "util/jsonb_parser_simd.h"
+#else
+#include "util/jsonb_parser.h"
+#endif
+#include "util/string_parser.hpp"
+#include "util/string_util.h"
+#include "vec/aggregate_functions/aggregate_function.h"
+#include "vec/columns/column.h"
+#include "vec/columns/column_nullable.h"
+#include "vec/columns/column_string.h"
+#include "vec/columns/column_vector.h"
+#include "vec/columns/columns_number.h"
+#include "vec/common/assert_cast.h"
+#include "vec/common/string_ref.h"
+#include "vec/core/block.h"
+#include "vec/core/column_numbers.h"
+#include "vec/core/column_with_type_and_name.h"
+#include "vec/core/types.h"
+#include "vec/data_types/data_type.h"
+#include "vec/data_types/data_type_nullable.h"
+#include "vec/data_types/data_type_number.h"
+#include "vec/data_types/data_type_string.h"
+#include "vec/functions/function.h"
+#include "vec/functions/function_string.h"
+#include "vec/functions/function_totype.h"
+#include "vec/functions/simple_function_factory.h"
+#include "vec/utils/template_helpers.hpp"
+
+namespace doris {
+class FunctionContext;
+} // namespace doris
+
+namespace doris::vectorized {
+static const re2::RE2 JSON_PATTERN("^([^\\\"\\[\\]]*)(?:\\[([0-9]+|\\*)\\])?");
+
+template <typename T, typename U>
+void char_split(std::vector<T>& res, const U& var, char p) {
+    int start = 0;
+    int pos = start;
+    int end = var.length();
+    while (pos < end) {
+        while (var[pos] != p && pos < end) {
+            pos++;
+        }
+        res.emplace_back(&var[start], pos - start);
+        pos++;
+        start = pos;
+    }
+}
+
+// T = std::vector<std::string>
+// TODO: update RE2 to support std::vector<std::string_view>
+template <typename T>
+void get_parsed_paths(const T& path_exprs, std::vector<JsonPath>* parsed_paths) {
+    if (path_exprs.empty()) {
+        return;
+    }
+
+    if (path_exprs[0] != "$") {
+        parsed_paths->emplace_back("", -1, false);
+    } else {
+        parsed_paths->emplace_back("$", -1, true);
+    }
+
+    for (int i = 1; i < path_exprs.size(); i++) {
+        std::string col;
+        std::string index;
+        if (UNLIKELY(!RE2::FullMatch(path_exprs[i], JSON_PATTERN, &col, &index))) {
+            parsed_paths->emplace_back("", -1, false);
+        } else {
+            int idx = -1;
+            if (!index.empty()) {
+                if (index == "*") {
+                    idx = -2;
+                } else {
+                    idx = atoi(index.c_str());
+                }
+            }
+            parsed_paths->emplace_back(col, idx, true);
+        }
+    }
+}
+
+rapidjson::Value* match_value(const std::vector<JsonPath>& parsed_paths, rapidjson::Value* document,
+                              rapidjson::Document::AllocatorType& mem_allocator,
+                              bool is_insert_null = false) {
+    rapidjson::Value* root = document;
+    rapidjson::Value* array_obj = nullptr;
+    for (int i = 1; i < parsed_paths.size(); i++) {
+        if (root == nullptr || root->IsNull()) {
+            return nullptr;
+        }
+
+        if (UNLIKELY(!parsed_paths[i].is_valid)) {
+            return nullptr;
+        }
+
+        const std::string& col = parsed_paths[i].key;
+        int index = parsed_paths[i].idx;
+        if (LIKELY(!col.empty())) {
+            if (root->IsArray()) {
+                array_obj = static_cast<rapidjson::Value*>(
+                        mem_allocator.Malloc(sizeof(rapidjson::Value)));
+                array_obj->SetArray();
+                bool is_null = true;
+
+                // if array ,loop the array,find out all Objects,then find the results from the objects
+                for (int j = 0; j < root->Size(); j++) {
+                    rapidjson::Value* json_elem = &((*root)[j]);
+
+                    if (json_elem->IsArray() || json_elem->IsNull()) {
+                        continue;
+                    } else {
+                        if (!json_elem->IsObject()) {
+                            continue;
+                        }
+                        if (!json_elem->HasMember(col.c_str())) {
+                            if (is_insert_null) { // not found item, then insert a null object.
+                                is_null = false;
+                                rapidjson::Value nullObject(rapidjson::kNullType);
+                                array_obj->PushBack(nullObject, mem_allocator);
+                            }
+                            continue;
+                        }
+                        rapidjson::Value* obj = &((*json_elem)[col.c_str()]);
+                        if (obj->IsArray()) {
+                            is_null = false;
+                            for (int k = 0; k < obj->Size(); k++) {
+                                array_obj->PushBack((*obj)[k], mem_allocator);
+                            }
+                        } else if (!obj->IsNull()) {
+                            is_null = false;
+                            array_obj->PushBack(*obj, mem_allocator);
+                        }
+                    }
+                }
+
+                root = is_null ? &(array_obj->SetNull()) : array_obj;
+            } else if (root->IsObject()) {
+                if (!root->HasMember(col.c_str())) {
+                    return nullptr;
+                } else {
+                    root = &((*root)[col.c_str()]);
+                }
+            } else {
+                // root is not a nested type, return NULL
+                return nullptr;
+            }
+        }
+
+        if (UNLIKELY(index != -1)) {
+            // judge the rapidjson:Value, which base the top's result,
+            // if not array return NULL;else get the index value from the array
+            if (root->IsArray()) {
+                if (root->IsNull()) {
+                    return nullptr;
+                } else if (index == -2) {
+                    // [*]
+                    array_obj = static_cast<rapidjson::Value*>(
+                            mem_allocator.Malloc(sizeof(rapidjson::Value)));
+                    array_obj->SetArray();
+
+                    for (int j = 0; j < root->Size(); j++) {
+                        rapidjson::Value v;
+                        v.CopyFrom((*root)[j], mem_allocator);
+                        array_obj->PushBack(v, mem_allocator);
+                    }
+                    root = array_obj;
+                } else if (index >= root->Size()) {
+                    return nullptr;
+                } else {
+                    root = &((*root)[index]);
+                }
+            } else {
+                return nullptr;
+            }
+        }
+    }
+    return root;
+}
+
+template <JsonFunctionType fntype>
+rapidjson::Value* get_json_object(std::string_view json_string, std::string_view path_string,
+                                  rapidjson::Document* document) {
+    std::vector<JsonPath>* parsed_paths;
+    std::vector<JsonPath> tmp_parsed_paths;
+
+#ifdef USE_LIBCPP
+    std::string s(path_string);
+    auto tok = get_json_token(s);
+#else
+    auto tok = get_json_token(path_string);
+#endif
+    std::vector<std::string> paths(tok.begin(), tok.end());
+    get_parsed_paths(paths, &tmp_parsed_paths);
+    if (tmp_parsed_paths.empty()) {
+        return document;
+    }
+
+    parsed_paths = &tmp_parsed_paths;
+
+    if (!(*parsed_paths)[0].is_valid) {
+        return document;
+    }
+
+    if (UNLIKELY((*parsed_paths).size() == 1)) {
+        if (fntype == JSON_FUN_STRING) {
+            document->SetString(json_string.data(), json_string.size(), document->GetAllocator());
+        } else {
+            return document;
+        }
+    }
+
+    document->Parse(json_string.data(), json_string.size());
+    if (UNLIKELY(document->HasParseError())) {
+        // VLOG_CRITICAL << "Error at offset " << document->GetErrorOffset() << ": "
+        //         << GetParseError_En(document->GetParseError());
+        document->SetNull();
+        return document;
+    }
+
+    return match_value(*parsed_paths, document, document->GetAllocator());
+}
+
+template <typename NumberType>
+struct GetJsonNumberType {
+    using ReturnType = typename NumberType::ReturnType;
+    using ColumnType = typename NumberType::ColumnType;
+    using Container = typename ColumnType::Container;
+
+    static void get_json_impl(rapidjson::Value*& root, const std::string_view& json_string,
+                              const std::string_view& path_string, rapidjson::Document& document,
+                              typename NumberType::T& res, UInt8& null_map) {
+        if constexpr (std::is_same_v<double, typename NumberType::T>) {
+            root = get_json_object<JSON_FUN_DOUBLE>(json_string, path_string, &document);
+            handle_result<double>(root, res, null_map);
+        } else if constexpr (std::is_same_v<int32_t, typename NumberType::T>) {
+            root = get_json_object<JSON_FUN_DOUBLE>(json_string, path_string, &document);
+            handle_result<int32_t>(root, res, null_map);
+        } else if constexpr (std::is_same_v<int64_t, typename NumberType::T>) {
+            root = get_json_object<JSON_FUN_DOUBLE>(json_string, path_string, &document);
+            handle_result<int64_t>(root, res, null_map);
+        }
+    }
+    static void vector_vector(FunctionContext* context, const ColumnString::Chars& ldata,
+                              const ColumnString::Offsets& loffsets,
+                              const ColumnString::Chars& rdata,
+                              const ColumnString::Offsets& roffsets, Container& res,
+                              NullMap& null_map) {
+        size_t size = loffsets.size();
+        res.resize(size);
+        for (size_t i = 0; i < size; ++i) {
+            const char* l_raw_str = reinterpret_cast<const char*>(&ldata[loffsets[i - 1]]);
+            int l_str_size = loffsets[i] - loffsets[i - 1];
+            const char* r_raw_str = reinterpret_cast<const char*>(&rdata[roffsets[i - 1]]);
+            int r_str_size = roffsets[i] - roffsets[i - 1];
+            if (null_map[i]) {
+                res[i] = 0;
+                continue;
+            }
+
+            std::string_view json_string(l_raw_str, l_str_size);
+            std::string_view path_string(r_raw_str, r_str_size);
+            rapidjson::Document document;
+            rapidjson::Value* root = nullptr;
+
+            get_json_impl(root, json_string, path_string, document, res[i], null_map[i]);
+        }
+    }
+    static void vector_scalar(FunctionContext* context, const ColumnString::Chars& ldata,
+                              const ColumnString::Offsets& loffsets, const StringRef& rdata,
+                              Container& res, NullMap& null_map) {
+        size_t size = loffsets.size();
+        res.resize(size);
+        std::string_view path_string(rdata.data, rdata.size);
+        for (size_t i = 0; i < size; ++i) {
+            const char* l_raw_str = reinterpret_cast<const char*>(&ldata[loffsets[i - 1]]);
+            int l_str_size = loffsets[i] - loffsets[i - 1];
+            if (null_map[i]) {
+                res[i] = 0;
+                continue;
+            }
+            std::string_view json_string(l_raw_str, l_str_size);
+
+            rapidjson::Document document;
+            rapidjson::Value* root = nullptr;
+
+            get_json_impl(root, json_string, path_string, document, res[i], null_map[i]);
+        }
+    }
+    static void scalar_vector(FunctionContext* context, const StringRef& ldata,
+                              const ColumnString::Chars& rdata,
+                              const ColumnString::Offsets& roffsets, Container& res,
+                              NullMap& null_map) {
+        size_t size = roffsets.size();
+        res.resize(size);
+        std::string_view json_string(ldata.data, ldata.size);
+        for (size_t i = 0; i < size; ++i) {
+            const char* r_raw_str = reinterpret_cast<const char*>(&rdata[roffsets[i - 1]]);
+            int r_str_size = roffsets[i] - roffsets[i - 1];
+            if (null_map[i]) {
+                res[i] = 0;
+                continue;
+            }
+            std::string_view path_string(r_raw_str, r_str_size);
+            rapidjson::Document document;
+            rapidjson::Value* root = nullptr;
+
+            get_json_impl(root, json_string, path_string, document, res[i], null_map[i]);
+        }
+    }
+
+    template <typename T, std::enable_if_t<std::is_same_v<double, T>, T>* = nullptr>
+    static void handle_result(rapidjson::Value* root, T& res, uint8_t& res_null) {
+        if (root == nullptr || root->IsNull()) {
+            res = 0;
+            res_null = 1;
+        } else if (root->IsInt()) {
+            res = root->GetInt();
+        } else if (root->IsInt64()) {
+            res = root->GetInt64();
+        } else if (root->IsDouble()) {
+            res = root->GetDouble();
+        } else {
+            res_null = 1;
+        }
+    }
+
+    template <typename T, std::enable_if_t<std::is_same_v<int32_t, T>, T>* = nullptr>
+    static void handle_result(rapidjson::Value* root, int32_t& res, uint8_t& res_null) {
+        if (root != nullptr && root->IsInt()) {
+            res = root->GetInt();
+        } else {
+            res_null = 1;
+        }
+    }
+
+    template <typename T, std::enable_if_t<std::is_same_v<int64_t, T>, T>* = nullptr>
+    static void handle_result(rapidjson::Value* root, int64_t& res, uint8_t& res_null) {
+        if (root != nullptr && root->IsInt64()) {
+            res = root->GetInt64();
+        } else {
+            res_null = 1;
+        }
+    }
+};
+
+// Helper Class
+struct JsonNumberTypeDouble {
+    using T = Float64;
+    using ReturnType = DataTypeFloat64;
+    using ColumnType = ColumnVector<T>;
+};
+
+struct JsonNumberTypeInt {
+    using T = int32_t;
+    using ReturnType = DataTypeInt32;
+    using ColumnType = ColumnVector<T>;
+};
+
+struct JsonNumberTypeBigInt {
+    using T = int64_t;
+    using ReturnType = DataTypeInt64;
+    using ColumnType = ColumnVector<T>;
+};
+
+struct GetJsonDouble : public GetJsonNumberType<JsonNumberTypeDouble> {
+    static constexpr auto name = "get_json_double";
+    using ReturnType = typename JsonNumberTypeDouble::ReturnType;
+    using ColumnType = typename JsonNumberTypeDouble::ColumnType;
+};
+
+struct GetJsonInt : public GetJsonNumberType<JsonNumberTypeInt> {
+    static constexpr auto name = "get_json_int";
+    using ReturnType = typename JsonNumberTypeInt::ReturnType;
+    using ColumnType = typename JsonNumberTypeInt::ColumnType;
+};
+
+struct GetJsonBigInt : public GetJsonNumberType<JsonNumberTypeBigInt> {
+    static constexpr auto name = "get_json_bigint";
+    using ReturnType = typename JsonNumberTypeBigInt::ReturnType;
+    using ColumnType = typename JsonNumberTypeBigInt::ColumnType;
+};
+
+struct GetJsonString {
+    static constexpr auto name = "get_json_string";
+    using ReturnType = DataTypeString;
+    using ColumnType = ColumnString;
+    using Chars = ColumnString::Chars;
+    using Offsets = ColumnString::Offsets;
+    static void vector_vector(FunctionContext* context, const Chars& ldata, const Offsets& loffsets,
+                              const Chars& rdata, const Offsets& roffsets, Chars& res_data,
+                              Offsets& res_offsets, NullMap& null_map) {
+        size_t input_rows_count = loffsets.size();
+        res_offsets.resize(input_rows_count);
+
+        for (size_t i = 0; i < input_rows_count; ++i) {
+            if (null_map[i]) {
+                StringOP::push_null_string(i, res_data, res_offsets, null_map);
+                continue;
+            }
+            int l_size = loffsets[i] - loffsets[i - 1];
+            const auto l_raw = reinterpret_cast<const char*>(&ldata[loffsets[i - 1]]);
+            int r_size = roffsets[i] - roffsets[i - 1];
+            const auto r_raw = reinterpret_cast<const char*>(&rdata[roffsets[i - 1]]);
+
+            std::string_view json_string(l_raw, l_size);
+            std::string_view path_string(r_raw, r_size);
+
+            execute_impl(json_string, path_string, res_data, res_offsets, null_map, i);
+        }
+    }
+    static void vector_scalar(FunctionContext* context, const Chars& ldata, const Offsets& loffsets,
+                              const StringRef& rdata, Chars& res_data, Offsets& res_offsets,
+                              NullMap& null_map) {
+        size_t input_rows_count = loffsets.size();
+        res_offsets.resize(input_rows_count);
+
+        for (size_t i = 0; i < input_rows_count; ++i) {
+            if (null_map[i]) {
+                StringOP::push_null_string(i, res_data, res_offsets, null_map);
+                continue;
+            }
+            int l_size = loffsets[i] - loffsets[i - 1];
+            const auto l_raw = reinterpret_cast<const char*>(&ldata[loffsets[i - 1]]);
+
+            std::string_view json_string(l_raw, l_size);
+            std::string_view path_string(rdata.data, rdata.size);
+
+            execute_impl(json_string, path_string, res_data, res_offsets, null_map, i);
+        }
+    }
+    static void scalar_vector(FunctionContext* context, const StringRef& ldata, const Chars& rdata,
+                              const Offsets& roffsets, Chars& res_data, Offsets& res_offsets,
+                              NullMap& null_map) {
+        size_t input_rows_count = roffsets.size();
+        res_offsets.resize(input_rows_count);
+
+        for (size_t i = 0; i < input_rows_count; ++i) {
+            if (null_map[i]) {
+                StringOP::push_null_string(i, res_data, res_offsets, null_map);
+                continue;
+            }
+            int r_size = roffsets[i] - roffsets[i - 1];
+            const auto r_raw = reinterpret_cast<const char*>(&rdata[roffsets[i - 1]]);
+
+            std::string_view json_string(ldata.data, ldata.size);
+            std::string_view path_string(r_raw, r_size);
+
+            execute_impl(json_string, path_string, res_data, res_offsets, null_map, i);
+        }
+    }
+
+    static void execute_impl(const std::string_view& json_string,
+                             const std::string_view& path_string, Chars& res_data,
+                             Offsets& res_offsets, NullMap& null_map, size_t index_now) {
+        rapidjson::Document document;
+        rapidjson::Value* root = nullptr;
+
+        root = get_json_object<JSON_FUN_STRING>(json_string, path_string, &document);
+        const int max_string_len = 65535;
+
+        if (root == nullptr || root->IsNull()) {
+            StringOP::push_null_string(index_now, res_data, res_offsets, null_map);
+        } else if (root->IsString()) {
+            const auto ptr = root->GetString();
+            size_t len = strnlen(ptr, max_string_len);
+            StringOP::push_value_string(std::string_view(ptr, len), index_now, res_data,
+                                        res_offsets);
+        } else {
+            rapidjson::StringBuffer buf;
+            rapidjson::Writer<rapidjson::StringBuffer> writer(buf);
+            root->Accept(writer);
+
+            const auto ptr = buf.GetString();
+            size_t len = strnlen(ptr, max_string_len);
+            StringOP::push_value_string(std::string_view(ptr, len), index_now, res_data,
+                                        res_offsets);
+        }
+    }
+};
+
+template <int flag>
+struct JsonParser {
+    //string
+    static void update_value(StringParser::ParseResult& result, rapidjson::Value& value,
+                             StringRef data, rapidjson::Document::AllocatorType& allocator) {
+        value.SetString(data.data, data.size, allocator);
+    }
+};
+
+template <>
+struct JsonParser<'0'> {
+    // null
+    static void update_value(StringParser::ParseResult& result, rapidjson::Value& value,
+                             StringRef data, rapidjson::Document::AllocatorType& allocator) {
+        value.SetNull();
+    }
+};
+
+template <>
+struct JsonParser<'1'> {
+    // bool
+    static void update_value(StringParser::ParseResult& result, rapidjson::Value& value,
+                             StringRef data, rapidjson::Document::AllocatorType& allocator) {
+        DCHECK(data.size == 1 || strncmp(data.data, "true", 4) == 0 ||
+               strncmp(data.data, "false", 5) == 0);
+        value.SetBool((*data.data == '1' || *data.data == 't') ? true : false);
+    }
+};
+
+template <>
+struct JsonParser<'2'> {
+    // int
+    static void update_value(StringParser::ParseResult& result, rapidjson::Value& value,
+                             StringRef data, rapidjson::Document::AllocatorType& allocator) {
+        value.SetInt(StringParser::string_to_int<int32_t>(data.data, data.size, &result));
+    }
+};
+
+template <>
+struct JsonParser<'3'> {
+    // double
+    static void update_value(StringParser::ParseResult& result, rapidjson::Value& value,
+                             StringRef data, rapidjson::Document::AllocatorType& allocator) {
+        value.SetDouble(StringParser::string_to_float<double>(data.data, data.size, &result));
+    }
+};
+
+template <>
+struct JsonParser<'4'> {
+    // time
+    static void update_value(StringParser::ParseResult& result, rapidjson::Value& value,
+                             StringRef data, rapidjson::Document::AllocatorType& allocator) {
+        // remove double quotes, "xxx" -> xxx
+        value.SetString(data.data + 1, data.size - 2, allocator);
+    }
+};
+
+template <>
+struct JsonParser<'5'> {
+    // bigint
+    static void update_value(StringParser::ParseResult& result, rapidjson::Value& value,
+                             StringRef data, rapidjson::Document::AllocatorType& allocator) {
+        value.SetInt64(StringParser::string_to_int<int64_t>(data.data, data.size, &result));
+    }
+};
+
+template <int flag, typename Impl>
+struct ExecuteReducer {
+    template <typename... TArgs>
+    static void run(TArgs&&... args) {
+        Impl::template execute_type<JsonParser<flag>>(std::forward<TArgs>(args)...);
+    }
+};
+
+struct FunctionJsonArrayImpl {
+    static constexpr auto name = "json_array";
+
+    template <int flag>
+    using Reducer = ExecuteReducer<flag, FunctionJsonArrayImpl>;
+
+    static void execute_parse(const std::string& type_flags,
+                              const std::vector<const ColumnString*>& data_columns,
+                              std::vector<rapidjson::Value>& objects,
+                              rapidjson::Document::AllocatorType& allocator,
+                              const std::vector<const ColumnUInt8*>& nullmaps) {
+        for (int i = 0; i < data_columns.size() - 1; i++) {
+            constexpr_int_match<'0', '6', Reducer>::run(type_flags[i], objects, allocator,
+                                                        data_columns[i], nullmaps[i]);
+        }
+    }
+
+    template <typename TypeImpl>
+    static void execute_type(std::vector<rapidjson::Value>& objects,
+                             rapidjson::Document::AllocatorType& allocator,
+                             const ColumnString* data_column, const ColumnUInt8* nullmap) {
+        StringParser::ParseResult result;
+        rapidjson::Value value;
+
+        for (int i = 0; i < objects.size(); i++) {
+            if (nullmap != nullptr && nullmap->get_data()[i]) {
+                JsonParser<'0'>::update_value(result, value, data_column->get_data_at(i),
+                                              allocator);
+            } else {
+                TypeImpl::update_value(result, value, data_column->get_data_at(i), allocator);
+            }
+            objects[i].PushBack(value, allocator);
+        }
+    }
+};
+
+struct FunctionJsonObjectImpl {
+    static constexpr auto name = "json_object";
+
+    template <int flag>
+    using Reducer = ExecuteReducer<flag, FunctionJsonObjectImpl>;
+
+    static void execute_parse(std::string type_flags,
+                              const std::vector<const ColumnString*>& data_columns,
+                              std::vector<rapidjson::Value>& objects,
+                              rapidjson::Document::AllocatorType& allocator,
+                              const std::vector<const ColumnUInt8*>& nullmaps) {
+        for (auto& array_object : objects) {
+            array_object.SetObject();
+        }
+
+        for (int i = 0; i + 1 < data_columns.size() - 1; i += 2) {
+            constexpr_int_match<'0', '6', Reducer>::run(type_flags[i + 1], objects, allocator,
+                                                        data_columns[i], data_columns[i + 1],
+                                                        nullmaps[i + 1]);
+        }
+    }
+
+    template <typename TypeImpl>
+    static void execute_type(std::vector<rapidjson::Value>& objects,
+                             rapidjson::Document::AllocatorType& allocator,
+                             const ColumnString* key_column, const ColumnString* value_column,
+                             const ColumnUInt8* nullmap) {
+        StringParser::ParseResult result;
+        rapidjson::Value key;
+        rapidjson::Value value;
+        for (int i = 0; i < objects.size(); i++) {
+            JsonParser<'6'>::update_value(result, key, key_column->get_data_at(i),
+                                          allocator); // key always is string
+            if (nullmap != nullptr && nullmap->get_data()[i]) {
+                JsonParser<'0'>::update_value(result, value, value_column->get_data_at(i),
+                                              allocator);
+            } else {
+                TypeImpl::update_value(result, value, value_column->get_data_at(i), allocator);
+            }
+            objects[i].AddMember(key, value, allocator);
+        }
+    }
+};
+
+template <typename SpecificImpl>
+class FunctionJsonAlwaysNotNullable : public IFunction {
+public:
+    using IFunction::execute;
+
+    static constexpr auto name = SpecificImpl::name;
+
+    static FunctionPtr create() {
+        return std::make_shared<FunctionJsonAlwaysNotNullable<SpecificImpl>>();
+    }
+
+    bool use_default_implementation_for_nulls() const override { return false; }
+
+    String get_name() const override { return name; }
+
+    size_t get_number_of_arguments() const override { return 0; }
+
+    bool is_variadic() const override { return true; }
+
+    DataTypePtr get_return_type_impl(const DataTypes& arguments) const override {
+        return std::make_shared<DataTypeString>();
+    }
+
+    Status execute_impl(FunctionContext* context, Block& block, const ColumnNumbers& arguments,
+                        size_t result, size_t input_rows_count) override {
+        auto result_column = ColumnString::create();
+
+        std::vector<ColumnPtr> column_ptrs; // prevent converted column destruct
+        std::vector<const ColumnString*> data_columns;
+        std::vector<const ColumnUInt8*> nullmaps;
+        for (int i = 0; i < arguments.size(); i++) {
+            auto column = block.get_by_position(arguments[i]).column;
+            column_ptrs.push_back(column->convert_to_full_column_if_const());
+            const ColumnNullable* col_nullable =
+                    check_and_get_column<ColumnNullable>(column_ptrs.back().get());
+            if (col_nullable) {
+                const ColumnUInt8* col_nullmap = check_and_get_column<ColumnUInt8>(
+                        col_nullable->get_null_map_column_ptr().get());
+                nullmaps.push_back(col_nullmap);
+                const ColumnString* col = check_and_get_column<ColumnString>(
+                        col_nullable->get_nested_column_ptr().get());
+                data_columns.push_back(col);
+            } else {
+                nullmaps.push_back(nullptr);
+                data_columns.push_back(assert_cast<const ColumnString*>(column_ptrs.back().get()));
+            }
+        }
+        execute(data_columns, *assert_cast<ColumnString*>(result_column.get()), input_rows_count,
+                nullmaps);
+        block.get_by_position(result).column = std::move(result_column);
+        return Status::OK();
+    }
+
+    static void execute(const std::vector<const ColumnString*>& data_columns,
+                        ColumnString& result_column, size_t input_rows_count,
+                        const std::vector<const ColumnUInt8*> nullmaps) {
+        std::string type_flags = data_columns.back()->get_data_at(0).to_string();
+
+        rapidjson::Document document;
+        rapidjson::Document::AllocatorType& allocator = document.GetAllocator();
+
+        std::vector<rapidjson::Value> objects;
+        for (int i = 0; i < input_rows_count; i++) {
+            objects.emplace_back(rapidjson::kArrayType);
+        }
+
+        SpecificImpl::execute_parse(type_flags, data_columns, objects, allocator, nullmaps);
+
+        rapidjson::StringBuffer buf;
+        rapidjson::Writer<rapidjson::StringBuffer> writer(buf);
+
+        for (int i = 0; i < input_rows_count; i++) {
+            buf.Clear();
+            writer.Reset(buf);
+            objects[i].Accept(writer);
+            result_column.insert_data(buf.GetString(), buf.GetSize());
+        }
+    }
+};
+
+struct FunctionJsonQuoteImpl {
+    static constexpr auto name = "json_quote";
+
+    static void execute(const std::vector<const ColumnString*>& data_columns,
+                        ColumnString& result_column, size_t input_rows_count) {
+        rapidjson::Document document;
+        rapidjson::Document::AllocatorType& allocator = document.GetAllocator();
+
+        rapidjson::Value value;
+
+        rapidjson::StringBuffer buf;
+        rapidjson::Writer<rapidjson::StringBuffer> writer(buf);
+
+        for (int i = 0; i < input_rows_count; i++) {
+            StringRef data = data_columns[0]->get_data_at(i);
+            value.SetString(data.data, data.size, allocator);
+
+            buf.Clear();
+            value.Accept(writer);
+            result_column.insert_data(buf.GetString(), buf.GetSize());
+        }
+    }
+};
+
+struct FunctionJsonExtractImpl {
+    static constexpr auto name = "json_extract";
+
+    static rapidjson::Value parse_json(const ColumnString* json_col, const ColumnString* path_col,
+                                       rapidjson::Document::AllocatorType& allocator,
+                                       const int row) {
+        rapidjson::Value value;
+        rapidjson::Document document;
+
+        const auto obj = json_col->get_data_at(row);
+        std::string_view json_string(obj.data, obj.size);
+        const auto path = path_col->get_data_at(row);
+        std::string_view path_string(path.data, path.size);
+
+        auto root = get_json_object<JSON_FUN_STRING>(json_string, path_string, &document);
+        if (root != nullptr) {
+            value.CopyFrom(*root, allocator);
+        }
+        return value;
+    }
+
+    static void execute(const std::vector<const ColumnString*>& data_columns,
+                        ColumnString& result_column, size_t input_rows_count) {
+        rapidjson::Document document;
+        rapidjson::Document::AllocatorType& allocator = document.GetAllocator();
+        rapidjson::StringBuffer buf;
+        rapidjson::Writer<rapidjson::StringBuffer> writer(buf);
+
+        const auto json_col = data_columns[0];
+        for (size_t row = 0; row < input_rows_count; row++) {
+            rapidjson::Value value;
+            if (data_columns.size() == 2) {
+                value = parse_json(json_col, data_columns[1], allocator, row);
+            } else {
+                value.SetArray();
+                value.Reserve(data_columns.size() - 1, allocator);
+                for (size_t col = 1; col < data_columns.size(); ++col) {
+                    value.PushBack(parse_json(json_col, data_columns[col], allocator, row),
+                                   allocator);
+                }
+            }
+
+            // write value as string
+            buf.Clear();
+            writer.Reset(buf);
+            value.Accept(writer);
+            result_column.insert_data(buf.GetString(), buf.GetSize());
+        }
+    }
+};
+
+template <typename Impl>
+class FunctionJson : public IFunction {
+public:
+    static constexpr auto name = Impl::name;
+
+    static FunctionPtr create() { return std::make_shared<FunctionJson<Impl>>(); }
+
+    String get_name() const override { return name; }
+
+    size_t get_number_of_arguments() const override { return 0; }
+
+    bool is_variadic() const override { return true; }
+
+    DataTypePtr get_return_type_impl(const DataTypes& arguments) const override {
+        return std::make_shared<DataTypeString>();
+    }
+
+    Status execute_impl(FunctionContext* context, Block& block, const ColumnNumbers& arguments,
+                        size_t result, size_t input_rows_count) override {
+        auto result_column = ColumnString::create();
+
+        std::vector<ColumnPtr> column_ptrs; // prevent converted column destruct
+        std::vector<const ColumnString*> data_columns;
+        for (int i = 0; i < arguments.size(); i++) {
+            column_ptrs.push_back(
+                    block.get_by_position(arguments[i]).column->convert_to_full_column_if_const());
+            data_columns.push_back(assert_cast<const ColumnString*>(column_ptrs.back().get()));
+        }
+
+        Impl::execute(data_columns, *assert_cast<ColumnString*>(result_column.get()),
+                      input_rows_count);
+        block.get_by_position(result).column = std::move(result_column);
+        return Status::OK();
+    }
+};
+
+using FunctionGetJsonDouble = FunctionBinaryStringOperateToNullType<GetJsonDouble>;
+using FunctionGetJsonInt = FunctionBinaryStringOperateToNullType<GetJsonInt>;
+using FunctionGetJsonBigInt = FunctionBinaryStringOperateToNullType<GetJsonBigInt>;
+using FunctionGetJsonString = FunctionBinaryStringOperateToNullType<GetJsonString>;
+
+class FunctionJsonValid : public IFunction {
+public:
+    static constexpr auto name = "json_valid";
+    static FunctionPtr create() { return std::make_shared<FunctionJsonValid>(); }
+
+    String get_name() const override { return name; }
+
+    size_t get_number_of_arguments() const override { return 1; }

Review Comment:
   warning: function 'get_number_of_arguments' should be marked [[nodiscard]] [modernize-use-nodiscard]
   
   ```suggestion
       [[nodiscard]] size_t get_number_of_arguments() const override { return 1; }
   ```
   



##########
be/src/vec/functions/function_wasm.h:
##########
@@ -0,0 +1,104 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#pragma once
+
+#include <fmt/format.h>

Review Comment:
   warning: 'fmt/format.h' file not found [clang-diagnostic-error]
   ```cpp
   #include <fmt/format.h>
            ^
   ```
   



##########
be/src/runtime/exec_env.h:
##########
@@ -162,6 +163,7 @@ class ExecEnv {
     BrpcClientCache<PFunctionService_Stub>* brpc_function_client_cache() const {
         return _function_client_cache;
     }
+    std::shared_ptr<WasmFunctionManager> wasm_function_manager() const { return _wasm_function_manager; }

Review Comment:
   warning: function 'wasm_function_manager' should be marked [[nodiscard]] [modernize-use-nodiscard]
   
   ```suggestion
       [[nodiscard]] std::shared_ptr<WasmFunctionManager> wasm_function_manager() const { return _wasm_function_manager; }
   ```
   



##########
be/src/vec/functions/function_wasm.h:
##########
@@ -0,0 +1,104 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#pragma once
+
+#include <fmt/format.h>
+#include <stddef.h>
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "common/status.h"
+#include "udf/udf.h"
+#include "util/wasm_manager.h"
+#include "vec/core/block.h"
+#include "vec/core/column_numbers.h"
+#include "vec/core/column_with_type_and_name.h"
+#include "vec/core/columns_with_type_and_name.h"
+#include "vec/core/types.h"
+#include "vec/data_types/data_type.h"
+#include "vec/functions/function.h"
+
+namespace doris {} // namespace doris
+
+namespace doris::vectorized {
+
+class WasmFnImpl {
+public:
+    WasmFnImpl(const TFunction& fn, const DataTypes& argument_types,
+               const DataTypePtr& return_type);
+    ~WasmFnImpl() = default;
+    Status vec_call(FunctionContext* context, vectorized::Block& block,
+                    const std::vector<size_t>& arguments, size_t result, size_t input_rows_count);
+    bool available() { return _manager != nullptr; }
+
+private:
+    std::shared_ptr<WasmFunctionManager> _manager;
+    std::string _function_name;
+    std::string _signature;
+    TFunction _fn;
+    DataTypes _defined_argument_types;
+    DataTypePtr _return_type;
+};
+
+class FunctionWasm : public IFunctionBase {
+public:
+    FunctionWasm(const TFunction& fn, const DataTypes& argument_types,
+                 const DataTypePtr& return_type);
+
+    static FunctionBasePtr create(const TFunction& fn, const ColumnsWithTypeAndName& argument_types,
+                                  const DataTypePtr& return_type) {
+        DataTypes data_types(argument_types.size());
+        for (size_t i = 0; i < argument_types.size(); ++i) {
+            data_types[i] = argument_types[i].type;
+        }
+        return std::make_shared<FunctionWasm>(fn, data_types, return_type);
+    }
+
+    /// Get the main function name.
+    String get_name() const override {
+        return fmt::format("{}: [{}/{}]", _tfn.name.function_name, _tfn.hdfs_location,
+                           _tfn.scalar_fn.symbol);
+    }
+
+    const DataTypes& get_argument_types() const override { return _argument_types; }
+    const DataTypePtr& get_return_type() const override { return _return_type; }
+
+    PreparedFunctionPtr prepare(FunctionContext* context, const Block& sample_block,
+                                const ColumnNumbers& arguments, size_t result) const override {
+        return nullptr;
+    }
+
+    Status open(FunctionContext* context, FunctionContext::FunctionStateScope scope) override;
+
+    Status execute(FunctionContext* context, Block& block, const ColumnNumbers& arguments,
+                   size_t result, size_t input_rows_count, bool dry_run = false) override;
+
+    bool is_deterministic() const override { return false; }

Review Comment:
   warning: function 'is_deterministic' should be marked [[nodiscard]] [modernize-use-nodiscard]
   
   ```suggestion
       [[nodiscard]] bool is_deterministic() const override { return false; }
   ```
   



##########
be/src/util/wasm_manager.h:
##########
@@ -0,0 +1,66 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#pragma once
+
+#include <cassert>
+#include <fstream>
+#include <iostream>
+#include <limits>
+#include <sstream>
+#include <string>
+#include <unordered_map>
+#include <vector>
+#include <wasmtime.hh>

Review Comment:
   warning: 'wasmtime.hh' file not found [clang-diagnostic-error]
   ```cpp
   #include <wasmtime.hh>
            ^
   ```
   



##########
be/src/vec/functions/function_wasm.h:
##########
@@ -0,0 +1,104 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#pragma once
+
+#include <fmt/format.h>
+#include <stddef.h>
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "common/status.h"
+#include "udf/udf.h"
+#include "util/wasm_manager.h"
+#include "vec/core/block.h"
+#include "vec/core/column_numbers.h"
+#include "vec/core/column_with_type_and_name.h"
+#include "vec/core/columns_with_type_and_name.h"
+#include "vec/core/types.h"
+#include "vec/data_types/data_type.h"
+#include "vec/functions/function.h"
+
+namespace doris {} // namespace doris
+
+namespace doris::vectorized {
+
+class WasmFnImpl {
+public:
+    WasmFnImpl(const TFunction& fn, const DataTypes& argument_types,
+               const DataTypePtr& return_type);
+    ~WasmFnImpl() = default;
+    Status vec_call(FunctionContext* context, vectorized::Block& block,
+                    const std::vector<size_t>& arguments, size_t result, size_t input_rows_count);
+    bool available() { return _manager != nullptr; }
+
+private:
+    std::shared_ptr<WasmFunctionManager> _manager;
+    std::string _function_name;
+    std::string _signature;
+    TFunction _fn;
+    DataTypes _defined_argument_types;
+    DataTypePtr _return_type;
+};
+
+class FunctionWasm : public IFunctionBase {
+public:
+    FunctionWasm(const TFunction& fn, const DataTypes& argument_types,
+                 const DataTypePtr& return_type);
+
+    static FunctionBasePtr create(const TFunction& fn, const ColumnsWithTypeAndName& argument_types,
+                                  const DataTypePtr& return_type) {
+        DataTypes data_types(argument_types.size());
+        for (size_t i = 0; i < argument_types.size(); ++i) {
+            data_types[i] = argument_types[i].type;
+        }
+        return std::make_shared<FunctionWasm>(fn, data_types, return_type);
+    }
+
+    /// Get the main function name.
+    String get_name() const override {
+        return fmt::format("{}: [{}/{}]", _tfn.name.function_name, _tfn.hdfs_location,
+                           _tfn.scalar_fn.symbol);
+    }
+
+    const DataTypes& get_argument_types() const override { return _argument_types; }

Review Comment:
   warning: function 'get_argument_types' should be marked [[nodiscard]] [modernize-use-nodiscard]
   
   ```suggestion
       [[nodiscard]] const DataTypes& get_argument_types() const override { return _argument_types; }
   ```
   



##########
be/src/util/wasm_manager.cpp:
##########
@@ -0,0 +1,97 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#include "util/wasm_manager.h"
+namespace doris {
+
+WasmFunctionManager::WasmFunctionManager() {

Review Comment:
   warning: use '= default' to define a trivial default constructor [modernize-use-equals-default]
   ```cpp
   WasmFunctionManager::WasmFunctionManager() {
                        ^
   ```
   



##########
be/src/vec/functions/function_wasm.h:
##########
@@ -0,0 +1,104 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#pragma once
+
+#include <fmt/format.h>
+#include <stddef.h>
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "common/status.h"
+#include "udf/udf.h"
+#include "util/wasm_manager.h"
+#include "vec/core/block.h"
+#include "vec/core/column_numbers.h"
+#include "vec/core/column_with_type_and_name.h"
+#include "vec/core/columns_with_type_and_name.h"
+#include "vec/core/types.h"
+#include "vec/data_types/data_type.h"
+#include "vec/functions/function.h"
+
+namespace doris {} // namespace doris
+
+namespace doris::vectorized {
+
+class WasmFnImpl {
+public:
+    WasmFnImpl(const TFunction& fn, const DataTypes& argument_types,
+               const DataTypePtr& return_type);
+    ~WasmFnImpl() = default;
+    Status vec_call(FunctionContext* context, vectorized::Block& block,
+                    const std::vector<size_t>& arguments, size_t result, size_t input_rows_count);
+    bool available() { return _manager != nullptr; }
+
+private:
+    std::shared_ptr<WasmFunctionManager> _manager;
+    std::string _function_name;
+    std::string _signature;
+    TFunction _fn;
+    DataTypes _defined_argument_types;
+    DataTypePtr _return_type;
+};
+
+class FunctionWasm : public IFunctionBase {
+public:
+    FunctionWasm(const TFunction& fn, const DataTypes& argument_types,
+                 const DataTypePtr& return_type);
+
+    static FunctionBasePtr create(const TFunction& fn, const ColumnsWithTypeAndName& argument_types,
+                                  const DataTypePtr& return_type) {
+        DataTypes data_types(argument_types.size());
+        for (size_t i = 0; i < argument_types.size(); ++i) {
+            data_types[i] = argument_types[i].type;
+        }
+        return std::make_shared<FunctionWasm>(fn, data_types, return_type);
+    }
+
+    /// Get the main function name.
+    String get_name() const override {

Review Comment:
   warning: function 'get_name' should be marked [[nodiscard]] [modernize-use-nodiscard]
   
   ```suggestion
       [[nodiscard]] String get_name() const override {
   ```
   



##########
be/src/vec/functions/function_wasm.h:
##########
@@ -0,0 +1,104 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#pragma once
+
+#include <fmt/format.h>
+#include <stddef.h>
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "common/status.h"
+#include "udf/udf.h"
+#include "util/wasm_manager.h"
+#include "vec/core/block.h"
+#include "vec/core/column_numbers.h"
+#include "vec/core/column_with_type_and_name.h"
+#include "vec/core/columns_with_type_and_name.h"
+#include "vec/core/types.h"
+#include "vec/data_types/data_type.h"
+#include "vec/functions/function.h"
+
+namespace doris {} // namespace doris
+
+namespace doris::vectorized {
+
+class WasmFnImpl {
+public:
+    WasmFnImpl(const TFunction& fn, const DataTypes& argument_types,
+               const DataTypePtr& return_type);
+    ~WasmFnImpl() = default;
+    Status vec_call(FunctionContext* context, vectorized::Block& block,
+                    const std::vector<size_t>& arguments, size_t result, size_t input_rows_count);
+    bool available() { return _manager != nullptr; }
+
+private:
+    std::shared_ptr<WasmFunctionManager> _manager;
+    std::string _function_name;
+    std::string _signature;
+    TFunction _fn;
+    DataTypes _defined_argument_types;
+    DataTypePtr _return_type;
+};
+
+class FunctionWasm : public IFunctionBase {
+public:
+    FunctionWasm(const TFunction& fn, const DataTypes& argument_types,
+                 const DataTypePtr& return_type);
+
+    static FunctionBasePtr create(const TFunction& fn, const ColumnsWithTypeAndName& argument_types,
+                                  const DataTypePtr& return_type) {
+        DataTypes data_types(argument_types.size());
+        for (size_t i = 0; i < argument_types.size(); ++i) {
+            data_types[i] = argument_types[i].type;
+        }
+        return std::make_shared<FunctionWasm>(fn, data_types, return_type);
+    }
+
+    /// Get the main function name.
+    String get_name() const override {
+        return fmt::format("{}: [{}/{}]", _tfn.name.function_name, _tfn.hdfs_location,
+                           _tfn.scalar_fn.symbol);
+    }
+
+    const DataTypes& get_argument_types() const override { return _argument_types; }
+    const DataTypePtr& get_return_type() const override { return _return_type; }
+
+    PreparedFunctionPtr prepare(FunctionContext* context, const Block& sample_block,
+                                const ColumnNumbers& arguments, size_t result) const override {
+        return nullptr;
+    }
+
+    Status open(FunctionContext* context, FunctionContext::FunctionStateScope scope) override;
+
+    Status execute(FunctionContext* context, Block& block, const ColumnNumbers& arguments,
+                   size_t result, size_t input_rows_count, bool dry_run = false) override;
+
+    bool is_deterministic() const override { return false; }
+
+    bool is_deterministic_in_scope_of_query() const override { return false; }

Review Comment:
   warning: function 'is_deterministic_in_scope_of_query' should be marked [[nodiscard]] [modernize-use-nodiscard]
   
   ```suggestion
       [[nodiscard]] bool is_deterministic_in_scope_of_query() const override { return false; }
   ```
   



##########
be/src/vec/functions/function_wasm.h:
##########
@@ -0,0 +1,104 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#pragma once
+
+#include <fmt/format.h>
+#include <stddef.h>
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "common/status.h"
+#include "udf/udf.h"
+#include "util/wasm_manager.h"
+#include "vec/core/block.h"
+#include "vec/core/column_numbers.h"
+#include "vec/core/column_with_type_and_name.h"
+#include "vec/core/columns_with_type_and_name.h"
+#include "vec/core/types.h"
+#include "vec/data_types/data_type.h"
+#include "vec/functions/function.h"
+
+namespace doris {} // namespace doris
+
+namespace doris::vectorized {
+
+class WasmFnImpl {
+public:
+    WasmFnImpl(const TFunction& fn, const DataTypes& argument_types,
+               const DataTypePtr& return_type);
+    ~WasmFnImpl() = default;
+    Status vec_call(FunctionContext* context, vectorized::Block& block,
+                    const std::vector<size_t>& arguments, size_t result, size_t input_rows_count);
+    bool available() { return _manager != nullptr; }
+
+private:
+    std::shared_ptr<WasmFunctionManager> _manager;
+    std::string _function_name;
+    std::string _signature;
+    TFunction _fn;
+    DataTypes _defined_argument_types;
+    DataTypePtr _return_type;
+};
+
+class FunctionWasm : public IFunctionBase {
+public:
+    FunctionWasm(const TFunction& fn, const DataTypes& argument_types,
+                 const DataTypePtr& return_type);
+
+    static FunctionBasePtr create(const TFunction& fn, const ColumnsWithTypeAndName& argument_types,
+                                  const DataTypePtr& return_type) {
+        DataTypes data_types(argument_types.size());
+        for (size_t i = 0; i < argument_types.size(); ++i) {
+            data_types[i] = argument_types[i].type;
+        }
+        return std::make_shared<FunctionWasm>(fn, data_types, return_type);
+    }
+
+    /// Get the main function name.
+    String get_name() const override {
+        return fmt::format("{}: [{}/{}]", _tfn.name.function_name, _tfn.hdfs_location,
+                           _tfn.scalar_fn.symbol);
+    }
+
+    const DataTypes& get_argument_types() const override { return _argument_types; }
+    const DataTypePtr& get_return_type() const override { return _return_type; }
+
+    PreparedFunctionPtr prepare(FunctionContext* context, const Block& sample_block,
+                                const ColumnNumbers& arguments, size_t result) const override {
+        return nullptr;
+    }
+
+    Status open(FunctionContext* context, FunctionContext::FunctionStateScope scope) override;
+
+    Status execute(FunctionContext* context, Block& block, const ColumnNumbers& arguments,
+                   size_t result, size_t input_rows_count, bool dry_run = false) override;
+
+    bool is_deterministic() const override { return false; }
+
+    bool is_deterministic_in_scope_of_query() const override { return false; }
+
+    bool is_use_default_implementation_for_constants() const override { return true; }

Review Comment:
   warning: function 'is_use_default_implementation_for_constants' should be marked [[nodiscard]] [modernize-use-nodiscard]
   
   ```suggestion
       [[nodiscard]] bool is_use_default_implementation_for_constants() const override { return true; }
   ```
   



##########
function_json.cpp:
##########
@@ -0,0 +1,1320 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#include <rapidjson/allocators.h>

Review Comment:
   warning: 'rapidjson/allocators.h' file not found [clang-diagnostic-error]
   ```cpp
   #include <rapidjson/allocators.h>
            ^
   ```
   



##########
function_json.cpp:
##########
@@ -0,0 +1,1320 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#include <rapidjson/allocators.h>
+#include <rapidjson/document.h>
+#include <rapidjson/encodings.h>
+#include <rapidjson/pointer.h>
+#include <rapidjson/rapidjson.h>
+#include <rapidjson/stringbuffer.h>
+#include <rapidjson/writer.h>
+#include <re2/re2.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <algorithm>
+#include <boost/iterator/iterator_facade.hpp>
+#include <boost/token_functions.hpp>
+#include <boost/tokenizer.hpp>
+#include <memory>
+#include <string>
+#include <string_view>
+#include <type_traits>
+#include <utility>
+#include <vector>
+
+// IWYU pragma: no_include <opentelemetry/common/threadlocal.h>
+#include "common/compiler_util.h" // IWYU pragma: keep
+#include "common/status.h"
+#include "exprs/json_functions.h"
+#ifdef __AVX2__
+#include "util/jsonb_parser_simd.h"
+#else
+#include "util/jsonb_parser.h"
+#endif
+#include "util/string_parser.hpp"
+#include "util/string_util.h"
+#include "vec/aggregate_functions/aggregate_function.h"
+#include "vec/columns/column.h"
+#include "vec/columns/column_nullable.h"
+#include "vec/columns/column_string.h"
+#include "vec/columns/column_vector.h"
+#include "vec/columns/columns_number.h"
+#include "vec/common/assert_cast.h"
+#include "vec/common/string_ref.h"
+#include "vec/core/block.h"
+#include "vec/core/column_numbers.h"
+#include "vec/core/column_with_type_and_name.h"
+#include "vec/core/types.h"
+#include "vec/data_types/data_type.h"
+#include "vec/data_types/data_type_nullable.h"
+#include "vec/data_types/data_type_number.h"
+#include "vec/data_types/data_type_string.h"
+#include "vec/functions/function.h"
+#include "vec/functions/function_string.h"
+#include "vec/functions/function_totype.h"
+#include "vec/functions/simple_function_factory.h"
+#include "vec/utils/template_helpers.hpp"
+
+namespace doris {
+class FunctionContext;
+} // namespace doris
+
+namespace doris::vectorized {
+static const re2::RE2 JSON_PATTERN("^([^\\\"\\[\\]]*)(?:\\[([0-9]+|\\*)\\])?");
+
+template <typename T, typename U>
+void char_split(std::vector<T>& res, const U& var, char p) {
+    int start = 0;
+    int pos = start;
+    int end = var.length();
+    while (pos < end) {
+        while (var[pos] != p && pos < end) {
+            pos++;
+        }
+        res.emplace_back(&var[start], pos - start);
+        pos++;
+        start = pos;
+    }
+}
+
+// T = std::vector<std::string>
+// TODO: update RE2 to support std::vector<std::string_view>
+template <typename T>
+void get_parsed_paths(const T& path_exprs, std::vector<JsonPath>* parsed_paths) {
+    if (path_exprs.empty()) {
+        return;
+    }
+
+    if (path_exprs[0] != "$") {
+        parsed_paths->emplace_back("", -1, false);
+    } else {
+        parsed_paths->emplace_back("$", -1, true);
+    }
+
+    for (int i = 1; i < path_exprs.size(); i++) {
+        std::string col;
+        std::string index;
+        if (UNLIKELY(!RE2::FullMatch(path_exprs[i], JSON_PATTERN, &col, &index))) {
+            parsed_paths->emplace_back("", -1, false);
+        } else {
+            int idx = -1;
+            if (!index.empty()) {
+                if (index == "*") {
+                    idx = -2;
+                } else {
+                    idx = atoi(index.c_str());
+                }
+            }
+            parsed_paths->emplace_back(col, idx, true);
+        }
+    }
+}
+
+rapidjson::Value* match_value(const std::vector<JsonPath>& parsed_paths, rapidjson::Value* document,
+                              rapidjson::Document::AllocatorType& mem_allocator,
+                              bool is_insert_null = false) {
+    rapidjson::Value* root = document;
+    rapidjson::Value* array_obj = nullptr;
+    for (int i = 1; i < parsed_paths.size(); i++) {
+        if (root == nullptr || root->IsNull()) {
+            return nullptr;
+        }
+
+        if (UNLIKELY(!parsed_paths[i].is_valid)) {
+            return nullptr;
+        }
+
+        const std::string& col = parsed_paths[i].key;
+        int index = parsed_paths[i].idx;
+        if (LIKELY(!col.empty())) {
+            if (root->IsArray()) {
+                array_obj = static_cast<rapidjson::Value*>(
+                        mem_allocator.Malloc(sizeof(rapidjson::Value)));
+                array_obj->SetArray();
+                bool is_null = true;
+
+                // if array ,loop the array,find out all Objects,then find the results from the objects
+                for (int j = 0; j < root->Size(); j++) {
+                    rapidjson::Value* json_elem = &((*root)[j]);
+
+                    if (json_elem->IsArray() || json_elem->IsNull()) {
+                        continue;
+                    } else {
+                        if (!json_elem->IsObject()) {
+                            continue;
+                        }
+                        if (!json_elem->HasMember(col.c_str())) {
+                            if (is_insert_null) { // not found item, then insert a null object.
+                                is_null = false;
+                                rapidjson::Value nullObject(rapidjson::kNullType);
+                                array_obj->PushBack(nullObject, mem_allocator);
+                            }
+                            continue;
+                        }
+                        rapidjson::Value* obj = &((*json_elem)[col.c_str()]);
+                        if (obj->IsArray()) {
+                            is_null = false;
+                            for (int k = 0; k < obj->Size(); k++) {
+                                array_obj->PushBack((*obj)[k], mem_allocator);
+                            }
+                        } else if (!obj->IsNull()) {
+                            is_null = false;
+                            array_obj->PushBack(*obj, mem_allocator);
+                        }
+                    }
+                }
+
+                root = is_null ? &(array_obj->SetNull()) : array_obj;
+            } else if (root->IsObject()) {
+                if (!root->HasMember(col.c_str())) {
+                    return nullptr;
+                } else {
+                    root = &((*root)[col.c_str()]);
+                }
+            } else {
+                // root is not a nested type, return NULL
+                return nullptr;
+            }
+        }
+
+        if (UNLIKELY(index != -1)) {
+            // judge the rapidjson:Value, which base the top's result,
+            // if not array return NULL;else get the index value from the array
+            if (root->IsArray()) {
+                if (root->IsNull()) {
+                    return nullptr;
+                } else if (index == -2) {
+                    // [*]
+                    array_obj = static_cast<rapidjson::Value*>(
+                            mem_allocator.Malloc(sizeof(rapidjson::Value)));
+                    array_obj->SetArray();
+
+                    for (int j = 0; j < root->Size(); j++) {
+                        rapidjson::Value v;
+                        v.CopyFrom((*root)[j], mem_allocator);
+                        array_obj->PushBack(v, mem_allocator);
+                    }
+                    root = array_obj;
+                } else if (index >= root->Size()) {
+                    return nullptr;
+                } else {
+                    root = &((*root)[index]);
+                }
+            } else {
+                return nullptr;
+            }
+        }
+    }
+    return root;
+}
+
+template <JsonFunctionType fntype>
+rapidjson::Value* get_json_object(std::string_view json_string, std::string_view path_string,
+                                  rapidjson::Document* document) {
+    std::vector<JsonPath>* parsed_paths;
+    std::vector<JsonPath> tmp_parsed_paths;
+
+#ifdef USE_LIBCPP
+    std::string s(path_string);
+    auto tok = get_json_token(s);
+#else
+    auto tok = get_json_token(path_string);
+#endif
+    std::vector<std::string> paths(tok.begin(), tok.end());
+    get_parsed_paths(paths, &tmp_parsed_paths);
+    if (tmp_parsed_paths.empty()) {
+        return document;
+    }
+
+    parsed_paths = &tmp_parsed_paths;
+
+    if (!(*parsed_paths)[0].is_valid) {
+        return document;
+    }
+
+    if (UNLIKELY((*parsed_paths).size() == 1)) {
+        if (fntype == JSON_FUN_STRING) {
+            document->SetString(json_string.data(), json_string.size(), document->GetAllocator());
+        } else {
+            return document;
+        }
+    }
+
+    document->Parse(json_string.data(), json_string.size());
+    if (UNLIKELY(document->HasParseError())) {
+        // VLOG_CRITICAL << "Error at offset " << document->GetErrorOffset() << ": "
+        //         << GetParseError_En(document->GetParseError());
+        document->SetNull();
+        return document;
+    }
+
+    return match_value(*parsed_paths, document, document->GetAllocator());
+}
+
+template <typename NumberType>
+struct GetJsonNumberType {
+    using ReturnType = typename NumberType::ReturnType;
+    using ColumnType = typename NumberType::ColumnType;
+    using Container = typename ColumnType::Container;
+
+    static void get_json_impl(rapidjson::Value*& root, const std::string_view& json_string,
+                              const std::string_view& path_string, rapidjson::Document& document,
+                              typename NumberType::T& res, UInt8& null_map) {
+        if constexpr (std::is_same_v<double, typename NumberType::T>) {
+            root = get_json_object<JSON_FUN_DOUBLE>(json_string, path_string, &document);
+            handle_result<double>(root, res, null_map);
+        } else if constexpr (std::is_same_v<int32_t, typename NumberType::T>) {
+            root = get_json_object<JSON_FUN_DOUBLE>(json_string, path_string, &document);
+            handle_result<int32_t>(root, res, null_map);
+        } else if constexpr (std::is_same_v<int64_t, typename NumberType::T>) {
+            root = get_json_object<JSON_FUN_DOUBLE>(json_string, path_string, &document);
+            handle_result<int64_t>(root, res, null_map);
+        }
+    }
+    static void vector_vector(FunctionContext* context, const ColumnString::Chars& ldata,
+                              const ColumnString::Offsets& loffsets,
+                              const ColumnString::Chars& rdata,
+                              const ColumnString::Offsets& roffsets, Container& res,
+                              NullMap& null_map) {
+        size_t size = loffsets.size();
+        res.resize(size);
+        for (size_t i = 0; i < size; ++i) {
+            const char* l_raw_str = reinterpret_cast<const char*>(&ldata[loffsets[i - 1]]);
+            int l_str_size = loffsets[i] - loffsets[i - 1];
+            const char* r_raw_str = reinterpret_cast<const char*>(&rdata[roffsets[i - 1]]);
+            int r_str_size = roffsets[i] - roffsets[i - 1];
+            if (null_map[i]) {
+                res[i] = 0;
+                continue;
+            }
+
+            std::string_view json_string(l_raw_str, l_str_size);
+            std::string_view path_string(r_raw_str, r_str_size);
+            rapidjson::Document document;
+            rapidjson::Value* root = nullptr;
+
+            get_json_impl(root, json_string, path_string, document, res[i], null_map[i]);
+        }
+    }
+    static void vector_scalar(FunctionContext* context, const ColumnString::Chars& ldata,
+                              const ColumnString::Offsets& loffsets, const StringRef& rdata,
+                              Container& res, NullMap& null_map) {
+        size_t size = loffsets.size();
+        res.resize(size);
+        std::string_view path_string(rdata.data, rdata.size);
+        for (size_t i = 0; i < size; ++i) {
+            const char* l_raw_str = reinterpret_cast<const char*>(&ldata[loffsets[i - 1]]);
+            int l_str_size = loffsets[i] - loffsets[i - 1];
+            if (null_map[i]) {
+                res[i] = 0;
+                continue;
+            }
+            std::string_view json_string(l_raw_str, l_str_size);
+
+            rapidjson::Document document;
+            rapidjson::Value* root = nullptr;
+
+            get_json_impl(root, json_string, path_string, document, res[i], null_map[i]);
+        }
+    }
+    static void scalar_vector(FunctionContext* context, const StringRef& ldata,
+                              const ColumnString::Chars& rdata,
+                              const ColumnString::Offsets& roffsets, Container& res,
+                              NullMap& null_map) {
+        size_t size = roffsets.size();
+        res.resize(size);
+        std::string_view json_string(ldata.data, ldata.size);
+        for (size_t i = 0; i < size; ++i) {
+            const char* r_raw_str = reinterpret_cast<const char*>(&rdata[roffsets[i - 1]]);
+            int r_str_size = roffsets[i] - roffsets[i - 1];
+            if (null_map[i]) {
+                res[i] = 0;
+                continue;
+            }
+            std::string_view path_string(r_raw_str, r_str_size);
+            rapidjson::Document document;
+            rapidjson::Value* root = nullptr;
+
+            get_json_impl(root, json_string, path_string, document, res[i], null_map[i]);
+        }
+    }
+
+    template <typename T, std::enable_if_t<std::is_same_v<double, T>, T>* = nullptr>
+    static void handle_result(rapidjson::Value* root, T& res, uint8_t& res_null) {
+        if (root == nullptr || root->IsNull()) {
+            res = 0;
+            res_null = 1;
+        } else if (root->IsInt()) {
+            res = root->GetInt();
+        } else if (root->IsInt64()) {
+            res = root->GetInt64();
+        } else if (root->IsDouble()) {
+            res = root->GetDouble();
+        } else {
+            res_null = 1;
+        }
+    }
+
+    template <typename T, std::enable_if_t<std::is_same_v<int32_t, T>, T>* = nullptr>
+    static void handle_result(rapidjson::Value* root, int32_t& res, uint8_t& res_null) {
+        if (root != nullptr && root->IsInt()) {
+            res = root->GetInt();
+        } else {
+            res_null = 1;
+        }
+    }
+
+    template <typename T, std::enable_if_t<std::is_same_v<int64_t, T>, T>* = nullptr>
+    static void handle_result(rapidjson::Value* root, int64_t& res, uint8_t& res_null) {
+        if (root != nullptr && root->IsInt64()) {
+            res = root->GetInt64();
+        } else {
+            res_null = 1;
+        }
+    }
+};
+
+// Helper Class
+struct JsonNumberTypeDouble {
+    using T = Float64;
+    using ReturnType = DataTypeFloat64;
+    using ColumnType = ColumnVector<T>;
+};
+
+struct JsonNumberTypeInt {
+    using T = int32_t;
+    using ReturnType = DataTypeInt32;
+    using ColumnType = ColumnVector<T>;
+};
+
+struct JsonNumberTypeBigInt {
+    using T = int64_t;
+    using ReturnType = DataTypeInt64;
+    using ColumnType = ColumnVector<T>;
+};
+
+struct GetJsonDouble : public GetJsonNumberType<JsonNumberTypeDouble> {
+    static constexpr auto name = "get_json_double";
+    using ReturnType = typename JsonNumberTypeDouble::ReturnType;
+    using ColumnType = typename JsonNumberTypeDouble::ColumnType;
+};
+
+struct GetJsonInt : public GetJsonNumberType<JsonNumberTypeInt> {
+    static constexpr auto name = "get_json_int";
+    using ReturnType = typename JsonNumberTypeInt::ReturnType;
+    using ColumnType = typename JsonNumberTypeInt::ColumnType;
+};
+
+struct GetJsonBigInt : public GetJsonNumberType<JsonNumberTypeBigInt> {
+    static constexpr auto name = "get_json_bigint";
+    using ReturnType = typename JsonNumberTypeBigInt::ReturnType;
+    using ColumnType = typename JsonNumberTypeBigInt::ColumnType;
+};
+
+struct GetJsonString {
+    static constexpr auto name = "get_json_string";
+    using ReturnType = DataTypeString;
+    using ColumnType = ColumnString;
+    using Chars = ColumnString::Chars;
+    using Offsets = ColumnString::Offsets;
+    static void vector_vector(FunctionContext* context, const Chars& ldata, const Offsets& loffsets,
+                              const Chars& rdata, const Offsets& roffsets, Chars& res_data,
+                              Offsets& res_offsets, NullMap& null_map) {
+        size_t input_rows_count = loffsets.size();
+        res_offsets.resize(input_rows_count);
+
+        for (size_t i = 0; i < input_rows_count; ++i) {
+            if (null_map[i]) {
+                StringOP::push_null_string(i, res_data, res_offsets, null_map);
+                continue;
+            }
+            int l_size = loffsets[i] - loffsets[i - 1];
+            const auto l_raw = reinterpret_cast<const char*>(&ldata[loffsets[i - 1]]);
+            int r_size = roffsets[i] - roffsets[i - 1];
+            const auto r_raw = reinterpret_cast<const char*>(&rdata[roffsets[i - 1]]);
+
+            std::string_view json_string(l_raw, l_size);
+            std::string_view path_string(r_raw, r_size);
+
+            execute_impl(json_string, path_string, res_data, res_offsets, null_map, i);
+        }
+    }
+    static void vector_scalar(FunctionContext* context, const Chars& ldata, const Offsets& loffsets,
+                              const StringRef& rdata, Chars& res_data, Offsets& res_offsets,
+                              NullMap& null_map) {
+        size_t input_rows_count = loffsets.size();
+        res_offsets.resize(input_rows_count);
+
+        for (size_t i = 0; i < input_rows_count; ++i) {
+            if (null_map[i]) {
+                StringOP::push_null_string(i, res_data, res_offsets, null_map);
+                continue;
+            }
+            int l_size = loffsets[i] - loffsets[i - 1];
+            const auto l_raw = reinterpret_cast<const char*>(&ldata[loffsets[i - 1]]);
+
+            std::string_view json_string(l_raw, l_size);
+            std::string_view path_string(rdata.data, rdata.size);
+
+            execute_impl(json_string, path_string, res_data, res_offsets, null_map, i);
+        }
+    }
+    static void scalar_vector(FunctionContext* context, const StringRef& ldata, const Chars& rdata,
+                              const Offsets& roffsets, Chars& res_data, Offsets& res_offsets,
+                              NullMap& null_map) {
+        size_t input_rows_count = roffsets.size();
+        res_offsets.resize(input_rows_count);
+
+        for (size_t i = 0; i < input_rows_count; ++i) {
+            if (null_map[i]) {
+                StringOP::push_null_string(i, res_data, res_offsets, null_map);
+                continue;
+            }
+            int r_size = roffsets[i] - roffsets[i - 1];
+            const auto r_raw = reinterpret_cast<const char*>(&rdata[roffsets[i - 1]]);
+
+            std::string_view json_string(ldata.data, ldata.size);
+            std::string_view path_string(r_raw, r_size);
+
+            execute_impl(json_string, path_string, res_data, res_offsets, null_map, i);
+        }
+    }
+
+    static void execute_impl(const std::string_view& json_string,
+                             const std::string_view& path_string, Chars& res_data,
+                             Offsets& res_offsets, NullMap& null_map, size_t index_now) {
+        rapidjson::Document document;
+        rapidjson::Value* root = nullptr;
+
+        root = get_json_object<JSON_FUN_STRING>(json_string, path_string, &document);
+        const int max_string_len = 65535;
+
+        if (root == nullptr || root->IsNull()) {
+            StringOP::push_null_string(index_now, res_data, res_offsets, null_map);
+        } else if (root->IsString()) {
+            const auto ptr = root->GetString();
+            size_t len = strnlen(ptr, max_string_len);
+            StringOP::push_value_string(std::string_view(ptr, len), index_now, res_data,
+                                        res_offsets);
+        } else {
+            rapidjson::StringBuffer buf;
+            rapidjson::Writer<rapidjson::StringBuffer> writer(buf);
+            root->Accept(writer);
+
+            const auto ptr = buf.GetString();
+            size_t len = strnlen(ptr, max_string_len);
+            StringOP::push_value_string(std::string_view(ptr, len), index_now, res_data,
+                                        res_offsets);
+        }
+    }
+};
+
+template <int flag>
+struct JsonParser {
+    //string
+    static void update_value(StringParser::ParseResult& result, rapidjson::Value& value,
+                             StringRef data, rapidjson::Document::AllocatorType& allocator) {
+        value.SetString(data.data, data.size, allocator);
+    }
+};
+
+template <>
+struct JsonParser<'0'> {
+    // null
+    static void update_value(StringParser::ParseResult& result, rapidjson::Value& value,
+                             StringRef data, rapidjson::Document::AllocatorType& allocator) {
+        value.SetNull();
+    }
+};
+
+template <>
+struct JsonParser<'1'> {
+    // bool
+    static void update_value(StringParser::ParseResult& result, rapidjson::Value& value,
+                             StringRef data, rapidjson::Document::AllocatorType& allocator) {
+        DCHECK(data.size == 1 || strncmp(data.data, "true", 4) == 0 ||
+               strncmp(data.data, "false", 5) == 0);
+        value.SetBool((*data.data == '1' || *data.data == 't') ? true : false);
+    }
+};
+
+template <>
+struct JsonParser<'2'> {
+    // int
+    static void update_value(StringParser::ParseResult& result, rapidjson::Value& value,
+                             StringRef data, rapidjson::Document::AllocatorType& allocator) {
+        value.SetInt(StringParser::string_to_int<int32_t>(data.data, data.size, &result));
+    }
+};
+
+template <>
+struct JsonParser<'3'> {
+    // double
+    static void update_value(StringParser::ParseResult& result, rapidjson::Value& value,
+                             StringRef data, rapidjson::Document::AllocatorType& allocator) {
+        value.SetDouble(StringParser::string_to_float<double>(data.data, data.size, &result));
+    }
+};
+
+template <>
+struct JsonParser<'4'> {
+    // time
+    static void update_value(StringParser::ParseResult& result, rapidjson::Value& value,
+                             StringRef data, rapidjson::Document::AllocatorType& allocator) {
+        // remove double quotes, "xxx" -> xxx
+        value.SetString(data.data + 1, data.size - 2, allocator);
+    }
+};
+
+template <>
+struct JsonParser<'5'> {
+    // bigint
+    static void update_value(StringParser::ParseResult& result, rapidjson::Value& value,
+                             StringRef data, rapidjson::Document::AllocatorType& allocator) {
+        value.SetInt64(StringParser::string_to_int<int64_t>(data.data, data.size, &result));
+    }
+};
+
+template <int flag, typename Impl>
+struct ExecuteReducer {
+    template <typename... TArgs>
+    static void run(TArgs&&... args) {
+        Impl::template execute_type<JsonParser<flag>>(std::forward<TArgs>(args)...);
+    }
+};
+
+struct FunctionJsonArrayImpl {
+    static constexpr auto name = "json_array";
+
+    template <int flag>
+    using Reducer = ExecuteReducer<flag, FunctionJsonArrayImpl>;
+
+    static void execute_parse(const std::string& type_flags,
+                              const std::vector<const ColumnString*>& data_columns,
+                              std::vector<rapidjson::Value>& objects,
+                              rapidjson::Document::AllocatorType& allocator,
+                              const std::vector<const ColumnUInt8*>& nullmaps) {
+        for (int i = 0; i < data_columns.size() - 1; i++) {
+            constexpr_int_match<'0', '6', Reducer>::run(type_flags[i], objects, allocator,
+                                                        data_columns[i], nullmaps[i]);
+        }
+    }
+
+    template <typename TypeImpl>
+    static void execute_type(std::vector<rapidjson::Value>& objects,
+                             rapidjson::Document::AllocatorType& allocator,
+                             const ColumnString* data_column, const ColumnUInt8* nullmap) {
+        StringParser::ParseResult result;
+        rapidjson::Value value;
+
+        for (int i = 0; i < objects.size(); i++) {
+            if (nullmap != nullptr && nullmap->get_data()[i]) {
+                JsonParser<'0'>::update_value(result, value, data_column->get_data_at(i),
+                                              allocator);
+            } else {
+                TypeImpl::update_value(result, value, data_column->get_data_at(i), allocator);
+            }
+            objects[i].PushBack(value, allocator);
+        }
+    }
+};
+
+struct FunctionJsonObjectImpl {
+    static constexpr auto name = "json_object";
+
+    template <int flag>
+    using Reducer = ExecuteReducer<flag, FunctionJsonObjectImpl>;
+
+    static void execute_parse(std::string type_flags,
+                              const std::vector<const ColumnString*>& data_columns,
+                              std::vector<rapidjson::Value>& objects,
+                              rapidjson::Document::AllocatorType& allocator,
+                              const std::vector<const ColumnUInt8*>& nullmaps) {
+        for (auto& array_object : objects) {
+            array_object.SetObject();
+        }
+
+        for (int i = 0; i + 1 < data_columns.size() - 1; i += 2) {
+            constexpr_int_match<'0', '6', Reducer>::run(type_flags[i + 1], objects, allocator,
+                                                        data_columns[i], data_columns[i + 1],
+                                                        nullmaps[i + 1]);
+        }
+    }
+
+    template <typename TypeImpl>
+    static void execute_type(std::vector<rapidjson::Value>& objects,
+                             rapidjson::Document::AllocatorType& allocator,
+                             const ColumnString* key_column, const ColumnString* value_column,
+                             const ColumnUInt8* nullmap) {
+        StringParser::ParseResult result;
+        rapidjson::Value key;
+        rapidjson::Value value;
+        for (int i = 0; i < objects.size(); i++) {
+            JsonParser<'6'>::update_value(result, key, key_column->get_data_at(i),
+                                          allocator); // key always is string
+            if (nullmap != nullptr && nullmap->get_data()[i]) {
+                JsonParser<'0'>::update_value(result, value, value_column->get_data_at(i),
+                                              allocator);
+            } else {
+                TypeImpl::update_value(result, value, value_column->get_data_at(i), allocator);
+            }
+            objects[i].AddMember(key, value, allocator);
+        }
+    }
+};
+
+template <typename SpecificImpl>
+class FunctionJsonAlwaysNotNullable : public IFunction {
+public:
+    using IFunction::execute;
+
+    static constexpr auto name = SpecificImpl::name;
+
+    static FunctionPtr create() {
+        return std::make_shared<FunctionJsonAlwaysNotNullable<SpecificImpl>>();
+    }
+
+    bool use_default_implementation_for_nulls() const override { return false; }

Review Comment:
   warning: function 'use_default_implementation_for_nulls' should be marked [[nodiscard]] [modernize-use-nodiscard]
   
   ```suggestion
       [[nodiscard]] bool use_default_implementation_for_nulls() const override { return false; }
   ```
   



##########
function_json.cpp:
##########
@@ -0,0 +1,1320 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#include <rapidjson/allocators.h>
+#include <rapidjson/document.h>
+#include <rapidjson/encodings.h>
+#include <rapidjson/pointer.h>
+#include <rapidjson/rapidjson.h>
+#include <rapidjson/stringbuffer.h>
+#include <rapidjson/writer.h>
+#include <re2/re2.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <algorithm>
+#include <boost/iterator/iterator_facade.hpp>
+#include <boost/token_functions.hpp>
+#include <boost/tokenizer.hpp>
+#include <memory>
+#include <string>
+#include <string_view>
+#include <type_traits>
+#include <utility>
+#include <vector>
+
+// IWYU pragma: no_include <opentelemetry/common/threadlocal.h>
+#include "common/compiler_util.h" // IWYU pragma: keep
+#include "common/status.h"
+#include "exprs/json_functions.h"
+#ifdef __AVX2__
+#include "util/jsonb_parser_simd.h"
+#else
+#include "util/jsonb_parser.h"
+#endif
+#include "util/string_parser.hpp"
+#include "util/string_util.h"
+#include "vec/aggregate_functions/aggregate_function.h"
+#include "vec/columns/column.h"
+#include "vec/columns/column_nullable.h"
+#include "vec/columns/column_string.h"
+#include "vec/columns/column_vector.h"
+#include "vec/columns/columns_number.h"
+#include "vec/common/assert_cast.h"
+#include "vec/common/string_ref.h"
+#include "vec/core/block.h"
+#include "vec/core/column_numbers.h"
+#include "vec/core/column_with_type_and_name.h"
+#include "vec/core/types.h"
+#include "vec/data_types/data_type.h"
+#include "vec/data_types/data_type_nullable.h"
+#include "vec/data_types/data_type_number.h"
+#include "vec/data_types/data_type_string.h"
+#include "vec/functions/function.h"
+#include "vec/functions/function_string.h"
+#include "vec/functions/function_totype.h"
+#include "vec/functions/simple_function_factory.h"
+#include "vec/utils/template_helpers.hpp"
+
+namespace doris {
+class FunctionContext;
+} // namespace doris
+
+namespace doris::vectorized {
+static const re2::RE2 JSON_PATTERN("^([^\\\"\\[\\]]*)(?:\\[([0-9]+|\\*)\\])?");
+
+template <typename T, typename U>
+void char_split(std::vector<T>& res, const U& var, char p) {
+    int start = 0;
+    int pos = start;
+    int end = var.length();
+    while (pos < end) {
+        while (var[pos] != p && pos < end) {
+            pos++;
+        }
+        res.emplace_back(&var[start], pos - start);
+        pos++;
+        start = pos;
+    }
+}
+
+// T = std::vector<std::string>
+// TODO: update RE2 to support std::vector<std::string_view>
+template <typename T>
+void get_parsed_paths(const T& path_exprs, std::vector<JsonPath>* parsed_paths) {
+    if (path_exprs.empty()) {
+        return;
+    }
+
+    if (path_exprs[0] != "$") {
+        parsed_paths->emplace_back("", -1, false);
+    } else {
+        parsed_paths->emplace_back("$", -1, true);
+    }
+
+    for (int i = 1; i < path_exprs.size(); i++) {
+        std::string col;
+        std::string index;
+        if (UNLIKELY(!RE2::FullMatch(path_exprs[i], JSON_PATTERN, &col, &index))) {
+            parsed_paths->emplace_back("", -1, false);
+        } else {
+            int idx = -1;
+            if (!index.empty()) {
+                if (index == "*") {
+                    idx = -2;
+                } else {
+                    idx = atoi(index.c_str());
+                }
+            }
+            parsed_paths->emplace_back(col, idx, true);
+        }
+    }
+}
+
+rapidjson::Value* match_value(const std::vector<JsonPath>& parsed_paths, rapidjson::Value* document,
+                              rapidjson::Document::AllocatorType& mem_allocator,
+                              bool is_insert_null = false) {
+    rapidjson::Value* root = document;
+    rapidjson::Value* array_obj = nullptr;
+    for (int i = 1; i < parsed_paths.size(); i++) {
+        if (root == nullptr || root->IsNull()) {
+            return nullptr;
+        }
+
+        if (UNLIKELY(!parsed_paths[i].is_valid)) {
+            return nullptr;
+        }
+
+        const std::string& col = parsed_paths[i].key;
+        int index = parsed_paths[i].idx;
+        if (LIKELY(!col.empty())) {
+            if (root->IsArray()) {
+                array_obj = static_cast<rapidjson::Value*>(
+                        mem_allocator.Malloc(sizeof(rapidjson::Value)));
+                array_obj->SetArray();
+                bool is_null = true;
+
+                // if array ,loop the array,find out all Objects,then find the results from the objects
+                for (int j = 0; j < root->Size(); j++) {
+                    rapidjson::Value* json_elem = &((*root)[j]);
+
+                    if (json_elem->IsArray() || json_elem->IsNull()) {
+                        continue;
+                    } else {
+                        if (!json_elem->IsObject()) {
+                            continue;
+                        }
+                        if (!json_elem->HasMember(col.c_str())) {
+                            if (is_insert_null) { // not found item, then insert a null object.
+                                is_null = false;
+                                rapidjson::Value nullObject(rapidjson::kNullType);
+                                array_obj->PushBack(nullObject, mem_allocator);
+                            }
+                            continue;
+                        }
+                        rapidjson::Value* obj = &((*json_elem)[col.c_str()]);
+                        if (obj->IsArray()) {
+                            is_null = false;
+                            for (int k = 0; k < obj->Size(); k++) {
+                                array_obj->PushBack((*obj)[k], mem_allocator);
+                            }
+                        } else if (!obj->IsNull()) {
+                            is_null = false;
+                            array_obj->PushBack(*obj, mem_allocator);
+                        }
+                    }
+                }
+
+                root = is_null ? &(array_obj->SetNull()) : array_obj;
+            } else if (root->IsObject()) {
+                if (!root->HasMember(col.c_str())) {
+                    return nullptr;
+                } else {
+                    root = &((*root)[col.c_str()]);
+                }
+            } else {
+                // root is not a nested type, return NULL
+                return nullptr;
+            }
+        }
+
+        if (UNLIKELY(index != -1)) {
+            // judge the rapidjson:Value, which base the top's result,
+            // if not array return NULL;else get the index value from the array
+            if (root->IsArray()) {
+                if (root->IsNull()) {
+                    return nullptr;
+                } else if (index == -2) {
+                    // [*]
+                    array_obj = static_cast<rapidjson::Value*>(
+                            mem_allocator.Malloc(sizeof(rapidjson::Value)));
+                    array_obj->SetArray();
+
+                    for (int j = 0; j < root->Size(); j++) {
+                        rapidjson::Value v;
+                        v.CopyFrom((*root)[j], mem_allocator);
+                        array_obj->PushBack(v, mem_allocator);
+                    }
+                    root = array_obj;
+                } else if (index >= root->Size()) {
+                    return nullptr;
+                } else {
+                    root = &((*root)[index]);
+                }
+            } else {
+                return nullptr;
+            }
+        }
+    }
+    return root;
+}
+
+template <JsonFunctionType fntype>
+rapidjson::Value* get_json_object(std::string_view json_string, std::string_view path_string,
+                                  rapidjson::Document* document) {
+    std::vector<JsonPath>* parsed_paths;
+    std::vector<JsonPath> tmp_parsed_paths;
+
+#ifdef USE_LIBCPP
+    std::string s(path_string);
+    auto tok = get_json_token(s);
+#else
+    auto tok = get_json_token(path_string);
+#endif
+    std::vector<std::string> paths(tok.begin(), tok.end());
+    get_parsed_paths(paths, &tmp_parsed_paths);
+    if (tmp_parsed_paths.empty()) {
+        return document;
+    }
+
+    parsed_paths = &tmp_parsed_paths;
+
+    if (!(*parsed_paths)[0].is_valid) {
+        return document;
+    }
+
+    if (UNLIKELY((*parsed_paths).size() == 1)) {
+        if (fntype == JSON_FUN_STRING) {
+            document->SetString(json_string.data(), json_string.size(), document->GetAllocator());
+        } else {
+            return document;
+        }
+    }
+
+    document->Parse(json_string.data(), json_string.size());
+    if (UNLIKELY(document->HasParseError())) {
+        // VLOG_CRITICAL << "Error at offset " << document->GetErrorOffset() << ": "
+        //         << GetParseError_En(document->GetParseError());
+        document->SetNull();
+        return document;
+    }
+
+    return match_value(*parsed_paths, document, document->GetAllocator());
+}
+
+template <typename NumberType>
+struct GetJsonNumberType {
+    using ReturnType = typename NumberType::ReturnType;
+    using ColumnType = typename NumberType::ColumnType;
+    using Container = typename ColumnType::Container;
+
+    static void get_json_impl(rapidjson::Value*& root, const std::string_view& json_string,
+                              const std::string_view& path_string, rapidjson::Document& document,
+                              typename NumberType::T& res, UInt8& null_map) {
+        if constexpr (std::is_same_v<double, typename NumberType::T>) {
+            root = get_json_object<JSON_FUN_DOUBLE>(json_string, path_string, &document);
+            handle_result<double>(root, res, null_map);
+        } else if constexpr (std::is_same_v<int32_t, typename NumberType::T>) {
+            root = get_json_object<JSON_FUN_DOUBLE>(json_string, path_string, &document);
+            handle_result<int32_t>(root, res, null_map);
+        } else if constexpr (std::is_same_v<int64_t, typename NumberType::T>) {
+            root = get_json_object<JSON_FUN_DOUBLE>(json_string, path_string, &document);
+            handle_result<int64_t>(root, res, null_map);
+        }
+    }
+    static void vector_vector(FunctionContext* context, const ColumnString::Chars& ldata,
+                              const ColumnString::Offsets& loffsets,
+                              const ColumnString::Chars& rdata,
+                              const ColumnString::Offsets& roffsets, Container& res,
+                              NullMap& null_map) {
+        size_t size = loffsets.size();
+        res.resize(size);
+        for (size_t i = 0; i < size; ++i) {
+            const char* l_raw_str = reinterpret_cast<const char*>(&ldata[loffsets[i - 1]]);
+            int l_str_size = loffsets[i] - loffsets[i - 1];
+            const char* r_raw_str = reinterpret_cast<const char*>(&rdata[roffsets[i - 1]]);
+            int r_str_size = roffsets[i] - roffsets[i - 1];
+            if (null_map[i]) {
+                res[i] = 0;
+                continue;
+            }
+
+            std::string_view json_string(l_raw_str, l_str_size);
+            std::string_view path_string(r_raw_str, r_str_size);
+            rapidjson::Document document;
+            rapidjson::Value* root = nullptr;
+
+            get_json_impl(root, json_string, path_string, document, res[i], null_map[i]);
+        }
+    }
+    static void vector_scalar(FunctionContext* context, const ColumnString::Chars& ldata,
+                              const ColumnString::Offsets& loffsets, const StringRef& rdata,
+                              Container& res, NullMap& null_map) {
+        size_t size = loffsets.size();
+        res.resize(size);
+        std::string_view path_string(rdata.data, rdata.size);
+        for (size_t i = 0; i < size; ++i) {
+            const char* l_raw_str = reinterpret_cast<const char*>(&ldata[loffsets[i - 1]]);
+            int l_str_size = loffsets[i] - loffsets[i - 1];
+            if (null_map[i]) {
+                res[i] = 0;
+                continue;
+            }
+            std::string_view json_string(l_raw_str, l_str_size);
+
+            rapidjson::Document document;
+            rapidjson::Value* root = nullptr;
+
+            get_json_impl(root, json_string, path_string, document, res[i], null_map[i]);
+        }
+    }
+    static void scalar_vector(FunctionContext* context, const StringRef& ldata,
+                              const ColumnString::Chars& rdata,
+                              const ColumnString::Offsets& roffsets, Container& res,
+                              NullMap& null_map) {
+        size_t size = roffsets.size();
+        res.resize(size);
+        std::string_view json_string(ldata.data, ldata.size);
+        for (size_t i = 0; i < size; ++i) {
+            const char* r_raw_str = reinterpret_cast<const char*>(&rdata[roffsets[i - 1]]);
+            int r_str_size = roffsets[i] - roffsets[i - 1];
+            if (null_map[i]) {
+                res[i] = 0;
+                continue;
+            }
+            std::string_view path_string(r_raw_str, r_str_size);
+            rapidjson::Document document;
+            rapidjson::Value* root = nullptr;
+
+            get_json_impl(root, json_string, path_string, document, res[i], null_map[i]);
+        }
+    }
+
+    template <typename T, std::enable_if_t<std::is_same_v<double, T>, T>* = nullptr>
+    static void handle_result(rapidjson::Value* root, T& res, uint8_t& res_null) {
+        if (root == nullptr || root->IsNull()) {
+            res = 0;
+            res_null = 1;
+        } else if (root->IsInt()) {
+            res = root->GetInt();
+        } else if (root->IsInt64()) {
+            res = root->GetInt64();
+        } else if (root->IsDouble()) {
+            res = root->GetDouble();
+        } else {
+            res_null = 1;
+        }
+    }
+
+    template <typename T, std::enable_if_t<std::is_same_v<int32_t, T>, T>* = nullptr>
+    static void handle_result(rapidjson::Value* root, int32_t& res, uint8_t& res_null) {
+        if (root != nullptr && root->IsInt()) {
+            res = root->GetInt();
+        } else {
+            res_null = 1;
+        }
+    }
+
+    template <typename T, std::enable_if_t<std::is_same_v<int64_t, T>, T>* = nullptr>
+    static void handle_result(rapidjson::Value* root, int64_t& res, uint8_t& res_null) {
+        if (root != nullptr && root->IsInt64()) {
+            res = root->GetInt64();
+        } else {
+            res_null = 1;
+        }
+    }
+};
+
+// Helper Class
+struct JsonNumberTypeDouble {
+    using T = Float64;
+    using ReturnType = DataTypeFloat64;
+    using ColumnType = ColumnVector<T>;
+};
+
+struct JsonNumberTypeInt {
+    using T = int32_t;
+    using ReturnType = DataTypeInt32;
+    using ColumnType = ColumnVector<T>;
+};
+
+struct JsonNumberTypeBigInt {
+    using T = int64_t;
+    using ReturnType = DataTypeInt64;
+    using ColumnType = ColumnVector<T>;
+};
+
+struct GetJsonDouble : public GetJsonNumberType<JsonNumberTypeDouble> {
+    static constexpr auto name = "get_json_double";
+    using ReturnType = typename JsonNumberTypeDouble::ReturnType;
+    using ColumnType = typename JsonNumberTypeDouble::ColumnType;
+};
+
+struct GetJsonInt : public GetJsonNumberType<JsonNumberTypeInt> {
+    static constexpr auto name = "get_json_int";
+    using ReturnType = typename JsonNumberTypeInt::ReturnType;
+    using ColumnType = typename JsonNumberTypeInt::ColumnType;
+};
+
+struct GetJsonBigInt : public GetJsonNumberType<JsonNumberTypeBigInt> {
+    static constexpr auto name = "get_json_bigint";
+    using ReturnType = typename JsonNumberTypeBigInt::ReturnType;
+    using ColumnType = typename JsonNumberTypeBigInt::ColumnType;
+};
+
+struct GetJsonString {
+    static constexpr auto name = "get_json_string";
+    using ReturnType = DataTypeString;
+    using ColumnType = ColumnString;
+    using Chars = ColumnString::Chars;
+    using Offsets = ColumnString::Offsets;
+    static void vector_vector(FunctionContext* context, const Chars& ldata, const Offsets& loffsets,
+                              const Chars& rdata, const Offsets& roffsets, Chars& res_data,
+                              Offsets& res_offsets, NullMap& null_map) {
+        size_t input_rows_count = loffsets.size();
+        res_offsets.resize(input_rows_count);
+
+        for (size_t i = 0; i < input_rows_count; ++i) {
+            if (null_map[i]) {
+                StringOP::push_null_string(i, res_data, res_offsets, null_map);
+                continue;
+            }
+            int l_size = loffsets[i] - loffsets[i - 1];
+            const auto l_raw = reinterpret_cast<const char*>(&ldata[loffsets[i - 1]]);
+            int r_size = roffsets[i] - roffsets[i - 1];
+            const auto r_raw = reinterpret_cast<const char*>(&rdata[roffsets[i - 1]]);
+
+            std::string_view json_string(l_raw, l_size);
+            std::string_view path_string(r_raw, r_size);
+
+            execute_impl(json_string, path_string, res_data, res_offsets, null_map, i);
+        }
+    }
+    static void vector_scalar(FunctionContext* context, const Chars& ldata, const Offsets& loffsets,
+                              const StringRef& rdata, Chars& res_data, Offsets& res_offsets,
+                              NullMap& null_map) {
+        size_t input_rows_count = loffsets.size();
+        res_offsets.resize(input_rows_count);
+
+        for (size_t i = 0; i < input_rows_count; ++i) {
+            if (null_map[i]) {
+                StringOP::push_null_string(i, res_data, res_offsets, null_map);
+                continue;
+            }
+            int l_size = loffsets[i] - loffsets[i - 1];
+            const auto l_raw = reinterpret_cast<const char*>(&ldata[loffsets[i - 1]]);
+
+            std::string_view json_string(l_raw, l_size);
+            std::string_view path_string(rdata.data, rdata.size);
+
+            execute_impl(json_string, path_string, res_data, res_offsets, null_map, i);
+        }
+    }
+    static void scalar_vector(FunctionContext* context, const StringRef& ldata, const Chars& rdata,
+                              const Offsets& roffsets, Chars& res_data, Offsets& res_offsets,
+                              NullMap& null_map) {
+        size_t input_rows_count = roffsets.size();
+        res_offsets.resize(input_rows_count);
+
+        for (size_t i = 0; i < input_rows_count; ++i) {
+            if (null_map[i]) {
+                StringOP::push_null_string(i, res_data, res_offsets, null_map);
+                continue;
+            }
+            int r_size = roffsets[i] - roffsets[i - 1];
+            const auto r_raw = reinterpret_cast<const char*>(&rdata[roffsets[i - 1]]);
+
+            std::string_view json_string(ldata.data, ldata.size);
+            std::string_view path_string(r_raw, r_size);
+
+            execute_impl(json_string, path_string, res_data, res_offsets, null_map, i);
+        }
+    }
+
+    static void execute_impl(const std::string_view& json_string,
+                             const std::string_view& path_string, Chars& res_data,
+                             Offsets& res_offsets, NullMap& null_map, size_t index_now) {
+        rapidjson::Document document;
+        rapidjson::Value* root = nullptr;
+
+        root = get_json_object<JSON_FUN_STRING>(json_string, path_string, &document);
+        const int max_string_len = 65535;
+
+        if (root == nullptr || root->IsNull()) {
+            StringOP::push_null_string(index_now, res_data, res_offsets, null_map);
+        } else if (root->IsString()) {
+            const auto ptr = root->GetString();
+            size_t len = strnlen(ptr, max_string_len);
+            StringOP::push_value_string(std::string_view(ptr, len), index_now, res_data,
+                                        res_offsets);
+        } else {
+            rapidjson::StringBuffer buf;
+            rapidjson::Writer<rapidjson::StringBuffer> writer(buf);
+            root->Accept(writer);
+
+            const auto ptr = buf.GetString();
+            size_t len = strnlen(ptr, max_string_len);
+            StringOP::push_value_string(std::string_view(ptr, len), index_now, res_data,
+                                        res_offsets);
+        }
+    }
+};
+
+template <int flag>
+struct JsonParser {
+    //string
+    static void update_value(StringParser::ParseResult& result, rapidjson::Value& value,
+                             StringRef data, rapidjson::Document::AllocatorType& allocator) {
+        value.SetString(data.data, data.size, allocator);
+    }
+};
+
+template <>
+struct JsonParser<'0'> {
+    // null
+    static void update_value(StringParser::ParseResult& result, rapidjson::Value& value,
+                             StringRef data, rapidjson::Document::AllocatorType& allocator) {
+        value.SetNull();
+    }
+};
+
+template <>
+struct JsonParser<'1'> {
+    // bool
+    static void update_value(StringParser::ParseResult& result, rapidjson::Value& value,
+                             StringRef data, rapidjson::Document::AllocatorType& allocator) {
+        DCHECK(data.size == 1 || strncmp(data.data, "true", 4) == 0 ||
+               strncmp(data.data, "false", 5) == 0);
+        value.SetBool((*data.data == '1' || *data.data == 't') ? true : false);
+    }
+};
+
+template <>
+struct JsonParser<'2'> {
+    // int
+    static void update_value(StringParser::ParseResult& result, rapidjson::Value& value,
+                             StringRef data, rapidjson::Document::AllocatorType& allocator) {
+        value.SetInt(StringParser::string_to_int<int32_t>(data.data, data.size, &result));
+    }
+};
+
+template <>
+struct JsonParser<'3'> {
+    // double
+    static void update_value(StringParser::ParseResult& result, rapidjson::Value& value,
+                             StringRef data, rapidjson::Document::AllocatorType& allocator) {
+        value.SetDouble(StringParser::string_to_float<double>(data.data, data.size, &result));
+    }
+};
+
+template <>
+struct JsonParser<'4'> {
+    // time
+    static void update_value(StringParser::ParseResult& result, rapidjson::Value& value,
+                             StringRef data, rapidjson::Document::AllocatorType& allocator) {
+        // remove double quotes, "xxx" -> xxx
+        value.SetString(data.data + 1, data.size - 2, allocator);
+    }
+};
+
+template <>
+struct JsonParser<'5'> {
+    // bigint
+    static void update_value(StringParser::ParseResult& result, rapidjson::Value& value,
+                             StringRef data, rapidjson::Document::AllocatorType& allocator) {
+        value.SetInt64(StringParser::string_to_int<int64_t>(data.data, data.size, &result));
+    }
+};
+
+template <int flag, typename Impl>
+struct ExecuteReducer {
+    template <typename... TArgs>
+    static void run(TArgs&&... args) {
+        Impl::template execute_type<JsonParser<flag>>(std::forward<TArgs>(args)...);
+    }
+};
+
+struct FunctionJsonArrayImpl {
+    static constexpr auto name = "json_array";
+
+    template <int flag>
+    using Reducer = ExecuteReducer<flag, FunctionJsonArrayImpl>;
+
+    static void execute_parse(const std::string& type_flags,
+                              const std::vector<const ColumnString*>& data_columns,
+                              std::vector<rapidjson::Value>& objects,
+                              rapidjson::Document::AllocatorType& allocator,
+                              const std::vector<const ColumnUInt8*>& nullmaps) {
+        for (int i = 0; i < data_columns.size() - 1; i++) {
+            constexpr_int_match<'0', '6', Reducer>::run(type_flags[i], objects, allocator,
+                                                        data_columns[i], nullmaps[i]);
+        }
+    }
+
+    template <typename TypeImpl>
+    static void execute_type(std::vector<rapidjson::Value>& objects,
+                             rapidjson::Document::AllocatorType& allocator,
+                             const ColumnString* data_column, const ColumnUInt8* nullmap) {
+        StringParser::ParseResult result;
+        rapidjson::Value value;
+
+        for (int i = 0; i < objects.size(); i++) {
+            if (nullmap != nullptr && nullmap->get_data()[i]) {
+                JsonParser<'0'>::update_value(result, value, data_column->get_data_at(i),
+                                              allocator);
+            } else {
+                TypeImpl::update_value(result, value, data_column->get_data_at(i), allocator);
+            }
+            objects[i].PushBack(value, allocator);
+        }
+    }
+};
+
+struct FunctionJsonObjectImpl {
+    static constexpr auto name = "json_object";
+
+    template <int flag>
+    using Reducer = ExecuteReducer<flag, FunctionJsonObjectImpl>;
+
+    static void execute_parse(std::string type_flags,
+                              const std::vector<const ColumnString*>& data_columns,
+                              std::vector<rapidjson::Value>& objects,
+                              rapidjson::Document::AllocatorType& allocator,
+                              const std::vector<const ColumnUInt8*>& nullmaps) {
+        for (auto& array_object : objects) {
+            array_object.SetObject();
+        }
+
+        for (int i = 0; i + 1 < data_columns.size() - 1; i += 2) {
+            constexpr_int_match<'0', '6', Reducer>::run(type_flags[i + 1], objects, allocator,
+                                                        data_columns[i], data_columns[i + 1],
+                                                        nullmaps[i + 1]);
+        }
+    }
+
+    template <typename TypeImpl>
+    static void execute_type(std::vector<rapidjson::Value>& objects,
+                             rapidjson::Document::AllocatorType& allocator,
+                             const ColumnString* key_column, const ColumnString* value_column,
+                             const ColumnUInt8* nullmap) {
+        StringParser::ParseResult result;
+        rapidjson::Value key;
+        rapidjson::Value value;
+        for (int i = 0; i < objects.size(); i++) {
+            JsonParser<'6'>::update_value(result, key, key_column->get_data_at(i),
+                                          allocator); // key always is string
+            if (nullmap != nullptr && nullmap->get_data()[i]) {
+                JsonParser<'0'>::update_value(result, value, value_column->get_data_at(i),
+                                              allocator);
+            } else {
+                TypeImpl::update_value(result, value, value_column->get_data_at(i), allocator);
+            }
+            objects[i].AddMember(key, value, allocator);
+        }
+    }
+};
+
+template <typename SpecificImpl>
+class FunctionJsonAlwaysNotNullable : public IFunction {
+public:
+    using IFunction::execute;
+
+    static constexpr auto name = SpecificImpl::name;
+
+    static FunctionPtr create() {
+        return std::make_shared<FunctionJsonAlwaysNotNullable<SpecificImpl>>();
+    }
+
+    bool use_default_implementation_for_nulls() const override { return false; }
+
+    String get_name() const override { return name; }

Review Comment:
   warning: function 'get_name' should be marked [[nodiscard]] [modernize-use-nodiscard]
   
   ```suggestion
       [[nodiscard]] String get_name() const override { return name; }
   ```
   



##########
function_json.cpp:
##########
@@ -0,0 +1,1320 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#include <rapidjson/allocators.h>
+#include <rapidjson/document.h>
+#include <rapidjson/encodings.h>
+#include <rapidjson/pointer.h>
+#include <rapidjson/rapidjson.h>
+#include <rapidjson/stringbuffer.h>
+#include <rapidjson/writer.h>
+#include <re2/re2.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <algorithm>
+#include <boost/iterator/iterator_facade.hpp>
+#include <boost/token_functions.hpp>
+#include <boost/tokenizer.hpp>
+#include <memory>
+#include <string>
+#include <string_view>
+#include <type_traits>
+#include <utility>
+#include <vector>
+
+// IWYU pragma: no_include <opentelemetry/common/threadlocal.h>
+#include "common/compiler_util.h" // IWYU pragma: keep
+#include "common/status.h"
+#include "exprs/json_functions.h"
+#ifdef __AVX2__
+#include "util/jsonb_parser_simd.h"
+#else
+#include "util/jsonb_parser.h"
+#endif
+#include "util/string_parser.hpp"
+#include "util/string_util.h"
+#include "vec/aggregate_functions/aggregate_function.h"
+#include "vec/columns/column.h"
+#include "vec/columns/column_nullable.h"
+#include "vec/columns/column_string.h"
+#include "vec/columns/column_vector.h"
+#include "vec/columns/columns_number.h"
+#include "vec/common/assert_cast.h"
+#include "vec/common/string_ref.h"
+#include "vec/core/block.h"
+#include "vec/core/column_numbers.h"
+#include "vec/core/column_with_type_and_name.h"
+#include "vec/core/types.h"
+#include "vec/data_types/data_type.h"
+#include "vec/data_types/data_type_nullable.h"
+#include "vec/data_types/data_type_number.h"
+#include "vec/data_types/data_type_string.h"
+#include "vec/functions/function.h"
+#include "vec/functions/function_string.h"
+#include "vec/functions/function_totype.h"
+#include "vec/functions/simple_function_factory.h"
+#include "vec/utils/template_helpers.hpp"
+
+namespace doris {
+class FunctionContext;
+} // namespace doris
+
+namespace doris::vectorized {
+static const re2::RE2 JSON_PATTERN("^([^\\\"\\[\\]]*)(?:\\[([0-9]+|\\*)\\])?");
+
+template <typename T, typename U>
+void char_split(std::vector<T>& res, const U& var, char p) {
+    int start = 0;
+    int pos = start;
+    int end = var.length();
+    while (pos < end) {
+        while (var[pos] != p && pos < end) {
+            pos++;
+        }
+        res.emplace_back(&var[start], pos - start);
+        pos++;
+        start = pos;
+    }
+}
+
+// T = std::vector<std::string>
+// TODO: update RE2 to support std::vector<std::string_view>
+template <typename T>
+void get_parsed_paths(const T& path_exprs, std::vector<JsonPath>* parsed_paths) {
+    if (path_exprs.empty()) {
+        return;
+    }
+
+    if (path_exprs[0] != "$") {
+        parsed_paths->emplace_back("", -1, false);
+    } else {
+        parsed_paths->emplace_back("$", -1, true);
+    }
+
+    for (int i = 1; i < path_exprs.size(); i++) {
+        std::string col;
+        std::string index;
+        if (UNLIKELY(!RE2::FullMatch(path_exprs[i], JSON_PATTERN, &col, &index))) {
+            parsed_paths->emplace_back("", -1, false);
+        } else {
+            int idx = -1;
+            if (!index.empty()) {
+                if (index == "*") {
+                    idx = -2;
+                } else {
+                    idx = atoi(index.c_str());
+                }
+            }
+            parsed_paths->emplace_back(col, idx, true);
+        }
+    }
+}
+
+rapidjson::Value* match_value(const std::vector<JsonPath>& parsed_paths, rapidjson::Value* document,
+                              rapidjson::Document::AllocatorType& mem_allocator,
+                              bool is_insert_null = false) {
+    rapidjson::Value* root = document;
+    rapidjson::Value* array_obj = nullptr;
+    for (int i = 1; i < parsed_paths.size(); i++) {
+        if (root == nullptr || root->IsNull()) {
+            return nullptr;
+        }
+
+        if (UNLIKELY(!parsed_paths[i].is_valid)) {
+            return nullptr;
+        }
+
+        const std::string& col = parsed_paths[i].key;
+        int index = parsed_paths[i].idx;
+        if (LIKELY(!col.empty())) {
+            if (root->IsArray()) {
+                array_obj = static_cast<rapidjson::Value*>(
+                        mem_allocator.Malloc(sizeof(rapidjson::Value)));
+                array_obj->SetArray();
+                bool is_null = true;
+
+                // if array ,loop the array,find out all Objects,then find the results from the objects
+                for (int j = 0; j < root->Size(); j++) {
+                    rapidjson::Value* json_elem = &((*root)[j]);
+
+                    if (json_elem->IsArray() || json_elem->IsNull()) {
+                        continue;
+                    } else {
+                        if (!json_elem->IsObject()) {
+                            continue;
+                        }
+                        if (!json_elem->HasMember(col.c_str())) {
+                            if (is_insert_null) { // not found item, then insert a null object.
+                                is_null = false;
+                                rapidjson::Value nullObject(rapidjson::kNullType);
+                                array_obj->PushBack(nullObject, mem_allocator);
+                            }
+                            continue;
+                        }
+                        rapidjson::Value* obj = &((*json_elem)[col.c_str()]);
+                        if (obj->IsArray()) {
+                            is_null = false;
+                            for (int k = 0; k < obj->Size(); k++) {
+                                array_obj->PushBack((*obj)[k], mem_allocator);
+                            }
+                        } else if (!obj->IsNull()) {
+                            is_null = false;
+                            array_obj->PushBack(*obj, mem_allocator);
+                        }
+                    }
+                }
+
+                root = is_null ? &(array_obj->SetNull()) : array_obj;
+            } else if (root->IsObject()) {
+                if (!root->HasMember(col.c_str())) {
+                    return nullptr;
+                } else {
+                    root = &((*root)[col.c_str()]);
+                }
+            } else {
+                // root is not a nested type, return NULL
+                return nullptr;
+            }
+        }
+
+        if (UNLIKELY(index != -1)) {
+            // judge the rapidjson:Value, which base the top's result,
+            // if not array return NULL;else get the index value from the array
+            if (root->IsArray()) {
+                if (root->IsNull()) {
+                    return nullptr;
+                } else if (index == -2) {
+                    // [*]
+                    array_obj = static_cast<rapidjson::Value*>(
+                            mem_allocator.Malloc(sizeof(rapidjson::Value)));
+                    array_obj->SetArray();
+
+                    for (int j = 0; j < root->Size(); j++) {
+                        rapidjson::Value v;
+                        v.CopyFrom((*root)[j], mem_allocator);
+                        array_obj->PushBack(v, mem_allocator);
+                    }
+                    root = array_obj;
+                } else if (index >= root->Size()) {
+                    return nullptr;
+                } else {
+                    root = &((*root)[index]);
+                }
+            } else {
+                return nullptr;
+            }
+        }
+    }
+    return root;
+}
+
+template <JsonFunctionType fntype>
+rapidjson::Value* get_json_object(std::string_view json_string, std::string_view path_string,
+                                  rapidjson::Document* document) {
+    std::vector<JsonPath>* parsed_paths;
+    std::vector<JsonPath> tmp_parsed_paths;
+
+#ifdef USE_LIBCPP
+    std::string s(path_string);
+    auto tok = get_json_token(s);
+#else
+    auto tok = get_json_token(path_string);
+#endif
+    std::vector<std::string> paths(tok.begin(), tok.end());
+    get_parsed_paths(paths, &tmp_parsed_paths);
+    if (tmp_parsed_paths.empty()) {
+        return document;
+    }
+
+    parsed_paths = &tmp_parsed_paths;
+
+    if (!(*parsed_paths)[0].is_valid) {
+        return document;
+    }
+
+    if (UNLIKELY((*parsed_paths).size() == 1)) {
+        if (fntype == JSON_FUN_STRING) {
+            document->SetString(json_string.data(), json_string.size(), document->GetAllocator());
+        } else {
+            return document;
+        }
+    }
+
+    document->Parse(json_string.data(), json_string.size());
+    if (UNLIKELY(document->HasParseError())) {
+        // VLOG_CRITICAL << "Error at offset " << document->GetErrorOffset() << ": "
+        //         << GetParseError_En(document->GetParseError());
+        document->SetNull();
+        return document;
+    }
+
+    return match_value(*parsed_paths, document, document->GetAllocator());
+}
+
+template <typename NumberType>
+struct GetJsonNumberType {
+    using ReturnType = typename NumberType::ReturnType;
+    using ColumnType = typename NumberType::ColumnType;
+    using Container = typename ColumnType::Container;
+
+    static void get_json_impl(rapidjson::Value*& root, const std::string_view& json_string,
+                              const std::string_view& path_string, rapidjson::Document& document,
+                              typename NumberType::T& res, UInt8& null_map) {
+        if constexpr (std::is_same_v<double, typename NumberType::T>) {
+            root = get_json_object<JSON_FUN_DOUBLE>(json_string, path_string, &document);
+            handle_result<double>(root, res, null_map);
+        } else if constexpr (std::is_same_v<int32_t, typename NumberType::T>) {
+            root = get_json_object<JSON_FUN_DOUBLE>(json_string, path_string, &document);
+            handle_result<int32_t>(root, res, null_map);
+        } else if constexpr (std::is_same_v<int64_t, typename NumberType::T>) {
+            root = get_json_object<JSON_FUN_DOUBLE>(json_string, path_string, &document);
+            handle_result<int64_t>(root, res, null_map);
+        }
+    }
+    static void vector_vector(FunctionContext* context, const ColumnString::Chars& ldata,
+                              const ColumnString::Offsets& loffsets,
+                              const ColumnString::Chars& rdata,
+                              const ColumnString::Offsets& roffsets, Container& res,
+                              NullMap& null_map) {
+        size_t size = loffsets.size();
+        res.resize(size);
+        for (size_t i = 0; i < size; ++i) {
+            const char* l_raw_str = reinterpret_cast<const char*>(&ldata[loffsets[i - 1]]);
+            int l_str_size = loffsets[i] - loffsets[i - 1];
+            const char* r_raw_str = reinterpret_cast<const char*>(&rdata[roffsets[i - 1]]);
+            int r_str_size = roffsets[i] - roffsets[i - 1];
+            if (null_map[i]) {
+                res[i] = 0;
+                continue;
+            }
+
+            std::string_view json_string(l_raw_str, l_str_size);
+            std::string_view path_string(r_raw_str, r_str_size);
+            rapidjson::Document document;
+            rapidjson::Value* root = nullptr;
+
+            get_json_impl(root, json_string, path_string, document, res[i], null_map[i]);
+        }
+    }
+    static void vector_scalar(FunctionContext* context, const ColumnString::Chars& ldata,
+                              const ColumnString::Offsets& loffsets, const StringRef& rdata,
+                              Container& res, NullMap& null_map) {
+        size_t size = loffsets.size();
+        res.resize(size);
+        std::string_view path_string(rdata.data, rdata.size);
+        for (size_t i = 0; i < size; ++i) {
+            const char* l_raw_str = reinterpret_cast<const char*>(&ldata[loffsets[i - 1]]);
+            int l_str_size = loffsets[i] - loffsets[i - 1];
+            if (null_map[i]) {
+                res[i] = 0;
+                continue;
+            }
+            std::string_view json_string(l_raw_str, l_str_size);
+
+            rapidjson::Document document;
+            rapidjson::Value* root = nullptr;
+
+            get_json_impl(root, json_string, path_string, document, res[i], null_map[i]);
+        }
+    }
+    static void scalar_vector(FunctionContext* context, const StringRef& ldata,
+                              const ColumnString::Chars& rdata,
+                              const ColumnString::Offsets& roffsets, Container& res,
+                              NullMap& null_map) {
+        size_t size = roffsets.size();
+        res.resize(size);
+        std::string_view json_string(ldata.data, ldata.size);
+        for (size_t i = 0; i < size; ++i) {
+            const char* r_raw_str = reinterpret_cast<const char*>(&rdata[roffsets[i - 1]]);
+            int r_str_size = roffsets[i] - roffsets[i - 1];
+            if (null_map[i]) {
+                res[i] = 0;
+                continue;
+            }
+            std::string_view path_string(r_raw_str, r_str_size);
+            rapidjson::Document document;
+            rapidjson::Value* root = nullptr;
+
+            get_json_impl(root, json_string, path_string, document, res[i], null_map[i]);
+        }
+    }
+
+    template <typename T, std::enable_if_t<std::is_same_v<double, T>, T>* = nullptr>
+    static void handle_result(rapidjson::Value* root, T& res, uint8_t& res_null) {
+        if (root == nullptr || root->IsNull()) {
+            res = 0;
+            res_null = 1;
+        } else if (root->IsInt()) {
+            res = root->GetInt();
+        } else if (root->IsInt64()) {
+            res = root->GetInt64();
+        } else if (root->IsDouble()) {
+            res = root->GetDouble();
+        } else {
+            res_null = 1;
+        }
+    }
+
+    template <typename T, std::enable_if_t<std::is_same_v<int32_t, T>, T>* = nullptr>
+    static void handle_result(rapidjson::Value* root, int32_t& res, uint8_t& res_null) {
+        if (root != nullptr && root->IsInt()) {
+            res = root->GetInt();
+        } else {
+            res_null = 1;
+        }
+    }
+
+    template <typename T, std::enable_if_t<std::is_same_v<int64_t, T>, T>* = nullptr>
+    static void handle_result(rapidjson::Value* root, int64_t& res, uint8_t& res_null) {
+        if (root != nullptr && root->IsInt64()) {
+            res = root->GetInt64();
+        } else {
+            res_null = 1;
+        }
+    }
+};
+
+// Helper Class
+struct JsonNumberTypeDouble {
+    using T = Float64;
+    using ReturnType = DataTypeFloat64;
+    using ColumnType = ColumnVector<T>;
+};
+
+struct JsonNumberTypeInt {
+    using T = int32_t;
+    using ReturnType = DataTypeInt32;
+    using ColumnType = ColumnVector<T>;
+};
+
+struct JsonNumberTypeBigInt {
+    using T = int64_t;
+    using ReturnType = DataTypeInt64;
+    using ColumnType = ColumnVector<T>;
+};
+
+struct GetJsonDouble : public GetJsonNumberType<JsonNumberTypeDouble> {
+    static constexpr auto name = "get_json_double";
+    using ReturnType = typename JsonNumberTypeDouble::ReturnType;
+    using ColumnType = typename JsonNumberTypeDouble::ColumnType;
+};
+
+struct GetJsonInt : public GetJsonNumberType<JsonNumberTypeInt> {
+    static constexpr auto name = "get_json_int";
+    using ReturnType = typename JsonNumberTypeInt::ReturnType;
+    using ColumnType = typename JsonNumberTypeInt::ColumnType;
+};
+
+struct GetJsonBigInt : public GetJsonNumberType<JsonNumberTypeBigInt> {
+    static constexpr auto name = "get_json_bigint";
+    using ReturnType = typename JsonNumberTypeBigInt::ReturnType;
+    using ColumnType = typename JsonNumberTypeBigInt::ColumnType;
+};
+
+struct GetJsonString {
+    static constexpr auto name = "get_json_string";
+    using ReturnType = DataTypeString;
+    using ColumnType = ColumnString;
+    using Chars = ColumnString::Chars;
+    using Offsets = ColumnString::Offsets;
+    static void vector_vector(FunctionContext* context, const Chars& ldata, const Offsets& loffsets,
+                              const Chars& rdata, const Offsets& roffsets, Chars& res_data,
+                              Offsets& res_offsets, NullMap& null_map) {
+        size_t input_rows_count = loffsets.size();
+        res_offsets.resize(input_rows_count);
+
+        for (size_t i = 0; i < input_rows_count; ++i) {
+            if (null_map[i]) {
+                StringOP::push_null_string(i, res_data, res_offsets, null_map);
+                continue;
+            }
+            int l_size = loffsets[i] - loffsets[i - 1];
+            const auto l_raw = reinterpret_cast<const char*>(&ldata[loffsets[i - 1]]);
+            int r_size = roffsets[i] - roffsets[i - 1];
+            const auto r_raw = reinterpret_cast<const char*>(&rdata[roffsets[i - 1]]);
+
+            std::string_view json_string(l_raw, l_size);
+            std::string_view path_string(r_raw, r_size);
+
+            execute_impl(json_string, path_string, res_data, res_offsets, null_map, i);
+        }
+    }
+    static void vector_scalar(FunctionContext* context, const Chars& ldata, const Offsets& loffsets,
+                              const StringRef& rdata, Chars& res_data, Offsets& res_offsets,
+                              NullMap& null_map) {
+        size_t input_rows_count = loffsets.size();
+        res_offsets.resize(input_rows_count);
+
+        for (size_t i = 0; i < input_rows_count; ++i) {
+            if (null_map[i]) {
+                StringOP::push_null_string(i, res_data, res_offsets, null_map);
+                continue;
+            }
+            int l_size = loffsets[i] - loffsets[i - 1];
+            const auto l_raw = reinterpret_cast<const char*>(&ldata[loffsets[i - 1]]);
+
+            std::string_view json_string(l_raw, l_size);
+            std::string_view path_string(rdata.data, rdata.size);
+
+            execute_impl(json_string, path_string, res_data, res_offsets, null_map, i);
+        }
+    }
+    static void scalar_vector(FunctionContext* context, const StringRef& ldata, const Chars& rdata,
+                              const Offsets& roffsets, Chars& res_data, Offsets& res_offsets,
+                              NullMap& null_map) {
+        size_t input_rows_count = roffsets.size();
+        res_offsets.resize(input_rows_count);
+
+        for (size_t i = 0; i < input_rows_count; ++i) {
+            if (null_map[i]) {
+                StringOP::push_null_string(i, res_data, res_offsets, null_map);
+                continue;
+            }
+            int r_size = roffsets[i] - roffsets[i - 1];
+            const auto r_raw = reinterpret_cast<const char*>(&rdata[roffsets[i - 1]]);
+
+            std::string_view json_string(ldata.data, ldata.size);
+            std::string_view path_string(r_raw, r_size);
+
+            execute_impl(json_string, path_string, res_data, res_offsets, null_map, i);
+        }
+    }
+
+    static void execute_impl(const std::string_view& json_string,
+                             const std::string_view& path_string, Chars& res_data,
+                             Offsets& res_offsets, NullMap& null_map, size_t index_now) {
+        rapidjson::Document document;
+        rapidjson::Value* root = nullptr;
+
+        root = get_json_object<JSON_FUN_STRING>(json_string, path_string, &document);
+        const int max_string_len = 65535;
+
+        if (root == nullptr || root->IsNull()) {
+            StringOP::push_null_string(index_now, res_data, res_offsets, null_map);
+        } else if (root->IsString()) {
+            const auto ptr = root->GetString();
+            size_t len = strnlen(ptr, max_string_len);
+            StringOP::push_value_string(std::string_view(ptr, len), index_now, res_data,
+                                        res_offsets);
+        } else {
+            rapidjson::StringBuffer buf;
+            rapidjson::Writer<rapidjson::StringBuffer> writer(buf);
+            root->Accept(writer);
+
+            const auto ptr = buf.GetString();
+            size_t len = strnlen(ptr, max_string_len);
+            StringOP::push_value_string(std::string_view(ptr, len), index_now, res_data,
+                                        res_offsets);
+        }
+    }
+};
+
+template <int flag>
+struct JsonParser {
+    //string
+    static void update_value(StringParser::ParseResult& result, rapidjson::Value& value,
+                             StringRef data, rapidjson::Document::AllocatorType& allocator) {
+        value.SetString(data.data, data.size, allocator);
+    }
+};
+
+template <>
+struct JsonParser<'0'> {
+    // null
+    static void update_value(StringParser::ParseResult& result, rapidjson::Value& value,
+                             StringRef data, rapidjson::Document::AllocatorType& allocator) {
+        value.SetNull();
+    }
+};
+
+template <>
+struct JsonParser<'1'> {
+    // bool
+    static void update_value(StringParser::ParseResult& result, rapidjson::Value& value,
+                             StringRef data, rapidjson::Document::AllocatorType& allocator) {
+        DCHECK(data.size == 1 || strncmp(data.data, "true", 4) == 0 ||
+               strncmp(data.data, "false", 5) == 0);
+        value.SetBool((*data.data == '1' || *data.data == 't') ? true : false);
+    }
+};
+
+template <>
+struct JsonParser<'2'> {
+    // int
+    static void update_value(StringParser::ParseResult& result, rapidjson::Value& value,
+                             StringRef data, rapidjson::Document::AllocatorType& allocator) {
+        value.SetInt(StringParser::string_to_int<int32_t>(data.data, data.size, &result));
+    }
+};
+
+template <>
+struct JsonParser<'3'> {
+    // double
+    static void update_value(StringParser::ParseResult& result, rapidjson::Value& value,
+                             StringRef data, rapidjson::Document::AllocatorType& allocator) {
+        value.SetDouble(StringParser::string_to_float<double>(data.data, data.size, &result));
+    }
+};
+
+template <>
+struct JsonParser<'4'> {
+    // time
+    static void update_value(StringParser::ParseResult& result, rapidjson::Value& value,
+                             StringRef data, rapidjson::Document::AllocatorType& allocator) {
+        // remove double quotes, "xxx" -> xxx
+        value.SetString(data.data + 1, data.size - 2, allocator);
+    }
+};
+
+template <>
+struct JsonParser<'5'> {
+    // bigint
+    static void update_value(StringParser::ParseResult& result, rapidjson::Value& value,
+                             StringRef data, rapidjson::Document::AllocatorType& allocator) {
+        value.SetInt64(StringParser::string_to_int<int64_t>(data.data, data.size, &result));
+    }
+};
+
+template <int flag, typename Impl>
+struct ExecuteReducer {
+    template <typename... TArgs>
+    static void run(TArgs&&... args) {
+        Impl::template execute_type<JsonParser<flag>>(std::forward<TArgs>(args)...);
+    }
+};
+
+struct FunctionJsonArrayImpl {
+    static constexpr auto name = "json_array";
+
+    template <int flag>
+    using Reducer = ExecuteReducer<flag, FunctionJsonArrayImpl>;
+
+    static void execute_parse(const std::string& type_flags,
+                              const std::vector<const ColumnString*>& data_columns,
+                              std::vector<rapidjson::Value>& objects,
+                              rapidjson::Document::AllocatorType& allocator,
+                              const std::vector<const ColumnUInt8*>& nullmaps) {
+        for (int i = 0; i < data_columns.size() - 1; i++) {
+            constexpr_int_match<'0', '6', Reducer>::run(type_flags[i], objects, allocator,
+                                                        data_columns[i], nullmaps[i]);
+        }
+    }
+
+    template <typename TypeImpl>
+    static void execute_type(std::vector<rapidjson::Value>& objects,
+                             rapidjson::Document::AllocatorType& allocator,
+                             const ColumnString* data_column, const ColumnUInt8* nullmap) {
+        StringParser::ParseResult result;
+        rapidjson::Value value;
+
+        for (int i = 0; i < objects.size(); i++) {
+            if (nullmap != nullptr && nullmap->get_data()[i]) {
+                JsonParser<'0'>::update_value(result, value, data_column->get_data_at(i),
+                                              allocator);
+            } else {
+                TypeImpl::update_value(result, value, data_column->get_data_at(i), allocator);
+            }
+            objects[i].PushBack(value, allocator);
+        }
+    }
+};
+
+struct FunctionJsonObjectImpl {
+    static constexpr auto name = "json_object";
+
+    template <int flag>
+    using Reducer = ExecuteReducer<flag, FunctionJsonObjectImpl>;
+
+    static void execute_parse(std::string type_flags,
+                              const std::vector<const ColumnString*>& data_columns,
+                              std::vector<rapidjson::Value>& objects,
+                              rapidjson::Document::AllocatorType& allocator,
+                              const std::vector<const ColumnUInt8*>& nullmaps) {
+        for (auto& array_object : objects) {
+            array_object.SetObject();
+        }
+
+        for (int i = 0; i + 1 < data_columns.size() - 1; i += 2) {
+            constexpr_int_match<'0', '6', Reducer>::run(type_flags[i + 1], objects, allocator,
+                                                        data_columns[i], data_columns[i + 1],
+                                                        nullmaps[i + 1]);
+        }
+    }
+
+    template <typename TypeImpl>
+    static void execute_type(std::vector<rapidjson::Value>& objects,
+                             rapidjson::Document::AllocatorType& allocator,
+                             const ColumnString* key_column, const ColumnString* value_column,
+                             const ColumnUInt8* nullmap) {
+        StringParser::ParseResult result;
+        rapidjson::Value key;
+        rapidjson::Value value;
+        for (int i = 0; i < objects.size(); i++) {
+            JsonParser<'6'>::update_value(result, key, key_column->get_data_at(i),
+                                          allocator); // key always is string
+            if (nullmap != nullptr && nullmap->get_data()[i]) {
+                JsonParser<'0'>::update_value(result, value, value_column->get_data_at(i),
+                                              allocator);
+            } else {
+                TypeImpl::update_value(result, value, value_column->get_data_at(i), allocator);
+            }
+            objects[i].AddMember(key, value, allocator);
+        }
+    }
+};
+
+template <typename SpecificImpl>
+class FunctionJsonAlwaysNotNullable : public IFunction {
+public:
+    using IFunction::execute;
+
+    static constexpr auto name = SpecificImpl::name;
+
+    static FunctionPtr create() {
+        return std::make_shared<FunctionJsonAlwaysNotNullable<SpecificImpl>>();
+    }
+
+    bool use_default_implementation_for_nulls() const override { return false; }
+
+    String get_name() const override { return name; }
+
+    size_t get_number_of_arguments() const override { return 0; }
+
+    bool is_variadic() const override { return true; }

Review Comment:
   warning: function 'is_variadic' should be marked [[nodiscard]] [modernize-use-nodiscard]
   
   ```suggestion
       [[nodiscard]] bool is_variadic() const override { return true; }
   ```
   



##########
function_json.cpp:
##########
@@ -0,0 +1,1320 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#include <rapidjson/allocators.h>
+#include <rapidjson/document.h>
+#include <rapidjson/encodings.h>
+#include <rapidjson/pointer.h>
+#include <rapidjson/rapidjson.h>
+#include <rapidjson/stringbuffer.h>
+#include <rapidjson/writer.h>
+#include <re2/re2.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <algorithm>
+#include <boost/iterator/iterator_facade.hpp>
+#include <boost/token_functions.hpp>
+#include <boost/tokenizer.hpp>
+#include <memory>
+#include <string>
+#include <string_view>
+#include <type_traits>
+#include <utility>
+#include <vector>
+
+// IWYU pragma: no_include <opentelemetry/common/threadlocal.h>
+#include "common/compiler_util.h" // IWYU pragma: keep
+#include "common/status.h"
+#include "exprs/json_functions.h"
+#ifdef __AVX2__
+#include "util/jsonb_parser_simd.h"
+#else
+#include "util/jsonb_parser.h"
+#endif
+#include "util/string_parser.hpp"
+#include "util/string_util.h"
+#include "vec/aggregate_functions/aggregate_function.h"
+#include "vec/columns/column.h"
+#include "vec/columns/column_nullable.h"
+#include "vec/columns/column_string.h"
+#include "vec/columns/column_vector.h"
+#include "vec/columns/columns_number.h"
+#include "vec/common/assert_cast.h"
+#include "vec/common/string_ref.h"
+#include "vec/core/block.h"
+#include "vec/core/column_numbers.h"
+#include "vec/core/column_with_type_and_name.h"
+#include "vec/core/types.h"
+#include "vec/data_types/data_type.h"
+#include "vec/data_types/data_type_nullable.h"
+#include "vec/data_types/data_type_number.h"
+#include "vec/data_types/data_type_string.h"
+#include "vec/functions/function.h"
+#include "vec/functions/function_string.h"
+#include "vec/functions/function_totype.h"
+#include "vec/functions/simple_function_factory.h"
+#include "vec/utils/template_helpers.hpp"
+
+namespace doris {
+class FunctionContext;
+} // namespace doris
+
+namespace doris::vectorized {
+static const re2::RE2 JSON_PATTERN("^([^\\\"\\[\\]]*)(?:\\[([0-9]+|\\*)\\])?");
+
+template <typename T, typename U>
+void char_split(std::vector<T>& res, const U& var, char p) {
+    int start = 0;
+    int pos = start;
+    int end = var.length();
+    while (pos < end) {
+        while (var[pos] != p && pos < end) {
+            pos++;
+        }
+        res.emplace_back(&var[start], pos - start);
+        pos++;
+        start = pos;
+    }
+}
+
+// T = std::vector<std::string>
+// TODO: update RE2 to support std::vector<std::string_view>
+template <typename T>
+void get_parsed_paths(const T& path_exprs, std::vector<JsonPath>* parsed_paths) {
+    if (path_exprs.empty()) {
+        return;
+    }
+
+    if (path_exprs[0] != "$") {
+        parsed_paths->emplace_back("", -1, false);
+    } else {
+        parsed_paths->emplace_back("$", -1, true);
+    }
+
+    for (int i = 1; i < path_exprs.size(); i++) {
+        std::string col;
+        std::string index;
+        if (UNLIKELY(!RE2::FullMatch(path_exprs[i], JSON_PATTERN, &col, &index))) {
+            parsed_paths->emplace_back("", -1, false);
+        } else {
+            int idx = -1;
+            if (!index.empty()) {
+                if (index == "*") {
+                    idx = -2;
+                } else {
+                    idx = atoi(index.c_str());
+                }
+            }
+            parsed_paths->emplace_back(col, idx, true);
+        }
+    }
+}
+
+rapidjson::Value* match_value(const std::vector<JsonPath>& parsed_paths, rapidjson::Value* document,
+                              rapidjson::Document::AllocatorType& mem_allocator,
+                              bool is_insert_null = false) {
+    rapidjson::Value* root = document;
+    rapidjson::Value* array_obj = nullptr;
+    for (int i = 1; i < parsed_paths.size(); i++) {
+        if (root == nullptr || root->IsNull()) {
+            return nullptr;
+        }
+
+        if (UNLIKELY(!parsed_paths[i].is_valid)) {
+            return nullptr;
+        }
+
+        const std::string& col = parsed_paths[i].key;
+        int index = parsed_paths[i].idx;
+        if (LIKELY(!col.empty())) {
+            if (root->IsArray()) {
+                array_obj = static_cast<rapidjson::Value*>(
+                        mem_allocator.Malloc(sizeof(rapidjson::Value)));
+                array_obj->SetArray();
+                bool is_null = true;
+
+                // if array ,loop the array,find out all Objects,then find the results from the objects
+                for (int j = 0; j < root->Size(); j++) {
+                    rapidjson::Value* json_elem = &((*root)[j]);
+
+                    if (json_elem->IsArray() || json_elem->IsNull()) {
+                        continue;
+                    } else {
+                        if (!json_elem->IsObject()) {
+                            continue;
+                        }
+                        if (!json_elem->HasMember(col.c_str())) {
+                            if (is_insert_null) { // not found item, then insert a null object.
+                                is_null = false;
+                                rapidjson::Value nullObject(rapidjson::kNullType);
+                                array_obj->PushBack(nullObject, mem_allocator);
+                            }
+                            continue;
+                        }
+                        rapidjson::Value* obj = &((*json_elem)[col.c_str()]);
+                        if (obj->IsArray()) {
+                            is_null = false;
+                            for (int k = 0; k < obj->Size(); k++) {
+                                array_obj->PushBack((*obj)[k], mem_allocator);
+                            }
+                        } else if (!obj->IsNull()) {
+                            is_null = false;
+                            array_obj->PushBack(*obj, mem_allocator);
+                        }
+                    }
+                }
+
+                root = is_null ? &(array_obj->SetNull()) : array_obj;
+            } else if (root->IsObject()) {
+                if (!root->HasMember(col.c_str())) {
+                    return nullptr;
+                } else {
+                    root = &((*root)[col.c_str()]);
+                }
+            } else {
+                // root is not a nested type, return NULL
+                return nullptr;
+            }
+        }
+
+        if (UNLIKELY(index != -1)) {
+            // judge the rapidjson:Value, which base the top's result,
+            // if not array return NULL;else get the index value from the array
+            if (root->IsArray()) {
+                if (root->IsNull()) {
+                    return nullptr;
+                } else if (index == -2) {
+                    // [*]
+                    array_obj = static_cast<rapidjson::Value*>(
+                            mem_allocator.Malloc(sizeof(rapidjson::Value)));
+                    array_obj->SetArray();
+
+                    for (int j = 0; j < root->Size(); j++) {
+                        rapidjson::Value v;
+                        v.CopyFrom((*root)[j], mem_allocator);
+                        array_obj->PushBack(v, mem_allocator);
+                    }
+                    root = array_obj;
+                } else if (index >= root->Size()) {
+                    return nullptr;
+                } else {
+                    root = &((*root)[index]);
+                }
+            } else {
+                return nullptr;
+            }
+        }
+    }
+    return root;
+}
+
+template <JsonFunctionType fntype>
+rapidjson::Value* get_json_object(std::string_view json_string, std::string_view path_string,
+                                  rapidjson::Document* document) {
+    std::vector<JsonPath>* parsed_paths;
+    std::vector<JsonPath> tmp_parsed_paths;
+
+#ifdef USE_LIBCPP
+    std::string s(path_string);
+    auto tok = get_json_token(s);
+#else
+    auto tok = get_json_token(path_string);
+#endif
+    std::vector<std::string> paths(tok.begin(), tok.end());
+    get_parsed_paths(paths, &tmp_parsed_paths);
+    if (tmp_parsed_paths.empty()) {
+        return document;
+    }
+
+    parsed_paths = &tmp_parsed_paths;
+
+    if (!(*parsed_paths)[0].is_valid) {
+        return document;
+    }
+
+    if (UNLIKELY((*parsed_paths).size() == 1)) {
+        if (fntype == JSON_FUN_STRING) {
+            document->SetString(json_string.data(), json_string.size(), document->GetAllocator());
+        } else {
+            return document;
+        }
+    }
+
+    document->Parse(json_string.data(), json_string.size());
+    if (UNLIKELY(document->HasParseError())) {
+        // VLOG_CRITICAL << "Error at offset " << document->GetErrorOffset() << ": "
+        //         << GetParseError_En(document->GetParseError());
+        document->SetNull();
+        return document;
+    }
+
+    return match_value(*parsed_paths, document, document->GetAllocator());
+}
+
+template <typename NumberType>
+struct GetJsonNumberType {
+    using ReturnType = typename NumberType::ReturnType;
+    using ColumnType = typename NumberType::ColumnType;
+    using Container = typename ColumnType::Container;
+
+    static void get_json_impl(rapidjson::Value*& root, const std::string_view& json_string,
+                              const std::string_view& path_string, rapidjson::Document& document,
+                              typename NumberType::T& res, UInt8& null_map) {
+        if constexpr (std::is_same_v<double, typename NumberType::T>) {
+            root = get_json_object<JSON_FUN_DOUBLE>(json_string, path_string, &document);
+            handle_result<double>(root, res, null_map);
+        } else if constexpr (std::is_same_v<int32_t, typename NumberType::T>) {
+            root = get_json_object<JSON_FUN_DOUBLE>(json_string, path_string, &document);
+            handle_result<int32_t>(root, res, null_map);
+        } else if constexpr (std::is_same_v<int64_t, typename NumberType::T>) {
+            root = get_json_object<JSON_FUN_DOUBLE>(json_string, path_string, &document);
+            handle_result<int64_t>(root, res, null_map);
+        }
+    }
+    static void vector_vector(FunctionContext* context, const ColumnString::Chars& ldata,
+                              const ColumnString::Offsets& loffsets,
+                              const ColumnString::Chars& rdata,
+                              const ColumnString::Offsets& roffsets, Container& res,
+                              NullMap& null_map) {
+        size_t size = loffsets.size();
+        res.resize(size);
+        for (size_t i = 0; i < size; ++i) {
+            const char* l_raw_str = reinterpret_cast<const char*>(&ldata[loffsets[i - 1]]);
+            int l_str_size = loffsets[i] - loffsets[i - 1];
+            const char* r_raw_str = reinterpret_cast<const char*>(&rdata[roffsets[i - 1]]);
+            int r_str_size = roffsets[i] - roffsets[i - 1];
+            if (null_map[i]) {
+                res[i] = 0;
+                continue;
+            }
+
+            std::string_view json_string(l_raw_str, l_str_size);
+            std::string_view path_string(r_raw_str, r_str_size);
+            rapidjson::Document document;
+            rapidjson::Value* root = nullptr;
+
+            get_json_impl(root, json_string, path_string, document, res[i], null_map[i]);
+        }
+    }
+    static void vector_scalar(FunctionContext* context, const ColumnString::Chars& ldata,
+                              const ColumnString::Offsets& loffsets, const StringRef& rdata,
+                              Container& res, NullMap& null_map) {
+        size_t size = loffsets.size();
+        res.resize(size);
+        std::string_view path_string(rdata.data, rdata.size);
+        for (size_t i = 0; i < size; ++i) {
+            const char* l_raw_str = reinterpret_cast<const char*>(&ldata[loffsets[i - 1]]);
+            int l_str_size = loffsets[i] - loffsets[i - 1];
+            if (null_map[i]) {
+                res[i] = 0;
+                continue;
+            }
+            std::string_view json_string(l_raw_str, l_str_size);
+
+            rapidjson::Document document;
+            rapidjson::Value* root = nullptr;
+
+            get_json_impl(root, json_string, path_string, document, res[i], null_map[i]);
+        }
+    }
+    static void scalar_vector(FunctionContext* context, const StringRef& ldata,
+                              const ColumnString::Chars& rdata,
+                              const ColumnString::Offsets& roffsets, Container& res,
+                              NullMap& null_map) {
+        size_t size = roffsets.size();
+        res.resize(size);
+        std::string_view json_string(ldata.data, ldata.size);
+        for (size_t i = 0; i < size; ++i) {
+            const char* r_raw_str = reinterpret_cast<const char*>(&rdata[roffsets[i - 1]]);
+            int r_str_size = roffsets[i] - roffsets[i - 1];
+            if (null_map[i]) {
+                res[i] = 0;
+                continue;
+            }
+            std::string_view path_string(r_raw_str, r_str_size);
+            rapidjson::Document document;
+            rapidjson::Value* root = nullptr;
+
+            get_json_impl(root, json_string, path_string, document, res[i], null_map[i]);
+        }
+    }
+
+    template <typename T, std::enable_if_t<std::is_same_v<double, T>, T>* = nullptr>
+    static void handle_result(rapidjson::Value* root, T& res, uint8_t& res_null) {
+        if (root == nullptr || root->IsNull()) {
+            res = 0;
+            res_null = 1;
+        } else if (root->IsInt()) {
+            res = root->GetInt();
+        } else if (root->IsInt64()) {
+            res = root->GetInt64();
+        } else if (root->IsDouble()) {
+            res = root->GetDouble();
+        } else {
+            res_null = 1;
+        }
+    }
+
+    template <typename T, std::enable_if_t<std::is_same_v<int32_t, T>, T>* = nullptr>
+    static void handle_result(rapidjson::Value* root, int32_t& res, uint8_t& res_null) {
+        if (root != nullptr && root->IsInt()) {
+            res = root->GetInt();
+        } else {
+            res_null = 1;
+        }
+    }
+
+    template <typename T, std::enable_if_t<std::is_same_v<int64_t, T>, T>* = nullptr>
+    static void handle_result(rapidjson::Value* root, int64_t& res, uint8_t& res_null) {
+        if (root != nullptr && root->IsInt64()) {
+            res = root->GetInt64();
+        } else {
+            res_null = 1;
+        }
+    }
+};
+
+// Helper Class
+struct JsonNumberTypeDouble {
+    using T = Float64;
+    using ReturnType = DataTypeFloat64;
+    using ColumnType = ColumnVector<T>;
+};
+
+struct JsonNumberTypeInt {
+    using T = int32_t;
+    using ReturnType = DataTypeInt32;
+    using ColumnType = ColumnVector<T>;
+};
+
+struct JsonNumberTypeBigInt {
+    using T = int64_t;
+    using ReturnType = DataTypeInt64;
+    using ColumnType = ColumnVector<T>;
+};
+
+struct GetJsonDouble : public GetJsonNumberType<JsonNumberTypeDouble> {
+    static constexpr auto name = "get_json_double";
+    using ReturnType = typename JsonNumberTypeDouble::ReturnType;
+    using ColumnType = typename JsonNumberTypeDouble::ColumnType;
+};
+
+struct GetJsonInt : public GetJsonNumberType<JsonNumberTypeInt> {
+    static constexpr auto name = "get_json_int";
+    using ReturnType = typename JsonNumberTypeInt::ReturnType;
+    using ColumnType = typename JsonNumberTypeInt::ColumnType;
+};
+
+struct GetJsonBigInt : public GetJsonNumberType<JsonNumberTypeBigInt> {
+    static constexpr auto name = "get_json_bigint";
+    using ReturnType = typename JsonNumberTypeBigInt::ReturnType;
+    using ColumnType = typename JsonNumberTypeBigInt::ColumnType;
+};
+
+struct GetJsonString {
+    static constexpr auto name = "get_json_string";
+    using ReturnType = DataTypeString;
+    using ColumnType = ColumnString;
+    using Chars = ColumnString::Chars;
+    using Offsets = ColumnString::Offsets;
+    static void vector_vector(FunctionContext* context, const Chars& ldata, const Offsets& loffsets,
+                              const Chars& rdata, const Offsets& roffsets, Chars& res_data,
+                              Offsets& res_offsets, NullMap& null_map) {
+        size_t input_rows_count = loffsets.size();
+        res_offsets.resize(input_rows_count);
+
+        for (size_t i = 0; i < input_rows_count; ++i) {
+            if (null_map[i]) {
+                StringOP::push_null_string(i, res_data, res_offsets, null_map);
+                continue;
+            }
+            int l_size = loffsets[i] - loffsets[i - 1];
+            const auto l_raw = reinterpret_cast<const char*>(&ldata[loffsets[i - 1]]);
+            int r_size = roffsets[i] - roffsets[i - 1];
+            const auto r_raw = reinterpret_cast<const char*>(&rdata[roffsets[i - 1]]);
+
+            std::string_view json_string(l_raw, l_size);
+            std::string_view path_string(r_raw, r_size);
+
+            execute_impl(json_string, path_string, res_data, res_offsets, null_map, i);
+        }
+    }
+    static void vector_scalar(FunctionContext* context, const Chars& ldata, const Offsets& loffsets,
+                              const StringRef& rdata, Chars& res_data, Offsets& res_offsets,
+                              NullMap& null_map) {
+        size_t input_rows_count = loffsets.size();
+        res_offsets.resize(input_rows_count);
+
+        for (size_t i = 0; i < input_rows_count; ++i) {
+            if (null_map[i]) {
+                StringOP::push_null_string(i, res_data, res_offsets, null_map);
+                continue;
+            }
+            int l_size = loffsets[i] - loffsets[i - 1];
+            const auto l_raw = reinterpret_cast<const char*>(&ldata[loffsets[i - 1]]);
+
+            std::string_view json_string(l_raw, l_size);
+            std::string_view path_string(rdata.data, rdata.size);
+
+            execute_impl(json_string, path_string, res_data, res_offsets, null_map, i);
+        }
+    }
+    static void scalar_vector(FunctionContext* context, const StringRef& ldata, const Chars& rdata,
+                              const Offsets& roffsets, Chars& res_data, Offsets& res_offsets,
+                              NullMap& null_map) {
+        size_t input_rows_count = roffsets.size();
+        res_offsets.resize(input_rows_count);
+
+        for (size_t i = 0; i < input_rows_count; ++i) {
+            if (null_map[i]) {
+                StringOP::push_null_string(i, res_data, res_offsets, null_map);
+                continue;
+            }
+            int r_size = roffsets[i] - roffsets[i - 1];
+            const auto r_raw = reinterpret_cast<const char*>(&rdata[roffsets[i - 1]]);
+
+            std::string_view json_string(ldata.data, ldata.size);
+            std::string_view path_string(r_raw, r_size);
+
+            execute_impl(json_string, path_string, res_data, res_offsets, null_map, i);
+        }
+    }
+
+    static void execute_impl(const std::string_view& json_string,
+                             const std::string_view& path_string, Chars& res_data,
+                             Offsets& res_offsets, NullMap& null_map, size_t index_now) {
+        rapidjson::Document document;
+        rapidjson::Value* root = nullptr;
+
+        root = get_json_object<JSON_FUN_STRING>(json_string, path_string, &document);
+        const int max_string_len = 65535;
+
+        if (root == nullptr || root->IsNull()) {
+            StringOP::push_null_string(index_now, res_data, res_offsets, null_map);
+        } else if (root->IsString()) {
+            const auto ptr = root->GetString();
+            size_t len = strnlen(ptr, max_string_len);
+            StringOP::push_value_string(std::string_view(ptr, len), index_now, res_data,
+                                        res_offsets);
+        } else {
+            rapidjson::StringBuffer buf;
+            rapidjson::Writer<rapidjson::StringBuffer> writer(buf);
+            root->Accept(writer);
+
+            const auto ptr = buf.GetString();
+            size_t len = strnlen(ptr, max_string_len);
+            StringOP::push_value_string(std::string_view(ptr, len), index_now, res_data,
+                                        res_offsets);
+        }
+    }
+};
+
+template <int flag>
+struct JsonParser {
+    //string
+    static void update_value(StringParser::ParseResult& result, rapidjson::Value& value,
+                             StringRef data, rapidjson::Document::AllocatorType& allocator) {
+        value.SetString(data.data, data.size, allocator);
+    }
+};
+
+template <>
+struct JsonParser<'0'> {
+    // null
+    static void update_value(StringParser::ParseResult& result, rapidjson::Value& value,
+                             StringRef data, rapidjson::Document::AllocatorType& allocator) {
+        value.SetNull();
+    }
+};
+
+template <>
+struct JsonParser<'1'> {
+    // bool
+    static void update_value(StringParser::ParseResult& result, rapidjson::Value& value,
+                             StringRef data, rapidjson::Document::AllocatorType& allocator) {
+        DCHECK(data.size == 1 || strncmp(data.data, "true", 4) == 0 ||
+               strncmp(data.data, "false", 5) == 0);
+        value.SetBool((*data.data == '1' || *data.data == 't') ? true : false);
+    }
+};
+
+template <>
+struct JsonParser<'2'> {
+    // int
+    static void update_value(StringParser::ParseResult& result, rapidjson::Value& value,
+                             StringRef data, rapidjson::Document::AllocatorType& allocator) {
+        value.SetInt(StringParser::string_to_int<int32_t>(data.data, data.size, &result));
+    }
+};
+
+template <>
+struct JsonParser<'3'> {
+    // double
+    static void update_value(StringParser::ParseResult& result, rapidjson::Value& value,
+                             StringRef data, rapidjson::Document::AllocatorType& allocator) {
+        value.SetDouble(StringParser::string_to_float<double>(data.data, data.size, &result));
+    }
+};
+
+template <>
+struct JsonParser<'4'> {
+    // time
+    static void update_value(StringParser::ParseResult& result, rapidjson::Value& value,
+                             StringRef data, rapidjson::Document::AllocatorType& allocator) {
+        // remove double quotes, "xxx" -> xxx
+        value.SetString(data.data + 1, data.size - 2, allocator);
+    }
+};
+
+template <>
+struct JsonParser<'5'> {
+    // bigint
+    static void update_value(StringParser::ParseResult& result, rapidjson::Value& value,
+                             StringRef data, rapidjson::Document::AllocatorType& allocator) {
+        value.SetInt64(StringParser::string_to_int<int64_t>(data.data, data.size, &result));
+    }
+};
+
+template <int flag, typename Impl>
+struct ExecuteReducer {
+    template <typename... TArgs>
+    static void run(TArgs&&... args) {
+        Impl::template execute_type<JsonParser<flag>>(std::forward<TArgs>(args)...);
+    }
+};
+
+struct FunctionJsonArrayImpl {
+    static constexpr auto name = "json_array";
+
+    template <int flag>
+    using Reducer = ExecuteReducer<flag, FunctionJsonArrayImpl>;
+
+    static void execute_parse(const std::string& type_flags,
+                              const std::vector<const ColumnString*>& data_columns,
+                              std::vector<rapidjson::Value>& objects,
+                              rapidjson::Document::AllocatorType& allocator,
+                              const std::vector<const ColumnUInt8*>& nullmaps) {
+        for (int i = 0; i < data_columns.size() - 1; i++) {
+            constexpr_int_match<'0', '6', Reducer>::run(type_flags[i], objects, allocator,
+                                                        data_columns[i], nullmaps[i]);
+        }
+    }
+
+    template <typename TypeImpl>
+    static void execute_type(std::vector<rapidjson::Value>& objects,
+                             rapidjson::Document::AllocatorType& allocator,
+                             const ColumnString* data_column, const ColumnUInt8* nullmap) {
+        StringParser::ParseResult result;
+        rapidjson::Value value;
+
+        for (int i = 0; i < objects.size(); i++) {
+            if (nullmap != nullptr && nullmap->get_data()[i]) {
+                JsonParser<'0'>::update_value(result, value, data_column->get_data_at(i),
+                                              allocator);
+            } else {
+                TypeImpl::update_value(result, value, data_column->get_data_at(i), allocator);
+            }
+            objects[i].PushBack(value, allocator);
+        }
+    }
+};
+
+struct FunctionJsonObjectImpl {
+    static constexpr auto name = "json_object";
+
+    template <int flag>
+    using Reducer = ExecuteReducer<flag, FunctionJsonObjectImpl>;
+
+    static void execute_parse(std::string type_flags,
+                              const std::vector<const ColumnString*>& data_columns,
+                              std::vector<rapidjson::Value>& objects,
+                              rapidjson::Document::AllocatorType& allocator,
+                              const std::vector<const ColumnUInt8*>& nullmaps) {
+        for (auto& array_object : objects) {
+            array_object.SetObject();
+        }
+
+        for (int i = 0; i + 1 < data_columns.size() - 1; i += 2) {
+            constexpr_int_match<'0', '6', Reducer>::run(type_flags[i + 1], objects, allocator,
+                                                        data_columns[i], data_columns[i + 1],
+                                                        nullmaps[i + 1]);
+        }
+    }
+
+    template <typename TypeImpl>
+    static void execute_type(std::vector<rapidjson::Value>& objects,
+                             rapidjson::Document::AllocatorType& allocator,
+                             const ColumnString* key_column, const ColumnString* value_column,
+                             const ColumnUInt8* nullmap) {
+        StringParser::ParseResult result;
+        rapidjson::Value key;
+        rapidjson::Value value;
+        for (int i = 0; i < objects.size(); i++) {
+            JsonParser<'6'>::update_value(result, key, key_column->get_data_at(i),
+                                          allocator); // key always is string
+            if (nullmap != nullptr && nullmap->get_data()[i]) {
+                JsonParser<'0'>::update_value(result, value, value_column->get_data_at(i),
+                                              allocator);
+            } else {
+                TypeImpl::update_value(result, value, value_column->get_data_at(i), allocator);
+            }
+            objects[i].AddMember(key, value, allocator);
+        }
+    }
+};
+
+template <typename SpecificImpl>
+class FunctionJsonAlwaysNotNullable : public IFunction {
+public:
+    using IFunction::execute;
+
+    static constexpr auto name = SpecificImpl::name;
+
+    static FunctionPtr create() {
+        return std::make_shared<FunctionJsonAlwaysNotNullable<SpecificImpl>>();
+    }
+
+    bool use_default_implementation_for_nulls() const override { return false; }
+
+    String get_name() const override { return name; }
+
+    size_t get_number_of_arguments() const override { return 0; }
+
+    bool is_variadic() const override { return true; }
+
+    DataTypePtr get_return_type_impl(const DataTypes& arguments) const override {
+        return std::make_shared<DataTypeString>();
+    }
+
+    Status execute_impl(FunctionContext* context, Block& block, const ColumnNumbers& arguments,
+                        size_t result, size_t input_rows_count) override {
+        auto result_column = ColumnString::create();
+
+        std::vector<ColumnPtr> column_ptrs; // prevent converted column destruct
+        std::vector<const ColumnString*> data_columns;
+        std::vector<const ColumnUInt8*> nullmaps;
+        for (int i = 0; i < arguments.size(); i++) {
+            auto column = block.get_by_position(arguments[i]).column;
+            column_ptrs.push_back(column->convert_to_full_column_if_const());
+            const ColumnNullable* col_nullable =
+                    check_and_get_column<ColumnNullable>(column_ptrs.back().get());
+            if (col_nullable) {
+                const ColumnUInt8* col_nullmap = check_and_get_column<ColumnUInt8>(
+                        col_nullable->get_null_map_column_ptr().get());
+                nullmaps.push_back(col_nullmap);
+                const ColumnString* col = check_and_get_column<ColumnString>(
+                        col_nullable->get_nested_column_ptr().get());
+                data_columns.push_back(col);
+            } else {
+                nullmaps.push_back(nullptr);
+                data_columns.push_back(assert_cast<const ColumnString*>(column_ptrs.back().get()));
+            }
+        }
+        execute(data_columns, *assert_cast<ColumnString*>(result_column.get()), input_rows_count,
+                nullmaps);
+        block.get_by_position(result).column = std::move(result_column);
+        return Status::OK();
+    }
+
+    static void execute(const std::vector<const ColumnString*>& data_columns,
+                        ColumnString& result_column, size_t input_rows_count,
+                        const std::vector<const ColumnUInt8*> nullmaps) {
+        std::string type_flags = data_columns.back()->get_data_at(0).to_string();
+
+        rapidjson::Document document;
+        rapidjson::Document::AllocatorType& allocator = document.GetAllocator();
+
+        std::vector<rapidjson::Value> objects;
+        for (int i = 0; i < input_rows_count; i++) {
+            objects.emplace_back(rapidjson::kArrayType);
+        }
+
+        SpecificImpl::execute_parse(type_flags, data_columns, objects, allocator, nullmaps);
+
+        rapidjson::StringBuffer buf;
+        rapidjson::Writer<rapidjson::StringBuffer> writer(buf);
+
+        for (int i = 0; i < input_rows_count; i++) {
+            buf.Clear();
+            writer.Reset(buf);
+            objects[i].Accept(writer);
+            result_column.insert_data(buf.GetString(), buf.GetSize());
+        }
+    }
+};
+
+struct FunctionJsonQuoteImpl {
+    static constexpr auto name = "json_quote";
+
+    static void execute(const std::vector<const ColumnString*>& data_columns,
+                        ColumnString& result_column, size_t input_rows_count) {
+        rapidjson::Document document;
+        rapidjson::Document::AllocatorType& allocator = document.GetAllocator();
+
+        rapidjson::Value value;
+
+        rapidjson::StringBuffer buf;
+        rapidjson::Writer<rapidjson::StringBuffer> writer(buf);
+
+        for (int i = 0; i < input_rows_count; i++) {
+            StringRef data = data_columns[0]->get_data_at(i);
+            value.SetString(data.data, data.size, allocator);
+
+            buf.Clear();
+            value.Accept(writer);
+            result_column.insert_data(buf.GetString(), buf.GetSize());
+        }
+    }
+};
+
+struct FunctionJsonExtractImpl {
+    static constexpr auto name = "json_extract";
+
+    static rapidjson::Value parse_json(const ColumnString* json_col, const ColumnString* path_col,
+                                       rapidjson::Document::AllocatorType& allocator,
+                                       const int row) {
+        rapidjson::Value value;
+        rapidjson::Document document;
+
+        const auto obj = json_col->get_data_at(row);
+        std::string_view json_string(obj.data, obj.size);
+        const auto path = path_col->get_data_at(row);
+        std::string_view path_string(path.data, path.size);
+
+        auto root = get_json_object<JSON_FUN_STRING>(json_string, path_string, &document);
+        if (root != nullptr) {
+            value.CopyFrom(*root, allocator);
+        }
+        return value;
+    }
+
+    static void execute(const std::vector<const ColumnString*>& data_columns,
+                        ColumnString& result_column, size_t input_rows_count) {
+        rapidjson::Document document;
+        rapidjson::Document::AllocatorType& allocator = document.GetAllocator();
+        rapidjson::StringBuffer buf;
+        rapidjson::Writer<rapidjson::StringBuffer> writer(buf);
+
+        const auto json_col = data_columns[0];
+        for (size_t row = 0; row < input_rows_count; row++) {
+            rapidjson::Value value;
+            if (data_columns.size() == 2) {
+                value = parse_json(json_col, data_columns[1], allocator, row);
+            } else {
+                value.SetArray();
+                value.Reserve(data_columns.size() - 1, allocator);
+                for (size_t col = 1; col < data_columns.size(); ++col) {
+                    value.PushBack(parse_json(json_col, data_columns[col], allocator, row),
+                                   allocator);
+                }
+            }
+
+            // write value as string
+            buf.Clear();
+            writer.Reset(buf);
+            value.Accept(writer);
+            result_column.insert_data(buf.GetString(), buf.GetSize());
+        }
+    }
+};
+
+template <typename Impl>
+class FunctionJson : public IFunction {
+public:
+    static constexpr auto name = Impl::name;
+
+    static FunctionPtr create() { return std::make_shared<FunctionJson<Impl>>(); }
+
+    String get_name() const override { return name; }
+
+    size_t get_number_of_arguments() const override { return 0; }
+
+    bool is_variadic() const override { return true; }
+
+    DataTypePtr get_return_type_impl(const DataTypes& arguments) const override {
+        return std::make_shared<DataTypeString>();
+    }
+
+    Status execute_impl(FunctionContext* context, Block& block, const ColumnNumbers& arguments,
+                        size_t result, size_t input_rows_count) override {
+        auto result_column = ColumnString::create();
+
+        std::vector<ColumnPtr> column_ptrs; // prevent converted column destruct
+        std::vector<const ColumnString*> data_columns;
+        for (int i = 0; i < arguments.size(); i++) {
+            column_ptrs.push_back(
+                    block.get_by_position(arguments[i]).column->convert_to_full_column_if_const());
+            data_columns.push_back(assert_cast<const ColumnString*>(column_ptrs.back().get()));
+        }
+
+        Impl::execute(data_columns, *assert_cast<ColumnString*>(result_column.get()),
+                      input_rows_count);
+        block.get_by_position(result).column = std::move(result_column);
+        return Status::OK();
+    }
+};
+
+using FunctionGetJsonDouble = FunctionBinaryStringOperateToNullType<GetJsonDouble>;
+using FunctionGetJsonInt = FunctionBinaryStringOperateToNullType<GetJsonInt>;
+using FunctionGetJsonBigInt = FunctionBinaryStringOperateToNullType<GetJsonBigInt>;
+using FunctionGetJsonString = FunctionBinaryStringOperateToNullType<GetJsonString>;
+
+class FunctionJsonValid : public IFunction {
+public:
+    static constexpr auto name = "json_valid";
+    static FunctionPtr create() { return std::make_shared<FunctionJsonValid>(); }
+
+    String get_name() const override { return name; }

Review Comment:
   warning: function 'get_name' should be marked [[nodiscard]] [modernize-use-nodiscard]
   
   ```suggestion
       [[nodiscard]] String get_name() const override { return name; }
   ```
   



##########
function_json.cpp:
##########
@@ -0,0 +1,1320 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#include <rapidjson/allocators.h>
+#include <rapidjson/document.h>
+#include <rapidjson/encodings.h>
+#include <rapidjson/pointer.h>
+#include <rapidjson/rapidjson.h>
+#include <rapidjson/stringbuffer.h>
+#include <rapidjson/writer.h>
+#include <re2/re2.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <algorithm>
+#include <boost/iterator/iterator_facade.hpp>
+#include <boost/token_functions.hpp>
+#include <boost/tokenizer.hpp>
+#include <memory>
+#include <string>
+#include <string_view>
+#include <type_traits>
+#include <utility>
+#include <vector>
+
+// IWYU pragma: no_include <opentelemetry/common/threadlocal.h>
+#include "common/compiler_util.h" // IWYU pragma: keep
+#include "common/status.h"
+#include "exprs/json_functions.h"
+#ifdef __AVX2__
+#include "util/jsonb_parser_simd.h"
+#else
+#include "util/jsonb_parser.h"
+#endif
+#include "util/string_parser.hpp"
+#include "util/string_util.h"
+#include "vec/aggregate_functions/aggregate_function.h"
+#include "vec/columns/column.h"
+#include "vec/columns/column_nullable.h"
+#include "vec/columns/column_string.h"
+#include "vec/columns/column_vector.h"
+#include "vec/columns/columns_number.h"
+#include "vec/common/assert_cast.h"
+#include "vec/common/string_ref.h"
+#include "vec/core/block.h"
+#include "vec/core/column_numbers.h"
+#include "vec/core/column_with_type_and_name.h"
+#include "vec/core/types.h"
+#include "vec/data_types/data_type.h"
+#include "vec/data_types/data_type_nullable.h"
+#include "vec/data_types/data_type_number.h"
+#include "vec/data_types/data_type_string.h"
+#include "vec/functions/function.h"
+#include "vec/functions/function_string.h"
+#include "vec/functions/function_totype.h"
+#include "vec/functions/simple_function_factory.h"
+#include "vec/utils/template_helpers.hpp"
+
+namespace doris {
+class FunctionContext;
+} // namespace doris
+
+namespace doris::vectorized {
+static const re2::RE2 JSON_PATTERN("^([^\\\"\\[\\]]*)(?:\\[([0-9]+|\\*)\\])?");
+
+template <typename T, typename U>
+void char_split(std::vector<T>& res, const U& var, char p) {
+    int start = 0;
+    int pos = start;
+    int end = var.length();
+    while (pos < end) {
+        while (var[pos] != p && pos < end) {
+            pos++;
+        }
+        res.emplace_back(&var[start], pos - start);
+        pos++;
+        start = pos;
+    }
+}
+
+// T = std::vector<std::string>
+// TODO: update RE2 to support std::vector<std::string_view>
+template <typename T>
+void get_parsed_paths(const T& path_exprs, std::vector<JsonPath>* parsed_paths) {
+    if (path_exprs.empty()) {
+        return;
+    }
+
+    if (path_exprs[0] != "$") {
+        parsed_paths->emplace_back("", -1, false);
+    } else {
+        parsed_paths->emplace_back("$", -1, true);
+    }
+
+    for (int i = 1; i < path_exprs.size(); i++) {
+        std::string col;
+        std::string index;
+        if (UNLIKELY(!RE2::FullMatch(path_exprs[i], JSON_PATTERN, &col, &index))) {
+            parsed_paths->emplace_back("", -1, false);
+        } else {
+            int idx = -1;
+            if (!index.empty()) {
+                if (index == "*") {
+                    idx = -2;
+                } else {
+                    idx = atoi(index.c_str());
+                }
+            }
+            parsed_paths->emplace_back(col, idx, true);
+        }
+    }
+}
+
+rapidjson::Value* match_value(const std::vector<JsonPath>& parsed_paths, rapidjson::Value* document,
+                              rapidjson::Document::AllocatorType& mem_allocator,
+                              bool is_insert_null = false) {
+    rapidjson::Value* root = document;
+    rapidjson::Value* array_obj = nullptr;
+    for (int i = 1; i < parsed_paths.size(); i++) {
+        if (root == nullptr || root->IsNull()) {
+            return nullptr;
+        }
+
+        if (UNLIKELY(!parsed_paths[i].is_valid)) {
+            return nullptr;
+        }
+
+        const std::string& col = parsed_paths[i].key;
+        int index = parsed_paths[i].idx;
+        if (LIKELY(!col.empty())) {
+            if (root->IsArray()) {
+                array_obj = static_cast<rapidjson::Value*>(
+                        mem_allocator.Malloc(sizeof(rapidjson::Value)));
+                array_obj->SetArray();
+                bool is_null = true;
+
+                // if array ,loop the array,find out all Objects,then find the results from the objects
+                for (int j = 0; j < root->Size(); j++) {
+                    rapidjson::Value* json_elem = &((*root)[j]);
+
+                    if (json_elem->IsArray() || json_elem->IsNull()) {
+                        continue;
+                    } else {
+                        if (!json_elem->IsObject()) {
+                            continue;
+                        }
+                        if (!json_elem->HasMember(col.c_str())) {
+                            if (is_insert_null) { // not found item, then insert a null object.
+                                is_null = false;
+                                rapidjson::Value nullObject(rapidjson::kNullType);
+                                array_obj->PushBack(nullObject, mem_allocator);
+                            }
+                            continue;
+                        }
+                        rapidjson::Value* obj = &((*json_elem)[col.c_str()]);
+                        if (obj->IsArray()) {
+                            is_null = false;
+                            for (int k = 0; k < obj->Size(); k++) {
+                                array_obj->PushBack((*obj)[k], mem_allocator);
+                            }
+                        } else if (!obj->IsNull()) {
+                            is_null = false;
+                            array_obj->PushBack(*obj, mem_allocator);
+                        }
+                    }
+                }
+
+                root = is_null ? &(array_obj->SetNull()) : array_obj;
+            } else if (root->IsObject()) {
+                if (!root->HasMember(col.c_str())) {
+                    return nullptr;
+                } else {
+                    root = &((*root)[col.c_str()]);
+                }
+            } else {
+                // root is not a nested type, return NULL
+                return nullptr;
+            }
+        }
+
+        if (UNLIKELY(index != -1)) {
+            // judge the rapidjson:Value, which base the top's result,
+            // if not array return NULL;else get the index value from the array
+            if (root->IsArray()) {
+                if (root->IsNull()) {
+                    return nullptr;
+                } else if (index == -2) {
+                    // [*]
+                    array_obj = static_cast<rapidjson::Value*>(
+                            mem_allocator.Malloc(sizeof(rapidjson::Value)));
+                    array_obj->SetArray();
+
+                    for (int j = 0; j < root->Size(); j++) {
+                        rapidjson::Value v;
+                        v.CopyFrom((*root)[j], mem_allocator);
+                        array_obj->PushBack(v, mem_allocator);
+                    }
+                    root = array_obj;
+                } else if (index >= root->Size()) {
+                    return nullptr;
+                } else {
+                    root = &((*root)[index]);
+                }
+            } else {
+                return nullptr;
+            }
+        }
+    }
+    return root;
+}
+
+template <JsonFunctionType fntype>
+rapidjson::Value* get_json_object(std::string_view json_string, std::string_view path_string,
+                                  rapidjson::Document* document) {
+    std::vector<JsonPath>* parsed_paths;
+    std::vector<JsonPath> tmp_parsed_paths;
+
+#ifdef USE_LIBCPP
+    std::string s(path_string);
+    auto tok = get_json_token(s);
+#else
+    auto tok = get_json_token(path_string);
+#endif
+    std::vector<std::string> paths(tok.begin(), tok.end());
+    get_parsed_paths(paths, &tmp_parsed_paths);
+    if (tmp_parsed_paths.empty()) {
+        return document;
+    }
+
+    parsed_paths = &tmp_parsed_paths;
+
+    if (!(*parsed_paths)[0].is_valid) {
+        return document;
+    }
+
+    if (UNLIKELY((*parsed_paths).size() == 1)) {
+        if (fntype == JSON_FUN_STRING) {
+            document->SetString(json_string.data(), json_string.size(), document->GetAllocator());
+        } else {
+            return document;
+        }
+    }
+
+    document->Parse(json_string.data(), json_string.size());
+    if (UNLIKELY(document->HasParseError())) {
+        // VLOG_CRITICAL << "Error at offset " << document->GetErrorOffset() << ": "
+        //         << GetParseError_En(document->GetParseError());
+        document->SetNull();
+        return document;
+    }
+
+    return match_value(*parsed_paths, document, document->GetAllocator());
+}
+
+template <typename NumberType>
+struct GetJsonNumberType {
+    using ReturnType = typename NumberType::ReturnType;
+    using ColumnType = typename NumberType::ColumnType;
+    using Container = typename ColumnType::Container;
+
+    static void get_json_impl(rapidjson::Value*& root, const std::string_view& json_string,
+                              const std::string_view& path_string, rapidjson::Document& document,
+                              typename NumberType::T& res, UInt8& null_map) {
+        if constexpr (std::is_same_v<double, typename NumberType::T>) {
+            root = get_json_object<JSON_FUN_DOUBLE>(json_string, path_string, &document);
+            handle_result<double>(root, res, null_map);
+        } else if constexpr (std::is_same_v<int32_t, typename NumberType::T>) {
+            root = get_json_object<JSON_FUN_DOUBLE>(json_string, path_string, &document);
+            handle_result<int32_t>(root, res, null_map);
+        } else if constexpr (std::is_same_v<int64_t, typename NumberType::T>) {
+            root = get_json_object<JSON_FUN_DOUBLE>(json_string, path_string, &document);
+            handle_result<int64_t>(root, res, null_map);
+        }
+    }
+    static void vector_vector(FunctionContext* context, const ColumnString::Chars& ldata,
+                              const ColumnString::Offsets& loffsets,
+                              const ColumnString::Chars& rdata,
+                              const ColumnString::Offsets& roffsets, Container& res,
+                              NullMap& null_map) {
+        size_t size = loffsets.size();
+        res.resize(size);
+        for (size_t i = 0; i < size; ++i) {
+            const char* l_raw_str = reinterpret_cast<const char*>(&ldata[loffsets[i - 1]]);
+            int l_str_size = loffsets[i] - loffsets[i - 1];
+            const char* r_raw_str = reinterpret_cast<const char*>(&rdata[roffsets[i - 1]]);
+            int r_str_size = roffsets[i] - roffsets[i - 1];
+            if (null_map[i]) {
+                res[i] = 0;
+                continue;
+            }
+
+            std::string_view json_string(l_raw_str, l_str_size);
+            std::string_view path_string(r_raw_str, r_str_size);
+            rapidjson::Document document;
+            rapidjson::Value* root = nullptr;
+
+            get_json_impl(root, json_string, path_string, document, res[i], null_map[i]);
+        }
+    }
+    static void vector_scalar(FunctionContext* context, const ColumnString::Chars& ldata,
+                              const ColumnString::Offsets& loffsets, const StringRef& rdata,
+                              Container& res, NullMap& null_map) {
+        size_t size = loffsets.size();
+        res.resize(size);
+        std::string_view path_string(rdata.data, rdata.size);
+        for (size_t i = 0; i < size; ++i) {
+            const char* l_raw_str = reinterpret_cast<const char*>(&ldata[loffsets[i - 1]]);
+            int l_str_size = loffsets[i] - loffsets[i - 1];
+            if (null_map[i]) {
+                res[i] = 0;
+                continue;
+            }
+            std::string_view json_string(l_raw_str, l_str_size);
+
+            rapidjson::Document document;
+            rapidjson::Value* root = nullptr;
+
+            get_json_impl(root, json_string, path_string, document, res[i], null_map[i]);
+        }
+    }
+    static void scalar_vector(FunctionContext* context, const StringRef& ldata,
+                              const ColumnString::Chars& rdata,
+                              const ColumnString::Offsets& roffsets, Container& res,
+                              NullMap& null_map) {
+        size_t size = roffsets.size();
+        res.resize(size);
+        std::string_view json_string(ldata.data, ldata.size);
+        for (size_t i = 0; i < size; ++i) {
+            const char* r_raw_str = reinterpret_cast<const char*>(&rdata[roffsets[i - 1]]);
+            int r_str_size = roffsets[i] - roffsets[i - 1];
+            if (null_map[i]) {
+                res[i] = 0;
+                continue;
+            }
+            std::string_view path_string(r_raw_str, r_str_size);
+            rapidjson::Document document;
+            rapidjson::Value* root = nullptr;
+
+            get_json_impl(root, json_string, path_string, document, res[i], null_map[i]);
+        }
+    }
+
+    template <typename T, std::enable_if_t<std::is_same_v<double, T>, T>* = nullptr>
+    static void handle_result(rapidjson::Value* root, T& res, uint8_t& res_null) {
+        if (root == nullptr || root->IsNull()) {
+            res = 0;
+            res_null = 1;
+        } else if (root->IsInt()) {
+            res = root->GetInt();
+        } else if (root->IsInt64()) {
+            res = root->GetInt64();
+        } else if (root->IsDouble()) {
+            res = root->GetDouble();
+        } else {
+            res_null = 1;
+        }
+    }
+
+    template <typename T, std::enable_if_t<std::is_same_v<int32_t, T>, T>* = nullptr>
+    static void handle_result(rapidjson::Value* root, int32_t& res, uint8_t& res_null) {
+        if (root != nullptr && root->IsInt()) {
+            res = root->GetInt();
+        } else {
+            res_null = 1;
+        }
+    }
+
+    template <typename T, std::enable_if_t<std::is_same_v<int64_t, T>, T>* = nullptr>
+    static void handle_result(rapidjson::Value* root, int64_t& res, uint8_t& res_null) {
+        if (root != nullptr && root->IsInt64()) {
+            res = root->GetInt64();
+        } else {
+            res_null = 1;
+        }
+    }
+};
+
+// Helper Class
+struct JsonNumberTypeDouble {
+    using T = Float64;
+    using ReturnType = DataTypeFloat64;
+    using ColumnType = ColumnVector<T>;
+};
+
+struct JsonNumberTypeInt {
+    using T = int32_t;
+    using ReturnType = DataTypeInt32;
+    using ColumnType = ColumnVector<T>;
+};
+
+struct JsonNumberTypeBigInt {
+    using T = int64_t;
+    using ReturnType = DataTypeInt64;
+    using ColumnType = ColumnVector<T>;
+};
+
+struct GetJsonDouble : public GetJsonNumberType<JsonNumberTypeDouble> {
+    static constexpr auto name = "get_json_double";
+    using ReturnType = typename JsonNumberTypeDouble::ReturnType;
+    using ColumnType = typename JsonNumberTypeDouble::ColumnType;
+};
+
+struct GetJsonInt : public GetJsonNumberType<JsonNumberTypeInt> {
+    static constexpr auto name = "get_json_int";
+    using ReturnType = typename JsonNumberTypeInt::ReturnType;
+    using ColumnType = typename JsonNumberTypeInt::ColumnType;
+};
+
+struct GetJsonBigInt : public GetJsonNumberType<JsonNumberTypeBigInt> {
+    static constexpr auto name = "get_json_bigint";
+    using ReturnType = typename JsonNumberTypeBigInt::ReturnType;
+    using ColumnType = typename JsonNumberTypeBigInt::ColumnType;
+};
+
+struct GetJsonString {
+    static constexpr auto name = "get_json_string";
+    using ReturnType = DataTypeString;
+    using ColumnType = ColumnString;
+    using Chars = ColumnString::Chars;
+    using Offsets = ColumnString::Offsets;
+    static void vector_vector(FunctionContext* context, const Chars& ldata, const Offsets& loffsets,
+                              const Chars& rdata, const Offsets& roffsets, Chars& res_data,
+                              Offsets& res_offsets, NullMap& null_map) {
+        size_t input_rows_count = loffsets.size();
+        res_offsets.resize(input_rows_count);
+
+        for (size_t i = 0; i < input_rows_count; ++i) {
+            if (null_map[i]) {
+                StringOP::push_null_string(i, res_data, res_offsets, null_map);
+                continue;
+            }
+            int l_size = loffsets[i] - loffsets[i - 1];
+            const auto l_raw = reinterpret_cast<const char*>(&ldata[loffsets[i - 1]]);
+            int r_size = roffsets[i] - roffsets[i - 1];
+            const auto r_raw = reinterpret_cast<const char*>(&rdata[roffsets[i - 1]]);
+
+            std::string_view json_string(l_raw, l_size);
+            std::string_view path_string(r_raw, r_size);
+
+            execute_impl(json_string, path_string, res_data, res_offsets, null_map, i);
+        }
+    }
+    static void vector_scalar(FunctionContext* context, const Chars& ldata, const Offsets& loffsets,
+                              const StringRef& rdata, Chars& res_data, Offsets& res_offsets,
+                              NullMap& null_map) {
+        size_t input_rows_count = loffsets.size();
+        res_offsets.resize(input_rows_count);
+
+        for (size_t i = 0; i < input_rows_count; ++i) {
+            if (null_map[i]) {
+                StringOP::push_null_string(i, res_data, res_offsets, null_map);
+                continue;
+            }
+            int l_size = loffsets[i] - loffsets[i - 1];
+            const auto l_raw = reinterpret_cast<const char*>(&ldata[loffsets[i - 1]]);
+
+            std::string_view json_string(l_raw, l_size);
+            std::string_view path_string(rdata.data, rdata.size);
+
+            execute_impl(json_string, path_string, res_data, res_offsets, null_map, i);
+        }
+    }
+    static void scalar_vector(FunctionContext* context, const StringRef& ldata, const Chars& rdata,
+                              const Offsets& roffsets, Chars& res_data, Offsets& res_offsets,
+                              NullMap& null_map) {
+        size_t input_rows_count = roffsets.size();
+        res_offsets.resize(input_rows_count);
+
+        for (size_t i = 0; i < input_rows_count; ++i) {
+            if (null_map[i]) {
+                StringOP::push_null_string(i, res_data, res_offsets, null_map);
+                continue;
+            }
+            int r_size = roffsets[i] - roffsets[i - 1];
+            const auto r_raw = reinterpret_cast<const char*>(&rdata[roffsets[i - 1]]);
+
+            std::string_view json_string(ldata.data, ldata.size);
+            std::string_view path_string(r_raw, r_size);
+
+            execute_impl(json_string, path_string, res_data, res_offsets, null_map, i);
+        }
+    }
+
+    static void execute_impl(const std::string_view& json_string,
+                             const std::string_view& path_string, Chars& res_data,
+                             Offsets& res_offsets, NullMap& null_map, size_t index_now) {
+        rapidjson::Document document;
+        rapidjson::Value* root = nullptr;
+
+        root = get_json_object<JSON_FUN_STRING>(json_string, path_string, &document);
+        const int max_string_len = 65535;
+
+        if (root == nullptr || root->IsNull()) {
+            StringOP::push_null_string(index_now, res_data, res_offsets, null_map);
+        } else if (root->IsString()) {
+            const auto ptr = root->GetString();
+            size_t len = strnlen(ptr, max_string_len);
+            StringOP::push_value_string(std::string_view(ptr, len), index_now, res_data,
+                                        res_offsets);
+        } else {
+            rapidjson::StringBuffer buf;
+            rapidjson::Writer<rapidjson::StringBuffer> writer(buf);
+            root->Accept(writer);
+
+            const auto ptr = buf.GetString();
+            size_t len = strnlen(ptr, max_string_len);
+            StringOP::push_value_string(std::string_view(ptr, len), index_now, res_data,
+                                        res_offsets);
+        }
+    }
+};
+
+template <int flag>
+struct JsonParser {
+    //string
+    static void update_value(StringParser::ParseResult& result, rapidjson::Value& value,
+                             StringRef data, rapidjson::Document::AllocatorType& allocator) {
+        value.SetString(data.data, data.size, allocator);
+    }
+};
+
+template <>
+struct JsonParser<'0'> {
+    // null
+    static void update_value(StringParser::ParseResult& result, rapidjson::Value& value,
+                             StringRef data, rapidjson::Document::AllocatorType& allocator) {
+        value.SetNull();
+    }
+};
+
+template <>
+struct JsonParser<'1'> {
+    // bool
+    static void update_value(StringParser::ParseResult& result, rapidjson::Value& value,
+                             StringRef data, rapidjson::Document::AllocatorType& allocator) {
+        DCHECK(data.size == 1 || strncmp(data.data, "true", 4) == 0 ||
+               strncmp(data.data, "false", 5) == 0);
+        value.SetBool((*data.data == '1' || *data.data == 't') ? true : false);
+    }
+};
+
+template <>
+struct JsonParser<'2'> {
+    // int
+    static void update_value(StringParser::ParseResult& result, rapidjson::Value& value,
+                             StringRef data, rapidjson::Document::AllocatorType& allocator) {
+        value.SetInt(StringParser::string_to_int<int32_t>(data.data, data.size, &result));
+    }
+};
+
+template <>
+struct JsonParser<'3'> {
+    // double
+    static void update_value(StringParser::ParseResult& result, rapidjson::Value& value,
+                             StringRef data, rapidjson::Document::AllocatorType& allocator) {
+        value.SetDouble(StringParser::string_to_float<double>(data.data, data.size, &result));
+    }
+};
+
+template <>
+struct JsonParser<'4'> {
+    // time
+    static void update_value(StringParser::ParseResult& result, rapidjson::Value& value,
+                             StringRef data, rapidjson::Document::AllocatorType& allocator) {
+        // remove double quotes, "xxx" -> xxx
+        value.SetString(data.data + 1, data.size - 2, allocator);
+    }
+};
+
+template <>
+struct JsonParser<'5'> {
+    // bigint
+    static void update_value(StringParser::ParseResult& result, rapidjson::Value& value,
+                             StringRef data, rapidjson::Document::AllocatorType& allocator) {
+        value.SetInt64(StringParser::string_to_int<int64_t>(data.data, data.size, &result));
+    }
+};
+
+template <int flag, typename Impl>
+struct ExecuteReducer {
+    template <typename... TArgs>
+    static void run(TArgs&&... args) {
+        Impl::template execute_type<JsonParser<flag>>(std::forward<TArgs>(args)...);
+    }
+};
+
+struct FunctionJsonArrayImpl {
+    static constexpr auto name = "json_array";
+
+    template <int flag>
+    using Reducer = ExecuteReducer<flag, FunctionJsonArrayImpl>;
+
+    static void execute_parse(const std::string& type_flags,
+                              const std::vector<const ColumnString*>& data_columns,
+                              std::vector<rapidjson::Value>& objects,
+                              rapidjson::Document::AllocatorType& allocator,
+                              const std::vector<const ColumnUInt8*>& nullmaps) {
+        for (int i = 0; i < data_columns.size() - 1; i++) {
+            constexpr_int_match<'0', '6', Reducer>::run(type_flags[i], objects, allocator,
+                                                        data_columns[i], nullmaps[i]);
+        }
+    }
+
+    template <typename TypeImpl>
+    static void execute_type(std::vector<rapidjson::Value>& objects,
+                             rapidjson::Document::AllocatorType& allocator,
+                             const ColumnString* data_column, const ColumnUInt8* nullmap) {
+        StringParser::ParseResult result;
+        rapidjson::Value value;
+
+        for (int i = 0; i < objects.size(); i++) {
+            if (nullmap != nullptr && nullmap->get_data()[i]) {
+                JsonParser<'0'>::update_value(result, value, data_column->get_data_at(i),
+                                              allocator);
+            } else {
+                TypeImpl::update_value(result, value, data_column->get_data_at(i), allocator);
+            }
+            objects[i].PushBack(value, allocator);
+        }
+    }
+};
+
+struct FunctionJsonObjectImpl {
+    static constexpr auto name = "json_object";
+
+    template <int flag>
+    using Reducer = ExecuteReducer<flag, FunctionJsonObjectImpl>;
+
+    static void execute_parse(std::string type_flags,
+                              const std::vector<const ColumnString*>& data_columns,
+                              std::vector<rapidjson::Value>& objects,
+                              rapidjson::Document::AllocatorType& allocator,
+                              const std::vector<const ColumnUInt8*>& nullmaps) {
+        for (auto& array_object : objects) {
+            array_object.SetObject();
+        }
+
+        for (int i = 0; i + 1 < data_columns.size() - 1; i += 2) {
+            constexpr_int_match<'0', '6', Reducer>::run(type_flags[i + 1], objects, allocator,
+                                                        data_columns[i], data_columns[i + 1],
+                                                        nullmaps[i + 1]);
+        }
+    }
+
+    template <typename TypeImpl>
+    static void execute_type(std::vector<rapidjson::Value>& objects,
+                             rapidjson::Document::AllocatorType& allocator,
+                             const ColumnString* key_column, const ColumnString* value_column,
+                             const ColumnUInt8* nullmap) {
+        StringParser::ParseResult result;
+        rapidjson::Value key;
+        rapidjson::Value value;
+        for (int i = 0; i < objects.size(); i++) {
+            JsonParser<'6'>::update_value(result, key, key_column->get_data_at(i),
+                                          allocator); // key always is string
+            if (nullmap != nullptr && nullmap->get_data()[i]) {
+                JsonParser<'0'>::update_value(result, value, value_column->get_data_at(i),
+                                              allocator);
+            } else {
+                TypeImpl::update_value(result, value, value_column->get_data_at(i), allocator);
+            }
+            objects[i].AddMember(key, value, allocator);
+        }
+    }
+};
+
+template <typename SpecificImpl>
+class FunctionJsonAlwaysNotNullable : public IFunction {
+public:
+    using IFunction::execute;
+
+    static constexpr auto name = SpecificImpl::name;
+
+    static FunctionPtr create() {
+        return std::make_shared<FunctionJsonAlwaysNotNullable<SpecificImpl>>();
+    }
+
+    bool use_default_implementation_for_nulls() const override { return false; }
+
+    String get_name() const override { return name; }
+
+    size_t get_number_of_arguments() const override { return 0; }
+
+    bool is_variadic() const override { return true; }
+
+    DataTypePtr get_return_type_impl(const DataTypes& arguments) const override {

Review Comment:
   warning: function 'get_return_type_impl' should be marked [[nodiscard]] [modernize-use-nodiscard]
   
   ```suggestion
       [[nodiscard]] DataTypePtr get_return_type_impl(const DataTypes& arguments) const override {
   ```
   



##########
function_json.cpp:
##########
@@ -0,0 +1,1320 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#include <rapidjson/allocators.h>
+#include <rapidjson/document.h>
+#include <rapidjson/encodings.h>
+#include <rapidjson/pointer.h>
+#include <rapidjson/rapidjson.h>
+#include <rapidjson/stringbuffer.h>
+#include <rapidjson/writer.h>
+#include <re2/re2.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <algorithm>
+#include <boost/iterator/iterator_facade.hpp>
+#include <boost/token_functions.hpp>
+#include <boost/tokenizer.hpp>
+#include <memory>
+#include <string>
+#include <string_view>
+#include <type_traits>
+#include <utility>
+#include <vector>
+
+// IWYU pragma: no_include <opentelemetry/common/threadlocal.h>
+#include "common/compiler_util.h" // IWYU pragma: keep
+#include "common/status.h"
+#include "exprs/json_functions.h"
+#ifdef __AVX2__
+#include "util/jsonb_parser_simd.h"
+#else
+#include "util/jsonb_parser.h"
+#endif
+#include "util/string_parser.hpp"
+#include "util/string_util.h"
+#include "vec/aggregate_functions/aggregate_function.h"
+#include "vec/columns/column.h"
+#include "vec/columns/column_nullable.h"
+#include "vec/columns/column_string.h"
+#include "vec/columns/column_vector.h"
+#include "vec/columns/columns_number.h"
+#include "vec/common/assert_cast.h"
+#include "vec/common/string_ref.h"
+#include "vec/core/block.h"
+#include "vec/core/column_numbers.h"
+#include "vec/core/column_with_type_and_name.h"
+#include "vec/core/types.h"
+#include "vec/data_types/data_type.h"
+#include "vec/data_types/data_type_nullable.h"
+#include "vec/data_types/data_type_number.h"
+#include "vec/data_types/data_type_string.h"
+#include "vec/functions/function.h"
+#include "vec/functions/function_string.h"
+#include "vec/functions/function_totype.h"
+#include "vec/functions/simple_function_factory.h"
+#include "vec/utils/template_helpers.hpp"
+
+namespace doris {
+class FunctionContext;
+} // namespace doris
+
+namespace doris::vectorized {
+static const re2::RE2 JSON_PATTERN("^([^\\\"\\[\\]]*)(?:\\[([0-9]+|\\*)\\])?");
+
+template <typename T, typename U>
+void char_split(std::vector<T>& res, const U& var, char p) {
+    int start = 0;
+    int pos = start;
+    int end = var.length();
+    while (pos < end) {
+        while (var[pos] != p && pos < end) {
+            pos++;
+        }
+        res.emplace_back(&var[start], pos - start);
+        pos++;
+        start = pos;
+    }
+}
+
+// T = std::vector<std::string>
+// TODO: update RE2 to support std::vector<std::string_view>
+template <typename T>
+void get_parsed_paths(const T& path_exprs, std::vector<JsonPath>* parsed_paths) {
+    if (path_exprs.empty()) {
+        return;
+    }
+
+    if (path_exprs[0] != "$") {
+        parsed_paths->emplace_back("", -1, false);
+    } else {
+        parsed_paths->emplace_back("$", -1, true);
+    }
+
+    for (int i = 1; i < path_exprs.size(); i++) {
+        std::string col;
+        std::string index;
+        if (UNLIKELY(!RE2::FullMatch(path_exprs[i], JSON_PATTERN, &col, &index))) {
+            parsed_paths->emplace_back("", -1, false);
+        } else {
+            int idx = -1;
+            if (!index.empty()) {
+                if (index == "*") {
+                    idx = -2;
+                } else {
+                    idx = atoi(index.c_str());
+                }
+            }
+            parsed_paths->emplace_back(col, idx, true);
+        }
+    }
+}
+
+rapidjson::Value* match_value(const std::vector<JsonPath>& parsed_paths, rapidjson::Value* document,
+                              rapidjson::Document::AllocatorType& mem_allocator,
+                              bool is_insert_null = false) {
+    rapidjson::Value* root = document;
+    rapidjson::Value* array_obj = nullptr;
+    for (int i = 1; i < parsed_paths.size(); i++) {
+        if (root == nullptr || root->IsNull()) {
+            return nullptr;
+        }
+
+        if (UNLIKELY(!parsed_paths[i].is_valid)) {
+            return nullptr;
+        }
+
+        const std::string& col = parsed_paths[i].key;
+        int index = parsed_paths[i].idx;
+        if (LIKELY(!col.empty())) {
+            if (root->IsArray()) {
+                array_obj = static_cast<rapidjson::Value*>(
+                        mem_allocator.Malloc(sizeof(rapidjson::Value)));
+                array_obj->SetArray();
+                bool is_null = true;
+
+                // if array ,loop the array,find out all Objects,then find the results from the objects
+                for (int j = 0; j < root->Size(); j++) {
+                    rapidjson::Value* json_elem = &((*root)[j]);
+
+                    if (json_elem->IsArray() || json_elem->IsNull()) {
+                        continue;
+                    } else {
+                        if (!json_elem->IsObject()) {
+                            continue;
+                        }
+                        if (!json_elem->HasMember(col.c_str())) {
+                            if (is_insert_null) { // not found item, then insert a null object.
+                                is_null = false;
+                                rapidjson::Value nullObject(rapidjson::kNullType);
+                                array_obj->PushBack(nullObject, mem_allocator);
+                            }
+                            continue;
+                        }
+                        rapidjson::Value* obj = &((*json_elem)[col.c_str()]);
+                        if (obj->IsArray()) {
+                            is_null = false;
+                            for (int k = 0; k < obj->Size(); k++) {
+                                array_obj->PushBack((*obj)[k], mem_allocator);
+                            }
+                        } else if (!obj->IsNull()) {
+                            is_null = false;
+                            array_obj->PushBack(*obj, mem_allocator);
+                        }
+                    }
+                }
+
+                root = is_null ? &(array_obj->SetNull()) : array_obj;
+            } else if (root->IsObject()) {
+                if (!root->HasMember(col.c_str())) {
+                    return nullptr;
+                } else {
+                    root = &((*root)[col.c_str()]);
+                }
+            } else {
+                // root is not a nested type, return NULL
+                return nullptr;
+            }
+        }
+
+        if (UNLIKELY(index != -1)) {
+            // judge the rapidjson:Value, which base the top's result,
+            // if not array return NULL;else get the index value from the array
+            if (root->IsArray()) {
+                if (root->IsNull()) {
+                    return nullptr;
+                } else if (index == -2) {
+                    // [*]
+                    array_obj = static_cast<rapidjson::Value*>(
+                            mem_allocator.Malloc(sizeof(rapidjson::Value)));
+                    array_obj->SetArray();
+
+                    for (int j = 0; j < root->Size(); j++) {
+                        rapidjson::Value v;
+                        v.CopyFrom((*root)[j], mem_allocator);
+                        array_obj->PushBack(v, mem_allocator);
+                    }
+                    root = array_obj;
+                } else if (index >= root->Size()) {
+                    return nullptr;
+                } else {
+                    root = &((*root)[index]);
+                }
+            } else {
+                return nullptr;
+            }
+        }
+    }
+    return root;
+}
+
+template <JsonFunctionType fntype>
+rapidjson::Value* get_json_object(std::string_view json_string, std::string_view path_string,
+                                  rapidjson::Document* document) {
+    std::vector<JsonPath>* parsed_paths;
+    std::vector<JsonPath> tmp_parsed_paths;
+
+#ifdef USE_LIBCPP
+    std::string s(path_string);
+    auto tok = get_json_token(s);
+#else
+    auto tok = get_json_token(path_string);
+#endif
+    std::vector<std::string> paths(tok.begin(), tok.end());
+    get_parsed_paths(paths, &tmp_parsed_paths);
+    if (tmp_parsed_paths.empty()) {
+        return document;
+    }
+
+    parsed_paths = &tmp_parsed_paths;
+
+    if (!(*parsed_paths)[0].is_valid) {
+        return document;
+    }
+
+    if (UNLIKELY((*parsed_paths).size() == 1)) {
+        if (fntype == JSON_FUN_STRING) {
+            document->SetString(json_string.data(), json_string.size(), document->GetAllocator());
+        } else {
+            return document;
+        }
+    }
+
+    document->Parse(json_string.data(), json_string.size());
+    if (UNLIKELY(document->HasParseError())) {
+        // VLOG_CRITICAL << "Error at offset " << document->GetErrorOffset() << ": "
+        //         << GetParseError_En(document->GetParseError());
+        document->SetNull();
+        return document;
+    }
+
+    return match_value(*parsed_paths, document, document->GetAllocator());
+}
+
+template <typename NumberType>
+struct GetJsonNumberType {
+    using ReturnType = typename NumberType::ReturnType;
+    using ColumnType = typename NumberType::ColumnType;
+    using Container = typename ColumnType::Container;
+
+    static void get_json_impl(rapidjson::Value*& root, const std::string_view& json_string,
+                              const std::string_view& path_string, rapidjson::Document& document,
+                              typename NumberType::T& res, UInt8& null_map) {
+        if constexpr (std::is_same_v<double, typename NumberType::T>) {
+            root = get_json_object<JSON_FUN_DOUBLE>(json_string, path_string, &document);
+            handle_result<double>(root, res, null_map);
+        } else if constexpr (std::is_same_v<int32_t, typename NumberType::T>) {
+            root = get_json_object<JSON_FUN_DOUBLE>(json_string, path_string, &document);
+            handle_result<int32_t>(root, res, null_map);
+        } else if constexpr (std::is_same_v<int64_t, typename NumberType::T>) {
+            root = get_json_object<JSON_FUN_DOUBLE>(json_string, path_string, &document);
+            handle_result<int64_t>(root, res, null_map);
+        }
+    }
+    static void vector_vector(FunctionContext* context, const ColumnString::Chars& ldata,
+                              const ColumnString::Offsets& loffsets,
+                              const ColumnString::Chars& rdata,
+                              const ColumnString::Offsets& roffsets, Container& res,
+                              NullMap& null_map) {
+        size_t size = loffsets.size();
+        res.resize(size);
+        for (size_t i = 0; i < size; ++i) {
+            const char* l_raw_str = reinterpret_cast<const char*>(&ldata[loffsets[i - 1]]);
+            int l_str_size = loffsets[i] - loffsets[i - 1];
+            const char* r_raw_str = reinterpret_cast<const char*>(&rdata[roffsets[i - 1]]);
+            int r_str_size = roffsets[i] - roffsets[i - 1];
+            if (null_map[i]) {
+                res[i] = 0;
+                continue;
+            }
+
+            std::string_view json_string(l_raw_str, l_str_size);
+            std::string_view path_string(r_raw_str, r_str_size);
+            rapidjson::Document document;
+            rapidjson::Value* root = nullptr;
+
+            get_json_impl(root, json_string, path_string, document, res[i], null_map[i]);
+        }
+    }
+    static void vector_scalar(FunctionContext* context, const ColumnString::Chars& ldata,
+                              const ColumnString::Offsets& loffsets, const StringRef& rdata,
+                              Container& res, NullMap& null_map) {
+        size_t size = loffsets.size();
+        res.resize(size);
+        std::string_view path_string(rdata.data, rdata.size);
+        for (size_t i = 0; i < size; ++i) {
+            const char* l_raw_str = reinterpret_cast<const char*>(&ldata[loffsets[i - 1]]);
+            int l_str_size = loffsets[i] - loffsets[i - 1];
+            if (null_map[i]) {
+                res[i] = 0;
+                continue;
+            }
+            std::string_view json_string(l_raw_str, l_str_size);
+
+            rapidjson::Document document;
+            rapidjson::Value* root = nullptr;
+
+            get_json_impl(root, json_string, path_string, document, res[i], null_map[i]);
+        }
+    }
+    static void scalar_vector(FunctionContext* context, const StringRef& ldata,
+                              const ColumnString::Chars& rdata,
+                              const ColumnString::Offsets& roffsets, Container& res,
+                              NullMap& null_map) {
+        size_t size = roffsets.size();
+        res.resize(size);
+        std::string_view json_string(ldata.data, ldata.size);
+        for (size_t i = 0; i < size; ++i) {
+            const char* r_raw_str = reinterpret_cast<const char*>(&rdata[roffsets[i - 1]]);
+            int r_str_size = roffsets[i] - roffsets[i - 1];
+            if (null_map[i]) {
+                res[i] = 0;
+                continue;
+            }
+            std::string_view path_string(r_raw_str, r_str_size);
+            rapidjson::Document document;
+            rapidjson::Value* root = nullptr;
+
+            get_json_impl(root, json_string, path_string, document, res[i], null_map[i]);
+        }
+    }
+
+    template <typename T, std::enable_if_t<std::is_same_v<double, T>, T>* = nullptr>
+    static void handle_result(rapidjson::Value* root, T& res, uint8_t& res_null) {
+        if (root == nullptr || root->IsNull()) {
+            res = 0;
+            res_null = 1;
+        } else if (root->IsInt()) {
+            res = root->GetInt();
+        } else if (root->IsInt64()) {
+            res = root->GetInt64();
+        } else if (root->IsDouble()) {
+            res = root->GetDouble();
+        } else {
+            res_null = 1;
+        }
+    }
+
+    template <typename T, std::enable_if_t<std::is_same_v<int32_t, T>, T>* = nullptr>
+    static void handle_result(rapidjson::Value* root, int32_t& res, uint8_t& res_null) {
+        if (root != nullptr && root->IsInt()) {
+            res = root->GetInt();
+        } else {
+            res_null = 1;
+        }
+    }
+
+    template <typename T, std::enable_if_t<std::is_same_v<int64_t, T>, T>* = nullptr>
+    static void handle_result(rapidjson::Value* root, int64_t& res, uint8_t& res_null) {
+        if (root != nullptr && root->IsInt64()) {
+            res = root->GetInt64();
+        } else {
+            res_null = 1;
+        }
+    }
+};
+
+// Helper Class
+struct JsonNumberTypeDouble {
+    using T = Float64;
+    using ReturnType = DataTypeFloat64;
+    using ColumnType = ColumnVector<T>;
+};
+
+struct JsonNumberTypeInt {
+    using T = int32_t;
+    using ReturnType = DataTypeInt32;
+    using ColumnType = ColumnVector<T>;
+};
+
+struct JsonNumberTypeBigInt {
+    using T = int64_t;
+    using ReturnType = DataTypeInt64;
+    using ColumnType = ColumnVector<T>;
+};
+
+struct GetJsonDouble : public GetJsonNumberType<JsonNumberTypeDouble> {
+    static constexpr auto name = "get_json_double";
+    using ReturnType = typename JsonNumberTypeDouble::ReturnType;
+    using ColumnType = typename JsonNumberTypeDouble::ColumnType;
+};
+
+struct GetJsonInt : public GetJsonNumberType<JsonNumberTypeInt> {
+    static constexpr auto name = "get_json_int";
+    using ReturnType = typename JsonNumberTypeInt::ReturnType;
+    using ColumnType = typename JsonNumberTypeInt::ColumnType;
+};
+
+struct GetJsonBigInt : public GetJsonNumberType<JsonNumberTypeBigInt> {
+    static constexpr auto name = "get_json_bigint";
+    using ReturnType = typename JsonNumberTypeBigInt::ReturnType;
+    using ColumnType = typename JsonNumberTypeBigInt::ColumnType;
+};
+
+struct GetJsonString {
+    static constexpr auto name = "get_json_string";
+    using ReturnType = DataTypeString;
+    using ColumnType = ColumnString;
+    using Chars = ColumnString::Chars;
+    using Offsets = ColumnString::Offsets;
+    static void vector_vector(FunctionContext* context, const Chars& ldata, const Offsets& loffsets,
+                              const Chars& rdata, const Offsets& roffsets, Chars& res_data,
+                              Offsets& res_offsets, NullMap& null_map) {
+        size_t input_rows_count = loffsets.size();
+        res_offsets.resize(input_rows_count);
+
+        for (size_t i = 0; i < input_rows_count; ++i) {
+            if (null_map[i]) {
+                StringOP::push_null_string(i, res_data, res_offsets, null_map);
+                continue;
+            }
+            int l_size = loffsets[i] - loffsets[i - 1];
+            const auto l_raw = reinterpret_cast<const char*>(&ldata[loffsets[i - 1]]);
+            int r_size = roffsets[i] - roffsets[i - 1];
+            const auto r_raw = reinterpret_cast<const char*>(&rdata[roffsets[i - 1]]);
+
+            std::string_view json_string(l_raw, l_size);
+            std::string_view path_string(r_raw, r_size);
+
+            execute_impl(json_string, path_string, res_data, res_offsets, null_map, i);
+        }
+    }
+    static void vector_scalar(FunctionContext* context, const Chars& ldata, const Offsets& loffsets,
+                              const StringRef& rdata, Chars& res_data, Offsets& res_offsets,
+                              NullMap& null_map) {
+        size_t input_rows_count = loffsets.size();
+        res_offsets.resize(input_rows_count);
+
+        for (size_t i = 0; i < input_rows_count; ++i) {
+            if (null_map[i]) {
+                StringOP::push_null_string(i, res_data, res_offsets, null_map);
+                continue;
+            }
+            int l_size = loffsets[i] - loffsets[i - 1];
+            const auto l_raw = reinterpret_cast<const char*>(&ldata[loffsets[i - 1]]);
+
+            std::string_view json_string(l_raw, l_size);
+            std::string_view path_string(rdata.data, rdata.size);
+
+            execute_impl(json_string, path_string, res_data, res_offsets, null_map, i);
+        }
+    }
+    static void scalar_vector(FunctionContext* context, const StringRef& ldata, const Chars& rdata,
+                              const Offsets& roffsets, Chars& res_data, Offsets& res_offsets,
+                              NullMap& null_map) {
+        size_t input_rows_count = roffsets.size();
+        res_offsets.resize(input_rows_count);
+
+        for (size_t i = 0; i < input_rows_count; ++i) {
+            if (null_map[i]) {
+                StringOP::push_null_string(i, res_data, res_offsets, null_map);
+                continue;
+            }
+            int r_size = roffsets[i] - roffsets[i - 1];
+            const auto r_raw = reinterpret_cast<const char*>(&rdata[roffsets[i - 1]]);
+
+            std::string_view json_string(ldata.data, ldata.size);
+            std::string_view path_string(r_raw, r_size);
+
+            execute_impl(json_string, path_string, res_data, res_offsets, null_map, i);
+        }
+    }
+
+    static void execute_impl(const std::string_view& json_string,
+                             const std::string_view& path_string, Chars& res_data,
+                             Offsets& res_offsets, NullMap& null_map, size_t index_now) {
+        rapidjson::Document document;
+        rapidjson::Value* root = nullptr;
+
+        root = get_json_object<JSON_FUN_STRING>(json_string, path_string, &document);
+        const int max_string_len = 65535;
+
+        if (root == nullptr || root->IsNull()) {
+            StringOP::push_null_string(index_now, res_data, res_offsets, null_map);
+        } else if (root->IsString()) {
+            const auto ptr = root->GetString();
+            size_t len = strnlen(ptr, max_string_len);
+            StringOP::push_value_string(std::string_view(ptr, len), index_now, res_data,
+                                        res_offsets);
+        } else {
+            rapidjson::StringBuffer buf;
+            rapidjson::Writer<rapidjson::StringBuffer> writer(buf);
+            root->Accept(writer);
+
+            const auto ptr = buf.GetString();
+            size_t len = strnlen(ptr, max_string_len);
+            StringOP::push_value_string(std::string_view(ptr, len), index_now, res_data,
+                                        res_offsets);
+        }
+    }
+};
+
+template <int flag>
+struct JsonParser {
+    //string
+    static void update_value(StringParser::ParseResult& result, rapidjson::Value& value,
+                             StringRef data, rapidjson::Document::AllocatorType& allocator) {
+        value.SetString(data.data, data.size, allocator);
+    }
+};
+
+template <>
+struct JsonParser<'0'> {
+    // null
+    static void update_value(StringParser::ParseResult& result, rapidjson::Value& value,
+                             StringRef data, rapidjson::Document::AllocatorType& allocator) {
+        value.SetNull();
+    }
+};
+
+template <>
+struct JsonParser<'1'> {
+    // bool
+    static void update_value(StringParser::ParseResult& result, rapidjson::Value& value,
+                             StringRef data, rapidjson::Document::AllocatorType& allocator) {
+        DCHECK(data.size == 1 || strncmp(data.data, "true", 4) == 0 ||
+               strncmp(data.data, "false", 5) == 0);
+        value.SetBool((*data.data == '1' || *data.data == 't') ? true : false);
+    }
+};
+
+template <>
+struct JsonParser<'2'> {
+    // int
+    static void update_value(StringParser::ParseResult& result, rapidjson::Value& value,
+                             StringRef data, rapidjson::Document::AllocatorType& allocator) {
+        value.SetInt(StringParser::string_to_int<int32_t>(data.data, data.size, &result));
+    }
+};
+
+template <>
+struct JsonParser<'3'> {
+    // double
+    static void update_value(StringParser::ParseResult& result, rapidjson::Value& value,
+                             StringRef data, rapidjson::Document::AllocatorType& allocator) {
+        value.SetDouble(StringParser::string_to_float<double>(data.data, data.size, &result));
+    }
+};
+
+template <>
+struct JsonParser<'4'> {
+    // time
+    static void update_value(StringParser::ParseResult& result, rapidjson::Value& value,
+                             StringRef data, rapidjson::Document::AllocatorType& allocator) {
+        // remove double quotes, "xxx" -> xxx
+        value.SetString(data.data + 1, data.size - 2, allocator);
+    }
+};
+
+template <>
+struct JsonParser<'5'> {
+    // bigint
+    static void update_value(StringParser::ParseResult& result, rapidjson::Value& value,
+                             StringRef data, rapidjson::Document::AllocatorType& allocator) {
+        value.SetInt64(StringParser::string_to_int<int64_t>(data.data, data.size, &result));
+    }
+};
+
+template <int flag, typename Impl>
+struct ExecuteReducer {
+    template <typename... TArgs>
+    static void run(TArgs&&... args) {
+        Impl::template execute_type<JsonParser<flag>>(std::forward<TArgs>(args)...);
+    }
+};
+
+struct FunctionJsonArrayImpl {
+    static constexpr auto name = "json_array";
+
+    template <int flag>
+    using Reducer = ExecuteReducer<flag, FunctionJsonArrayImpl>;
+
+    static void execute_parse(const std::string& type_flags,
+                              const std::vector<const ColumnString*>& data_columns,
+                              std::vector<rapidjson::Value>& objects,
+                              rapidjson::Document::AllocatorType& allocator,
+                              const std::vector<const ColumnUInt8*>& nullmaps) {
+        for (int i = 0; i < data_columns.size() - 1; i++) {
+            constexpr_int_match<'0', '6', Reducer>::run(type_flags[i], objects, allocator,
+                                                        data_columns[i], nullmaps[i]);
+        }
+    }
+
+    template <typename TypeImpl>
+    static void execute_type(std::vector<rapidjson::Value>& objects,
+                             rapidjson::Document::AllocatorType& allocator,
+                             const ColumnString* data_column, const ColumnUInt8* nullmap) {
+        StringParser::ParseResult result;
+        rapidjson::Value value;
+
+        for (int i = 0; i < objects.size(); i++) {
+            if (nullmap != nullptr && nullmap->get_data()[i]) {
+                JsonParser<'0'>::update_value(result, value, data_column->get_data_at(i),
+                                              allocator);
+            } else {
+                TypeImpl::update_value(result, value, data_column->get_data_at(i), allocator);
+            }
+            objects[i].PushBack(value, allocator);
+        }
+    }
+};
+
+struct FunctionJsonObjectImpl {
+    static constexpr auto name = "json_object";
+
+    template <int flag>
+    using Reducer = ExecuteReducer<flag, FunctionJsonObjectImpl>;
+
+    static void execute_parse(std::string type_flags,
+                              const std::vector<const ColumnString*>& data_columns,
+                              std::vector<rapidjson::Value>& objects,
+                              rapidjson::Document::AllocatorType& allocator,
+                              const std::vector<const ColumnUInt8*>& nullmaps) {
+        for (auto& array_object : objects) {
+            array_object.SetObject();
+        }
+
+        for (int i = 0; i + 1 < data_columns.size() - 1; i += 2) {
+            constexpr_int_match<'0', '6', Reducer>::run(type_flags[i + 1], objects, allocator,
+                                                        data_columns[i], data_columns[i + 1],
+                                                        nullmaps[i + 1]);
+        }
+    }
+
+    template <typename TypeImpl>
+    static void execute_type(std::vector<rapidjson::Value>& objects,
+                             rapidjson::Document::AllocatorType& allocator,
+                             const ColumnString* key_column, const ColumnString* value_column,
+                             const ColumnUInt8* nullmap) {
+        StringParser::ParseResult result;
+        rapidjson::Value key;
+        rapidjson::Value value;
+        for (int i = 0; i < objects.size(); i++) {
+            JsonParser<'6'>::update_value(result, key, key_column->get_data_at(i),
+                                          allocator); // key always is string
+            if (nullmap != nullptr && nullmap->get_data()[i]) {
+                JsonParser<'0'>::update_value(result, value, value_column->get_data_at(i),
+                                              allocator);
+            } else {
+                TypeImpl::update_value(result, value, value_column->get_data_at(i), allocator);
+            }
+            objects[i].AddMember(key, value, allocator);
+        }
+    }
+};
+
+template <typename SpecificImpl>
+class FunctionJsonAlwaysNotNullable : public IFunction {
+public:
+    using IFunction::execute;
+
+    static constexpr auto name = SpecificImpl::name;
+
+    static FunctionPtr create() {
+        return std::make_shared<FunctionJsonAlwaysNotNullable<SpecificImpl>>();
+    }
+
+    bool use_default_implementation_for_nulls() const override { return false; }
+
+    String get_name() const override { return name; }
+
+    size_t get_number_of_arguments() const override { return 0; }
+
+    bool is_variadic() const override { return true; }
+
+    DataTypePtr get_return_type_impl(const DataTypes& arguments) const override {
+        return std::make_shared<DataTypeString>();
+    }
+
+    Status execute_impl(FunctionContext* context, Block& block, const ColumnNumbers& arguments,
+                        size_t result, size_t input_rows_count) override {
+        auto result_column = ColumnString::create();
+
+        std::vector<ColumnPtr> column_ptrs; // prevent converted column destruct
+        std::vector<const ColumnString*> data_columns;
+        std::vector<const ColumnUInt8*> nullmaps;
+        for (int i = 0; i < arguments.size(); i++) {
+            auto column = block.get_by_position(arguments[i]).column;
+            column_ptrs.push_back(column->convert_to_full_column_if_const());
+            const ColumnNullable* col_nullable =
+                    check_and_get_column<ColumnNullable>(column_ptrs.back().get());
+            if (col_nullable) {
+                const ColumnUInt8* col_nullmap = check_and_get_column<ColumnUInt8>(
+                        col_nullable->get_null_map_column_ptr().get());
+                nullmaps.push_back(col_nullmap);
+                const ColumnString* col = check_and_get_column<ColumnString>(
+                        col_nullable->get_nested_column_ptr().get());
+                data_columns.push_back(col);
+            } else {
+                nullmaps.push_back(nullptr);
+                data_columns.push_back(assert_cast<const ColumnString*>(column_ptrs.back().get()));
+            }
+        }
+        execute(data_columns, *assert_cast<ColumnString*>(result_column.get()), input_rows_count,
+                nullmaps);
+        block.get_by_position(result).column = std::move(result_column);
+        return Status::OK();
+    }
+
+    static void execute(const std::vector<const ColumnString*>& data_columns,
+                        ColumnString& result_column, size_t input_rows_count,
+                        const std::vector<const ColumnUInt8*> nullmaps) {
+        std::string type_flags = data_columns.back()->get_data_at(0).to_string();
+
+        rapidjson::Document document;
+        rapidjson::Document::AllocatorType& allocator = document.GetAllocator();
+
+        std::vector<rapidjson::Value> objects;
+        for (int i = 0; i < input_rows_count; i++) {
+            objects.emplace_back(rapidjson::kArrayType);
+        }
+
+        SpecificImpl::execute_parse(type_flags, data_columns, objects, allocator, nullmaps);
+
+        rapidjson::StringBuffer buf;
+        rapidjson::Writer<rapidjson::StringBuffer> writer(buf);
+
+        for (int i = 0; i < input_rows_count; i++) {
+            buf.Clear();
+            writer.Reset(buf);
+            objects[i].Accept(writer);
+            result_column.insert_data(buf.GetString(), buf.GetSize());
+        }
+    }
+};
+
+struct FunctionJsonQuoteImpl {
+    static constexpr auto name = "json_quote";
+
+    static void execute(const std::vector<const ColumnString*>& data_columns,
+                        ColumnString& result_column, size_t input_rows_count) {
+        rapidjson::Document document;
+        rapidjson::Document::AllocatorType& allocator = document.GetAllocator();
+
+        rapidjson::Value value;
+
+        rapidjson::StringBuffer buf;
+        rapidjson::Writer<rapidjson::StringBuffer> writer(buf);
+
+        for (int i = 0; i < input_rows_count; i++) {
+            StringRef data = data_columns[0]->get_data_at(i);
+            value.SetString(data.data, data.size, allocator);
+
+            buf.Clear();
+            value.Accept(writer);
+            result_column.insert_data(buf.GetString(), buf.GetSize());
+        }
+    }
+};
+
+struct FunctionJsonExtractImpl {
+    static constexpr auto name = "json_extract";
+
+    static rapidjson::Value parse_json(const ColumnString* json_col, const ColumnString* path_col,
+                                       rapidjson::Document::AllocatorType& allocator,
+                                       const int row) {
+        rapidjson::Value value;
+        rapidjson::Document document;
+
+        const auto obj = json_col->get_data_at(row);
+        std::string_view json_string(obj.data, obj.size);
+        const auto path = path_col->get_data_at(row);
+        std::string_view path_string(path.data, path.size);
+
+        auto root = get_json_object<JSON_FUN_STRING>(json_string, path_string, &document);
+        if (root != nullptr) {
+            value.CopyFrom(*root, allocator);
+        }
+        return value;
+    }
+
+    static void execute(const std::vector<const ColumnString*>& data_columns,
+                        ColumnString& result_column, size_t input_rows_count) {
+        rapidjson::Document document;
+        rapidjson::Document::AllocatorType& allocator = document.GetAllocator();
+        rapidjson::StringBuffer buf;
+        rapidjson::Writer<rapidjson::StringBuffer> writer(buf);
+
+        const auto json_col = data_columns[0];
+        for (size_t row = 0; row < input_rows_count; row++) {
+            rapidjson::Value value;
+            if (data_columns.size() == 2) {
+                value = parse_json(json_col, data_columns[1], allocator, row);
+            } else {
+                value.SetArray();
+                value.Reserve(data_columns.size() - 1, allocator);
+                for (size_t col = 1; col < data_columns.size(); ++col) {
+                    value.PushBack(parse_json(json_col, data_columns[col], allocator, row),
+                                   allocator);
+                }
+            }
+
+            // write value as string
+            buf.Clear();
+            writer.Reset(buf);
+            value.Accept(writer);
+            result_column.insert_data(buf.GetString(), buf.GetSize());
+        }
+    }
+};
+
+template <typename Impl>
+class FunctionJson : public IFunction {
+public:
+    static constexpr auto name = Impl::name;
+
+    static FunctionPtr create() { return std::make_shared<FunctionJson<Impl>>(); }
+
+    String get_name() const override { return name; }
+
+    size_t get_number_of_arguments() const override { return 0; }

Review Comment:
   warning: function 'get_number_of_arguments' should be marked [[nodiscard]] [modernize-use-nodiscard]
   
   ```suggestion
       [[nodiscard]] size_t get_number_of_arguments() const override { return 0; }
   ```
   



##########
function_json.cpp:
##########
@@ -0,0 +1,1320 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#include <rapidjson/allocators.h>
+#include <rapidjson/document.h>
+#include <rapidjson/encodings.h>
+#include <rapidjson/pointer.h>
+#include <rapidjson/rapidjson.h>
+#include <rapidjson/stringbuffer.h>
+#include <rapidjson/writer.h>
+#include <re2/re2.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <algorithm>
+#include <boost/iterator/iterator_facade.hpp>
+#include <boost/token_functions.hpp>
+#include <boost/tokenizer.hpp>
+#include <memory>
+#include <string>
+#include <string_view>
+#include <type_traits>
+#include <utility>
+#include <vector>
+
+// IWYU pragma: no_include <opentelemetry/common/threadlocal.h>
+#include "common/compiler_util.h" // IWYU pragma: keep
+#include "common/status.h"
+#include "exprs/json_functions.h"
+#ifdef __AVX2__
+#include "util/jsonb_parser_simd.h"
+#else
+#include "util/jsonb_parser.h"
+#endif
+#include "util/string_parser.hpp"
+#include "util/string_util.h"
+#include "vec/aggregate_functions/aggregate_function.h"
+#include "vec/columns/column.h"
+#include "vec/columns/column_nullable.h"
+#include "vec/columns/column_string.h"
+#include "vec/columns/column_vector.h"
+#include "vec/columns/columns_number.h"
+#include "vec/common/assert_cast.h"
+#include "vec/common/string_ref.h"
+#include "vec/core/block.h"
+#include "vec/core/column_numbers.h"
+#include "vec/core/column_with_type_and_name.h"
+#include "vec/core/types.h"
+#include "vec/data_types/data_type.h"
+#include "vec/data_types/data_type_nullable.h"
+#include "vec/data_types/data_type_number.h"
+#include "vec/data_types/data_type_string.h"
+#include "vec/functions/function.h"
+#include "vec/functions/function_string.h"
+#include "vec/functions/function_totype.h"
+#include "vec/functions/simple_function_factory.h"
+#include "vec/utils/template_helpers.hpp"
+
+namespace doris {
+class FunctionContext;
+} // namespace doris
+
+namespace doris::vectorized {
+static const re2::RE2 JSON_PATTERN("^([^\\\"\\[\\]]*)(?:\\[([0-9]+|\\*)\\])?");
+
+template <typename T, typename U>
+void char_split(std::vector<T>& res, const U& var, char p) {
+    int start = 0;
+    int pos = start;
+    int end = var.length();
+    while (pos < end) {
+        while (var[pos] != p && pos < end) {
+            pos++;
+        }
+        res.emplace_back(&var[start], pos - start);
+        pos++;
+        start = pos;
+    }
+}
+
+// T = std::vector<std::string>
+// TODO: update RE2 to support std::vector<std::string_view>
+template <typename T>
+void get_parsed_paths(const T& path_exprs, std::vector<JsonPath>* parsed_paths) {
+    if (path_exprs.empty()) {
+        return;
+    }
+
+    if (path_exprs[0] != "$") {
+        parsed_paths->emplace_back("", -1, false);
+    } else {
+        parsed_paths->emplace_back("$", -1, true);
+    }
+
+    for (int i = 1; i < path_exprs.size(); i++) {
+        std::string col;
+        std::string index;
+        if (UNLIKELY(!RE2::FullMatch(path_exprs[i], JSON_PATTERN, &col, &index))) {
+            parsed_paths->emplace_back("", -1, false);
+        } else {
+            int idx = -1;
+            if (!index.empty()) {
+                if (index == "*") {
+                    idx = -2;
+                } else {
+                    idx = atoi(index.c_str());
+                }
+            }
+            parsed_paths->emplace_back(col, idx, true);
+        }
+    }
+}
+
+rapidjson::Value* match_value(const std::vector<JsonPath>& parsed_paths, rapidjson::Value* document,
+                              rapidjson::Document::AllocatorType& mem_allocator,
+                              bool is_insert_null = false) {
+    rapidjson::Value* root = document;
+    rapidjson::Value* array_obj = nullptr;
+    for (int i = 1; i < parsed_paths.size(); i++) {
+        if (root == nullptr || root->IsNull()) {
+            return nullptr;
+        }
+
+        if (UNLIKELY(!parsed_paths[i].is_valid)) {
+            return nullptr;
+        }
+
+        const std::string& col = parsed_paths[i].key;
+        int index = parsed_paths[i].idx;
+        if (LIKELY(!col.empty())) {
+            if (root->IsArray()) {
+                array_obj = static_cast<rapidjson::Value*>(
+                        mem_allocator.Malloc(sizeof(rapidjson::Value)));
+                array_obj->SetArray();
+                bool is_null = true;
+
+                // if array ,loop the array,find out all Objects,then find the results from the objects
+                for (int j = 0; j < root->Size(); j++) {
+                    rapidjson::Value* json_elem = &((*root)[j]);
+
+                    if (json_elem->IsArray() || json_elem->IsNull()) {
+                        continue;
+                    } else {
+                        if (!json_elem->IsObject()) {
+                            continue;
+                        }
+                        if (!json_elem->HasMember(col.c_str())) {
+                            if (is_insert_null) { // not found item, then insert a null object.
+                                is_null = false;
+                                rapidjson::Value nullObject(rapidjson::kNullType);
+                                array_obj->PushBack(nullObject, mem_allocator);
+                            }
+                            continue;
+                        }
+                        rapidjson::Value* obj = &((*json_elem)[col.c_str()]);
+                        if (obj->IsArray()) {
+                            is_null = false;
+                            for (int k = 0; k < obj->Size(); k++) {
+                                array_obj->PushBack((*obj)[k], mem_allocator);
+                            }
+                        } else if (!obj->IsNull()) {
+                            is_null = false;
+                            array_obj->PushBack(*obj, mem_allocator);
+                        }
+                    }
+                }
+
+                root = is_null ? &(array_obj->SetNull()) : array_obj;
+            } else if (root->IsObject()) {
+                if (!root->HasMember(col.c_str())) {
+                    return nullptr;
+                } else {
+                    root = &((*root)[col.c_str()]);
+                }
+            } else {
+                // root is not a nested type, return NULL
+                return nullptr;
+            }
+        }
+
+        if (UNLIKELY(index != -1)) {
+            // judge the rapidjson:Value, which base the top's result,
+            // if not array return NULL;else get the index value from the array
+            if (root->IsArray()) {
+                if (root->IsNull()) {
+                    return nullptr;
+                } else if (index == -2) {
+                    // [*]
+                    array_obj = static_cast<rapidjson::Value*>(
+                            mem_allocator.Malloc(sizeof(rapidjson::Value)));
+                    array_obj->SetArray();
+
+                    for (int j = 0; j < root->Size(); j++) {
+                        rapidjson::Value v;
+                        v.CopyFrom((*root)[j], mem_allocator);
+                        array_obj->PushBack(v, mem_allocator);
+                    }
+                    root = array_obj;
+                } else if (index >= root->Size()) {
+                    return nullptr;
+                } else {
+                    root = &((*root)[index]);
+                }
+            } else {
+                return nullptr;
+            }
+        }
+    }
+    return root;
+}
+
+template <JsonFunctionType fntype>
+rapidjson::Value* get_json_object(std::string_view json_string, std::string_view path_string,
+                                  rapidjson::Document* document) {
+    std::vector<JsonPath>* parsed_paths;
+    std::vector<JsonPath> tmp_parsed_paths;
+
+#ifdef USE_LIBCPP
+    std::string s(path_string);
+    auto tok = get_json_token(s);
+#else
+    auto tok = get_json_token(path_string);
+#endif
+    std::vector<std::string> paths(tok.begin(), tok.end());
+    get_parsed_paths(paths, &tmp_parsed_paths);
+    if (tmp_parsed_paths.empty()) {
+        return document;
+    }
+
+    parsed_paths = &tmp_parsed_paths;
+
+    if (!(*parsed_paths)[0].is_valid) {
+        return document;
+    }
+
+    if (UNLIKELY((*parsed_paths).size() == 1)) {
+        if (fntype == JSON_FUN_STRING) {
+            document->SetString(json_string.data(), json_string.size(), document->GetAllocator());
+        } else {
+            return document;
+        }
+    }
+
+    document->Parse(json_string.data(), json_string.size());
+    if (UNLIKELY(document->HasParseError())) {
+        // VLOG_CRITICAL << "Error at offset " << document->GetErrorOffset() << ": "
+        //         << GetParseError_En(document->GetParseError());
+        document->SetNull();
+        return document;
+    }
+
+    return match_value(*parsed_paths, document, document->GetAllocator());
+}
+
+template <typename NumberType>
+struct GetJsonNumberType {
+    using ReturnType = typename NumberType::ReturnType;
+    using ColumnType = typename NumberType::ColumnType;
+    using Container = typename ColumnType::Container;
+
+    static void get_json_impl(rapidjson::Value*& root, const std::string_view& json_string,
+                              const std::string_view& path_string, rapidjson::Document& document,
+                              typename NumberType::T& res, UInt8& null_map) {
+        if constexpr (std::is_same_v<double, typename NumberType::T>) {
+            root = get_json_object<JSON_FUN_DOUBLE>(json_string, path_string, &document);
+            handle_result<double>(root, res, null_map);
+        } else if constexpr (std::is_same_v<int32_t, typename NumberType::T>) {
+            root = get_json_object<JSON_FUN_DOUBLE>(json_string, path_string, &document);
+            handle_result<int32_t>(root, res, null_map);
+        } else if constexpr (std::is_same_v<int64_t, typename NumberType::T>) {
+            root = get_json_object<JSON_FUN_DOUBLE>(json_string, path_string, &document);
+            handle_result<int64_t>(root, res, null_map);
+        }
+    }
+    static void vector_vector(FunctionContext* context, const ColumnString::Chars& ldata,
+                              const ColumnString::Offsets& loffsets,
+                              const ColumnString::Chars& rdata,
+                              const ColumnString::Offsets& roffsets, Container& res,
+                              NullMap& null_map) {
+        size_t size = loffsets.size();
+        res.resize(size);
+        for (size_t i = 0; i < size; ++i) {
+            const char* l_raw_str = reinterpret_cast<const char*>(&ldata[loffsets[i - 1]]);
+            int l_str_size = loffsets[i] - loffsets[i - 1];
+            const char* r_raw_str = reinterpret_cast<const char*>(&rdata[roffsets[i - 1]]);
+            int r_str_size = roffsets[i] - roffsets[i - 1];
+            if (null_map[i]) {
+                res[i] = 0;
+                continue;
+            }
+
+            std::string_view json_string(l_raw_str, l_str_size);
+            std::string_view path_string(r_raw_str, r_str_size);
+            rapidjson::Document document;
+            rapidjson::Value* root = nullptr;
+
+            get_json_impl(root, json_string, path_string, document, res[i], null_map[i]);
+        }
+    }
+    static void vector_scalar(FunctionContext* context, const ColumnString::Chars& ldata,
+                              const ColumnString::Offsets& loffsets, const StringRef& rdata,
+                              Container& res, NullMap& null_map) {
+        size_t size = loffsets.size();
+        res.resize(size);
+        std::string_view path_string(rdata.data, rdata.size);
+        for (size_t i = 0; i < size; ++i) {
+            const char* l_raw_str = reinterpret_cast<const char*>(&ldata[loffsets[i - 1]]);
+            int l_str_size = loffsets[i] - loffsets[i - 1];
+            if (null_map[i]) {
+                res[i] = 0;
+                continue;
+            }
+            std::string_view json_string(l_raw_str, l_str_size);
+
+            rapidjson::Document document;
+            rapidjson::Value* root = nullptr;
+
+            get_json_impl(root, json_string, path_string, document, res[i], null_map[i]);
+        }
+    }
+    static void scalar_vector(FunctionContext* context, const StringRef& ldata,
+                              const ColumnString::Chars& rdata,
+                              const ColumnString::Offsets& roffsets, Container& res,
+                              NullMap& null_map) {
+        size_t size = roffsets.size();
+        res.resize(size);
+        std::string_view json_string(ldata.data, ldata.size);
+        for (size_t i = 0; i < size; ++i) {
+            const char* r_raw_str = reinterpret_cast<const char*>(&rdata[roffsets[i - 1]]);
+            int r_str_size = roffsets[i] - roffsets[i - 1];
+            if (null_map[i]) {
+                res[i] = 0;
+                continue;
+            }
+            std::string_view path_string(r_raw_str, r_str_size);
+            rapidjson::Document document;
+            rapidjson::Value* root = nullptr;
+
+            get_json_impl(root, json_string, path_string, document, res[i], null_map[i]);
+        }
+    }
+
+    template <typename T, std::enable_if_t<std::is_same_v<double, T>, T>* = nullptr>
+    static void handle_result(rapidjson::Value* root, T& res, uint8_t& res_null) {
+        if (root == nullptr || root->IsNull()) {
+            res = 0;
+            res_null = 1;
+        } else if (root->IsInt()) {
+            res = root->GetInt();
+        } else if (root->IsInt64()) {
+            res = root->GetInt64();
+        } else if (root->IsDouble()) {
+            res = root->GetDouble();
+        } else {
+            res_null = 1;
+        }
+    }
+
+    template <typename T, std::enable_if_t<std::is_same_v<int32_t, T>, T>* = nullptr>
+    static void handle_result(rapidjson::Value* root, int32_t& res, uint8_t& res_null) {
+        if (root != nullptr && root->IsInt()) {
+            res = root->GetInt();
+        } else {
+            res_null = 1;
+        }
+    }
+
+    template <typename T, std::enable_if_t<std::is_same_v<int64_t, T>, T>* = nullptr>
+    static void handle_result(rapidjson::Value* root, int64_t& res, uint8_t& res_null) {
+        if (root != nullptr && root->IsInt64()) {
+            res = root->GetInt64();
+        } else {
+            res_null = 1;
+        }
+    }
+};
+
+// Helper Class
+struct JsonNumberTypeDouble {
+    using T = Float64;
+    using ReturnType = DataTypeFloat64;
+    using ColumnType = ColumnVector<T>;
+};
+
+struct JsonNumberTypeInt {
+    using T = int32_t;
+    using ReturnType = DataTypeInt32;
+    using ColumnType = ColumnVector<T>;
+};
+
+struct JsonNumberTypeBigInt {
+    using T = int64_t;
+    using ReturnType = DataTypeInt64;
+    using ColumnType = ColumnVector<T>;
+};
+
+struct GetJsonDouble : public GetJsonNumberType<JsonNumberTypeDouble> {
+    static constexpr auto name = "get_json_double";
+    using ReturnType = typename JsonNumberTypeDouble::ReturnType;
+    using ColumnType = typename JsonNumberTypeDouble::ColumnType;
+};
+
+struct GetJsonInt : public GetJsonNumberType<JsonNumberTypeInt> {
+    static constexpr auto name = "get_json_int";
+    using ReturnType = typename JsonNumberTypeInt::ReturnType;
+    using ColumnType = typename JsonNumberTypeInt::ColumnType;
+};
+
+struct GetJsonBigInt : public GetJsonNumberType<JsonNumberTypeBigInt> {
+    static constexpr auto name = "get_json_bigint";
+    using ReturnType = typename JsonNumberTypeBigInt::ReturnType;
+    using ColumnType = typename JsonNumberTypeBigInt::ColumnType;
+};
+
+struct GetJsonString {
+    static constexpr auto name = "get_json_string";
+    using ReturnType = DataTypeString;
+    using ColumnType = ColumnString;
+    using Chars = ColumnString::Chars;
+    using Offsets = ColumnString::Offsets;
+    static void vector_vector(FunctionContext* context, const Chars& ldata, const Offsets& loffsets,
+                              const Chars& rdata, const Offsets& roffsets, Chars& res_data,
+                              Offsets& res_offsets, NullMap& null_map) {
+        size_t input_rows_count = loffsets.size();
+        res_offsets.resize(input_rows_count);
+
+        for (size_t i = 0; i < input_rows_count; ++i) {
+            if (null_map[i]) {
+                StringOP::push_null_string(i, res_data, res_offsets, null_map);
+                continue;
+            }
+            int l_size = loffsets[i] - loffsets[i - 1];
+            const auto l_raw = reinterpret_cast<const char*>(&ldata[loffsets[i - 1]]);
+            int r_size = roffsets[i] - roffsets[i - 1];
+            const auto r_raw = reinterpret_cast<const char*>(&rdata[roffsets[i - 1]]);
+
+            std::string_view json_string(l_raw, l_size);
+            std::string_view path_string(r_raw, r_size);
+
+            execute_impl(json_string, path_string, res_data, res_offsets, null_map, i);
+        }
+    }
+    static void vector_scalar(FunctionContext* context, const Chars& ldata, const Offsets& loffsets,
+                              const StringRef& rdata, Chars& res_data, Offsets& res_offsets,
+                              NullMap& null_map) {
+        size_t input_rows_count = loffsets.size();
+        res_offsets.resize(input_rows_count);
+
+        for (size_t i = 0; i < input_rows_count; ++i) {
+            if (null_map[i]) {
+                StringOP::push_null_string(i, res_data, res_offsets, null_map);
+                continue;
+            }
+            int l_size = loffsets[i] - loffsets[i - 1];
+            const auto l_raw = reinterpret_cast<const char*>(&ldata[loffsets[i - 1]]);
+
+            std::string_view json_string(l_raw, l_size);
+            std::string_view path_string(rdata.data, rdata.size);
+
+            execute_impl(json_string, path_string, res_data, res_offsets, null_map, i);
+        }
+    }
+    static void scalar_vector(FunctionContext* context, const StringRef& ldata, const Chars& rdata,
+                              const Offsets& roffsets, Chars& res_data, Offsets& res_offsets,
+                              NullMap& null_map) {
+        size_t input_rows_count = roffsets.size();
+        res_offsets.resize(input_rows_count);
+
+        for (size_t i = 0; i < input_rows_count; ++i) {
+            if (null_map[i]) {
+                StringOP::push_null_string(i, res_data, res_offsets, null_map);
+                continue;
+            }
+            int r_size = roffsets[i] - roffsets[i - 1];
+            const auto r_raw = reinterpret_cast<const char*>(&rdata[roffsets[i - 1]]);
+
+            std::string_view json_string(ldata.data, ldata.size);
+            std::string_view path_string(r_raw, r_size);
+
+            execute_impl(json_string, path_string, res_data, res_offsets, null_map, i);
+        }
+    }
+
+    static void execute_impl(const std::string_view& json_string,
+                             const std::string_view& path_string, Chars& res_data,
+                             Offsets& res_offsets, NullMap& null_map, size_t index_now) {
+        rapidjson::Document document;
+        rapidjson::Value* root = nullptr;
+
+        root = get_json_object<JSON_FUN_STRING>(json_string, path_string, &document);
+        const int max_string_len = 65535;
+
+        if (root == nullptr || root->IsNull()) {
+            StringOP::push_null_string(index_now, res_data, res_offsets, null_map);
+        } else if (root->IsString()) {
+            const auto ptr = root->GetString();
+            size_t len = strnlen(ptr, max_string_len);
+            StringOP::push_value_string(std::string_view(ptr, len), index_now, res_data,
+                                        res_offsets);
+        } else {
+            rapidjson::StringBuffer buf;
+            rapidjson::Writer<rapidjson::StringBuffer> writer(buf);
+            root->Accept(writer);
+
+            const auto ptr = buf.GetString();
+            size_t len = strnlen(ptr, max_string_len);
+            StringOP::push_value_string(std::string_view(ptr, len), index_now, res_data,
+                                        res_offsets);
+        }
+    }
+};
+
+template <int flag>
+struct JsonParser {
+    //string
+    static void update_value(StringParser::ParseResult& result, rapidjson::Value& value,
+                             StringRef data, rapidjson::Document::AllocatorType& allocator) {
+        value.SetString(data.data, data.size, allocator);
+    }
+};
+
+template <>
+struct JsonParser<'0'> {
+    // null
+    static void update_value(StringParser::ParseResult& result, rapidjson::Value& value,
+                             StringRef data, rapidjson::Document::AllocatorType& allocator) {
+        value.SetNull();
+    }
+};
+
+template <>
+struct JsonParser<'1'> {
+    // bool
+    static void update_value(StringParser::ParseResult& result, rapidjson::Value& value,
+                             StringRef data, rapidjson::Document::AllocatorType& allocator) {
+        DCHECK(data.size == 1 || strncmp(data.data, "true", 4) == 0 ||
+               strncmp(data.data, "false", 5) == 0);
+        value.SetBool((*data.data == '1' || *data.data == 't') ? true : false);
+    }
+};
+
+template <>
+struct JsonParser<'2'> {
+    // int
+    static void update_value(StringParser::ParseResult& result, rapidjson::Value& value,
+                             StringRef data, rapidjson::Document::AllocatorType& allocator) {
+        value.SetInt(StringParser::string_to_int<int32_t>(data.data, data.size, &result));
+    }
+};
+
+template <>
+struct JsonParser<'3'> {
+    // double
+    static void update_value(StringParser::ParseResult& result, rapidjson::Value& value,
+                             StringRef data, rapidjson::Document::AllocatorType& allocator) {
+        value.SetDouble(StringParser::string_to_float<double>(data.data, data.size, &result));
+    }
+};
+
+template <>
+struct JsonParser<'4'> {
+    // time
+    static void update_value(StringParser::ParseResult& result, rapidjson::Value& value,
+                             StringRef data, rapidjson::Document::AllocatorType& allocator) {
+        // remove double quotes, "xxx" -> xxx
+        value.SetString(data.data + 1, data.size - 2, allocator);
+    }
+};
+
+template <>
+struct JsonParser<'5'> {
+    // bigint
+    static void update_value(StringParser::ParseResult& result, rapidjson::Value& value,
+                             StringRef data, rapidjson::Document::AllocatorType& allocator) {
+        value.SetInt64(StringParser::string_to_int<int64_t>(data.data, data.size, &result));
+    }
+};
+
+template <int flag, typename Impl>
+struct ExecuteReducer {
+    template <typename... TArgs>
+    static void run(TArgs&&... args) {
+        Impl::template execute_type<JsonParser<flag>>(std::forward<TArgs>(args)...);
+    }
+};
+
+struct FunctionJsonArrayImpl {
+    static constexpr auto name = "json_array";
+
+    template <int flag>
+    using Reducer = ExecuteReducer<flag, FunctionJsonArrayImpl>;
+
+    static void execute_parse(const std::string& type_flags,
+                              const std::vector<const ColumnString*>& data_columns,
+                              std::vector<rapidjson::Value>& objects,
+                              rapidjson::Document::AllocatorType& allocator,
+                              const std::vector<const ColumnUInt8*>& nullmaps) {
+        for (int i = 0; i < data_columns.size() - 1; i++) {
+            constexpr_int_match<'0', '6', Reducer>::run(type_flags[i], objects, allocator,
+                                                        data_columns[i], nullmaps[i]);
+        }
+    }
+
+    template <typename TypeImpl>
+    static void execute_type(std::vector<rapidjson::Value>& objects,
+                             rapidjson::Document::AllocatorType& allocator,
+                             const ColumnString* data_column, const ColumnUInt8* nullmap) {
+        StringParser::ParseResult result;
+        rapidjson::Value value;
+
+        for (int i = 0; i < objects.size(); i++) {
+            if (nullmap != nullptr && nullmap->get_data()[i]) {
+                JsonParser<'0'>::update_value(result, value, data_column->get_data_at(i),
+                                              allocator);
+            } else {
+                TypeImpl::update_value(result, value, data_column->get_data_at(i), allocator);
+            }
+            objects[i].PushBack(value, allocator);
+        }
+    }
+};
+
+struct FunctionJsonObjectImpl {
+    static constexpr auto name = "json_object";
+
+    template <int flag>
+    using Reducer = ExecuteReducer<flag, FunctionJsonObjectImpl>;
+
+    static void execute_parse(std::string type_flags,
+                              const std::vector<const ColumnString*>& data_columns,
+                              std::vector<rapidjson::Value>& objects,
+                              rapidjson::Document::AllocatorType& allocator,
+                              const std::vector<const ColumnUInt8*>& nullmaps) {
+        for (auto& array_object : objects) {
+            array_object.SetObject();
+        }
+
+        for (int i = 0; i + 1 < data_columns.size() - 1; i += 2) {
+            constexpr_int_match<'0', '6', Reducer>::run(type_flags[i + 1], objects, allocator,
+                                                        data_columns[i], data_columns[i + 1],
+                                                        nullmaps[i + 1]);
+        }
+    }
+
+    template <typename TypeImpl>
+    static void execute_type(std::vector<rapidjson::Value>& objects,
+                             rapidjson::Document::AllocatorType& allocator,
+                             const ColumnString* key_column, const ColumnString* value_column,
+                             const ColumnUInt8* nullmap) {
+        StringParser::ParseResult result;
+        rapidjson::Value key;
+        rapidjson::Value value;
+        for (int i = 0; i < objects.size(); i++) {
+            JsonParser<'6'>::update_value(result, key, key_column->get_data_at(i),
+                                          allocator); // key always is string
+            if (nullmap != nullptr && nullmap->get_data()[i]) {
+                JsonParser<'0'>::update_value(result, value, value_column->get_data_at(i),
+                                              allocator);
+            } else {
+                TypeImpl::update_value(result, value, value_column->get_data_at(i), allocator);
+            }
+            objects[i].AddMember(key, value, allocator);
+        }
+    }
+};
+
+template <typename SpecificImpl>
+class FunctionJsonAlwaysNotNullable : public IFunction {
+public:
+    using IFunction::execute;
+
+    static constexpr auto name = SpecificImpl::name;
+
+    static FunctionPtr create() {
+        return std::make_shared<FunctionJsonAlwaysNotNullable<SpecificImpl>>();
+    }
+
+    bool use_default_implementation_for_nulls() const override { return false; }
+
+    String get_name() const override { return name; }
+
+    size_t get_number_of_arguments() const override { return 0; }
+
+    bool is_variadic() const override { return true; }
+
+    DataTypePtr get_return_type_impl(const DataTypes& arguments) const override {
+        return std::make_shared<DataTypeString>();
+    }
+
+    Status execute_impl(FunctionContext* context, Block& block, const ColumnNumbers& arguments,
+                        size_t result, size_t input_rows_count) override {
+        auto result_column = ColumnString::create();
+
+        std::vector<ColumnPtr> column_ptrs; // prevent converted column destruct
+        std::vector<const ColumnString*> data_columns;
+        std::vector<const ColumnUInt8*> nullmaps;
+        for (int i = 0; i < arguments.size(); i++) {
+            auto column = block.get_by_position(arguments[i]).column;
+            column_ptrs.push_back(column->convert_to_full_column_if_const());
+            const ColumnNullable* col_nullable =
+                    check_and_get_column<ColumnNullable>(column_ptrs.back().get());
+            if (col_nullable) {
+                const ColumnUInt8* col_nullmap = check_and_get_column<ColumnUInt8>(
+                        col_nullable->get_null_map_column_ptr().get());
+                nullmaps.push_back(col_nullmap);
+                const ColumnString* col = check_and_get_column<ColumnString>(
+                        col_nullable->get_nested_column_ptr().get());
+                data_columns.push_back(col);
+            } else {
+                nullmaps.push_back(nullptr);
+                data_columns.push_back(assert_cast<const ColumnString*>(column_ptrs.back().get()));
+            }
+        }
+        execute(data_columns, *assert_cast<ColumnString*>(result_column.get()), input_rows_count,
+                nullmaps);
+        block.get_by_position(result).column = std::move(result_column);
+        return Status::OK();
+    }
+
+    static void execute(const std::vector<const ColumnString*>& data_columns,
+                        ColumnString& result_column, size_t input_rows_count,
+                        const std::vector<const ColumnUInt8*> nullmaps) {
+        std::string type_flags = data_columns.back()->get_data_at(0).to_string();
+
+        rapidjson::Document document;
+        rapidjson::Document::AllocatorType& allocator = document.GetAllocator();
+
+        std::vector<rapidjson::Value> objects;
+        for (int i = 0; i < input_rows_count; i++) {
+            objects.emplace_back(rapidjson::kArrayType);
+        }
+
+        SpecificImpl::execute_parse(type_flags, data_columns, objects, allocator, nullmaps);
+
+        rapidjson::StringBuffer buf;
+        rapidjson::Writer<rapidjson::StringBuffer> writer(buf);
+
+        for (int i = 0; i < input_rows_count; i++) {
+            buf.Clear();
+            writer.Reset(buf);
+            objects[i].Accept(writer);
+            result_column.insert_data(buf.GetString(), buf.GetSize());
+        }
+    }
+};
+
+struct FunctionJsonQuoteImpl {
+    static constexpr auto name = "json_quote";
+
+    static void execute(const std::vector<const ColumnString*>& data_columns,
+                        ColumnString& result_column, size_t input_rows_count) {
+        rapidjson::Document document;
+        rapidjson::Document::AllocatorType& allocator = document.GetAllocator();
+
+        rapidjson::Value value;
+
+        rapidjson::StringBuffer buf;
+        rapidjson::Writer<rapidjson::StringBuffer> writer(buf);
+
+        for (int i = 0; i < input_rows_count; i++) {
+            StringRef data = data_columns[0]->get_data_at(i);
+            value.SetString(data.data, data.size, allocator);
+
+            buf.Clear();
+            value.Accept(writer);
+            result_column.insert_data(buf.GetString(), buf.GetSize());
+        }
+    }
+};
+
+struct FunctionJsonExtractImpl {
+    static constexpr auto name = "json_extract";
+
+    static rapidjson::Value parse_json(const ColumnString* json_col, const ColumnString* path_col,
+                                       rapidjson::Document::AllocatorType& allocator,
+                                       const int row) {
+        rapidjson::Value value;
+        rapidjson::Document document;
+
+        const auto obj = json_col->get_data_at(row);
+        std::string_view json_string(obj.data, obj.size);
+        const auto path = path_col->get_data_at(row);
+        std::string_view path_string(path.data, path.size);
+
+        auto root = get_json_object<JSON_FUN_STRING>(json_string, path_string, &document);
+        if (root != nullptr) {
+            value.CopyFrom(*root, allocator);
+        }
+        return value;
+    }
+
+    static void execute(const std::vector<const ColumnString*>& data_columns,
+                        ColumnString& result_column, size_t input_rows_count) {
+        rapidjson::Document document;
+        rapidjson::Document::AllocatorType& allocator = document.GetAllocator();
+        rapidjson::StringBuffer buf;
+        rapidjson::Writer<rapidjson::StringBuffer> writer(buf);
+
+        const auto json_col = data_columns[0];
+        for (size_t row = 0; row < input_rows_count; row++) {
+            rapidjson::Value value;
+            if (data_columns.size() == 2) {
+                value = parse_json(json_col, data_columns[1], allocator, row);
+            } else {
+                value.SetArray();
+                value.Reserve(data_columns.size() - 1, allocator);
+                for (size_t col = 1; col < data_columns.size(); ++col) {
+                    value.PushBack(parse_json(json_col, data_columns[col], allocator, row),
+                                   allocator);
+                }
+            }
+
+            // write value as string
+            buf.Clear();
+            writer.Reset(buf);
+            value.Accept(writer);
+            result_column.insert_data(buf.GetString(), buf.GetSize());
+        }
+    }
+};
+
+template <typename Impl>
+class FunctionJson : public IFunction {
+public:
+    static constexpr auto name = Impl::name;
+
+    static FunctionPtr create() { return std::make_shared<FunctionJson<Impl>>(); }
+
+    String get_name() const override { return name; }
+
+    size_t get_number_of_arguments() const override { return 0; }
+
+    bool is_variadic() const override { return true; }

Review Comment:
   warning: function 'is_variadic' should be marked [[nodiscard]] [modernize-use-nodiscard]
   
   ```suggestion
       [[nodiscard]] bool is_variadic() const override { return true; }
   ```
   



##########
function_json.cpp:
##########
@@ -0,0 +1,1320 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#include <rapidjson/allocators.h>
+#include <rapidjson/document.h>
+#include <rapidjson/encodings.h>
+#include <rapidjson/pointer.h>
+#include <rapidjson/rapidjson.h>
+#include <rapidjson/stringbuffer.h>
+#include <rapidjson/writer.h>
+#include <re2/re2.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <algorithm>
+#include <boost/iterator/iterator_facade.hpp>
+#include <boost/token_functions.hpp>
+#include <boost/tokenizer.hpp>
+#include <memory>
+#include <string>
+#include <string_view>
+#include <type_traits>
+#include <utility>
+#include <vector>
+
+// IWYU pragma: no_include <opentelemetry/common/threadlocal.h>
+#include "common/compiler_util.h" // IWYU pragma: keep
+#include "common/status.h"
+#include "exprs/json_functions.h"
+#ifdef __AVX2__
+#include "util/jsonb_parser_simd.h"
+#else
+#include "util/jsonb_parser.h"
+#endif
+#include "util/string_parser.hpp"
+#include "util/string_util.h"
+#include "vec/aggregate_functions/aggregate_function.h"
+#include "vec/columns/column.h"
+#include "vec/columns/column_nullable.h"
+#include "vec/columns/column_string.h"
+#include "vec/columns/column_vector.h"
+#include "vec/columns/columns_number.h"
+#include "vec/common/assert_cast.h"
+#include "vec/common/string_ref.h"
+#include "vec/core/block.h"
+#include "vec/core/column_numbers.h"
+#include "vec/core/column_with_type_and_name.h"
+#include "vec/core/types.h"
+#include "vec/data_types/data_type.h"
+#include "vec/data_types/data_type_nullable.h"
+#include "vec/data_types/data_type_number.h"
+#include "vec/data_types/data_type_string.h"
+#include "vec/functions/function.h"
+#include "vec/functions/function_string.h"
+#include "vec/functions/function_totype.h"
+#include "vec/functions/simple_function_factory.h"
+#include "vec/utils/template_helpers.hpp"
+
+namespace doris {
+class FunctionContext;
+} // namespace doris
+
+namespace doris::vectorized {
+static const re2::RE2 JSON_PATTERN("^([^\\\"\\[\\]]*)(?:\\[([0-9]+|\\*)\\])?");
+
+template <typename T, typename U>
+void char_split(std::vector<T>& res, const U& var, char p) {
+    int start = 0;
+    int pos = start;
+    int end = var.length();
+    while (pos < end) {
+        while (var[pos] != p && pos < end) {
+            pos++;
+        }
+        res.emplace_back(&var[start], pos - start);
+        pos++;
+        start = pos;
+    }
+}
+
+// T = std::vector<std::string>
+// TODO: update RE2 to support std::vector<std::string_view>
+template <typename T>
+void get_parsed_paths(const T& path_exprs, std::vector<JsonPath>* parsed_paths) {
+    if (path_exprs.empty()) {
+        return;
+    }
+
+    if (path_exprs[0] != "$") {
+        parsed_paths->emplace_back("", -1, false);
+    } else {
+        parsed_paths->emplace_back("$", -1, true);
+    }
+
+    for (int i = 1; i < path_exprs.size(); i++) {
+        std::string col;
+        std::string index;
+        if (UNLIKELY(!RE2::FullMatch(path_exprs[i], JSON_PATTERN, &col, &index))) {
+            parsed_paths->emplace_back("", -1, false);
+        } else {
+            int idx = -1;
+            if (!index.empty()) {
+                if (index == "*") {
+                    idx = -2;
+                } else {
+                    idx = atoi(index.c_str());
+                }
+            }
+            parsed_paths->emplace_back(col, idx, true);
+        }
+    }
+}
+
+rapidjson::Value* match_value(const std::vector<JsonPath>& parsed_paths, rapidjson::Value* document,
+                              rapidjson::Document::AllocatorType& mem_allocator,
+                              bool is_insert_null = false) {
+    rapidjson::Value* root = document;
+    rapidjson::Value* array_obj = nullptr;
+    for (int i = 1; i < parsed_paths.size(); i++) {
+        if (root == nullptr || root->IsNull()) {
+            return nullptr;
+        }
+
+        if (UNLIKELY(!parsed_paths[i].is_valid)) {
+            return nullptr;
+        }
+
+        const std::string& col = parsed_paths[i].key;
+        int index = parsed_paths[i].idx;
+        if (LIKELY(!col.empty())) {
+            if (root->IsArray()) {
+                array_obj = static_cast<rapidjson::Value*>(
+                        mem_allocator.Malloc(sizeof(rapidjson::Value)));
+                array_obj->SetArray();
+                bool is_null = true;
+
+                // if array ,loop the array,find out all Objects,then find the results from the objects
+                for (int j = 0; j < root->Size(); j++) {
+                    rapidjson::Value* json_elem = &((*root)[j]);
+
+                    if (json_elem->IsArray() || json_elem->IsNull()) {
+                        continue;
+                    } else {
+                        if (!json_elem->IsObject()) {
+                            continue;
+                        }
+                        if (!json_elem->HasMember(col.c_str())) {
+                            if (is_insert_null) { // not found item, then insert a null object.
+                                is_null = false;
+                                rapidjson::Value nullObject(rapidjson::kNullType);
+                                array_obj->PushBack(nullObject, mem_allocator);
+                            }
+                            continue;
+                        }
+                        rapidjson::Value* obj = &((*json_elem)[col.c_str()]);
+                        if (obj->IsArray()) {
+                            is_null = false;
+                            for (int k = 0; k < obj->Size(); k++) {
+                                array_obj->PushBack((*obj)[k], mem_allocator);
+                            }
+                        } else if (!obj->IsNull()) {
+                            is_null = false;
+                            array_obj->PushBack(*obj, mem_allocator);
+                        }
+                    }
+                }
+
+                root = is_null ? &(array_obj->SetNull()) : array_obj;
+            } else if (root->IsObject()) {
+                if (!root->HasMember(col.c_str())) {
+                    return nullptr;
+                } else {
+                    root = &((*root)[col.c_str()]);
+                }
+            } else {
+                // root is not a nested type, return NULL
+                return nullptr;
+            }
+        }
+
+        if (UNLIKELY(index != -1)) {
+            // judge the rapidjson:Value, which base the top's result,
+            // if not array return NULL;else get the index value from the array
+            if (root->IsArray()) {
+                if (root->IsNull()) {
+                    return nullptr;
+                } else if (index == -2) {
+                    // [*]
+                    array_obj = static_cast<rapidjson::Value*>(
+                            mem_allocator.Malloc(sizeof(rapidjson::Value)));
+                    array_obj->SetArray();
+
+                    for (int j = 0; j < root->Size(); j++) {
+                        rapidjson::Value v;
+                        v.CopyFrom((*root)[j], mem_allocator);
+                        array_obj->PushBack(v, mem_allocator);
+                    }
+                    root = array_obj;
+                } else if (index >= root->Size()) {
+                    return nullptr;
+                } else {
+                    root = &((*root)[index]);
+                }
+            } else {
+                return nullptr;
+            }
+        }
+    }
+    return root;
+}
+
+template <JsonFunctionType fntype>
+rapidjson::Value* get_json_object(std::string_view json_string, std::string_view path_string,
+                                  rapidjson::Document* document) {
+    std::vector<JsonPath>* parsed_paths;
+    std::vector<JsonPath> tmp_parsed_paths;
+
+#ifdef USE_LIBCPP
+    std::string s(path_string);
+    auto tok = get_json_token(s);
+#else
+    auto tok = get_json_token(path_string);
+#endif
+    std::vector<std::string> paths(tok.begin(), tok.end());
+    get_parsed_paths(paths, &tmp_parsed_paths);
+    if (tmp_parsed_paths.empty()) {
+        return document;
+    }
+
+    parsed_paths = &tmp_parsed_paths;
+
+    if (!(*parsed_paths)[0].is_valid) {
+        return document;
+    }
+
+    if (UNLIKELY((*parsed_paths).size() == 1)) {
+        if (fntype == JSON_FUN_STRING) {
+            document->SetString(json_string.data(), json_string.size(), document->GetAllocator());
+        } else {
+            return document;
+        }
+    }
+
+    document->Parse(json_string.data(), json_string.size());
+    if (UNLIKELY(document->HasParseError())) {
+        // VLOG_CRITICAL << "Error at offset " << document->GetErrorOffset() << ": "
+        //         << GetParseError_En(document->GetParseError());
+        document->SetNull();
+        return document;
+    }
+
+    return match_value(*parsed_paths, document, document->GetAllocator());
+}
+
+template <typename NumberType>
+struct GetJsonNumberType {
+    using ReturnType = typename NumberType::ReturnType;
+    using ColumnType = typename NumberType::ColumnType;
+    using Container = typename ColumnType::Container;
+
+    static void get_json_impl(rapidjson::Value*& root, const std::string_view& json_string,
+                              const std::string_view& path_string, rapidjson::Document& document,
+                              typename NumberType::T& res, UInt8& null_map) {
+        if constexpr (std::is_same_v<double, typename NumberType::T>) {
+            root = get_json_object<JSON_FUN_DOUBLE>(json_string, path_string, &document);
+            handle_result<double>(root, res, null_map);
+        } else if constexpr (std::is_same_v<int32_t, typename NumberType::T>) {
+            root = get_json_object<JSON_FUN_DOUBLE>(json_string, path_string, &document);
+            handle_result<int32_t>(root, res, null_map);
+        } else if constexpr (std::is_same_v<int64_t, typename NumberType::T>) {
+            root = get_json_object<JSON_FUN_DOUBLE>(json_string, path_string, &document);
+            handle_result<int64_t>(root, res, null_map);
+        }
+    }
+    static void vector_vector(FunctionContext* context, const ColumnString::Chars& ldata,
+                              const ColumnString::Offsets& loffsets,
+                              const ColumnString::Chars& rdata,
+                              const ColumnString::Offsets& roffsets, Container& res,
+                              NullMap& null_map) {
+        size_t size = loffsets.size();
+        res.resize(size);
+        for (size_t i = 0; i < size; ++i) {
+            const char* l_raw_str = reinterpret_cast<const char*>(&ldata[loffsets[i - 1]]);
+            int l_str_size = loffsets[i] - loffsets[i - 1];
+            const char* r_raw_str = reinterpret_cast<const char*>(&rdata[roffsets[i - 1]]);
+            int r_str_size = roffsets[i] - roffsets[i - 1];
+            if (null_map[i]) {
+                res[i] = 0;
+                continue;
+            }
+
+            std::string_view json_string(l_raw_str, l_str_size);
+            std::string_view path_string(r_raw_str, r_str_size);
+            rapidjson::Document document;
+            rapidjson::Value* root = nullptr;
+
+            get_json_impl(root, json_string, path_string, document, res[i], null_map[i]);
+        }
+    }
+    static void vector_scalar(FunctionContext* context, const ColumnString::Chars& ldata,
+                              const ColumnString::Offsets& loffsets, const StringRef& rdata,
+                              Container& res, NullMap& null_map) {
+        size_t size = loffsets.size();
+        res.resize(size);
+        std::string_view path_string(rdata.data, rdata.size);
+        for (size_t i = 0; i < size; ++i) {
+            const char* l_raw_str = reinterpret_cast<const char*>(&ldata[loffsets[i - 1]]);
+            int l_str_size = loffsets[i] - loffsets[i - 1];
+            if (null_map[i]) {
+                res[i] = 0;
+                continue;
+            }
+            std::string_view json_string(l_raw_str, l_str_size);
+
+            rapidjson::Document document;
+            rapidjson::Value* root = nullptr;
+
+            get_json_impl(root, json_string, path_string, document, res[i], null_map[i]);
+        }
+    }
+    static void scalar_vector(FunctionContext* context, const StringRef& ldata,
+                              const ColumnString::Chars& rdata,
+                              const ColumnString::Offsets& roffsets, Container& res,
+                              NullMap& null_map) {
+        size_t size = roffsets.size();
+        res.resize(size);
+        std::string_view json_string(ldata.data, ldata.size);
+        for (size_t i = 0; i < size; ++i) {
+            const char* r_raw_str = reinterpret_cast<const char*>(&rdata[roffsets[i - 1]]);
+            int r_str_size = roffsets[i] - roffsets[i - 1];
+            if (null_map[i]) {
+                res[i] = 0;
+                continue;
+            }
+            std::string_view path_string(r_raw_str, r_str_size);
+            rapidjson::Document document;
+            rapidjson::Value* root = nullptr;
+
+            get_json_impl(root, json_string, path_string, document, res[i], null_map[i]);
+        }
+    }
+
+    template <typename T, std::enable_if_t<std::is_same_v<double, T>, T>* = nullptr>
+    static void handle_result(rapidjson::Value* root, T& res, uint8_t& res_null) {
+        if (root == nullptr || root->IsNull()) {
+            res = 0;
+            res_null = 1;
+        } else if (root->IsInt()) {
+            res = root->GetInt();
+        } else if (root->IsInt64()) {
+            res = root->GetInt64();
+        } else if (root->IsDouble()) {
+            res = root->GetDouble();
+        } else {
+            res_null = 1;
+        }
+    }
+
+    template <typename T, std::enable_if_t<std::is_same_v<int32_t, T>, T>* = nullptr>
+    static void handle_result(rapidjson::Value* root, int32_t& res, uint8_t& res_null) {
+        if (root != nullptr && root->IsInt()) {
+            res = root->GetInt();
+        } else {
+            res_null = 1;
+        }
+    }
+
+    template <typename T, std::enable_if_t<std::is_same_v<int64_t, T>, T>* = nullptr>
+    static void handle_result(rapidjson::Value* root, int64_t& res, uint8_t& res_null) {
+        if (root != nullptr && root->IsInt64()) {
+            res = root->GetInt64();
+        } else {
+            res_null = 1;
+        }
+    }
+};
+
+// Helper Class
+struct JsonNumberTypeDouble {
+    using T = Float64;
+    using ReturnType = DataTypeFloat64;
+    using ColumnType = ColumnVector<T>;
+};
+
+struct JsonNumberTypeInt {
+    using T = int32_t;
+    using ReturnType = DataTypeInt32;
+    using ColumnType = ColumnVector<T>;
+};
+
+struct JsonNumberTypeBigInt {
+    using T = int64_t;
+    using ReturnType = DataTypeInt64;
+    using ColumnType = ColumnVector<T>;
+};
+
+struct GetJsonDouble : public GetJsonNumberType<JsonNumberTypeDouble> {
+    static constexpr auto name = "get_json_double";
+    using ReturnType = typename JsonNumberTypeDouble::ReturnType;
+    using ColumnType = typename JsonNumberTypeDouble::ColumnType;
+};
+
+struct GetJsonInt : public GetJsonNumberType<JsonNumberTypeInt> {
+    static constexpr auto name = "get_json_int";
+    using ReturnType = typename JsonNumberTypeInt::ReturnType;
+    using ColumnType = typename JsonNumberTypeInt::ColumnType;
+};
+
+struct GetJsonBigInt : public GetJsonNumberType<JsonNumberTypeBigInt> {
+    static constexpr auto name = "get_json_bigint";
+    using ReturnType = typename JsonNumberTypeBigInt::ReturnType;
+    using ColumnType = typename JsonNumberTypeBigInt::ColumnType;
+};
+
+struct GetJsonString {
+    static constexpr auto name = "get_json_string";
+    using ReturnType = DataTypeString;
+    using ColumnType = ColumnString;
+    using Chars = ColumnString::Chars;
+    using Offsets = ColumnString::Offsets;
+    static void vector_vector(FunctionContext* context, const Chars& ldata, const Offsets& loffsets,
+                              const Chars& rdata, const Offsets& roffsets, Chars& res_data,
+                              Offsets& res_offsets, NullMap& null_map) {
+        size_t input_rows_count = loffsets.size();
+        res_offsets.resize(input_rows_count);
+
+        for (size_t i = 0; i < input_rows_count; ++i) {
+            if (null_map[i]) {
+                StringOP::push_null_string(i, res_data, res_offsets, null_map);
+                continue;
+            }
+            int l_size = loffsets[i] - loffsets[i - 1];
+            const auto l_raw = reinterpret_cast<const char*>(&ldata[loffsets[i - 1]]);
+            int r_size = roffsets[i] - roffsets[i - 1];
+            const auto r_raw = reinterpret_cast<const char*>(&rdata[roffsets[i - 1]]);
+
+            std::string_view json_string(l_raw, l_size);
+            std::string_view path_string(r_raw, r_size);
+
+            execute_impl(json_string, path_string, res_data, res_offsets, null_map, i);
+        }
+    }
+    static void vector_scalar(FunctionContext* context, const Chars& ldata, const Offsets& loffsets,
+                              const StringRef& rdata, Chars& res_data, Offsets& res_offsets,
+                              NullMap& null_map) {
+        size_t input_rows_count = loffsets.size();
+        res_offsets.resize(input_rows_count);
+
+        for (size_t i = 0; i < input_rows_count; ++i) {
+            if (null_map[i]) {
+                StringOP::push_null_string(i, res_data, res_offsets, null_map);
+                continue;
+            }
+            int l_size = loffsets[i] - loffsets[i - 1];
+            const auto l_raw = reinterpret_cast<const char*>(&ldata[loffsets[i - 1]]);
+
+            std::string_view json_string(l_raw, l_size);
+            std::string_view path_string(rdata.data, rdata.size);
+
+            execute_impl(json_string, path_string, res_data, res_offsets, null_map, i);
+        }
+    }
+    static void scalar_vector(FunctionContext* context, const StringRef& ldata, const Chars& rdata,
+                              const Offsets& roffsets, Chars& res_data, Offsets& res_offsets,
+                              NullMap& null_map) {
+        size_t input_rows_count = roffsets.size();
+        res_offsets.resize(input_rows_count);
+
+        for (size_t i = 0; i < input_rows_count; ++i) {
+            if (null_map[i]) {
+                StringOP::push_null_string(i, res_data, res_offsets, null_map);
+                continue;
+            }
+            int r_size = roffsets[i] - roffsets[i - 1];
+            const auto r_raw = reinterpret_cast<const char*>(&rdata[roffsets[i - 1]]);
+
+            std::string_view json_string(ldata.data, ldata.size);
+            std::string_view path_string(r_raw, r_size);
+
+            execute_impl(json_string, path_string, res_data, res_offsets, null_map, i);
+        }
+    }
+
+    static void execute_impl(const std::string_view& json_string,
+                             const std::string_view& path_string, Chars& res_data,
+                             Offsets& res_offsets, NullMap& null_map, size_t index_now) {
+        rapidjson::Document document;
+        rapidjson::Value* root = nullptr;
+
+        root = get_json_object<JSON_FUN_STRING>(json_string, path_string, &document);
+        const int max_string_len = 65535;
+
+        if (root == nullptr || root->IsNull()) {
+            StringOP::push_null_string(index_now, res_data, res_offsets, null_map);
+        } else if (root->IsString()) {
+            const auto ptr = root->GetString();
+            size_t len = strnlen(ptr, max_string_len);
+            StringOP::push_value_string(std::string_view(ptr, len), index_now, res_data,
+                                        res_offsets);
+        } else {
+            rapidjson::StringBuffer buf;
+            rapidjson::Writer<rapidjson::StringBuffer> writer(buf);
+            root->Accept(writer);
+
+            const auto ptr = buf.GetString();
+            size_t len = strnlen(ptr, max_string_len);
+            StringOP::push_value_string(std::string_view(ptr, len), index_now, res_data,
+                                        res_offsets);
+        }
+    }
+};
+
+template <int flag>
+struct JsonParser {
+    //string
+    static void update_value(StringParser::ParseResult& result, rapidjson::Value& value,
+                             StringRef data, rapidjson::Document::AllocatorType& allocator) {
+        value.SetString(data.data, data.size, allocator);
+    }
+};
+
+template <>
+struct JsonParser<'0'> {
+    // null
+    static void update_value(StringParser::ParseResult& result, rapidjson::Value& value,
+                             StringRef data, rapidjson::Document::AllocatorType& allocator) {
+        value.SetNull();
+    }
+};
+
+template <>
+struct JsonParser<'1'> {
+    // bool
+    static void update_value(StringParser::ParseResult& result, rapidjson::Value& value,
+                             StringRef data, rapidjson::Document::AllocatorType& allocator) {
+        DCHECK(data.size == 1 || strncmp(data.data, "true", 4) == 0 ||
+               strncmp(data.data, "false", 5) == 0);
+        value.SetBool((*data.data == '1' || *data.data == 't') ? true : false);
+    }
+};
+
+template <>
+struct JsonParser<'2'> {
+    // int
+    static void update_value(StringParser::ParseResult& result, rapidjson::Value& value,
+                             StringRef data, rapidjson::Document::AllocatorType& allocator) {
+        value.SetInt(StringParser::string_to_int<int32_t>(data.data, data.size, &result));
+    }
+};
+
+template <>
+struct JsonParser<'3'> {
+    // double
+    static void update_value(StringParser::ParseResult& result, rapidjson::Value& value,
+                             StringRef data, rapidjson::Document::AllocatorType& allocator) {
+        value.SetDouble(StringParser::string_to_float<double>(data.data, data.size, &result));
+    }
+};
+
+template <>
+struct JsonParser<'4'> {
+    // time
+    static void update_value(StringParser::ParseResult& result, rapidjson::Value& value,
+                             StringRef data, rapidjson::Document::AllocatorType& allocator) {
+        // remove double quotes, "xxx" -> xxx
+        value.SetString(data.data + 1, data.size - 2, allocator);
+    }
+};
+
+template <>
+struct JsonParser<'5'> {
+    // bigint
+    static void update_value(StringParser::ParseResult& result, rapidjson::Value& value,
+                             StringRef data, rapidjson::Document::AllocatorType& allocator) {
+        value.SetInt64(StringParser::string_to_int<int64_t>(data.data, data.size, &result));
+    }
+};
+
+template <int flag, typename Impl>
+struct ExecuteReducer {
+    template <typename... TArgs>
+    static void run(TArgs&&... args) {
+        Impl::template execute_type<JsonParser<flag>>(std::forward<TArgs>(args)...);
+    }
+};
+
+struct FunctionJsonArrayImpl {
+    static constexpr auto name = "json_array";
+
+    template <int flag>
+    using Reducer = ExecuteReducer<flag, FunctionJsonArrayImpl>;
+
+    static void execute_parse(const std::string& type_flags,
+                              const std::vector<const ColumnString*>& data_columns,
+                              std::vector<rapidjson::Value>& objects,
+                              rapidjson::Document::AllocatorType& allocator,
+                              const std::vector<const ColumnUInt8*>& nullmaps) {
+        for (int i = 0; i < data_columns.size() - 1; i++) {
+            constexpr_int_match<'0', '6', Reducer>::run(type_flags[i], objects, allocator,
+                                                        data_columns[i], nullmaps[i]);
+        }
+    }
+
+    template <typename TypeImpl>
+    static void execute_type(std::vector<rapidjson::Value>& objects,
+                             rapidjson::Document::AllocatorType& allocator,
+                             const ColumnString* data_column, const ColumnUInt8* nullmap) {
+        StringParser::ParseResult result;
+        rapidjson::Value value;
+
+        for (int i = 0; i < objects.size(); i++) {
+            if (nullmap != nullptr && nullmap->get_data()[i]) {
+                JsonParser<'0'>::update_value(result, value, data_column->get_data_at(i),
+                                              allocator);
+            } else {
+                TypeImpl::update_value(result, value, data_column->get_data_at(i), allocator);
+            }
+            objects[i].PushBack(value, allocator);
+        }
+    }
+};
+
+struct FunctionJsonObjectImpl {
+    static constexpr auto name = "json_object";
+
+    template <int flag>
+    using Reducer = ExecuteReducer<flag, FunctionJsonObjectImpl>;
+
+    static void execute_parse(std::string type_flags,
+                              const std::vector<const ColumnString*>& data_columns,
+                              std::vector<rapidjson::Value>& objects,
+                              rapidjson::Document::AllocatorType& allocator,
+                              const std::vector<const ColumnUInt8*>& nullmaps) {
+        for (auto& array_object : objects) {
+            array_object.SetObject();
+        }
+
+        for (int i = 0; i + 1 < data_columns.size() - 1; i += 2) {
+            constexpr_int_match<'0', '6', Reducer>::run(type_flags[i + 1], objects, allocator,
+                                                        data_columns[i], data_columns[i + 1],
+                                                        nullmaps[i + 1]);
+        }
+    }
+
+    template <typename TypeImpl>
+    static void execute_type(std::vector<rapidjson::Value>& objects,
+                             rapidjson::Document::AllocatorType& allocator,
+                             const ColumnString* key_column, const ColumnString* value_column,
+                             const ColumnUInt8* nullmap) {
+        StringParser::ParseResult result;
+        rapidjson::Value key;
+        rapidjson::Value value;
+        for (int i = 0; i < objects.size(); i++) {
+            JsonParser<'6'>::update_value(result, key, key_column->get_data_at(i),
+                                          allocator); // key always is string
+            if (nullmap != nullptr && nullmap->get_data()[i]) {
+                JsonParser<'0'>::update_value(result, value, value_column->get_data_at(i),
+                                              allocator);
+            } else {
+                TypeImpl::update_value(result, value, value_column->get_data_at(i), allocator);
+            }
+            objects[i].AddMember(key, value, allocator);
+        }
+    }
+};
+
+template <typename SpecificImpl>
+class FunctionJsonAlwaysNotNullable : public IFunction {
+public:
+    using IFunction::execute;
+
+    static constexpr auto name = SpecificImpl::name;
+
+    static FunctionPtr create() {
+        return std::make_shared<FunctionJsonAlwaysNotNullable<SpecificImpl>>();
+    }
+
+    bool use_default_implementation_for_nulls() const override { return false; }
+
+    String get_name() const override { return name; }
+
+    size_t get_number_of_arguments() const override { return 0; }
+
+    bool is_variadic() const override { return true; }
+
+    DataTypePtr get_return_type_impl(const DataTypes& arguments) const override {
+        return std::make_shared<DataTypeString>();
+    }
+
+    Status execute_impl(FunctionContext* context, Block& block, const ColumnNumbers& arguments,
+                        size_t result, size_t input_rows_count) override {
+        auto result_column = ColumnString::create();
+
+        std::vector<ColumnPtr> column_ptrs; // prevent converted column destruct
+        std::vector<const ColumnString*> data_columns;
+        std::vector<const ColumnUInt8*> nullmaps;
+        for (int i = 0; i < arguments.size(); i++) {
+            auto column = block.get_by_position(arguments[i]).column;
+            column_ptrs.push_back(column->convert_to_full_column_if_const());
+            const ColumnNullable* col_nullable =
+                    check_and_get_column<ColumnNullable>(column_ptrs.back().get());
+            if (col_nullable) {
+                const ColumnUInt8* col_nullmap = check_and_get_column<ColumnUInt8>(
+                        col_nullable->get_null_map_column_ptr().get());
+                nullmaps.push_back(col_nullmap);
+                const ColumnString* col = check_and_get_column<ColumnString>(
+                        col_nullable->get_nested_column_ptr().get());
+                data_columns.push_back(col);
+            } else {
+                nullmaps.push_back(nullptr);
+                data_columns.push_back(assert_cast<const ColumnString*>(column_ptrs.back().get()));
+            }
+        }
+        execute(data_columns, *assert_cast<ColumnString*>(result_column.get()), input_rows_count,
+                nullmaps);
+        block.get_by_position(result).column = std::move(result_column);
+        return Status::OK();
+    }
+
+    static void execute(const std::vector<const ColumnString*>& data_columns,
+                        ColumnString& result_column, size_t input_rows_count,
+                        const std::vector<const ColumnUInt8*> nullmaps) {
+        std::string type_flags = data_columns.back()->get_data_at(0).to_string();
+
+        rapidjson::Document document;
+        rapidjson::Document::AllocatorType& allocator = document.GetAllocator();
+
+        std::vector<rapidjson::Value> objects;
+        for (int i = 0; i < input_rows_count; i++) {
+            objects.emplace_back(rapidjson::kArrayType);
+        }
+
+        SpecificImpl::execute_parse(type_flags, data_columns, objects, allocator, nullmaps);
+
+        rapidjson::StringBuffer buf;
+        rapidjson::Writer<rapidjson::StringBuffer> writer(buf);
+
+        for (int i = 0; i < input_rows_count; i++) {
+            buf.Clear();
+            writer.Reset(buf);
+            objects[i].Accept(writer);
+            result_column.insert_data(buf.GetString(), buf.GetSize());
+        }
+    }
+};
+
+struct FunctionJsonQuoteImpl {
+    static constexpr auto name = "json_quote";
+
+    static void execute(const std::vector<const ColumnString*>& data_columns,
+                        ColumnString& result_column, size_t input_rows_count) {
+        rapidjson::Document document;
+        rapidjson::Document::AllocatorType& allocator = document.GetAllocator();
+
+        rapidjson::Value value;
+
+        rapidjson::StringBuffer buf;
+        rapidjson::Writer<rapidjson::StringBuffer> writer(buf);
+
+        for (int i = 0; i < input_rows_count; i++) {
+            StringRef data = data_columns[0]->get_data_at(i);
+            value.SetString(data.data, data.size, allocator);
+
+            buf.Clear();
+            value.Accept(writer);
+            result_column.insert_data(buf.GetString(), buf.GetSize());
+        }
+    }
+};
+
+struct FunctionJsonExtractImpl {
+    static constexpr auto name = "json_extract";
+
+    static rapidjson::Value parse_json(const ColumnString* json_col, const ColumnString* path_col,
+                                       rapidjson::Document::AllocatorType& allocator,
+                                       const int row) {
+        rapidjson::Value value;
+        rapidjson::Document document;
+
+        const auto obj = json_col->get_data_at(row);
+        std::string_view json_string(obj.data, obj.size);
+        const auto path = path_col->get_data_at(row);
+        std::string_view path_string(path.data, path.size);
+
+        auto root = get_json_object<JSON_FUN_STRING>(json_string, path_string, &document);
+        if (root != nullptr) {
+            value.CopyFrom(*root, allocator);
+        }
+        return value;
+    }
+
+    static void execute(const std::vector<const ColumnString*>& data_columns,
+                        ColumnString& result_column, size_t input_rows_count) {
+        rapidjson::Document document;
+        rapidjson::Document::AllocatorType& allocator = document.GetAllocator();
+        rapidjson::StringBuffer buf;
+        rapidjson::Writer<rapidjson::StringBuffer> writer(buf);
+
+        const auto json_col = data_columns[0];
+        for (size_t row = 0; row < input_rows_count; row++) {
+            rapidjson::Value value;
+            if (data_columns.size() == 2) {
+                value = parse_json(json_col, data_columns[1], allocator, row);
+            } else {
+                value.SetArray();
+                value.Reserve(data_columns.size() - 1, allocator);
+                for (size_t col = 1; col < data_columns.size(); ++col) {
+                    value.PushBack(parse_json(json_col, data_columns[col], allocator, row),
+                                   allocator);
+                }
+            }
+
+            // write value as string
+            buf.Clear();
+            writer.Reset(buf);
+            value.Accept(writer);
+            result_column.insert_data(buf.GetString(), buf.GetSize());
+        }
+    }
+};
+
+template <typename Impl>
+class FunctionJson : public IFunction {
+public:
+    static constexpr auto name = Impl::name;
+
+    static FunctionPtr create() { return std::make_shared<FunctionJson<Impl>>(); }
+
+    String get_name() const override { return name; }
+
+    size_t get_number_of_arguments() const override { return 0; }
+
+    bool is_variadic() const override { return true; }
+
+    DataTypePtr get_return_type_impl(const DataTypes& arguments) const override {

Review Comment:
   warning: function 'get_return_type_impl' should be marked [[nodiscard]] [modernize-use-nodiscard]
   
   ```suggestion
       [[nodiscard]] DataTypePtr get_return_type_impl(const DataTypes& arguments) const override {
   ```
   



##########
function_json.cpp:
##########
@@ -0,0 +1,1320 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#include <rapidjson/allocators.h>
+#include <rapidjson/document.h>
+#include <rapidjson/encodings.h>
+#include <rapidjson/pointer.h>
+#include <rapidjson/rapidjson.h>
+#include <rapidjson/stringbuffer.h>
+#include <rapidjson/writer.h>
+#include <re2/re2.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <algorithm>
+#include <boost/iterator/iterator_facade.hpp>
+#include <boost/token_functions.hpp>
+#include <boost/tokenizer.hpp>
+#include <memory>
+#include <string>
+#include <string_view>
+#include <type_traits>
+#include <utility>
+#include <vector>
+
+// IWYU pragma: no_include <opentelemetry/common/threadlocal.h>
+#include "common/compiler_util.h" // IWYU pragma: keep
+#include "common/status.h"
+#include "exprs/json_functions.h"
+#ifdef __AVX2__
+#include "util/jsonb_parser_simd.h"
+#else
+#include "util/jsonb_parser.h"
+#endif
+#include "util/string_parser.hpp"
+#include "util/string_util.h"
+#include "vec/aggregate_functions/aggregate_function.h"
+#include "vec/columns/column.h"
+#include "vec/columns/column_nullable.h"
+#include "vec/columns/column_string.h"
+#include "vec/columns/column_vector.h"
+#include "vec/columns/columns_number.h"
+#include "vec/common/assert_cast.h"
+#include "vec/common/string_ref.h"
+#include "vec/core/block.h"
+#include "vec/core/column_numbers.h"
+#include "vec/core/column_with_type_and_name.h"
+#include "vec/core/types.h"
+#include "vec/data_types/data_type.h"
+#include "vec/data_types/data_type_nullable.h"
+#include "vec/data_types/data_type_number.h"
+#include "vec/data_types/data_type_string.h"
+#include "vec/functions/function.h"
+#include "vec/functions/function_string.h"
+#include "vec/functions/function_totype.h"
+#include "vec/functions/simple_function_factory.h"
+#include "vec/utils/template_helpers.hpp"
+
+namespace doris {
+class FunctionContext;
+} // namespace doris
+
+namespace doris::vectorized {
+static const re2::RE2 JSON_PATTERN("^([^\\\"\\[\\]]*)(?:\\[([0-9]+|\\*)\\])?");
+
+template <typename T, typename U>
+void char_split(std::vector<T>& res, const U& var, char p) {
+    int start = 0;
+    int pos = start;
+    int end = var.length();
+    while (pos < end) {
+        while (var[pos] != p && pos < end) {
+            pos++;
+        }
+        res.emplace_back(&var[start], pos - start);
+        pos++;
+        start = pos;
+    }
+}
+
+// T = std::vector<std::string>
+// TODO: update RE2 to support std::vector<std::string_view>
+template <typename T>
+void get_parsed_paths(const T& path_exprs, std::vector<JsonPath>* parsed_paths) {
+    if (path_exprs.empty()) {
+        return;
+    }
+
+    if (path_exprs[0] != "$") {
+        parsed_paths->emplace_back("", -1, false);
+    } else {
+        parsed_paths->emplace_back("$", -1, true);
+    }
+
+    for (int i = 1; i < path_exprs.size(); i++) {
+        std::string col;
+        std::string index;
+        if (UNLIKELY(!RE2::FullMatch(path_exprs[i], JSON_PATTERN, &col, &index))) {
+            parsed_paths->emplace_back("", -1, false);
+        } else {
+            int idx = -1;
+            if (!index.empty()) {
+                if (index == "*") {
+                    idx = -2;
+                } else {
+                    idx = atoi(index.c_str());
+                }
+            }
+            parsed_paths->emplace_back(col, idx, true);
+        }
+    }
+}
+
+rapidjson::Value* match_value(const std::vector<JsonPath>& parsed_paths, rapidjson::Value* document,
+                              rapidjson::Document::AllocatorType& mem_allocator,
+                              bool is_insert_null = false) {
+    rapidjson::Value* root = document;
+    rapidjson::Value* array_obj = nullptr;
+    for (int i = 1; i < parsed_paths.size(); i++) {
+        if (root == nullptr || root->IsNull()) {
+            return nullptr;
+        }
+
+        if (UNLIKELY(!parsed_paths[i].is_valid)) {
+            return nullptr;
+        }
+
+        const std::string& col = parsed_paths[i].key;
+        int index = parsed_paths[i].idx;
+        if (LIKELY(!col.empty())) {
+            if (root->IsArray()) {
+                array_obj = static_cast<rapidjson::Value*>(
+                        mem_allocator.Malloc(sizeof(rapidjson::Value)));
+                array_obj->SetArray();
+                bool is_null = true;
+
+                // if array ,loop the array,find out all Objects,then find the results from the objects
+                for (int j = 0; j < root->Size(); j++) {
+                    rapidjson::Value* json_elem = &((*root)[j]);
+
+                    if (json_elem->IsArray() || json_elem->IsNull()) {
+                        continue;
+                    } else {
+                        if (!json_elem->IsObject()) {
+                            continue;
+                        }
+                        if (!json_elem->HasMember(col.c_str())) {
+                            if (is_insert_null) { // not found item, then insert a null object.
+                                is_null = false;
+                                rapidjson::Value nullObject(rapidjson::kNullType);
+                                array_obj->PushBack(nullObject, mem_allocator);
+                            }
+                            continue;
+                        }
+                        rapidjson::Value* obj = &((*json_elem)[col.c_str()]);
+                        if (obj->IsArray()) {
+                            is_null = false;
+                            for (int k = 0; k < obj->Size(); k++) {
+                                array_obj->PushBack((*obj)[k], mem_allocator);
+                            }
+                        } else if (!obj->IsNull()) {
+                            is_null = false;
+                            array_obj->PushBack(*obj, mem_allocator);
+                        }
+                    }
+                }
+
+                root = is_null ? &(array_obj->SetNull()) : array_obj;
+            } else if (root->IsObject()) {
+                if (!root->HasMember(col.c_str())) {
+                    return nullptr;
+                } else {
+                    root = &((*root)[col.c_str()]);
+                }
+            } else {
+                // root is not a nested type, return NULL
+                return nullptr;
+            }
+        }
+
+        if (UNLIKELY(index != -1)) {
+            // judge the rapidjson:Value, which base the top's result,
+            // if not array return NULL;else get the index value from the array
+            if (root->IsArray()) {
+                if (root->IsNull()) {
+                    return nullptr;
+                } else if (index == -2) {
+                    // [*]
+                    array_obj = static_cast<rapidjson::Value*>(
+                            mem_allocator.Malloc(sizeof(rapidjson::Value)));
+                    array_obj->SetArray();
+
+                    for (int j = 0; j < root->Size(); j++) {
+                        rapidjson::Value v;
+                        v.CopyFrom((*root)[j], mem_allocator);
+                        array_obj->PushBack(v, mem_allocator);
+                    }
+                    root = array_obj;
+                } else if (index >= root->Size()) {
+                    return nullptr;
+                } else {
+                    root = &((*root)[index]);
+                }
+            } else {
+                return nullptr;
+            }
+        }
+    }
+    return root;
+}
+
+template <JsonFunctionType fntype>
+rapidjson::Value* get_json_object(std::string_view json_string, std::string_view path_string,
+                                  rapidjson::Document* document) {
+    std::vector<JsonPath>* parsed_paths;
+    std::vector<JsonPath> tmp_parsed_paths;
+
+#ifdef USE_LIBCPP
+    std::string s(path_string);
+    auto tok = get_json_token(s);
+#else
+    auto tok = get_json_token(path_string);
+#endif
+    std::vector<std::string> paths(tok.begin(), tok.end());
+    get_parsed_paths(paths, &tmp_parsed_paths);
+    if (tmp_parsed_paths.empty()) {
+        return document;
+    }
+
+    parsed_paths = &tmp_parsed_paths;
+
+    if (!(*parsed_paths)[0].is_valid) {
+        return document;
+    }
+
+    if (UNLIKELY((*parsed_paths).size() == 1)) {
+        if (fntype == JSON_FUN_STRING) {
+            document->SetString(json_string.data(), json_string.size(), document->GetAllocator());
+        } else {
+            return document;
+        }
+    }
+
+    document->Parse(json_string.data(), json_string.size());
+    if (UNLIKELY(document->HasParseError())) {
+        // VLOG_CRITICAL << "Error at offset " << document->GetErrorOffset() << ": "
+        //         << GetParseError_En(document->GetParseError());
+        document->SetNull();
+        return document;
+    }
+
+    return match_value(*parsed_paths, document, document->GetAllocator());
+}
+
+template <typename NumberType>
+struct GetJsonNumberType {
+    using ReturnType = typename NumberType::ReturnType;
+    using ColumnType = typename NumberType::ColumnType;
+    using Container = typename ColumnType::Container;
+
+    static void get_json_impl(rapidjson::Value*& root, const std::string_view& json_string,
+                              const std::string_view& path_string, rapidjson::Document& document,
+                              typename NumberType::T& res, UInt8& null_map) {
+        if constexpr (std::is_same_v<double, typename NumberType::T>) {
+            root = get_json_object<JSON_FUN_DOUBLE>(json_string, path_string, &document);
+            handle_result<double>(root, res, null_map);
+        } else if constexpr (std::is_same_v<int32_t, typename NumberType::T>) {
+            root = get_json_object<JSON_FUN_DOUBLE>(json_string, path_string, &document);
+            handle_result<int32_t>(root, res, null_map);
+        } else if constexpr (std::is_same_v<int64_t, typename NumberType::T>) {
+            root = get_json_object<JSON_FUN_DOUBLE>(json_string, path_string, &document);
+            handle_result<int64_t>(root, res, null_map);
+        }
+    }
+    static void vector_vector(FunctionContext* context, const ColumnString::Chars& ldata,
+                              const ColumnString::Offsets& loffsets,
+                              const ColumnString::Chars& rdata,
+                              const ColumnString::Offsets& roffsets, Container& res,
+                              NullMap& null_map) {
+        size_t size = loffsets.size();
+        res.resize(size);
+        for (size_t i = 0; i < size; ++i) {
+            const char* l_raw_str = reinterpret_cast<const char*>(&ldata[loffsets[i - 1]]);
+            int l_str_size = loffsets[i] - loffsets[i - 1];
+            const char* r_raw_str = reinterpret_cast<const char*>(&rdata[roffsets[i - 1]]);
+            int r_str_size = roffsets[i] - roffsets[i - 1];
+            if (null_map[i]) {
+                res[i] = 0;
+                continue;
+            }
+
+            std::string_view json_string(l_raw_str, l_str_size);
+            std::string_view path_string(r_raw_str, r_str_size);
+            rapidjson::Document document;
+            rapidjson::Value* root = nullptr;
+
+            get_json_impl(root, json_string, path_string, document, res[i], null_map[i]);
+        }
+    }
+    static void vector_scalar(FunctionContext* context, const ColumnString::Chars& ldata,
+                              const ColumnString::Offsets& loffsets, const StringRef& rdata,
+                              Container& res, NullMap& null_map) {
+        size_t size = loffsets.size();
+        res.resize(size);
+        std::string_view path_string(rdata.data, rdata.size);
+        for (size_t i = 0; i < size; ++i) {
+            const char* l_raw_str = reinterpret_cast<const char*>(&ldata[loffsets[i - 1]]);
+            int l_str_size = loffsets[i] - loffsets[i - 1];
+            if (null_map[i]) {
+                res[i] = 0;
+                continue;
+            }
+            std::string_view json_string(l_raw_str, l_str_size);
+
+            rapidjson::Document document;
+            rapidjson::Value* root = nullptr;
+
+            get_json_impl(root, json_string, path_string, document, res[i], null_map[i]);
+        }
+    }
+    static void scalar_vector(FunctionContext* context, const StringRef& ldata,
+                              const ColumnString::Chars& rdata,
+                              const ColumnString::Offsets& roffsets, Container& res,
+                              NullMap& null_map) {
+        size_t size = roffsets.size();
+        res.resize(size);
+        std::string_view json_string(ldata.data, ldata.size);
+        for (size_t i = 0; i < size; ++i) {
+            const char* r_raw_str = reinterpret_cast<const char*>(&rdata[roffsets[i - 1]]);
+            int r_str_size = roffsets[i] - roffsets[i - 1];
+            if (null_map[i]) {
+                res[i] = 0;
+                continue;
+            }
+            std::string_view path_string(r_raw_str, r_str_size);
+            rapidjson::Document document;
+            rapidjson::Value* root = nullptr;
+
+            get_json_impl(root, json_string, path_string, document, res[i], null_map[i]);
+        }
+    }
+
+    template <typename T, std::enable_if_t<std::is_same_v<double, T>, T>* = nullptr>
+    static void handle_result(rapidjson::Value* root, T& res, uint8_t& res_null) {
+        if (root == nullptr || root->IsNull()) {
+            res = 0;
+            res_null = 1;
+        } else if (root->IsInt()) {
+            res = root->GetInt();
+        } else if (root->IsInt64()) {
+            res = root->GetInt64();
+        } else if (root->IsDouble()) {
+            res = root->GetDouble();
+        } else {
+            res_null = 1;
+        }
+    }
+
+    template <typename T, std::enable_if_t<std::is_same_v<int32_t, T>, T>* = nullptr>
+    static void handle_result(rapidjson::Value* root, int32_t& res, uint8_t& res_null) {
+        if (root != nullptr && root->IsInt()) {
+            res = root->GetInt();
+        } else {
+            res_null = 1;
+        }
+    }
+
+    template <typename T, std::enable_if_t<std::is_same_v<int64_t, T>, T>* = nullptr>
+    static void handle_result(rapidjson::Value* root, int64_t& res, uint8_t& res_null) {
+        if (root != nullptr && root->IsInt64()) {
+            res = root->GetInt64();
+        } else {
+            res_null = 1;
+        }
+    }
+};
+
+// Helper Class
+struct JsonNumberTypeDouble {
+    using T = Float64;
+    using ReturnType = DataTypeFloat64;
+    using ColumnType = ColumnVector<T>;
+};
+
+struct JsonNumberTypeInt {
+    using T = int32_t;
+    using ReturnType = DataTypeInt32;
+    using ColumnType = ColumnVector<T>;
+};
+
+struct JsonNumberTypeBigInt {
+    using T = int64_t;
+    using ReturnType = DataTypeInt64;
+    using ColumnType = ColumnVector<T>;
+};
+
+struct GetJsonDouble : public GetJsonNumberType<JsonNumberTypeDouble> {
+    static constexpr auto name = "get_json_double";
+    using ReturnType = typename JsonNumberTypeDouble::ReturnType;
+    using ColumnType = typename JsonNumberTypeDouble::ColumnType;
+};
+
+struct GetJsonInt : public GetJsonNumberType<JsonNumberTypeInt> {
+    static constexpr auto name = "get_json_int";
+    using ReturnType = typename JsonNumberTypeInt::ReturnType;
+    using ColumnType = typename JsonNumberTypeInt::ColumnType;
+};
+
+struct GetJsonBigInt : public GetJsonNumberType<JsonNumberTypeBigInt> {
+    static constexpr auto name = "get_json_bigint";
+    using ReturnType = typename JsonNumberTypeBigInt::ReturnType;
+    using ColumnType = typename JsonNumberTypeBigInt::ColumnType;
+};
+
+struct GetJsonString {
+    static constexpr auto name = "get_json_string";
+    using ReturnType = DataTypeString;
+    using ColumnType = ColumnString;
+    using Chars = ColumnString::Chars;
+    using Offsets = ColumnString::Offsets;
+    static void vector_vector(FunctionContext* context, const Chars& ldata, const Offsets& loffsets,
+                              const Chars& rdata, const Offsets& roffsets, Chars& res_data,
+                              Offsets& res_offsets, NullMap& null_map) {
+        size_t input_rows_count = loffsets.size();
+        res_offsets.resize(input_rows_count);
+
+        for (size_t i = 0; i < input_rows_count; ++i) {
+            if (null_map[i]) {
+                StringOP::push_null_string(i, res_data, res_offsets, null_map);
+                continue;
+            }
+            int l_size = loffsets[i] - loffsets[i - 1];
+            const auto l_raw = reinterpret_cast<const char*>(&ldata[loffsets[i - 1]]);
+            int r_size = roffsets[i] - roffsets[i - 1];
+            const auto r_raw = reinterpret_cast<const char*>(&rdata[roffsets[i - 1]]);
+
+            std::string_view json_string(l_raw, l_size);
+            std::string_view path_string(r_raw, r_size);
+
+            execute_impl(json_string, path_string, res_data, res_offsets, null_map, i);
+        }
+    }
+    static void vector_scalar(FunctionContext* context, const Chars& ldata, const Offsets& loffsets,
+                              const StringRef& rdata, Chars& res_data, Offsets& res_offsets,
+                              NullMap& null_map) {
+        size_t input_rows_count = loffsets.size();
+        res_offsets.resize(input_rows_count);
+
+        for (size_t i = 0; i < input_rows_count; ++i) {
+            if (null_map[i]) {
+                StringOP::push_null_string(i, res_data, res_offsets, null_map);
+                continue;
+            }
+            int l_size = loffsets[i] - loffsets[i - 1];
+            const auto l_raw = reinterpret_cast<const char*>(&ldata[loffsets[i - 1]]);
+
+            std::string_view json_string(l_raw, l_size);
+            std::string_view path_string(rdata.data, rdata.size);
+
+            execute_impl(json_string, path_string, res_data, res_offsets, null_map, i);
+        }
+    }
+    static void scalar_vector(FunctionContext* context, const StringRef& ldata, const Chars& rdata,
+                              const Offsets& roffsets, Chars& res_data, Offsets& res_offsets,
+                              NullMap& null_map) {
+        size_t input_rows_count = roffsets.size();
+        res_offsets.resize(input_rows_count);
+
+        for (size_t i = 0; i < input_rows_count; ++i) {
+            if (null_map[i]) {
+                StringOP::push_null_string(i, res_data, res_offsets, null_map);
+                continue;
+            }
+            int r_size = roffsets[i] - roffsets[i - 1];
+            const auto r_raw = reinterpret_cast<const char*>(&rdata[roffsets[i - 1]]);
+
+            std::string_view json_string(ldata.data, ldata.size);
+            std::string_view path_string(r_raw, r_size);
+
+            execute_impl(json_string, path_string, res_data, res_offsets, null_map, i);
+        }
+    }
+
+    static void execute_impl(const std::string_view& json_string,
+                             const std::string_view& path_string, Chars& res_data,
+                             Offsets& res_offsets, NullMap& null_map, size_t index_now) {
+        rapidjson::Document document;
+        rapidjson::Value* root = nullptr;
+
+        root = get_json_object<JSON_FUN_STRING>(json_string, path_string, &document);
+        const int max_string_len = 65535;
+
+        if (root == nullptr || root->IsNull()) {
+            StringOP::push_null_string(index_now, res_data, res_offsets, null_map);
+        } else if (root->IsString()) {
+            const auto ptr = root->GetString();
+            size_t len = strnlen(ptr, max_string_len);
+            StringOP::push_value_string(std::string_view(ptr, len), index_now, res_data,
+                                        res_offsets);
+        } else {
+            rapidjson::StringBuffer buf;
+            rapidjson::Writer<rapidjson::StringBuffer> writer(buf);
+            root->Accept(writer);
+
+            const auto ptr = buf.GetString();
+            size_t len = strnlen(ptr, max_string_len);
+            StringOP::push_value_string(std::string_view(ptr, len), index_now, res_data,
+                                        res_offsets);
+        }
+    }
+};
+
+template <int flag>
+struct JsonParser {
+    //string
+    static void update_value(StringParser::ParseResult& result, rapidjson::Value& value,
+                             StringRef data, rapidjson::Document::AllocatorType& allocator) {
+        value.SetString(data.data, data.size, allocator);
+    }
+};
+
+template <>
+struct JsonParser<'0'> {
+    // null
+    static void update_value(StringParser::ParseResult& result, rapidjson::Value& value,
+                             StringRef data, rapidjson::Document::AllocatorType& allocator) {
+        value.SetNull();
+    }
+};
+
+template <>
+struct JsonParser<'1'> {
+    // bool
+    static void update_value(StringParser::ParseResult& result, rapidjson::Value& value,
+                             StringRef data, rapidjson::Document::AllocatorType& allocator) {
+        DCHECK(data.size == 1 || strncmp(data.data, "true", 4) == 0 ||
+               strncmp(data.data, "false", 5) == 0);
+        value.SetBool((*data.data == '1' || *data.data == 't') ? true : false);
+    }
+};
+
+template <>
+struct JsonParser<'2'> {
+    // int
+    static void update_value(StringParser::ParseResult& result, rapidjson::Value& value,
+                             StringRef data, rapidjson::Document::AllocatorType& allocator) {
+        value.SetInt(StringParser::string_to_int<int32_t>(data.data, data.size, &result));
+    }
+};
+
+template <>
+struct JsonParser<'3'> {
+    // double
+    static void update_value(StringParser::ParseResult& result, rapidjson::Value& value,
+                             StringRef data, rapidjson::Document::AllocatorType& allocator) {
+        value.SetDouble(StringParser::string_to_float<double>(data.data, data.size, &result));
+    }
+};
+
+template <>
+struct JsonParser<'4'> {
+    // time
+    static void update_value(StringParser::ParseResult& result, rapidjson::Value& value,
+                             StringRef data, rapidjson::Document::AllocatorType& allocator) {
+        // remove double quotes, "xxx" -> xxx
+        value.SetString(data.data + 1, data.size - 2, allocator);
+    }
+};
+
+template <>
+struct JsonParser<'5'> {
+    // bigint
+    static void update_value(StringParser::ParseResult& result, rapidjson::Value& value,
+                             StringRef data, rapidjson::Document::AllocatorType& allocator) {
+        value.SetInt64(StringParser::string_to_int<int64_t>(data.data, data.size, &result));
+    }
+};
+
+template <int flag, typename Impl>
+struct ExecuteReducer {
+    template <typename... TArgs>
+    static void run(TArgs&&... args) {
+        Impl::template execute_type<JsonParser<flag>>(std::forward<TArgs>(args)...);
+    }
+};
+
+struct FunctionJsonArrayImpl {
+    static constexpr auto name = "json_array";
+
+    template <int flag>
+    using Reducer = ExecuteReducer<flag, FunctionJsonArrayImpl>;
+
+    static void execute_parse(const std::string& type_flags,
+                              const std::vector<const ColumnString*>& data_columns,
+                              std::vector<rapidjson::Value>& objects,
+                              rapidjson::Document::AllocatorType& allocator,
+                              const std::vector<const ColumnUInt8*>& nullmaps) {
+        for (int i = 0; i < data_columns.size() - 1; i++) {
+            constexpr_int_match<'0', '6', Reducer>::run(type_flags[i], objects, allocator,
+                                                        data_columns[i], nullmaps[i]);
+        }
+    }
+
+    template <typename TypeImpl>
+    static void execute_type(std::vector<rapidjson::Value>& objects,
+                             rapidjson::Document::AllocatorType& allocator,
+                             const ColumnString* data_column, const ColumnUInt8* nullmap) {
+        StringParser::ParseResult result;
+        rapidjson::Value value;
+
+        for (int i = 0; i < objects.size(); i++) {
+            if (nullmap != nullptr && nullmap->get_data()[i]) {
+                JsonParser<'0'>::update_value(result, value, data_column->get_data_at(i),
+                                              allocator);
+            } else {
+                TypeImpl::update_value(result, value, data_column->get_data_at(i), allocator);
+            }
+            objects[i].PushBack(value, allocator);
+        }
+    }
+};
+
+struct FunctionJsonObjectImpl {
+    static constexpr auto name = "json_object";
+
+    template <int flag>
+    using Reducer = ExecuteReducer<flag, FunctionJsonObjectImpl>;
+
+    static void execute_parse(std::string type_flags,
+                              const std::vector<const ColumnString*>& data_columns,
+                              std::vector<rapidjson::Value>& objects,
+                              rapidjson::Document::AllocatorType& allocator,
+                              const std::vector<const ColumnUInt8*>& nullmaps) {
+        for (auto& array_object : objects) {
+            array_object.SetObject();
+        }
+
+        for (int i = 0; i + 1 < data_columns.size() - 1; i += 2) {
+            constexpr_int_match<'0', '6', Reducer>::run(type_flags[i + 1], objects, allocator,
+                                                        data_columns[i], data_columns[i + 1],
+                                                        nullmaps[i + 1]);
+        }
+    }
+
+    template <typename TypeImpl>
+    static void execute_type(std::vector<rapidjson::Value>& objects,
+                             rapidjson::Document::AllocatorType& allocator,
+                             const ColumnString* key_column, const ColumnString* value_column,
+                             const ColumnUInt8* nullmap) {
+        StringParser::ParseResult result;
+        rapidjson::Value key;
+        rapidjson::Value value;
+        for (int i = 0; i < objects.size(); i++) {
+            JsonParser<'6'>::update_value(result, key, key_column->get_data_at(i),
+                                          allocator); // key always is string
+            if (nullmap != nullptr && nullmap->get_data()[i]) {
+                JsonParser<'0'>::update_value(result, value, value_column->get_data_at(i),
+                                              allocator);
+            } else {
+                TypeImpl::update_value(result, value, value_column->get_data_at(i), allocator);
+            }
+            objects[i].AddMember(key, value, allocator);
+        }
+    }
+};
+
+template <typename SpecificImpl>
+class FunctionJsonAlwaysNotNullable : public IFunction {
+public:
+    using IFunction::execute;
+
+    static constexpr auto name = SpecificImpl::name;
+
+    static FunctionPtr create() {
+        return std::make_shared<FunctionJsonAlwaysNotNullable<SpecificImpl>>();
+    }
+
+    bool use_default_implementation_for_nulls() const override { return false; }
+
+    String get_name() const override { return name; }
+
+    size_t get_number_of_arguments() const override { return 0; }
+
+    bool is_variadic() const override { return true; }
+
+    DataTypePtr get_return_type_impl(const DataTypes& arguments) const override {
+        return std::make_shared<DataTypeString>();
+    }
+
+    Status execute_impl(FunctionContext* context, Block& block, const ColumnNumbers& arguments,
+                        size_t result, size_t input_rows_count) override {
+        auto result_column = ColumnString::create();
+
+        std::vector<ColumnPtr> column_ptrs; // prevent converted column destruct
+        std::vector<const ColumnString*> data_columns;
+        std::vector<const ColumnUInt8*> nullmaps;
+        for (int i = 0; i < arguments.size(); i++) {
+            auto column = block.get_by_position(arguments[i]).column;
+            column_ptrs.push_back(column->convert_to_full_column_if_const());
+            const ColumnNullable* col_nullable =
+                    check_and_get_column<ColumnNullable>(column_ptrs.back().get());
+            if (col_nullable) {
+                const ColumnUInt8* col_nullmap = check_and_get_column<ColumnUInt8>(
+                        col_nullable->get_null_map_column_ptr().get());
+                nullmaps.push_back(col_nullmap);
+                const ColumnString* col = check_and_get_column<ColumnString>(
+                        col_nullable->get_nested_column_ptr().get());
+                data_columns.push_back(col);
+            } else {
+                nullmaps.push_back(nullptr);
+                data_columns.push_back(assert_cast<const ColumnString*>(column_ptrs.back().get()));
+            }
+        }
+        execute(data_columns, *assert_cast<ColumnString*>(result_column.get()), input_rows_count,
+                nullmaps);
+        block.get_by_position(result).column = std::move(result_column);
+        return Status::OK();
+    }
+
+    static void execute(const std::vector<const ColumnString*>& data_columns,
+                        ColumnString& result_column, size_t input_rows_count,
+                        const std::vector<const ColumnUInt8*> nullmaps) {
+        std::string type_flags = data_columns.back()->get_data_at(0).to_string();
+
+        rapidjson::Document document;
+        rapidjson::Document::AllocatorType& allocator = document.GetAllocator();
+
+        std::vector<rapidjson::Value> objects;
+        for (int i = 0; i < input_rows_count; i++) {
+            objects.emplace_back(rapidjson::kArrayType);
+        }
+
+        SpecificImpl::execute_parse(type_flags, data_columns, objects, allocator, nullmaps);
+
+        rapidjson::StringBuffer buf;
+        rapidjson::Writer<rapidjson::StringBuffer> writer(buf);
+
+        for (int i = 0; i < input_rows_count; i++) {
+            buf.Clear();
+            writer.Reset(buf);
+            objects[i].Accept(writer);
+            result_column.insert_data(buf.GetString(), buf.GetSize());
+        }
+    }
+};
+
+struct FunctionJsonQuoteImpl {
+    static constexpr auto name = "json_quote";
+
+    static void execute(const std::vector<const ColumnString*>& data_columns,
+                        ColumnString& result_column, size_t input_rows_count) {
+        rapidjson::Document document;
+        rapidjson::Document::AllocatorType& allocator = document.GetAllocator();
+
+        rapidjson::Value value;
+
+        rapidjson::StringBuffer buf;
+        rapidjson::Writer<rapidjson::StringBuffer> writer(buf);
+
+        for (int i = 0; i < input_rows_count; i++) {
+            StringRef data = data_columns[0]->get_data_at(i);
+            value.SetString(data.data, data.size, allocator);
+
+            buf.Clear();
+            value.Accept(writer);
+            result_column.insert_data(buf.GetString(), buf.GetSize());
+        }
+    }
+};
+
+struct FunctionJsonExtractImpl {
+    static constexpr auto name = "json_extract";
+
+    static rapidjson::Value parse_json(const ColumnString* json_col, const ColumnString* path_col,
+                                       rapidjson::Document::AllocatorType& allocator,
+                                       const int row) {
+        rapidjson::Value value;
+        rapidjson::Document document;
+
+        const auto obj = json_col->get_data_at(row);
+        std::string_view json_string(obj.data, obj.size);
+        const auto path = path_col->get_data_at(row);
+        std::string_view path_string(path.data, path.size);
+
+        auto root = get_json_object<JSON_FUN_STRING>(json_string, path_string, &document);
+        if (root != nullptr) {
+            value.CopyFrom(*root, allocator);
+        }
+        return value;
+    }
+
+    static void execute(const std::vector<const ColumnString*>& data_columns,
+                        ColumnString& result_column, size_t input_rows_count) {
+        rapidjson::Document document;
+        rapidjson::Document::AllocatorType& allocator = document.GetAllocator();
+        rapidjson::StringBuffer buf;
+        rapidjson::Writer<rapidjson::StringBuffer> writer(buf);
+
+        const auto json_col = data_columns[0];
+        for (size_t row = 0; row < input_rows_count; row++) {
+            rapidjson::Value value;
+            if (data_columns.size() == 2) {
+                value = parse_json(json_col, data_columns[1], allocator, row);
+            } else {
+                value.SetArray();
+                value.Reserve(data_columns.size() - 1, allocator);
+                for (size_t col = 1; col < data_columns.size(); ++col) {
+                    value.PushBack(parse_json(json_col, data_columns[col], allocator, row),
+                                   allocator);
+                }
+            }
+
+            // write value as string
+            buf.Clear();
+            writer.Reset(buf);
+            value.Accept(writer);
+            result_column.insert_data(buf.GetString(), buf.GetSize());
+        }
+    }
+};
+
+template <typename Impl>
+class FunctionJson : public IFunction {
+public:
+    static constexpr auto name = Impl::name;
+
+    static FunctionPtr create() { return std::make_shared<FunctionJson<Impl>>(); }
+
+    String get_name() const override { return name; }

Review Comment:
   warning: function 'get_name' should be marked [[nodiscard]] [modernize-use-nodiscard]
   
   ```suggestion
       [[nodiscard]] String get_name() const override { return name; }
   ```
   



##########
function_json.cpp:
##########
@@ -0,0 +1,1320 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#include <rapidjson/allocators.h>
+#include <rapidjson/document.h>
+#include <rapidjson/encodings.h>
+#include <rapidjson/pointer.h>
+#include <rapidjson/rapidjson.h>
+#include <rapidjson/stringbuffer.h>
+#include <rapidjson/writer.h>
+#include <re2/re2.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <algorithm>
+#include <boost/iterator/iterator_facade.hpp>
+#include <boost/token_functions.hpp>
+#include <boost/tokenizer.hpp>
+#include <memory>
+#include <string>
+#include <string_view>
+#include <type_traits>
+#include <utility>
+#include <vector>
+
+// IWYU pragma: no_include <opentelemetry/common/threadlocal.h>
+#include "common/compiler_util.h" // IWYU pragma: keep
+#include "common/status.h"
+#include "exprs/json_functions.h"
+#ifdef __AVX2__
+#include "util/jsonb_parser_simd.h"
+#else
+#include "util/jsonb_parser.h"
+#endif
+#include "util/string_parser.hpp"
+#include "util/string_util.h"
+#include "vec/aggregate_functions/aggregate_function.h"
+#include "vec/columns/column.h"
+#include "vec/columns/column_nullable.h"
+#include "vec/columns/column_string.h"
+#include "vec/columns/column_vector.h"
+#include "vec/columns/columns_number.h"
+#include "vec/common/assert_cast.h"
+#include "vec/common/string_ref.h"
+#include "vec/core/block.h"
+#include "vec/core/column_numbers.h"
+#include "vec/core/column_with_type_and_name.h"
+#include "vec/core/types.h"
+#include "vec/data_types/data_type.h"
+#include "vec/data_types/data_type_nullable.h"
+#include "vec/data_types/data_type_number.h"
+#include "vec/data_types/data_type_string.h"
+#include "vec/functions/function.h"
+#include "vec/functions/function_string.h"
+#include "vec/functions/function_totype.h"
+#include "vec/functions/simple_function_factory.h"
+#include "vec/utils/template_helpers.hpp"
+
+namespace doris {
+class FunctionContext;
+} // namespace doris
+
+namespace doris::vectorized {
+static const re2::RE2 JSON_PATTERN("^([^\\\"\\[\\]]*)(?:\\[([0-9]+|\\*)\\])?");
+
+template <typename T, typename U>
+void char_split(std::vector<T>& res, const U& var, char p) {
+    int start = 0;
+    int pos = start;
+    int end = var.length();
+    while (pos < end) {
+        while (var[pos] != p && pos < end) {
+            pos++;
+        }
+        res.emplace_back(&var[start], pos - start);
+        pos++;
+        start = pos;
+    }
+}
+
+// T = std::vector<std::string>
+// TODO: update RE2 to support std::vector<std::string_view>
+template <typename T>
+void get_parsed_paths(const T& path_exprs, std::vector<JsonPath>* parsed_paths) {
+    if (path_exprs.empty()) {
+        return;
+    }
+
+    if (path_exprs[0] != "$") {
+        parsed_paths->emplace_back("", -1, false);
+    } else {
+        parsed_paths->emplace_back("$", -1, true);
+    }
+
+    for (int i = 1; i < path_exprs.size(); i++) {
+        std::string col;
+        std::string index;
+        if (UNLIKELY(!RE2::FullMatch(path_exprs[i], JSON_PATTERN, &col, &index))) {
+            parsed_paths->emplace_back("", -1, false);
+        } else {
+            int idx = -1;
+            if (!index.empty()) {
+                if (index == "*") {
+                    idx = -2;
+                } else {
+                    idx = atoi(index.c_str());
+                }
+            }
+            parsed_paths->emplace_back(col, idx, true);
+        }
+    }
+}
+
+rapidjson::Value* match_value(const std::vector<JsonPath>& parsed_paths, rapidjson::Value* document,
+                              rapidjson::Document::AllocatorType& mem_allocator,
+                              bool is_insert_null = false) {
+    rapidjson::Value* root = document;
+    rapidjson::Value* array_obj = nullptr;
+    for (int i = 1; i < parsed_paths.size(); i++) {
+        if (root == nullptr || root->IsNull()) {
+            return nullptr;
+        }
+
+        if (UNLIKELY(!parsed_paths[i].is_valid)) {
+            return nullptr;
+        }
+
+        const std::string& col = parsed_paths[i].key;
+        int index = parsed_paths[i].idx;
+        if (LIKELY(!col.empty())) {
+            if (root->IsArray()) {
+                array_obj = static_cast<rapidjson::Value*>(
+                        mem_allocator.Malloc(sizeof(rapidjson::Value)));
+                array_obj->SetArray();
+                bool is_null = true;
+
+                // if array ,loop the array,find out all Objects,then find the results from the objects
+                for (int j = 0; j < root->Size(); j++) {
+                    rapidjson::Value* json_elem = &((*root)[j]);
+
+                    if (json_elem->IsArray() || json_elem->IsNull()) {
+                        continue;
+                    } else {
+                        if (!json_elem->IsObject()) {
+                            continue;
+                        }
+                        if (!json_elem->HasMember(col.c_str())) {
+                            if (is_insert_null) { // not found item, then insert a null object.
+                                is_null = false;
+                                rapidjson::Value nullObject(rapidjson::kNullType);
+                                array_obj->PushBack(nullObject, mem_allocator);
+                            }
+                            continue;
+                        }
+                        rapidjson::Value* obj = &((*json_elem)[col.c_str()]);
+                        if (obj->IsArray()) {
+                            is_null = false;
+                            for (int k = 0; k < obj->Size(); k++) {
+                                array_obj->PushBack((*obj)[k], mem_allocator);
+                            }
+                        } else if (!obj->IsNull()) {
+                            is_null = false;
+                            array_obj->PushBack(*obj, mem_allocator);
+                        }
+                    }
+                }
+
+                root = is_null ? &(array_obj->SetNull()) : array_obj;
+            } else if (root->IsObject()) {
+                if (!root->HasMember(col.c_str())) {
+                    return nullptr;
+                } else {
+                    root = &((*root)[col.c_str()]);
+                }
+            } else {
+                // root is not a nested type, return NULL
+                return nullptr;
+            }
+        }
+
+        if (UNLIKELY(index != -1)) {
+            // judge the rapidjson:Value, which base the top's result,
+            // if not array return NULL;else get the index value from the array
+            if (root->IsArray()) {
+                if (root->IsNull()) {
+                    return nullptr;
+                } else if (index == -2) {
+                    // [*]
+                    array_obj = static_cast<rapidjson::Value*>(
+                            mem_allocator.Malloc(sizeof(rapidjson::Value)));
+                    array_obj->SetArray();
+
+                    for (int j = 0; j < root->Size(); j++) {
+                        rapidjson::Value v;
+                        v.CopyFrom((*root)[j], mem_allocator);
+                        array_obj->PushBack(v, mem_allocator);
+                    }
+                    root = array_obj;
+                } else if (index >= root->Size()) {
+                    return nullptr;
+                } else {
+                    root = &((*root)[index]);
+                }
+            } else {
+                return nullptr;
+            }
+        }
+    }
+    return root;
+}
+
+template <JsonFunctionType fntype>
+rapidjson::Value* get_json_object(std::string_view json_string, std::string_view path_string,
+                                  rapidjson::Document* document) {
+    std::vector<JsonPath>* parsed_paths;
+    std::vector<JsonPath> tmp_parsed_paths;
+
+#ifdef USE_LIBCPP
+    std::string s(path_string);
+    auto tok = get_json_token(s);
+#else
+    auto tok = get_json_token(path_string);
+#endif
+    std::vector<std::string> paths(tok.begin(), tok.end());
+    get_parsed_paths(paths, &tmp_parsed_paths);
+    if (tmp_parsed_paths.empty()) {
+        return document;
+    }
+
+    parsed_paths = &tmp_parsed_paths;
+
+    if (!(*parsed_paths)[0].is_valid) {
+        return document;
+    }
+
+    if (UNLIKELY((*parsed_paths).size() == 1)) {
+        if (fntype == JSON_FUN_STRING) {
+            document->SetString(json_string.data(), json_string.size(), document->GetAllocator());
+        } else {
+            return document;
+        }
+    }
+
+    document->Parse(json_string.data(), json_string.size());
+    if (UNLIKELY(document->HasParseError())) {
+        // VLOG_CRITICAL << "Error at offset " << document->GetErrorOffset() << ": "
+        //         << GetParseError_En(document->GetParseError());
+        document->SetNull();
+        return document;
+    }
+
+    return match_value(*parsed_paths, document, document->GetAllocator());
+}
+
+template <typename NumberType>
+struct GetJsonNumberType {
+    using ReturnType = typename NumberType::ReturnType;
+    using ColumnType = typename NumberType::ColumnType;
+    using Container = typename ColumnType::Container;
+
+    static void get_json_impl(rapidjson::Value*& root, const std::string_view& json_string,
+                              const std::string_view& path_string, rapidjson::Document& document,
+                              typename NumberType::T& res, UInt8& null_map) {
+        if constexpr (std::is_same_v<double, typename NumberType::T>) {
+            root = get_json_object<JSON_FUN_DOUBLE>(json_string, path_string, &document);
+            handle_result<double>(root, res, null_map);
+        } else if constexpr (std::is_same_v<int32_t, typename NumberType::T>) {
+            root = get_json_object<JSON_FUN_DOUBLE>(json_string, path_string, &document);
+            handle_result<int32_t>(root, res, null_map);
+        } else if constexpr (std::is_same_v<int64_t, typename NumberType::T>) {
+            root = get_json_object<JSON_FUN_DOUBLE>(json_string, path_string, &document);
+            handle_result<int64_t>(root, res, null_map);
+        }
+    }
+    static void vector_vector(FunctionContext* context, const ColumnString::Chars& ldata,
+                              const ColumnString::Offsets& loffsets,
+                              const ColumnString::Chars& rdata,
+                              const ColumnString::Offsets& roffsets, Container& res,
+                              NullMap& null_map) {
+        size_t size = loffsets.size();
+        res.resize(size);
+        for (size_t i = 0; i < size; ++i) {
+            const char* l_raw_str = reinterpret_cast<const char*>(&ldata[loffsets[i - 1]]);
+            int l_str_size = loffsets[i] - loffsets[i - 1];
+            const char* r_raw_str = reinterpret_cast<const char*>(&rdata[roffsets[i - 1]]);
+            int r_str_size = roffsets[i] - roffsets[i - 1];
+            if (null_map[i]) {
+                res[i] = 0;
+                continue;
+            }
+
+            std::string_view json_string(l_raw_str, l_str_size);
+            std::string_view path_string(r_raw_str, r_str_size);
+            rapidjson::Document document;
+            rapidjson::Value* root = nullptr;
+
+            get_json_impl(root, json_string, path_string, document, res[i], null_map[i]);
+        }
+    }
+    static void vector_scalar(FunctionContext* context, const ColumnString::Chars& ldata,
+                              const ColumnString::Offsets& loffsets, const StringRef& rdata,
+                              Container& res, NullMap& null_map) {
+        size_t size = loffsets.size();
+        res.resize(size);
+        std::string_view path_string(rdata.data, rdata.size);
+        for (size_t i = 0; i < size; ++i) {
+            const char* l_raw_str = reinterpret_cast<const char*>(&ldata[loffsets[i - 1]]);
+            int l_str_size = loffsets[i] - loffsets[i - 1];
+            if (null_map[i]) {
+                res[i] = 0;
+                continue;
+            }
+            std::string_view json_string(l_raw_str, l_str_size);
+
+            rapidjson::Document document;
+            rapidjson::Value* root = nullptr;
+
+            get_json_impl(root, json_string, path_string, document, res[i], null_map[i]);
+        }
+    }
+    static void scalar_vector(FunctionContext* context, const StringRef& ldata,
+                              const ColumnString::Chars& rdata,
+                              const ColumnString::Offsets& roffsets, Container& res,
+                              NullMap& null_map) {
+        size_t size = roffsets.size();
+        res.resize(size);
+        std::string_view json_string(ldata.data, ldata.size);
+        for (size_t i = 0; i < size; ++i) {
+            const char* r_raw_str = reinterpret_cast<const char*>(&rdata[roffsets[i - 1]]);
+            int r_str_size = roffsets[i] - roffsets[i - 1];
+            if (null_map[i]) {
+                res[i] = 0;
+                continue;
+            }
+            std::string_view path_string(r_raw_str, r_str_size);
+            rapidjson::Document document;
+            rapidjson::Value* root = nullptr;
+
+            get_json_impl(root, json_string, path_string, document, res[i], null_map[i]);
+        }
+    }
+
+    template <typename T, std::enable_if_t<std::is_same_v<double, T>, T>* = nullptr>
+    static void handle_result(rapidjson::Value* root, T& res, uint8_t& res_null) {
+        if (root == nullptr || root->IsNull()) {
+            res = 0;
+            res_null = 1;
+        } else if (root->IsInt()) {
+            res = root->GetInt();
+        } else if (root->IsInt64()) {
+            res = root->GetInt64();
+        } else if (root->IsDouble()) {
+            res = root->GetDouble();
+        } else {
+            res_null = 1;
+        }
+    }
+
+    template <typename T, std::enable_if_t<std::is_same_v<int32_t, T>, T>* = nullptr>
+    static void handle_result(rapidjson::Value* root, int32_t& res, uint8_t& res_null) {
+        if (root != nullptr && root->IsInt()) {
+            res = root->GetInt();
+        } else {
+            res_null = 1;
+        }
+    }
+
+    template <typename T, std::enable_if_t<std::is_same_v<int64_t, T>, T>* = nullptr>
+    static void handle_result(rapidjson::Value* root, int64_t& res, uint8_t& res_null) {
+        if (root != nullptr && root->IsInt64()) {
+            res = root->GetInt64();
+        } else {
+            res_null = 1;
+        }
+    }
+};
+
+// Helper Class
+struct JsonNumberTypeDouble {
+    using T = Float64;
+    using ReturnType = DataTypeFloat64;
+    using ColumnType = ColumnVector<T>;
+};
+
+struct JsonNumberTypeInt {
+    using T = int32_t;
+    using ReturnType = DataTypeInt32;
+    using ColumnType = ColumnVector<T>;
+};
+
+struct JsonNumberTypeBigInt {
+    using T = int64_t;
+    using ReturnType = DataTypeInt64;
+    using ColumnType = ColumnVector<T>;
+};
+
+struct GetJsonDouble : public GetJsonNumberType<JsonNumberTypeDouble> {
+    static constexpr auto name = "get_json_double";
+    using ReturnType = typename JsonNumberTypeDouble::ReturnType;
+    using ColumnType = typename JsonNumberTypeDouble::ColumnType;
+};
+
+struct GetJsonInt : public GetJsonNumberType<JsonNumberTypeInt> {
+    static constexpr auto name = "get_json_int";
+    using ReturnType = typename JsonNumberTypeInt::ReturnType;
+    using ColumnType = typename JsonNumberTypeInt::ColumnType;
+};
+
+struct GetJsonBigInt : public GetJsonNumberType<JsonNumberTypeBigInt> {
+    static constexpr auto name = "get_json_bigint";
+    using ReturnType = typename JsonNumberTypeBigInt::ReturnType;
+    using ColumnType = typename JsonNumberTypeBigInt::ColumnType;
+};
+
+struct GetJsonString {
+    static constexpr auto name = "get_json_string";
+    using ReturnType = DataTypeString;
+    using ColumnType = ColumnString;
+    using Chars = ColumnString::Chars;
+    using Offsets = ColumnString::Offsets;
+    static void vector_vector(FunctionContext* context, const Chars& ldata, const Offsets& loffsets,
+                              const Chars& rdata, const Offsets& roffsets, Chars& res_data,
+                              Offsets& res_offsets, NullMap& null_map) {
+        size_t input_rows_count = loffsets.size();
+        res_offsets.resize(input_rows_count);
+
+        for (size_t i = 0; i < input_rows_count; ++i) {
+            if (null_map[i]) {
+                StringOP::push_null_string(i, res_data, res_offsets, null_map);
+                continue;
+            }
+            int l_size = loffsets[i] - loffsets[i - 1];
+            const auto l_raw = reinterpret_cast<const char*>(&ldata[loffsets[i - 1]]);
+            int r_size = roffsets[i] - roffsets[i - 1];
+            const auto r_raw = reinterpret_cast<const char*>(&rdata[roffsets[i - 1]]);
+
+            std::string_view json_string(l_raw, l_size);
+            std::string_view path_string(r_raw, r_size);
+
+            execute_impl(json_string, path_string, res_data, res_offsets, null_map, i);
+        }
+    }
+    static void vector_scalar(FunctionContext* context, const Chars& ldata, const Offsets& loffsets,
+                              const StringRef& rdata, Chars& res_data, Offsets& res_offsets,
+                              NullMap& null_map) {
+        size_t input_rows_count = loffsets.size();
+        res_offsets.resize(input_rows_count);
+
+        for (size_t i = 0; i < input_rows_count; ++i) {
+            if (null_map[i]) {
+                StringOP::push_null_string(i, res_data, res_offsets, null_map);
+                continue;
+            }
+            int l_size = loffsets[i] - loffsets[i - 1];
+            const auto l_raw = reinterpret_cast<const char*>(&ldata[loffsets[i - 1]]);
+
+            std::string_view json_string(l_raw, l_size);
+            std::string_view path_string(rdata.data, rdata.size);
+
+            execute_impl(json_string, path_string, res_data, res_offsets, null_map, i);
+        }
+    }
+    static void scalar_vector(FunctionContext* context, const StringRef& ldata, const Chars& rdata,
+                              const Offsets& roffsets, Chars& res_data, Offsets& res_offsets,
+                              NullMap& null_map) {
+        size_t input_rows_count = roffsets.size();
+        res_offsets.resize(input_rows_count);
+
+        for (size_t i = 0; i < input_rows_count; ++i) {
+            if (null_map[i]) {
+                StringOP::push_null_string(i, res_data, res_offsets, null_map);
+                continue;
+            }
+            int r_size = roffsets[i] - roffsets[i - 1];
+            const auto r_raw = reinterpret_cast<const char*>(&rdata[roffsets[i - 1]]);
+
+            std::string_view json_string(ldata.data, ldata.size);
+            std::string_view path_string(r_raw, r_size);
+
+            execute_impl(json_string, path_string, res_data, res_offsets, null_map, i);
+        }
+    }
+
+    static void execute_impl(const std::string_view& json_string,
+                             const std::string_view& path_string, Chars& res_data,
+                             Offsets& res_offsets, NullMap& null_map, size_t index_now) {
+        rapidjson::Document document;
+        rapidjson::Value* root = nullptr;
+
+        root = get_json_object<JSON_FUN_STRING>(json_string, path_string, &document);
+        const int max_string_len = 65535;
+
+        if (root == nullptr || root->IsNull()) {
+            StringOP::push_null_string(index_now, res_data, res_offsets, null_map);
+        } else if (root->IsString()) {
+            const auto ptr = root->GetString();
+            size_t len = strnlen(ptr, max_string_len);
+            StringOP::push_value_string(std::string_view(ptr, len), index_now, res_data,
+                                        res_offsets);
+        } else {
+            rapidjson::StringBuffer buf;
+            rapidjson::Writer<rapidjson::StringBuffer> writer(buf);
+            root->Accept(writer);
+
+            const auto ptr = buf.GetString();
+            size_t len = strnlen(ptr, max_string_len);
+            StringOP::push_value_string(std::string_view(ptr, len), index_now, res_data,
+                                        res_offsets);
+        }
+    }
+};
+
+template <int flag>
+struct JsonParser {
+    //string
+    static void update_value(StringParser::ParseResult& result, rapidjson::Value& value,
+                             StringRef data, rapidjson::Document::AllocatorType& allocator) {
+        value.SetString(data.data, data.size, allocator);
+    }
+};
+
+template <>
+struct JsonParser<'0'> {
+    // null
+    static void update_value(StringParser::ParseResult& result, rapidjson::Value& value,
+                             StringRef data, rapidjson::Document::AllocatorType& allocator) {
+        value.SetNull();
+    }
+};
+
+template <>
+struct JsonParser<'1'> {
+    // bool
+    static void update_value(StringParser::ParseResult& result, rapidjson::Value& value,
+                             StringRef data, rapidjson::Document::AllocatorType& allocator) {
+        DCHECK(data.size == 1 || strncmp(data.data, "true", 4) == 0 ||
+               strncmp(data.data, "false", 5) == 0);
+        value.SetBool((*data.data == '1' || *data.data == 't') ? true : false);
+    }
+};
+
+template <>
+struct JsonParser<'2'> {
+    // int
+    static void update_value(StringParser::ParseResult& result, rapidjson::Value& value,
+                             StringRef data, rapidjson::Document::AllocatorType& allocator) {
+        value.SetInt(StringParser::string_to_int<int32_t>(data.data, data.size, &result));
+    }
+};
+
+template <>
+struct JsonParser<'3'> {
+    // double
+    static void update_value(StringParser::ParseResult& result, rapidjson::Value& value,
+                             StringRef data, rapidjson::Document::AllocatorType& allocator) {
+        value.SetDouble(StringParser::string_to_float<double>(data.data, data.size, &result));
+    }
+};
+
+template <>
+struct JsonParser<'4'> {
+    // time
+    static void update_value(StringParser::ParseResult& result, rapidjson::Value& value,
+                             StringRef data, rapidjson::Document::AllocatorType& allocator) {
+        // remove double quotes, "xxx" -> xxx
+        value.SetString(data.data + 1, data.size - 2, allocator);
+    }
+};
+
+template <>
+struct JsonParser<'5'> {
+    // bigint
+    static void update_value(StringParser::ParseResult& result, rapidjson::Value& value,
+                             StringRef data, rapidjson::Document::AllocatorType& allocator) {
+        value.SetInt64(StringParser::string_to_int<int64_t>(data.data, data.size, &result));
+    }
+};
+
+template <int flag, typename Impl>
+struct ExecuteReducer {
+    template <typename... TArgs>
+    static void run(TArgs&&... args) {
+        Impl::template execute_type<JsonParser<flag>>(std::forward<TArgs>(args)...);
+    }
+};
+
+struct FunctionJsonArrayImpl {
+    static constexpr auto name = "json_array";
+
+    template <int flag>
+    using Reducer = ExecuteReducer<flag, FunctionJsonArrayImpl>;
+
+    static void execute_parse(const std::string& type_flags,
+                              const std::vector<const ColumnString*>& data_columns,
+                              std::vector<rapidjson::Value>& objects,
+                              rapidjson::Document::AllocatorType& allocator,
+                              const std::vector<const ColumnUInt8*>& nullmaps) {
+        for (int i = 0; i < data_columns.size() - 1; i++) {
+            constexpr_int_match<'0', '6', Reducer>::run(type_flags[i], objects, allocator,
+                                                        data_columns[i], nullmaps[i]);
+        }
+    }
+
+    template <typename TypeImpl>
+    static void execute_type(std::vector<rapidjson::Value>& objects,
+                             rapidjson::Document::AllocatorType& allocator,
+                             const ColumnString* data_column, const ColumnUInt8* nullmap) {
+        StringParser::ParseResult result;
+        rapidjson::Value value;
+
+        for (int i = 0; i < objects.size(); i++) {
+            if (nullmap != nullptr && nullmap->get_data()[i]) {
+                JsonParser<'0'>::update_value(result, value, data_column->get_data_at(i),
+                                              allocator);
+            } else {
+                TypeImpl::update_value(result, value, data_column->get_data_at(i), allocator);
+            }
+            objects[i].PushBack(value, allocator);
+        }
+    }
+};
+
+struct FunctionJsonObjectImpl {
+    static constexpr auto name = "json_object";
+
+    template <int flag>
+    using Reducer = ExecuteReducer<flag, FunctionJsonObjectImpl>;
+
+    static void execute_parse(std::string type_flags,
+                              const std::vector<const ColumnString*>& data_columns,
+                              std::vector<rapidjson::Value>& objects,
+                              rapidjson::Document::AllocatorType& allocator,
+                              const std::vector<const ColumnUInt8*>& nullmaps) {
+        for (auto& array_object : objects) {
+            array_object.SetObject();
+        }
+
+        for (int i = 0; i + 1 < data_columns.size() - 1; i += 2) {
+            constexpr_int_match<'0', '6', Reducer>::run(type_flags[i + 1], objects, allocator,
+                                                        data_columns[i], data_columns[i + 1],
+                                                        nullmaps[i + 1]);
+        }
+    }
+
+    template <typename TypeImpl>
+    static void execute_type(std::vector<rapidjson::Value>& objects,
+                             rapidjson::Document::AllocatorType& allocator,
+                             const ColumnString* key_column, const ColumnString* value_column,
+                             const ColumnUInt8* nullmap) {
+        StringParser::ParseResult result;
+        rapidjson::Value key;
+        rapidjson::Value value;
+        for (int i = 0; i < objects.size(); i++) {
+            JsonParser<'6'>::update_value(result, key, key_column->get_data_at(i),
+                                          allocator); // key always is string
+            if (nullmap != nullptr && nullmap->get_data()[i]) {
+                JsonParser<'0'>::update_value(result, value, value_column->get_data_at(i),
+                                              allocator);
+            } else {
+                TypeImpl::update_value(result, value, value_column->get_data_at(i), allocator);
+            }
+            objects[i].AddMember(key, value, allocator);
+        }
+    }
+};
+
+template <typename SpecificImpl>
+class FunctionJsonAlwaysNotNullable : public IFunction {
+public:
+    using IFunction::execute;
+
+    static constexpr auto name = SpecificImpl::name;
+
+    static FunctionPtr create() {
+        return std::make_shared<FunctionJsonAlwaysNotNullable<SpecificImpl>>();
+    }
+
+    bool use_default_implementation_for_nulls() const override { return false; }
+
+    String get_name() const override { return name; }
+
+    size_t get_number_of_arguments() const override { return 0; }
+
+    bool is_variadic() const override { return true; }
+
+    DataTypePtr get_return_type_impl(const DataTypes& arguments) const override {
+        return std::make_shared<DataTypeString>();
+    }
+
+    Status execute_impl(FunctionContext* context, Block& block, const ColumnNumbers& arguments,
+                        size_t result, size_t input_rows_count) override {
+        auto result_column = ColumnString::create();
+
+        std::vector<ColumnPtr> column_ptrs; // prevent converted column destruct
+        std::vector<const ColumnString*> data_columns;
+        std::vector<const ColumnUInt8*> nullmaps;
+        for (int i = 0; i < arguments.size(); i++) {
+            auto column = block.get_by_position(arguments[i]).column;
+            column_ptrs.push_back(column->convert_to_full_column_if_const());
+            const ColumnNullable* col_nullable =
+                    check_and_get_column<ColumnNullable>(column_ptrs.back().get());
+            if (col_nullable) {
+                const ColumnUInt8* col_nullmap = check_and_get_column<ColumnUInt8>(
+                        col_nullable->get_null_map_column_ptr().get());
+                nullmaps.push_back(col_nullmap);
+                const ColumnString* col = check_and_get_column<ColumnString>(
+                        col_nullable->get_nested_column_ptr().get());
+                data_columns.push_back(col);
+            } else {
+                nullmaps.push_back(nullptr);
+                data_columns.push_back(assert_cast<const ColumnString*>(column_ptrs.back().get()));
+            }
+        }
+        execute(data_columns, *assert_cast<ColumnString*>(result_column.get()), input_rows_count,
+                nullmaps);
+        block.get_by_position(result).column = std::move(result_column);
+        return Status::OK();
+    }
+
+    static void execute(const std::vector<const ColumnString*>& data_columns,
+                        ColumnString& result_column, size_t input_rows_count,
+                        const std::vector<const ColumnUInt8*> nullmaps) {
+        std::string type_flags = data_columns.back()->get_data_at(0).to_string();
+
+        rapidjson::Document document;
+        rapidjson::Document::AllocatorType& allocator = document.GetAllocator();
+
+        std::vector<rapidjson::Value> objects;
+        for (int i = 0; i < input_rows_count; i++) {
+            objects.emplace_back(rapidjson::kArrayType);
+        }
+
+        SpecificImpl::execute_parse(type_flags, data_columns, objects, allocator, nullmaps);
+
+        rapidjson::StringBuffer buf;
+        rapidjson::Writer<rapidjson::StringBuffer> writer(buf);
+
+        for (int i = 0; i < input_rows_count; i++) {
+            buf.Clear();
+            writer.Reset(buf);
+            objects[i].Accept(writer);
+            result_column.insert_data(buf.GetString(), buf.GetSize());
+        }
+    }
+};
+
+struct FunctionJsonQuoteImpl {
+    static constexpr auto name = "json_quote";
+
+    static void execute(const std::vector<const ColumnString*>& data_columns,
+                        ColumnString& result_column, size_t input_rows_count) {
+        rapidjson::Document document;
+        rapidjson::Document::AllocatorType& allocator = document.GetAllocator();
+
+        rapidjson::Value value;
+
+        rapidjson::StringBuffer buf;
+        rapidjson::Writer<rapidjson::StringBuffer> writer(buf);
+
+        for (int i = 0; i < input_rows_count; i++) {
+            StringRef data = data_columns[0]->get_data_at(i);
+            value.SetString(data.data, data.size, allocator);
+
+            buf.Clear();
+            value.Accept(writer);
+            result_column.insert_data(buf.GetString(), buf.GetSize());
+        }
+    }
+};
+
+struct FunctionJsonExtractImpl {
+    static constexpr auto name = "json_extract";
+
+    static rapidjson::Value parse_json(const ColumnString* json_col, const ColumnString* path_col,
+                                       rapidjson::Document::AllocatorType& allocator,
+                                       const int row) {
+        rapidjson::Value value;
+        rapidjson::Document document;
+
+        const auto obj = json_col->get_data_at(row);
+        std::string_view json_string(obj.data, obj.size);
+        const auto path = path_col->get_data_at(row);
+        std::string_view path_string(path.data, path.size);
+
+        auto root = get_json_object<JSON_FUN_STRING>(json_string, path_string, &document);
+        if (root != nullptr) {
+            value.CopyFrom(*root, allocator);
+        }
+        return value;
+    }
+
+    static void execute(const std::vector<const ColumnString*>& data_columns,
+                        ColumnString& result_column, size_t input_rows_count) {
+        rapidjson::Document document;
+        rapidjson::Document::AllocatorType& allocator = document.GetAllocator();
+        rapidjson::StringBuffer buf;
+        rapidjson::Writer<rapidjson::StringBuffer> writer(buf);
+
+        const auto json_col = data_columns[0];
+        for (size_t row = 0; row < input_rows_count; row++) {
+            rapidjson::Value value;
+            if (data_columns.size() == 2) {
+                value = parse_json(json_col, data_columns[1], allocator, row);
+            } else {
+                value.SetArray();
+                value.Reserve(data_columns.size() - 1, allocator);
+                for (size_t col = 1; col < data_columns.size(); ++col) {
+                    value.PushBack(parse_json(json_col, data_columns[col], allocator, row),
+                                   allocator);
+                }
+            }
+
+            // write value as string
+            buf.Clear();
+            writer.Reset(buf);
+            value.Accept(writer);
+            result_column.insert_data(buf.GetString(), buf.GetSize());
+        }
+    }
+};
+
+template <typename Impl>
+class FunctionJson : public IFunction {
+public:
+    static constexpr auto name = Impl::name;
+
+    static FunctionPtr create() { return std::make_shared<FunctionJson<Impl>>(); }
+
+    String get_name() const override { return name; }
+
+    size_t get_number_of_arguments() const override { return 0; }
+
+    bool is_variadic() const override { return true; }
+
+    DataTypePtr get_return_type_impl(const DataTypes& arguments) const override {
+        return std::make_shared<DataTypeString>();
+    }
+
+    Status execute_impl(FunctionContext* context, Block& block, const ColumnNumbers& arguments,
+                        size_t result, size_t input_rows_count) override {
+        auto result_column = ColumnString::create();
+
+        std::vector<ColumnPtr> column_ptrs; // prevent converted column destruct
+        std::vector<const ColumnString*> data_columns;
+        for (int i = 0; i < arguments.size(); i++) {
+            column_ptrs.push_back(
+                    block.get_by_position(arguments[i]).column->convert_to_full_column_if_const());
+            data_columns.push_back(assert_cast<const ColumnString*>(column_ptrs.back().get()));
+        }
+
+        Impl::execute(data_columns, *assert_cast<ColumnString*>(result_column.get()),
+                      input_rows_count);
+        block.get_by_position(result).column = std::move(result_column);
+        return Status::OK();
+    }
+};
+
+using FunctionGetJsonDouble = FunctionBinaryStringOperateToNullType<GetJsonDouble>;
+using FunctionGetJsonInt = FunctionBinaryStringOperateToNullType<GetJsonInt>;
+using FunctionGetJsonBigInt = FunctionBinaryStringOperateToNullType<GetJsonBigInt>;
+using FunctionGetJsonString = FunctionBinaryStringOperateToNullType<GetJsonString>;
+
+class FunctionJsonValid : public IFunction {
+public:
+    static constexpr auto name = "json_valid";
+    static FunctionPtr create() { return std::make_shared<FunctionJsonValid>(); }
+
+    String get_name() const override { return name; }
+
+    size_t get_number_of_arguments() const override { return 1; }
+
+    DataTypePtr get_return_type_impl(const DataTypes& arguments) const override {
+        return make_nullable(std::make_shared<DataTypeInt32>());
+    }
+
+    bool use_default_implementation_for_nulls() const override { return false; }

Review Comment:
   warning: function 'use_default_implementation_for_nulls' should be marked [[nodiscard]] [modernize-use-nodiscard]
   
   ```suggestion
       [[nodiscard]] bool use_default_implementation_for_nulls() const override { return false; }
   ```
   



##########
function_json.cpp:
##########
@@ -0,0 +1,1320 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#include <rapidjson/allocators.h>
+#include <rapidjson/document.h>
+#include <rapidjson/encodings.h>
+#include <rapidjson/pointer.h>
+#include <rapidjson/rapidjson.h>
+#include <rapidjson/stringbuffer.h>
+#include <rapidjson/writer.h>
+#include <re2/re2.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <algorithm>
+#include <boost/iterator/iterator_facade.hpp>
+#include <boost/token_functions.hpp>
+#include <boost/tokenizer.hpp>
+#include <memory>
+#include <string>
+#include <string_view>
+#include <type_traits>
+#include <utility>
+#include <vector>
+
+// IWYU pragma: no_include <opentelemetry/common/threadlocal.h>
+#include "common/compiler_util.h" // IWYU pragma: keep
+#include "common/status.h"
+#include "exprs/json_functions.h"
+#ifdef __AVX2__
+#include "util/jsonb_parser_simd.h"
+#else
+#include "util/jsonb_parser.h"
+#endif
+#include "util/string_parser.hpp"
+#include "util/string_util.h"
+#include "vec/aggregate_functions/aggregate_function.h"
+#include "vec/columns/column.h"
+#include "vec/columns/column_nullable.h"
+#include "vec/columns/column_string.h"
+#include "vec/columns/column_vector.h"
+#include "vec/columns/columns_number.h"
+#include "vec/common/assert_cast.h"
+#include "vec/common/string_ref.h"
+#include "vec/core/block.h"
+#include "vec/core/column_numbers.h"
+#include "vec/core/column_with_type_and_name.h"
+#include "vec/core/types.h"
+#include "vec/data_types/data_type.h"
+#include "vec/data_types/data_type_nullable.h"
+#include "vec/data_types/data_type_number.h"
+#include "vec/data_types/data_type_string.h"
+#include "vec/functions/function.h"
+#include "vec/functions/function_string.h"
+#include "vec/functions/function_totype.h"
+#include "vec/functions/simple_function_factory.h"
+#include "vec/utils/template_helpers.hpp"
+
+namespace doris {
+class FunctionContext;
+} // namespace doris
+
+namespace doris::vectorized {
+static const re2::RE2 JSON_PATTERN("^([^\\\"\\[\\]]*)(?:\\[([0-9]+|\\*)\\])?");
+
+template <typename T, typename U>
+void char_split(std::vector<T>& res, const U& var, char p) {
+    int start = 0;
+    int pos = start;
+    int end = var.length();
+    while (pos < end) {
+        while (var[pos] != p && pos < end) {
+            pos++;
+        }
+        res.emplace_back(&var[start], pos - start);
+        pos++;
+        start = pos;
+    }
+}
+
+// T = std::vector<std::string>
+// TODO: update RE2 to support std::vector<std::string_view>
+template <typename T>
+void get_parsed_paths(const T& path_exprs, std::vector<JsonPath>* parsed_paths) {
+    if (path_exprs.empty()) {
+        return;
+    }
+
+    if (path_exprs[0] != "$") {
+        parsed_paths->emplace_back("", -1, false);
+    } else {
+        parsed_paths->emplace_back("$", -1, true);
+    }
+
+    for (int i = 1; i < path_exprs.size(); i++) {
+        std::string col;
+        std::string index;
+        if (UNLIKELY(!RE2::FullMatch(path_exprs[i], JSON_PATTERN, &col, &index))) {
+            parsed_paths->emplace_back("", -1, false);
+        } else {
+            int idx = -1;
+            if (!index.empty()) {
+                if (index == "*") {
+                    idx = -2;
+                } else {
+                    idx = atoi(index.c_str());
+                }
+            }
+            parsed_paths->emplace_back(col, idx, true);
+        }
+    }
+}
+
+rapidjson::Value* match_value(const std::vector<JsonPath>& parsed_paths, rapidjson::Value* document,
+                              rapidjson::Document::AllocatorType& mem_allocator,
+                              bool is_insert_null = false) {
+    rapidjson::Value* root = document;
+    rapidjson::Value* array_obj = nullptr;
+    for (int i = 1; i < parsed_paths.size(); i++) {
+        if (root == nullptr || root->IsNull()) {
+            return nullptr;
+        }
+
+        if (UNLIKELY(!parsed_paths[i].is_valid)) {
+            return nullptr;
+        }
+
+        const std::string& col = parsed_paths[i].key;
+        int index = parsed_paths[i].idx;
+        if (LIKELY(!col.empty())) {
+            if (root->IsArray()) {
+                array_obj = static_cast<rapidjson::Value*>(
+                        mem_allocator.Malloc(sizeof(rapidjson::Value)));
+                array_obj->SetArray();
+                bool is_null = true;
+
+                // if array ,loop the array,find out all Objects,then find the results from the objects
+                for (int j = 0; j < root->Size(); j++) {
+                    rapidjson::Value* json_elem = &((*root)[j]);
+
+                    if (json_elem->IsArray() || json_elem->IsNull()) {
+                        continue;
+                    } else {
+                        if (!json_elem->IsObject()) {
+                            continue;
+                        }
+                        if (!json_elem->HasMember(col.c_str())) {
+                            if (is_insert_null) { // not found item, then insert a null object.
+                                is_null = false;
+                                rapidjson::Value nullObject(rapidjson::kNullType);
+                                array_obj->PushBack(nullObject, mem_allocator);
+                            }
+                            continue;
+                        }
+                        rapidjson::Value* obj = &((*json_elem)[col.c_str()]);
+                        if (obj->IsArray()) {
+                            is_null = false;
+                            for (int k = 0; k < obj->Size(); k++) {
+                                array_obj->PushBack((*obj)[k], mem_allocator);
+                            }
+                        } else if (!obj->IsNull()) {
+                            is_null = false;
+                            array_obj->PushBack(*obj, mem_allocator);
+                        }
+                    }
+                }
+
+                root = is_null ? &(array_obj->SetNull()) : array_obj;
+            } else if (root->IsObject()) {
+                if (!root->HasMember(col.c_str())) {
+                    return nullptr;
+                } else {
+                    root = &((*root)[col.c_str()]);
+                }
+            } else {
+                // root is not a nested type, return NULL
+                return nullptr;
+            }
+        }
+
+        if (UNLIKELY(index != -1)) {
+            // judge the rapidjson:Value, which base the top's result,
+            // if not array return NULL;else get the index value from the array
+            if (root->IsArray()) {
+                if (root->IsNull()) {
+                    return nullptr;
+                } else if (index == -2) {
+                    // [*]
+                    array_obj = static_cast<rapidjson::Value*>(
+                            mem_allocator.Malloc(sizeof(rapidjson::Value)));
+                    array_obj->SetArray();
+
+                    for (int j = 0; j < root->Size(); j++) {
+                        rapidjson::Value v;
+                        v.CopyFrom((*root)[j], mem_allocator);
+                        array_obj->PushBack(v, mem_allocator);
+                    }
+                    root = array_obj;
+                } else if (index >= root->Size()) {
+                    return nullptr;
+                } else {
+                    root = &((*root)[index]);
+                }
+            } else {
+                return nullptr;
+            }
+        }
+    }
+    return root;
+}
+
+template <JsonFunctionType fntype>
+rapidjson::Value* get_json_object(std::string_view json_string, std::string_view path_string,
+                                  rapidjson::Document* document) {
+    std::vector<JsonPath>* parsed_paths;
+    std::vector<JsonPath> tmp_parsed_paths;
+
+#ifdef USE_LIBCPP
+    std::string s(path_string);
+    auto tok = get_json_token(s);
+#else
+    auto tok = get_json_token(path_string);
+#endif
+    std::vector<std::string> paths(tok.begin(), tok.end());
+    get_parsed_paths(paths, &tmp_parsed_paths);
+    if (tmp_parsed_paths.empty()) {
+        return document;
+    }
+
+    parsed_paths = &tmp_parsed_paths;
+
+    if (!(*parsed_paths)[0].is_valid) {
+        return document;
+    }
+
+    if (UNLIKELY((*parsed_paths).size() == 1)) {
+        if (fntype == JSON_FUN_STRING) {
+            document->SetString(json_string.data(), json_string.size(), document->GetAllocator());
+        } else {
+            return document;
+        }
+    }
+
+    document->Parse(json_string.data(), json_string.size());
+    if (UNLIKELY(document->HasParseError())) {
+        // VLOG_CRITICAL << "Error at offset " << document->GetErrorOffset() << ": "
+        //         << GetParseError_En(document->GetParseError());
+        document->SetNull();
+        return document;
+    }
+
+    return match_value(*parsed_paths, document, document->GetAllocator());
+}
+
+template <typename NumberType>
+struct GetJsonNumberType {
+    using ReturnType = typename NumberType::ReturnType;
+    using ColumnType = typename NumberType::ColumnType;
+    using Container = typename ColumnType::Container;
+
+    static void get_json_impl(rapidjson::Value*& root, const std::string_view& json_string,
+                              const std::string_view& path_string, rapidjson::Document& document,
+                              typename NumberType::T& res, UInt8& null_map) {
+        if constexpr (std::is_same_v<double, typename NumberType::T>) {
+            root = get_json_object<JSON_FUN_DOUBLE>(json_string, path_string, &document);
+            handle_result<double>(root, res, null_map);
+        } else if constexpr (std::is_same_v<int32_t, typename NumberType::T>) {
+            root = get_json_object<JSON_FUN_DOUBLE>(json_string, path_string, &document);
+            handle_result<int32_t>(root, res, null_map);
+        } else if constexpr (std::is_same_v<int64_t, typename NumberType::T>) {
+            root = get_json_object<JSON_FUN_DOUBLE>(json_string, path_string, &document);
+            handle_result<int64_t>(root, res, null_map);
+        }
+    }
+    static void vector_vector(FunctionContext* context, const ColumnString::Chars& ldata,
+                              const ColumnString::Offsets& loffsets,
+                              const ColumnString::Chars& rdata,
+                              const ColumnString::Offsets& roffsets, Container& res,
+                              NullMap& null_map) {
+        size_t size = loffsets.size();
+        res.resize(size);
+        for (size_t i = 0; i < size; ++i) {
+            const char* l_raw_str = reinterpret_cast<const char*>(&ldata[loffsets[i - 1]]);
+            int l_str_size = loffsets[i] - loffsets[i - 1];
+            const char* r_raw_str = reinterpret_cast<const char*>(&rdata[roffsets[i - 1]]);
+            int r_str_size = roffsets[i] - roffsets[i - 1];
+            if (null_map[i]) {
+                res[i] = 0;
+                continue;
+            }
+
+            std::string_view json_string(l_raw_str, l_str_size);
+            std::string_view path_string(r_raw_str, r_str_size);
+            rapidjson::Document document;
+            rapidjson::Value* root = nullptr;
+
+            get_json_impl(root, json_string, path_string, document, res[i], null_map[i]);
+        }
+    }
+    static void vector_scalar(FunctionContext* context, const ColumnString::Chars& ldata,
+                              const ColumnString::Offsets& loffsets, const StringRef& rdata,
+                              Container& res, NullMap& null_map) {
+        size_t size = loffsets.size();
+        res.resize(size);
+        std::string_view path_string(rdata.data, rdata.size);
+        for (size_t i = 0; i < size; ++i) {
+            const char* l_raw_str = reinterpret_cast<const char*>(&ldata[loffsets[i - 1]]);
+            int l_str_size = loffsets[i] - loffsets[i - 1];
+            if (null_map[i]) {
+                res[i] = 0;
+                continue;
+            }
+            std::string_view json_string(l_raw_str, l_str_size);
+
+            rapidjson::Document document;
+            rapidjson::Value* root = nullptr;
+
+            get_json_impl(root, json_string, path_string, document, res[i], null_map[i]);
+        }
+    }
+    static void scalar_vector(FunctionContext* context, const StringRef& ldata,
+                              const ColumnString::Chars& rdata,
+                              const ColumnString::Offsets& roffsets, Container& res,
+                              NullMap& null_map) {
+        size_t size = roffsets.size();
+        res.resize(size);
+        std::string_view json_string(ldata.data, ldata.size);
+        for (size_t i = 0; i < size; ++i) {
+            const char* r_raw_str = reinterpret_cast<const char*>(&rdata[roffsets[i - 1]]);
+            int r_str_size = roffsets[i] - roffsets[i - 1];
+            if (null_map[i]) {
+                res[i] = 0;
+                continue;
+            }
+            std::string_view path_string(r_raw_str, r_str_size);
+            rapidjson::Document document;
+            rapidjson::Value* root = nullptr;
+
+            get_json_impl(root, json_string, path_string, document, res[i], null_map[i]);
+        }
+    }
+
+    template <typename T, std::enable_if_t<std::is_same_v<double, T>, T>* = nullptr>
+    static void handle_result(rapidjson::Value* root, T& res, uint8_t& res_null) {
+        if (root == nullptr || root->IsNull()) {
+            res = 0;
+            res_null = 1;
+        } else if (root->IsInt()) {
+            res = root->GetInt();
+        } else if (root->IsInt64()) {
+            res = root->GetInt64();
+        } else if (root->IsDouble()) {
+            res = root->GetDouble();
+        } else {
+            res_null = 1;
+        }
+    }
+
+    template <typename T, std::enable_if_t<std::is_same_v<int32_t, T>, T>* = nullptr>
+    static void handle_result(rapidjson::Value* root, int32_t& res, uint8_t& res_null) {
+        if (root != nullptr && root->IsInt()) {
+            res = root->GetInt();
+        } else {
+            res_null = 1;
+        }
+    }
+
+    template <typename T, std::enable_if_t<std::is_same_v<int64_t, T>, T>* = nullptr>
+    static void handle_result(rapidjson::Value* root, int64_t& res, uint8_t& res_null) {
+        if (root != nullptr && root->IsInt64()) {
+            res = root->GetInt64();
+        } else {
+            res_null = 1;
+        }
+    }
+};
+
+// Helper Class
+struct JsonNumberTypeDouble {
+    using T = Float64;
+    using ReturnType = DataTypeFloat64;
+    using ColumnType = ColumnVector<T>;
+};
+
+struct JsonNumberTypeInt {
+    using T = int32_t;
+    using ReturnType = DataTypeInt32;
+    using ColumnType = ColumnVector<T>;
+};
+
+struct JsonNumberTypeBigInt {
+    using T = int64_t;
+    using ReturnType = DataTypeInt64;
+    using ColumnType = ColumnVector<T>;
+};
+
+struct GetJsonDouble : public GetJsonNumberType<JsonNumberTypeDouble> {
+    static constexpr auto name = "get_json_double";
+    using ReturnType = typename JsonNumberTypeDouble::ReturnType;
+    using ColumnType = typename JsonNumberTypeDouble::ColumnType;
+};
+
+struct GetJsonInt : public GetJsonNumberType<JsonNumberTypeInt> {
+    static constexpr auto name = "get_json_int";
+    using ReturnType = typename JsonNumberTypeInt::ReturnType;
+    using ColumnType = typename JsonNumberTypeInt::ColumnType;
+};
+
+struct GetJsonBigInt : public GetJsonNumberType<JsonNumberTypeBigInt> {
+    static constexpr auto name = "get_json_bigint";
+    using ReturnType = typename JsonNumberTypeBigInt::ReturnType;
+    using ColumnType = typename JsonNumberTypeBigInt::ColumnType;
+};
+
+struct GetJsonString {
+    static constexpr auto name = "get_json_string";
+    using ReturnType = DataTypeString;
+    using ColumnType = ColumnString;
+    using Chars = ColumnString::Chars;
+    using Offsets = ColumnString::Offsets;
+    static void vector_vector(FunctionContext* context, const Chars& ldata, const Offsets& loffsets,
+                              const Chars& rdata, const Offsets& roffsets, Chars& res_data,
+                              Offsets& res_offsets, NullMap& null_map) {
+        size_t input_rows_count = loffsets.size();
+        res_offsets.resize(input_rows_count);
+
+        for (size_t i = 0; i < input_rows_count; ++i) {
+            if (null_map[i]) {
+                StringOP::push_null_string(i, res_data, res_offsets, null_map);
+                continue;
+            }
+            int l_size = loffsets[i] - loffsets[i - 1];
+            const auto l_raw = reinterpret_cast<const char*>(&ldata[loffsets[i - 1]]);
+            int r_size = roffsets[i] - roffsets[i - 1];
+            const auto r_raw = reinterpret_cast<const char*>(&rdata[roffsets[i - 1]]);
+
+            std::string_view json_string(l_raw, l_size);
+            std::string_view path_string(r_raw, r_size);
+
+            execute_impl(json_string, path_string, res_data, res_offsets, null_map, i);
+        }
+    }
+    static void vector_scalar(FunctionContext* context, const Chars& ldata, const Offsets& loffsets,
+                              const StringRef& rdata, Chars& res_data, Offsets& res_offsets,
+                              NullMap& null_map) {
+        size_t input_rows_count = loffsets.size();
+        res_offsets.resize(input_rows_count);
+
+        for (size_t i = 0; i < input_rows_count; ++i) {
+            if (null_map[i]) {
+                StringOP::push_null_string(i, res_data, res_offsets, null_map);
+                continue;
+            }
+            int l_size = loffsets[i] - loffsets[i - 1];
+            const auto l_raw = reinterpret_cast<const char*>(&ldata[loffsets[i - 1]]);
+
+            std::string_view json_string(l_raw, l_size);
+            std::string_view path_string(rdata.data, rdata.size);
+
+            execute_impl(json_string, path_string, res_data, res_offsets, null_map, i);
+        }
+    }
+    static void scalar_vector(FunctionContext* context, const StringRef& ldata, const Chars& rdata,
+                              const Offsets& roffsets, Chars& res_data, Offsets& res_offsets,
+                              NullMap& null_map) {
+        size_t input_rows_count = roffsets.size();
+        res_offsets.resize(input_rows_count);
+
+        for (size_t i = 0; i < input_rows_count; ++i) {
+            if (null_map[i]) {
+                StringOP::push_null_string(i, res_data, res_offsets, null_map);
+                continue;
+            }
+            int r_size = roffsets[i] - roffsets[i - 1];
+            const auto r_raw = reinterpret_cast<const char*>(&rdata[roffsets[i - 1]]);
+
+            std::string_view json_string(ldata.data, ldata.size);
+            std::string_view path_string(r_raw, r_size);
+
+            execute_impl(json_string, path_string, res_data, res_offsets, null_map, i);
+        }
+    }
+
+    static void execute_impl(const std::string_view& json_string,
+                             const std::string_view& path_string, Chars& res_data,
+                             Offsets& res_offsets, NullMap& null_map, size_t index_now) {
+        rapidjson::Document document;
+        rapidjson::Value* root = nullptr;
+
+        root = get_json_object<JSON_FUN_STRING>(json_string, path_string, &document);
+        const int max_string_len = 65535;
+
+        if (root == nullptr || root->IsNull()) {
+            StringOP::push_null_string(index_now, res_data, res_offsets, null_map);
+        } else if (root->IsString()) {
+            const auto ptr = root->GetString();
+            size_t len = strnlen(ptr, max_string_len);
+            StringOP::push_value_string(std::string_view(ptr, len), index_now, res_data,
+                                        res_offsets);
+        } else {
+            rapidjson::StringBuffer buf;
+            rapidjson::Writer<rapidjson::StringBuffer> writer(buf);
+            root->Accept(writer);
+
+            const auto ptr = buf.GetString();
+            size_t len = strnlen(ptr, max_string_len);
+            StringOP::push_value_string(std::string_view(ptr, len), index_now, res_data,
+                                        res_offsets);
+        }
+    }
+};
+
+template <int flag>
+struct JsonParser {
+    //string
+    static void update_value(StringParser::ParseResult& result, rapidjson::Value& value,
+                             StringRef data, rapidjson::Document::AllocatorType& allocator) {
+        value.SetString(data.data, data.size, allocator);
+    }
+};
+
+template <>
+struct JsonParser<'0'> {
+    // null
+    static void update_value(StringParser::ParseResult& result, rapidjson::Value& value,
+                             StringRef data, rapidjson::Document::AllocatorType& allocator) {
+        value.SetNull();
+    }
+};
+
+template <>
+struct JsonParser<'1'> {
+    // bool
+    static void update_value(StringParser::ParseResult& result, rapidjson::Value& value,
+                             StringRef data, rapidjson::Document::AllocatorType& allocator) {
+        DCHECK(data.size == 1 || strncmp(data.data, "true", 4) == 0 ||
+               strncmp(data.data, "false", 5) == 0);
+        value.SetBool((*data.data == '1' || *data.data == 't') ? true : false);
+    }
+};
+
+template <>
+struct JsonParser<'2'> {
+    // int
+    static void update_value(StringParser::ParseResult& result, rapidjson::Value& value,
+                             StringRef data, rapidjson::Document::AllocatorType& allocator) {
+        value.SetInt(StringParser::string_to_int<int32_t>(data.data, data.size, &result));
+    }
+};
+
+template <>
+struct JsonParser<'3'> {
+    // double
+    static void update_value(StringParser::ParseResult& result, rapidjson::Value& value,
+                             StringRef data, rapidjson::Document::AllocatorType& allocator) {
+        value.SetDouble(StringParser::string_to_float<double>(data.data, data.size, &result));
+    }
+};
+
+template <>
+struct JsonParser<'4'> {
+    // time
+    static void update_value(StringParser::ParseResult& result, rapidjson::Value& value,
+                             StringRef data, rapidjson::Document::AllocatorType& allocator) {
+        // remove double quotes, "xxx" -> xxx
+        value.SetString(data.data + 1, data.size - 2, allocator);
+    }
+};
+
+template <>
+struct JsonParser<'5'> {
+    // bigint
+    static void update_value(StringParser::ParseResult& result, rapidjson::Value& value,
+                             StringRef data, rapidjson::Document::AllocatorType& allocator) {
+        value.SetInt64(StringParser::string_to_int<int64_t>(data.data, data.size, &result));
+    }
+};
+
+template <int flag, typename Impl>
+struct ExecuteReducer {
+    template <typename... TArgs>
+    static void run(TArgs&&... args) {
+        Impl::template execute_type<JsonParser<flag>>(std::forward<TArgs>(args)...);
+    }
+};
+
+struct FunctionJsonArrayImpl {
+    static constexpr auto name = "json_array";
+
+    template <int flag>
+    using Reducer = ExecuteReducer<flag, FunctionJsonArrayImpl>;
+
+    static void execute_parse(const std::string& type_flags,
+                              const std::vector<const ColumnString*>& data_columns,
+                              std::vector<rapidjson::Value>& objects,
+                              rapidjson::Document::AllocatorType& allocator,
+                              const std::vector<const ColumnUInt8*>& nullmaps) {
+        for (int i = 0; i < data_columns.size() - 1; i++) {
+            constexpr_int_match<'0', '6', Reducer>::run(type_flags[i], objects, allocator,
+                                                        data_columns[i], nullmaps[i]);
+        }
+    }
+
+    template <typename TypeImpl>
+    static void execute_type(std::vector<rapidjson::Value>& objects,
+                             rapidjson::Document::AllocatorType& allocator,
+                             const ColumnString* data_column, const ColumnUInt8* nullmap) {
+        StringParser::ParseResult result;
+        rapidjson::Value value;
+
+        for (int i = 0; i < objects.size(); i++) {
+            if (nullmap != nullptr && nullmap->get_data()[i]) {
+                JsonParser<'0'>::update_value(result, value, data_column->get_data_at(i),
+                                              allocator);
+            } else {
+                TypeImpl::update_value(result, value, data_column->get_data_at(i), allocator);
+            }
+            objects[i].PushBack(value, allocator);
+        }
+    }
+};
+
+struct FunctionJsonObjectImpl {
+    static constexpr auto name = "json_object";
+
+    template <int flag>
+    using Reducer = ExecuteReducer<flag, FunctionJsonObjectImpl>;
+
+    static void execute_parse(std::string type_flags,
+                              const std::vector<const ColumnString*>& data_columns,
+                              std::vector<rapidjson::Value>& objects,
+                              rapidjson::Document::AllocatorType& allocator,
+                              const std::vector<const ColumnUInt8*>& nullmaps) {
+        for (auto& array_object : objects) {
+            array_object.SetObject();
+        }
+
+        for (int i = 0; i + 1 < data_columns.size() - 1; i += 2) {
+            constexpr_int_match<'0', '6', Reducer>::run(type_flags[i + 1], objects, allocator,
+                                                        data_columns[i], data_columns[i + 1],
+                                                        nullmaps[i + 1]);
+        }
+    }
+
+    template <typename TypeImpl>
+    static void execute_type(std::vector<rapidjson::Value>& objects,
+                             rapidjson::Document::AllocatorType& allocator,
+                             const ColumnString* key_column, const ColumnString* value_column,
+                             const ColumnUInt8* nullmap) {
+        StringParser::ParseResult result;
+        rapidjson::Value key;
+        rapidjson::Value value;
+        for (int i = 0; i < objects.size(); i++) {
+            JsonParser<'6'>::update_value(result, key, key_column->get_data_at(i),
+                                          allocator); // key always is string
+            if (nullmap != nullptr && nullmap->get_data()[i]) {
+                JsonParser<'0'>::update_value(result, value, value_column->get_data_at(i),
+                                              allocator);
+            } else {
+                TypeImpl::update_value(result, value, value_column->get_data_at(i), allocator);
+            }
+            objects[i].AddMember(key, value, allocator);
+        }
+    }
+};
+
+template <typename SpecificImpl>
+class FunctionJsonAlwaysNotNullable : public IFunction {
+public:
+    using IFunction::execute;
+
+    static constexpr auto name = SpecificImpl::name;
+
+    static FunctionPtr create() {
+        return std::make_shared<FunctionJsonAlwaysNotNullable<SpecificImpl>>();
+    }
+
+    bool use_default_implementation_for_nulls() const override { return false; }
+
+    String get_name() const override { return name; }
+
+    size_t get_number_of_arguments() const override { return 0; }
+
+    bool is_variadic() const override { return true; }
+
+    DataTypePtr get_return_type_impl(const DataTypes& arguments) const override {
+        return std::make_shared<DataTypeString>();
+    }
+
+    Status execute_impl(FunctionContext* context, Block& block, const ColumnNumbers& arguments,
+                        size_t result, size_t input_rows_count) override {
+        auto result_column = ColumnString::create();
+
+        std::vector<ColumnPtr> column_ptrs; // prevent converted column destruct
+        std::vector<const ColumnString*> data_columns;
+        std::vector<const ColumnUInt8*> nullmaps;
+        for (int i = 0; i < arguments.size(); i++) {
+            auto column = block.get_by_position(arguments[i]).column;
+            column_ptrs.push_back(column->convert_to_full_column_if_const());
+            const ColumnNullable* col_nullable =
+                    check_and_get_column<ColumnNullable>(column_ptrs.back().get());
+            if (col_nullable) {
+                const ColumnUInt8* col_nullmap = check_and_get_column<ColumnUInt8>(
+                        col_nullable->get_null_map_column_ptr().get());
+                nullmaps.push_back(col_nullmap);
+                const ColumnString* col = check_and_get_column<ColumnString>(
+                        col_nullable->get_nested_column_ptr().get());
+                data_columns.push_back(col);
+            } else {
+                nullmaps.push_back(nullptr);
+                data_columns.push_back(assert_cast<const ColumnString*>(column_ptrs.back().get()));
+            }
+        }
+        execute(data_columns, *assert_cast<ColumnString*>(result_column.get()), input_rows_count,
+                nullmaps);
+        block.get_by_position(result).column = std::move(result_column);
+        return Status::OK();
+    }
+
+    static void execute(const std::vector<const ColumnString*>& data_columns,
+                        ColumnString& result_column, size_t input_rows_count,
+                        const std::vector<const ColumnUInt8*> nullmaps) {
+        std::string type_flags = data_columns.back()->get_data_at(0).to_string();
+
+        rapidjson::Document document;
+        rapidjson::Document::AllocatorType& allocator = document.GetAllocator();
+
+        std::vector<rapidjson::Value> objects;
+        for (int i = 0; i < input_rows_count; i++) {
+            objects.emplace_back(rapidjson::kArrayType);
+        }
+
+        SpecificImpl::execute_parse(type_flags, data_columns, objects, allocator, nullmaps);
+
+        rapidjson::StringBuffer buf;
+        rapidjson::Writer<rapidjson::StringBuffer> writer(buf);
+
+        for (int i = 0; i < input_rows_count; i++) {
+            buf.Clear();
+            writer.Reset(buf);
+            objects[i].Accept(writer);
+            result_column.insert_data(buf.GetString(), buf.GetSize());
+        }
+    }
+};
+
+struct FunctionJsonQuoteImpl {
+    static constexpr auto name = "json_quote";
+
+    static void execute(const std::vector<const ColumnString*>& data_columns,
+                        ColumnString& result_column, size_t input_rows_count) {
+        rapidjson::Document document;
+        rapidjson::Document::AllocatorType& allocator = document.GetAllocator();
+
+        rapidjson::Value value;
+
+        rapidjson::StringBuffer buf;
+        rapidjson::Writer<rapidjson::StringBuffer> writer(buf);
+
+        for (int i = 0; i < input_rows_count; i++) {
+            StringRef data = data_columns[0]->get_data_at(i);
+            value.SetString(data.data, data.size, allocator);
+
+            buf.Clear();
+            value.Accept(writer);
+            result_column.insert_data(buf.GetString(), buf.GetSize());
+        }
+    }
+};
+
+struct FunctionJsonExtractImpl {
+    static constexpr auto name = "json_extract";
+
+    static rapidjson::Value parse_json(const ColumnString* json_col, const ColumnString* path_col,
+                                       rapidjson::Document::AllocatorType& allocator,
+                                       const int row) {
+        rapidjson::Value value;
+        rapidjson::Document document;
+
+        const auto obj = json_col->get_data_at(row);
+        std::string_view json_string(obj.data, obj.size);
+        const auto path = path_col->get_data_at(row);
+        std::string_view path_string(path.data, path.size);
+
+        auto root = get_json_object<JSON_FUN_STRING>(json_string, path_string, &document);
+        if (root != nullptr) {
+            value.CopyFrom(*root, allocator);
+        }
+        return value;
+    }
+
+    static void execute(const std::vector<const ColumnString*>& data_columns,
+                        ColumnString& result_column, size_t input_rows_count) {
+        rapidjson::Document document;
+        rapidjson::Document::AllocatorType& allocator = document.GetAllocator();
+        rapidjson::StringBuffer buf;
+        rapidjson::Writer<rapidjson::StringBuffer> writer(buf);
+
+        const auto json_col = data_columns[0];
+        for (size_t row = 0; row < input_rows_count; row++) {
+            rapidjson::Value value;
+            if (data_columns.size() == 2) {
+                value = parse_json(json_col, data_columns[1], allocator, row);
+            } else {
+                value.SetArray();
+                value.Reserve(data_columns.size() - 1, allocator);
+                for (size_t col = 1; col < data_columns.size(); ++col) {
+                    value.PushBack(parse_json(json_col, data_columns[col], allocator, row),
+                                   allocator);
+                }
+            }
+
+            // write value as string
+            buf.Clear();
+            writer.Reset(buf);
+            value.Accept(writer);
+            result_column.insert_data(buf.GetString(), buf.GetSize());
+        }
+    }
+};
+
+template <typename Impl>
+class FunctionJson : public IFunction {
+public:
+    static constexpr auto name = Impl::name;
+
+    static FunctionPtr create() { return std::make_shared<FunctionJson<Impl>>(); }
+
+    String get_name() const override { return name; }
+
+    size_t get_number_of_arguments() const override { return 0; }
+
+    bool is_variadic() const override { return true; }
+
+    DataTypePtr get_return_type_impl(const DataTypes& arguments) const override {
+        return std::make_shared<DataTypeString>();
+    }
+
+    Status execute_impl(FunctionContext* context, Block& block, const ColumnNumbers& arguments,
+                        size_t result, size_t input_rows_count) override {
+        auto result_column = ColumnString::create();
+
+        std::vector<ColumnPtr> column_ptrs; // prevent converted column destruct
+        std::vector<const ColumnString*> data_columns;
+        for (int i = 0; i < arguments.size(); i++) {
+            column_ptrs.push_back(
+                    block.get_by_position(arguments[i]).column->convert_to_full_column_if_const());
+            data_columns.push_back(assert_cast<const ColumnString*>(column_ptrs.back().get()));
+        }
+
+        Impl::execute(data_columns, *assert_cast<ColumnString*>(result_column.get()),
+                      input_rows_count);
+        block.get_by_position(result).column = std::move(result_column);
+        return Status::OK();
+    }
+};
+
+using FunctionGetJsonDouble = FunctionBinaryStringOperateToNullType<GetJsonDouble>;
+using FunctionGetJsonInt = FunctionBinaryStringOperateToNullType<GetJsonInt>;
+using FunctionGetJsonBigInt = FunctionBinaryStringOperateToNullType<GetJsonBigInt>;
+using FunctionGetJsonString = FunctionBinaryStringOperateToNullType<GetJsonString>;
+
+class FunctionJsonValid : public IFunction {
+public:
+    static constexpr auto name = "json_valid";
+    static FunctionPtr create() { return std::make_shared<FunctionJsonValid>(); }
+
+    String get_name() const override { return name; }
+
+    size_t get_number_of_arguments() const override { return 1; }
+
+    DataTypePtr get_return_type_impl(const DataTypes& arguments) const override {

Review Comment:
   warning: function 'get_return_type_impl' should be marked [[nodiscard]] [modernize-use-nodiscard]
   
   ```suggestion
       [[nodiscard]] DataTypePtr get_return_type_impl(const DataTypes& arguments) const override {
   ```
   



-- 
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-unsubscribe@doris.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org