Skip to content

Commit

Permalink
MDEV-30145: JSON_TABLE: allow to retrieve the key when iterating on JSON
Browse files Browse the repository at this point in the history
objects

Idea behind implementation:
We get the json object specified by the json path. Then, transform it into
key-value pairs by going over the json. Get each key-value pair
one-by-one and return the result.
  • Loading branch information
mariadb-RuchaDeodhar committed Jul 24, 2023
1 parent 2e09258 commit 15a7b6c
Show file tree
Hide file tree
Showing 5 changed files with 524 additions and 7 deletions.
192 changes: 190 additions & 2 deletions mysql-test/main/func_json.result
Expand Up @@ -671,8 +671,8 @@ DROP TABLE t1;
SELECT JSON_EXTRACT( '{"foo":"bar"}', '$[*].*' );
JSON_EXTRACT( '{"foo":"bar"}', '$[*].*' )
NULL
SELECT JSON_EXTRACT( '{"foo":"bar"}', '$[*]' );
JSON_EXTRACT( '{"foo":"bar"}', '$[*]' )
SELECT JSON_EXTRACT( '{"foo":"bar"}', '$[*]');
JSON_EXTRACT( '{"foo":"bar"}', '$[*]')
NULL
select JSON_EXTRACT('{"name":"value"}', '$.name') = 'value';
JSON_EXTRACT('{"name":"value"}', '$.name') = 'value'
Expand Down Expand Up @@ -4759,3 +4759,191 @@ SELECT JSON_SCHEMA_VALID(NULL, NULL);
JSON_SCHEMA_VALID(NULL, NULL)
NULL
# End of 11.1 test
# Beginning of 11.2
#
# MDEV-30145: JSON_TABLE: allow to retrieve the key when iterating on JSON objects
#
# Checking json table with NULL and empty json doc
SELECT jt.*
FROM JSON_TABLE(
NULL, '$[*]'
COLUMNS (k VARCHAR(20) PATH '$.key', v VARCHAR(20) PATH '$.value', id FOR ORDINALITY)) AS jt;
k v id
# With Empty and NULL
SELECT JSON_KEY_VALUE(NULL, '$.a');
JSON_KEY_VALUE(NULL, '$.a')
NULL
SELECT JSON_KEY_VALUE('', '$.a');
JSON_KEY_VALUE('', '$.a')
NULL
SELECT JSON_KEY_VALUE('[1,2,3]', '');
JSON_KEY_VALUE('[1,2,3]', '')
NULL
SELECT JSON_KEY_VALUE('[1,2,3]', NULL);
JSON_KEY_VALUE('[1,2,3]', NULL)
NULL
# With scalars
SELECT JSON_KEY_VALUE('2', '$');
JSON_KEY_VALUE('2', '$')
NULL
SELECT jt.*
FROM JSON_TABLE(
JSON_KEY_VALUE('2', '$'), '$[*]'
COLUMNS (k VARCHAR(20) PATH '$.key', v VARCHAR(20) PATH '$.value', id FOR ORDINALITY)) AS jt;
k v id
SELECT JSON_KEY_VALUE('"some_string"', '$');
JSON_KEY_VALUE('"some_string"', '$')
NULL
SELECT jt.*
FROM JSON_TABLE(
JSON_KEY_VALUE('"some_string"', '$'), '$[*]'
COLUMNS (k VARCHAR(20) PATH '$.key', v VARCHAR(20) PATH '$.value', id FOR ORDINALITY)) AS jt;
k v id
SELECT JSON_KEY_VALUE('"some_string"', '$.a');
JSON_KEY_VALUE('"some_string"', '$.a')
NULL
SELECT jt.*
FROM JSON_TABLE(
JSON_KEY_VALUE('"some_string"', '$.a'), '$[*]'
COLUMNS (k VARCHAR(20) PATH '$.key', v VARCHAR(20) PATH '$.value', id FOR ORDINALITY)) AS jt;
k v id
SELECT JSON_KEY_VALUE('"some_string"', '$[0]');
JSON_KEY_VALUE('"some_string"', '$[0]')
NULL
SELECT jt.*
FROM JSON_TABLE(
JSON_KEY_VALUE('"some_string"', '$[0]'), '$[*]'
COLUMNS (k VARCHAR(20) PATH '$.key', v VARCHAR(20) PATH '$.value', id FOR ORDINALITY)) AS jt;
k v id
SELECT JSON_KEY_VALUE('false', '$[0]');
JSON_KEY_VALUE('false', '$[0]')
NULL
SELECT jt.*
FROM JSON_TABLE(
JSON_KEY_VALUE('false', '$[0]'), '$[*]'
COLUMNS (k VARCHAR(20) PATH '$.key', v VARCHAR(20) PATH '$.value', id FOR ORDINALITY)) AS jt;
k v id
# With non-scalar
# With array
SELECT JSON_KEY_VALUE('[]', '[0]');
JSON_KEY_VALUE('[]', '[0]')
NULL
SELECT JSON_KEY_VALUE('[1, 2, 3]', '$[0]');
JSON_KEY_VALUE('[1, 2, 3]', '$[0]')
NULL
SELECT jt.*
FROM JSON_TABLE(
JSON_KEY_VALUE('[1, 2, 3]', '$[0]'), '$[*]'
COLUMNS (k VARCHAR(20) PATH '$.key', v VARCHAR(20) PATH '$.value', id FOR ORDINALITY)) AS jt;
k v id
SELECT JSON_KEY_VALUE('[[1, 2, 3], 2, 3]', '$[0]');
JSON_KEY_VALUE('[[1, 2, 3], 2, 3]', '$[0]')
NULL
SELECT jt.*
FROM JSON_TABLE(
JSON_KEY_VALUE('[[1, 2, 3], 2, 3]', '$[0]'), '$[*]'
COLUMNS (k VARCHAR(20) PATH '$.key', v VARCHAR(20) PATH '$.value', id FOR ORDINALITY)) AS jt;
k v id
SELECT JSON_KEY_VALUE('[[1, 2, 3], 2, 3]', '$[0].a');
JSON_KEY_VALUE('[[1, 2, 3], 2, 3]', '$[0].a')
NULL
SELECT jt.*
FROM JSON_TABLE(
JSON_KEY_VALUE('[[1, 2, 3], 2, 3]', '$[0].a'), '$[*]'
COLUMNS (k VARCHAR(20) PATH '$.key', v VARCHAR(20) PATH '$.value', id FOR ORDINALITY)) AS jt;
k v id
SELECT JSON_KEY_VALUE('[[1, 2, 3], 2, 3]', '$[0][1]');
JSON_KEY_VALUE('[[1, 2, 3], 2, 3]', '$[0][1]')
NULL
SELECT jt.*
FROM JSON_TABLE(
JSON_KEY_VALUE('[[1, 2, 3], 2, 3]', '$[0][1]'), '$[*]'
COLUMNS (k VARCHAR(20) PATH '$.key', v VARCHAR(20) PATH '$.value', id FOR ORDINALITY)) AS jt;
k v id
SELECT JSON_KEY_VALUE('[[1, {"key1":"val1", "key2":"val2"}, 3], 2, 3]', '$[0][1]');
JSON_KEY_VALUE('[[1, {"key1":"val1", "key2":"val2"}, 3], 2, 3]', '$[0][1]')
[{"key": "key1", "value": "val1"}, {"key": "key2", "value": "val2"}]
SELECT jt.*
FROM JSON_TABLE(
JSON_KEY_VALUE('[[1, {"key1":"val1", "key2":"val2"}, 3], 2, 3]', '$[0][1]'), '$[*]'
COLUMNS (k VARCHAR(20) PATH '$.key', v VARCHAR(20) PATH '$.value', id FOR ORDINALITY)) AS jt;
k v id
key1 val1 1
key2 val2 2
SELECT JSON_KEY_VALUE('[[1, {"key1":"val1", "key2":"val2"}, 3], 2, 3]', '$[0][1].key1');
JSON_KEY_VALUE('[[1, {"key1":"val1", "key2":"val2"}, 3], 2, 3]', '$[0][1].key1')
NULL
SELECT jt.*
FROM JSON_TABLE(
JSON_KEY_VALUE('[[1, {"key1":"val1", "key2":"val2"}, 3], 2, 3]', '$[0][1].key1'), '$[*]'
COLUMNS (k VARCHAR(20) PATH '$.key', v VARCHAR(20) PATH '$.value', id FOR ORDINALITY)) AS jt;
k v id
SELECT JSON_KEY_VALUE('[[1, [{"key1":"val1", "key2":"val2"}], 3], 2, 3]', '$[0][1]');
JSON_KEY_VALUE('[[1, [{"key1":"val1", "key2":"val2"}], 3], 2, 3]', '$[0][1]')
NULL
SELECT jt.*
FROM JSON_TABLE(
JSON_KEY_VALUE('[[1, [{"key1":"val1", "key2":"val2"}], 3], 2, 3]', '$[0][1]'), '$[*]'
COLUMNS (k VARCHAR(20) PATH '$.key', v VARCHAR(20) PATH '$.value', id FOR ORDINALITY)) AS jt;
k v id
SELECT JSON_KEY_VALUE('[[1, [{"key1":"val1", "key2":"val2"}], 3], 2, 3]', '$[0][1][0]');
JSON_KEY_VALUE('[[1, [{"key1":"val1", "key2":"val2"}], 3], 2, 3]', '$[0][1][0]')
[{"key": "key1", "value": "val1"}, {"key": "key2", "value": "val2"}]
SELECT jt.*
FROM JSON_TABLE(
JSON_KEY_VALUE('[[1, [{"key1":"val1", "key2":"val2"}], 3], 2, 3]', '$[0][1][0]'), '$[*]'
COLUMNS (k VARCHAR(20) PATH '$.key', v VARCHAR(20) PATH '$.value', id FOR ORDINALITY)) AS jt;
k v id
key1 val1 1
key2 val2 2
# With object
SELECT JSON_KEY_VALUE('{}', '$.key1');
JSON_KEY_VALUE('{}', '$.key1')
NULL
SELECT JSON_KEY_VALUE('{"key1":"val1", "key2":"val2"}', '$');
JSON_KEY_VALUE('{"key1":"val1", "key2":"val2"}', '$')
[{"key": "key1", "value": "val1"}, {"key": "key2", "value": "val2"}]
SELECT jt.*
FROM JSON_TABLE(
JSON_KEY_VALUE('{"key1":"val1", "key2":"val2"}', '$'), '$[*]'
COLUMNS (k VARCHAR(11) PATH '$.key', v VARCHAR(5) PATH '$.value', id FOR ORDINALITY)) AS jt;
k v id
key1 val1 1
key2 val2 2
SELECT JSON_KEY_VALUE('{"key1":"val1", "key2":"val2"}', '$.key1');
JSON_KEY_VALUE('{"key1":"val1", "key2":"val2"}', '$.key1')
NULL
SELECT jt.*
FROM JSON_TABLE(
JSON_KEY_VALUE('{"key1":"val1", "key2":"val2"}', '$.key1'), '$[*]'
COLUMNS (k VARCHAR(11) PATH '$.key', v VARCHAR(5) PATH '$.value', id FOR ORDINALITY)) AS jt;
k v id
SELECT JSON_KEY_VALUE('{"key1":{"a":1, "b":2}, "key2":"val2"}', '$.key1');
JSON_KEY_VALUE('{"key1":{"a":1, "b":2}, "key2":"val2"}', '$.key1')
[{"key": "a", "value": 1}, {"key": "b", "value": 2}]
SELECT jt.*
FROM JSON_TABLE(
JSON_KEY_VALUE('{"key1":{"a":1, "b":2}, "key2":"val2"}', '$.key1'), '$[*]'
COLUMNS (k VARCHAR(11) PATH '$.key', v VARCHAR(5) PATH '$.value', id FOR ORDINALITY)) AS jt;
k v id
a 1 1
b 2 2
SELECT JSON_KEY_VALUE('{"key1":{"a":1, "b": [1,2,3, {"some_key":"some_val", "c":3}]}, "key2":"val2"}', '$.key1.b[3]');
JSON_KEY_VALUE('{"key1":{"a":1, "b": [1,2,3, {"some_key":"some_val", "c":3}]}, "key2":"val2"}', '$.key1.b[3]')
[{"key": "some_key", "value": "some_val"}, {"key": "c", "value": 3}]
SELECT jt.*
FROM JSON_TABLE(
JSON_KEY_VALUE('{"key1":{"a":1, "b": [1,2,3, {"some_key":"some_val", "c":3}]}, "key2":"val2"}', '$.key1.b[3]'), '$[*]'
COLUMNS (k VARCHAR(20) PATH '$.key', v VARCHAR(20) PATH '$.value', id FOR ORDINALITY)) AS jt;
k v id
some_key some_val 1
c 3 2
SELECT JSON_KEY_VALUE('{"key1":{"a":1, "b": [1,2,3, {"some_key":"some_val", "c":3}]}, "key2":"val2"}', '$.key1.b[0]');
JSON_KEY_VALUE('{"key1":{"a":1, "b": [1,2,3, {"some_key":"some_val", "c":3}]}, "key2":"val2"}', '$.key1.b[0]')
NULL
SELECT jt.*
FROM JSON_TABLE(
JSON_KEY_VALUE('{"key1":{"a":1, "b": [1,2,3, {"some_key":"some_val", "c":3}]}, "key2":"val2"}', '$.key1.b[0]'), '$[*]'
COLUMNS (k VARCHAR(20) PATH '$.key', v VARCHAR(20) PATH '$.value', id FOR ORDINALITY)) AS jt;
k v id
# End of 11.2 test
145 changes: 144 additions & 1 deletion mysql-test/main/func_json.test
Expand Up @@ -338,7 +338,7 @@ DROP TABLE t1;
# MDEV-12324 Wrong result (phantom array value) on JSON_EXTRACT.
#
SELECT JSON_EXTRACT( '{"foo":"bar"}', '$[*].*' );
SELECT JSON_EXTRACT( '{"foo":"bar"}', '$[*]' );
SELECT JSON_EXTRACT( '{"foo":"bar"}', '$[*]');

