From 30c231b03a270d3056d2e0da6e263ac10091567b Mon Sep 17 00:00:00 2001 From: Alexey Botchkov Date: Fri, 16 Dec 2016 13:51:35 +0400 Subject: [PATCH] MDEV-11569 JSON_ARRAY_INSERT produces an invalid result. String insertion fixed. --- mysql-test/r/func_json.result | 5 +++- mysql-test/t/func_json.test | 1 + sql/item_jsonfunc.cc | 55 ++++++++++++++++++----------------- 3 files changed, 34 insertions(+), 27 deletions(-) diff --git a/mysql-test/r/func_json.result b/mysql-test/r/func_json.result index 7c311c23033..8ce3ccb876f 100644 --- a/mysql-test/r/func_json.result +++ b/mysql-test/r/func_json.result @@ -75,10 +75,13 @@ json_array_insert('["a", {"b": [1, 2]}, [3, 4]]', '$[4]', 'x') ["a", {"b": [1, 2]}, [3, 4], "x"] select json_array_insert('["a", {"b": [1, 2]}, [3, 4]]', '$[1].b[0]', 'x'); json_array_insert('["a", {"b": [1, 2]}, [3, 4]]', '$[1].b[0]', 'x') -["a", {"b": [ "x",1, 2]}, [3, 4]] +["a", {"b": ["x", 1, 2]}, [3, 4]] select json_array_insert('true', '$', 1); json_array_insert('true', '$', 1) NULL +select json_array_insert('["a", {"b": [1, 2]}, [3, 4]]', '$[2][1]', 'y'); +json_array_insert('["a", {"b": [1, 2]}, [3, 4]]', '$[2][1]', 'y') +["a", {"b": [1, 2]}, [3, "y", 4]] select json_contains('{"k1":123, "k2":345}', '123', '$.k1'); json_contains('{"k1":123, "k2":345}', '123', '$.k1') 1 diff --git a/mysql-test/t/func_json.test b/mysql-test/t/func_json.test index f7cc6f99f73..b85b89c068d 100644 --- a/mysql-test/t/func_json.test +++ b/mysql-test/t/func_json.test @@ -30,6 +30,7 @@ select json_array_insert('["a", {"b": [1, 2]}, [3, 4]]', '$[3]', 'x'); select json_array_insert('["a", {"b": [1, 2]}, [3, 4]]', '$[4]', 'x'); select json_array_insert('["a", {"b": [1, 2]}, [3, 4]]', '$[1].b[0]', 'x'); select json_array_insert('true', '$', 1); +select json_array_insert('["a", {"b": [1, 2]}, [3, 4]]', '$[2][1]', 'y'); select json_contains('{"k1":123, "k2":345}', '123', '$.k1'); select json_contains('"you"', '"you"'); diff --git a/sql/item_jsonfunc.cc b/sql/item_jsonfunc.cc index fc3f772321a..413b241f496 100644 --- a/sql/item_jsonfunc.cc +++ b/sql/item_jsonfunc.cc @@ -1396,27 +1396,19 @@ String *Item_func_json_array_insert::val_str(String *str) item_pos= 0; n_item= 0; - while (json_scan_next(&je) == 0 && - je.state != JST_ARRAY_END && item_pos == 0) + while (json_scan_next(&je) == 0 && je.state != JST_ARRAY_END) { - switch (je.state) + DBUG_ASSERT(je.state == JST_VALUE); + if (n_item == c_path->p.last_step[1].n_item) { - case JST_VALUE: - if (n_item == c_path->p.last_step[1].n_item) - { - item_pos= (const char *) je.s.c_str; - break; - } - n_item++; - break; - case JST_OBJ_START: - case JST_ARRAY_START: - if (json_skip_level(&je)) - break; - break; - default: + item_pos= (const char *) je.s.c_str; break; } + n_item++; + + if (json_read_value(&je) || + (!json_value_scalar(&je) && json_skip_level(&je))) + goto js_error; } if (je.s.error) @@ -1424,16 +1416,27 @@ String *Item_func_json_array_insert::val_str(String *str) str->length(0); str->set_charset(js->charset()); - if (!item_pos) + if (item_pos) + { + if (append_simple(str, js->ptr(), item_pos - js->ptr()) || + (n_item > 0 && str->append(" ", 1)) || + append_json_value(str, args[n_arg+1], &tmp_val) || + str->append(",", 1) || + (n_item == 0 && str->append(" ", 1)) || + append_simple(str, item_pos, js->end() - item_pos)) + goto return_null; /* Out of memory. */ + } + else + { + /* Insert position wasn't found - append to the array. */ + DBUG_ASSERT(je.state == JST_ARRAY_END); item_pos= (const char *) (je.s.c_str - je.sav_c_len); - - if (append_simple(str, js->ptr(), item_pos - js->ptr()) || - ((je.state == JST_ARRAY_END) ? - (n_item > 0 && str->append(", ", 2)) : str->append(" ", 1)) || - append_json_value(str, args[n_arg+1], &tmp_val) || - (je.state != JST_ARRAY_END && str->append(",", 1)) || - append_simple(str, item_pos, js->end() - item_pos)) - goto return_null; /* Out of memory. */ + if (append_simple(str, js->ptr(), item_pos - js->ptr()) || + (n_item > 0 && str->append(", ", 2)) || + append_json_value(str, args[n_arg+1], &tmp_val) || + append_simple(str, item_pos, js->end() - item_pos)) + goto return_null; /* Out of memory. */ + } { /* Swap str and js. */