mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03:00
MDEV-32287: JSON_EXTRACT not returning multiple values for same path
Analysis: When scanning json and getting the exact path at each step, if a path is reached, we end up adding the item in the result and immediately get the next item which results in current path changing. Fix: Instead of immediately returning the item, count the occurences of the path in argument and append in the result as needed.
This commit is contained in:
@ -1690,6 +1690,12 @@ select json_arrayagg('ä'), json_objectagg(1, 'ä');
|
||||
json_arrayagg('ä') json_objectagg(1, 'ä')
|
||||
["ä"] {"1":"ä"}
|
||||
#
|
||||
# MDEV-32287: JSON_EXTRACT not returning multiple values for same path
|
||||
#
|
||||
select JSON_EXTRACT("[1, 2, [30, 40]]", '$[2][1]', '$[2][1]');
|
||||
JSON_EXTRACT("[1, 2, [30, 40]]", '$[2][1]', '$[2][1]')
|
||||
[40, 40]
|
||||
#
|
||||
# MDEV-31402: SIGSEGV in json_get_path_next | Item_func_json_extract::read_json
|
||||
#
|
||||
CREATE TABLE t (id CHAR AS (JSON_COMPACT (JSON_EXTRACT(doc,"$._id"))) UNIQUE KEY,doc JSON,CONSTRAINT notnu CHECK (id IS NOT NULL));
|
||||
|
@ -1115,6 +1115,14 @@ set names latin1;
|
||||
select json_arrayagg('ä'), json_objectagg(1, 'ä');
|
||||
--enable_service_connection
|
||||
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-32287: JSON_EXTRACT not returning multiple values for same path
|
||||
--echo #
|
||||
|
||||
select JSON_EXTRACT("[1, 2, [30, 40]]", '$[2][1]', '$[2][1]');
|
||||
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-31402: SIGSEGV in json_get_path_next | Item_func_json_extract::read_json
|
||||
--echo #
|
||||
|
@ -893,15 +893,16 @@ bool Item_func_json_extract::fix_length_and_dec()
|
||||
}
|
||||
|
||||
|
||||
static bool path_exact(const json_path_with_flags *paths_list, int n_paths,
|
||||
static int path_exact(const json_path_with_flags *paths_list, int n_paths,
|
||||
const json_path_t *p, json_value_types vt)
|
||||
{
|
||||
int count_path= 0;
|
||||
for (; n_paths > 0; n_paths--, paths_list++)
|
||||
{
|
||||
if (json_path_compare(&paths_list->p, p, vt) == 0)
|
||||
return TRUE;
|
||||
count_path++;
|
||||
}
|
||||
return FALSE;
|
||||
return count_path;
|
||||
}
|
||||
|
||||
|
||||
@ -925,7 +926,7 @@ String *Item_func_json_extract::read_json(String *str,
|
||||
json_engine_t je, sav_je;
|
||||
json_path_t p;
|
||||
const uchar *value;
|
||||
int not_first_value= 0;
|
||||
int not_first_value= 0, count_path= 0;
|
||||
uint n_arg;
|
||||
size_t v_len;
|
||||
int possible_multiple_values;
|
||||
@ -972,7 +973,7 @@ String *Item_func_json_extract::read_json(String *str,
|
||||
|
||||
while (json_get_path_next(&je, &p) == 0)
|
||||
{
|
||||
if (!path_exact(paths, arg_count-1, &p, je.value_type))
|
||||
if (!(count_path= path_exact(paths, arg_count-1, &p, je.value_type)))
|
||||
continue;
|
||||
|
||||
value= je.value_begin;
|
||||
@ -1002,9 +1003,12 @@ String *Item_func_json_extract::read_json(String *str,
|
||||
je= sav_je;
|
||||
}
|
||||
|
||||
if ((not_first_value && str->append(", ", 2)) ||
|
||||
str->append((const char *) value, v_len))
|
||||
for (int count= 0; count < count_path; count++)
|
||||
{
|
||||
if (str->append((const char *) value, v_len) ||
|
||||
str->append(", ", 2))
|
||||
goto error; /* Out of memory. */
|
||||
}
|
||||
|
||||
not_first_value= 1;
|
||||
|
||||
@ -1025,6 +1029,11 @@ String *Item_func_json_extract::read_json(String *str,
|
||||
goto return_null;
|
||||
}
|
||||
|
||||
if (str->length()>2)
|
||||
{
|
||||
str->chop();
|
||||
str->chop();
|
||||
}
|
||||
if (possible_multiple_values && str->append("]", 1))
|
||||
goto error; /* Out of memory. */
|
||||
|
||||
|
Reference in New Issue
Block a user