#
# MDEV-12604 Comparison of JSON_EXTRACT result differs with Mysql.
Expand Down Expand Up @@ -3640,3 +3640,146 @@ SELECT JSON_SCHEMA_VALID(NULL, '{}');
SELECT JSON_SCHEMA_VALID(NULL, NULL);

--echo # End of 11.1 test

--echo # Beginning of 11.2

--echo #
--echo # MDEV-30145: JSON_TABLE: allow to retrieve the key when iterating on JSON objects
--echo #

--echo # Checking json table with NULL and empty json doc

SELECT jt.*
FROM JSON_TABLE(
NULL, '$[*]'
COLUMNS (k VARCHAR(20) PATH '$.key', v VARCHAR(20) PATH '$.value', id FOR ORDINALITY)) AS jt;

--echo # With Empty and NULL

SELECT JSON_KEY_VALUE(NULL, '$.a');
SELECT JSON_KEY_VALUE('', '$.a');
SELECT JSON_KEY_VALUE('[1,2,3]', '');
SELECT JSON_KEY_VALUE('[1,2,3]', NULL);

--echo # With scalars

SELECT JSON_KEY_VALUE('2', '$');
SELECT jt.*
FROM JSON_TABLE(
JSON_KEY_VALUE('2', '$'), '$[*]'
COLUMNS (k VARCHAR(20) PATH '$.key', v VARCHAR(20) PATH '$.value', id FOR ORDINALITY)) AS jt;

