mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03:00
MDEV-31411: JSON_ARRAY_INTERSECT/JSON_OBJECT_FILTER_KEYS should fetch
data from a table similar to other JSON functions Analysis: Since we are fetching values for every row ( because we are running SELECT for all rows of a table ), correct value can be only obtained at the time of calling val_int() because it is called to get value for each row. Fix: Set up hash for each row instead of doing it during fixing fields.
This commit is contained in:
@ -5126,5 +5126,19 @@ SELECT JSON_OBJECT_TO_ARRAY(@arr1);
|
|||||||
JSON_OBJECT_TO_ARRAY(@arr1)
|
JSON_OBJECT_TO_ARRAY(@arr1)
|
||||||
NULL
|
NULL
|
||||||
#
|
#
|
||||||
|
# MDEV-31411: JSON_ARRAY_INTERSECT/JSON_OBJECT_FILTER_KEYS should fetch
|
||||||
|
# data from a table similar to other JSON functions
|
||||||
|
#
|
||||||
|
CREATE TABLE t1 (
|
||||||
|
c1 longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL CHECK (json_valid(c1)),
|
||||||
|
c2 longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL CHECK (json_valid(`c2`))
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci;
|
||||||
|
INSERT INTO t1 VALUES('[1,2,3]', '[2, 3, 4]'), ('[2 ,3, 4]', '[4, 5, 6]');
|
||||||
|
SELECT JSON_ARRAY_INTERSECT(c1, c2) FROM t1;
|
||||||
|
JSON_ARRAY_INTERSECT(c1, c2)
|
||||||
|
[2, 3]
|
||||||
|
[4]
|
||||||
|
DROP TABLE t1;
|
||||||
|
#
|
||||||
# End of 11.2 Test
|
# End of 11.2 Test
|
||||||
#
|
#
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
--source include/have_innodb.inc
|
||||||
|
|
||||||
select json_valid('[1, 2]');
|
select json_valid('[1, 2]');
|
||||||
select json_valid('"string"}');
|
select json_valid('"string"}');
|
||||||
select json_valid('{"key1":1, "key2":[2,3]}');
|
select json_valid('{"key1":1, "key2":[2,3]}');
|
||||||
@ -3947,6 +3949,24 @@ SELECT JSON_OBJECT_TO_ARRAY(@obj1);
|
|||||||
SET @arr1= '[1, 2, 3]';
|
SET @arr1= '[1, 2, 3]';
|
||||||
SELECT JSON_OBJECT_TO_ARRAY(@arr1);
|
SELECT JSON_OBJECT_TO_ARRAY(@arr1);
|
||||||
|
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # MDEV-31411: JSON_ARRAY_INTERSECT/JSON_OBJECT_FILTER_KEYS should fetch
|
||||||
|
--echo # data from a table similar to other JSON functions
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
CREATE TABLE t1 (
|
||||||
|
c1 longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL CHECK (json_valid(c1)),
|
||||||
|
c2 longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL CHECK (json_valid(`c2`))
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci;
|
||||||
|
|
||||||
|
INSERT INTO t1 VALUES('[1,2,3]', '[2, 3, 4]'), ('[2 ,3, 4]', '[4, 5, 6]');
|
||||||
|
|
||||||
|
SELECT JSON_ARRAY_INTERSECT(c1, c2) FROM t1;
|
||||||
|
|
||||||
|
DROP TABLE t1;
|
||||||
|
|
||||||
|
|
||||||
--echo #
|
--echo #
|
||||||
--echo # End of 11.2 Test
|
--echo # End of 11.2 Test
|
||||||
--echo #
|
--echo #
|
||||||
|
7
mysql-test/main/temp.test
Normal file
7
mysql-test/main/temp.test
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
CREATE TABLE t1 ( c1 longtext , c2 longtext );
|
||||||
|
|
||||||
|
INSERT INTO t1 VALUES('[1,2,3]', '[2, 3, 4]'), ('[1,2,3]', '[2, 3, 4]');
|
||||||
|
|
||||||
|
SELECT JSON_ARRAY_INTERSECT(c1, c2) FROM t1;
|
||||||
|
|
||||||
|
DROP TABLE t1;
|
@ -2081,7 +2081,7 @@ return_null:
|
|||||||
String *Item_func_json_array_insert::val_str(String *str)
|
String *Item_func_json_array_insert::val_str(String *str)
|
||||||
{
|
{
|
||||||
json_engine_t je;
|
json_engine_t je;
|
||||||
String *js= args[0]->val_json(&tmp_js);
|
String *js= args[0]->val_str(&tmp_js);
|
||||||
uint n_arg, n_path;
|
uint n_arg, n_path;
|
||||||
THD *thd= current_thd;
|
THD *thd= current_thd;
|
||||||
|
|
||||||
@ -5155,8 +5155,21 @@ String* Item_func_json_array_intersect::val_str(String *str)
|
|||||||
{
|
{
|
||||||
DBUG_ASSERT(fixed());
|
DBUG_ASSERT(fixed());
|
||||||
|
|
||||||
json_engine_t je2, res_je;
|
json_engine_t je2, res_je, je1;
|
||||||
String *js2= args[1]->val_json(&tmp_js2);
|
String *js2= args[1]->val_json(&tmp_js2), *js1= args[0]->val_json(&tmp_js1);
|
||||||
|
|
||||||
|
if (parse_for_each_row)
|
||||||
|
{
|
||||||
|
if (args[0]->null_value)
|
||||||
|
goto null_return;
|
||||||
|
if (hash_inited)
|
||||||
|
my_hash_free(&items);
|
||||||
|
if (root_inited)
|
||||||
|
free_root(&hash_root, MYF(0));
|
||||||
|
root_inited= false;
|
||||||
|
hash_inited= false;
|
||||||
|
prepare_json_and_create_hash(&je1, js1);
|
||||||
|
}
|
||||||
|
|
||||||
if (null_value || args[1]->null_value)
|
if (null_value || args[1]->null_value)
|
||||||
goto null_return;
|
goto null_return;
|
||||||
@ -5197,18 +5210,10 @@ null_return:
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Item_func_json_array_intersect::fix_length_and_dec(THD *thd)
|
void Item_func_json_array_intersect::prepare_json_and_create_hash(json_engine_t *je1, String *js)
|
||||||
{
|
{
|
||||||
json_engine_t je1;
|
json_scan_start(je1, js->charset(), (const uchar *) js->ptr(),
|
||||||
String *js1= args[0]->val_json(&tmp_js1);
|
(const uchar *) js->ptr() + js->length());
|
||||||
|
|
||||||
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.
|
Scan value uses the hash table to get the intersection of two arrays.
|
||||||
*/
|
*/
|
||||||
@ -5217,18 +5222,40 @@ bool Item_func_json_array_intersect::fix_length_and_dec(THD *thd)
|
|||||||
init_alloc_root(PSI_NOT_INSTRUMENTED, &hash_root, 1024, 0, MYF(0));
|
init_alloc_root(PSI_NOT_INSTRUMENTED, &hash_root, 1024, 0, MYF(0));
|
||||||
root_inited= true;
|
root_inited= true;
|
||||||
|
|
||||||
if (json_read_value(&je1) || je1.value_type != JSON_VALUE_ARRAY ||
|
if (json_read_value(je1) || je1->value_type != JSON_VALUE_ARRAY ||
|
||||||
create_hash(&je1, &items, hash_inited, &hash_root))
|
create_hash(je1, &items, hash_inited, &hash_root))
|
||||||
|
{
|
||||||
|
if (je1->s.error)
|
||||||
|
report_json_error(js, je1, 0);
|
||||||
|
null_value= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
max_length= (args[0]->max_length < args[1]->max_length) ?
|
||||||
|
args[0]->max_length : args[1]->max_length;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Item_func_json_array_intersect::fix_length_and_dec(THD *thd)
|
||||||
|
{
|
||||||
|
json_engine_t je1;
|
||||||
|
String *js1;
|
||||||
|
|
||||||
|
if (!args[0]->const_item())
|
||||||
{
|
{
|
||||||
if (je1.s.error)
|
if (args[1]->const_item())
|
||||||
report_json_error(js1, &je1, 0);
|
{
|
||||||
null_value= 1;
|
std::swap(args[0], args[1]);
|
||||||
return FALSE;
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
parse_for_each_row= true;
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
max_length= (args[0]->max_length < args[1]->max_length) ?
|
js1= args[0]->val_json(&tmp_js1);
|
||||||
args[0]->max_length : args[1]->max_length;
|
prepare_json_and_create_hash(&je1, js1);
|
||||||
|
|
||||||
|
end:
|
||||||
set_maybe_null();
|
set_maybe_null();
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
@ -869,9 +869,10 @@ protected:
|
|||||||
bool hash_inited, root_inited;
|
bool hash_inited, root_inited;
|
||||||
HASH items;
|
HASH items;
|
||||||
MEM_ROOT hash_root;
|
MEM_ROOT hash_root;
|
||||||
|
bool parse_for_each_row;
|
||||||
public:
|
public:
|
||||||
Item_func_json_array_intersect(THD *thd, Item *a, Item *b):
|
Item_func_json_array_intersect(THD *thd, Item *a, Item *b):
|
||||||
Item_str_func(thd, a, b) { hash_inited= root_inited= false; }
|
Item_str_func(thd, a, b) { hash_inited= root_inited= parse_for_each_row= false; }
|
||||||
String *val_str(String *) override;
|
String *val_str(String *) override;
|
||||||
bool fix_length_and_dec(THD *thd) override;
|
bool fix_length_and_dec(THD *thd) override;
|
||||||
LEX_CSTRING func_name_cstring() const override
|
LEX_CSTRING func_name_cstring() const override
|
||||||
@ -889,6 +890,7 @@ public:
|
|||||||
if (root_inited)
|
if (root_inited)
|
||||||
free_root(&hash_root, MYF(0));
|
free_root(&hash_root, MYF(0));
|
||||||
}
|
}
|
||||||
|
void prepare_json_and_create_hash(json_engine_t *je1, String *js);
|
||||||
};
|
};
|
||||||
|
|
||||||
class Item_func_json_object_filter_keys: public Item_str_func
|
class Item_func_json_object_filter_keys: public Item_str_func
|
||||||
|
Reference in New Issue
Block a user