diff options
author | Rucha Deodhar <rucha.deodhar@mariadb.com> | 2022-03-05 01:03:49 +0530 |
---|---|---|
committer | Rucha Deodhar <rucha.deodhar@mariadb.com> | 2022-04-15 01:02:44 +0530 |
commit | c781cefd8afc0fa5840456c96f5a0c37cac2edfa (patch) | |
tree | db5008c4f763e4d954f7f9fefa0270f6bc3effbd | |
parent | abe971219456b1f41923c06ff715fd4efeb02850 (diff) | |
download | mariadb-git-c781cefd8afc0fa5840456c96f5a0c37cac2edfa.tar.gz |
MDEV-27911: Implement range notation for json path
Range can be thought about in similar manner as wildcard (*) where
more than one elements are processed. To implement range notation, extended
json parser to parse the 'to' keyword and added JSON_PATH_ARRAY_RANGE for
path type. If there is 'to' keyword then use JSON_PATH_ARRAY range for
path type along with existing type.
This new integer to store the end index of range is n_item_end.
When there is 'to' keyword, store the integer in n_item_end else store in
n_item.
-rw-r--r-- | include/json_lib.h | 4 | ||||
-rw-r--r-- | mysql-test/main/func_json.result | 189 | ||||
-rw-r--r-- | mysql-test/main/func_json.test | 161 | ||||
-rw-r--r-- | mysql-test/suite/json/r/json_no_table.result | 56 | ||||
-rw-r--r-- | sql/item_jsonfunc.cc | 6 | ||||
-rw-r--r-- | sql/json_table.cc | 3 | ||||
-rw-r--r-- | sql/share/errmsg-utf8.txt | 2 | ||||
-rw-r--r-- | strings/json_lib.c | 147 |
8 files changed, 480 insertions, 88 deletions
diff --git a/include/json_lib.h b/include/json_lib.h index 41ab88b06ce..1f12487d7e8 100644 --- a/include/json_lib.h +++ b/include/json_lib.h @@ -84,7 +84,8 @@ enum json_path_step_types JSON_PATH_KEY_DOUBLEWILD= 1+8, JSON_PATH_ARRAY_WILD= 2+4, JSON_PATH_ARRAY_DOUBLEWILD= 2+8, - JSON_PATH_NEGATIVE_INDEX= 16 + JSON_PATH_NEGATIVE_INDEX= 16, + JSON_PATH_ARRAY_RANGE= 32 }; @@ -95,6 +96,7 @@ typedef struct st_json_path_step_t const uchar *key; /* Pointer to the beginning of the key. */ const uchar *key_end; /* Pointer to the end of the key. */ int n_item; /* Item number in an array. No meaning for the key step. */ + int n_item_end; /* Last index of the range. */ } json_path_step_t; diff --git a/mysql-test/main/func_json.result b/mysql-test/main/func_json.result index 18a700607ab..1707c59bf19 100644 --- a/mysql-test/main/func_json.result +++ b/mysql-test/main/func_json.result @@ -2029,5 +2029,194 @@ SELECT JSON_VALUE(@json,'$.x[0]'); JSON_VALUE(@json,'$.x[0]') 0 # +# MDEV-27911: Implement range notation for json path +# +SET @json= '[ + [1, {"key1": "value1"}, 3], + [false, 5, 6], + [7, 8, [9, {"key2": 2}, 11]], + [15, 1.34, [14], ["string1", [16, {"key1":[1,2,3,[4,5,6]]}, 18]]], + [19, 20], + 21, 22 + ]'; +SELECT JSON_EXISTS(@json, '$[3][3][-2 to last]'); +JSON_EXISTS(@json, '$[3][3][-2 to last]') +1 +SET @json= '[ + [1, {"key1": "value1"}, 3], + [false, 5, 6], + [7, 8, [9, {"key2": 2}, 11]], + [15, 1.34, [14], ["string1", [16, {"key1":[1,2,3,[4,5,6]]}, 18]]], + [19, 20], + 21, 22 + ]'; +SELECT JSON_SEARCH(@json, 'one', '12', NULL, '$[3][0 to 3]'); +JSON_SEARCH(@json, 'one', '12', NULL, '$[3][0 to 3]') +NULL +SET @json= '[ + [1, {"key1": "value1"}, 3], + [false, 5, 6], + [7, 8, [9, {"key2": 2}, 11]], + [12, 1.34, [14], ["string1", [16, {"key1":[1,2,3,[4,5,6]]}, 18]]], + [19, 20] + ]'; +SELECT JSON_VALUE(@json, '$[0][1 to 2].key1'); +JSON_VALUE(@json, '$[0][1 to 2].key1') +value1 +SET @json='{ + "A": [0, + [1, 2, 3], + [4, 5, 6], + "seven", + 0.8, + true, + false, + "eleven", + [12, [13, 14], {"key1":"value1"},[15]], + true], + "B": {"C": 1}, + "D": 2 + }'; +SELECT JSON_QUERY(@json, '$.A[-2][-3 to -1]'); +JSON_QUERY(@json, '$.A[-2][-3 to -1]') +[13, 14] +SET @json= '[ + [1, {"key1": "value1"}, 3], + [false, 5, 6], + [7, 8, [9, {"key2": 2}, 11]], + [15, 1.34, [14], ["string1", [16, {"key1":[1,2,3,[4,5,6]]}, 18]]], + [19, 20], + 21, 22 + ]'; +SELECT JSON_EXTRACT(@json, '$[0 to 3][2]'); +JSON_EXTRACT(@json, '$[0 to 3][2]') +[3, 6, [9, {"key2": 2}, 11], [14]] +SELECT JSON_EXTRACT(@json, '$[3][3][last-1 to last]'); +JSON_EXTRACT(@json, '$[3][3][last-1 to last]') +["string1", [16, {"key1": [1, 2, 3, [4, 5, 6]]}, 18]] +SELECT JSON_EXTRACT(@json, '$[3][3][-2 to -1]'); +JSON_EXTRACT(@json, '$[3][3][-2 to -1]') +["string1", [16, {"key1": [1, 2, 3, [4, 5, 6]]}, 18]] +# Checking errors +SET @json= '[ + [1, {"key1": "value1"}, 3], + [false, 5, 6], + [7, 8, [9, {"key2": 2}, 11]], + [15, 1.34, [14], ["string1", [16, {"key1":[1,2,3,[4,5,6]]}, 18]]], + [19, 20], + 21, 22 + ]'; +SELECT JSON_CONTAINS_PATH(@json,'one', '$[3][0 to 3]'); +JSON_CONTAINS_PATH(@json,'one', '$[3][0 to 3]') +1 +SET @json= '[ + [1, {"key1": "value1"}, 3], + [false, 5, 6], + [7, 8, [9, {"key2": 2}, 11]], + [15, 1.34, [14], ["string1", [16, {"key1":[1,2,3,[4,5,6]]}, 18]]], + [19, 20], + 21, 22 + ]'; +SELECT JSON_CONTAINS(@json, '$[3][0 to 3]'); +JSON_CONTAINS(@json, '$[3][0 to 3]') +NULL +Warnings: +Warning 4038 Syntax error in JSON text in argument 2 to function 'json_contains' at position 1 +SET @json='{ + "A": [0, + [1, 2, 3], + [4, 5, 6], + "seven", + 0.8, + true, + false, + "eleven", + [12, 13, {"key1":"value1"},[15]], + true], + "B": {"C": 1}, + "D": 2 + }'; +SELECT JSON_ARRAY_INSERT(@json, '$.A[0 to last-1]', 5); +JSON_ARRAY_INSERT(@json, '$.A[0 to last-1]', 5) +NULL +Warnings: +Warning 4044 Wildcards or range in JSON path not allowed in argument 2 to function 'json_array_insert' +SET @json='{ + "A": [0, + [1, 2, 3], + [4, 5, 6], + "seven", + 0.8, + true, + false, + "eleven", + [12, 13, {"key1":"value1"},[15]], + true], + "B": {"C": 1}, + "D": 2 + }'; +SELECT JSON_ARRAY_APPEND(@json, '$.A[*]', 7); +JSON_ARRAY_APPEND(@json, '$.A[*]', 7) +NULL +Warnings: +Warning 4044 Wildcards or range in JSON path not allowed in argument 2 to function 'json_array_append' +SET @json= '[ + [1, {"key1": "value1"}, 3], + [false, 5, 6], + [7, 8, [9, {"key2": 2}, 11]], + [12, 1.34, [14], ["string1", [16, {"key1":[1,2,3,[4,5,6]]}, 18]]], + [19, 20] + ]'; +SELECT JSON_SET(@json, '$[0][1 to 2].key1', 1); +JSON_SET(@json, '$[0][1 to 2].key1', 1) +NULL +Warnings: +Warning 4044 Wildcards or range in JSON path not allowed in argument 2 to function 'json_set' +SET @json= '[ + [1, {"key1": "value1"}, 3], + [false, 5, 6], + [7, 8, [9, {"key2": 2}, 11]], + [15, 1.34, [14], ["string1", [16, {"key1":[1,2,3,[4,5,6]]}, 18]]], + [19, 20], + 21, 22 + ]'; +SELECT JSON_REPLACE(@json, '$[1][last-2 to last]', 4); +JSON_REPLACE(@json, '$[1][last-2 to last]', 4) +NULL +Warnings: +Warning 4044 Wildcards or range in JSON path not allowed in argument 2 to function 'json_replace' +SET @json= '[ + [1, {"key1": "value1"}, 3], + [false, 5, 6], + [7, 8, [9, {"key2": 2}, 11]], + [15, 1.34, [14], ["string1", [16, {"key1":[1,2,3,[4,5,6]]}, 18]]], + [19, 20], + 21, 22 + ]'; +SELECT JSON_REMOVE(@json, '$[1][-6 to last-2]'); +JSON_REMOVE(@json, '$[1][-6 to last-2]') +NULL +Warnings: +Warning 4044 Wildcards or range in JSON path not allowed in argument 2 to function 'json_remove' +SET @json='{ + "A": [0, + [1, 2, 3], + [4, 5, 6], + "seven", + 0.8, + true, + false, + "eleven", + [12, [13, 14], {"key1":"value1"},[15]], + true], + "B": {"C": 1}, + "D": 2 + }'; +SELECT JSON_KEYS(@json, '$.A[8][1 to 3]'); +JSON_KEYS(@json, '$.A[8][1 to 3]') +NULL +Warnings: +Warning 4044 Wildcards or range in JSON path not allowed in argument 2 to function 'json_keys' +# # End of 10.9 Test # diff --git a/mysql-test/main/func_json.test b/mysql-test/main/func_json.test index 34a4b30b0ab..2a06313e5c7 100644 --- a/mysql-test/main/func_json.test +++ b/mysql-test/main/func_json.test @@ -1316,6 +1316,167 @@ SELECT JSON_VALUE(@json,'$.x[last-0]'); SELECT JSON_VALUE(@json,'$.x[-0]'); SELECT JSON_VALUE(@json,'$.x[0]'); + +--echo # +--echo # MDEV-27911: Implement range notation for json path +--echo # + +SET @json= '[ + [1, {"key1": "value1"}, 3], + [false, 5, 6], + [7, 8, [9, {"key2": 2}, 11]], + [15, 1.34, [14], ["string1", [16, {"key1":[1,2,3,[4,5,6]]}, 18]]], + [19, 20], + 21, 22 + ]'; +SELECT JSON_EXISTS(@json, '$[3][3][-2 to last]'); + +SET @json= '[ + [1, {"key1": "value1"}, 3], + [false, 5, 6], + [7, 8, [9, {"key2": 2}, 11]], + [15, 1.34, [14], ["string1", [16, {"key1":[1,2,3,[4,5,6]]}, 18]]], + [19, 20], + 21, 22 + ]'; +SELECT JSON_SEARCH(@json, 'one', '12', NULL, '$[3][0 to 3]'); + +SET @json= '[ + [1, {"key1": "value1"}, 3], + [false, 5, 6], + [7, 8, [9, {"key2": 2}, 11]], + [12, 1.34, [14], ["string1", [16, {"key1":[1,2,3,[4,5,6]]}, 18]]], + [19, 20] + ]'; +SELECT JSON_VALUE(@json, '$[0][1 to 2].key1'); + +SET @json='{ + "A": [0, + [1, 2, 3], + [4, 5, 6], + "seven", + 0.8, + true, + false, + "eleven", + [12, [13, 14], {"key1":"value1"},[15]], + true], + "B": {"C": 1}, + "D": 2 + }'; +SELECT JSON_QUERY(@json, '$.A[-2][-3 to -1]'); + +SET @json= '[ + [1, {"key1": "value1"}, 3], + [false, 5, 6], + [7, 8, [9, {"key2": 2}, 11]], + [15, 1.34, [14], ["string1", [16, {"key1":[1,2,3,[4,5,6]]}, 18]]], + [19, 20], + 21, 22 + ]'; +SELECT JSON_EXTRACT(@json, '$[0 to 3][2]'); +SELECT JSON_EXTRACT(@json, '$[3][3][last-1 to last]'); +SELECT JSON_EXTRACT(@json, '$[3][3][-2 to -1]'); + +--echo # Checking errors + +SET @json= '[ + [1, {"key1": "value1"}, 3], + [false, 5, 6], + [7, 8, [9, {"key2": 2}, 11]], + [15, 1.34, [14], ["string1", [16, {"key1":[1,2,3,[4,5,6]]}, 18]]], + [19, 20], + 21, 22 + ]'; +SELECT JSON_CONTAINS_PATH(@json,'one', '$[3][0 to 3]'); + +SET @json= '[ + [1, {"key1": "value1"}, 3], + [false, 5, 6], + [7, 8, [9, {"key2": 2}, 11]], + [15, 1.34, [14], ["string1", [16, {"key1":[1,2,3,[4,5,6]]}, 18]]], + [19, 20], + 21, 22 + ]'; +SELECT JSON_CONTAINS(@json, '$[3][0 to 3]'); + +SET @json='{ + "A": [0, + [1, 2, 3], + [4, 5, 6], + "seven", + 0.8, + true, + false, + "eleven", + [12, 13, {"key1":"value1"},[15]], + true], + "B": {"C": 1}, + "D": 2 + }'; +SELECT JSON_ARRAY_INSERT(@json, '$.A[0 to last-1]', 5); + +SET @json='{ + "A": [0, + [1, 2, 3], + [4, 5, 6], + "seven", + 0.8, + true, + false, + "eleven", + [12, 13, {"key1":"value1"},[15]], + true], + "B": {"C": 1}, + "D": 2 + }'; +SELECT JSON_ARRAY_APPEND(@json, '$.A[*]', 7); + +SET @json= '[ + [1, {"key1": "value1"}, 3], + [false, 5, 6], + [7, 8, [9, {"key2": 2}, 11]], + [12, 1.34, [14], ["string1", [16, {"key1":[1,2,3,[4,5,6]]}, 18]]], + [19, 20] + ]'; +SELECT JSON_SET(@json, '$[0][1 to 2].key1', 1); + +SET @json= '[ + [1, {"key1": "value1"}, 3], + [false, 5, 6], + [7, 8, [9, {"key2": 2}, 11]], + [15, 1.34, [14], ["string1", [16, {"key1":[1,2,3,[4,5,6]]}, 18]]], + [19, 20], + 21, 22 + ]'; +SELECT JSON_REPLACE(@json, '$[1][last-2 to last]', 4); + +SET @json= '[ + [1, {"key1": "value1"}, 3], + [false, 5, 6], + [7, 8, [9, {"key2": 2}, 11]], + [15, 1.34, [14], ["string1", [16, {"key1":[1,2,3,[4,5,6]]}, 18]]], + [19, 20], + 21, 22 + ]'; +SELECT JSON_REMOVE(@json, '$[1][-6 to last-2]'); + +SET @json='{ + "A": [0, + [1, 2, 3], + [4, 5, 6], + "seven", + 0.8, + true, + false, + "eleven", + [12, [13, 14], {"key1":"value1"},[15]], + true], + "B": {"C": 1}, + "D": 2 + }'; +SELECT JSON_KEYS(@json, '$.A[8][1 to 3]'); + --echo # --echo # End of 10.9 Test --echo # diff --git a/mysql-test/suite/json/r/json_no_table.result b/mysql-test/suite/json/r/json_no_table.result index 6784fe6da32..e9af1fc68c8 100644 --- a/mysql-test/suite/json/r/json_no_table.result +++ b/mysql-test/suite/json/r/json_no_table.result @@ -402,7 +402,7 @@ select json_length( 'true', '$.*' ); json_length( 'true', '$.*' ) NULL Warnings: -Warning 4044 Wildcards in JSON path not allowed in argument 2 to function 'json_length' +Warning 4044 Wildcards or range in JSON path not allowed in argument 2 to function 'json_length' # wildcards not allowed in path expressions for this function error ER_INVALID_JSON_PATH_WILDCARD @@ -410,7 +410,7 @@ select json_length( 'true', '$.foo**.bar' ); json_length( 'true', '$.foo**.bar' ) NULL Warnings: -Warning 4044 Wildcards in JSON path not allowed in argument 2 to function 'json_length' +Warning 4044 Wildcards or range in JSON path not allowed in argument 2 to function 'json_length' select json_length( '[ 1, [ 2, 3, 4 ], 5 ]', '$[0]' ); json_length( '[ 1, [ 2, 3, 4 ], 5 ]', '$[0]' ) 1 @@ -691,25 +691,25 @@ select json_remove( '[ 1, 2, 3 ]', '$[*]' ); json_remove( '[ 1, 2, 3 ]', '$[*]' ) NULL Warnings: -Warning 4044 Wildcards in JSON path not allowed in argument 2 to function 'json_remove' +Warning 4044 Wildcards or range in JSON path not allowed in argument 2 to function 'json_remove' error ER_INVALID_JSON_PATH_WILDCARD select json_remove( '[ 1, 2, 3 ]', '$**[2]' ); json_remove( '[ 1, 2, 3 ]', '$**[2]' ) NULL Warnings: -Warning 4044 Wildcards in JSON path not allowed in argument 2 to function 'json_remove' +Warning 4044 Wildcards or range in JSON path not allowed in argument 2 to function 'json_remove' error ER_INVALID_JSON_PATH_WILDCARD select json_remove( '[ 1, 2, 3 ]', '$[2]', '$[*]' ); json_remove( '[ 1, 2, 3 ]', '$[2]', '$[*]' ) NULL Warnings: -Warning 4044 Wildcards in JSON path not allowed in argument 3 to function 'json_remove' +Warning 4044 Wildcards or range in JSON path not allowed in argument 3 to function 'json_remove' error ER_INVALID_JSON_PATH_WILDCARD select json_remove( '[ 1, 2, 3 ]', '$[2]', '$**[2]' ); json_remove( '[ 1, 2, 3 ]', '$[2]', '$**[2]' ) NULL Warnings: -Warning 4044 Wildcards in JSON path not allowed in argument 3 to function 'json_remove' +Warning 4044 Wildcards or range in JSON path not allowed in argument 3 to function 'json_remove' select json_remove( '[ 1, 2, 3 ]', '$[0]' ); json_remove( '[ 1, 2, 3 ]', '$[0]' ) [2, 3] @@ -730,7 +730,7 @@ select json_remove( '[ { "a": { "a": true } } ]', '$**.a' ); json_remove( '[ { "a": { "a": true } } ]', '$**.a' ) NULL Warnings: -Warning 4044 Wildcards in JSON path not allowed in argument 2 to function 'json_remove' +Warning 4044 Wildcards or range in JSON path not allowed in argument 2 to function 'json_remove' select json_remove( '[ { "a": true }, { "b": false }, { "c": null }, { "a": null } ]', '$[0].a', '$[2].c' ); json_remove( '[ { "a": true }, { "b": false }, { "c": null }, { "a": null } ]', '$[0].a', '$[2].c' ) [{}, {"b": false}, {}, {"a": null}] @@ -739,7 +739,7 @@ select json_remove( '[ { "a": true }, { "b": [ { "c": { "a": true } } ] }, { "c json_remove( '[ { "a": true }, { "b": [ { "c": { "a": true } } ] }, { "c": null }, { "a": null } ]', '$**.a' ) NULL Warnings: -Warning 4044 Wildcards in JSON path not allowed in argument 2 to function 'json_remove' +Warning 4044 Wildcards or range in JSON path not allowed in argument 2 to function 'json_remove' select json_remove( '{"id": 123, "name": "systemQA", "array": [1, 2, 3]}', '$[0]' ); json_remove( '{"id": 123, "name": "systemQA", "array": [1, 2, 3]}', '$[0]' ) {"id": 123, "name": "systemQA", "array": [1, 2, 3]} @@ -1210,7 +1210,7 @@ select json_keys('{"a": 1, "b": {"e": "foo", "b": 3}}', '$.*.b'); json_keys('{"a": 1, "b": {"e": "foo", "b": 3}}', '$.*.b') NULL Warnings: -Warning 4044 Wildcards in JSON path not allowed in argument 2 to function 'json_keys' +Warning 4044 Wildcards or range in JSON path not allowed in argument 2 to function 'json_keys' # returns [ "a", "b" ] SELECT JSON_KEYS('{ "a" : "foo", "b" : [ true, { "c" : "123" } ] }'); JSON_KEYS('{ "a" : "foo", "b" : [ true, { "c" : "123" } ] }') @@ -1637,7 +1637,7 @@ select json_array_append(json_compact('{"a": {"b": [3]}}'), '$**[0]', 6); json_array_append(json_compact('{"a": {"b": [3]}}'), '$**[0]', 6) NULL Warnings: -Warning 4044 Wildcards in JSON path not allowed in argument 2 to function 'json_array_append' +Warning 4044 Wildcards or range in JSON path not allowed in argument 2 to function 'json_array_append' # Auto-wrapping, since because the paths identify scalars. # should return {"a": "foo", "b": ["bar", 4], "c": ["wibble", "grape"]} SELECT JSON_ARRAY_APPEND('{"a": "foo", "b": "bar", "c": "wibble"}', @@ -1668,13 +1668,13 @@ select json_array_append( '[[], [], []]', '$[*]', 3, '$[*]', 4); json_array_append( '[[], [], []]', '$[*]', 3, '$[*]', 4) NULL Warnings: -Warning 4044 Wildcards in JSON path not allowed in argument 2 to function 'json_array_append' +Warning 4044 Wildcards or range in JSON path not allowed in argument 2 to function 'json_array_append' error ER_INVALID_JSON_PATH_WILDCARD select json_array_append( '[[], "not array", []]', '$[*]', 3, '$[*]', 4); json_array_append( '[[], "not array", []]', '$[*]', 3, '$[*]', 4) NULL Warnings: -Warning 4044 Wildcards in JSON path not allowed in argument 2 to function 'json_array_append' +Warning 4044 Wildcards or range in JSON path not allowed in argument 2 to function 'json_array_append' SELECT JSON_ARRAY_APPEND ( '{ "a" : "foo", "b" : "bar", "c" : "wibble" }', @@ -1775,73 +1775,73 @@ select json_insert(json_compact('{"a": [1], "b": 2}'), '$.*[1]', 6); json_insert(json_compact('{"a": [1], "b": 2}'), '$.*[1]', 6) NULL Warnings: -Warning 4044 Wildcards in JSON path not allowed in argument 2 to function 'json_insert' +Warning 4044 Wildcards or range in JSON path not allowed in argument 2 to function 'json_insert' error ER_INVALID_JSON_PATH_WILDCARD select json_insert(json_compact('{"a": 1, "b": 2}'), '$.*[1]', 6); json_insert(json_compact('{"a": 1, "b": 2}'), '$.*[1]', 6) NULL Warnings: -Warning 4044 Wildcards in JSON path not allowed in argument 2 to function 'json_insert' +Warning 4044 Wildcards or range in JSON path not allowed in argument 2 to function 'json_insert' error ER_INVALID_JSON_PATH_WILDCARD select json_insert(json_compact('{"a": {"b": 3}}'), '$.a.*[1]', 6); json_insert(json_compact('{"a": {"b": 3}}'), '$.a.*[1]', 6) NULL Warnings: -Warning 4044 Wildcards in JSON path not allowed in argument 2 to function 'json_insert' +Warning 4044 Wildcards or range in JSON path not allowed in argument 2 to function 'json_insert' error ER_INVALID_JSON_PATH_WILDCARD select json_insert(json_compact('{"a": {"b": [3]}}'), '$.a.*[1]', 6); json_insert(json_compact('{"a": {"b": [3]}}'), '$.a.*[1]', 6) NULL Warnings: -Warning 4044 Wildcards in JSON path not allowed in argument 2 to function 'json_insert' +Warning 4044 Wildcards or range in JSON path not allowed in argument 2 to function 'json_insert' error ER_INVALID_JSON_PATH_WILDCARD select json_insert(json_compact('{"a": {"b": 3}}'), '$**[1]', 6); json_insert(json_compact('{"a": {"b": 3}}'), '$**[1]', 6) NULL Warnings: -Warning 4044 Wildcards in JSON path not allowed in argument 2 to function 'json_insert' +Warning 4044 Wildcards or range in JSON path not allowed in argument 2 to function 'json_insert' error ER_INVALID_JSON_PATH_WILDCARD select json_insert(json_compact('{"a": {"b": [3]}}'), '$**[1]', 6); json_insert(json_compact('{"a": {"b": [3]}}'), '$**[1]', 6) NULL Warnings: -Warning 4044 Wildcards in JSON path not allowed in argument 2 to function 'json_insert' +Warning 4044 Wildcards or range in JSON path not allowed in argument 2 to function 'json_insert' error ER_INVALID_JSON_PATH_WILDCARD select json_insert(json_compact('[1]'), '$[*][1]', 6); json_insert(json_compact('[1]'), '$[*][1]', 6) NULL Warnings: -Warning 4044 Wildcards in JSON path not allowed in argument 2 to function 'json_insert' +Warning 4044 Wildcards or range in JSON path not allowed in argument 2 to function 'json_insert' error ER_INVALID_JSON_PATH_WILDCARD select json_insert(json_compact('[1]'), '$**[1]', 6); json_insert(json_compact('[1]'), '$**[1]', 6) NULL Warnings: -Warning 4044 Wildcards in JSON path not allowed in argument 2 to function 'json_insert' +Warning 4044 Wildcards or range in JSON path not allowed in argument 2 to function 'json_insert' error ER_INVALID_JSON_PATH_WILDCARD select json_insert(json_compact('[1, [2], 3]'), '$[*][1]', 6); json_insert(json_compact('[1, [2], 3]'), '$[*][1]', 6) NULL Warnings: -Warning 4044 Wildcards in JSON path not allowed in argument 2 to function 'json_insert' +Warning 4044 Wildcards or range in JSON path not allowed in argument 2 to function 'json_insert' error ER_INVALID_JSON_PATH_WILDCARD select json_insert(json_compact('[1, [2], 3]'), '$**[1]', 6); json_insert(json_compact('[1, [2], 3]'), '$**[1]', 6) NULL Warnings: -Warning 4044 Wildcards in JSON path not allowed in argument 2 to function 'json_insert' +Warning 4044 Wildcards or range in JSON path not allowed in argument 2 to function 'json_insert' error ER_INVALID_JSON_PATH_WILDCARD select json_insert(json_compact('[[1]]'), '$[*][1]', 6); json_insert(json_compact('[[1]]'), '$[*][1]', 6) NULL Warnings: -Warning 4044 Wildcards in JSON path not allowed in argument 2 to function 'json_insert' +Warning 4044 Wildcards or range in JSON path not allowed in argument 2 to function 'json_insert' error ER_INVALID_JSON_PATH_WILDCARD select json_insert(json_compact('[[1]]'), '$**[1]', 6); json_insert(json_compact('[[1]]'), '$**[1]', 6) NULL Warnings: -Warning 4044 Wildcards in JSON path not allowed in argument 2 to function 'json_insert' +Warning 4044 Wildcards or range in JSON path not allowed in argument 2 to function 'json_insert' select json_insert(json_compact('{"a": 3}'), '$[1]', 6); json_insert(json_compact('{"a": 3}'), '$[1]', 6) [{"a": 3}, 6] @@ -2053,19 +2053,19 @@ select json_insert('[]', '$.a.*[1]', 6); json_insert('[]', '$.a.*[1]', 6) NULL Warnings: -Warning 4044 Wildcards in JSON path not allowed in argument 2 to function 'json_insert' +Warning 4044 Wildcards or range in JSON path not allowed in argument 2 to function 'json_insert' error ER_INVALID_JSON_PATH_WILDCARD select json_insert('[]', '$**[1]', 6); json_insert('[]', '$**[1]', 6) NULL Warnings: -Warning 4044 Wildcards in JSON path not allowed in argument 2 to function 'json_insert' +Warning 4044 Wildcards or range in JSON path not allowed in argument 2 to function 'json_insert' error ER_INVALID_JSON_PATH_WILDCARD select json_insert('[]', '$[*][1]', 6); json_insert('[]', '$[*][1]', 6) NULL Warnings: -Warning 4044 Wildcards in JSON path not allowed in argument 2 to function 'json_insert' +Warning 4044 Wildcards or range in JSON path not allowed in argument 2 to function 'json_insert' select json_array_insert( '[ 1, 2, 3 ]', '$[1]', true, '$[1]', false ); json_array_insert( '[ 1, 2, 3 ]', '$[1]', true, '$[1]', false ) [1, false, true, 2, 3] @@ -2154,7 +2154,7 @@ select json_set(json_compact('{"a": {"b": [3]}}'), '$**[1]', 6); json_set(json_compact('{"a": {"b": [3]}}'), '$**[1]', 6) NULL Warnings: -Warning 4044 Wildcards in JSON path not allowed in argument 2 to function 'json_set' +Warning 4044 Wildcards or range in JSON path not allowed in argument 2 to function 'json_set' SELECT JSON_SET('{ "a" : "foo", "b" : [ 1, 2, 3 ] }', '$.a', JSON_OBJECT()); diff --git a/sql/item_jsonfunc.cc b/sql/item_jsonfunc.cc index e7d4e247999..d2d4fc087c9 100644 --- a/sql/item_jsonfunc.cc +++ b/sql/item_jsonfunc.cc @@ -374,7 +374,8 @@ static int path_setup_nwc(json_path_t *p, CHARSET_INFO *i_cs, { if (!json_path_setup(p, i_cs, str, end)) { - if ((p->types_used & (JSON_PATH_WILD | JSON_PATH_DOUBLE_WILD)) == 0) + if ((p->types_used & (JSON_PATH_WILD | JSON_PATH_DOUBLE_WILD | + JSON_PATH_ARRAY_RANGE)) == 0) return 0; p->s.error= NO_WILDCARD_ALLOWED; } @@ -862,7 +863,8 @@ String *Item_func_json_extract::read_json(String *str, } possible_multiple_values= arg_count > 2 || - (paths[0].p.types_used & (JSON_PATH_WILD | JSON_PATH_DOUBLE_WILD)); + (paths[0].p.types_used & (JSON_PATH_WILD | JSON_PATH_DOUBLE_WILD | + JSON_PATH_ARRAY_RANGE)); *type= possible_multiple_values ? JSON_VALUE_ARRAY : JSON_VALUE_NULL; diff --git a/sql/json_table.cc b/sql/json_table.cc index e48646ace3c..e2f90aa2a9a 100644 --- a/sql/json_table.cc +++ b/sql/json_table.cc @@ -561,7 +561,8 @@ int ha_json_table::fill_column_values(THD *thd, uchar * buf, uchar *pos) more matches for it in json and report an error if so. */ if (jc->m_path.types_used & - (JSON_PATH_WILD | JSON_PATH_DOUBLE_WILD) && + (JSON_PATH_WILD | JSON_PATH_DOUBLE_WILD | + JSON_PATH_ARRAY_RANGE) && (json_scan_next(&je) || !json_find_path(&je, &jc->m_path, &cur_step, array_counters))) diff --git a/sql/share/errmsg-utf8.txt b/sql/share/errmsg-utf8.txt index 652b0e548ee..5a4ee62e53f 100644 --- a/sql/share/errmsg-utf8.txt +++ b/sql/share/errmsg-utf8.txt @@ -8420,7 +8420,7 @@ ER_JSON_PATH_DEPTH eng "Limit of %d on JSON path depth is reached in argument %d to function '%s' at position %d" spa "El límite de %d en profundidad de ruta JSON se ha alcanzado en argumento %d a función '%s' en la posición %d" ER_JSON_PATH_NO_WILDCARD - eng "Wildcards in JSON path not allowed in argument %d to function '%s'" + eng "Wildcards or range in JSON path not allowed in argument %d to function '%s'" spa "Comodines en ruta JSON no permitidos en argumento %d a función '%s'" ER_JSON_PATH_ARRAY eng "JSON path should end with an array identifier in argument %d to function '%s'" diff --git a/strings/json_lib.c b/strings/json_lib.c index 602a57cc03b..70a155ec696 100644 --- a/strings/json_lib.c +++ b/strings/json_lib.c @@ -983,6 +983,7 @@ enum json_path_chr_classes { P_USD, /* $ */ P_ASTER, /* * */ P_LSQRB, /* [ */ + P_T, /* t (for to) */ P_RSQRB, /* ] */ P_POINT, /* . */ P_NEG, /* hyphen (for negative index in path) */ @@ -1013,12 +1014,12 @@ static enum json_path_chr_classes json_path_chr_map[128] = { P_ETC, P_ETC, P_ETC, P_ETC, P_ETC, P_ETC, P_ETC, P_ETC, P_ETC, P_ETC, P_ETC, P_ETC, P_L, P_ETC, P_ETC, P_ETC, - P_ETC, P_ETC, P_S, P_ETC, P_ETC, P_ETC, P_ETC, P_ETC, + P_ETC, P_ETC, P_S, P_ETC, P_T, P_ETC, P_ETC, P_ETC, P_ETC, P_ETC, P_ETC, P_LSQRB, P_BKSL, P_RSQRB, P_ETC, P_ETC, P_ETC, P_ETC, P_ETC, P_ETC, P_ETC, P_ETC, P_ETC, P_ETC, P_ETC, P_ETC, P_ETC, P_ETC, P_L, P_ETC, P_ETC, P_ETC, - P_ETC, P_ETC, P_S, P_ETC, P_ETC, P_ETC, P_ETC, P_ETC, + P_ETC, P_ETC, P_S, P_ETC, P_T, P_ETC, P_ETC, P_ETC, P_ETC, P_ETC, P_ETC, P_ETC, P_ETC, P_ETC, P_ETC, P_ETC }; @@ -1042,6 +1043,7 @@ enum json_path_states { PS_KEYX, /* Key started with quote ("). */ PS_KNMX, /* Parse quoted key name. */ PS_LAST, /* Parse 'last' keyword */ + PS_T, /* Parse 'to' keyword. */ N_PATH_STATES, /* Below are states that aren't in the transitions table. */ PS_SCT, /* Parse the 'strict' keyword. */ PS_EKY, /* '.' after the keyname so next step is the key. */ @@ -1057,71 +1059,75 @@ enum json_path_states { static int json_path_transitions[N_PATH_STATES][N_PATH_CLASSES]= { /* - EOS $, * [ ] . - 0 - 1..9 L S SPACE \ " ETC + EOS $, * [ to ] . - + 0 1..9 L S SPACE \ " ETC ERR BAD */ -/* GO */ { JE_EOS, PS_PT, JE_SYN, JE_SYN, JE_SYN, JE_SYN, JE_SYN, JE_SYN, - JE_SYN, PS_LAX, PS_SCT, PS_GO, JE_SYN, JE_SYN, JE_SYN, +/* GO */ { JE_EOS, PS_PT, JE_SYN, JE_SYN, JE_SYN, JE_SYN, JE_SYN, JE_SYN, + JE_SYN, JE_SYN, PS_LAX, PS_SCT, PS_GO, JE_SYN, JE_SYN, JE_SYN, JE_NOT_JSON_CHR, JE_BAD_CHR}, /* LAX */ { JE_EOS, JE_SYN, JE_SYN, JE_SYN, JE_SYN, JE_SYN, JE_SYN, JE_SYN, - JE_SYN, PS_LAX, JE_SYN, PS_GO, JE_SYN, JE_SYN, JE_SYN, + JE_SYN, JE_SYN, PS_LAX, JE_SYN, PS_GO, JE_SYN, JE_SYN, JE_SYN, JE_NOT_JSON_CHR, JE_BAD_CHR}, -/* PT */ { PS_OK, JE_SYN, PS_AST, PS_AR, JE_SYN, PS_KEY, JE_SYN, JE_SYN, JE_SYN, - JE_SYN, JE_SYN, JE_SYN, JE_SYN, JE_SYN, JE_SYN, +/* PT */ { PS_OK, JE_SYN, PS_AST, PS_AR, JE_SYN, JE_SYN, PS_KEY, JE_SYN, + JE_SYN, JE_SYN, JE_SYN, JE_SYN, JE_SYN, JE_SYN, JE_SYN, JE_SYN, JE_NOT_JSON_CHR, JE_BAD_CHR}, -/* AR */ { JE_EOS, JE_SYN, PS_AWD, JE_SYN, JE_SYN, JE_SYN, PS_NEG,PS_Z, - PS_INT, PS_LAST, JE_SYN, PS_SAR, JE_SYN, JE_SYN, JE_SYN, +/* AR */ { JE_EOS, JE_SYN, PS_AWD, JE_SYN, JE_SYN, JE_SYN, JE_SYN, PS_NEG, + PS_Z, PS_INT, PS_LAST, JE_SYN, PS_SAR, JE_SYN, JE_SYN, JE_SYN, JE_NOT_JSON_CHR, JE_BAD_CHR}, -/* SAR */ { JE_EOS, JE_SYN, PS_AWD, JE_SYN, PS_PT, JE_SYN,JE_SYN, PS_Z, - PS_INT, PS_LAST, JE_SYN, PS_SAR, JE_SYN, JE_SYN, JE_SYN, +/* SAR */ { JE_EOS, JE_SYN, PS_AWD, JE_SYN, JE_SYN, PS_PT, JE_SYN, JE_SYN, + PS_Z, PS_INT, PS_LAST, JE_SYN, PS_SAR, JE_SYN, JE_SYN, JE_SYN, JE_NOT_JSON_CHR, JE_BAD_CHR}, -/* AWD */ { JE_EOS, JE_SYN, JE_SYN, JE_SYN, PS_PT, JE_SYN,JE_SYN, JE_SYN, - JE_SYN, JE_SYN, JE_SYN, PS_AS, JE_SYN, JE_SYN, JE_SYN, +/* AWD */ { JE_EOS, JE_SYN, JE_SYN, JE_SYN, JE_SYN, PS_PT, JE_SYN, JE_SYN, + JE_SYN, JE_SYN, JE_SYN, JE_SYN, PS_AS, JE_SYN, JE_SYN, JE_SYN, JE_NOT_JSON_CHR, JE_BAD_CHR}, -/* NEG */ { JE_EOS, JE_SYN, JE_SYN, JE_SYN, JE_SYN, JE_SYN, JE_SYN, PS_INT, - PS_INT, JE_SYN, JE_SYN, JE_SYN, JE_SYN, JE_SYN, JE_SYN, +/* NEG */ { JE_EOS, JE_SYN, JE_SYN, JE_SYN, JE_SYN, JE_SYN, JE_SYN, JE_SYN, + PS_INT, PS_INT, JE_SYN, JE_SYN, JE_SYN, JE_SYN, JE_SYN, JE_SYN, JE_NOT_JSON_CHR, JE_BAD_CHR}, -/* Z */ { JE_EOS, JE_SYN, JE_SYN, JE_SYN, PS_PT, JE_SYN,JE_SYN, JE_SYN, - JE_SYN, JE_SYN, JE_SYN, PS_AS, JE_SYN, JE_SYN, JE_SYN, +/* Z */ { JE_EOS, JE_SYN, JE_SYN, JE_SYN, JE_SYN, PS_PT, JE_SYN, JE_SYN, + JE_SYN, JE_SYN, JE_SYN, JE_SYN, PS_AS, JE_SYN, JE_SYN, JE_SYN, JE_NOT_JSON_CHR, JE_BAD_CHR}, -/* INT */ { JE_EOS, JE_SYN, JE_SYN, JE_SYN, PS_PT, JE_SYN,JE_SYN, PS_INT, - PS_INT, JE_SYN, JE_SYN, PS_AS, JE_SYN, JE_SYN, JE_SYN, +/* INT */ { JE_EOS, JE_SYN, JE_SYN, JE_SYN, JE_SYN, PS_PT, JE_SYN, JE_SYN, + PS_INT, PS_INT, JE_SYN, JE_SYN, PS_AS, JE_SYN, JE_SYN, JE_SYN, JE_NOT_JSON_CHR, JE_BAD_CHR}, -/* AS */ { JE_EOS, JE_SYN, JE_SYN, JE_SYN, PS_PT, JE_SYN, JE_SYN, JE_SYN, - JE_SYN, JE_SYN, PS_AS, JE_SYN, JE_SYN, JE_SYN, +/* AS */ { JE_EOS, JE_SYN, JE_SYN, JE_SYN, PS_T, PS_PT, JE_SYN, PS_NEG, + JE_SYN, PS_INT, PS_LAST, PS_AS, JE_SYN, JE_SYN, JE_SYN, JE_NOT_JSON_CHR, JE_BAD_CHR}, -/* KEY */ { JE_EOS, PS_KNM, PS_KWD, JE_SYN, PS_KNM, JE_SYN,JE_SYN, PS_KNM, - PS_KNM, PS_KNM, PS_KNM, PS_KNM, JE_SYN, PS_KEYX, PS_KNM, +/* KEY */ { JE_EOS, PS_KNM, PS_KWD, JE_SYN, PS_KNM, PS_KNM, JE_SYN, JE_SYN, + PS_KNM, PS_KNM, PS_KNM, PS_KNM, PS_KNM, JE_SYN, PS_KEYX, PS_KNM, JE_NOT_JSON_CHR, JE_BAD_CHR}, -/* KNM */ { PS_KOK, PS_KNM, PS_AST, PS_EAR, PS_KNM, PS_EKY, JE_SYN,PS_KNM, - PS_KNM, PS_KNM, PS_KNM, PS_KNM, PS_ESC, PS_KNM, PS_KNM, +/* KNM */ { PS_KOK, PS_KNM, PS_AST, PS_EAR, PS_KNM, PS_KNM, PS_EKY, JE_SYN, + PS_KNM, PS_KNM, PS_KNM, PS_KNM, PS_KNM, PS_ESC, PS_KNM, PS_KNM, JE_NOT_JSON_CHR, JE_BAD_CHR}, -/* KWD */ { PS_OK, JE_SYN, JE_SYN, PS_AR, JE_SYN, PS_EKY, JE_SYN,JE_SYN, - JE_SYN, JE_SYN, JE_SYN, JE_SYN, JE_SYN, JE_SYN, JE_SYN, +/* KWD */ { PS_OK, JE_SYN, JE_SYN, PS_AR, JE_SYN, JE_SYN, PS_EKY, JE_SYN, + JE_SYN, JE_SYN, JE_SYN, JE_SYN, JE_SYN, JE_SYN, JE_SYN, JE_SYN, JE_NOT_JSON_CHR, JE_BAD_CHR}, -/* AST */ { JE_SYN, JE_SYN, PS_DWD, JE_SYN, JE_SYN, JE_SYN, JE_SYN,JE_SYN, - JE_SYN, JE_SYN, JE_SYN, JE_SYN, JE_SYN, JE_SYN, JE_SYN, +/* AST */ { JE_SYN, JE_SYN, PS_DWD, JE_SYN, JE_SYN, JE_SYN, JE_SYN, JE_SYN, + JE_SYN, JE_SYN, JE_SYN, JE_SYN, JE_SYN, JE_SYN, JE_SYN, JE_SYN, JE_NOT_JSON_CHR, JE_BAD_CHR}, -/* DWD */ { JE_SYN, JE_SYN, PS_AST, PS_AR, JE_SYN, PS_KEY,JE_SYN, JE_SYN, JE_SYN, - JE_SYN, JE_SYN, JE_SYN, JE_SYN, JE_SYN, JE_SYN, +/* DWD */ { JE_SYN, JE_SYN, PS_AST, PS_AR, JE_SYN, JE_SYN, PS_KEY, JE_SYN, + JE_SYN, JE_SYN, JE_SYN, JE_SYN, JE_SYN, JE_SYN, JE_SYN, JE_SYN, JE_NOT_JSON_CHR, JE_BAD_CHR}, -/* KEYX*/ { JE_EOS, PS_KNMX, PS_KNMX, PS_KNMX, PS_KNMX, PS_KNMX, JE_SYN,PS_KNMX, - PS_KNMX,PS_KNMX, PS_KNMX, PS_KNMX, PS_ESCX, PS_EKYX, PS_KNMX, +/* KEYX*/ { JE_EOS, PS_KNMX, PS_KNMX, PS_KNMX, JE_SYN, PS_KNMX, PS_KNMX, JE_SYN, + PS_KNMX, PS_KNMX, PS_KNMX, PS_KNMX, PS_KNMX, PS_ESCX, PS_EKYX, PS_KNMX, JE_NOT_JSON_CHR, JE_BAD_CHR}, -/* KNMX */{ JE_EOS, PS_KNMX, PS_KNMX, PS_KNMX, PS_KNMX, PS_KNMX, JE_SYN,PS_KNMX, - PS_KNMX, PS_KNMX, PS_KNMX, PS_KNMX,PS_ESCX, PS_EKYX, PS_KNMX, +/* KNMX */{ JE_EOS, PS_KNMX, PS_KNMX, PS_KNMX, PS_KNMX, PS_KNMX, PS_KNMX, JE_SYN, + PS_KNMX, PS_KNMX, PS_KNMX, PS_KNMX, PS_KNMX, PS_ESCX, PS_EKYX, PS_KNMX, JE_NOT_JSON_CHR, JE_BAD_CHR}, -/* LAST */{ JE_SYN, JE_SYN, JE_SYN, JE_SYN, PS_PT, JE_SYN, PS_NEG, JE_SYN, - JE_SYN, JE_SYN, JE_SYN, PS_AS, JE_SYN, JE_SYN, JE_SYN, - JE_SYN, JE_BAD_CHR} +/* LAST */{ JE_SYN, JE_SYN, JE_SYN, JE_SYN, JE_SYN, PS_PT, JE_SYN, PS_NEG, + JE_SYN, JE_SYN, JE_SYN, JE_SYN, PS_AS, JE_SYN, JE_SYN, JE_SYN, + JE_SYN, JE_BAD_CHR}, +/* T */ { JE_SYN, JE_SYN, JE_SYN, JE_SYN, JE_SYN, PS_PT, JE_SYN, PS_NEG, + JE_SYN, JE_SYN, JE_SYN, JE_SYN, PS_AS, JE_SYN, JE_SYN, JE_SYN, + JE_SYN, JE_BAD_CHR}, }; int json_path_setup(json_path_t *p, CHARSET_INFO *i_cs, const uchar *str, const uchar *end) { - int c_len, t_next, state= PS_GO, is_negative_index= 0, is_last= 0, prev_value=0; + int c_len, t_next, state= PS_GO, is_negative_index= 0, is_last= 0, + prev_value=0, is_to= 0, *cur_val; enum json_path_step_types double_wildcard= JSON_PATH_KEY_NULL; json_string_setup(&p->s, i_cs, str, end); @@ -1161,19 +1167,21 @@ int json_path_setup(json_path_t *p, p->types_used|= JSON_PATH_WILD; continue; case PS_INT: + cur_val= is_to ? &(p->last_step->n_item_end) : + &(p->last_step->n_item); if (is_last) { prev_value*= 10; prev_value-= p->s.c_next - '0'; - p->last_step->n_item= -1 + prev_value; + *cur_val= -1 + prev_value; } else { - p->last_step->n_item*= 10; + (*cur_val)*= 10; if (is_negative_index) - p->last_step->n_item-= p->s.c_next - '0'; + *cur_val-= p->s.c_next - '0'; else - p->last_step->n_item+= p->s.c_next - '0'; + *cur_val+= p->s.c_next - '0'; } continue; case PS_EKYX: @@ -1186,7 +1194,10 @@ int json_path_setup(json_path_t *p, /* fall through */ case PS_KEY: p->last_step++; + is_to= 0; + prev_value= 0; is_negative_index= 0; + is_last= 0; if (p->last_step - p->steps >= JSON_DEPTH_LIMIT) return p->s.error= JE_DEPTH; p->types_used|= p->last_step->type= JSON_PATH_KEY | double_wildcard; @@ -1202,13 +1213,14 @@ int json_path_setup(json_path_t *p, case PS_AR: p->last_step++; is_last= 0; + is_to= 0; + prev_value= 0; + is_negative_index= 0; if (p->last_step - p->steps >= JSON_DEPTH_LIMIT) return p->s.error= JE_DEPTH; p->types_used|= p->last_step->type= JSON_PATH_ARRAY | double_wildcard; double_wildcard= JSON_PATH_KEY_NULL; p->last_step->n_item= 0; - prev_value= 0; - is_negative_index= 0; continue; case PS_ESC: if (json_handle_esc(&p->s)) @@ -1230,15 +1242,27 @@ int json_path_setup(json_path_t *p, case PS_NEG: p->types_used|= JSON_PATH_NEGATIVE_INDEX; is_negative_index= 1; - if (is_last) - p->last_step->n_item= 0; continue; case PS_LAST: if ((p->s.error= skip_string_verbatim(&p->s, "ast"))) return 1; p->types_used|= JSON_PATH_NEGATIVE_INDEX; is_last= 1; - p->last_step->n_item= -1; + if (is_to) + p->last_step->n_item_end= -1; + else + p->last_step->n_item= -1; + continue; + case PS_T: + if ((p->s.error= skip_string_verbatim(&p->s, "o"))) + return 1; + is_to= 1; + is_negative_index= 0; + is_last= 0; + prev_value= 0; + p->last_step->n_item_end= 0; + p->last_step->type|= JSON_PATH_ARRAY_RANGE; + p->types_used|= JSON_PATH_ARRAY_RANGE; continue; }; } while (state != PS_OK); @@ -1420,7 +1444,7 @@ int json_find_path(json_engine_t *je, break; case JST_VALUE: DBUG_ASSERT(cur_step->type & JSON_PATH_ARRAY); - if (cur_step->type & JSON_PATH_WILD || + if (cur_step->type & (JSON_PATH_WILD | JSON_PATH_ARRAY_RANGE) || cur_step->n_item == array_counters[cur_step - p->steps]++) { /* Array item matches. */ @@ -1855,14 +1879,27 @@ int json_path_parts_compare( DBUG_ASSERT((b->type & (JSON_PATH_WILD | JSON_PATH_DOUBLE_WILD)) == 0); - if (a->type & JSON_PATH_ARRAY) { if (b->type & JSON_PATH_ARRAY) { - if ((a->type & JSON_PATH_WILD) || - (a->n_item >= 0 ? a->n_item == b->n_item : - a->n_item == b->n_item - array_sizes[b-temp_b])) + int res= 0, corrected_n_item_a= 0, corrected_n_item_end_a= 0; + if (array_sizes) + { + corrected_n_item_a= a->n_item < 0 ? array_sizes[b-temp_b] + + a->n_item : + a->n_item; + corrected_n_item_end_a= a->n_item_end < 0 ? array_sizes[b-temp_b] + + a->n_item_end : + a->n_item_end; + } + if (a->type & JSON_PATH_ARRAY_RANGE) + res= b->n_item >= corrected_n_item_a && + b->n_item <= corrected_n_item_end_a; + else + res= corrected_n_item_a == b->n_item; + + if ((a->type & JSON_PATH_WILD) || res) goto step_fits; goto step_failed; } |