SELECT JSON_KEY_VALUE('"some_string"', '$');
SELECT jt.*
FROM JSON_TABLE(
JSON_KEY_VALUE('"some_string"', '$'), '$[*]'
COLUMNS (k VARCHAR(20) PATH '$.key', v VARCHAR(20) PATH '$.value', id FOR ORDINALITY)) AS jt;

SELECT JSON_KEY_VALUE('"some_string"', '$.a');
SELECT jt.*
FROM JSON_TABLE(
JSON_KEY_VALUE('"some_string"', '$.a'), '$[*]'
COLUMNS (k VARCHAR(20) PATH '$.key', v VARCHAR(20) PATH '$.value', id FOR ORDINALITY)) AS jt;

SELECT JSON_KEY_VALUE('"some_string"', '$[0]');
SELECT jt.*
FROM JSON_TABLE(
JSON_KEY_VALUE('"some_string"', '$[0]'), '$[*]'
COLUMNS (k VARCHAR(20) PATH '$.key', v VARCHAR(20) PATH '$.value', id FOR ORDINALITY)) AS jt;

SELECT JSON_KEY_VALUE('false', '$[0]');
SELECT jt.*
FROM JSON_TABLE(
JSON_KEY_VALUE('false', '$[0]'), '$[*]'
COLUMNS (k VARCHAR(20) PATH '$.key', v VARCHAR(20) PATH '$.value', id FOR ORDINALITY)) AS jt;

