mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03:00
MDEV-26182: Implement JSON_INTERSECT()
The idea is to have simple functions that the user can combine to produce the exact result one wants, whether the user wants JSON object that has common keys with another JSON object, or same key/value pair etc. So making simpler function helps here. We accomplish this by making three separate functions. 1) JSON_OBJECT_FILTER_KEYS(Obj, Arr_keys): Put keys ( which are basically strings ) in hash, go over the object and get key one by one. If the key is present in the hash, add the key-value pair to result. 2) JSON_OBJECT_TO_ARRAY(Obj) : Create a string variable, Go over the json object, and add each key value pair as an array into the result. 3) JSON_ARRAY_INTERSECT(arr1, arr2) : Go over one of the json and add each item of the array in hash (after normalizing each item). Go over the second array, search the normalized item one by one in the hash. If item is found, add it to the result. Implementation Idea: Holyfoot ( Alexey Botchkov) Author: tanruixiang and Rucha Deodhar
This commit is contained in:
committed by
Rucha Deodhar
parent
15a7b6c0b7
commit
49088c914b
@ -4947,3 +4947,180 @@ JSON_KEY_VALUE('{"key1":{"a":1, "b": [1,2,3, {"some_key":"some_val", "c":3}]}, "
|
||||
COLUMNS (k VARCHAR(20) PATH '$.key', v VARCHAR(20) PATH '$.value', id FOR ORDINALITY)) AS jt;
|
||||
k v id
|
||||
# End of 11.2 test
|
||||
#
|
||||
# Beginning of 11.2 tests
|
||||
#
|
||||
# MDEV-26182: Implement json_array_intersect()
|
||||
#
|
||||
# JSON_ARRAY_INTERSECT()
|
||||
# Scalar as elements
|
||||
SET @json1= '[1,2,3]';
|
||||
SET @json2= '[1,2,3]';
|
||||
SELECT json_array_intersect(@json1, @json2);
|
||||
json_array_intersect(@json1, @json2)
|
||||
[1, 2, 3]
|
||||
SET @json1= '[1,2,3]';
|
||||
SET @json2= '[1,2,4]';
|
||||
SELECT json_array_intersect(@json1, @json2);
|
||||
json_array_intersect(@json1, @json2)
|
||||
[1, 2]
|
||||
SET @json1= '["abc","def","ghi"]';
|
||||
SET @json2= '["xyz", "abc", "tuv"]';
|
||||
SELECT json_array_intersect(@json1, @json2);
|
||||
json_array_intersect(@json1, @json2)
|
||||
["abc"]
|
||||
SET @obj1= '[true]';
|
||||
SET @obj2= '[false, "true"]';
|
||||
select json_array_intersect(@obj1, @obj2);
|
||||
json_array_intersect(@obj1, @obj2)
|
||||
NULL
|
||||
SET @obj1= '[true]';
|
||||
SET @obj2= '[false, true]';
|
||||
select json_array_intersect(@obj1, @obj2);
|
||||
json_array_intersect(@obj1, @obj2)
|
||||
[true]
|
||||
SET @obj1= '[null, true]';
|
||||
SET @obj2= '[false, null]';
|
||||
select json_array_intersect(@obj1, @obj2);
|
||||
json_array_intersect(@obj1, @obj2)
|
||||
[null]
|
||||
# array as elements
|
||||
SET @json1= '[6,6,6]';
|
||||
SET @json2= '[[1,2,3],[4,5,6],[1,3,2]]';
|
||||
SELECT json_array_intersect(@json1, @json2);
|
||||
json_array_intersect(@json1, @json2)
|
||||
NULL
|
||||
SET @json1= '[[1,2,3],[4,5,6],[1,3,2]]';
|
||||
SET @json2= '[[1,2,3],[4,5,6],[1,3,2]]';
|
||||
SELECT json_array_intersect(@json1, @json2);
|
||||
json_array_intersect(@json1, @json2)
|
||||
[[1, 2, 3], [4, 5, 6], [1, 3, 2]]
|
||||
SET @json1= '[[1,2,3],[4,5,6],[1,3,2]]';
|
||||
SET @json2= '[[1,2,3],[4,5,6],[1,4,2]]';
|
||||
SELECT json_array_intersect(@json1, @json2);
|
||||
json_array_intersect(@json1, @json2)
|
||||
[[1, 2, 3], [4, 5, 6]]
|
||||
# object as elements
|
||||
SET @json1 = '[{"k1":"v1","k2":"v2"},{"k2":"v2"}]';
|
||||
SET @json2 = '[{"kkey1":"vvalue1"},{"k2":"v2","k1":"v1"}]';
|
||||
SELECT json_array_intersect(@json1, @json2);
|
||||
json_array_intersect(@json1, @json2)
|
||||
[{"k2": "v2", "k1": "v1"}]
|
||||
SET @json1 = '[{"k1":"v1","k2":"v2"},{"k2":"v2","k1":"v1"}]';
|
||||
SET @json2 = '[{"k1":"v1","k2":"v2"},{"k1":"v1","k2":"v2"}]';
|
||||
SELECT json_array_intersect(@json1, @json2);
|
||||
json_array_intersect(@json1, @json2)
|
||||
[{"k1": "v1", "k2": "v2"}, {"k1": "v1", "k2": "v2"}]
|
||||
# multi type elements
|
||||
SET @obj1= '[1,2,3, "abc", "xyz", {"key1":"val1"}, {"key2":"val2"}, [1,2,3]]';
|
||||
SET @obj2= '[3.0, 4, 5, "abc", {"key1":"val1"}, [3,2,1]]';
|
||||
select json_array_intersect(@obj1, @obj2);
|
||||
json_array_intersect(@obj1, @obj2)
|
||||
[3.0, "abc", {"key1": "val1"}]
|
||||
SET @obj1= '[1, 2, 3, "abc", "xyz", {"key1": {"key2" : [1,2,3] } }, [4,5,6] ]';
|
||||
SET @obj2= '[3.0, 4, 5, "abc", {"key1": {"key2" : [3,2,1]} }, {"key1": {"key2" : [1,2,3] } }, [4,5,6], [6,5,4] ]';
|
||||
select json_array_intersect(@obj1, @obj2);
|
||||
json_array_intersect(@obj1, @obj2)
|
||||
[3.0, "abc", {"key1": {"key2": [1, 2, 3]}}, [4, 5, 6]]
|
||||
# Checking duplicates
|
||||
SET @obj1= '[1, 2, 3, 3, 3.0, "abc", true, true, {"key1":"val1"}]';
|
||||
SET @obj2= '[3.0, 3, 5, "abc", "abc", true, {"key2":"val2"}, {"key1":"val1"}, {"key1":"val2"}]';
|
||||
select json_array_intersect(@obj1, @obj2);
|
||||
json_array_intersect(@obj1, @obj2)
|
||||
[3.0, 3, "abc", true, {"key1": "val1"}]
|
||||
# Checking Syntax error for JSON_ARRAY_INTERSECT()
|
||||
SET @obj1= '[1, 2, 3, 3, 3.0, "abc", true, true, {"key1":"val1" ]';
|
||||
SET @obj2= '[3.0, 3, 5, "abc", "abc", true, {"key2":"val2"}, {"key1":"val1"}, {"key1":"val2"}]';
|
||||
select json_array_intersect(@obj1, @obj2);
|
||||
json_array_intersect(@obj1, @obj2)
|
||||
NULL
|
||||
Warnings:
|
||||
Warning 4038 Syntax error in JSON text in argument 1 to function 'json_array_intersect' at position 53
|
||||
# Checking incorrect type for input
|
||||
SET @obj1= '{"key1": "val1"}';
|
||||
SET @arr1= '[ 1, 2, 3 ]';
|
||||
SET @num1= '2';
|
||||
SET @str1= '"abc"';
|
||||
SET @bool1= 'true';
|
||||
select json_array_intersect(@obj1, @arr1);
|
||||
json_array_intersect(@obj1, @arr1)
|
||||
NULL
|
||||
select json_array_intersect(@arr1, @obj1);
|
||||
json_array_intersect(@arr1, @obj1)
|
||||
NULL
|
||||
select json_array_intersect(@arr1, @num1);
|
||||
json_array_intersect(@arr1, @num1)
|
||||
NULL
|
||||
select json_array_intersect(@num1, @bool1);
|
||||
json_array_intersect(@num1, @bool1)
|
||||
NULL
|
||||
# JSON_OBJECT_FILTER_KEYS()
|
||||
SET @obj1= '{ "a": 1, "b": 2, "c": 3}';
|
||||
SET @obj2= '{"b" : 10, "c": 20, "d": 30}';
|
||||
SELECT JSON_OBJECT_FILTER_KEYS (@obj1, json_array_intersect(json_keys(@obj1), json_keys(@obj2)));
|
||||
JSON_OBJECT_FILTER_KEYS (@obj1, json_array_intersect(json_keys(@obj1), json_keys(@obj2)))
|
||||
{"b": 2, "c": 3}
|
||||
SET @obj1= '{ "a": 1, "b": {"key1": {"key2":"val2"}}, "c": [1, 2, 3] }';
|
||||
SET @obj2= '{"b" : 10, "c": 20, "d": 30}';
|
||||
SELECT JSON_OBJECT_FILTER_KEYS (@obj1, json_array_intersect(json_keys(@obj1), json_keys(@obj2)));
|
||||
JSON_OBJECT_FILTER_KEYS (@obj1, json_array_intersect(json_keys(@obj1), json_keys(@obj2)))
|
||||
{"b": {"key1": {"key2": "val2"}}, "c": [1, 2, 3]}
|
||||
SET @obj1= '{ "a": 1, "b": {"key1": {"key2":"val2"}}, "c": [1, 2, 3] }';
|
||||
SET @arr2='["x", "y", "z"]';
|
||||
SELECT JSON_OBJECT_FILTER_KEYS(@obj1, @arr2);
|
||||
JSON_OBJECT_FILTER_KEYS(@obj1, @arr2)
|
||||
NULL
|
||||
SET @obj1= '{ "a": 1, "b": {"key1": {"key2":"val2"}}, "c": [1, 2, 3] }';
|
||||
SET @arr2='["key2", "key1", "b"]';
|
||||
SELECT JSON_OBJECT_FILTER_KEYS(@obj1, @arr1);
|
||||
JSON_OBJECT_FILTER_KEYS(@obj1, @arr1)
|
||||
NULL
|
||||
# Incorrect type in input returns NULL
|
||||
SELECT JSON_OBJECT_FILTER_KEYS(@obj1, @obj1);
|
||||
JSON_OBJECT_FILTER_KEYS(@obj1, @obj1)
|
||||
NULL
|
||||
SELECT JSON_OBJECT_FILTER_KEYS(@arr1, @arr1);
|
||||
JSON_OBJECT_FILTER_KEYS(@arr1, @arr1)
|
||||
NULL
|
||||
SET @obj1= '{ "a": 1, "b": {"key1": {"key2":"val2"}}, "c": [1, 2, 3] }';
|
||||
SET @scalar1='2';
|
||||
SELECT JSON_OBJECT_FILTER_KEYS(@obj1, @scalar1);
|
||||
JSON_OBJECT_FILTER_KEYS(@obj1, @scalar1)
|
||||
NULL
|
||||
# Checking syntax error
|
||||
SET @obj1= '{ "a": 1, "b": 2, "c": 3}';
|
||||
SET @obj2= '{"b" : 10, "c": 20, "d" 30}';
|
||||
SELECT JSON_OBJECT_FILTER_KEYS (@obj1, json_array_intersect(json_keys(@obj1), json_keys(@obj2)));
|
||||
JSON_OBJECT_FILTER_KEYS (@obj1, json_array_intersect(json_keys(@obj1), json_keys(@obj2)))
|
||||
NULL
|
||||
Warnings:
|
||||
Warning 4038 Syntax error in JSON text in argument 1 to function 'json_keys' at position 25
|
||||
SET @obj1= '{ "a": 1, "b": {"key1": {"key2":"val2"}}, "c": [1, 2, 3] }';
|
||||
SET @arr2= '[ "key2", "key1", "b" ';
|
||||
SELECT JSON_OBJECT_FILTER_KEYS(@obj1, @arr1);
|
||||
JSON_OBJECT_FILTER_KEYS(@obj1, @arr1)
|
||||
NULL
|
||||
# JSON_OBJECT_TO_ARRAY()
|
||||
SET @obj1= '{ "a": [1, 2, 3], "b": { "key1":"val1", "key2": {"key3":"val3"} }, "c": 3, "d" : 1, "e": "xyz", "f": true, "g" : null}';
|
||||
SELECT JSON_OBJECT_TO_ARRAY(@obj1);
|
||||
JSON_OBJECT_TO_ARRAY(@obj1)
|
||||
[["a", [1, 2, 3]], ["b", {"key1": "val1", "key2": {"key3": "val3"}}], ["c", 3], ["d", 1], ["e", "xyz"], ["f", true], ["g", null]]
|
||||
SET @obj1= '{ "a": [1, 2, 3], "b": { "key1":"val1", "key2": [1, 2, 3] }, "c": 3, "d" : 1, "e": "xyz", "f": true, "g" : null}';
|
||||
SELECT JSON_OBJECT_TO_ARRAY(@obj1);
|
||||
JSON_OBJECT_TO_ARRAY(@obj1)
|
||||
[["a", [1, 2, 3]], ["b", {"key1": "val1", "key2": [1, 2, 3]}], ["c", 3], ["d", 1], ["e", "xyz"], ["f", true], ["g", null]]
|
||||
# Checking syntax error
|
||||
SET @obj1= '{ "a": [1, 2, 3], "b": "key1": "val1", "key2": {"key3":"val3"} }, "c": 3, "d" : 1, "e": "xyz", "f": true, "g" : null}';
|
||||
SELECT JSON_OBJECT_TO_ARRAY(@obj1);
|
||||
JSON_OBJECT_TO_ARRAY(@obj1)
|
||||
NULL
|
||||
Warnings:
|
||||
Warning 4038 Syntax error in JSON text in argument 1 to function 'json_object_to_array' at position 30
|
||||
Checking incorrect type in argument
|
||||
SET @arr1= '[1, 2, 3]';
|
||||
SELECT JSON_OBJECT_TO_ARRAY(@arr1);
|
||||
JSON_OBJECT_TO_ARRAY(@arr1)
|
||||
NULL
|
||||
#
|
||||
# End of 11.2 Test
|
||||
#
|
||||
|
@ -3783,3 +3783,162 @@ FROM JSON_TABLE(
|
||||
COLUMNS (k VARCHAR(20) PATH '$.key', v VARCHAR(20) PATH '$.value', id FOR ORDINALITY)) AS jt;
|
||||
|
||||
--echo # End of 11.2 test
|
||||
|
||||
--echo #
|
||||
--echo # Beginning of 11.2 tests
|
||||
--echo #
|
||||
--echo # MDEV-26182: Implement json_array_intersect()
|
||||
--echo #
|
||||
|
||||
|
||||
|
||||
--echo # JSON_ARRAY_INTERSECT()
|
||||
|
||||
--echo # Scalar as elements
|
||||
|
||||
SET @json1= '[1,2,3]';
|
||||
SET @json2= '[1,2,3]';
|
||||
SELECT json_array_intersect(@json1, @json2);
|
||||
|
||||
SET @json1= '[1,2,3]';
|
||||
SET @json2= '[1,2,4]';
|
||||
SELECT json_array_intersect(@json1, @json2);
|
||||
|
||||
SET @json1= '["abc","def","ghi"]';
|
||||
SET @json2= '["xyz", "abc", "tuv"]';
|
||||
SELECT json_array_intersect(@json1, @json2);
|
||||
|
||||
SET @obj1= '[true]';
|
||||
SET @obj2= '[false, "true"]';
|
||||
select json_array_intersect(@obj1, @obj2);
|
||||
|
||||
SET @obj1= '[true]';
|
||||
SET @obj2= '[false, true]';
|
||||
select json_array_intersect(@obj1, @obj2);
|
||||
|
||||
SET @obj1= '[null, true]';
|
||||
SET @obj2= '[false, null]';
|
||||
select json_array_intersect(@obj1, @obj2);
|
||||
|
||||
|
||||
--echo # array as elements
|
||||
|
||||
SET @json1= '[6,6,6]';
|
||||
SET @json2= '[[1,2,3],[4,5,6],[1,3,2]]';
|
||||
SELECT json_array_intersect(@json1, @json2);
|
||||
|
||||
SET @json1= '[[1,2,3],[4,5,6],[1,3,2]]';
|
||||
SET @json2= '[[1,2,3],[4,5,6],[1,3,2]]';
|
||||
SELECT json_array_intersect(@json1, @json2);
|
||||
|
||||
SET @json1= '[[1,2,3],[4,5,6],[1,3,2]]';
|
||||
SET @json2= '[[1,2,3],[4,5,6],[1,4,2]]';
|
||||
SELECT json_array_intersect(@json1, @json2);
|
||||
|
||||
--echo # object as elements
|
||||
|
||||
SET @json1 = '[{"k1":"v1","k2":"v2"},{"k2":"v2"}]';
|
||||
SET @json2 = '[{"kkey1":"vvalue1"},{"k2":"v2","k1":"v1"}]';
|
||||
SELECT json_array_intersect(@json1, @json2);
|
||||
|
||||
SET @json1 = '[{"k1":"v1","k2":"v2"},{"k2":"v2","k1":"v1"}]';
|
||||
SET @json2 = '[{"k1":"v1","k2":"v2"},{"k1":"v1","k2":"v2"}]';
|
||||
SELECT json_array_intersect(@json1, @json2);
|
||||
|
||||
--echo # multi type elements
|
||||
|
||||
SET @obj1= '[1,2,3, "abc", "xyz", {"key1":"val1"}, {"key2":"val2"}, [1,2,3]]';
|
||||
SET @obj2= '[3.0, 4, 5, "abc", {"key1":"val1"}, [3,2,1]]';
|
||||
select json_array_intersect(@obj1, @obj2);
|
||||
|
||||
SET @obj1= '[1, 2, 3, "abc", "xyz", {"key1": {"key2" : [1,2,3] } }, [4,5,6] ]';
|
||||
SET @obj2= '[3.0, 4, 5, "abc", {"key1": {"key2" : [3,2,1]} }, {"key1": {"key2" : [1,2,3] } }, [4,5,6], [6,5,4] ]';
|
||||
select json_array_intersect(@obj1, @obj2);
|
||||
|
||||
--echo # Checking duplicates
|
||||
|
||||
SET @obj1= '[1, 2, 3, 3, 3.0, "abc", true, true, {"key1":"val1"}]';
|
||||
SET @obj2= '[3.0, 3, 5, "abc", "abc", true, {"key2":"val2"}, {"key1":"val1"}, {"key1":"val2"}]';
|
||||
select json_array_intersect(@obj1, @obj2);
|
||||
|
||||
|
||||
--echo # Checking Syntax error for JSON_ARRAY_INTERSECT()
|
||||
SET @obj1= '[1, 2, 3, 3, 3.0, "abc", true, true, {"key1":"val1" ]';
|
||||
SET @obj2= '[3.0, 3, 5, "abc", "abc", true, {"key2":"val2"}, {"key1":"val1"}, {"key1":"val2"}]';
|
||||
select json_array_intersect(@obj1, @obj2);
|
||||
|
||||
--echo # Checking incorrect type for input
|
||||
SET @obj1= '{"key1": "val1"}';
|
||||
SET @arr1= '[ 1, 2, 3 ]';
|
||||
SET @num1= '2';
|
||||
SET @str1= '"abc"';
|
||||
SET @bool1= 'true';
|
||||
select json_array_intersect(@obj1, @arr1);
|
||||
select json_array_intersect(@arr1, @obj1);
|
||||
select json_array_intersect(@arr1, @num1);
|
||||
select json_array_intersect(@num1, @bool1);
|
||||
|
||||
|
||||
|
||||
--echo # JSON_OBJECT_FILTER_KEYS()
|
||||
|
||||
SET @obj1= '{ "a": 1, "b": 2, "c": 3}';
|
||||
SET @obj2= '{"b" : 10, "c": 20, "d": 30}';
|
||||
SELECT JSON_OBJECT_FILTER_KEYS (@obj1, json_array_intersect(json_keys(@obj1), json_keys(@obj2)));
|
||||
|
||||
SET @obj1= '{ "a": 1, "b": {"key1": {"key2":"val2"}}, "c": [1, 2, 3] }';
|
||||
SET @obj2= '{"b" : 10, "c": 20, "d": 30}';
|
||||
SELECT JSON_OBJECT_FILTER_KEYS (@obj1, json_array_intersect(json_keys(@obj1), json_keys(@obj2)));
|
||||
|
||||
|
||||
SET @obj1= '{ "a": 1, "b": {"key1": {"key2":"val2"}}, "c": [1, 2, 3] }';
|
||||
SET @arr2='["x", "y", "z"]';
|
||||
SELECT JSON_OBJECT_FILTER_KEYS(@obj1, @arr2);
|
||||
|
||||
|
||||
SET @obj1= '{ "a": 1, "b": {"key1": {"key2":"val2"}}, "c": [1, 2, 3] }';
|
||||
SET @arr2='["key2", "key1", "b"]';
|
||||
SELECT JSON_OBJECT_FILTER_KEYS(@obj1, @arr1);
|
||||
|
||||
--echo # Incorrect type in input returns NULL
|
||||
|
||||
SELECT JSON_OBJECT_FILTER_KEYS(@obj1, @obj1);
|
||||
SELECT JSON_OBJECT_FILTER_KEYS(@arr1, @arr1);
|
||||
|
||||
SET @obj1= '{ "a": 1, "b": {"key1": {"key2":"val2"}}, "c": [1, 2, 3] }';
|
||||
SET @scalar1='2';
|
||||
SELECT JSON_OBJECT_FILTER_KEYS(@obj1, @scalar1);
|
||||
|
||||
--echo # Checking syntax error
|
||||
|
||||
SET @obj1= '{ "a": 1, "b": 2, "c": 3}';
|
||||
SET @obj2= '{"b" : 10, "c": 20, "d" 30}';
|
||||
SELECT JSON_OBJECT_FILTER_KEYS (@obj1, json_array_intersect(json_keys(@obj1), json_keys(@obj2)));
|
||||
|
||||
SET @obj1= '{ "a": 1, "b": {"key1": {"key2":"val2"}}, "c": [1, 2, 3] }';
|
||||
SET @arr2= '[ "key2", "key1", "b" ';
|
||||
SELECT JSON_OBJECT_FILTER_KEYS(@obj1, @arr1);
|
||||
|
||||
|
||||
|
||||
--echo # JSON_OBJECT_TO_ARRAY()
|
||||
|
||||
SET @obj1= '{ "a": [1, 2, 3], "b": { "key1":"val1", "key2": {"key3":"val3"} }, "c": 3, "d" : 1, "e": "xyz", "f": true, "g" : null}';
|
||||
SELECT JSON_OBJECT_TO_ARRAY(@obj1);
|
||||
|
||||
SET @obj1= '{ "a": [1, 2, 3], "b": { "key1":"val1", "key2": [1, 2, 3] }, "c": 3, "d" : 1, "e": "xyz", "f": true, "g" : null}';
|
||||
SELECT JSON_OBJECT_TO_ARRAY(@obj1);
|
||||
|
||||
--echo # Checking syntax error
|
||||
|
||||
SET @obj1= '{ "a": [1, 2, 3], "b": "key1": "val1", "key2": {"key3":"val3"} }, "c": 3, "d" : 1, "e": "xyz", "f": true, "g" : null}';
|
||||
SELECT JSON_OBJECT_TO_ARRAY(@obj1);
|
||||
|
||||
--echo Checking incorrect type in argument
|
||||
|
||||
SET @arr1= '[1, 2, 3]';
|
||||
SELECT JSON_OBJECT_TO_ARRAY(@arr1);
|
||||
|
||||
--echo #
|
||||
--echo # End of 11.2 Test
|
||||
--echo #
|
||||
|
@ -958,6 +958,17 @@ protected:
|
||||
virtual ~Create_func_json_normalize() = default;
|
||||
};
|
||||
|
||||
class Create_func_json_object_to_array : public Create_func_arg1
|
||||
{
|
||||
public:
|
||||
virtual Item *create_1_arg(THD *thd, Item *arg1);
|
||||
|
||||
static Create_func_json_object_to_array s_singleton;
|
||||
|
||||
protected:
|
||||
Create_func_json_object_to_array() {}
|
||||
virtual ~Create_func_json_object_to_array() {}
|
||||
};
|
||||
|
||||
class Create_func_json_equals : public Create_func_arg2
|
||||
{
|
||||
@ -1377,6 +1388,32 @@ protected:
|
||||
};
|
||||
|
||||
|
||||
class Create_func_json_array_intersect : public Create_func_arg2
|
||||
{
|
||||
public:
|
||||
virtual Item *create_2_arg(THD *thd, Item *arg1, Item *arg2);
|
||||
|
||||
static Create_func_json_array_intersect s_singleton;
|
||||
|
||||
protected:
|
||||
Create_func_json_array_intersect() {}
|
||||
virtual ~Create_func_json_array_intersect() {}
|
||||
};
|
||||
|
||||
|
||||
class Create_func_json_object_filter_keys : public Create_func_arg2
|
||||
{
|
||||
public:
|
||||
virtual Item *create_2_arg(THD *thd, Item *arg1, Item *arg2);
|
||||
|
||||
static Create_func_json_object_filter_keys s_singleton;
|
||||
|
||||
protected:
|
||||
Create_func_json_object_filter_keys() {}
|
||||
virtual ~Create_func_json_object_filter_keys() {}
|
||||
};
|
||||
|
||||
|
||||
class Create_func_last_day : public Create_func_arg1
|
||||
{
|
||||
public:
|
||||
@ -3818,6 +3855,15 @@ Create_func_json_normalize::create_1_arg(THD *thd, Item *arg1)
|
||||
return new (thd->mem_root) Item_func_json_normalize(thd, arg1);
|
||||
}
|
||||
|
||||
Create_func_json_object_to_array Create_func_json_object_to_array::s_singleton;
|
||||
|
||||
Item*
|
||||
Create_func_json_object_to_array::create_1_arg(THD *thd, Item *arg1)
|
||||
{
|
||||
status_var_increment(thd->status_var.feature_json);
|
||||
return new (thd->mem_root) Item_func_json_object_to_array(thd, arg1);
|
||||
}
|
||||
|
||||
|
||||
Create_func_json_equals Create_func_json_equals::s_singleton;
|
||||
|
||||
@ -4204,6 +4250,27 @@ Create_func_json_length::create_native(THD *thd, const LEX_CSTRING *name,
|
||||
return func;
|
||||
}
|
||||
|
||||
Create_func_json_array_intersect Create_func_json_array_intersect::s_singleton;
|
||||
Item*
|
||||
Create_func_json_array_intersect::create_2_arg(THD *thd, Item *arg1, Item *arg2)
|
||||
{
|
||||
if (unlikely( ( !arg1 || !arg2 ) )) // json, json
|
||||
{
|
||||
my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0));
|
||||
}
|
||||
status_var_increment(thd->status_var.feature_json);
|
||||
return new (thd->mem_root) Item_func_json_array_intersect(thd, arg1, arg2);
|
||||
}
|
||||
|
||||
Create_func_json_object_filter_keys Create_func_json_object_filter_keys::s_singleton;
|
||||
|
||||
Item*
|
||||
Create_func_json_object_filter_keys::create_2_arg(THD *thd, Item *arg1, Item *arg2)
|
||||
{
|
||||
status_var_increment(thd->status_var.feature_json);
|
||||
return new (thd->mem_root) Item_func_json_object_filter_keys(thd, arg1, arg2);
|
||||
}
|
||||
|
||||
|
||||
Create_func_json_merge Create_func_json_merge::s_singleton;
|
||||
|
||||
@ -5822,6 +5889,7 @@ Native_func_registry func_array[] =
|
||||
{ { STRING_WITH_LEN("JSON_ARRAY") }, BUILDER(Create_func_json_array)},
|
||||
{ { STRING_WITH_LEN("JSON_ARRAY_APPEND") }, BUILDER(Create_func_json_array_append)},
|
||||
{ { STRING_WITH_LEN("JSON_ARRAY_INSERT") }, BUILDER(Create_func_json_array_insert)},
|
||||
{ { STRING_WITH_LEN("JSON_ARRAY_INTERSECT") }, BUILDER(Create_func_json_array_intersect)},
|
||||
{ { STRING_WITH_LEN("JSON_COMPACT") }, BUILDER(Create_func_json_compact)},
|
||||
{ { STRING_WITH_LEN("JSON_CONTAINS") }, BUILDER(Create_func_json_contains)},
|
||||
{ { STRING_WITH_LEN("JSON_CONTAINS_PATH") }, BUILDER(Create_func_json_contains_path)},
|
||||
@ -5843,6 +5911,8 @@ Native_func_registry func_array[] =
|
||||
{ { STRING_WITH_LEN("JSON_QUERY") }, BUILDER(Create_func_json_query)},
|
||||
{ { STRING_WITH_LEN("JSON_QUOTE") }, BUILDER(Create_func_json_quote)},
|
||||
{ { STRING_WITH_LEN("JSON_OBJECT") }, BUILDER(Create_func_json_object)},
|
||||
{ { STRING_WITH_LEN("JSON_OBJECT_FILTER_KEYS") }, BUILDER(Create_func_json_object_filter_keys)},
|
||||
{ { STRING_WITH_LEN("JSON_OBJECT_TO_ARRAY") }, BUILDER(Create_func_json_object_to_array)},
|
||||
{ { STRING_WITH_LEN("JSON_OVERLAPS") }, BUILDER(Create_func_json_overlaps)},
|
||||
{ { STRING_WITH_LEN("JSON_REMOVE") }, BUILDER(Create_func_json_remove)},
|
||||
{ { STRING_WITH_LEN("JSON_REPLACE") }, BUILDER(Create_func_json_replace)},
|
||||
|
@ -4982,3 +4982,515 @@ bool Item_func_json_key_value::fix_length_and_dec(THD *thd)
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
bool create_hash(json_engine_t *value, HASH *items, bool &hash_inited,
|
||||
MEM_ROOT *hash_root)
|
||||
{
|
||||
int level= value->stack_p;
|
||||
if (my_hash_init(PSI_INSTRUMENT_ME, items, value->s.cs, 0, 0, 0,
|
||||
(my_hash_get_key) get_key_name, NULL, 0))
|
||||
return true;
|
||||
hash_inited= true;
|
||||
|
||||
while (json_scan_next(value) == 0 && value->stack_p >= level)
|
||||
{
|
||||
const uchar *value_start= NULL;
|
||||
size_t value_len= 0;
|
||||
DYNAMIC_STRING norm_val;
|
||||
|
||||
if (json_read_value(value) ||
|
||||
get_current_value(value, value_start, value_len) ||
|
||||
init_dynamic_string(&norm_val, NULL, 0, 0))
|
||||
return true;
|
||||
|
||||
if (json_normalize(&norm_val, (const char*) value_start,
|
||||
value_len, value->s.cs))
|
||||
{
|
||||
dynstr_free(&norm_val);
|
||||
return true;
|
||||
}
|
||||
|
||||
char *new_entry= (char*)alloc_root(hash_root,
|
||||
norm_val.length+1);
|
||||
if (!new_entry)
|
||||
{
|
||||
dynstr_free(&norm_val);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
strncpy(new_entry, norm_val.str, norm_val.length);
|
||||
new_entry[norm_val.length]='\0';
|
||||
|
||||
dynstr_free(&norm_val);
|
||||
|
||||
if (my_hash_insert(items, (const uchar *) new_entry))
|
||||
{
|
||||
my_free(new_entry);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Get the starting pointer and length of the value of the current layer.
|
||||
RETURN
|
||||
FALSE - The function was successfully completed without errors.
|
||||
TRUE - An error occurred while running.
|
||||
*/
|
||||
bool get_current_value(json_engine_t *js, const uchar *&value_start,
|
||||
size_t &value_len)
|
||||
{
|
||||
value_start= js->value_begin;
|
||||
|
||||
if (json_value_scalar(js))
|
||||
{
|
||||
value_len= js->value_end - value_start;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (json_skip_level(js))
|
||||
return true;
|
||||
value_len= js->s.c_str - value_start;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
If the outermost layer of JSON is an array,
|
||||
the intersection of arrays is independent of order.
|
||||
Create a hash containing all elements in the array,
|
||||
itterate over another array and add the common elements
|
||||
to the result.
|
||||
|
||||
RETURN
|
||||
FALSE - if two array documents have intersection
|
||||
TRUE - If two array documents do not have intersection
|
||||
*/
|
||||
bool get_intersect_between_arrays(String *str, json_engine_t *value,
|
||||
HASH items)
|
||||
{
|
||||
bool res= true, has_value= false;
|
||||
int level= value->stack_p;
|
||||
String temp_str(0);
|
||||
|
||||
temp_str.append('[');
|
||||
while (json_scan_next(value) == 0 && value->stack_p >= level)
|
||||
{
|
||||
const uchar *value_start= NULL;
|
||||
size_t value_len= 0;
|
||||
DYNAMIC_STRING norm_val;
|
||||
|
||||
if (json_read_value(value) ||
|
||||
get_current_value(value, value_start, value_len) ||
|
||||
init_dynamic_string(&norm_val, NULL, 0, 0))
|
||||
goto error;
|
||||
|
||||
if (json_normalize(&norm_val, (const char*) value_start,
|
||||
value_len, value->s.cs))
|
||||
{
|
||||
dynstr_free(&norm_val);
|
||||
goto error;
|
||||
}
|
||||
|
||||
char *new_entry= (char*)malloc(norm_val.length+1);
|
||||
if (!new_entry)
|
||||
{
|
||||
dynstr_free(&norm_val);
|
||||
goto error;
|
||||
}
|
||||
strncpy(new_entry, norm_val.str, norm_val.length);
|
||||
new_entry[norm_val.length]='\0';
|
||||
|
||||
dynstr_free(&norm_val);
|
||||
|
||||
/*
|
||||
If the same value is found in the hash table, add
|
||||
that value to str. At the same time, update the number
|
||||
of times the value appears in the hash table.
|
||||
*/
|
||||
uchar * found= NULL;
|
||||
if ((found= my_hash_search(&items,
|
||||
(const uchar *) new_entry,
|
||||
strlen(new_entry))))
|
||||
{
|
||||
has_value= true;
|
||||
temp_str.append( (const char*) value_start, value_len);
|
||||
temp_str.append(',');
|
||||
if (my_hash_delete(&items, found))
|
||||
{
|
||||
free(new_entry);
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
free(new_entry);
|
||||
}
|
||||
|
||||
res= false;
|
||||
|
||||
if (has_value)
|
||||
{
|
||||
temp_str.chop(); /* remove last comma because there are no values after that. */
|
||||
temp_str.append(']');
|
||||
str->append(temp_str.ptr(), temp_str.length());
|
||||
}
|
||||
|
||||
error:
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
String* Item_func_json_array_intersect::val_str(String *str)
|
||||
{
|
||||
DBUG_ASSERT(fixed());
|
||||
|
||||
json_engine_t je2, res_je;
|
||||
String *js2= args[1]->val_json(&tmp_js2);
|
||||
|
||||
if (null_value || args[1]->null_value)
|
||||
goto null_return;
|
||||
|
||||
str->set_charset(js2->charset());
|
||||
str->length(0);
|
||||
|
||||
json_scan_start(&je2, js2->charset(), (const uchar *) js2->ptr(),
|
||||
(const uchar *) js2->ptr() + js2->length());
|
||||
|
||||
if (json_read_value(&je2) || je2.value_type != JSON_VALUE_ARRAY)
|
||||
goto error_return;
|
||||
|
||||
if (get_intersect_between_arrays(str, &je2, items))
|
||||
goto error_return;
|
||||
|
||||
if (str->length())
|
||||
{
|
||||
json_scan_start(&res_je, str->charset(), (const uchar *) str->ptr(),
|
||||
(const uchar *) str->ptr() + str->length());
|
||||
str= &tmp_js1;
|
||||
if (json_nice(&res_je, str, Item_func_json_format::LOOSE))
|
||||
goto error_return;
|
||||
|
||||
null_value= 0;
|
||||
return str;
|
||||
}
|
||||
else
|
||||
{
|
||||
goto null_return;
|
||||
}
|
||||
|
||||
error_return:
|
||||
if (je2.s.error)
|
||||
report_json_error(js2, &je2, 1);
|
||||
null_return:
|
||||
null_value= 1;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool Item_func_json_array_intersect::fix_length_and_dec(THD *thd)
|
||||
{
|
||||
json_engine_t je1;
|
||||
String *js1= args[0]->val_json(&tmp_js1);
|
||||
|
||||
if (args[0]->null_value)
|
||||
{
|
||||
null_value= true;
|
||||
return FALSE;
|
||||
}
|
||||
json_scan_start(&je1, js1->charset(), (const uchar *) js1->ptr(),
|
||||
(const uchar *) js1->ptr() + js1->length());
|
||||
/*
|
||||
Scan value uses the hash table to get the intersection of two arrays.
|
||||
*/
|
||||
|
||||
init_alloc_root(PSI_NOT_INSTRUMENTED, &hash_root, 1024, 0, MYF(0));
|
||||
root_inited= true;
|
||||
|
||||
if (json_read_value(&je1) || je1.value_type != JSON_VALUE_ARRAY ||
|
||||
create_hash(&je1, &items, hash_inited, &hash_root))
|
||||
{
|
||||
if (je1.s.error)
|
||||
report_json_error(js1, &je1, 0);
|
||||
null_value= 1;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
max_length= (args[0]->max_length < args[1]->max_length) ?
|
||||
args[0]->max_length : args[1]->max_length;
|
||||
|
||||
set_maybe_null();
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
bool filter_keys(json_engine_t *je1, String *str, HASH items)
|
||||
{
|
||||
int level= je1->stack_p;
|
||||
String temp_str(0);
|
||||
bool res= true, has_value= false;
|
||||
|
||||
temp_str.append('{');
|
||||
while (json_scan_next(je1)==0 && level <= je1->stack_p)
|
||||
{
|
||||
switch(je1->state)
|
||||
{
|
||||
case JST_KEY:
|
||||
{
|
||||
const uchar *key_start= je1->s.c_str;
|
||||
const uchar *key_end;
|
||||
String str("", 0, je1->s.cs);
|
||||
str.append('"');
|
||||
|
||||
do
|
||||
{
|
||||
key_end= je1->s.c_str;
|
||||
} while (json_read_keyname_chr(je1) == 0);
|
||||
|
||||
if (unlikely(je1->s.error))
|
||||
goto error;
|
||||
if (json_read_value(je1))
|
||||
goto error;
|
||||
|
||||
const uchar* value_start= NULL;
|
||||
size_t value_len= 0;
|
||||
if (get_current_value(je1, value_start, value_len))
|
||||
goto error;
|
||||
|
||||
str.append((const char*)key_start, (size_t)(key_end-key_start));
|
||||
str.append('"');
|
||||
str.append('\0');
|
||||
|
||||
char *curr_key= (char*)malloc((size_t)(key_end-key_start+3));
|
||||
strncpy(curr_key, str.ptr(), str.length());
|
||||
|
||||
if (my_hash_search(&items, (const uchar*)curr_key, strlen(curr_key)))
|
||||
{
|
||||
has_value= true;
|
||||
|
||||
temp_str.append('"');
|
||||
temp_str.append((const char*)key_start, (size_t)(key_end-key_start));
|
||||
temp_str.append('"');
|
||||
|
||||
temp_str.append(':');
|
||||
|
||||
temp_str.append((const char*)value_start, value_len);
|
||||
|
||||
temp_str.append(',');
|
||||
}
|
||||
free(curr_key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
res= false;
|
||||
|
||||
if (has_value)
|
||||
{
|
||||
temp_str.chop();
|
||||
temp_str.append('}');
|
||||
str->append(temp_str.ptr(), temp_str.length());
|
||||
}
|
||||
|
||||
error:
|
||||
return res;
|
||||
}
|
||||
|
||||
String* Item_func_json_object_filter_keys::val_str(String *str)
|
||||
{
|
||||
DBUG_ASSERT(fixed());
|
||||
|
||||
json_engine_t je1, res_je;
|
||||
String *js1= args[0]->val_json(&tmp_js1);
|
||||
|
||||
if (null_value || args[0]->null_value)
|
||||
goto null_return;
|
||||
|
||||
str->set_charset(js1->charset());
|
||||
str->length(0);
|
||||
|
||||
json_scan_start(&je1, js1->charset(),(const uchar *) js1->ptr(),
|
||||
(const uchar *) js1->ptr() + js1->length());
|
||||
|
||||
if (json_read_value(&je1) || je1.value_type != JSON_VALUE_OBJECT)
|
||||
goto error_return;
|
||||
|
||||
if(filter_keys(&je1, str, items))
|
||||
goto null_return;
|
||||
|
||||
if (str->length())
|
||||
{
|
||||
json_scan_start(&res_je, str->charset(), (const uchar *) str->ptr(),
|
||||
(const uchar *) str->ptr() + str->length());
|
||||
str= &tmp_js1;
|
||||
if (json_nice(&res_je, str, Item_func_json_format::LOOSE))
|
||||
goto error_return;
|
||||
|
||||
null_value= 0;
|
||||
return str;
|
||||
}
|
||||
else
|
||||
{
|
||||
goto null_return;
|
||||
}
|
||||
|
||||
|
||||
error_return:
|
||||
if (je1.s.error)
|
||||
report_json_error(js1, &je1, 0);
|
||||
null_return:
|
||||
null_value= 1;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
bool Item_func_json_object_filter_keys::fix_length_and_dec(THD *thd)
|
||||
{
|
||||
String *js2= args[1]->val_json(&tmp_js2);
|
||||
json_engine_t je2;
|
||||
|
||||
if (args[1]->null_value)
|
||||
{
|
||||
null_value= 1;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
json_scan_start(&je2, js2->charset(),(const uchar *) js2->ptr(),
|
||||
(const uchar *) js2->ptr() + js2->length());
|
||||
init_alloc_root(PSI_NOT_INSTRUMENTED, &hash_root, 1024, 0, MYF(0));
|
||||
root_inited= true;
|
||||
|
||||
if (json_read_value(&je2) || je2.value_type != JSON_VALUE_ARRAY ||
|
||||
create_hash(&je2, &items, hash_inited, &hash_root))
|
||||
{
|
||||
if (je2.s.error)
|
||||
report_json_error(js2, &je2, 0);
|
||||
null_value= 1;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
max_length= args[0]->max_length;
|
||||
set_maybe_null();
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
bool convert_to_array(json_engine_t *je, String *str)
|
||||
{
|
||||
int level= je->stack_p;
|
||||
String temp_str(0);
|
||||
temp_str.append('[');
|
||||
|
||||
while (json_scan_next(je)==0 && level <= je->stack_p)
|
||||
{
|
||||
switch(je->state)
|
||||
{
|
||||
case JST_KEY:
|
||||
{
|
||||
temp_str.append('[');
|
||||
|
||||
const uchar *key_start= je->s.c_str;
|
||||
const uchar *key_end;
|
||||
|
||||
do
|
||||
{
|
||||
key_end= je->s.c_str;
|
||||
} while (json_read_keyname_chr(je) == 0);
|
||||
|
||||
if (unlikely(je->s.error))
|
||||
return true;
|
||||
|
||||
temp_str.append('"');
|
||||
temp_str.append((const char*)key_start, (size_t)(key_end-key_start));
|
||||
temp_str.append('"');
|
||||
|
||||
temp_str.append(',');
|
||||
|
||||
int v_len= 0;
|
||||
const uchar *value= NULL;
|
||||
|
||||
if (json_read_value(je))
|
||||
return true;
|
||||
value= je->value_begin;
|
||||
if (json_value_scalar(je))
|
||||
v_len= (int)(je->value_end - value);
|
||||
else
|
||||
{
|
||||
if (json_skip_level(je))
|
||||
return true;
|
||||
v_len= (int)(je->s.c_str - value);
|
||||
}
|
||||
temp_str.append((const char *) value, v_len);
|
||||
|
||||
temp_str.append(']');
|
||||
temp_str.append(',');
|
||||
}
|
||||
}
|
||||
}
|
||||
if (je->s.error)
|
||||
return true;
|
||||
|
||||
temp_str.chop(); /* remove the last comma. */
|
||||
temp_str.append(']');
|
||||
str->append(temp_str.ptr(), temp_str.length());
|
||||
return false;
|
||||
}
|
||||
|
||||
String* Item_func_json_object_to_array::val_str(String *str)
|
||||
{
|
||||
DBUG_ASSERT(fixed());
|
||||
|
||||
json_engine_t je;
|
||||
String *js1= args[0]->val_str(&tmp);
|
||||
|
||||
if (args[0]->null_value)
|
||||
goto null_return;
|
||||
|
||||
str->set_charset(js1->charset());
|
||||
str->length(0);
|
||||
|
||||
json_scan_start(&je, js1->charset(),(const uchar *) js1->ptr(),
|
||||
(const uchar *) js1->ptr() + js1->length());
|
||||
|
||||
if (json_read_value(&je))
|
||||
goto error_return;
|
||||
if (je.value_type != JSON_VALUE_OBJECT)
|
||||
goto null_return;
|
||||
|
||||
if (convert_to_array(&je, str))
|
||||
goto error_return;
|
||||
|
||||
if (str->length())
|
||||
{
|
||||
json_scan_start(&je, str->charset(), (const uchar *) str->ptr(),
|
||||
(const uchar *) str->ptr() + str->length());
|
||||
str= &tmp;
|
||||
if (json_nice(&je, str, Item_func_json_format::LOOSE))
|
||||
goto error_return;
|
||||
|
||||
null_value= 0;
|
||||
return str;
|
||||
}
|
||||
else
|
||||
{
|
||||
goto null_return;
|
||||
}
|
||||
|
||||
error_return:
|
||||
if (je.s.error)
|
||||
report_json_error(js1, &je, 0);
|
||||
null_return:
|
||||
null_value= 1;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
bool Item_func_json_object_to_array::fix_length_and_dec(THD *thd)
|
||||
{
|
||||
max_length= args[0]->max_length + (args[0]->max_length/2);
|
||||
set_maybe_null();
|
||||
return FALSE;
|
||||
}
|
||||
|
@ -60,7 +60,13 @@ int json_find_overlap_with_array(json_engine_t *js,
|
||||
json_engine_t *value,
|
||||
bool compare_whole);
|
||||
|
||||
|
||||
bool create_hash(json_engine_t *value, HASH *items, bool &hash_inited);
|
||||
bool create_item(LEX_CSTRING *&new_entry,
|
||||
const uchar *value_start, size_t value_len);
|
||||
bool get_current_value(json_engine_t *js, const uchar *&value_start,
|
||||
size_t &value_len);
|
||||
bool get_intersect_between_arrays(String *str,
|
||||
json_engine_t *value);
|
||||
|
||||
class Json_engine_scan: public json_engine_t
|
||||
{
|
||||
@ -491,6 +497,25 @@ public:
|
||||
};
|
||||
|
||||
|
||||
class Item_func_json_object_to_array: public Item_json_func
|
||||
{
|
||||
protected:
|
||||
String tmp;
|
||||
public:
|
||||
Item_func_json_object_to_array(THD *thd, Item *a):
|
||||
Item_json_func(thd, a) {}
|
||||
String *val_str(String *) override;
|
||||
LEX_CSTRING func_name_cstring() const override
|
||||
{
|
||||
static LEX_CSTRING name= {STRING_WITH_LEN("json_object_to_array") };
|
||||
return name;
|
||||
}
|
||||
bool fix_length_and_dec(THD *thd) override;
|
||||
Item *get_copy(THD *thd) override
|
||||
{ return get_item_copy<Item_func_json_object_to_array>(thd, this); }
|
||||
};
|
||||
|
||||
|
||||
class Item_func_json_length: public Item_long_func
|
||||
{
|
||||
bool check_arguments() const override
|
||||
@ -855,4 +880,69 @@ public:
|
||||
};
|
||||
|
||||
|
||||
|
||||
class Item_func_json_array_intersect: public Item_str_func
|
||||
{
|
||||
protected:
|
||||
String tmp_js1, tmp_js2;
|
||||
bool hash_inited, root_inited;
|
||||
HASH items;
|
||||
MEM_ROOT hash_root;
|
||||
public:
|
||||
Item_func_json_array_intersect(THD *thd, Item *a, Item *b):
|
||||
Item_str_func(thd, a, b) { hash_inited= root_inited= false; }
|
||||
String *val_str(String *) override;
|
||||
bool fix_length_and_dec(THD *thd) override;
|
||||
LEX_CSTRING func_name_cstring() const override
|
||||
{
|
||||
static LEX_CSTRING name= {STRING_WITH_LEN("json_array_intersect") };
|
||||
return name;
|
||||
}
|
||||
Item *get_copy(THD *thd) override
|
||||
{ return get_item_copy<Item_func_json_array_intersect>(thd, this); }
|
||||
void cleanup() override
|
||||
{
|
||||
if (hash_inited)
|
||||
my_hash_free(&items);
|
||||
}
|
||||
~Item_func_json_array_intersect()
|
||||
{
|
||||
if (root_inited)
|
||||
free_root(&hash_root, MYF(0));
|
||||
}
|
||||
};
|
||||
|
||||
class Item_func_json_object_filter_keys: public Item_str_func
|
||||
{
|
||||
protected:
|
||||
String tmp_js1, tmp_js2;
|
||||
bool hash_inited, root_inited;
|
||||
HASH items;
|
||||
MEM_ROOT hash_root;
|
||||
public:
|
||||
Item_func_json_object_filter_keys(THD *thd, Item *a, Item *b):
|
||||
Item_str_func(thd, a, b) { hash_inited= root_inited= false; }
|
||||
String *val_str(String *) override;
|
||||
bool fix_length_and_dec(THD *thd) override;
|
||||
LEX_CSTRING func_name_cstring() const override
|
||||
{
|
||||
static LEX_CSTRING name= {STRING_WITH_LEN("json_object_filter_keys") };
|
||||
return name;
|
||||
}
|
||||
Item *get_copy(THD *thd) override
|
||||
{ return get_item_copy<Item_func_json_object_filter_keys>(thd, this); }
|
||||
|
||||
void cleanup() override
|
||||
{
|
||||
if (hash_inited)
|
||||
my_hash_free(&items);
|
||||
}
|
||||
~Item_func_json_object_filter_keys()
|
||||
{
|
||||
if (root_inited)
|
||||
free_root(&hash_root, MYF(0));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#endif /* ITEM_JSONFUNC_INCLUDED */
|
||||
|
Reference in New Issue
Block a user