Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
315 changes: 315 additions & 0 deletions mysql-test/main/json_operators.result
Original file line number Diff line number Diff line change
@@ -0,0 +1,315 @@
#
# MDEV-13594: Support for -> and ->> JSON operators
#
# 1. Basic Extraction with ->
SELECT '{"a": 1, "b": "text"}'->'$.a' AS int_val,
'{"a": 1, "b": "text"}'->'$.b' AS str_val;
int_val str_val
1 "text"
# 2. Unquoted Extraction with ->>
SELECT '{"a": 1, "b": "text"}'->> '$.a' AS int_val,
'{"a": 1, "b": "text"}'->> '$.b' AS str_val;
int_val str_val
1 text
# 3. Chaining Operators
# Should support nested extraction
SELECT '{"a": {"b": {"c": 42}}}'->'$.a'->'$.b'->'$.c' AS chained_arrow,
'{"a": {"b": {"c": 42}}}'->'$.a'->'$.b'->>'$.c' AS chained_unquoted;
chained_arrow chained_unquoted
42 42
# 4. Operator Precedence
# -> and ->> bind tighter than arithmetic operators
SELECT '{"a": 5}'->'$.a' + 1 AS arrow_plus_one;
arrow_plus_one
6
SELECT '{"a": 5}'->> '$.a' + 1 AS unquoted_arrow_plus_one;
unquoted_arrow_plus_one
6
SELECT '{"a": 5}'->'$.a' * 2 AS arrow_times_two;
arrow_times_two
10
# 5. Table Integration
CREATE TABLE t1 (
id INT PRIMARY KEY,
data JSON
);
INSERT INTO t1 VALUES
(1, '{"name": "Alice", "meta": {"age": 25, "city": "London"}}'),
(2, '{"name": "Bob", "meta": {"age": 30, "city": "Paris"}}'),
(3, '{"name": "Charlie", "meta": null}');
# Usage in SELECT list
SELECT id, data->'$.name', data->>'$.meta.city' FROM t1;
id data->'$.name' data->>'$.meta.city'
1 "Alice" London
2 "Bob" Paris
3 "Charlie" NULL
# Usage in WHERE clause
SELECT data->>'$.name' FROM t1 WHERE data->'$.meta.age' > 25;
data->>'$.name'
Bob
# Usage in ORDER BY
SELECT data->>'$.name' FROM t1 ORDER BY data->'$.meta.age' DESC;
data->>'$.name'
Bob
Alice
Charlie
DROP TABLE t1;
# 6. Edge Cases: Invalid JSON and Paths
# Invalid JSON text returns a warning; result is NULL
SELECT '{"a": 1'->'$.a';
'{"a": 1'->'$.a'
NULL
Warnings:
Warning 4037 Unexpected end of JSON text in argument 1 to function 'json_extract'
# Missing key returns NULL (no error)
SELECT '{"a": 1}'->'$.no_key';
'{"a": 1}'->'$.no_key'
NULL
# Invalid path returns a warning; result is NULL
SELECT '{"a": 1}'->'invalid_path';
'{"a": 1}'->'invalid_path'
NULL
Warnings:
Warning 4042 Syntax error in JSON path in argument 2 to function 'json_extract' at position 1
# 7. Integration with Generated Columns
CREATE TABLE t2 (
j JSON,
name VARCHAR(50) AS (j->>'$.name') VIRTUAL,
INDEX (name)
);
INSERT INTO t2 (j) VALUES ('{"name": "Zoe", "score": 100}');
SELECT name FROM t2;
name
Zoe
EXPLAIN SELECT name FROM t2 WHERE name = 'Zoe';
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 system name NULL NULL NULL 1
DROP TABLE t2;
# 8. Chaining with non-JSON results
# ->> returns a string. If the string is valid JSON, another -> can follow.
SELECT '{"outer": "{\\"inner\\": 1}"}'->> '$.outer'->'$.inner' AS complex_chain;
complex_chain
1
#
# 9. Ported tests from MySQL (Oracle). Authors at Oracle Corporation.
# Path: mysql-test/suite/json/inc/json_functions.inc
#
CREATE TABLE t1_mysql(autopk int primary key auto_increment, f1 JSON);
INSERT INTO t1_mysql(f1) VALUES
('{"a":1}'),
('{"a":3}'),
('{"a":2}'),
('{"a":11, "b":3}'),
('{"a":33, "b":1}'),
('{"a":22,"b":2}');
ANALYZE TABLE t1_mysql;
Table Op Msg_type Msg_text
test.t1_mysql analyze status Engine-independent statistics collected
test.t1_mysql analyze Warning Engine-independent statistics are not collected for column 'f1'
test.t1_mysql analyze status OK
SELECT f1->"$.a" FROM t1_mysql order by autopk;
f1->"$.a"
1
3
2
11
33
22
EXPLAIN SELECT f1->"$.a" FROM t1_mysql order by autopk;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1_mysql ALL NULL NULL NULL NULL 6 Using filesort
SELECT f1->"$.a" FROM t1_mysql WHERE f1->"$.b" > 1 order by autopk;
f1->"$.a"
11
22
EXPLAIN SELECT f1->"$.a" FROM t1_mysql WHERE f1->"$.b" > 1 order by autopk;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1_mysql ALL NULL NULL NULL NULL 6 Using where; Using filesort
SELECT f1->"$.a", f1->"$.b" FROM t1_mysql ORDER BY autopk;
f1->"$.a" f1->"$.b"
1 NULL
3 NULL
2 NULL
11 3
33 1
22 2
SELECT MAX(f1->"$.a"), f1->"$.b" FROM t1_mysql GROUP BY f1->"$.b";
MAX(f1->"$.a") f1->"$.b"
11 3
22 2
3 NULL
33 1
SELECT JSON_OBJECT("c",f1->"$.b") AS f2
FROM t1_mysql HAVING JSON_TYPE(f2->"$.c") <> 'NULL' ORDER BY autopk;
f2
{"c": 3}
{"c": 1}
{"c": 2}
Test unquoting operator
INSERT INTO t1_mysql(f1) VALUES
('{"t":"a"}'),
('{"t":"b"}'),
('{"t":"c"}');
Returned values should be quoted
SELECT f1->"$.t" FROM t1_mysql WHERE f1->"$.t" <> 'NULL' order by autopk;
f1->"$.t"
"a"
"b"
"c"
Returned values should be unquoted
SELECT f1->>"$.t" FROM t1_mysql WHERE f1->>"$.t" <> 'NULL' order by autopk;
f1->>"$.t"
a
b
c
# Error cases (using MariaDB error codes/behaviors)
# MariaDB allows NULL on the RHS (returns NULL)
SELECT f1->>NULL FROM t1_mysql;
f1->>NULL
NULL
NULL
NULL
NULL
NULL
NULL
NULL
NULL
NULL
# Invalid path returns a warning
SELECT f1 ->> "NULL" FROM t1_mysql;
f1 ->> "NULL"
NULL
NULL
NULL
NULL
NULL
NULL
NULL
NULL
NULL
Warnings:
Warning 4042 Syntax error in JSON path in argument 2 to function 'json_extract' at position 1
Warning 4042 Syntax error in JSON path in argument 2 to function 'json_extract' at position 1
Warning 4042 Syntax error in JSON path in argument 2 to function 'json_extract' at position 1
Warning 4042 Syntax error in JSON path in argument 2 to function 'json_extract' at position 1
Warning 4042 Syntax error in JSON path in argument 2 to function 'json_extract' at position 1
Warning 4042 Syntax error in JSON path in argument 2 to function 'json_extract' at position 1
Warning 4042 Syntax error in JSON path in argument 2 to function 'json_extract' at position 1
Warning 4042 Syntax error in JSON path in argument 2 to function 'json_extract' at position 1
Warning 4042 Syntax error in JSON path in argument 2 to function 'json_extract' at position 1
INSERT INTO t1_mysql(f1) VALUES
('[ { "a": 1 }, { "a": 2 } ]'),
('{ "a" : "foo", "b" : [ true, { "c" : 123, "c" : 456 } ] }'),
('{ "a" : "foo", "b" : [ true, { "c" : "123" } ] }'),
('{ "a" : "foo", "b" : [ true, { "c" : 123 } ] }');
SELECT
f1->>"$**.b",
JSON_UNQUOTE(JSON_EXTRACT(f1,"$**.b"))
FROM t1_mysql order by autopk;
f1->>"$**.b" JSON_UNQUOTE(JSON_EXTRACT(f1,"$**.b"))
NULL NULL
NULL NULL
NULL NULL
[3] [3]
[1] [1]
[2] [2]
NULL NULL
NULL NULL
NULL NULL
NULL NULL
[[true, {"c": 123, "c": 456}]] [[true, {"c": 123, "c": 456}]]
[[true, {"c": "123"}]] [[true, {"c": "123"}]]
[[true, {"c": 123}]] [[true, {"c": 123}]]
SELECT
f1->>"$.c",
JSON_UNQUOTE(JSON_EXTRACT(f1,"$.c"))
FROM t1_mysql order by autopk;
f1->>"$.c" JSON_UNQUOTE(JSON_EXTRACT(f1,"$.c"))
NULL NULL
NULL NULL
NULL NULL
NULL NULL
NULL NULL
NULL NULL
NULL NULL
NULL NULL
NULL NULL
NULL NULL
NULL NULL
NULL NULL
NULL NULL
DROP TABLE t1_mysql;
#
# 10. Ported tests from MySQL (Oracle). Authors at Oracle Corporation.
# Path: mysql-test/suite/json/t/json_prep_stmts.test
#
CREATE TABLE t1_prep(j JSON);
set @int=123;
set @intstr='123';
set @dec=3.14;
set @decstr='3.14';
set @flt=3.14E1;
set @fltstr='3.14E1';
set @strstr='xyz';
set @quotstr='"xyz"';
set @json='{"int" : 123, "dec" : 3.14, "flt" : 3.14E1, "str" : "xyz", "array" : [1, 2, 4]}';
insert into t1_prep values (@json);
prepare ps_get_int from "select * from t1_prep where j->'$.int' = ?";
prepare ps_get_dec from "select * from t1_prep where j->'$.dec' = ?";
prepare ps_get_flt from "select * from t1_prep where j->'$.flt' = ?";
prepare ps_get_str from "select * from t1_prep where j->'$.str' = ?";
execute ps_get_int using @int;
j
{"int" : 123, "dec" : 3.14, "flt" : 3.14E1, "str" : "xyz", "array" : [1, 2, 4]}
execute ps_get_int using @intstr;
j
{"int" : 123, "dec" : 3.14, "flt" : 3.14E1, "str" : "xyz", "array" : [1, 2, 4]}
execute ps_get_dec using @dec;
j
{"int" : 123, "dec" : 3.14, "flt" : 3.14E1, "str" : "xyz", "array" : [1, 2, 4]}
execute ps_get_dec using @decstr;
j
{"int" : 123, "dec" : 3.14, "flt" : 3.14E1, "str" : "xyz", "array" : [1, 2, 4]}
execute ps_get_flt using @flt;
j
{"int" : 123, "dec" : 3.14, "flt" : 3.14E1, "str" : "xyz", "array" : [1, 2, 4]}
execute ps_get_flt using @fltstr;
j
{"int" : 123, "dec" : 3.14, "flt" : 3.14E1, "str" : "xyz", "array" : [1, 2, 4]}
execute ps_get_str using @quotstr;
j
deallocate prepare ps_get_int;
deallocate prepare ps_get_dec;
deallocate prepare ps_get_flt;
deallocate prepare ps_get_str;
prepare ps_get_int from "select * from t1_prep where j->>'$.int' = ?";
prepare ps_get_dec from "select * from t1_prep where j->>'$.dec' = ?";
prepare ps_get_flt from "select * from t1_prep where j->>'$.flt' = ?";
prepare ps_get_str from "select * from t1_prep where j->>'$.str' = ?";
execute ps_get_int using @int;
j
{"int" : 123, "dec" : 3.14, "flt" : 3.14E1, "str" : "xyz", "array" : [1, 2, 4]}
execute ps_get_int using @intstr;
j
{"int" : 123, "dec" : 3.14, "flt" : 3.14E1, "str" : "xyz", "array" : [1, 2, 4]}
execute ps_get_dec using @dec;
j
{"int" : 123, "dec" : 3.14, "flt" : 3.14E1, "str" : "xyz", "array" : [1, 2, 4]}
execute ps_get_dec using @decstr;
j
{"int" : 123, "dec" : 3.14, "flt" : 3.14E1, "str" : "xyz", "array" : [1, 2, 4]}
execute ps_get_flt using @flt;
j
{"int" : 123, "dec" : 3.14, "flt" : 3.14E1, "str" : "xyz", "array" : [1, 2, 4]}
execute ps_get_flt using @fltstr;
j
{"int" : 123, "dec" : 3.14, "flt" : 3.14E1, "str" : "xyz", "array" : [1, 2, 4]}
execute ps_get_str using @strstr;
j
{"int" : 123, "dec" : 3.14, "flt" : 3.14E1, "str" : "xyz", "array" : [1, 2, 4]}
deallocate prepare ps_get_int;
deallocate prepare ps_get_dec;
deallocate prepare ps_get_flt;
deallocate prepare ps_get_str;
DROP TABLE t1_prep;
End of 13.0 tests
Loading