--echo # With non-scalar

--echo # With array

SELECT JSON_KEY_VALUE('[]', '[0]');


SELECT JSON_KEY_VALUE('[1, 2, 3]', '$[0]');
SELECT jt.*
FROM JSON_TABLE(
JSON_KEY_VALUE('[1, 2, 3]', '$[0]'), '$[*]'
COLUMNS (k VARCHAR(20) PATH '$.key', v VARCHAR(20) PATH '$.value', id FOR ORDINALITY)) AS jt;

SELECT JSON_KEY_VALUE('[[1, 2, 3], 2, 3]', '$[0]');
SELECT jt.*
FROM JSON_TABLE(
JSON_KEY_VALUE('[[1, 2, 3], 2, 3]', '$[0]'), '$[*]'
COLUMNS (k VARCHAR(20) PATH '$.key', v VARCHAR(20) PATH '$.value', id FOR ORDINALITY)) AS jt;

SELECT JSON_KEY_VALUE('[[1, 2, 3], 2, 3]', '$[0].a');
SELECT jt.*
FROM JSON_TABLE(
JSON_KEY_VALUE('[[1, 2, 3], 2, 3]', '$[0].a'), '$[*]'
COLUMNS (k VARCHAR(20) PATH '$.key', v VARCHAR(20) PATH '$.value', id FOR ORDINALITY)) AS jt;

