Commit 5ca64e65 authored by Rucha Deodhar's avatar Rucha Deodhar

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.
parent d7df63e1
......@@ -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))
goto error; /* Out of memory. */
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. */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment