Skip to content
Draft
40 changes: 40 additions & 0 deletions mysql-test/main/func_json.result
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,46 @@ t1 CREATE TABLE `t1` (
`json_quote('foo')` varchar(38) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci
drop table t1;
select json_quote(17);
json_quote(17)
17
select json_quote(3.14);
json_quote(3.14)
3.14
select json_quote(1.5e2);
json_quote(1.5e2)
150
select json_quote(NULL);
json_quote(NULL)
null
select isnull(json_quote(NULL));
isnull(json_quote(NULL))
0
select json_quote('hello');
json_quote('hello')
"hello"
select json_quote('"already_quoted"');
json_quote('"already_quoted"')
"\"already_quoted\""
select json_contains(json_quote(NULL), 'null');
json_contains(json_quote(NULL), 'null')
1
create table t1 (a int);
insert into t1 values (NULL), (5);
select json_quote(a) from t1 order by a;
json_quote(a)
null
5
drop table t1;
select json_quote(NULL) is NULL;
json_quote(NULL) is NULL
0
select json_quote(NULL) = 'null';
json_quote(NULL) = 'null'
1
select coalesce(json_quote(NULL), 'fallback');
coalesce(json_quote(NULL), 'fallback')
null
select json_merge('string');
ERROR 42000: Incorrect parameter count in the call to native function 'json_merge'
select json_merge('string', 123);
Expand Down
31 changes: 31 additions & 0 deletions mysql-test/main/func_json.test
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,37 @@ select * from t1;
show create table t1;
drop table t1;

#
# MDEV-13645 JSON_QUOTE should handle numeric and NULL arguments
#
# Integer literal: must return the unquoted number, not SQL NULL
select json_quote(17);
# Decimal literal: must return the unquoted decimal, not SQL NULL
select json_quote(3.14);
# Double/float literal: must return the unquoted value text, not SQL NULL
select json_quote(1.5e2);
# NULL input: must return the JSON null literal as a non-NULL string result
select json_quote(NULL);
select isnull(json_quote(NULL));
# String regression: must still quote and escape exactly as before
select json_quote('hello');
select json_quote('"already_quoted"');
# JSON_QUOTE(NULL) must compose correctly inside another JSON function
# as the JSON null literal, not break the outer call with SQL NULL
select json_contains(json_quote(NULL), 'null');
# Column-sourced NULL: result must match literal NULL case (JSON null literal)
create table t1 (a int);
insert into t1 values (NULL), (5);
select json_quote(a) from t1 order by a;
drop table t1;
# SQL-NULL propagation checks: json_quote(NULL) must NOT propagate SQL NULL
# - IS NULL must return 0 (the string "null" is not SQL NULL)
select json_quote(NULL) is NULL;
# - equality with the string 'null' must return 1
select json_quote(NULL) = 'null';
# - COALESCE must return 'null', NOT 'fallback' (result is not SQL NULL)
select coalesce(json_quote(NULL), 'fallback');

--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT
select json_merge('string');
select json_merge('string', 123);
Expand Down
2 changes: 2 additions & 0 deletions mysql-test/main/func_json_notembedded.result
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ select json_replace(@obj,'$.foo',1);
ERROR 70100: Query was interrupted: execution time limit 0.0001 sec exceeded
select json_set(@arr,'$[1000]',1);
ERROR 70100: Query was interrupted: execution time limit 0.0001 sec exceeded
select 1 member of (@arr);
ERROR 70100: Query was interrupted: execution time limit 0.0001 sec exceeded
select ST_AsTEXT(ST_GeomFromGeoJSON(JSON_OBJECT("type", "Point", "coordinates", @arr),2)) as exp;
ERROR 70100: Query was interrupted: execution time limit 0.0001 sec exceeded
SET debug_dbug= @old_debug;
Expand Down
1 change: 1 addition & 0 deletions mysql-test/main/func_json_notembedded.test
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ select json_merge_preserve(@obj, @arr);
select json_remove(@obj,'$.foo');
select json_replace(@obj,'$.foo',1);
select json_set(@arr,'$[1000]',1);
select 1 member of (@arr);
select ST_AsTEXT(ST_GeomFromGeoJSON(JSON_OBJECT("type", "Point", "coordinates", @arr),2)) as exp;
enable_abort_on_error;
SET debug_dbug= @old_debug;
Expand Down
10 changes: 3 additions & 7 deletions mysql-test/suite/json/r/json_no_table.result
Original file line number Diff line number Diff line change
Expand Up @@ -2801,7 +2801,7 @@ select json_unquote('"abc"', NULL);
ERROR 42000: Incorrect parameter count in the call to native function 'json_unquote'
select json_quote(NULL);
json_quote(NULL)
NULL
null
select json_unquote(NULL);
json_unquote(NULL)
NULL
Expand Down Expand Up @@ -2846,11 +2846,9 @@ json_unquote('"')
"
Warnings:
Warning 4037 Unexpected end of JSON text in argument 1 to function 'json_unquote'
error ER_INCORRECT_TYPE
select json_quote(123);
json_quote(123)
NULL
error ER_INCORRECT_TYPE
123
select json_unquote(123);
json_unquote(123)
123
Expand Down Expand Up @@ -2931,7 +2929,6 @@ JSON_UNQUOTE( '"abc' )
"abc
Warnings:
Warning 4037 Unexpected end of JSON text in argument 1 to function 'json_unquote'
error ER_INCORRECT_TYPE
SELECT JSON_UNQUOTE( 123 );
JSON_UNQUOTE( 123 )
123
Expand Down Expand Up @@ -2968,10 +2965,9 @@ AS CHAR
SELECT JSON_QUOTE( 'abc' );
JSON_QUOTE( 'abc' )
"abc"
error ER_INCORRECT_TYPE
SELECT JSON_QUOTE( 123 );
JSON_QUOTE( 123 )
NULL
123
SELECT json_compact( JSON_QUOTE( '123' ));
json_compact( JSON_QUOTE( '123' ))
"123"
Expand Down
199 changes: 199 additions & 0 deletions mysql-test/suite/json/r/member_of.result
Original file line number Diff line number Diff line change
@@ -0,0 +1,199 @@
#
# MDEV-38591: MEMBER OF operator
#
# 1. Simple member checks (should succeed)
SELECT 1 MEMBER OF ('[1,2,3]');
1 MEMBER OF ('[1,2,3]')
1
SELECT 2 MEMBER OF ('[1,2,3]');
2 MEMBER OF ('[1,2,3]')
1
# 2. Non-member checks (should return 0)
SELECT 4 MEMBER OF ('[1,2,3]');
4 MEMBER OF ('[1,2,3]')
0
# 3. Type-strict checks (string "2" must NOT match number 2, should return 0)
SELECT '2' MEMBER OF ('[1,2,3]');
'2' MEMBER OF ('[1,2,3]')
0
SELECT 2 MEMBER OF ('["1","2","3"]');
2 MEMBER OF ('["1","2","3"]')
0
# 4. SQL NULL propagation checks
SELECT NULL MEMBER OF ('[1,2,3]');
NULL MEMBER OF ('[1,2,3]')
NULL
SELECT NULL MEMBER OF ('[1,2,3]') IS NULL;
NULL MEMBER OF ('[1,2,3]') IS NULL
1
SELECT 1 MEMBER OF (NULL);
1 MEMBER OF (NULL)
NULL
SELECT 1 MEMBER OF (NULL) IS NULL;
1 MEMBER OF (NULL) IS NULL
1
# 5. Error/Warning handling for malformed JSON
SELECT 1 MEMBER OF ('[1,2');
1 MEMBER OF ('[1,2')
NULL
Warnings:
Warning 4037 Unexpected end of JSON text in argument 2 to function 'member of'
SHOW WARNINGS;
Level Code Message
Warning 4037 Unexpected end of JSON text in argument 2 to function 'member of'
# 6. Nested array and object checks using JSON_COMPACT() vs uncast strings
SELECT JSON_COMPACT('[1,2]') MEMBER OF ('[[1,2],[3,4]]');
JSON_COMPACT('[1,2]') MEMBER OF ('[[1,2],[3,4]]')
1
SELECT '[1,2]' MEMBER OF ('[[1,2],[3,4]]');
'[1,2]' MEMBER OF ('[[1,2],[3,4]]')
0
SELECT JSON_COMPACT('{"name":"John"}') MEMBER OF ('[{"name":"John"},{"name":"Joe"}]') AS expr;
expr
1
SELECT '{"name":"John"}' MEMBER OF ('[{"name":"John"},{"name":"Joe"}]');
'{"name":"John"}' MEMBER OF ('[{"name":"John"},{"name":"Joe"}]')
0
# 7. MEMBER OF with scalar/object as container (acting as 1-element array)
SELECT 2 MEMBER OF ('2');
2 MEMBER OF ('2')
1
SELECT 2 MEMBER OF ('3');
2 MEMBER OF ('3')
0
SELECT 2 MEMBER OF ('"2"');
2 MEMBER OF ('"2"')
0
# 8. Test using table columns and row evaluations
CREATE TABLE t1 (id INT, val JSON);
INSERT INTO t1 VALUES (1, '[1, 2, 3]'), (2, '[4, 5, 6]'), (3, NULL);
SELECT id, val, 2 MEMBER OF (val) FROM t1;
id val 2 MEMBER OF (val)
1 [1, 2, 3] 1
2 [4, 5, 6] 0
3 NULL NULL
SELECT id, val, NULL MEMBER OF (val) FROM t1;
id val NULL MEMBER OF (val)
1 [1, 2, 3] NULL
2 [4, 5, 6] NULL
3 NULL NULL
CREATE TABLE t2 (candidate INT);
INSERT INTO t2 VALUES (2), (4), (NULL);
SELECT candidate, val, candidate MEMBER OF (val) FROM t1, t2 ORDER BY id, candidate;
candidate val candidate MEMBER OF (val)
NULL [1, 2, 3] NULL
2 [1, 2, 3] 1
4 [1, 2, 3] 0
NULL [4, 5, 6] NULL
2 [4, 5, 6] 0
4 [4, 5, 6] 1
NULL NULL NULL
2 NULL NULL
4 NULL NULL
DROP TABLE t1, t2;
# 9. Prepared Statements twice execution test
PREPARE stmt1 FROM 'SELECT ? MEMBER OF (?)';
SET @candidate = 2;
SET @container = '[1,2,3]';
EXECUTE stmt1 USING @candidate, @container;
? MEMBER OF (?)
1
SET @candidate = 4;
SET @container = '[1,2,3]';
EXECUTE stmt1 USING @candidate, @container;
? MEMBER OF (?)
0
DEALLOCATE PREPARE stmt1;
# 10. Prepared Statements with JSON_COMPACT
PREPARE stmt2 FROM 'SELECT JSON_COMPACT(?) MEMBER OF (?)';
SET @candidate_json = '[1,2]';
SET @container_nested = '[[1,2],[3,4]]';
EXECUTE stmt2 USING @candidate_json, @container_nested;
JSON_COMPACT(?) MEMBER OF (?)
1
EXECUTE stmt2 USING @candidate_json, @container_nested;
JSON_COMPACT(?) MEMBER OF (?)
1
DEALLOCATE PREPARE stmt2;
# 11. Malformed JSON-typed candidate test (using CHECK constraints bypass)
CREATE TABLE t3 (val JSON);
SET STATEMENT check_constraint_checks=0 FOR INSERT INTO t3 VALUES ('[1,2');
SELECT val MEMBER OF ('[1,2,3]') FROM t3;
val MEMBER OF ('[1,2,3]')
NULL
Warnings:
Warning 4037 Unexpected end of JSON text in argument 1 to function 'member of'
SHOW WARNINGS;
Level Code Message
Warning 4037 Unexpected end of JSON text in argument 1 to function 'member of'
DROP TABLE t3;
# 12. JSON scalar candidate test (type-strictness in passthrough branch)
CREATE TABLE t4 (val JSON);
INSERT INTO t4 VALUES ('2'), ('"2"');
SELECT val, val MEMBER OF ('[1,2,3]') FROM t4;
val val MEMBER OF ('[1,2,3]')
2 1
"2" 0
DROP TABLE t4;
# 13. NOT MEMBER OF tests
# 13.1 1 NOT MEMBER OF ('[1,2,3]') -> 0 (1 IS a member)
SELECT 1 NOT MEMBER OF ('[1,2,3]');
1 NOT MEMBER OF ('[1,2,3]')
0
# 13.2 4 NOT MEMBER OF ('[1,2,3]') -> 1
SELECT 4 NOT MEMBER OF ('[1,2,3]');
4 NOT MEMBER OF ('[1,2,3]')
1
# 13.3 '2' NOT MEMBER OF ('[1,2,3]') -> 1 (type-strict comparison)
SELECT '2' NOT MEMBER OF ('[1,2,3]');
'2' NOT MEMBER OF ('[1,2,3]')
1
# 13.4 NULL NOT MEMBER OF ('[1,2,3]') -> NULL (and IS NULL -> 1)
SELECT NULL NOT MEMBER OF ('[1,2,3]');
NULL NOT MEMBER OF ('[1,2,3]')
NULL
SELECT NULL NOT MEMBER OF ('[1,2,3]') IS NULL;
NULL NOT MEMBER OF ('[1,2,3]') IS NULL
1
# 13.5 1 NOT MEMBER OF (NULL) -> NULL (and IS NULL -> 1)
SELECT 1 NOT MEMBER OF (NULL);
1 NOT MEMBER OF (NULL)
NULL
SELECT 1 NOT MEMBER OF (NULL) IS NULL;
1 NOT MEMBER OF (NULL) IS NULL
1
# 13.6 Malformed JSON with NOT MEMBER OF (returns NULL with warning)
SELECT 1 NOT MEMBER OF ('not_json');
1 NOT MEMBER OF ('not_json')
NULL
Warnings:
Warning 4038 Syntax error in JSON text in argument 2 to function 'not member of' at position 1
SHOW WARNINGS;
Level Code Message
Warning 4038 Syntax error in JSON text in argument 2 to function 'not member of' at position 1
# 13.7 EXPLAIN EXTENDED round-trip print check
EXPLAIN EXTENDED SELECT 1 NOT MEMBER OF ('[1,2,3]');
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
Note 1003 select 1 not member of ('[1,2,3]') AS `1 NOT MEMBER OF ('[1,2,3]')`
SHOW WARNINGS;
Level Code Message
Note 1003 select 1 not member of ('[1,2,3]') AS `1 NOT MEMBER OF ('[1,2,3]')`
# 14. Prepared Statements twice execution for Section 6 nested cases
PREPARE stmt3 FROM 'SELECT JSON_COMPACT(\'[1,2]\') MEMBER OF (\'[[1,2],[3,4]]\')';
EXECUTE stmt3;
JSON_COMPACT('[1,2]') MEMBER OF ('[[1,2],[3,4]]')
1
EXECUTE stmt3;
JSON_COMPACT('[1,2]') MEMBER OF ('[[1,2],[3,4]]')
1
DEALLOCATE PREPARE stmt3;
PREPARE stmt4 FROM 'SELECT JSON_COMPACT(\'{"name":"John"}\') MEMBER OF (\'[{"name":"John"},{"name":"Joe"}]\')';
EXECUTE stmt4;
JSON_COMPACT('{"name":"John"}') MEMBER OF ('[{"name":"John"},{"name":"Joe"}]')
1
EXECUTE stmt4;
JSON_COMPACT('{"name":"John"}') MEMBER OF ('[{"name":"John"},{"name":"Joe"}]')
1
DEALLOCATE PREPARE stmt4;
8 changes: 2 additions & 6 deletions mysql-test/suite/json/t/json_no_table.test
Original file line number Diff line number Diff line change
Expand Up @@ -1842,12 +1842,10 @@ select json_unquote(convert('"abc"' using utf8mb4));
select json_quote('"');
select json_unquote('"'); # should do nothing

--echo error ER_INCORRECT_TYPE
select json_quote(123); # integer not allowed
select json_quote(123); # integer is now allowed, returns "123"
# Enable after fix MDEV-31554
--disable_cursor_protocol
--echo error ER_INCORRECT_TYPE
select json_unquote(123); # integer not allowed
select json_unquote(123); # integer is now allowed, returns "123"
--enable_cursor_protocol

select json_unquote('""'); # empty string
Expand Down Expand Up @@ -1903,7 +1901,6 @@ SELECT JSON_UNQUOTE( '"abc"' );
# returns the SQL string literal "abc
SELECT JSON_UNQUOTE( '"abc' );

--echo error ER_INCORRECT_TYPE
SELECT JSON_UNQUOTE( 123 );
--enable_cursor_protocol

Expand All @@ -1930,7 +1927,6 @@ SELECT
# returns "abc"
SELECT JSON_QUOTE( 'abc' );

--echo error ER_INCORRECT_TYPE
SELECT JSON_QUOTE( 123 );

# returns the JSON document consisting of the string scalar "123"
Expand Down
Loading