SELECT JSON_KEY_VALUE('[[1, 2, 3], 2, 3]', '$[0][1]');
SELECT jt.*
FROM JSON_TABLE(
JSON_KEY_VALUE('[[1, 2, 3], 2, 3]', '$[0][1]'), '$[*]'
COLUMNS (k VARCHAR(20) PATH '$.key', v VARCHAR(20) PATH '$.value', id FOR ORDINALITY)) AS jt;

SELECT JSON_KEY_VALUE('[[1, {"key1":"val1", "key2":"val2"}, 3], 2, 3]', '$[0][1]');
SELECT jt.*
FROM JSON_TABLE(
JSON_KEY_VALUE('[[1, {"key1":"val1", "key2":"val2"}, 3], 2, 3]', '$[0][1]'), '$[*]'
COLUMNS (k VARCHAR(20) PATH '$.key', v VARCHAR(20) PATH '$.value', id FOR ORDINALITY)) AS jt;

SELECT JSON_KEY_VALUE('[[1, {"key1":"val1", "key2":"val2"}, 3], 2, 3]', '$[0][1].key1');
SELECT jt.*
FROM JSON_TABLE(
JSON_KEY_VALUE('[[1, {"key1":"val1", "key2":"val2"}, 3], 2, 3]', '$[0][1].key1'), '$[*]'
COLUMNS (k VARCHAR(20) PATH '$.key', v VARCHAR(20) PATH '$.value', id FOR ORDINALITY)) AS jt;

