diff options
-rw-r--r-- | include/json_lib.h | 24 | ||||
-rw-r--r-- | mysql-test/r/func_json.result | 6 | ||||
-rw-r--r-- | mysql-test/t/func_json.test | 2 | ||||
-rw-r--r-- | sql/item_jsonfunc.cc | 5 | ||||
-rw-r--r-- | strings/json_lib.c | 23 |
5 files changed, 36 insertions, 24 deletions
diff --git a/include/json_lib.h b/include/json_lib.h index b26d865fd36..ce7f27317bc 100644 --- a/include/json_lib.h +++ b/include/json_lib.h @@ -295,13 +295,27 @@ int json_read_value(json_engine_t *j); int json_skip_key(json_engine_t *j); +typedef const int *json_level_t; + +/* + json_skip_to_level() makes parser quickly get out of nested + loops and arrays. It is used when we're not interested in what is + there in the rest of these structures. + The 'level' should be remembered in advance. + json_level_t level= json_get_level(j); + .... // getting into the nested JSON structures + json_skip_to_level(j, level); +*/ +#define json_get_level(j) (j->stack_p) + +int json_skip_to_level(json_engine_t *j, json_level_t level); + /* - json_skip_level() makes parser quickly skip the JSON content - to the end of the current object or array. - It is used when we're not interested in the rest of an array - or the rest of the keys of an object. + json_skip_level() works as above with just current structre. + So it gets to the end of the current JSON array or object. */ -int json_skip_level(json_engine_t *j); +#define json_skip_level(json_engine) \ + json_skip_to_level((json_engine), (json_engine)->stack_p) #define json_skip_array_item json_skip_key diff --git a/mysql-test/r/func_json.result b/mysql-test/r/func_json.result index 99e1e95372f..6466b1a2dc2 100644 --- a/mysql-test/r/func_json.result +++ b/mysql-test/r/func_json.result @@ -143,6 +143,12 @@ json_contains('[1, {"a":1}]', '{}') select json_contains('[1, {"a":1}]', '{"a":1}'); json_contains('[1, {"a":1}]', '{"a":1}') 1 +select json_contains('[{"abc":"def", "def":"abc"}]', '["foo","bar"]'); +json_contains('[{"abc":"def", "def":"abc"}]', '["foo","bar"]') +0 +select json_contains('[{"abc":"def", "def":"abc"}, "bar"]', '["bar", {}]'); +json_contains('[{"abc":"def", "def":"abc"}, "bar"]', '["bar", {}]') +1 select json_contains_path('{"key1":1, "key2":[2,3]}', "oNE", "$.key2[1]"); json_contains_path('{"key1":1, "key2":[2,3]}', "oNE", "$.key2[1]") 1 diff --git a/mysql-test/t/func_json.test b/mysql-test/t/func_json.test index 8685d82b635..8e36a3ed18b 100644 --- a/mysql-test/t/func_json.test +++ b/mysql-test/t/func_json.test @@ -53,6 +53,8 @@ select json_contains('{"b":[1,2], "a":1}', '{"a":1, "b":2}'); select json_contains('{"a":1}', '{}'); select json_contains('[1, {"a":1}]', '{}'); select json_contains('[1, {"a":1}]', '{"a":1}'); +select json_contains('[{"abc":"def", "def":"abc"}]', '["foo","bar"]'); +select json_contains('[{"abc":"def", "def":"abc"}, "bar"]', '["bar", {}]'); select json_contains_path('{"key1":1, "key2":[2,3]}', "oNE", "$.key2[1]"); select json_contains_path('{"key1":1, "key2":[2,3]}', "oNE", "$.key2[10]"); diff --git a/sql/item_jsonfunc.cc b/sql/item_jsonfunc.cc index 7bf2283dd53..9535feb0d8e 100644 --- a/sql/item_jsonfunc.cc +++ b/sql/item_jsonfunc.cc @@ -796,17 +796,20 @@ static int check_contains(json_engine_t *js, json_engine_t *value) { while (json_scan_next(js) == 0 && js->state != JST_ARRAY_END) { + json_level_t c_level; DBUG_ASSERT(js->state == JST_VALUE); if (json_read_value(js)) return FALSE; + c_level= json_value_scalar(js) ? NULL : json_get_level(js); if (check_contains(js, value)) { if (json_skip_level(js)) return FALSE; return TRUE; } - if (value->s.error || js->s.error) + if (value->s.error || js->s.error || + (c_level && json_skip_to_level(js, c_level))) return FALSE; } return FALSE; diff --git a/strings/json_lib.c b/strings/json_lib.c index acca7eb0739..a93200cd4dd 100644 --- a/strings/json_lib.c +++ b/strings/json_lib.c @@ -1158,25 +1158,12 @@ int json_path_setup(json_path_t *p, } -int json_skip_level(json_engine_t *j) +int json_skip_to_level(json_engine_t *j, json_level_t level) { - int ct= 0; - - while (json_scan_next(j) == 0) - { - switch (j->state) { - case JST_OBJ_START: - case JST_ARRAY_START: - ct++; - break; - case JST_OBJ_END: - case JST_ARRAY_END: - if (ct == 0) - return 0; - ct--; - break; - } - } + do { + if (j->stack_p < level) + return 0; + } while (json_scan_next(j) == 0); return 1; } |