diff options
author | Alexey Botchkov <holyfoot@askmonty.org> | 2017-01-26 16:35:05 +0400 |
---|---|---|
committer | Alexey Botchkov <holyfoot@askmonty.org> | 2017-01-26 16:35:05 +0400 |
commit | d96ee168a1f87c090421fb593930515ae8db3d7f (patch) | |
tree | 7eb78889644c1bc4eb32ab4274a0840a1622cfd4 | |
parent | 71495a1748784a887f42888a2a7b8cac5e088ff6 (diff) | |
download | mariadb-git-d96ee168a1f87c090421fb593930515ae8db3d7f.tar.gz |
MDEV-11557 port MySQL-5.7 JSON tests to MariaDB.
paths ending on [0]..[0] should be handled in conforming manner.
-rw-r--r-- | mysql-test/r/func_json.result | 50 | ||||
-rw-r--r-- | mysql-test/suite/json/r/json_no_table.result | 62 | ||||
-rw-r--r-- | mysql-test/t/func_json.test | 18 | ||||
-rw-r--r-- | sql/item_jsonfunc.cc | 24 | ||||
-rw-r--r-- | strings/json_lib.c | 43 |
5 files changed, 147 insertions, 50 deletions
diff --git a/mysql-test/r/func_json.result b/mysql-test/r/func_json.result index 47993ae9a32..6968cf79d7d 100644 --- a/mysql-test/r/func_json.result +++ b/mysql-test/r/func_json.result @@ -444,3 +444,53 @@ json CREATE TABLE `json` ( `j` int(11) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 drop table json; +select json_length( '[ 1, [ 2, 3, 4 ], 5 ]', '$[2]' ); +json_length( '[ 1, [ 2, 3, 4 ], 5 ]', '$[2]' ) +1 +select json_length( '[ 1, [ 2, 3, 4 ], 5 ]', '$[2][0]' ); +json_length( '[ 1, [ 2, 3, 4 ], 5 ]', '$[2][0]' ) +1 +select json_length( '[ 1, [ 2, 3, 4 ], 5 ]', '$[2][0][0]' ); +json_length( '[ 1, [ 2, 3, 4 ], 5 ]', '$[2][0][0]' ) +1 +select json_length( '[ 1, [ 2, 3, 4 ], 5 ]', '$[2][0][0][0]' ); +json_length( '[ 1, [ 2, 3, 4 ], 5 ]', '$[2][0][0][0]' ) +1 +select json_length( '[ 1, [ 2, 3, 4 ], {"a":5, "b":6} ]', '$[2]' ); +json_length( '[ 1, [ 2, 3, 4 ], {"a":5, "b":6} ]', '$[2]' ) +2 +select json_length( '[ 1, [ 2, 3, 4 ], {"a":5, "b":6} ]', '$[2][0]' ); +json_length( '[ 1, [ 2, 3, 4 ], {"a":5, "b":6} ]', '$[2][0]' ) +2 +select json_length( '[ 1, [ 2, 3, 4 ], {"a":5, "b":6} ]', '$[2][0][0]' ); +json_length( '[ 1, [ 2, 3, 4 ], {"a":5, "b":6} ]', '$[2][0][0]' ) +2 +select json_length( '[ 1, [ 2, 3, 4 ], {"a":5, "b":6} ]', '$[2][0][0][0]' ); +json_length( '[ 1, [ 2, 3, 4 ], {"a":5, "b":6} ]', '$[2][0][0][0]' ) +2 +select json_length( '{"a":{"b":{"d":1}}, "a":{"c":{"d":1, "j":2}}}', '$.a[0][0][0].c' ); +json_length( '{"a":{"b":{"d":1}}, "a":{"c":{"d":1, "j":2}}}', '$.a[0][0][0].c' ) +2 +select json_set('1', '$[0]', 100); +json_set('1', '$[0]', 100) +100 +select json_set('1', '$[0][0]', 100); +json_set('1', '$[0][0]', 100) +100 +select json_set('1', '$[1]', 100); +json_set('1', '$[1]', 100) +[1, 100] +select json_set('{"a":12}', '$[0]', 100); +json_set('{"a":12}', '$[0]', 100) +100 +select json_set('{"a":12}', '$[0].a', 100); +json_set('{"a":12}', '$[0].a', 100) +{"a":100} +select json_set('{"a":12}', '$[0][0].a', 100); +json_set('{"a":12}', '$[0][0].a', 100) +{"a":100} +select json_set('{"a":12}', '$[0][1].a', 100); +json_set('{"a":12}', '$[0][1].a', 100) +NULL +Warnings: +Warning 4037 Unexpected end of JSON text in argument 1 to function 'json_set' diff --git a/mysql-test/suite/json/r/json_no_table.result b/mysql-test/suite/json/r/json_no_table.result index 88016ebfd19..97148bdad43 100644 --- a/mysql-test/suite/json/r/json_no_table.result +++ b/mysql-test/suite/json/r/json_no_table.result @@ -420,10 +420,10 @@ json_length( '[ 1, [ 2, 3, 4 ], 5 ]', '$[2]' ) 1 select json_length( '[ 1, [ 2, 3, 4 ], 5 ]', '$[2][0]' ); json_length( '[ 1, [ 2, 3, 4 ], 5 ]', '$[2][0]' ) -NULL +1 select json_length( '[ 1, [ 2, 3, 4 ], {"a": 1} ]', '$[2][0]' ); json_length( '[ 1, [ 2, 3, 4 ], {"a": 1} ]', '$[2][0]' ) -NULL +1 select json_length( '[ 1, [ 2, 3, 4 ], 5 ]', '$[2][1]' ); json_length( '[ 1, [ 2, 3, 4 ], 5 ]', '$[2][1]' ) NULL @@ -1694,13 +1694,13 @@ JSON_ARRAY_APPEND # ---------------------------------------------------------------------- select json_array_append('{"a":1}', '$[0]', 100); json_array_append('{"a":1}', '$[0]', 100) -NULL +[{"a":1}, 100] select json_array_append('3', '$[0]', 100); json_array_append('3', '$[0]', 100) -NULL +[3, 100] select json_array_append('3', '$[0][0][0][0]', 100); json_array_append('3', '$[0][0][0][0]', 100) -NULL +[3, 100] # ---------------------------------------------------------------------- # Test of JSON_INSERT function. # ---------------------------------------------------------------------- @@ -2118,7 +2118,7 @@ json_set('1', '$', 4) 4 select json_set('1', '$[0]', 4); json_set('1', '$[0]', 4) -[1, 4] +4 select json_set('1', '$[1]', 4); json_set('1', '$[1]', 4) [1, 4] @@ -2127,13 +2127,13 @@ json_set('1', '$[10]', '4', '$[11]', 5) [1, "4", 5] select json_set('[1,2,3]', '$[2][0]', 4); json_set('[1,2,3]', '$[2][0]', 4) -[1,2,[3, 4]] +[1,2,4] select json_set('[1,2,3]', '$[2][2]', 4); json_set('[1,2,3]', '$[2][2]', 4) [1,2,[3, 4]] select json_set('{"a": 3}', '$.a[0]', 4); json_set('{"a": 3}', '$.a[0]', 4) -{"a": [3, 4]} +{"a": 4} select json_set('{"a": 3}', '$.a[1]', 4, '$.a[2]', '5'); json_set('{"a": 3}', '$.a[1]', 4, '$.a[2]', '5') {"a": [3, 4, "5"]} @@ -2280,7 +2280,7 @@ json_replace('1', '$', 4) 4 select json_replace('1', '$[0]', 4); json_replace('1', '$[0]', 4) -1 +4 select json_replace('1', '$[1]', 4); json_replace('1', '$[1]', 4) 1 @@ -2289,13 +2289,13 @@ json_replace('1', '$[10]', '4', '$[11]', 5) 1 select json_replace('[1,2,3]', '$[2][0]', 4); json_replace('[1,2,3]', '$[2][0]', 4) -[1,2,3] +[1,2,4] select json_replace('[1,2,3]', '$[2][2]', 4); json_replace('[1,2,3]', '$[2][2]', 4) [1,2,3] select json_replace('{"a": 3}', '$.a[0]', 4); json_replace('{"a": 3}', '$.a[0]', 4) -{"a": 3} +{"a": 4} select json_replace('{"a": 3}', '$.a[1]', 4, '$.a[2]', '5'); json_replace('{"a": 3}', '$.a[1]', 4, '$.a[2]', '5') {"a": 3} @@ -2312,7 +2312,7 @@ true); JSON_REPLACE('{ "a" : "foo", "b" : [ 1, 2, 3 ] }', '$.a[0]', true) -{ "a" : "foo", "b" : [ 1, 2, 3 ] } +{ "a" : true, "b" : [ 1, 2, 3 ] } SELECT JSON_REPLACE('{ "a" : "foo", "b" : [ 1, 2, 3 ] }', '$.b[5]', true); @@ -3489,23 +3489,19 @@ JSON_SET('1', '$', 100) 100 SELECT JSON_SET('1', '$[0]', 100); JSON_SET('1', '$[0]', 100) -[1, 100] +100 SELECT JSON_SET('1', '$[0][0]', 100); JSON_SET('1', '$[0][0]', 100) -NULL -Warnings: -Warning 4037 Unexpected end of JSON text in argument 1 to function 'json_set' +100 SELECT JSON_SET('1', '$[0][0][0]', 100); JSON_SET('1', '$[0][0][0]', 100) -NULL -Warnings: -Warning 4037 Unexpected end of JSON text in argument 1 to function 'json_set' +100 SELECT JSON_SET('[]', '$', 100); JSON_SET('[]', '$', 100) 100 SELECT JSON_SET('[]', '$[0]', 100); JSON_SET('[]', '$[0]', 100) -[, 100] +[100] SELECT JSON_SET('[]', '$[0][0]', 100); JSON_SET('[]', '$[0][0]', 100) NULL @@ -3524,12 +3520,10 @@ JSON_SET('[1]', '$[0]', 100) [100] SELECT JSON_SET('[1]', '$[0][0]', 100); JSON_SET('[1]', '$[0][0]', 100) -[[1, 100]] +[100] SELECT JSON_SET('[1]', '$[0][0][0]', 100); JSON_SET('[1]', '$[0][0][0]', 100) -NULL -Warnings: -Warning 4037 Unexpected end of JSON text in argument 1 to function 'json_set' +[100] SELECT JSON_SET('[[1]]', '$', 100); JSON_SET('[[1]]', '$', 100) 100 @@ -3541,7 +3535,7 @@ JSON_SET('[[1]]', '$[0][0]', 100) [[100]] SELECT JSON_SET('[[1]]', '$[0][0][0]', 100); JSON_SET('[[1]]', '$[0][0][0]', 100) -[[[1, 100]]] +[[100]] SELECT JSON_SET('[[[1]]]', '$', 100); JSON_SET('[[[1]]]', '$', 100) 100 @@ -3559,17 +3553,13 @@ JSON_REPLACE('1', '$', 100) 100 SELECT JSON_REPLACE('1', '$[0]', 100); JSON_REPLACE('1', '$[0]', 100) -1 +100 SELECT JSON_REPLACE('1', '$[0][0]', 100); JSON_REPLACE('1', '$[0][0]', 100) -NULL -Warnings: -Warning 4037 Unexpected end of JSON text in argument 1 to function 'json_update' +100 SELECT JSON_REPLACE('1', '$[0][0][0]', 100); JSON_REPLACE('1', '$[0][0][0]', 100) -NULL -Warnings: -Warning 4037 Unexpected end of JSON text in argument 1 to function 'json_update' +100 SELECT JSON_REPLACE('[]', '$', 100); JSON_REPLACE('[]', '$', 100) 100 @@ -3594,12 +3584,10 @@ JSON_REPLACE('[1]', '$[0]', 100) [100] SELECT JSON_REPLACE('[1]', '$[0][0]', 100); JSON_REPLACE('[1]', '$[0][0]', 100) -[1] +[100] SELECT JSON_REPLACE('[1]', '$[0][0][0]', 100); JSON_REPLACE('[1]', '$[0][0][0]', 100) -NULL -Warnings: -Warning 4037 Unexpected end of JSON text in argument 1 to function 'json_update' +[100] SELECT JSON_REPLACE('[[1]]', '$', 100); JSON_REPLACE('[[1]]', '$', 100) 100 @@ -3611,7 +3599,7 @@ JSON_REPLACE('[[1]]', '$[0][0]', 100) [[100]] SELECT JSON_REPLACE('[[1]]', '$[0][0][0]', 100); JSON_REPLACE('[[1]]', '$[0][0][0]', 100) -[[1]] +[[100]] SELECT JSON_REPLACE('[[[1]]]', '$', 100); JSON_REPLACE('[[[1]]]', '$', 100) 100 diff --git a/mysql-test/t/func_json.test b/mysql-test/t/func_json.test index 455f1a722ea..b9b4ab3726a 100644 --- a/mysql-test/t/func_json.test +++ b/mysql-test/t/func_json.test @@ -179,3 +179,21 @@ create table json (j INT); show create table json; drop table json; +select json_length( '[ 1, [ 2, 3, 4 ], 5 ]', '$[2]' ); +select json_length( '[ 1, [ 2, 3, 4 ], 5 ]', '$[2][0]' ); +select json_length( '[ 1, [ 2, 3, 4 ], 5 ]', '$[2][0][0]' ); +select json_length( '[ 1, [ 2, 3, 4 ], 5 ]', '$[2][0][0][0]' ); +select json_length( '[ 1, [ 2, 3, 4 ], {"a":5, "b":6} ]', '$[2]' ); +select json_length( '[ 1, [ 2, 3, 4 ], {"a":5, "b":6} ]', '$[2][0]' ); +select json_length( '[ 1, [ 2, 3, 4 ], {"a":5, "b":6} ]', '$[2][0][0]' ); +select json_length( '[ 1, [ 2, 3, 4 ], {"a":5, "b":6} ]', '$[2][0][0][0]' ); +select json_length( '{"a":{"b":{"d":1}}, "a":{"c":{"d":1, "j":2}}}', '$.a[0][0][0].c' ); + +select json_set('1', '$[0]', 100); +select json_set('1', '$[0][0]', 100); +select json_set('1', '$[1]', 100); +select json_set('{"a":12}', '$[0]', 100); +select json_set('{"a":12}', '$[0].a', 100); +select json_set('{"a":12}', '$[0][0].a', 100); +select json_set('{"a":12}', '$[0][1].a', 100); + diff --git a/sql/item_jsonfunc.cc b/sql/item_jsonfunc.cc index fc146427bc1..4731bada6ab 100644 --- a/sql/item_jsonfunc.cc +++ b/sql/item_jsonfunc.cc @@ -1983,13 +1983,22 @@ String *Item_func_json_insert::val_str(String *str) if (je.value_type != JSON_VALUE_ARRAY) { const uchar *v_from= je.value_begin; - if (!mode_insert) - continue; + int do_array_autowrap; + + if (mode_insert) + do_array_autowrap= !mode_replace || lp->n_item; + else + { + if (lp->n_item) + continue; + do_array_autowrap= 0; + } + str->length(0); /* Wrap the value as an array. */ if (append_simple(str, js->ptr(), (const char *) v_from - js->ptr()) || - str->append("[", 1)) + (do_array_autowrap && str->append("[", 1))) goto js_error; /* Out of memory. */ if (je.value_type == JSON_VALUE_OBJECT) @@ -1998,10 +2007,11 @@ String *Item_func_json_insert::val_str(String *str) goto js_error; } - if (append_simple(str, v_from, je.s.c_str - v_from) || - str->append(", ", 2) || + if ((do_array_autowrap && + (append_simple(str, v_from, je.s.c_str - v_from) || + str->append(", ", 2))) || append_json_value(str, args[n_arg+1], &tmp_val) || - str->append("]", 1) || + (do_array_autowrap && str->append("]", 1)) || append_simple(str, je.s.c_str, js->end()-(const char *) je.s.c_str)) goto js_error; /* Out of memory. */ @@ -2033,7 +2043,7 @@ String *Item_func_json_insert::val_str(String *str) v_to= (const char *) (je.s.c_str - je.sav_c_len); str->length(0); if (append_simple(str, js->ptr(), v_to - js->ptr()) || - str->append(", ", 2) || + (n_item > 0 && str->append(", ", 2)) || append_json_value(str, args[n_arg+1], &tmp_val) || append_simple(str, v_to, js->end() - v_to)) goto js_error; /* Out of memory. */ diff --git a/strings/json_lib.c b/strings/json_lib.c index 66b075a997b..18bdce2613f 100644 --- a/strings/json_lib.c +++ b/strings/json_lib.c @@ -1187,6 +1187,8 @@ int json_skip_key(json_engine_t *j) } +#define SKIPPED_STEP_MARK ((uint) ~0) + /* Current step of the patch matches the JSON construction. Now we should either stop the search or go to the next @@ -1195,24 +1197,48 @@ int json_skip_key(json_engine_t *j) static int handle_match(json_engine_t *je, json_path_t *p, json_path_step_t **p_cur_step, uint *array_counters) { + json_path_step_t *next_step= *p_cur_step + 1; + DBUG_ASSERT(*p_cur_step < p->last_step); if (json_read_value(je)) return 1; if (json_value_scalar(je)) + { + while (next_step->type == JSON_PATH_ARRAY && next_step->n_item == 0) + { + if (++next_step > p->last_step) + { + je->s.c_str= je->value_begin; + return 1; + } + } return 0; + } + + if (next_step->type == JSON_PATH_ARRAY && next_step->n_item == 0 && + je->value_type & JSON_VALUE_OBJECT) + { + do + { + array_counters[next_step - p->steps]= SKIPPED_STEP_MARK; + if (++next_step > p->last_step) + { + je->s.c_str= je->value_begin; + return 1; + } + } while (next_step->type == JSON_PATH_ARRAY && next_step->n_item == 0); + } - (*p_cur_step)++; - array_counters[*p_cur_step - p->steps]= 0; + + array_counters[next_step - p->steps]= 0; if ((int) je->value_type != - (int) ((*p_cur_step)->type & JSON_PATH_KEY_OR_ARRAY)) - { - (*p_cur_step)--; + (int) (next_step->type & JSON_PATH_KEY_OR_ARRAY)) return json_skip_level(je); - } + *p_cur_step= next_step; return 0; } @@ -1277,6 +1303,11 @@ int json_find_path(json_engine_t *je, json_skip_array_item(je); break; case JST_OBJ_END: + do + { + (*p_cur_step)--; + } while (array_counters[(*p_cur_step) - p->steps] == SKIPPED_STEP_MARK); + break; case JST_ARRAY_END: (*p_cur_step)--; break; |