Commit c781cefd authored by Rucha Deodhar's avatar Rucha Deodhar

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.
parent abe97121
......@@ -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;
......
......@@ -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
#
......@@ -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 #
......@@ -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;
......
......@@ -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)))
......
......@@ -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'"
......
This diff is collapsed.
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