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, 'ä')
|
json_arrayagg('ä') json_objectagg(1, 'ä')
|
||||||
["ä"] {"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
|
# 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));
|
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, 'ä');
|
select json_arrayagg('ä'), json_objectagg(1, 'ä');
|
||||||
--enable_service_connection
|
--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 #
|
||||||
--echo # MDEV-31402: SIGSEGV in json_get_path_next | Item_func_json_extract::read_json
|
--echo # MDEV-31402: SIGSEGV in json_get_path_next | Item_func_json_extract::read_json
|
||||||
--echo #
|
--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)
|
const json_path_t *p, json_value_types vt)
|
||||||
{
|
{
|
||||||
|
int count_path= 0;
|
||||||
for (; n_paths > 0; n_paths--, paths_list++)
|
for (; n_paths > 0; n_paths--, paths_list++)
|
||||||
{
|
{
|
||||||
if (json_path_compare(&paths_list->p, p, vt) == 0)
|
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_engine_t je, sav_je;
|
||||||
json_path_t p;
|
json_path_t p;
|
||||||
const uchar *value;
|
const uchar *value;
|
||||||
int not_first_value= 0;
|
int not_first_value= 0, count_path= 0;
|
||||||
uint n_arg;
|
uint n_arg;
|
||||||
size_t v_len;
|
size_t v_len;
|
||||||
int possible_multiple_values;
|
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)
|
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;
|
continue;
|
||||||
|
|
||||||
value= je.value_begin;
|
value= je.value_begin;
|
||||||
@ -1002,9 +1003,12 @@ String *Item_func_json_extract::read_json(String *str,
|
|||||||
je= sav_je;
|
je= sav_je;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((not_first_value && str->append(", ", 2)) ||
|
for (int count= 0; count < count_path; count++)
|
||||||
str->append((const char *) value, v_len))
|
{
|
||||||
|
if (str->append((const char *) value, v_len) ||
|
||||||
|
str->append(", ", 2))
|
||||||
goto error; /* Out of memory. */
|
goto error; /* Out of memory. */
|
||||||
|
}
|
||||||
|
|
||||||
not_first_value= 1;
|
not_first_value= 1;
|
||||||
|
|
||||||
@ -1025,6 +1029,11 @@ String *Item_func_json_extract::read_json(String *str,
|
|||||||
goto return_null;
|
goto return_null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (str->length()>2)
|
||||||
|
{
|
||||||
|
str->chop();
|
||||||
|
str->chop();
|
||||||
|
}
|
||||||
if (possible_multiple_values && str->append("]", 1))
|
if (possible_multiple_values && str->append("]", 1))
|
||||||
goto error; /* Out of memory. */
|
goto error; /* Out of memory. */
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user