This is an automated email from the ASF dual-hosted git repository.

dataroaring pushed a commit to branch branch-3.0
in repository https://gitbox.apache.org/repos/asf/doris.git


The following commit(s) were added to refs/heads/branch-3.0 by this push:
     new d7cbe470ac9 [fix](json) incorrect results of json_contains (#53291) 
(#53364)
d7cbe470ac9 is described below

commit d7cbe470ac9c92c4cb4c96534b34d1f5ea585755
Author: Jerry Hu <[email protected]>
AuthorDate: Thu Jul 17 13:21:51 2025 +0800

    [fix](json) incorrect results of json_contains (#53291) (#53364)
    
    Fix the incorrect results and remove unused code.
    
    Pick: #53291
---
 be/src/util/jsonb_document.h                       |  12 +-
 be/src/vec/functions/function_json.cpp             | 132 ---------------------
 .../data/jsonb_p0/test_jsonb_load_and_function.out | Bin 188934 -> 188939 bytes
 .../test_jsonb_load_unique_key_and_function.out    | Bin 124394 -> 124396 bytes
 .../json_functions/test_json_function.out          | Bin 1476 -> 1644 bytes
 .../json_functions/test_json_function.groovy       |  19 +++
 6 files changed, 25 insertions(+), 138 deletions(-)

diff --git a/be/src/util/jsonb_document.h b/be/src/util/jsonb_document.h
index 7f50c4012ba..6d269f6dd52 100644
--- a/be/src/util/jsonb_document.h
+++ b/be/src/util/jsonb_document.h
@@ -1326,12 +1326,12 @@ inline bool JsonbValue::contains(JsonbValue* rhs) const 
{
     }
     case JsonbType::T_Object: {
         if (rhs->isObject()) {
-            auto* str_value1 = (ObjectVal*)this;
-            auto* str_value2 = (ObjectVal*)rhs;
-            for (int i = 0; i < str_value2->numElem(); ++i) {
-                JsonbKeyValue* key = str_value2->getJsonbKeyValue(i);
-                JsonbValue* value = str_value1->find(key->getKeyStr(), 
key->klen());
-                if (key != nullptr && value != nullptr && 
!value->contains(key->value())) {
+            const auto* obj_value1 = (ObjectVal*)this;
+            const auto* obj_value2 = (ObjectVal*)rhs;
+            for (int i = 0; i < obj_value2->numElem(); ++i) {
+                JsonbKeyValue* key = obj_value2->getJsonbKeyValue(i);
+                JsonbValue* value = obj_value1->find(key->getKeyStr(), 
key->klen());
+                if (value == nullptr || !value->contains(key->value())) {
                     return false;
                 }
             }
diff --git a/be/src/vec/functions/function_json.cpp 
b/be/src/vec/functions/function_json.cpp
index ab1ff616f2b..7ce4049249d 100644
--- a/be/src/vec/functions/function_json.cpp
+++ b/be/src/vec/functions/function_json.cpp
@@ -1105,137 +1105,6 @@ public:
     }
 };
 
-class FunctionJsonContains : public IFunction {
-public:
-    static constexpr auto name = "json_contains";
-    static FunctionPtr create() { return 
std::make_shared<FunctionJsonContains>(); }
-
-    String get_name() const override { return name; }
-
-    size_t get_number_of_arguments() const override { return 3; }
-
-    DataTypePtr get_return_type_impl(const DataTypes& arguments) const 
override {
-        return make_nullable(std::make_shared<DataTypeUInt8>());
-    }
-
-    DataTypes get_variadic_argument_types_impl() const override {
-        return {std::make_shared<DataTypeString>(), 
std::make_shared<DataTypeString>(),
-                std::make_shared<DataTypeString>()};
-    }
-
-    bool use_default_implementation_for_nulls() const override { return false; 
}
-
-    bool json_contains_object(const rapidjson::Value& target,
-                              const rapidjson::Value& search_value) const {
-        if (!target.IsObject() || !search_value.IsObject()) {
-            return false;
-        }
-
-        for (auto itr = search_value.MemberBegin(); itr != 
search_value.MemberEnd(); ++itr) {
-            if (!target.HasMember(itr->name) || 
!json_contains(target[itr->name], itr->value)) {
-                return false;
-            }
-        }
-
-        return true;
-    }
-
-    bool json_contains_array(const rapidjson::Value& target,
-                             const rapidjson::Value& search_value) const {
-        if (!target.IsArray() || !search_value.IsArray()) {
-            return false;
-        }
-
-        for (auto itr = search_value.Begin(); itr != search_value.End(); 
++itr) {
-            bool found = false;
-            for (auto target_itr = target.Begin(); target_itr != target.End(); 
++target_itr) {
-                if (json_contains(*target_itr, *itr)) {
-                    found = true;
-                    break;
-                }
-            }
-            if (!found) {
-                return false;
-            }
-        }
-
-        return true;
-    }
-
-    bool json_contains(const rapidjson::Value& target, const rapidjson::Value& 
search_value) const {
-        if (target == search_value) {
-            return true;
-        }
-
-        if (target.IsObject() && search_value.IsObject()) {
-            return json_contains_object(target, search_value);
-        }
-
-        if (target.IsArray() && search_value.IsArray()) {
-            return json_contains_array(target, search_value);
-        }
-
-        return false;
-    }
-
-    Status execute_impl(FunctionContext* context, Block& block, const 
ColumnNumbers& arguments,
-                        size_t result, size_t input_rows_count) const override 
{
-        const IColumn& col_json = 
*(block.get_by_position(arguments[0]).column);
-        const IColumn& col_search = 
*(block.get_by_position(arguments[1]).column);
-        const IColumn& col_path = 
*(block.get_by_position(arguments[2]).column);
-
-        auto null_map = ColumnUInt8::create(input_rows_count, 0);
-
-        const ColumnString* col_json_string = 
check_and_get_column<ColumnString>(col_json);
-        const ColumnString* col_search_string = 
check_and_get_column<ColumnString>(col_search);
-        const ColumnString* col_path_string = 
check_and_get_column<ColumnString>(col_path);
-
-        if (!col_json_string || !col_search_string || !col_path_string) {
-            return Status::RuntimeError("Illegal column should be 
ColumnString");
-        }
-
-        auto col_to = ColumnVector<vectorized::UInt8>::create();
-        auto& vec_to = col_to->get_data();
-        size_t size = col_json.size();
-        vec_to.resize(size);
-
-        for (size_t i = 0; i < input_rows_count; ++i) {
-            if (col_json.is_null_at(i) || col_search.is_null_at(i) || 
col_path.is_null_at(i)) {
-                null_map->get_data()[i] = 1;
-                vec_to[i] = 0;
-                continue;
-            }
-
-            const auto& json_val = col_json_string->get_data_at(i);
-            const auto& search_val = col_search_string->get_data_at(i);
-            const auto& path_val = col_path_string->get_data_at(i);
-
-            std::string_view json_string(json_val.data, json_val.size);
-            std::string_view search_string(search_val.data, search_val.size);
-            std::string_view path_string(path_val.data, path_val.size);
-
-            rapidjson::Document document;
-            auto target_val = get_json_object<JSON_FUN_STRING>(json_string, 
path_string, &document);
-            if (target_val == nullptr || target_val->IsNull()) {
-                vec_to[i] = 0;
-            } else {
-                rapidjson::Document search_doc;
-                search_doc.Parse(search_string.data(), search_string.size());
-                if (json_contains(*target_val, search_doc)) {
-                    vec_to[i] = 1;
-                } else {
-                    vec_to[i] = 0;
-                }
-            }
-        }
-
-        block.replace_by_position(result,
-                                  ColumnNullable::create(std::move(col_to), 
std::move(null_map)));
-
-        return Status::OK();
-    }
-};
-
 class FunctionJsonUnquote : public IFunction {
 public:
     static constexpr auto name = "json_unquote";
@@ -1658,7 +1527,6 @@ void register_function_json(SimpleFunctionFactory& 
factory) {
             
FunctionJsonNullable<FunctionJsonExtractImpl<JsonExtractNoQuotesName, true>>>();
 
     factory.register_function<FunctionJsonValid>();
-    factory.register_function<FunctionJsonContains>();
 
     factory.register_function<FunctionJsonModifyImpl<FunctionJsonInsert>>();
     factory.register_function<FunctionJsonModifyImpl<FunctionJsonReplace>>();
diff --git a/regression-test/data/jsonb_p0/test_jsonb_load_and_function.out 
b/regression-test/data/jsonb_p0/test_jsonb_load_and_function.out
index d7d7611931f..a27fa14581f 100644
Binary files a/regression-test/data/jsonb_p0/test_jsonb_load_and_function.out 
and b/regression-test/data/jsonb_p0/test_jsonb_load_and_function.out differ
diff --git 
a/regression-test/data/jsonb_p0/test_jsonb_load_unique_key_and_function.out 
b/regression-test/data/jsonb_p0/test_jsonb_load_unique_key_and_function.out
index 427b6426d68..36d14661668 100644
Binary files 
a/regression-test/data/jsonb_p0/test_jsonb_load_unique_key_and_function.out and 
b/regression-test/data/jsonb_p0/test_jsonb_load_unique_key_and_function.out 
differ
diff --git 
a/regression-test/data/query_p0/sql_functions/json_functions/test_json_function.out
 
b/regression-test/data/query_p0/sql_functions/json_functions/test_json_function.out
index c22acc17134..47da4ec2bbe 100644
Binary files 
a/regression-test/data/query_p0/sql_functions/json_functions/test_json_function.out
 and 
b/regression-test/data/query_p0/sql_functions/json_functions/test_json_function.out
 differ
diff --git 
a/regression-test/suites/query_p0/sql_functions/json_functions/test_json_function.groovy
 
b/regression-test/suites/query_p0/sql_functions/json_functions/test_json_function.groovy
index fe4dfc55315..517db385cc2 100644
--- 
a/regression-test/suites/query_p0/sql_functions/json_functions/test_json_function.groovy
+++ 
b/regression-test/suites/query_p0/sql_functions/json_functions/test_json_function.groovy
@@ -91,4 +91,23 @@ suite("test_json_function", "arrow_flight_sql") {
     qt_sql """select get_json_string('{"name\\k" : 123}', '\$.name\\k')"""
     qt_sql """select get_json_string('{"name\\k" : 123}', '\$.name\\\\k')"""
     qt_sql """select get_json_string('{"name\\k" : 123}', '\$.name\\\\\\k')"""
+
+    qt_json_contains1 """
+      SELECT JSON_CONTAINS('{"age": 30, "name": "John", "hobbies": ["reading", 
"swimming"]}', '{"invalid": "format"}');
+    """
+    qt_json_contains2 """
+      SELECT JSON_CONTAINS('{"age": 25, "name": "Alice", "hobbies": 
["painting", "music"]}', '{"age": 25}');
+    """
+    qt_json_contains3 """
+      SELECT JSON_CONTAINS('{"age": 25, "name": "Alice", "hobbies": 
["painting", "music"]}', '{"age": "25"}');
+    """
+    qt_json_contains4 """
+      SELECT JSON_CONTAINS('{"age": 25, "name": "Alice", "hobbies": 
["painting", "music"]}', '"music"', '\$.hobbies[1]');
+    """
+    qt_json_contains5 """
+      SELECT JSON_CONTAINS('{"age": 25, "name": "Alice", "hobbies": 
["painting", "music"]}', '"music"', '\$.hobbies[0]');
+    """
+    qt_json_contains6 """
+      SELECT JSON_CONTAINS(NULL, '"music"', '{"age": 25}');
+    """
 }


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to