SELECT JSON_KEY_VALUE('[[1, [{"key1":"val1", "key2":"val2"}], 3], 2, 3]', '$[0][1]');
SELECT jt.*
FROM JSON_TABLE(
JSON_KEY_VALUE('[[1, [{"key1":"val1", "key2":"val2"}], 3], 2, 3]', '$[0][1]'), '$[*]'
COLUMNS (k VARCHAR(20) PATH '$.key', v VARCHAR(20) PATH '$.value', id FOR ORDINALITY)) AS jt;

SELECT JSON_KEY_VALUE('[[1, [{"key1":"val1", "key2":"val2"}], 3], 2, 3]', '$[0][1][0]');
SELECT jt.*
FROM JSON_TABLE(
JSON_KEY_VALUE('[[1, [{"key1":"val1", "key2":"val2"}], 3], 2, 3]', '$[0][1][0]'), '$[*]'
COLUMNS (k VARCHAR(20) PATH '$.key', v VARCHAR(20) PATH '$.value', id FOR ORDINALITY)) AS jt;

--echo # With object

SELECT JSON_KEY_VALUE('{}', '$.key1');

SELECT JSON_KEY_VALUE('{"key1":"val1", "key2":"val2"}', '$');
SELECT jt.*
FROM JSON_TABLE(
JSON_KEY_VALUE('{"key1":"val1", "key2":"val2"}', '$'), '$[*]'
COLUMNS (k VARCHAR(11) PATH '$.key', v VARCHAR(5) PATH '$.value', id FOR ORDINALITY)) AS jt;

SELECT JSON_KEY_VALUE('{"key1":"val1", "key2":"val2"}', '$.key1');
SELECT jt.*
FROM JSON_TABLE(
JSON_KEY_VALUE('{"key1":"val1", "key2":"val2"}', '$.key1'), '$[*]'
COLUMNS (k VARCHAR(11) PATH '$.key', v VARCHAR(5) PATH '$.value', id FOR ORDINALITY)) AS jt;

SELECT JSON_KEY_VALUE('{"key1":{"a":1, "b":2}, "key2":"val2"}', '$.key1');
SELECT jt.*
FROM JSON_TABLE(
JSON_KEY_VALUE('{"key1":{"a":1, "b":2}, "key2":"val2"}', '$.key1'), '$[*]'
COLUMNS (k VARCHAR(11) PATH '$.key', v VARCHAR(5) PATH '$.value', id FOR ORDINALITY)) AS jt;

SELECT JSON_KEY_VALUE('{"key1":{"a":1, "b": [1,2,3, {"some_key":"some_val", "c":3}]}, "key2":"val2"}', '$.key1.b[3]');
SELECT jt.*
FROM JSON_TABLE(
JSON_KEY_VALUE('{"key1":{"a":1, "b": [1,2,3, {"some_key":"some_val", "c":3}]}, "key2":"val2"}', '$.key1.b[3]'), '$[*]'
COLUMNS (k VARCHAR(20) PATH '$.key', v VARCHAR(20) PATH '$.value', id FOR ORDINALITY)) AS jt;

SELECT JSON_KEY_VALUE('{"key1":{"a":1, "b": [1,2,3, {"some_key":"some_val", "c":3}]}, "key2":"val2"}', '$.key1.b[0]');
SELECT jt.*
FROM JSON_TABLE(
JSON_KEY_VALUE('{"key1":{"a":1, "b": [1,2,3, {"some_key":"some_val", "c":3}]}, "key2":"val2"}', '$.key1.b[0]'), '$[*]'
COLUMNS (k VARCHAR(20) PATH '$.key', v VARCHAR(20) PATH '$.value', id FOR ORDINALITY)) AS jt;

--echo # End of 11.2 test

0 comments on commit 15a7b6c

Please sign in to comment.