Linux ip-172-26-2-223 5.4.0-1018-aws #18-Ubuntu SMP Wed Jun 24 01:15:00 UTC 2020 x86_64
Apache
: 172.26.2.223 | : 13.59.210.36
Cant Read [ /etc/named.conf ]
8.1.13
www
www.github.com/MadExploits
Terminal
AUTO ROOT
Adminer
Backdoor Destroyer
Linux Exploit
Lock Shell
Lock File
Create User
CREATE RDP
PHP Mailer
BACKCONNECT
UNLOCK SHELL
HASH IDENTIFIER
CPANEL RESET
CREATE WP USER
BLACK DEFEND!
README
+ Create Folder
+ Create File
/
www /
server /
mysql /
mysql-test /
suite /
json /
inc /
[ HOME SHELL ]
Name
Size
Permission
Action
json_client.inc
594
B
-rw-r--r--
json_ddl.inc
2.51
KB
-rw-r--r--
json_fulltext.inc
3.55
KB
-rw-r--r--
json_functions.inc
125.65
KB
-rw-r--r--
json_gcol.inc
5.91
KB
-rw-r--r--
json_group_concat.inc
1.77
KB
-rw-r--r--
json_insert.inc
5.02
KB
-rw-r--r--
json_vs_json_comparator.inc
7.26
KB
-rw-r--r--
sql_vs_json_equalto.inc
22.79
KB
-rw-r--r--
sql_vs_json_greaterthan.inc
22.79
KB
-rw-r--r--
sql_vs_json_greaterthanequalto...
22.89
KB
-rw-r--r--
sql_vs_json_lessthan.inc
22.79
KB
-rw-r--r--
sql_vs_json_lessthanequalto.in...
22.89
KB
-rw-r--r--
sql_vs_json_notequal.inc
22.89
KB
-rw-r--r--
sql_vs_json_null_safe_equal_to...
22.99
KB
-rw-r--r--
Delete
Unzip
Zip
${this.title}
Close
Code Editor : json_functions.inc
--echo # Test of the JSON functions used in SQL statements --echo # ---------------------------------------------------------------------- SET NAMES utf8; CREATE TABLE t1 (pk int NOT NULL PRIMARY KEY AUTO_INCREMENT, i INT, j JSON); SHOW CREATE TABLE t1; INSERT INTO t1(i, j) VALUES (0, NULL); INSERT INTO t1(i, j) VALUES (1, '{"a": 2}'); INSERT INTO t1(i, j) VALUES (2, '[1,2]'); INSERT INTO t1(i, j) VALUES (3, '{"a":"b", "c":"d","ab":"abc", "bc": ["x", "y"]}'); INSERT INTO t1(i, j) VALUES (4, '["here", ["I", "am"], "!!!"]'); INSERT INTO t1(i, j) VALUES (5, '"scalar string"'); INSERT INTO t1(i, j) VALUES (6, 'true'); INSERT INTO t1(i, j) VALUES (7, 'false'); INSERT INTO t1(i, j) VALUES (8, 'null'); INSERT INTO t1(i, j) VALUES (9, '-1'); INSERT INTO t1(i, j) VALUES (10, CAST(CAST(1 AS UNSIGNED) AS JSON)); INSERT INTO t1(i, j) VALUES (11, '32767'); INSERT INTO t1(i, j) VALUES (12, '32768'); INSERT INTO t1(i, j) VALUES (13, '-32768'); INSERT INTO t1(i, j) VALUES (14, '-32769'); INSERT INTO t1(i, j) VALUES (15, '2147483647'); INSERT INTO t1(i, j) VALUES (16, '2147483648'); INSERT INTO t1(i, j) VALUES (17, '-2147483648'); INSERT INTO t1(i, j) VALUES (18, '-2147483649'); INSERT INTO t1(i, j) VALUES (19, '18446744073709551615'); INSERT INTO t1(i, j) VALUES (20, '18446744073709551616'); INSERT INTO t1(i, j) VALUES (21, '3.14'); INSERT INTO t1(i, j) VALUES (22, '{}'); INSERT INTO t1(i, j) VALUES (23, '[]'); INSERT INTO t1(i, j) VALUES (24, CAST(CAST('2015-01-15 23:24:25' AS DATETIME) AS JSON)); INSERT INTO t1(i, j) VALUES (25, CAST(CAST('23:24:25' AS TIME) AS JSON)); INSERT INTO t1(i, j) VALUES (26, CAST(CAST('2015-01-15' AS DATE) AS JSON)); INSERT INTO t1(i, j) VALUES (27, CAST(TIMESTAMP'2015-01-15 23:24:25' AS JSON)); INSERT INTO t1(i, j) VALUES (28, CAST(ST_GeomFromText('POINT(1 1)') AS JSON)); # auto-convert to utf8mb4 INSERT INTO t1(i, j) VALUES (29, CAST('[]' AS CHAR CHARACTER SET 'ascii')); INSERT INTO t1(i, j) VALUES (30, CAST(x'cafe' AS JSON)); INSERT INTO t1(i, j) VALUES (31, CAST(x'cafebabe' AS JSON)); --echo # --echo # Test of JSON comparator. --echo # SELECT i, (j = '"scalar string"') AS c1, (j = 'scalar string') AS c2, (j = CAST('"scalar string"' AS JSON)) AS c3, (j = CAST(CAST(j AS CHAR CHARACTER SET 'utf8mb4') AS JSON)) AS c4, (j = CAST(NULL AS JSON)) AS c5, (j = NULL) AS c6, (j <=> NULL) AS c7, (j <=> CAST(NULL AS JSON)) AS c8, (j IN (-1, 2, 32768, 3.14)) AS c9, (j IN (CAST('[1, 2]' AS JSON), CAST('{}' AS JSON), CAST(3.14 AS JSON))) AS c10, (j = (SELECT j FROM t1 WHERE j = CAST('null' AS JSON))) AS c11, (j = (SELECT j FROM t1 WHERE j IS NULL)) AS c12, (j = (SELECT j FROM t1 WHERE 1<>1)) AS c13, (j = DATE'2015-01-15') AS c14, (j = TIME'23:24:25') AS c15, (j = TIMESTAMP'2015-01-15 23:24:25') AS c16, (j = CURRENT_TIMESTAMP) AS c17, (j = ST_GeomFromText('POINT(1 1)')) AS c18, (JSON_EXTRACT(j, '$.a') = 2) AS c19 FROM t1 ORDER BY i; SELECT i FROM t1 WHERE j = CAST(CAST(j AS CHAR CHARACTER SET 'utf8') AS JSON) ORDER BY i; SELECT CAST(NULL AS UNSIGNED) = CAST(NULL AS JSON); SELECT CAST(NULL AS JSON) = CAST(NULL AS JSON); SELECT CAST(NULL AS JSON) = NULL; SELECT CAST(1 AS JSON) = NULL; SELECT CAST('true' AS JSON) = 1; SELECT CAST('true' AS JSON) = true; SELECT a.i, b.i, a.j < b.j, a.j = b.j, a.j > b.j, a.j <> b.j, a.j <=> b.j FROM t1 a, t1 b ORDER BY a.i, b.i; --echo # Verify that the index on the int column is not used when --echo # comparing the int column to a JSON column. The two columns --echo # should be compared using the JSON comparator. CREATE TABLE t2(i int, j json); CREATE INDEX t2_i ON t2(i); INSERT INTO t2 values (1, CAST(1 AS JSON)); INSERT INTO t2 values (1, CAST('"1"' AS JSON)); ANALYZE TABLE t2; let $query=SELECT * FROM t2 where i = j; eval EXPLAIN $query; eval $query; DROP TABLE t2; # Create a table full of JSON numeric scalars to verify that the JSON # comparator returns the expected result when comparing all # combinations of those values. # # The values should be inserted in ascending order. The table has a # rank column that tells how the comparator is expected to order the # JSON values. If two rows have the same rank, the comparator is # expected to say that the JSON values on the two rows are equal. If a # row has a lower rank than another, the JSON value in that row is # expected to be smaller than the JSON value in the other row. CREATE TABLE numbers(id INT NOT NULL AUTO_INCREMENT, rank INT, j JSON, PRIMARY KEY(id)); INSERT INTO numbers(rank, j) VALUES (1, '-1e100'), (2, '-1e65'), # smallest DECIMAL (negative with 65 digits) (3, CAST(-99999999999999999999999999999999999999999999999999999999999999999 AS JSON)), (4, CAST(-9223372036854776001 AS JSON)), (5, CAST(-9223372036854776000 AS JSON)), # closest DOUBLE approximation of the smallest SIGNED BIGINT (5 /* same rank as previous */, '-9.223372036854776e18'), (6, CAST(-9223372036854775999 AS JSON)), (7, CAST(-9223372036854775809 AS JSON)), # smallest SIGNED BIGINT - 1 (8, CAST(-9223372036854775808 AS JSON)), # smallest SIGNED BIGINT (9, CAST(-9223372036854775807 AS JSON)), # smallest SIGNED BIGINT + 1 (10, '-1e-50'), # close to zero, fits in a DECIMAL (11, '-1.2345678901234e-71'), # has to be truncated to fit in a DECIMAL (12, CAST(-0.000000000000000000000000000000000000000000000000000000000000000000000012 AS JSON)), (12 /* same rank as previous */, '-1.2e-71'), (13, '-1.0345678901234e-71'), # has to be truncated to fit in a DECIMAL (14, '-1e-100'), # too close to zero to fit in a DECIMAL (15, '0'), (15 /* same rank as previous */, '0.0'), (15 /* same rank as previous */, '-0.0'), (15 /* same rank as previous */, CAST(0.0 AS JSON)), (15 /* same rank as previous */, CAST(CAST(-0.0e0 AS DECIMAL) AS JSON)), (16, '1e-100'), # too close to zero to fit in a DECIMAL (17, '1.0345678901234e-71'), # has to be truncated to fit in a DECIMAL (18, CAST(0.000000000000000000000000000000000000000000000000000000000000000000000012 AS JSON)), (18 /* same rank as previous */, '1.2e-71'), (19, '1.2345678901234e-71'), # has to be truncated to fit in a DECIMAL (20, '1e-50'), # close to zero, fits in a DECIMAL (21, CAST(9223372036854775806 AS JSON)), # largest SIGNED BIGINT - 1 (22, CAST(9223372036854775807 AS JSON)), # largest SIGNED BIGINT (23, CAST(9223372036854775808 AS JSON)), # largest SIGNED BIGINT + 1 (24, CAST(9223372036854775999 AS JSON)), # closest DOUBLE approximation of the largest SIGNED BIGINT (25, '9.223372036854776e18'), (25 /* same rank as previous */, CAST(9223372036854776000 AS JSON)), (26, CAST(9223372036854776001 AS JSON)), (27, CAST(18446744073709551614 AS JSON)), # largest UNSIGNED BIGINT - 1 (28, CAST(18446744073709551615 AS JSON)), # largest UNSIGNED BIGINT (29, CAST(18446744073709551616 AS JSON)), # largest UNSIGNED BIGINT + 1 # Gets converted to the closest DOUBLE approximation of UNSIGNED BIGINT + 1 # by the JSON parser (30, '18446744073709551616'), # biggest DECIMAL (65 digits) (31, CAST(99999999999999999999999999999999999999999999999999999999999999999 AS JSON)), (32, CAST('1e65' AS JSON)), (33, CAST('1e100' AS JSON)); SELECT *, JSON_TYPE(j) FROM numbers ORDER BY id; # Now compare every combination of scalars in the table using <, =, >, # <> and <=>, and cross-check the results against the ranks. The query # returns the rows where the comparison returned an unexpected result. # If all is well, the query returns no rows. SELECT a.j, b.j, a.j < b.j, a.j = b.j, a.j > b.j, a.j <=> b.j FROM numbers a, numbers b WHERE ((a.j < b.j) <> (a.rank < b.rank)) OR ((a.j = b.j) <> (a.rank = b.rank)) OR ((a.j > b.j) <> (a.rank > b.rank)) OR ((a.j <=> b.j) <> (a.rank <=> b.rank)); DROP TABLE numbers; # Verify handling of errors during evaluation of the arguments to the # comparator, both in the left argument and in the right argument. CREATE TABLE t(txt TEXT); INSERT INTO t VALUES (''); --error ER_INVALID_JSON_TEXT_IN_PARAM SELECT COUNT(*) FROM t WHERE JSON_EXTRACT(txt, '$') = 5; --error ER_INVALID_JSON_TEXT_IN_PARAM SELECT COUNT(*) FROM t WHERE 5 = JSON_EXTRACT(txt, '$'); DROP TABLE t; --echo # --echo # WL#8539 - Ordering of scalar JSON values --echo # # Create some timestamps. CREATE TABLE timestamps (ts TIMESTAMP(6)); INSERT INTO timestamps VALUES ('2000-01-01 00:00:00'), ('2000-01-01 00:00:00.01'), ('2000-01-01 00:00:00.001'), ('2000-01-01 00:00:00.002'), ('2000-01-01 00:00:00.02'), ('2000-01-01 23:59:59.999999'), ('2000-01-02 00:00:00'), ('2000-02-01 00:00:00'), ('2010-12-02 01:00:00'), ('2010-12-02 01:02:00'), ('2010-12-02 01:02:03'), ('2010-12-02 02:01:00'), ('1970-01-02 00:00:01'), ('1970-01-02 00:00:01.000001'); SELECT * FROM timestamps ORDER BY CAST(ts AS JSON); # Create datetimes that correspond to the above timestamps, and add some values # that are outside the accepted range of the timestamp data type. CREATE TABLE datetimes (dt DATETIME(6)); INSERT INTO datetimes SELECT ts FROM timestamps; INSERT INTO datetimes VALUES ('1960-01-02 03:04:05'), ('1960-01-02 03:04:06'), ('1000-01-01 00:00:00'), ('9999-12-31 23:59:59.999999'); SELECT * FROM datetimes ORDER BY CAST(dt AS JSON); # Create some times using the time component of the above datetimes. Also add # some times that go outside of the 0-24 range of the time component of # datetime. CREATE TABLE times (t TIME(6)); INSERT INTO times SELECT DISTINCT TIME(dt) FROM datetimes; INSERT INTO times VALUES ('-838:59:59'), ('838:59:59'), ('-00:00:00.000001'), ('-00:00:00'), ('24:00:00'), ('-12:00:00'), ('-24:00:00'); SELECT * FROM times ORDER BY CAST(t AS JSON); # Create dates using the date component of the above datetimes. CREATE TABLE dates(d DATE); INSERT INTO dates SELECT DISTINCT DATE(dt) FROM datetimes; # Create some signed integers. CREATE TABLE signed_integers(i BIGINT); INSERT INTO signed_integers VALUES (0), (1), (2), (3), (4), (5), (10), (11), (12), (20), (21), (22), (99), (100), (101), (999), (1000), (1001), (9223372036854775806), (9223372036854775807); INSERT INTO signed_integers SELECT -i FROM signed_integers; INSERT INTO signed_integers VALUES (-9223372036854775808); SELECT * FROM signed_integers ORDER BY CAST(i AS JSON); # Create some unsigned integers. CREATE TABLE unsigned_integers(i BIGINT UNSIGNED); INSERT INTO unsigned_integers SELECT i FROM signed_integers where i >= 0; INSERT INTO unsigned_integers VALUES (9223372036854775808), (18446744073709551614), (18446744073709551615); SELECT * FROM unsigned_integers ORDER BY CAST(i AS JSON); # Create some decimals. CREATE TABLE decimals (d DECIMAL(25,3)); INSERT INTO decimals SELECT i FROM signed_integers; INSERT INTO decimals SELECT i FROM unsigned_integers; INSERT INTO decimals VALUES (9223372036854776000), (-9223372036854776000), (9223372036854776001), (-9223372036854776001), (3.13), (3.14), (3.15), (-3.13), (-3.14), (-3.15), (3.131), (3.141), (3.151), (-3.131), (-3.141), (-3.151), (3.129), (3.139), (3.149), (-3.129), (-3.139), (-3.149), (0.1), (0.01), (0.001), (-0.1), (-0.01), (-0.001); SELECT * FROM decimals ORDER BY CAST(d AS JSON); # Create some doubles. CREATE TABLE doubles (d DOUBLE); INSERT INTO doubles SELECT d FROM decimals; INSERT INTO doubles VALUES (1.5E-200), (1.5E200), (-1.5E-200), (-1.5E200), (-1E-323), (-1E-322), (-1E-321), (1E-323), (1E-322), (1E-321), (-1E308), (-1E307), (-1E306), (1E308), (1E307), (1E306); SELECT * FROM doubles ORDER BY CAST(d AS JSON); # Now convert all of the above values to JSON. CREATE TABLE t(id INT PRIMARY KEY AUTO_INCREMENT, j JSON); INSERT INTO t(j) SELECT CAST(ts AS JSON) FROM timestamps ORDER BY ts; INSERT INTO t(j) SELECT CAST(dt AS JSON) FROM datetimes ORDER BY dt; INSERT INTO t(j) SELECT CAST(t AS JSON) FROM times ORDER BY t; INSERT INTO t(j) SELECT CAST(d AS JSON) FROM dates ORDER BY d; INSERT INTO t(j) SELECT CAST(i AS JSON) FROM signed_integers ORDER BY i; INSERT INTO t(j) SELECT CAST(i AS JSON) FROM unsigned_integers ORDER BY i; INSERT INTO t(j) SELECT CAST(d AS JSON) FROM decimals ORDER BY d; INSERT INTO t(j) SELECT CAST(d AS JSON) FROM doubles ORDER BY d; # Insert some more JSON values. INSERT INTO t(j) VALUES (NULL), (NULL), ('true'), ('false'), ('null'), ('"abc"'), ('""'), ('"abcd"'), ('"bc"'), ('"abc\\u0000\\u0000"'), ('"abc\\u0000"'), ('0.0'), ('-0.0'), ('9223372036854776000'), ('1.0e-1'), ('1.0e-2'), (CAST(0.000000000000001 AS JSON)), (CAST(0.00000000000000115 AS JSON)), (CAST(0.0000000000000001 AS JSON)), (CAST(0.000000000000000116 AS JSON)), (CAST(0.0 AS JSON)), (CAST(-999999999999999999999999999999999999999999999999999999999999999999999999999999999 AS JSON)), (CAST(-999999999999999999999999999999999999999999999999999999999999999999999999999999998 AS JSON)), (CAST(-999999999999999999999999999999999999999999999999999999999999999999999999999999997 AS JSON)), (CAST(999999999999999999999999999999999999999999999999999999999999999999999999999999997 AS JSON)), (CAST(999999999999999999999999999999999999999999999999999999999999999999999999999999998 AS JSON)), (CAST(999999999999999999999999999999999999999999999999999999999999999999999999999999999 AS JSON)), (CAST(-1E81 AS JSON)), (CAST(-9.99E80 AS JSON)), (CAST(9.99E80 AS JSON)), (CAST(1E81 AS JSON)), (JSON_ARRAY('an array')), (JSON_ARRAY('another array')), (JSON_OBJECT('an', 'object')), (JSON_OBJECT('another', 'object')), (CAST(ST_GeomFromText('POINT(0 0)') AS JSON)), (CAST(ST_GeomFromText('POINT(0 1)') AS JSON)), (CAST(CAST('1234abcd' AS BINARY) AS JSON)); # Now order the table on the JSON column. SELECT j, JSON_TYPE(j) AS tp FROM t ORDER BY j, id; SELECT j, JSON_TYPE(j) AS tp FROM t ORDER BY j DESC, id; # Ordering on a JSON expression should give the same result. SELECT JSON_EXTRACT(j, '$') AS je, JSON_TYPE(j) AS tp FROM t ORDER BY je, id; # Set max_sort_length as small as possible and order again. Since we'll now just # look at a prefix of the values, distinct values with a common prefix may order # as equal. SET @@max_sort_length=4; SELECT j, JSON_TYPE(j) AS tp FROM t ORDER BY j, id; SET @@max_sort_length=default; # GROUP BY uses a temporary for grouping, GROUP BY WITH ROLLUP uses filesort to # do the grouping. ANALYZE TABLE t; EXPLAIN SELECT j, COUNT(*) FROM t GROUP BY j ORDER BY j; EXPLAIN SELECT j, COUNT(*) FROM t GROUP BY j WITH ROLLUP; # Grouping produces indeterminate results based on the order of evaluation. For example, # either '2' or '2.0' could be the name of the group # either '20' or '20.000' could be the name of the group # either '-0.1' or '-0.100' could be the name of the group # either '9223372036854775807.000' or '9223372036854775807' could be the name of the group # These issues are resolved by removing trailing zeros from decimals and replacing -0 with 0. # This also replaces .000010 with 010 and .000001 with 001 [because \s is not supported]. --replace_regex /1\.0e\-1/0.1/ /1\.0e\-2/0.01/ /0\.010/0.01/ /\.000// /\.0// /0\.100/0.1/ /\-0/0/ /3\.130/3.13/ /3\.140/3.14/ /3\.150/3.15/ /9\.223372036854776e18/9223372036854776000/ SELECT j, COUNT(*) FROM t GROUP BY j ORDER BY j; --replace_regex /1\.0e\-1/0.1/ /1\.0e\-2/0.01/ /0\.010/0.01/ /\.000// /\.0// /0\.100/0.1/ /\-0/0/ /3\.130/3.13/ /3\.140/3.14/ /3\.150/3.15/ /9\.223372036854776e18/9223372036854776000/ SELECT JSON_EXTRACT(j, '$') AS je, COUNT(*) FROM t GROUP BY je ORDER BY je; --replace_regex /1\.0e\-1/0.1/ /1\.0e\-2/0.01/ /0\.010/0.01/ /\.000// /\.0// /0\.100/0.1/ /\-0/0/ /3\.130/3.13/ /3\.140/3.14/ /3\.150/3.15/ /9\.223372036854776e18/9223372036854776000/ SELECT j, COUNT(*) FROM t GROUP BY j WITH ROLLUP; --replace_regex /1\.0e\-1/0.1/ /1\.0e\-2/0.01/ /0\.010/0.01/ /\.000// /\.0// /0\.100/0.1/ /\-0/0/ /3\.130/3.13/ /3\.140/3.14/ /3\.150/3.15/ /9\.223372036854776e18/9223372036854776000/ SELECT JSON_EXTRACT(j, '$') AS je, COUNT(*) FROM t GROUP BY je WITH ROLLUP; DROP TABLE t, timestamps, datetimes, times, dates, signed_integers, unsigned_integers, decimals, doubles; # Test ordering of a not nullable column. CREATE TABLE t(j JSON NOT NULL); INSERT INTO t VALUES ('1'), ('2'), ('10'), ('"1"'), ('"2"'), ('"10"'), ('true'), ('false'), ('null'); SELECT j FROM t ORDER BY j; SELECT j FROM t ORDER BY JSON_EXTRACT(j, '$'); SELECT JSON_EXTRACT(j, '$') FROM t ORDER BY 1; # Ordering on (j+1) will convert to a numeric type. SELECT j FROM t ORDER BY j+1, JSON_TYPE(j); DROP TABLE t; CREATE TABLE t(vc varchar(10)); INSERT INTO t VALUES ('["abc"]'), ('[1'); --error ER_INVALID_JSON_TEXT_IN_PARAM SELECT * FROM t ORDER BY CAST(vc AS JSON); --error ER_INVALID_JSON_TEXT_IN_PARAM SELECT * FROM t ORDER BY JSON_EXTRACT(vc, '$[0]'); --error ER_INVALID_JSON_TEXT_IN_PARAM SELECT CAST(vc AS JSON) AS j FROM t ORDER BY j; --error ER_INVALID_JSON_TEXT_IN_PARAM SELECT JSON_EXTRACT(vc, '$[0]') AS j FROM t ORDER BY j; --error ER_INVALID_JSON_TEXT_IN_PARAM SELECT CAST(vc AS JSON) FROM t ORDER BY 1; --error ER_INVALID_JSON_TEXT_IN_PARAM SELECT JSON_EXTRACT(vc, '$[0]') FROM t ORDER BY 1; DROP TABLE t; --echo # --echo # Internal ordering of arrays and objects. Ordered by cardinality. --echo # CREATE TABLE t(i int, j json); INSERT INTO t VALUES (1, '{}'), (2, '{"a":1}'), (3, '{"ab":2}'), (4, '{"a":1,"b":2}'), (5, '{"c":3,"d":4}'), (6, '{"a":1,"b":2,"c":3,"d":4}'); INSERT INTO t VALUES (1, '[]'), (2, '[1]'), (3, '[2]'), (4, '[1,2]'), (5, '[2,1]'), (6, '[1,2,3]'), (7, '[1,2,3,4]'), (8, '[4,3,2,1]'), (9, '[1,2,3,4,5]'); INSERT INTO t SELECT i+100, j FROM t; SELECT * FROM t ORDER BY j, i; SELECT * FROM t ORDER BY j DESC, i; # GROUP BY knows how to distinguish the arrays and the objects, even # if they have the same cardinality. # Group by produces indeterminate results based on the order the items are evaluated # SELECT j, COUNT(*) FROM t GROUP BY j ORDER BY j; # GROUP BY WITH ROLLUP, on the other hand, doesn't know how to # distinguish them, and produces confusing results for arrays/objects. # GROUP BY WITH ROLLUP is only useful on scalar results for now. SELECT j, COUNT(*) FROM t GROUP BY j WITH ROLLUP; DROP TABLE t; --echo # Test NULLs sorting. CREATE TABLE t(i int, j json); INSERT INTO t(i) VALUES (1),(2),(3),(2),(1); SELECT * FROM t ORDER BY j, i; SELECT * FROM t ORDER BY j DESC, i; SELECT i, JSON_EXTRACT(j, '$') AS je FROM t ORDER BY je, i; SELECT i, JSON_EXTRACT(j, '$') AS je FROM t ORDER BY je DESC, i; INSERT INTO t(i, j) VALUES (1, '1'); SELECT * FROM t ORDER BY j, i; SELECT * FROM t ORDER BY j DESC, i; SELECT i, JSON_EXTRACT(j, '$') AS je FROM t ORDER BY je, i; SELECT i, JSON_EXTRACT(j, '$') AS je FROM t ORDER BY je DESC, i; DROP TABLE t; # Merging of sort results should not get confused if one of the sort columns is # a JSON column. CREATE TABLE t(vc TEXT, j JSON); INSERT INTO t (vc) VALUES ('a'), ('b'), ('c'); INSERT INTO t SELECT * FROM t; INSERT INTO t SELECT * FROM t; INSERT INTO t SELECT * FROM t; INSERT INTO t SELECT * FROM t; INSERT INTO t SELECT * FROM t; INSERT INTO t SELECT * FROM t; INSERT INTO t SELECT * FROM t; SELECT * FROM t ORDER BY vc, j; DROP TABLE t; --echo # ---------------------------------------------------------------------- --echo # Test of JSON_VALID function. --echo # ---------------------------------------------------------------------- --echo --echo # Table - Json string column - utf-8, NULL --echo Note: 'utf8' is a subset of internal 'utf8mb4' --echo create table utf8_t (c varchar(20)) CHARACTER SET 'utf8'; insert into utf8_t values (NULL); -- echo # Expect NULL: select JSON_VALID(c) from utf8_t; delete from utf8_t; --echo --echo # Table - Json string column - utf-8, valid insert into utf8_t values ('[123]'); select JSON_VALID(c) from utf8_t; delete from utf8_t; --echo --echo # Table - Json string column - utf-8, non-utf8 insert into utf8_t values ('[123'); --echo expect 0 (false) select JSON_VALID(c) from utf8_t; delete from utf8_t; --echo --echo # Table - Try to extract JSON from TIMESTAMP column ALTER TABLE utf8_t ADD d TIMESTAMP; --echo # Should give false; not string or JSON type --echo # and we do not convert automatically from TIMESTAMP to JSON insert into utf8_t values (NULL, '2014-11-25 18:00'); select JSON_VALID(d) from utf8_t; --echo # Explicit cast to a character data type --echo # allows MySQL to parse this is a JSON text --echo # The string isn't a legal JSON document, tho, so not valid. select JSON_VALID(CAST(d as CHAR)) from utf8_t; --echo # Should give true select JSON_VALID(CONCAT( CONCAT('"', CAST(d as CHAR)), '"')) from utf8_t; delete from utf8_t; drop table utf8_t; --echo --echo # Table - JSON type; should give true by definition create table json_t(t json); insert into json_t values ('[123]'); select json_VALID(t) from json_t; --echo --echo # Function result - JSON select JSON_VALID( JSON_ARRAY(t, t) ) from json_t; drop table json_t; --echo # ---------------------------------------------------------------------- --echo # Test of JSON_LENGTH function. --echo # ---------------------------------------------------------------------- create table utf8_mj_length (a int, c varchar(20)) CHARACTER SET 'utf8'; insert into utf8_mj_length values( 1, null ); insert into utf8_mj_length values( 2, '1' ); insert into utf8_mj_length values( 3, 'abc' ); insert into utf8_mj_length values( 4, '"abc"' ); insert into utf8_mj_length values ( 5, 'true' ); insert into utf8_mj_length values ( 6, 'false' ); insert into utf8_mj_length values ( 7, 'null' ); select a, c, json_length( c ) from utf8_mj_length where a = 1; select a, c, json_length( c ) from utf8_mj_length where a = 2; --echo --echo # invalid json text --error ER_INVALID_JSON_TEXT_IN_PARAM select a, c, json_length( c ) from utf8_mj_length where a = 3; select a, c, json_length( c ) from utf8_mj_length where a = 4; select a, c, json_length( c ) from utf8_mj_length where a = 5; select a, c, json_length( c ) from utf8_mj_length where a = 6; select a, c, json_length( c ) from utf8_mj_length where a = 7; create table json_mj_length( a int, b json ); insert into json_mj_length values( 1, NULL ); select a, b, json_length( b ) from json_mj_length where a = 1; # json_length() with vacuous path expressions set names 'ascii'; --echo --echo # path auto-converted to a utf8 string from ascii --echo select a, c, json_length( c, '$' ) from utf8_mj_length where a = 2; set names 'utf8'; select a, c, json_length( c, '$' ) from utf8_mj_length where a = 1; select a, c, json_length( c, '$' ) from utf8_mj_length where a = 2; --echo --echo # invalid json text --error ER_INVALID_JSON_TEXT_IN_PARAM select a, c, json_length( c, '$' ) from utf8_mj_length where a = 3; select a, c, json_length( c, '$' ) from utf8_mj_length where a = 4; select a, c, json_length( c, '$' ) from utf8_mj_length where a = 5; select a, c, json_length( c, '$' ) from utf8_mj_length where a = 6; select a, c, json_length( c, '$' ) from utf8_mj_length where a = 7; select a, b, json_length( b, '$' ) from json_mj_length where a = 1; drop table utf8_mj_length; drop table json_mj_length; # different paths for each row CREATE TABLE json_remove_t(j JSON, p TEXT); INSERT INTO json_remove_t(p) VALUES ('$.a'), ('$.b'), ('$.c'); UPDATE json_remove_t SET j = '{"a":1,"b":2,"c":3}'; SELECT j, p, json_remove(j, p) FROM json_remove_t ORDER BY p; DROP TABLE json_remove_t; CREATE TABLE json_merge_t(i INT, j JSON); INSERT INTO json_merge_t VALUES (0, NULL), (1, 'true'), (2, '5'), (3, '[1,2]'), (4, '{"a":["x", "y"]}'), (5, '{"a":"b","c":"d"}'); SELECT t1.j, t2.j, JSON_MERGE_PRESERVE(t1.j, t2.j) AS m1, JSON_MERGE_PRESERVE(t2.j, t1.j) AS m2 FROM json_merge_t t1, json_merge_t t2 ORDER BY t1.i, t2.i; DROP TABLE json_merge_t; create table keys1(i int, j json); insert into keys1 select i, j from t1; DROP TABLE t1; # example from the wl7909 spec create table rawOrders( orderID int, doc json ); insert into rawOrders values ( 1, '100' ), ( 2, '{ "id": 2, "quantity": 200 }' ); create table orders( orderID int, quantity int unsigned ); INSERT INTO orders( orderID, quantity ) SELECT r.orderID, CASE( JSON_TYPE( r.doc ) ) WHEN "INTEGER" THEN CAST( r.doc AS UNSIGNED INT ) WHEN "OBJECT" THEN CAST( JSON_EXTRACT( r.doc, '$.quantity' ) AS UNSIGNED INT ) ELSE NULL END FROM rawOrders r; select * from rawOrders order by orderID; select * from orders order by orderID; drop table rawOrders; drop table orders; # the value here isn't important, but it should be stable select charset(json_type('{}')); --echo # ---------------------------------------------------------------------- --echo # Test of CAST(<column> AS JSON) --echo # ---------------------------------------------------------------------- create table t1(dati datetime, da date, tim time, ts timestamp, y year, -- ti tinyint, tiu tinyint unsigned, si smallint, siu smallint unsigned, mi mediumint, miu mediumint unsigned, i int, iu int unsigned, bi bigint, biu bigint unsigned, boo boolean, -- dc decimal(5,2), n numeric(5,2), -- f float, d double, bitt bit(10), blb blob, bin binary(10), en enum('a','b','c'), se set('a','b','c'), -- ge geometry, po point, ls linestring, py polygon, js json ); insert into t1 values('2014-11-25 18:00', '2014-11-25', '18:00:59', '2014-11-25 18:00', '1999', -- 127, 255, 32767, 65535, 8388607, 16777215, -- 3 bytes 2147483647, 4294967295, -- 4 bytes 9223372036854775807, 18446744073709551615, true, -- 3.14, 3.14, -- 3.14, 3.14, b'10101', '10101abcde', '10101abcde', 'b', 'a,c', -- ST_GeomFromText('POINT(1 1)'), ST_GeomFromText('POINT(1 1)'), ST_GeomFromText('LINESTRING(0 0,1 1,2 2)'), ST_GeomFromText('POLYGON((0 0,10 0,10 10,0 10,0 0), (5 5,7 5,7 7,5 7, 5 5))'), '[123]' ); select json_type(cast(dati as json)) from t1; select json_type(cast(da as json)) from t1; select json_type(cast(tim as json)) from t1; select json_type(cast(ts as json)) from t1; select json_type(cast(y as json)) from t1; select json_type(cast(ti as json)) from t1; select json_type(cast(tiu as json)) from t1; select json_type(cast(si as json)) from t1; select json_type(cast(siu as json)) from t1; select json_type(cast(mi as json)) from t1; select json_type(cast(miu as json)) from t1; select json_type(cast(i as json)) from t1; select json_type(cast(iu as json)) from t1; select json_type(cast(bi as json)) from t1; select json_type(cast(biu as json)) from t1; select json_type(cast(boo as json)) from t1; # INTEGER (not enough info) select json_type(cast(dc as json)) from t1; # select json_type(cast(n as json)) from t1; select json_type(cast(f as json)) from t1; select json_type(cast(d as json)) from t1; select json_type(cast(bitt as json)) from t1; select json_type(cast(blb as json)) from t1; select json_type(cast(bin as json)) from t1; select json_type(cast(en as json)) from t1; select json_type(cast(se as json)) from t1; select json_type(cast(ge as json)) from t1; select json_type(cast(po as json)) from t1; select json_type(cast(ls as json)) from t1; select json_type(cast(py as json)) from t1; select json_type(cast(js as json)) from t1; # # same, but now show the printable value: # select cast(dati as json) from t1; select cast(da as json) from t1; select cast(tim as json) from t1; select cast(ts as json) from t1; select cast(y as json) from t1; select cast(ti as json) from t1; select cast(tiu as json) from t1; select cast(si as json) from t1; select cast(siu as json) from t1; select cast(mi as json) from t1; select cast(miu as json) from t1; select cast(i as json) from t1; select cast(iu as json) from t1; select cast(bi as json) from t1; select cast(biu as json) from t1; select cast(boo as json) from t1; # INTEGER (not enough info) select cast(dc as json) from t1; # select cast(n as json) from t1; select cast(f as json) from t1; select cast(d as json) from t1; select cast(bitt as json) from t1; select cast(blb as json) from t1; select cast(bin as json) from t1; select cast(en as json) from t1; select cast(se as json) from t1; select cast(ge as json) from t1; select cast(po as json) from t1; select cast(ls as json) from t1; select cast(py as json) from t1; select cast(js as json) from t1; --echo # --echo # Bug#21442878 INCORRECT RETURN STATUS FROM --echo # ITEM_JSON_TYPECAST::VAL_JSON() ON PARSE ERRORS --echo # --error ER_INVALID_TYPE_FOR_JSON select json_extract(en, '$') from t1; drop table t1; create table t1 ( c1 varchar(200) character set 'latin1', c2 varchar(200) character set 'utf8' ); insert into t1 values ('[1,2]', # legal json, but not utf-8 '[1,2 '); # illegal json, but utf-8 # convert latin1 to UTF-8 select cast(c1 as json) from t1; --error ER_INVALID_JSON_TEXT_IN_PARAM select cast(c2 as json) from t1; --error ER_INVALID_JSON_TEXT_IN_PARAM select cast(c2 as json) is null from t1; drop table t1; # Two distinct but related bugs detected by Knut 2015-02-05 caused NULL for y here: create table t2(x int); insert into t2 values (1), (2); select x, cast(y as json) from (select x, cast(x as json) as y from t2) s order by x; select x, cast(y as json) from (select x, cast(cast(x as json) as char charset utf8) as y from t2) s order by x; drop table t2; --echo # ---------------------------------------------------------------------- --echo # Test of CAST(<select> AS JSON) --echo # ---------------------------------------------------------------------- # positive test cases select cast((select 1) as json); create table t(i int, j json, c char(10) character set 'utf8'); insert into t values (5, '6', '{}'); select cast((select i from t) as json); select cast((select j from t) as json); select cast((select c from t) as json); select cast((select cast(i as json) from t) as json); select cast((select cast(j as json) from t) as json); select cast((select cast(c as json) from t) as json); insert into t values (7, '8', '[]'); --error ER_SUBQUERY_NO_1_ROW select cast((select i from t) as json); # Test what happens if the subquery returns NULL. The casts should # return SQL NULL. delete from t; insert into t values (null, null, null); select cast((select i from t) as json); select cast((select j from t) as json); select cast((select cast(i as json) from t) as json); select cast((select cast(j as json) from t) as json); select cast((select cast(c as json) from t) as json); # negative test cases --error ER_OPERAND_COLUMNS select cast((select i,i from t) as json); --error ER_OPERAND_COLUMNS select cast((select * from t) as json); drop table t; --echo # ---------------------------------------------------------------------- --echo # Test of JSON_KEYS function. --echo # ---------------------------------------------------------------------- select i, json_keys(j) from keys1 order by i; delete from keys1; insert into keys1 values (0, NULL), (1, '{"a": 1, "b": {"e": "foo", "b": 3}}'); select i, json_keys(j), json_keys(j, '$.b') from keys1 order by i; select cast(j as char) from keys1 order by i; create table t(i int); select cast(json_extract(j, '$.b.b') as char) from keys1 order by i; insert into t select cast(json_extract(j, '$.b.b') as char) from keys1; select * from t order by i; drop table t; drop table keys1; # positive test cases create table t(j json); insert into t values ('[ 1, 2, 3, {"a": [4,5,6]}]'); select json_array_append(j, '$[3].a', cast(7 as json)) from t; select json_array_append(j, '$', 7) from t; select json_array_append(j, '$', cast(7 as json), '$[3].a', 3.14) from t; --echo # second path's append ignored since it doesn't specify an array --echo # nor is it an existing scalar, so no auto-wrapping either select json_array_append(j, '$', 7, '$[3].b', cast(8 as json)) from t; drop table t; # path caching and leg popping create table jdoc( id int, doc json ); insert into jdoc values ( 1, '[ [ true ], [ false ] ]' ), ( 2, '[ [ 0 ], [ 1 ] ]' ), ( 3, '[ [ "abc" ], [ "def" ] ]' ); select id, json_array_insert( doc, '$[0][1]', 'fred' ) from jdoc order by id; select id, json_array_insert( doc, '$[1][0]', 'fred' ) from jdoc order by id; drop table jdoc; create table t( id int, v varchar(10)); insert into t values (1, 'a'), (2, null), (3, 'a'); select id v, json_array_insert('[[1]]', '$[0][0]', v) from t order by id; drop table t; --echo # --echo # Bug #21304639: JSON_SET() WITH MULTI-LEG PATH RETURNS DIFFERENT --echo # RESULTS ON FIRST ROW VS NEXT --echo # create table t21304639(pk int); insert into t21304639 values (2), (1), (3); select json_set( json_object('existing', pk), '$.key_b.test', json_object('new', 'apple') ) as field1 from t21304639 order by field1; select json_set( json_object('existing', pk), '$.key_b.test', json_object('new', 'apple') ) as field1 from t21304639 order by field1; drop table t21304639; create table t (i int, j json, d double); insert into t values (3, '["a", "b"]', 3.14); select json_array(i, j, d) from t; drop table t; # Array with the smallest possible signed integer and the largest possible # unsigned integer. CREATE TABLE t(j JSON); INSERT INTO t VALUES (JSON_ARRAY(-9223372036854775808, 18446744073709551614)); SELECT * FROM t; DROP TABLE t; # examples from the wl7909 spec create table department( id int, deptName varchar(50), isExempt boolean, blobColumn blob ); insert into department values ( 405, 'Accounting', true, '<a><b>ccc</b><d></d></a>' ); # returns ["Accounting", {"processed": true }] SELECT JSON_ARRAY( d.deptName, CAST( '{ "processed" : true }' AS JSON ) ) FROM department d WHERE id = 405; # stores a JSON value in a JSON-typed column create table json_table( json_column json ); INSERT INTO json_table( json_column ) SELECT JSON_ARRAY( d.deptName, d.id, d.blobColumn ) FROM department d WHERE id = 405; drop table json_table; drop table department; create table misc_dt ( id int, py polygon ); insert into misc_dt values ( 1, ST_GeomFromText('POLYGON((0 0,10 0,10 10,0 10,0 0), (5 5,7 5,7 7,5 7, 5 5))') ), ( 2, null ); select id, json_array( true, py, false ) from misc_dt order by id; drop table misc_dt; # construct from data in a table create table jro ( a int, b varchar( 10 ), c boolean ); insert into jro( a, b, c ) values ( 0, 'zero', false ), ( 1, 'one', true ), ( null, null, null ); select a, json_object( 'a', a, 'b', b, 'c', c ) from jro order by a; drop table jro; create table jro2( a int, b varchar( 10 ), c json ); insert into jro2 ( a, b, c ) values ( 1, 'array', '[ 1, 2, 3 ]' ), ( 2, 'object', '{ "d": "foo", "e": true }' ); select a, json_object( 'type', b, 'value', c ) from jro2 order by a; drop table jro2; # examples from the wl7909 spec create table department( id int, deptName varchar(50), isExempt boolean, blobColumn blob ); insert into department values ( 405, 'Accounting', true, '<a><b>ccc</b><d></d></a>' ); # returns {"deptName": "Accounting", "id": 405, "isExempt": true, "date": 2014-11-0400:00:00.000000} SELECT JSON_OBJECT ( 'deptName', d.deptName, 'id', d.id, 'isExempt', d.isExempt and true ) FROM department d WHERE id = 405; drop table department; # key names which aren't strings create table misc_dt ( py polygon ); insert into misc_dt values ( ST_GeomFromText('POLYGON((0 0,10 0,10 10,0 10,0 0), (5 5,7 5,7 7,5 7, 5 5))') ); --error ER_INVALID_JSON_CHARSET select json_object( py, 'def' ) from misc_dt; drop table misc_dt; create table json_search_table( id_col int, json_col json ); insert into json_search_table values ( 1, '{ "a": "foobar" }' ), ( 2, '{ "a": "foobar", "b": "focus", "c": [ "arm", "foot", "shoulder" ] }' ); select id_col, json_search( json_col, 'all', 'foo%' ) from json_search_table order by id_col; select id_col, json_search( json_col, 'all', 'foot' ) from json_search_table order by id_col; select id_col, json_search( json_col, 'all', 'f__us' ) from json_search_table order by id_col; # tests with path arguments delete from json_search_table; insert into json_search_table values ( 1, '{ "a": "foobar" }' ), ( 2, '{ "a": [ "foolish", "folly", "foolhardy" ], "b" : "fool" }' ); select id_col, json_search( json_col, 'all', 'foo%', null, '$.a' ) from json_search_table order by id_col; select id_col, json_search( json_col, 'all', 'foo%', null, '$.a', '$.b' ) from json_search_table order by id_col; select id_col, json_search( json_col, 'one', 'foo%', null, '$.a', '$.b' ) from json_search_table order by id_col; delete from json_search_table; insert into json_search_table values ( 1, '{ "a": "foobar" }' ), ( 2, '[ { "a": { "b": { "c": "fool" } } }, { "b": { "c": "shoulder" } }, { "c": { "c": "food"} } ]' ); select id_col, json_search( json_col, 'all', 'foo%', null, '$.a', '$**.c' ) from json_search_table order by id_col; select id_col, json_search( json_col, 'one', 'foo%', null, '$.a', '$**.c' ) from json_search_table order by id_col; drop table json_search_table; # verify that the double-quoted strings returned by json_search() # are valid path expressions when unpacked via json_unquote(). create table jep( key_col int primary key, doc json, path varchar( 50 ) ); insert into jep values ( 1, '{ "onepotato": "seven" }', '$.onepotato' ), ( 2, '{ "one potato": "seven" }', '$."one potato"' ), ( 3, '{ "one \\"potato": "seven" }', '$."one \\"potato"' ), ( 4, '{ "one \\npotato": "seven" }', '$."one \\npotato"' ); select key_col, json_search( doc, 'all', 'seven' ) paths, json_unquote( cast( json_search( doc, 'all', 'seven' ) as char ) ) unquoted, path from jep order by key_col; drop table jep; --echo # ---------------------------------------------------------------------- --echo # Test of CASE and IF expressions returning JSON --echo # ---------------------------------------------------------------------- create table t(j json); insert into t values (null), ('[3,4,5]'); select json_type(case (j is null) when 1 then cast('null' as json) else cast('[1,2,3]' as json) end) from t order by j; # no else clause select json_type(case (j is null) when 1 then cast(1 as json) end) from t order by j; select json_type( if(j is null, cast('{"a": 6}' as json), cast('[1,2,3]' as json))) from t order by j; select json_type( if(j is null, NULL, cast('[1,2,3]' as json)) ) from t order by j; --echo # ---------------------------------------------------------------------- --echo # Test of CASE and IF expressions with mix of JSON and other types --echo # Common result type is VARCHAR --echo # ---------------------------------------------------------------------- select json_type(case (j is null) when 1 then 3.14 else cast('[1,2,3]' as json) end) from t order by j; select case (j is null) when 1 then 3.14 else cast('[1,2,3]' as json) end from t order by j; select case (j is null) when 1 then 'foobar' else cast('[1,2,3]' as json) end from t order by j; select json_type( if(j is null, 3.14, cast('[1,2,3]' as json))) from t order by j; select if(j is null, 3.14, cast('[1,2,3]' as json)) from t order by j; --echo # ---------------------------------------------------------------------- --echo # Test of IFNULL --echo # ---------------------------------------------------------------------- select json_type(ifnull(j, cast(3 as json))) from t order by j; select ifnull(j, cast(3 as json)) from t order by j; # json_type masked a bug select json_type(ifnull(NULL, cast(3 as json))); select json_type(ifnull(cast(3 as json), NULL)); --error ER_INVALID_JSON_TEXT_IN_PARAM SELECT JSON_TYPE(IFNULL(JSON_EXTRACT(CONCAT(t1.j, 'abc'), '$'), t2.j)) FROM t t1, t t2; --error ER_INVALID_JSON_TEXT_IN_PARAM SELECT JSON_TYPE(IFNULL(t1.j, JSON_EXTRACT(CONCAT(t2.j, 'abc'), '$'))) FROM t t1, t t2; --echo # ---------------------------------------------------------------------- --echo # Json values used in text contexts --echo # ---------------------------------------------------------------------- delete from t; insert into t values (NULL), (cast('"aBc"' as json)); select upper(j) from t order by j; delete from t; insert into t values (cast(1 as json)), (cast(10 as json)), (cast(2 as json)); select * from t order by j; select max(j) from t; select json_type(max(j)) from t; select min(j) from t; select json_type(max(j)) from t; # if we want another sorting, cast to suitable type select max(cast(j as unsigned)) from t; --error ER_INVALID_TYPE_FOR_JSON select json_type(max(cast(j as unsigned))) from t; drop table t; --echo # ---------------------------------------------------------------------- --echo # Test JSON arguments and return values of stored functions --echo # ---------------------------------------------------------------------- create function make_message ( sender varchar(50), receiver varchar(50), subject text, received datetime, body text ) returns json language sql deterministic no sql return json_object ( 'sender', sender, 'receiver', receiver, 'subject', subject, 'received', received, 'body', body ); create function extract_date( message json ) returns datetime language sql deterministic no sql return json_extract( message, '$.received' ); create table messages ( id int, raw_message json ); insert into messages(id, raw_message) values ( 1, make_message ( 'fred', 'alice', 'lunch today?', timestamp( '2015-05-11 09:30:05' ), 'How about lunch at 11:30?' ) ), ( 2, make_message ( 'alice', 'fred', 're: lunch today?', timestamp( '2015-05-11 09:45:05' ), 'Sorry. I am in meetings all day long.' ) ), ( 3, json_object ( 'sender', 'fred', 'receiver', 'alice', 'subject', 're: lunch today?', 'received', timestamp( '2015-05-11 09:50:05' ), 'body', 'Oh, bummer.' ) ) ; select * from messages order by id; # should be DATETIME select json_type ( json_extract ( json_object ( 'sender', 'fred', 'receiver', 'alice', 'subject', 'lunch today?', 'received', timestamp( '2015-05-11 09:45:05' ), 'body', 'How about lunch at 11:30?' ), '$.received' ) ) received_type ; select id, extract_date( raw_message ) extracted_date from messages order by id; create function show_received_type( message json ) returns tinytext language sql deterministic no sql return json_type( json_extract( message, '$.received' ) ); # should be DATETIME select show_received_type ( json_object ( 'sender', 'fred', 'receiver', 'alice', 'subject', 're: lunch today?', 'received', timestamp( '2015-05-11 09:50:05' ), 'body', 'Oh, bummer.' ) ) received_type; # should be DATETIME select show_received_type ( make_message ( 'fred', 'alice', 'lunch today?', timestamp( '2015-05-11 09:30:05' ), 'How about lunch at 11:30?' ) ) received_type; # should be DATETIME select id, show_received_type( raw_message ) received_type from messages order by id; drop function show_received_type; drop function make_message; drop function extract_date; drop table messages; --echo # Test a function that fails. CREATE FUNCTION func_that_fails() RETURNS JSON LANGUAGE SQL DETERMINISTIC NO SQL RETURN '[not valid json]'; --error ER_INVALID_JSON_TEXT SELECT JSON_EXTRACT(func_that_fails(), '$'); DROP FUNCTION func_that_fails; # test a more complicated stored function which declares a JSON variable delimiter //; create function get_types( input_value json ) returns json language sql deterministic contains sql begin declare array_length integer; declare return_value json; declare idx int; declare path varchar(100); set array_length = json_length( input_value ); set return_value = json_array(); set idx = 0; while idx < array_length do set path = concat( '$[', idx, ']' ); set return_value = json_array_append ( return_value, '$', json_type( json_extract( input_value, path ) ) ); set idx = idx + 1; end while; return return_value; end// delimiter ;// create table blob_table( blob_col blob ); insert into blob_table values( '10101abcde' ); select json_type( dt.a ), dt.a from ( select get_types ( json_array ( cast( '{}' as json ), cast( '[]' as json ), 'null', true, 1, 2.3, timestamp( '2015-05-11 09:30:05' ), cast('23:24:25' as time), cast('2015-01-15' as date), b'10101', blob_col ) ) a from blob_table ) dt; drop table blob_table; drop function get_types; delimiter //; create procedure merge_docs ( inout inout_value json ) begin set inout_value = json_object(); end// delimiter ;// delimiter //; create procedure merge_doc_types() begin declare proc_inout json; declare tmp_types varchar(100); set proc_inout = null; call merge_docs( proc_inout ); set tmp_types = json_type( proc_inout ); end// delimiter ;// call merge_doc_types(); drop procedure merge_doc_types; drop procedure merge_docs; delimiter //; create function get_types( input_value json ) returns json language sql deterministic contains sql begin declare array_length integer; declare return_value json; declare idx int; declare path varchar(100); set array_length = json_length( input_value ); set return_value = json_array(); set idx = 0; while idx < array_length do set path = concat( '$[', idx, ']' ); set return_value = json_array_append ( return_value, '$', json_type( json_extract( input_value, path ) ) ); set idx = idx + 1; end while; return return_value; end// delimiter ;// delimiter //; create procedure merge_docs ( in in_value json, inout inout_value json, out out_value json ) language sql deterministic contains sql begin set out_value = json_merge_preserve(in_value, inout_value); set inout_value = in_value; end// delimiter ;// delimiter //; create procedure merge_doc_types ( out in_types varchar(100), out inout_types varchar(100), out out_types varchar(100) ) language sql deterministic contains sql begin declare proc_in json; declare proc_inout json; declare proc_out json; set proc_in = json_array ( cast( '{}' as json ), cast( '[]' as json ), 'null', true ); set proc_inout = json_array ( 1, 2.3, timestamp( '2015-05-11 09:30:05' ), cast('23:24:25' as time), cast('2015-01-15' as date), b'10101' ); set proc_out = null; call merge_docs( proc_in, proc_inout, proc_out ); set in_types = get_types( proc_in ); set inout_types = get_types( proc_inout ); set out_types = get_types( proc_out ); end// delimiter ;// call merge_doc_types( @in_types, @inout_types, @out_types ); select @in_types, @inout_types, @out_types; drop procedure merge_doc_types; drop procedure merge_docs; drop function get_types; --echo # --echo # Bug#20898238: WRONG RESULT FOR MAX() OF JSON SCALARS RETURNED --echo # WHEN NULL IS PRESENT --echo # CREATE TABLE bug20898238(j JSON); INSERT INTO bug20898238 VALUES ('{"id":1}'), (NULL), ('{"id":2}'), ('{"id":0}'); SELECT MIN(JSON_EXTRACT(j, '$.id')), MAX(JSON_EXTRACT(j, '$.id')) FROM bug20898238; DROP TABLE bug20898238; --echo # ---------------------------------------------------------------------- --echo # Test of aggregate function SUM, AVG: in constrast to strings, we do not --echo # auto-convert to numeric (double) type: --echo # ---------------------------------------------------------------------- create table t(j json, c varchar(20)); insert into t values (cast('[1,2,3]' as json), '[a,b,c]'); insert into t values (cast(7 as json), '7'), (cast(2 as json), '2'); --disable_warnings select sum(j), sum(cast(j as unsigned)), sum(c) from t; select avg(j), avg(cast(j as unsigned)), avg(c) from t; --enable_warnings --echo # ---------------------------------------------------------------------- --echo # Test of aggregate function COUNT(DISTINCT) and unaggregated DISTINCT --echo # ---------------------------------------------------------------------- create table t_doc( bucket int, doc json); insert into t_doc values ( 1, cast( 1 as json ) ), ( 1, cast( 1.0 as json ) ), ( 1, cast( 1e0 as json ) ), ( 2, cast( cast( 1 as unsigned ) as json ) ), ( 2, cast( 2 as json ) ), ( 2, cast( 2.0 as json ) ), ( 3, cast( 2e0 as json ) ), ( 3, cast( cast( 7 as unsigned ) as json ) ), ( 3, cast( 7 as json ) ), ( 4, cast( 7.0 as json ) ), ( 4, cast( 7e0 as json ) ), ( 4, cast( cast( 7 as unsigned ) as json ) ), ( 5, cast( true as json ) ), ( 5, cast( true as json ) ), ( 5, cast( false as json ) ), ( 6, cast( false as json ) ), ( 6, cast( 'null' as json ) ), ( 6, cast( 'null' as json ) ), ( 7, cast( '"abc"' as json ) ), ( 7, cast( '"abc"' as json ) ), ( 7, cast( '"abcd"' as json ) ), ( 8, cast( '"abcd"' as json ) ), ( 8, cast( '{ "a": 1, "b": 2 }' as json ) ), ( 8, cast( '{ "a": 1, "b": 2 }' as json ) ), ( 9, cast( '{ "a": 1, "b": 3 }' as json ) ), ( 9, cast( '{ "a": 1, "b": 3 }' as json ) ), ( 9, cast( '[ true, false ]' as json ) ), ( 10, cast( '[ true, false ]' as json ) ), ( 10, cast( '[ true, true ]' as json ) ); # The results depend on the order of evaluation of rows. # Values 7, 7.0, and 7e0 compare equal for distinct but the result # depends on which row is evaluated first so we remove .0 and e0. --replace_regex /\.0// /e0// select distinct( doc ) a from t_doc order by a; select count( distinct doc ) from t_doc; select bucket, count( distinct doc ) from t_doc group by bucket; delete from t_doc; create table dt(dati datetime, da date, tim time, ts timestamp, y year, -- ti tinyint, tiu tinyint unsigned, si smallint, siu smallint unsigned, mi mediumint, miu mediumint unsigned, i int, iu int unsigned, bi bigint, biu bigint unsigned, boo boolean, -- dc decimal(5,2), n numeric(5,2), -- f float, d double, bitt bit(10), blb blob, bin binary(10), en enum('a','b','c'), se set('a','b','c'), -- ge geometry, po point, ls linestring, py polygon, jso json, jsa json, id int ); # test with distinct values insert into dt values('2014-11-25 18:00', '2014-11-25', '18:00:59', '2014-11-25 17:00', '1999', -- 127, 255, 32767, 65535, 8388607, 16777215, -- 3 bytes 2147483647, 4294967295, -- 4 bytes 9223372036854775807, 18446744073709551615, true, -- 3.1, 3.2, -- 3.3, 3.4, b'10101', '10101abcde', '10001abcde', 'b', 'a,c', -- ST_GeomFromText('POINT(1 1)'), ST_GeomFromText('POINT(1 2)'), ST_GeomFromText('LINESTRING(0 0,1 1,2 2)'), ST_GeomFromText('POLYGON((0 0,10 0,10 10,0 10,0 0), (5 5,7 5,7 7,5 7, 5 5))'), '{"a": 1, "b": 2 }', '[1, 2]', 1 ), ('2013-11-25 18:00', '2013-11-25', '17:00:59', '2013-11-25 17:00', '1998', -- 126, 254, 32766, 65534, 8388606, 16777214, -- 3 bytes 2147483646, 4294967294, -- 4 bytes 9223372036854775806, 18446744073709551614, false, -- 4.1, 4.2, -- 4.3, 4.4, b'10111', '10001abcdf', '10101abcdf', 'a', 'a,b', -- ST_GeomFromText('POINT(1 3)'), ST_GeomFromText('POINT(1 4)'), ST_GeomFromText('LINESTRING(0 0,1 1,2 3)'), ST_GeomFromText('POLYGON((0 0,10 0,10 10,0 9,0 0), (5 5,7 5,7 7,5 7, 5 5))'), '{"a": 1, "b": 3 }', '[1, 3]', 2 ); # types whose representations are unstable across platforms insert into t_doc select id, cast(f as json) from dt; insert into t_doc select id, cast(d as json) from dt; insert into t_doc select * from t_doc; select count( distinct doc ) from t_doc; select bucket, count( distinct doc ) from t_doc group by bucket; delete from t_doc; # types which have stable representations across platforms insert into t_doc select id, cast(dati as json) from dt; insert into t_doc select id, cast(da as json) from dt; insert into t_doc select id, cast(tim as json) from dt; insert into t_doc select id, cast(ts as json) from dt; insert into t_doc select id, cast(y as json) from dt; insert into t_doc select id, cast(ti as json) from dt; insert into t_doc select id, cast(tiu as json) from dt; insert into t_doc select id, cast(si as json) from dt; insert into t_doc select id, cast(siu as json) from dt; insert into t_doc select id, cast(mi as json) from dt; insert into t_doc select id, cast(miu as json) from dt; insert into t_doc select id, cast(i as json) from dt; insert into t_doc select id, cast(iu as json) from dt; insert into t_doc select id, cast(bi as json) from dt; insert into t_doc select id, cast(biu as json) from dt; # FIXME: booleans don't retain their boolean values. they become ints. #insert into t_doc select id, cast(boo as json) from dt; insert into t_doc select id, cast(dc as json) from dt; insert into t_doc select id, cast(n as json) from dt; insert into t_doc select id, cast(bitt as json) from dt; insert into t_doc select id, cast(blb as json) from dt; insert into t_doc select id, cast(bin as json) from dt; insert into t_doc select id, cast(en as json) from dt; insert into t_doc select id, cast(se as json) from dt; insert into t_doc select id, cast(ge as json) from dt; insert into t_doc select id, cast(po as json) from dt; insert into t_doc select id, cast(ls as json) from dt; insert into t_doc select id, cast(py as json) from dt; insert into t_doc select id, jso from dt; insert into t_doc select id, jsa from dt; insert into t_doc select * from t_doc; #The results depend on the order of evaluation of rows select distinct( doc ) a from t_doc order by a; select count( distinct doc ) from t_doc; select bucket, count( distinct doc ) from t_doc group by bucket; # test with non-distinct values delete from t_doc; create table ndt(dati datetime, ts timestamp, -- ti tinyint, tiu tinyint unsigned, si smallint, siu smallint unsigned, mi mediumint, miu mediumint unsigned, i int, iu int unsigned, bi bigint, biu bigint unsigned, -- dc decimal(5,2), n numeric(5,2), -- f float, d double, id int ); insert into ndt values('2014-11-25 18:00', '2014-11-25 18:00', -- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -- 1.0, 1.0, -- 1.0, 1.0, 1 ), ('2013-11-25 18:00', '2013-11-25 18:00', -- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, -- 2.0, 2.0, -- 2.0, 2.0, 2 ); insert into t_doc select id, cast(dati as json) from ndt; insert into t_doc select id, cast(ts as json) from ndt; insert into t_doc select id, cast(ti as json) from ndt; insert into t_doc select id, cast(tiu as json) from ndt; insert into t_doc select id, cast(si as json) from ndt; insert into t_doc select id, cast(siu as json) from ndt; insert into t_doc select id, cast(mi as json) from ndt; insert into t_doc select id, cast(miu as json) from ndt; insert into t_doc select id, cast(i as json) from ndt; insert into t_doc select id, cast(iu as json) from ndt; insert into t_doc select id, cast(bi as json) from ndt; insert into t_doc select id, cast(biu as json) from ndt; insert into t_doc select id, cast(dc as json) from ndt; insert into t_doc select id, cast(n as json) from ndt; insert into t_doc select id, cast(f as json) from ndt; insert into t_doc select id, cast(d as json) from ndt; insert into t_doc select * from t_doc; # The results depend on the order of evaluation of rows #select distinct( doc ) a from t_doc order by a; select count( distinct doc ) from t_doc; select bucket, count( distinct doc ) from t_doc group by bucket; drop table t_doc; drop table dt; drop table ndt; --echo # ---------------------------------------------------------------------- --echo # Special CASTing behavior of geometry types --echo # ---------------------------------------------------------------------- create table jtable( id int, descr varchar(20), doc json ); create table misc_dt ( ge geometry, po point, ls linestring, py polygon ); insert into misc_dt values ( ST_GeomFromText('POINT(1 1)'), ST_GeomFromText('POINT(1 1)'), ST_GeomFromText('LINESTRING(0 0,1 1,2 2)'), ST_GeomFromText('POLYGON((0 0,10 0,10 10,0 10,0 0), (5 5,7 5,7 7,5 7, 5 5))') ); insert into jtable select 1, 'geometry', cast(ge as json) from misc_dt; insert into jtable select 2, 'point', cast(po as json) from misc_dt; insert into jtable select 3, 'linestring', cast(ls as json) from misc_dt; insert into jtable select 4, 'polygon', cast(py as json) from misc_dt; # select id, descr, json_type( doc ), doc from jtable order by id; select json_object ( 'geometry', ST_GeomFromText('POINT(1 1)'), 'point', ST_GeomFromText('POINT(1 1)'), 'linestring', ST_GeomFromText('LINESTRING(0 0,1 1,2 2)'), 'polygon', ST_GeomFromText('POLYGON((0 0,10 0,10 10,0 10,0 0), (5 5,7 5,7 7,5 7, 5 5))') ); # verify the workaround for CASTing JSON values to GEOMETRY delete from misc_dt; select * from misc_dt; insert into misc_dt values ( (select ST_GeomFromGeoJSON( cast( doc as char ) ) from jtable where id = 1), (select ST_GeomFromGeoJSON( cast( doc as char ) ) from jtable where id = 2), (select ST_GeomFromGeoJSON( cast( doc as char ) ) from jtable where id = 3), (select ST_GeomFromGeoJSON( cast( doc as char ) ) from jtable where id = 4) ); select ST_AsGeoJSON( ge ), ST_AsGeoJSON( po ), ST_AsGeoJSON( ls ), ST_AsGeoJSON( py ) from misc_dt; drop table misc_dt; drop table jtable; create table jtable( id int, descr varchar(20), doc json ); create table misc_dt ( ge geometrycollection, po multipoint, ls multilinestring, py multipolygon ); insert into misc_dt values ( geometrycollection(point(1, 1), point(2, 2)), multipoint(point(1, 1), point(2, 2)), multilinestring ( linestring(point(0, 0), point(1, 1), point(2, 2)), linestring(point(0, 0), point(11, 11), point(12, 12)) ), multipolygon ( polygon ( linestring(point(0, 0), point(10, 0), point(10, 10), point(0, 10), point(0, 0)), linestring(point(5, 5), point(7, 5), point(7, 7), point(5, 7), point(5, 5)) ), polygon ( linestring(point(0, 0), point(10, 0), point(10, 10), point(0, 10), point(0, 0)), linestring(point(5, 5), point(7, 5), point(7, 7), point(5, 7), point(5, 5)) ) ) ); insert into jtable select 1, 'geometrycollection', cast(ge as json) from misc_dt; insert into jtable select 2, 'multipoint', cast(po as json) from misc_dt; insert into jtable select 3, 'multilinestring', cast(ls as json) from misc_dt; insert into jtable select 4, 'multipolygon', cast(py as json) from misc_dt; # select id, descr, json_type( doc ), doc from jtable order by id; select ST_AsGeoJSON( ge ), ST_AsGeoJSON( po ), ST_AsGeoJSON( ls ), ST_AsGeoJSON( py ) from misc_dt; delete from misc_dt; select * from misc_dt; insert into misc_dt values ( (select ST_GeomFromGeoJSON( cast( doc as char ) ) from jtable where id = 1), (select ST_GeomFromGeoJSON( cast( doc as char ) ) from jtable where id = 2), (select ST_GeomFromGeoJSON( cast( doc as char ) ) from jtable where id = 3), (select ST_GeomFromGeoJSON( cast( doc as char ) ) from jtable where id = 4) ); select ST_AsGeoJSON( ge ), ST_AsGeoJSON( po ), ST_AsGeoJSON( ls ), ST_AsGeoJSON( py ) from misc_dt; drop table misc_dt; drop table jtable; --echo # ---------------------------------------------------------------------- --echo # Test of COALESCE --echo # ---------------------------------------------------------------------- select coalesce(cast(1 as json), cast(2 as json)); select coalesce(j, cast(3 as json)) from t order by c; select coalesce(j, 666) from t order by c; select json_type(coalesce(j, '[1,2,3]')) from t order by c; select json_type(coalesce(j, 'abc')) from t order by c; select json_type(coalesce(j, cast('"arg2"' as json))) from t order by c; select json_type(coalesce(j, j)) from t order by c; --echo inconsistent result: error message depends on the order of evaluation of rows --echo --error ER_INVALID_JSON_TEXT_IN_PARAM --echo select json_type(coalesce(json_extract(concat(j, 'abc'), '\$'), j)) from t; --echo --error ER_INVALID_JSON_TEXT_IN_PARAM --echo #select json_type(coalesce(t1.j, json_extract(concat(t2.j, 'abc'), '\$'))) --echo from t t1, t t2; drop table t; --echo # ---------------------------------------------------------------------- --echo # Auto-convert of non-utf8 returning system function --echo # ---------------------------------------------------------------------- create table t(j json, id int); insert into t values ('{"user": "foo"}', 8), (NULL, 8); update t set j=json_set(j, '$.user', current_user()) where id=8; select j from t order by j; update t set j=json_set(j, '$.user', rtrim('foo ')) where id=8; select j from t order by j; update t set j=json_set(j, '$.user', hex('abc')) where id=8; select j from t order by j; update t set j=json_set(j, '$.user', md5('bingle')) where id=8; select j from t order by j; update t set j=json_set(j, '$.user', database()) where id=8; select j from t order by j; update t set j=json_set(j, '$.user', schema()) where id=8; select j from t order by j; # # The hex of some UTF-8 from supplementary plane: U+2070E update t set j=json_set(j, '$.user', cast(UNHEX('F0A09C8E') as char character set 'utf8mb4')) where id=8; set names 'utf8mb4'; # se we can see the character select j from t order by j; select char_length(json_extract(j, '$.user')) from t order by j; drop table t; --echo # --echo # Bug#21257946 JSON_TYPE(TEXT) OF TABLE COLUMN STICKS WITH NULL --echo # AFTER FIRST ENCOUNTER OF NULL --echo # CREATE TABLE T_WITH_NULLS(i INT, j JSON); INSERT INTO T_WITH_NULLS VALUES (0, NULL), (1, '[1]'), (2, NULL), (3, '{"a":"b"}'), (4, NULL), (5, '"abc"'); let $query= SELECT JSON_VALID(j), JSON_TYPE(j), JSON_KEYS(j), JSON_EXTRACT(j, '\$'), JSON_REMOVE(j, '\$.a.b.c'), JSON_ARRAY_APPEND(j, '\$', 2), JSON_SET(j, '\$[0]', 2), JSON_INSERT(j, '\$[0]', 2), JSON_REPLACE(j, '\$[0]', 2), JSON_MERGE_PRESERVE(j, j), JSON_SEARCH(j, 'one', 'abc'), JSON_CONTAINS(j, '[1]'), JSON_CONTAINS_PATH(j, 'all', '\$.a'), JSON_LENGTH(j), JSON_DEPTH(j), JSON_ARRAY(j, j), JSON_OBJECT('k', j), JSON_UNQUOTE(CAST(j AS CHAR)), JSON_QUOTE(CAST(j AS CHAR)), JSON_PRETTY(j), JSON_STORAGE_SIZE(j) FROM T_WITH_NULLS ORDER BY i; eval $query; # It should work the same way with a TEXT column as with a JSON column. ALTER TABLE T_WITH_NULLS MODIFY COLUMN j TEXT; eval $query; DROP TABLE T_WITH_NULLS; # Make sure that every JSON function accepts latin1 text arguments. The JSON # functions use utf8mb4 internally, so they will need to perform charset # conversion. CREATE TABLE t_latin1(id INT PRIMARY KEY AUTO_INCREMENT, json_text VARCHAR(20), json_atom_text VARCHAR(20), json_path VARCHAR(20)) CHARACTER SET 'latin1'; INSERT INTO t_latin1 (json_text, json_atom_text, json_path) VALUES (CONVERT(X'5B22E6F8E5225D' USING latin1), # ["\u00e6\u00f8\u00e5"] CONVERT(X'E5F8E6' USING latin1), # \u00e5\u00f8\u00e6 '$[0]'), (CONVERT(X'7B22E6F8E5223A22E6F8E5227D' USING latin1), # {"\u00e6\u00f8\u00e5":"\u00e6\u00f8\u00e5"} CONVERT(X'E5F8E6' USING latin1), # \u00e5\u00f8\u00e6 CONVERT(X'242E22E6F8E522' USING latin1)); # $."\u00e6\u00f8\u00e5" SELECT * FROM t_latin1 ORDER BY id; SELECT CAST(json_text AS JSON) FROM t_latin1 ORDER BY id; SELECT JSON_VALID(json_text) FROM t_latin1 ORDER BY id; SELECT JSON_VALID(json_atom_text) FROM t_latin1 ORDER BY id; SELECT JSON_TYPE(json_text) FROM t_latin1 ORDER BY id; SELECT JSON_EXTRACT(json_text, json_path) FROM t_latin1 ORDER BY id; SELECT JSON_REMOVE(json_text, json_path) FROM t_latin1 ORDER BY id; SELECT JSON_ARRAY_APPEND(json_text, json_path, json_atom_text) FROM t_latin1 ORDER BY id; SELECT JSON_SET(json_text, json_path, json_atom_text) FROM t_latin1 ORDER BY id; SELECT JSON_INSERT(json_text, json_path, json_atom_text) FROM t_latin1 ORDER BY id; SELECT JSON_REPLACE(json_text, json_path, json_atom_text) FROM t_latin1 ORDER BY id; SELECT JSON_MERGE_PRESERVE(json_text, json_text) FROM t_latin1 ORDER BY id; SELECT JSON_SEARCH(json_text, CONVERT('one' USING latin1), json_atom_text, CONVERT(X'F8' USING latin1), json_path) FROM t_latin1 ORDER BY id; SELECT JSON_CONTAINS(json_text, json_text, json_path) FROM t_latin1 ORDER BY id; SELECT JSON_CONTAINS_PATH(json_text, CONVERT('one' USING latin1), json_path) FROM t_latin1 ORDER BY id; SELECT JSON_LENGTH(json_text, json_path) FROM t_latin1 ORDER BY id; SELECT JSON_DEPTH(json_text) FROM t_latin1 ORDER BY id; SELECT JSON_ARRAY(json_atom_text, json_atom_text) FROM t_latin1 ORDER BY id; SELECT JSON_OBJECT(json_atom_text, json_atom_text) FROM t_latin1 ORDER BY id; SELECT JSON_UNQUOTE(json_atom_text) FROM t_latin1 ORDER BY id; SELECT JSON_UNQUOTE(CONVERT(CONCAT('"', json_atom_text, '"') USING latin1)) FROM t_latin1 ORDER BY id; SELECT JSON_QUOTE(json_atom_text) FROM t_latin1 ORDER BY id; DROP TABLE t_latin1; --echo # ---------------------------------------------------------------------- --echo # Test that boolean expressions are treated as boolean atom literals --echo # ---------------------------------------------------------------------- create table t_bool_literals( a int, b varchar(10) ); insert into t_bool_literals values ( 1, 'food' ), ( 2, 'fool' ), ( 3, 'water' ); # expressions built out of logical connectives should evaluate to boolean literals, but they don't select a, json_array( ((a < 3) and (a > 1)) ) from t_bool_literals order by a; select a, json_array_append( '[]', '$', ((a < 3) and (a > 1)) ) from t_bool_literals order by a; select a, json_array( not ((a < 3) and (a > 1)) ) from t_bool_literals order by a; select a, json_array_append( '[]', '$', not ((a < 3) and (a > 1)) ) from t_bool_literals order by a; select a, json_array( ((a < 3) or (a > 1)) ) from t_bool_literals order by a; select a, json_array_append( '[]', '$', ((a < 3) or (a > 1)) ) from t_bool_literals order by a; select a, json_array( not ((a < 3) or (a > 1)) ) from t_bool_literals order by a; select a, json_array_append( '[]', '$', not ((a < 3) or (a > 1)) ) from t_bool_literals order by a; select json_array( not true, not false ); select json_array_append( '[]', '$', not true, '$', not false ); select a, json_array( 1 and true ) from t_bool_literals order by a; select a, json_array_append( '[]', '$', 1 and true ) from t_bool_literals order by a; select a, json_array( not 1 ) from t_bool_literals order by a; select a, json_array_append( '[]', '$', not 1 ) from t_bool_literals order by a; # true and false literals select json_array( true, false ); select json_array_append( '[]', '$', true, '$', false ); # comparison operators should evaluate to boolean literals select a, json_array( (a < 3) ) from t_bool_literals order by a; select a, json_array_append( '[]', '$', (a < 3) ) from t_bool_literals order by a; select a, json_array( (a <= 3) ) from t_bool_literals order by a; select a, json_array_append( '[]', '$', (a <= 3) ) from t_bool_literals order by a; select a, json_array( (a > 3) ) from t_bool_literals order by a; select a, json_array_append( '[]', '$', (a > 3) ) from t_bool_literals order by a; select a, json_array( (a >= 3) ) from t_bool_literals order by a; select a, json_array_append( '[]', '$', (a >= 3) ) from t_bool_literals order by a; select a, json_array( (a <> 3) ) from t_bool_literals order by a; select a, json_array_append( '[]', '$', (a <> 3) ) from t_bool_literals order by a; select a, json_array( (a != 3) ) from t_bool_literals order by a; select a, json_array_append( '[]', '$', (a != 3) ) from t_bool_literals order by a; # IS NULL and IS NOT NULL select a, json_array( a is null ) from t_bool_literals order by a; select a, json_array_append( '[]', '$', a is null ) from t_bool_literals order by a; select a, json_array( a is not null ) from t_bool_literals order by a; select a, json_array_append( '[]', '$', a is not null ) from t_bool_literals order by a; # IS TRUE and IS NOT TRUE select a, json_array( a is true ) from t_bool_literals order by a; select a, json_array_append( '[]', '$', a is true ) from t_bool_literals order by a; select a, json_array( a is not true ) from t_bool_literals order by a; select a, json_array_append( '[]', '$', a is not true ) from t_bool_literals order by a; # NULLIF which coalesce booleans should evaluate to boolean literals select a, json_array(nullif(true, false) ) from t_bool_literals order by a; select a, json_array_append ( '[]', '$', nullif(true, false) ) from t_bool_literals order by a; # would be nice if CASE coalesced a boolean type if all branches are boolean. FIXME maybe #select a, json_array( case when (a > 1) then true else false end ) from t_bool_literals order by a; #select a, json_array_append #( # '[]', # '$', case when (a > 1) then true else false end #) from t_bool_literals order by a; # as a workaround, you can always AND problematic expressions with true select a, json_array( (case when (a > 1) then true else false end) and true ) from t_bool_literals order by a; select a, json_array_append ( '[]', '$', (case when (a > 1) then true else false end) and true ) from t_bool_literals order by a; # between predicates should evaluate to boolean literals select a, json_array( a between 2 and 4 ) from t_bool_literals order by a; select a, json_array_append( '[]', '$', a between 2 and 4 ) from t_bool_literals order by a; # in predicates should evaluate to boolean literals select a, json_array( a in (1,3) ) from t_bool_literals order by a; select a, json_array_append( '[]', '$', a in (1,3) ) from t_bool_literals order by a; # like predicates should evaluate to boolean literals select a, json_array( b like 'foo%' ) from t_bool_literals order by a; select a, json_array_append( '[]', '$', b like 'foo%' ) from t_bool_literals order by a; # regexp predicates should evaluate to boolean literals select a, json_array( b REGEXP '^fo+d' ) from t_bool_literals order by a; select a, json_array_append( '[]', '$', b REGEXP '^fo+d' ) from t_bool_literals order by a; select a, json_array( b rlike '^fo+d' ) from t_bool_literals order by a; select a, json_array_append( '[]', '$', b rlike '^fo+d' ) from t_bool_literals order by a; select a, json_array( b not REGEXP '^fo+d' ) from t_bool_literals order by a; select a, json_array_append( '[]', '$', b not REGEXP '^fo+d' ) from t_bool_literals order by a; select a, json_array( b not rlike '^fo+d' ) from t_bool_literals order by a; select a, json_array_append( '[]', '$', b not rlike '^fo+d' ) from t_bool_literals order by a; # quantified comparisons should evaluate to boolean literals select a, json_array( b = some( select b from t_bool_literals ) ) from t_bool_literals order by a; select a, json_array_append( '[]', '$', b = some( select b from t_bool_literals ) ) from t_bool_literals order by a; select a, json_array( b = all( select b from t_bool_literals ) ) from t_bool_literals order by a; select a, json_array_append( '[]', '$', b = all( select b from t_bool_literals ) ) from t_bool_literals order by a; select a, json_array( b = any( select b from t_bool_literals ) ) from t_bool_literals order by a; select a, json_array_append( '[]', '$', b = any( select b from t_bool_literals ) ) from t_bool_literals order by a; select a, json_array( b > some( select b from t_bool_literals ) ) from t_bool_literals order by a; select a, json_array_append( '[]', '$', b > some( select b from t_bool_literals ) ) from t_bool_literals order by a; select a, json_array( b > all( select b from t_bool_literals ) ) from t_bool_literals order by a; select a, json_array_append( '[]', '$', b > all( select b from t_bool_literals ) ) from t_bool_literals order by a; select a, json_array( b > any( select b from t_bool_literals ) ) from t_bool_literals order by a; select a, json_array_append( '[]', '$', b > any( select b from t_bool_literals ) ) from t_bool_literals order by a; select a, json_array( b < some( select b from t_bool_literals ) ) from t_bool_literals order by a; select a, json_array_append( '[]', '$', b < some( select b from t_bool_literals ) ) from t_bool_literals order by a; select a, json_array( b < all( select b from t_bool_literals ) ) from t_bool_literals order by a; select a, json_array_append( '[]', '$', b < all( select b from t_bool_literals ) ) from t_bool_literals order by a; select a, json_array( b < any( select b from t_bool_literals ) ) from t_bool_literals order by a; select a, json_array_append( '[]', '$', b < any( select b from t_bool_literals ) ) from t_bool_literals order by a; select a, json_array( b <= some( select b from t_bool_literals ) ) from t_bool_literals order by a; select a, json_array_append( '[]', '$', b <= some( select b from t_bool_literals ) ) from t_bool_literals order by a; select a, json_array( b <= all( select b from t_bool_literals ) ) from t_bool_literals order by a; select a, json_array_append( '[]', '$', b <= all( select b from t_bool_literals ) ) from t_bool_literals order by a; select a, json_array( b <= any( select b from t_bool_literals ) ) from t_bool_literals order by a; select a, json_array_append( '[]', '$', b <= any( select b from t_bool_literals ) ) from t_bool_literals order by a; select a, json_array( b >= some( select b from t_bool_literals ) ) from t_bool_literals order by a; select a, json_array_append( '[]', '$', b >= some( select b from t_bool_literals ) ) from t_bool_literals order by a; select a, json_array( b >= all( select b from t_bool_literals ) ) from t_bool_literals order by a; select a, json_array_append( '[]', '$', b >= all( select b from t_bool_literals ) ) from t_bool_literals order by a; select a, json_array( b >= any( select b from t_bool_literals ) ) from t_bool_literals order by a; select a, json_array_append( '[]', '$', b >= any( select b from t_bool_literals ) ) from t_bool_literals order by a; # exists predicates should evaluate to boolean literals select a, json_array( exists( select b from t_bool_literals where a = 1 ) ) from t_bool_literals order by a; select a, json_array_append( '[]', '$', exists( select b from t_bool_literals where a = 1 ) ) from t_bool_literals order by a; select a, json_array( not exists( select b from t_bool_literals where a = 1 ) ) from t_bool_literals order by a; select a, json_array_append( '[]', '$', not exists( select b from t_bool_literals where a = 1 ) ) from t_bool_literals order by a; # json_valid() calls should evaluate to boolean literals select a, json_array( json_valid( b ) ) from t_bool_literals order by a; select a, json_array_append( '[]', '$', json_valid( b ) ) from t_bool_literals order by a; select a, json_array( not json_valid( b ) ) from t_bool_literals order by a; select a, json_array_append( '[]', '$', not json_valid( b ) ) from t_bool_literals order by a; # json_contains_path() calls should evaluate to boolean literals select json_array( json_contains_path( '{ "a" : { "b" : 100 } }', 'all', '$.a.b' ) ); # gtid_subset() calls should evaluate to boolean literals select a, json_array( gtid_subset('3E11FA47-71CA-11E1-9E33-C80AA9429562:23', '3E11FA47-71CA-11E1-9E33-C80AA9429562:21-57') ) from t_bool_literals order by a; select a, json_array_append( '[]', '$', gtid_subset('3E11FA47-71CA-11E1-9E33-C80AA9429562:23', '3E11FA47-71CA-11E1-9E33-C80AA9429562:21-57') ) from t_bool_literals order by a; select a, json_array( not gtid_subset('3E11FA47-71CA-11E1-9E33-C80AA9429562:23', '3E11FA47-71CA-11E1-9E33-C80AA9429562:21-57') ) from t_bool_literals order by a; select a, json_array_append( '[]', '$', not gtid_subset('3E11FA47-71CA-11E1-9E33-C80AA9429562:23', '3E11FA47-71CA-11E1-9E33-C80AA9429562:21-57') ) from t_bool_literals order by a; # comparisons to subqueries should evaluate to boolean literals select a, json_array( b = ( select distinct b from t_bool_literals where a = 1 ) ) from t_bool_literals order by a; select a, json_array_append( '[]', '$', b = ( select distinct b from t_bool_literals where a = 1 ) ) from t_bool_literals order by a; select a, json_array( b > ( select distinct b from t_bool_literals where a = 1 ) ) from t_bool_literals order by a; select a, json_array_append( '[]', '$', b > ( select distinct b from t_bool_literals where a = 1 ) ) from t_bool_literals order by a; select a, json_array( b >= ( select distinct b from t_bool_literals where a = 1 ) ) from t_bool_literals order by a; select a, json_array_append( '[]', '$', b >= ( select distinct b from t_bool_literals where a = 1 ) ) from t_bool_literals order by a; select a, json_array( b < ( select distinct b from t_bool_literals where a = 1 ) ) from t_bool_literals order by a; select a, json_array_append( '[]', '$', b < ( select distinct b from t_bool_literals where a = 1 ) ) from t_bool_literals order by a; select a, json_array( b <= ( select distinct b from t_bool_literals where a = 1 ) ) from t_bool_literals order by a; select a, json_array_append( '[]', '$', b <= ( select distinct b from t_bool_literals where a = 1 ) ) from t_bool_literals order by a; # make sure ordinary subselects still function correctly select a, json_array( ( select distinct a from t_bool_literals where a = 1 ) ) from t_bool_literals order by a; drop table t_bool_literals; --echo # ---------------------------------------------------------------------- --echo # Verify that all of the string types behave similarly when used as ANY_JSON_ATOMS --echo # ---------------------------------------------------------------------- create table t_char( a int, b char(20) ); insert into t_char values ( 1, 'foo' ); create table t_varchar( a int, b varchar(20) ); insert into t_varchar values ( 1, 'foo' ); Create table t_tinytext( a int, b tinytext ); insert into t_tinytext values ( 1, 'foo' ); create table t_text( a int, b text ); insert into t_text values ( 1, 'foo' ); create table t_mediumtext( a int, b mediumtext ); insert into t_mediumtext values ( 1, 'foo' ); create table t_longtext( a int, b longtext ); insert into t_longtext values ( 1, 'foo' ); # treated as a string. evaluates to ["foo"] select json_array( b ) from t_char; select json_array( b ) from t_varchar; select json_array( b ) from t_tinytext; select json_array( b ) from t_text; select json_array( b ) from t_mediumtext; select json_array( b ) from t_longtext; # casts to CHAR should still be strings select json_array( cast( b as char ) ) from t_char; select json_array( cast( b as char ) ) from t_varchar; select json_array( cast( b as char ) ) from t_tinytext; select json_array( cast( b as char ) ) from t_text; select json_array( cast( b as char ) ) from t_mediumtext; select json_array( cast( b as char ) ) from t_longtext; # string-valued XML functions should behave as strings when used as ANY_JSON_ATOMs select json_array( UpdateXML('<a><b>ccc</b><d></d></a>', '/a/d', '<e>fff</e>') ); select json_array( cast( UpdateXML('<a><b>ccc</b><d></d></a>', '/a/d', '<e>fff</e>') as char ) ); select json_array( ExtractValue('<r><n id="1">v1</n><n id="2">v2</n></r>','//n[@id=1]' ) ); select json_array( cast( ExtractValue('<r><n id="1">v1</n><n id="2">v2</n></r>','//n[@id=1]' ) as char ) ); drop table t_char; drop table t_varchar; drop table t_tinytext; drop table t_text; drop table t_mediumtext; drop table t_longtext; --echo # ---------------------------------------------------------------------- --echo # Check that JSON values stemming from views and derived tables work --echo # ---------------------------------------------------------------------- create table t(x int); insert into t values (NULL), (4); select json_array(x) from (select x from t) tt order by x; create view v as select * from t; select json_array(x) from v order by x; drop view v; drop table t; --echo # ---------------------------------------------------------------------- --echo # Ignore collation.collation when handing off val_str to a JSON field - --echo # bug found by John E. --echo # ---------------------------------------------------------------------- create table t3( col_json json ); insert into t3(col_json) values ( json_quote( '1' ) ); select * from t3; select json_type(col_json) from t3; drop table t3; --echo # ---------------------------------------------------------------------- --echo # Correctly escape key names when pretty-printing JSON objects. --echo # Correct behavior means that the strings can be re-used for --echo # their original purposes as key names and paths. --echo # ---------------------------------------------------------------------- create table jep( key_col int primary key, doc json, path varchar( 50 ) ); insert into jep values ( 1, '{ "one \\"potato": "seven" }', '$."one \\"potato"' ), ( 2, '{ "one \\npotato": "seven" }', '$."one \\npotato"' ), ( 3, '{ "one \\tpotato": "seven" }', '$."one \\tpotato"' ), ( 4, '{ "one \\bpotato": "seven" }', '$."one \\bpotato"' ), ( 5, '{ "one \\fpotato": "seven" }', '$."one \\fpotato"' ), ( 6, '{ "one \\rpotato": "seven" }', '$."one \\rpotato"' ), ( 7, '{ "one \\\\potato": "seven" }', '$."one \\\\potato"' ); insert into jep select key_col + 100, cast( doc as char ), path from jep; select key_col, doc, json_keys( doc ) from jep order by key_col; select key_col, doc, json_extract( doc, cast(path as char) ) from jep order by key_col; select * from jep order by key_col; drop table jep; --echo # ---------------------------------------------------------------------- --echo # Test that cached, constant path objects are restored --echo # after the leg popping which happens inside json_insert() --echo # and json_replace(). --echo # ---------------------------------------------------------------------- create table t_cache( id int, doc json ); insert into t_cache values ( 1, '{ "a": { "b": 1 } }' ), ( 2, '{ "a": { "c": 1 } }' ), ( 3, '{ "a": { "d": 1 } }' ); select id, doc, json_insert( doc, '$.a.c', 2 ) from t_cache order by id; select id, doc, json_insert( doc, '$.a.c', 2, '$.a.d', 3 ) from t_cache order by id; delete from t_cache; insert into t_cache values ( 1, '{ "a": { "b": 1, "c": 2, "d": 3 } }' ), ( 2, '{ "a": { "c": 2, "d": 3 } }' ), ( 3, '{ "a": { "b": 1, "d": 3 } }' ), ( 4, '{ "a": { "b": 1, "c": 2 } }' ), ( 5, '{ "a": { "b": 1 } }' ), ( 6, '{ "a": { "c": 2 } }' ), ( 7, '{ "a": { "d": 3 } }' ), ( 8, '{ "a": {} }' ); select id, doc, json_replace( doc, '$.a.c', 20 ) from t_cache order by id; select id, doc, json_replace( doc, '$.a.c', 20, '$.a.d', 30 ) from t_cache order by id; drop table t_cache; --echo # ---------------------------------------------------------------------- --echo # Test that one_or_all arguments are cached correctly. --echo # ---------------------------------------------------------------------- create table t_ooa( id int, doc json, one_or_all varchar(10) ); insert into t_ooa values ( 1, '{ "a": 1, "b": 2, "c": 3 }', 'one' ), ( 2, '{ "d": 4 }', 'one' ), ( 3, '{ "a": 1, "b": 2, "d": 4 }', 'all' ), ( 4, '{ "a": 1, "c": 3 }', 'all' ), ( 5, '{ "d": 4 }', 'all' ), ( 6, '{ "a": 1, "b": 2, "c": 3 }', null ); select id, doc, one_or_all, json_contains_path( doc, one_or_all, '$.a', '$.b' ) from t_ooa order by id; select id, doc, json_contains_path( doc, 'one', '$.a', '$.b' ) from t_ooa order by id; select id, doc, json_contains_path( doc, 'all', '$.a', '$.b' ) from t_ooa order by id; select id, doc, json_contains_path( doc, null, '$.a', '$.b' ) from t_ooa order by id; delete from t_ooa; insert into t_ooa values ( 1, '{ "a": "foot", "b": "fool", "c": "food" }', 'one' ), ( 1, '{ "a": "foot", "b": "fool", "c": "food" }', 'all' ), ( 1, '{ "a": "foot", "b": "fool", "c": "food" }', null ); select id, doc, one_or_all, json_search( doc, one_or_all, 'foo%' ) from t_ooa order by id; select id, doc, json_search( doc, 'one', 'foo%' ) from t_ooa order by id; select id, doc, json_search( doc, 'all', 'foo%' ) from t_ooa order by id; select id, doc, json_search( doc, null, 'foo%' ) from t_ooa order by id; drop table t_ooa; # This test case reproduces a problem seen during development. The update # statement crashed if the target table was the inner table of the join. CREATE TABLE t1(j JSON); CREATE TABLE t2(j JSON); INSERT INTO t1 VALUES ('[1]'), ('[2]'), ('[3]'), ('[4]'); INSERT INTO t2 VALUES ('[1]'); ANALYZE TABLE t1, t2; let $query= UPDATE t1, t2 SET t1.j = JSON_INSERT(t2.j, '\$[1]', t2.j) WHERE t1.j=t2.j; eval EXPLAIN $query; eval $query; SELECT * FROM t1 ORDER BY (CAST(j AS CHAR)); DROP TABLE t1, t2; --echo # --echo # Bug#20888919: ASSERT `!THD->IS_ERROR()' FAILED IN HANDLE_QUERY() --echo # ON EXPLAIN SELECT JSON --echo # create table t (pk int primary key, col_json json); ANALYZE TABLE t; explain SELECT col_json FROM t WHERE pk = 1; drop table t; --echo # ---------------------------------------------------------------------- --echo # Bug#20889248 Used to crash the server --echo # ---------------------------------------------------------------------- create table tt(i int, j json, si int); select count(*) , json_keys('{"key17": {"a": {"b": "c"}}, "key88": "value94"}'); # Tests Item_copy_json::save_in_field. int target column here gets assigned via # JSON->string->int parse since Field_long::store doesn't have an overload for # JSON. Similar for other non-JSON target columns. The JSON column assignment # does not go via string, since Field_json knows how to store JSON. insert into tt(i, j) select count(*), json_extract('{"key17": {"a": {"b": "c"}}, "key88": 100}', '$.key88'); insert into tt(i, si) select count(*), json_extract('{"key17": {"a": {"b": "c"}}, "key88": 100}', '$.key88'); select * from tt order by i; # This exercises Item_copy_json::val_real delete from tt; insert into tt(j) values (cast(1 as json)), (null); select sum( distinct j ) from tt group by j having j in ( avg( 1 ), 1 + j); # Exercise Item_copy_json::val_json SELECT JSON_ARRAY(j), COUNT(*) FROM tt GROUP BY j, i WITH ROLLUP; # Exercise Item_copy_json::val_int SELECT REPEAT('abc', j), COUNT(*) FROM tt GROUP BY j, i WITH ROLLUP; # Exercise Item_copy_json::val_str SELECT REPEAT(j, 2), COUNT(*) FROM tt GROUP BY j, i WITH ROLLUP; # Exercise Item_copy_json::val_decimal SELECT CAST(j AS DECIMAL(5,2)), COUNT(*) FROM tt GROUP BY j, i WITH ROLLUP; # Exercise Item_copy_json::get_time UPDATE tt SET j = CAST(CAST('12:13:14' AS TIME) AS JSON) WHERE j IS NOT NULL; SELECT CAST(j AS TIME), COUNT(*) FROM tt GROUP BY j, i WITH ROLLUP; # Exercise Item_copy_json::get_date SELECT CAST(j AS DATE) = CURRENT_DATE, COUNT(*) FROM tt GROUP BY j, i WITH ROLLUP; UPDATE tt SET j = CAST(CAST('2015-06-19' AS DATE) AS JSON) WHERE j IS NOT NULL; SELECT CAST(j AS DATE), COUNT(*) FROM tt GROUP BY j, i WITH ROLLUP; # Exercise an error path through Item_copy_json::val_str DELETE FROM tt; INSERT INTO tt(j) VALUES (JSON_ARRAY(REPEAT('abc', 100))); UPDATE tt SET j = JSON_ARRAY(j,j,j,j); SET GLOBAL net_buffer_length = 1024; SET GLOBAL max_allowed_packet = 1024; CONNECT (con1,localhost,root,,); CONNECTION con1; SELECT REPEAT(j, 2), COUNT(*) FROM tt GROUP BY j, i WITH ROLLUP; CONNECTION default; DISCONNECT con1; SET GLOBAL max_allowed_packet = default; SET GLOBAL net_buffer_length = default; DROP TABLE tt; --echo # ---------------------------------------------------------------------- --echo # Bug#20914054 Used to crash the server --echo # ---------------------------------------------------------------------- CREATE TABLE t1 ( pk INT NOT NULL, col_int_key INT, col_json json, PRIMARY KEY (pk), KEY col_int_key (col_int_key) ); INSERT INTO t1 VALUES (8, 4, '{}'); CREATE TABLE t2 ( pk INT NOT NULL, PRIMARY KEY (pk) ); INSERT INTO t2 VALUES (20); SELECT MIN(JSON_KEYS( t1.col_json )) AS field1 FROM t1 JOIN t2 HAVING field1 = 7; drop table t1; drop table t2; --echo # ---------------------------------------------------------------------- --echo # Bug#20920788 Used to give SQL state 22032: Cannot create a JSON value --echo # from a string with CHARACTER SET 'binary'. --echo #---------------------------------------------------------------------- CREATE TABLE t ( col_json JSON, col_varchar VARCHAR(1), col_varchar_key VARCHAR(1), KEY col_varchar_key (col_varchar_key) ); INSERT INTO t VALUES ('{}', 'a', 'a'); --echo # This always succeeded, group by column is indexed, optimizer does not --echo # use filesort: SELECT MAX(col_json) AS field1, col_varchar_key AS field2 FROM t GROUP BY field2; --echo # This used to fail, group by column is not indexed, EXPLAIN says --echo # filesort is used: SELECT MAX(col_json) AS field1, col_varchar AS field2 FROM t GROUP BY field2; drop table t; --echo # ---------------------------------------------------------------------- --echo # Bug#20962317 WARNING 3150 'INVALID JSON VALUE FOR CAST TO INTEGER' ON --echo # SUBQUERY IN JSON_VALID --echo #---------------------------------------------------------------------- create table myt(col_json json); insert into myt values ('{}'); --echo # This statement used to give two wrong warnings select json_valid((select col_json from myt)); drop table myt; --echo # ---------------------------------------------------------------------- --echo # Bug#20954309 JSON_SEARCH() IN VIEWS DOES NOT WORK, ALWAYS RETURNS NULL --echo #---------------------------------------------------------------------- CREATE TABLE t_20954309 (id int, col_json JSON); INSERT INTO t_20954309 VALUES (2, '{"keyA": "eleven"}'); CREATE VIEW v1_20954309 AS SELECT id, JSON_SEARCH(col_json, 'one', 'ele%' ) FROM t_20954309; CREATE VIEW v2_20954309 AS SELECT id, col_json FROM t_20954309; SELECT id, JSON_SEARCH(col_json, 'one', 'ele%' ) from t_20954309 order by id; SELECT id, JSON_SEARCH(col_json, 'one', 'eleven' ) from v2_20954309 order by id; SELECT * FROM v1_20954309 order by id; drop view v1_20954309; drop view v2_20954309; drop table t_20954309; # # Arguments vary from row to row. # create table t_20954309 (id int, doc JSON, search_string varchar(20), escape_char varchar(10) ); insert into t_20954309 values (1, '{"match11": "eleven", "match12": "element", "notMatch": "elven" }', 'ele%', null ), (2, '{"match21": "eleven", "match22": "element", "notMatch": "elven" }', 'ele%', 'z' ), (3, '{"match31": "tw%elve", "match32": "tw%ilight", "notMatch": "twitter" }', 'tw|%%', '|' ); select id, json_search( doc, 'all', search_string, '|' ) from t_20954309 order by id; create view v_20954309 as select id, json_search( doc, 'all', search_string, '|' ) from t_20954309 order by id; select * from v_20954309; select id, json_search( doc, 'all', search_string, null ) from t_20954309 where id < 3 order by id; create view v2_20954309 as select id, json_search( doc, 'all', search_string, null ) result from t_20954309 where id < 3 order by id; select * from v2_20954309; drop view v_20954309; drop view v2_20954309; drop table t_20954309; create table t_doc (id int, doc JSON ); insert into t_doc values (1, '{"match11": "eleven", "match12": "element", "notMatch": "elven" }' ), (2, '{"match21": "eleven", "match22": "element", "notMatch": "elven" }' ), (3, '{"match31": "tw%elve", "match32": "tw%ilight", "notMatch": "twitter" }' ); create table t_search_string (id int, search_string varchar(20) ); insert into t_search_string values (1, 'ele%' ), (2, 'ele%' ), (3, 'tw|%%' ); select t.id, json_search( doc, 'all', (select search_string from t_search_string s where s.id = t.id), '|' ) from t_doc t order by id; create view v_doc as select t.id, json_search( doc, 'all', (select search_string from t_search_string s where s.id = t.id), '|' ) from t_doc t order by id; select * from v_doc; drop view v_doc; drop table t_doc; drop table t_search_string; set names default; -- echo # -- echo # Bug#20972793 ASSERT FIELD_TYPE() == MYSQL_TYPE_JSON... -- echo # IN ARG_COMPARATOR::COMPARE_JSON -- echo # CREATE TABLE t1 ( pk INT NOT NULL, col_int_key INT, col_int INT, col_json JSON, PRIMARY KEY (pk), KEY col_int_key (col_int_key) ); INSERT INTO t1 VALUES (2,4,2,NULL); CREATE TABLE t2 ( pk INT NOT NULL, col_int_key INT, PRIMARY KEY (pk), KEY col_int_key (col_int_key) ); SELECT (SELECT MAX(sq1_alias1.pk) AS sq1_field1 FROM (t1 AS sq1_alias1 INNER JOIN t2 AS sq1_alias2 ON (sq1_alias2.col_int_key = sq1_alias1.col_int_key) ) WHERE sq1_alias2.pk <= alias1.col_int ) AS field1, MAX(alias1.col_json) AS field2 FROM ( SELECT sq2_alias1.* FROM t1 AS sq2_alias1 ) AS alias1 GROUP BY field1 HAVING field2 > 1; DROP TABLE t1, t2; --echo # ---------------------------------------------------------------------- --echo # Bug#20987329 VALUE OF PREPARED STATEMENT PLACEHOLDER FOR PARAMETER --echo # IN JSON_EXTRACT IS STICKY --echo #---------------------------------------------------------------------- # should get different results with different parameter values # json_extract() CREATE TABLE t_reuse (pk INT, col_json JSON); INSERT INTO t_reuse VALUES (1, '{"keyA": 1}'), (2, '{"keyA": 2, "keyB": 22}'); PREPARE getjson FROM 'SELECT JSON_EXTRACT(col_json, ?) FROM t_reuse order by pk'; SET @mypath = '$.keyA'; EXECUTE getjson USING @mypath; SET @mypath = '$.keyB'; EXECUTE getjson USING @mypath; drop table t_reuse; --echo # --echo # Test that max_allowed_packet is respected. --echo # SET GLOBAL net_buffer_length = 1024; SET GLOBAL max_allowed_packet = 1024; CONNECT (con1,localhost,root,,); CONNECTION con1; CREATE TABLE t1(j JSON); INSERT INTO t1 VALUES (JSON_ARRAY(REPEAT('abc', 100))); SELECT JSON_ARRAY(j, j, j, j) FROM t1; --error ER_WARN_ALLOWED_PACKET_OVERFLOWED UPDATE t1 SET j = JSON_ARRAY(j, j, j, j); CREATE TABLE t2(s TEXT); --error ER_WARN_ALLOWED_PACKET_OVERFLOWED INSERT INTO t2 SELECT JSON_ARRAY(j, j, j, j) FROM t1; SELECT * FROM t2; INSERT INTO t2 SELECT * FROM t1; --error ER_WARN_ALLOWED_PACKET_OVERFLOWED UPDATE t2 SET s = JSON_ARRAY(s, s, s, s); DROP TABLE t1, t2; CONNECTION default; DISCONNECT con1; SET GLOBAL max_allowed_packet = default; SET GLOBAL net_buffer_length = default; --echo # --echo # Test that very deep documents are rejected. --echo # # Currently, the maximum accepted depth is 100. Make some documents that are # nested to that exact depth. CREATE TABLE t(jarray JSON, jobject JSON, jmix JSON) ROW_FORMAT=DYNAMIC; INSERT INTO t VALUES ('1', '1', '1'); let $depth=1; while ($depth < 100) { eval UPDATE t SET jarray = JSON_ARRAY(jarray), jobject = JSON_OBJECT('a', jobject), jmix = CASE WHEN MOD($depth, 2) = 0 THEN JSON_ARRAY(jmix) ELSE JSON_OBJECT('a', jmix) END; inc $depth; } SELECT JSON_DEPTH(jarray), JSON_DEPTH(jobject), JSON_DEPTH(jmix) FROM t; SELECT JSON_DEPTH(CAST(jarray AS CHAR)), JSON_DEPTH(CAST(jobject AS CHAR)), JSON_DEPTH(CAST(jmix AS CHAR)) FROM t; SELECT JSON_VALID(jarray), JSON_VALID(jobject), JSON_VALID(jmix) FROM t; SELECT JSON_VALID(CAST(jarray AS CHAR)), JSON_VALID(CAST(jobject AS CHAR)), JSON_VALID(CAST(jmix AS CHAR)) FROM t; --error ER_JSON_DOCUMENT_TOO_DEEP INSERT INTO t(jarray) SELECT JSON_ARRAY(jarray) FROM t; --error ER_JSON_DOCUMENT_TOO_DEEP INSERT INTO t(jobject) SELECT JSON_OBJECT('a', jobject) FROM t; --error ER_JSON_DOCUMENT_TOO_DEEP INSERT INTO t(jmix) SELECT JSON_ARRAY(jmix) FROM t; --error ER_JSON_DOCUMENT_TOO_DEEP INSERT INTO t(jmix) SELECT JSON_OBJECT('a', jmix) FROM t; CREATE TABLE too_deep_docs(id INT PRIMARY KEY AUTO_INCREMENT, x text); INSERT INTO too_deep_docs(x) SELECT CONCAT('[', jarray, ']') FROM t; INSERT INTO too_deep_docs(x) SELECT CONCAT('[', jobject, ']') FROM t; INSERT INTO too_deep_docs(x) SELECT CONCAT('[', jmix, ']') FROM t; INSERT INTO too_deep_docs(x) SELECT CONCAT('{"a":', jarray, '}') FROM t; INSERT INTO too_deep_docs(x) SELECT CONCAT('{"a":', jobject, '}') FROM t; INSERT INTO too_deep_docs(x) SELECT CONCAT('{"a":', jmix, '}') FROM t; INSERT INTO too_deep_docs(x) SELECT CONCAT('["abc", [', jarray, ']]') FROM t; INSERT INTO too_deep_docs(x) SELECT CONCAT('{"a":2,"b":{"c":', jobject, '}}') FROM t; let $count= `SELECT COUNT(*) FROM too_deep_docs`; while ($count) { --error ER_JSON_DOCUMENT_TOO_DEEP eval SELECT CAST(x AS JSON) FROM too_deep_docs WHERE id=$count; --error ER_JSON_DOCUMENT_TOO_DEEP eval SELECT JSON_DEPTH(x) FROM too_deep_docs WHERE id=$count; --error ER_JSON_DOCUMENT_TOO_DEEP eval SELECT JSON_VALID(x) FROM too_deep_docs WHERE id=$count; --error ER_JSON_DOCUMENT_TOO_DEEP eval INSERT INTO t(jarray) SELECT x FROM too_deep_docs WHERE id=$count; dec $count; } --error ER_JSON_DOCUMENT_TOO_DEEP SELECT CAST(JSON_ARRAY(jarray) AS CHAR) FROM t; --error ER_JSON_DOCUMENT_TOO_DEEP SELECT CAST(JSON_OBJECT('a', jobject) AS CHAR) FROM t; --error ER_JSON_DOCUMENT_TOO_DEEP SELECT CAST(JSON_ARRAY(jmix) AS CHAR) FROM t; --error ER_JSON_DOCUMENT_TOO_DEEP SELECT CAST(JSON_OBJECT('a', jmix) AS CHAR) FROM t; DROP TABLE t, too_deep_docs; --echo # --echo # Bug#21054252 QUERY HAVING SQL_BIG_RESULT ON JSON DATA GIVES INVALID --echo # DATA ERROR --echo # CREATE TABLE t1 (i1 INT, KEY(i1)); CREATE TABLE t2 (i2 INT, j2 JSON); INSERT INTO t2 (i2, j2) VALUES (1, '["a"]'), (2, '["ab"]'); --source include/turn_off_only_full_group_by.inc SELECT SQL_BIG_RESULT i1, j2 FROM t2 LEFT JOIN t1 ON i2 < i1 GROUP BY j2 ORDER BY i2; --source include/restore_sql_mode_after_turn_off_only_full_group_by.inc DROP TABLE t1, t2; --echo # --echo # Bug#21104470 WL8132:ASSERTION `! IS_SET()' FAILED. --echo # # abbreviated test case CREATE TABLE t_21104470(j JSON); INSERT INTO t_21104470 VALUES (NULL), (NULL); # Should return one row with the value NULL. SELECT j FROM t_21104470 GROUP BY j; # This one should return NULL too SELECT DISTINCT j FROM t_21104470; DROP TABLE t_21104470; CREATE TABLE t(j JSON NOT NULL); # There is no default for the field, and it can't be NULL, so this should fail. --error ER_NO_DEFAULT_FOR_FIELD INSERT INTO t(j) VALUES (DEFAULT); # Loosen up the checks. It works in non-strict mode. SET sql_mode = ''; INSERT INTO t(j) VALUES (DEFAULT); # This query failed with 'invalid data' before bug#21104470. SELECT * FROM t; SET sql_mode = default; DROP TABLE t; --echo # --echo # Bug#21072360 ASSERTION `(*A)->FIELD_TYPE() == MYSQL_TYPE_JSON || --echo # (*B)->FIELD_TYPE() == FAILED --echo # CREATE TABLE t (j JSON); INSERT INTO t VALUES ('true'), ('"abc"'); SELECT j FROM t WHERE j <= 'xyz' AND j = 'abc'; DROP TABLE t; --echo # --echo # Bug#21094905 VALGRIND ERRORS WITH LATEST BUILDS OF WL7909 --echo # CREATE TABLE F (i1 INT, j JSON); INSERT INTO F VALUES (1, '1'), (2, '2'); CREATE TABLE H (i2 INT); SELECT SUM(DISTINCT i2), j FROM F LEFT JOIN H ON i1 = i2 GROUP BY j ORDER BY j; DROP TABLE F, H; --echo # --echo # Bug#21110783 WL8132:DEBUG CRASH AT WRAPPER_TO_STRING | SQL/JSON_DOM.CC --echo # CREATE TABLE t1 (i1 INT) ENGINE=MyISAM; INSERT INTO t1 VALUES (1); CREATE TABLE t2 (i2 INT, j JSON) ENGINE=MyISAM; CREATE TABLE t3(v VARCHAR(100), j JSON) ENGINE=MyISAM; INSERT INTO t3(v) SELECT j FROM t1 LEFT JOIN t2 ON i1 = i2 GROUP BY j; INSERT INTO t3(j) SELECT j FROM t1 LEFT JOIN t2 ON i1 = i2 GROUP BY j; SELECT * FROM t3; DROP TABLE t1, t2, t3; --echo # --echo # Bug#21119971 WL8132:DEBUG CRASH AT ITEM_CACHE_JSON::CACHE_VALUE --echo # CREATE TABLE t1(j1 JSON); CREATE TABLE t2(j2 JSON); CREATE TABLE t3(j3 JSON); INSERT INTO t1 VALUES ('1'); INSERT INTO t2 VALUES ('1'); INSERT INTO t3 VALUES ('1'); SELECT * FROM t1 WHERE j1 >= ALL (SELECT j3 FROM t2 LEFT JOIN t3 ON (j2 > j3)); DROP TABLE t1, t2, t3; --echo # --echo # Bug#21145759 ER_INVALID_CAST_TO_JSON ON CALL TO JSON_REMOVE --echo # WITH EMPTY ARG + ORDER BY --echo # CREATE TABLE t (pk INT PRIMARY KEY, col_json JSON); INSERT INTO t VALUES (1, JSON_OBJECT()); SELECT JSON_REMOVE((SELECT col_json FROM t WHERE pk = 3), '$.testpath1') AS field1 FROM t HAVING field1 >= 'c' ORDER BY field1; SELECT JSON_REMOVE((SELECT col_json FROM t WHERE pk = 3), '$.testpath1') AS field1 FROM t HAVING field1 >= 'c'; SELECT JSON_REMOVE((SELECT col_json FROM t WHERE pk = 3), '$.testpath1') AS field1 FROM t ORDER BY field1; SELECT JSON_REMOVE((SELECT col_json FROM t WHERE pk = 3), '$.testpath1') AS field1 FROM t; DROP TABLE t; --echo # --echo # Bug#21135312 BUG IN JSON COMPARE OPARATOR WHEN USING JSON_QUOTE --echo # CREATE TABLE t1(c VARCHAR(10) CHARACTER SET latin1); INSERT INTO t1 VALUES ('abc'), ('"abc"'); CREATE TABLE t2(j JSON); INSERT INTO t2 VALUES ('"abc"'); SELECT c, c = CAST('"abc"' AS JSON) AS eq1, c = JSON_EXTRACT('"abc"', '$') AS eq2, c = j AS eq3 FROM t1, t2 ORDER BY c; DROP TABLE t1, t2; --echo # --echo # Bug#21147943 JSON_CONTAINS() RETURNS INCORRECT RESULT --echo # SELECT JSON_CONTAINS('[1, 2, [4] ]', '{ "b" : 2 }'); SELECT JSON_CONTAINS('[1, 2, [4,5] ]', '[1,2,3,4,5,6,7,8,9]'); SELECT JSON_CONTAINS('[1, 2, [4,5] ]', '[111111111111111111]'); --echo # --echo # Bug#21169109 WL8249:WRONG RESULTS WHILE COMPARING A JSON COLUMN --echo # WITH AN INDEXED INT COLUMN --echo # CREATE TABLE t1(j JSON, i INT); INSERT INTO t1 VALUES ('0', 0), ('1', 1), ('1.0', 2), ('[1,2,3]', 3), ('{}', 4), ('"abc"', 5); ANALYZE TABLE t1; let $query1=SELECT * FROM t1 WHERE j > i ORDER BY i; let $query2=SELECT * FROM t1 AS a, t1 AS b WHERE a.j > b.i ORDER BY b.i, a.i; eval EXPLAIN $query1; eval EXPLAIN $query2; eval $query1; eval $query2; --echo # Create an index on the INT column and verify that it is not used. CREATE INDEX t1_idx ON t1(i); ANALYZE TABLE t1; eval EXPLAIN $query1; eval EXPLAIN $query2; eval $query1; eval $query2; CREATE TABLE t2(i INT, vc VARCHAR(10)) ENGINE=InnoDB CHARACTER SET 'utf8mb4' COLLATE 'utf8mb4_bin'; INSERT INTO t2 VALUES (1, 'abc'), (2, '"abc"'); ANALYZE TABLE t2; let $query= SELECT i FROM t2 WHERE vc = CAST('"abc"' AS JSON); eval EXPLAIN $query; eval $query; --echo # Create an index on the VARCHAR column and verify that it is not used. --echo # Used to return 2 instead of 1. CREATE INDEX t2_idx ON t2(vc); ANALYZE TABLE t2; eval EXPLAIN $query; eval $query; DROP INDEX t2_idx ON t2; --echo # Create a unique index on the VARCHAR column and verify that it is not --echo # used. Used to return an empty result. CREATE UNIQUE INDEX t2_idx ON t2(vc); ANALYZE TABLE t2; eval EXPLAIN $query; eval $query; DROP TABLE t1, t2; # test that expanded escape sequences are not truncated create table t_varchar( a varchar(3) ); insert into t_varchar values ( json_unquote( '"\\u0000\\u0001\\u0002"' ) ); select length(a) l from t_varchar; select length( json_quote( a ) ) l, json_quote( a ) v from t_varchar; select * from ( select length( json_quote( a ) ) as field0, json_quote( a ) as field1 from t_varchar ) as derived_table; drop table t_varchar; --echo # --echo # Bug#21193273 CREATE TABLE SELECT JSN_QUOTE() RESULTS --echo # IN TRUNCATED DATA --echo # SELECT JSON_QUOTE('table') AS field1; CREATE TABLE t SELECT JSON_QUOTE('table') AS field1; SHOW WARNINGS; SELECT * FROM t; DESCRIBE t; drop table t; select json_unquote( '"table"' ) as field1; create table t1 select json_unquote( '"table"' ) as field1; SHOW WARNINGS; SELECT * FROM t1; DESCRIBE t1; drop table t1; --echo # --echo # Bug#21230644 JSON_MERGE MEMORY USAGE --echo # CREATE TABLE t (doc json); INSERT INTO t VALUES('{"array":[1,2,3,4]}'); UPDATE t SET doc=JSON_MERGE_PRESERVE(doc, doc); UPDATE t SET doc=JSON_MERGE_PRESERVE(doc, doc); drop table t; --echo # --echo # Bug#21224267 DEEPLY NESTED JSON OBJECTS MAY CAUSE CRASH --echo # CREATE TABLE t (j JSON); --error ER_JSON_DOCUMENT_TOO_DEEP INSERT INTO t VALUES (CONCAT(REPEAT('{"v":', 5000), '1', REPEAT('}', 5000))); --error ER_JSON_DOCUMENT_TOO_DEEP INSERT INTO t VALUES (CONCAT(REPEAT('{"v":[', 5000), '1', REPEAT(']}', 5000))); --error ER_JSON_DOCUMENT_TOO_DEEP INSERT INTO t VALUES (CONCAT(REPEAT('[{"v":', 5000), '1', REPEAT('}]', 5000))); DROP TABLE t; --echo # --echo # JSON should work with INSERT .. ON DUPLICATE KEY UPDATE --echo # CREATE TABLE t(id INT PRIMARY KEY, j JSON); INSERT INTO t VALUES (1, '[1]') ON DUPLICATE KEY UPDATE j = JSON_OBJECT("a", VALUES(j)); SELECT * FROM t; INSERT INTO t VALUES (1, '[1,2]') ON DUPLICATE KEY UPDATE j = JSON_OBJECT("ab", VALUES(j)); SELECT * FROM t; INSERT INTO t VALUES (1, '[1,2,3]') ON DUPLICATE KEY UPDATE j = JSON_OBJECT("abc", VALUES(j)); SELECT * FROM t; DROP TABLE t; --echo # --echo # Bug#21278178 JSON_QUOTE(LITERAL) GETS APPLIED DOUBLE DURING SELECT --echo # FROM TABLE WITH MTR --echo # CREATE TABLE t(x INT); INSERT INTO t VALUES (1), (2), (3); SET NAMES latin1; SELECT JSON_QUOTE('abc') FROM t; SET NAMES utf8mb4; SELECT JSON_QUOTE('abc') FROM t; SET NAMES default; DROP TABLE t; --echo # --echo # Bug#21291993 ASSERT `0' FAILED AT THD::SEND_STATEMENT_STATUS() --echo # ON JSON_SEARCH(NULL, ...)+JOIN --echo # CREATE TABLE t (pk INT NOT NULL PRIMARY KEY, col_varchar VARCHAR(1)); SELECT COUNT(*), JSON_SEARCH(NULL, 'one', '5%') FROM t t1, t t2 WHERE t1.pk = t2.pk; DROP TABLE t; --echo # --echo # Bug#21376088 JSON: CRASH IN VAL_JSON_FUNC_FIELD_SUBSELECT --echo # create table t(a json); insert into t values('{}'); select a from t where (select a from t where 1) in (select 1 from t); # repro select a from t where (select a from t where 1) in (select cast('{}' as json) from t); drop table t; --echo # --echo # Bug#21437989: ASSERTION FAILED: --echo # JSON_BINARY::PARSE_BINARY(PTR, LENGTH).IS_VALID() --echo # CREATE TABLE t(j JSON NOT NULL); --error ER_NO_DEFAULT_FOR_FIELD INSERT INTO t VALUES (); --error ER_BAD_NULL_ERROR INSERT INTO t VALUES (NULL); INSERT IGNORE INTO t VALUES (); INSERT IGNORE INTO t VALUES (NULL); SELECT * FROM t; # The next two statements used to trigger an assertion. INSERT INTO t SELECT j FROM t; REPLACE INTO t SELECT j FROM t; SELECT * FROM t; DROP TABLE t; --echo # --echo # Bug#21448719: WRONG RESULT FOR JSON VALUE IN OUTER JOIN WITH VIEW --echo # CREATE TABLE t1(j1 JSON); CREATE TABLE t2(j2 JSON); CREATE VIEW v AS SELECT CAST('1' AS JSON) AS jv, j2 FROM t2; INSERT INTO t1 VALUES ('1'); SELECT j1, jv, j2, JSON_ARRAY(j1, jv, j2) FROM t1 LEFT JOIN v ON j1 = jv; INSERT INTO t2 VALUES ('1'); SELECT j1, jv, j2, JSON_ARRAY(j1, jv, j2) FROM t1 LEFT JOIN v ON j1 = jv; DROP TABLE t1, t2; DROP VIEW v; --echo # --echo # Bug#21472872 WRONG RESULTS CAUSED BY PATH LEG POPPING --echo # IN JSON FUNCTIONS --echo # create table tdoc( id int, doc json ); insert into tdoc values ( 1, '[]' ), ( 2, '{ "a": { "b": true } }' ); select id, json_insert( doc, '$.a.c', false ) from tdoc where id = 2; select id, json_insert( doc, '$.a.c', false ) from tdoc order by id; drop table tdoc; create table tdoc( id int, doc json, new_value varchar( 10 ) ); insert into tdoc values ( 1, '{ "a": { "b": true } }', null ), ( 2, '{ "a": { "b": true } }', 'abc' ); select id, json_insert( doc, '$.a.c', new_value ) from tdoc where id = 2; select id, json_insert( doc, '$.a.c', new_value ) from tdoc order by id; drop table tdoc; --echo # --echo # Bug#21487833: DBUG_ABORT() IN JSON_WRAPPER::MAKE_HASH_KEY --echo # WITH ORDERED JSON --echo # --source include/turn_off_strict_mode.inc CREATE TABLE t (a BLOB, b JSON NOT NULL); INSERT INTO t VALUES ('', NULL), ('', NULL); UPDATE t SET a = 1 ORDER BY b; SELECT COUNT(a) FROM t GROUP BY b; SELECT DISTINCT B FROM t; SELECT b FROM t UNION DISTINCT SELECT b FROM t; SELECT * FROM t ORDER BY b; DROP TABLE t; --source include/restore_strict_mode.inc --echo # --echo # Bug#21541481: MEMORY LEAK OF ALLOCATIONS MADE IN --echo # VAL_JSON_FUNC_FIELD_SUBSELECT --echo # --echo # This comparison gave valgrind leakage before the fix create table t(a json not null) engine=innodb; insert into t values('{}'); select row(uuid(), a) < row(a, str_to_date(1,1)) from t; drop table t; --echo # Bug#21547877: UPDATE/INSERT JSON COLUMN CRASHES IF EXPRESSION --echo # REFERS TO SELF --echo # SET NAMES latin1; CREATE TABLE t (j JSON); INSERT INTO t VALUES ('{}'); --error ER_INVALID_JSON_TEXT UPDATE t SET j='1', j='1111-11-11', j=('1' NOT BETWEEN j AND '1'); SELECT * FROM t; DROP TABLE t; SET NAMES DEFAULT; --echo # --echo # Bug#21602361: ASSERTION FAILED: (VECTOR_IDX == -1) || (VECTOR_IDX >= 0) --echo # create table t(b int, key(b)); insert into t values(1),(2); # more than one row --error ER_TOO_MANY_ROWS select json_length('{}',@uninitialized_21602361) from t group by b into @uninitialized_21602361; # second time around the path is invalid set @initialized_21602361 = '$'; --error ER_INVALID_JSON_PATH select json_length('{}',@initialized_21602361) from t group by b into @initialized_21602361; # invalid path set @error_value_21602361 = '$['; --error ER_INVALID_JSON_PATH select json_length('{}',@error_value_21602361) from t group by b into @error_value_21602361; # more than one row set @valid_path_21602361 = '$'; --error ER_TOO_MANY_ROWS select concat( '$[', json_length('{}',@valid_path_21602361), ']' ) from t group by b into @valid_path_21602361; # used to trip the assertion set @null_value_21602361 = null; --error ER_TOO_MANY_ROWS select json_length('{}',@null_value_21602361) from t group by b into @null_value_21602361; drop table t; --echo # --echo # Bug#21649073: JSON_TYPE RETURNS OPAQUE FOR SOME BINARY VALUES --echo # SELECT JSON_TYPE(CAST(CAST('abcd' AS BINARY) AS JSON)); CREATE TABLE t (bn BINARY(5), vb VARBINARY(5), tb TINYBLOB, mb MEDIUMBLOB, bb BLOB, lb LONGBLOB); INSERT INTO t (bn) VALUES (x'cafe'); UPDATE t SET vb = bn, tb = bn, mb = bn, bb = bn, lb = bn; SELECT JSON_TYPE(CAST(bn AS JSON)) AS bn, JSON_TYPE(CAST(vb AS JSON)) AS vb, JSON_TYPE(CAST(tb AS JSON)) AS tb, JSON_TYPE(CAST(mb AS JSON)) AS mb, JSON_TYPE(CAST(bb AS JSON)) AS bb, JSON_TYPE(CAST(lb AS JSON)) AS lb FROM t; DROP TABLE t; --echo # --echo # Basic tests for inlined JSON path --echo # CREATE TABLE t1(autopk int primary key auto_increment, f1 JSON); INSERT INTO t1(f1) VALUES ('{"a":1}'), ('{"a":3}'), ('{"a":2}'), ('{"a":11, "b":3}'), ('{"a":33, "b":1}'), ('{"a":22,"b":2}'); ANALYZE TABLE t1; SELECT f1->"$.a" FROM t1 order by autopk; EXPLAIN SELECT f1->"$.a" FROM t1 order by autopk; SELECT f1->"$.a" FROM t1 WHERE f1->"$.b" > 1 order by autopk; EXPLAIN SELECT f1->"$.a" FROM t1 WHERE f1->"$.b" > 1 order by autopk; SELECT f1->"$.a", f1->"$.b" FROM t1 ORDER BY autopk; EXPLAIN SELECT f1->"$.a", f1->"$.b" FROM t1 ORDER BY autopk; SELECT MAX(f1->"$.a"), f1->"$.b" FROM t1 GROUP BY f1->"$.b"; EXPLAIN SELECT MAX(f1->"$.a"), f1->"$.b" FROM t1 GROUP BY f1->"$.b"; SELECT JSON_OBJECT("c",f1->"$.b") AS f2 FROM t1 HAVING JSON_TYPE(f2->"$.c") <> 'NULL' ORDER BY autopk; EXPLAIN SELECT JSON_OBJECT("c",f1->"$.b") AS f2 FROM t1 HAVING JSON_TYPE(f2->"$.c") <> 'NULL' order by autopk; --echo Test unquoting operator INSERT INTO t1(f1) VALUES ('{"t":"a"}'), ('{"t":"b"}'), ('{"t":"c"}'); --echo Returned values should be quoted SELECT f1->"$.t" FROM t1 WHERE f1->"$.t" <> 'NULL' order by autopk; --echo Returned values should be unquoted SELECT f1->>"$.t" FROM t1 WHERE f1->>"$.t" <> 'NULL' order by autopk; EXPLAIN SELECT f1->>"$.t" FROM t1 WHERE f1->>"$.t" <> 'NULL'; --error ER_PARSE_ERROR SELECT f1->>NULL FROM t1; --error ER_INVALID_JSON_PATH SELECT f1 ->> "NULL" FROM t1; --error ER_INVALID_JSON_PATH SELECT f1->>"NULL" FROM t1; --error ER_INVALID_JSON_PATH SELECT f1->>"!@#" FROM t1; --error ER_PARSE_ERROR SELECT COUNT(*)->>"$.t" FROM t1; INSERT INTO t1(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", cast(json_unquote(json_extract(f1,"$**.b")) as char), cast(f1->>"$**.b" as char) <=> cast(json_unquote(json_extract(f1,"$**.b")) as char) FROM t1 order by autopk; SELECT f1->>"$.c", cast(json_unquote(json_extract(f1,"$.c")) as char), cast(f1->>"$.c" as char) <=> cast(json_unquote(json_extract(f1,"$.c")) as char) FROM t1 order by autopk; SELECT f1->>'$.b[1].c', cast(json_unquote(json_extract(f1,'$.b[1].c')) as char), cast(f1->>'$.b[1].c' as char)<=>cast(json_unquote(json_extract(f1,'$.b[1].c')) as char) FROM t1 order by autopk; SELECT f1->'$.b[1].c', cast(json_extract(f1,'$.b[1].c') as char), cast(f1->'$.b[1].c' as char) <=>cast(json_extract(f1,'$.b[1].c') as char) FROM t1 order by autopk; SELECT f1->>'$.b[1]', cast(json_unquote(json_extract(f1,'$.b[1]')) as char), cast(f1->>'$.b[1]' as char) <=> cast(json_unquote(json_extract(f1,'$.b[1]')) as char) FROM t1 order by autopk; SELECT f1->>'$[0][0]', cast(json_unquote(json_extract(f1,'$[0][0]')) as char), cast(f1->>'$[0][0]' as char) <=> cast(json_unquote(json_extract(f1,'$[0][0]')) as char) FROM t1 order by autopk; SELECT f1->>'$**[0]', cast(json_unquote(json_extract(f1,'$**[0]')) as char), cast(f1->>'$**[0]' as char) <=> cast(json_unquote(json_extract(f1,'$**[0]')) as char) FROM t1 order by autopk; SELECT f1->> '$.a[0]', cast(json_unquote(json_extract(f1, '$.a[0]')) as char), cast(f1->> '$.a[0]' as char) <=> cast(json_unquote(json_extract(f1, '$.a[0]')) as char) FROM t1 order by autopk; SELECT f1->>'$[0].a[0]', cast(json_unquote(json_extract(f1,'$[0].a[0]')) as char), cast(f1->>'$[0].a[0]' as char) <=> cast(json_unquote(json_extract(f1,'$[0].a[0]')) as char) FROM t1 order by autopk; SELECT f1->>'$**.a', cast(json_unquote(json_extract(f1,'$**.a')) as char), cast(f1->>'$**.a' as char) <=> cast(json_unquote(json_extract(f1,'$**.a')) as char) FROM t1 order by autopk; SELECT f1->>'$[0][0][0].a', cast(json_unquote(json_extract(f1,'$[0][0][0].a')) as char), cast(f1->>'$[0][0][0].a' as char) <=> cast(json_unquote(json_extract(f1,'$[0][0][0].a')) as char) FROM t1 order by autopk; SELECT f1->>'$[*].b', cast(json_unquote(json_extract(f1,'$[*].b')) as char), cast(f1->>'$[*].b' as char) <=> cast(json_unquote(json_extract(f1,'$[*].b')) as char) FROM t1 order by autopk; SELECT f1->>'$[*].a', cast(json_unquote(json_extract(f1,'$[*].a')) as char), cast(f1->>'$[*].a' as char) <=> cast(json_unquote(json_extract(f1,'$[*].a')) as char) FROM t1 order by autopk; DROP TABLE t1; --echo # --echo # Bug#21072360 ASSERTION `(*A)->FIELD_TYPE() == MYSQL_TYPE_JSON || --echo # (*B)->FIELD_TYPE() == FAILED --echo # --echo # --echo # Bug#21144949 WL8132:DELETE QUERY HAVING A SUB-QUERY DOES NOT --echo # DELETE ROWS IN THE TABLE --echo # CREATE TABLE t(j JSON); INSERT INTO t VALUES (JSON_OBJECT('a', 'b')), (JSON_OBJECT('a', 'b')); DELETE FROM t WHERE j IN (SELECT JSON_OBJECT('a', 'b') FROM DUAL WHERE 1); SELECT * FROM t; INSERT INTO t VALUES (JSON_OBJECT('a', 'b')), (JSON_OBJECT('a', 'b')); DELETE FROM t WHERE j IN (SELECT JSON_OBJECT('a', 'b') FROM DUAL); SELECT * FROM t; INSERT INTO t VALUES (JSON_OBJECT('a', 'b')), (JSON_OBJECT('a', 'b')); DELETE FROM t WHERE j IN (SELECT CAST(NULL AS JSON) FROM DUAL); DELETE FROM t WHERE j IN (SELECT CAST(NULL AS JSON) FROM DUAL WHERE 1); --error ER_INVALID_JSON_TEXT_IN_PARAM DELETE FROM t WHERE j IN (SELECT CAST('not json' AS JSON) FROM DUAL); --error ER_INVALID_JSON_TEXT_IN_PARAM DELETE FROM t WHERE j IN (SELECT CAST('not json' AS JSON) FROM DUAL WHERE 1); SELECT * FROM t; DROP TABLE t; --echo # Bug#22522073: Assertion failed: !thd->is_error() in optimize_cond() CREATE TABLE s(a INTEGER, b CHAR(1)); INSERT INTO s VALUES (1,0), (1,0), (1,0); CREATE TABLE t(c JSON); INSERT INTO t VALUES (), (), (); --error ER_SUBQUERY_NO_1_ROW SELECT 1 FROM s WHERE a NOT IN (SELECT 1 FROM s WHERE (SELECT c FROM t) = b); DROP TABLE s, t; --echo # --echo # WL#9191: JSON_PRETTY function --echo # CREATE TABLE t(id INT PRIMARY KEY AUTO_INCREMENT, uc VARCHAR(128) CHARACTER SET utf8mb4, lc VARCHAR(128) CHARACTER SET latin1, j JSON); INSERT INTO t(uc) VALUES (NULL), ('{}'), ('[]'), ('[1,2,3]'), ('{"a":1,"b":2}'), ('{"a":[1,{}],"b":[]}'), ('{"a":{"b":{"c":{"d":{"e":{"f":null}}}}}}'), ('true'), ('false'), ('null'), ('1'), ('1.1'), ('"hello"'), (JSON_ARRAY('abc def', '"abc"')); UPDATE t SET lc = uc, j = uc; SELECT JSON_PRETTY(uc) AS c1 FROM t ORDER BY id; SELECT JSON_PRETTY(lc) AS c1 FROM t ORDER BY id; SELECT JSON_PRETTY(j) AS c1 FROM t ORDER BY id; SELECT DISTINCT CHARSET(JSON_PRETTY(uc)) AS c1, CHARSET(JSON_PRETTY(lc)) AS c2, CHARSET(JSON_PRETTY(j)) AS c3 FROM t; DROP TABLE t; --error ER_INVALID_JSON_TEXT_IN_PARAM SELECT JSON_PRETTY('this is not JSON') AS j; --error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT SELECT JSON_PRETTY(); --error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT SELECT JSON_PRETTY('{}', 2); --echo # --echo # WL#9192: Add JSON_STORAGE_SIZE / JSON_STORAGE_FREE functions --echo # --error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT SELECT JSON_STORAGE_SIZE(); --error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT SELECT JSON_STORAGE_SIZE('{}', '[]'); --error ER_INVALID_JSON_TEXT_IN_PARAM SELECT JSON_STORAGE_SIZE('this is not JSON') AS j; SELECT JSON_STORAGE_SIZE(NULL); SELECT JSON_STORAGE_SIZE(JSON_ARRAY(1,2,3)); CREATE TABLE t(id INT PRIMARY KEY, j JSON, v VARCHAR(100)); INSERT INTO t(id, j) VALUES (0, NULL), (1, '[["abc", "def", "ghi", "jkl"]]'); UPDATE t SET v = j; let $dump_table= SELECT *, JSON_STORAGE_SIZE(j), JSON_STORAGE_SIZE(v), JSON_STORAGE_SIZE(j->'\$[0]'), JSON_STORAGE_SIZE(v->'\$[0]') FROM t ORDER BY id; --eval $dump_table UPDATE t SET j = JSON_SET(j, '$[0][1]', NULL, '$[0][3]', 'X'), v = JSON_SET(v, '$[0][1]', NULL, '$[0][3]', 'X'); --eval $dump_table DROP TABLE t; --echo # --echo # Get some extra coverage for partial update of JSON, WL#8963. --echo # Partial update will not happen in MySQL 5.7, since WL#8963 has not --echo # been backported. The test cases are kept in order to exercise --echo # the JSON_STORAGE_SIZE function. --echo # CREATE TABLE t(id INT PRIMARY KEY, j JSON); INSERT INTO t VALUES (1, '{"a":"a"}'), (2, '{"a":"b", "b":"b"}'), (3, '{"a":"c", "c":"c"}'); --let $dump_table= SELECT *, JSON_STORAGE_SIZE(j) ss FROM t ORDER BY id --eval $dump_table UPDATE t SET j = JSON_SET(j, '$.a', 'x'); --eval $dump_table UPDATE t SET j = JSON_SET(j, '$.a', 'y', '$.b', j->'$.a'); --eval $dump_table UPDATE t SET j = JSON_SET(j, '$.a', 'z'), j = JSON_SET(j, '$.b', j->'$.a'); --eval $dump_table UPDATE t SET j = JSON_SET(j, '$.a', 'w'), j = JSON_SET(j, '$.a', 'v', '$.b', j->'$.a'); --eval $dump_table UPDATE t SET j = JSON_REPLACE(j, '$.a', '1', '$.c', '2', '$.a', '3'); --eval $dump_table UPDATE t SET j = JSON_REPLACE(j, '$.a', '4'), j = JSON_REPLACE(j, '$.c', '5'), j = JSON_REPLACE(j, '$.a', '6'); --eval $dump_table UPDATE t SET j = JSON_REPLACE(j, '$.a', ''); --eval $dump_table UPDATE t SET j = JSON_REPLACE(j, '$.a', 'a'); --eval $dump_table UPDATE t SET j = JSON_REPLACE(j, '$.a', 'ab'); --eval $dump_table DROP TABLE t; CREATE TABLE t(id INT PRIMARY KEY, j1 JSON, j2 JSON); INSERT INTO t VALUES (1, '{"a":"a","b":"b"}', '{"a":"a","b":"b"}'), (2, NULL, NULL), (3, '{"a":"a","b":"b"}', '{"a":"a","b":"b"}'); let $dump_table= SELECT *, JSON_STORAGE_SIZE(j1) ss1, JSON_STORAGE_SIZE(j2) ss2 FROM t ORDER BY id; --eval $dump_table UPDATE t SET j1 = JSON_SET(j1, '$.a', 'x'), j2 = JSON_SET(j2, '$.a', 'y'), j1 = JSON_SET(j1, '$.b', 'z'); --eval $dump_table UPDATE t SET j1 = JSON_SET(j1, '$.a', 's'), j2 = JSON_SET(j2, '$.a', 'abcdefghi'), j1 = JSON_SET(j1, '$.b', 't'); --eval $dump_table UPDATE t SET j1 = JSON_SET(j1, '$.x.y.z', 'abc', '$.b', 'X'); --eval $dump_table UPDATE t SET j1 = JSON_REPLACE(j1, '$.x', 'abc', '$.b', 'Y'); --eval $dump_table UPDATE t SET j1 = JSON_SET(j1, '$.x', 'abc', '$.b', 'Z'); --eval $dump_table DROP TABLE t; CREATE TABLE t(j JSON, i INT DEFAULT 42, db DOUBLE DEFAULT 2.34e-10, dc DECIMAL(5, 3) DEFAULT 98.765, ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP, gc JSON GENERATED ALWAYS AS (JSON_ARRAY(i, db, dc, ts))) ENGINE=InnoDB; # Generated columns are not supported in NDB. INSERT INTO t(j, ts) VALUES ('[null, "abc", true, "def", false]', '2017-01-02 14:15:16'); --let $dump_table= SELECT j, JSON_TYPE(j) jt, JSON_STORAGE_SIZE(j) ss FROM t --eval $dump_table # The update of $[3] to a longer value should be able to reuse the space freed # by the update of $[1] to a shorter value. UPDATE t SET j = JSON_SET(j, '$[1]', 'xy', '$[3]', 'xyzw'); --eval $dump_table # Again, increasing the size of $[3] is OK as long as $[1] shrinks first, also # when done in two separate operations. UPDATE t SET j = JSON_SET(j, '$[1]', 'a'); --eval $dump_table UPDATE t SET j = JSON_SET(j, '$[3]', 'abcde'); --eval $dump_table # Test update to some other data types. UPDATE t SET j = JSON_ARRAY('abcdefghijklmnopqrstuvwxyz'); --eval $dump_table UPDATE t SET j = JSON_SET(j, '$[0]', 3.14e0); --eval $dump_table UPDATE t SET j = JSON_SET(j, '$[0]', CAST(10000000000 AS UNSIGNED)); --eval $dump_table UPDATE t SET j = JSON_SET(j, '$[0]', CAST(4000000000 AS SIGNED)); --eval $dump_table UPDATE t SET j = JSON_SET(j, '$[0]', CAST(123 AS UNSIGNED)); --eval $dump_table UPDATE t SET j = JSON_SET(j, '$[0]', CAST(456 AS SIGNED)); --eval $dump_table UPDATE t SET j = JSON_SET(j, '$[0]', -123); --eval $dump_table UPDATE t SET j = JSON_SET(j, '$[0]', -4000000000); --eval $dump_table UPDATE t SET j = JSON_SET(j, '$[0]', TRUE); --eval $dump_table UPDATE t SET j = JSON_SET(j, '$[0]', NULL); --eval $dump_table UPDATE t SET j = JSON_SET(j, '$[0]', CAST('abc' AS BINARY)); --eval $dump_table UPDATE t SET j = JSON_SET(j, '$[0]', CAST('2016-12-23 13:16:40' AS DATETIME)); --eval $dump_table UPDATE t SET j = JSON_SET(j, '$[0]', CAST('2016-12-24' AS DATE)); --eval $dump_table UPDATE t SET j = JSON_SET(j, '$[0]', CAST('14:17:41' AS TIME)); --eval $dump_table UPDATE t SET j = JSON_SET(j, '$[0]', 1.23); --eval $dump_table UPDATE t SET j = JSON_SET(j, '$[0]', i); --eval $dump_table UPDATE t SET j = JSON_SET(j, '$[0]', db); --eval $dump_table UPDATE t SET j = JSON_SET(j, '$[0]', dc); --eval $dump_table UPDATE t SET j = JSON_SET(j, '$[0]', ts); --eval $dump_table UPDATE t SET j = JSON_SET(j, '$[0]', gc->'$[0]'); --eval $dump_table UPDATE t SET j = JSON_SET(j, '$[0]', gc->'$[1]'); --eval $dump_table UPDATE t SET j = JSON_SET(j, '$[0]', gc->'$[2]'); --eval $dump_table UPDATE t SET j = JSON_SET(j, '$[0]', gc->'$[3]'); --eval $dump_table UPDATE t SET j = JSON_SET(j, '$[0]', gc->'$[4]'); --eval $dump_table DROP TABLE t; # Some multi-table updates which perform partial updates. CREATE TABLE t1(id INT PRIMARY KEY, j JSON, x INT); INSERT INTO t1 VALUES (1, '{"a":11}', 1), (2, '{"a":22}', 2); --let $dump_t1= SELECT *, JSON_STORAGE_SIZE(j) ss FROM t1 ORDER BY id --eval $dump_t1 CREATE TABLE t2(id INT PRIMARY KEY, j JSON, x INT); INSERT INTO t2 VALUES (1, '{"b":33}', 3), (2, '{"b":44}', 4); --let $dump_t2= SELECT *, JSON_STORAGE_SIZE(j) ss FROM t2 ORDER BY id --eval $dump_t2 UPDATE t1, t2 SET t1.j = JSON_SET(t1.j, '$.a', t2.j->'$.b') WHERE t1.id = t2.id; --eval $dump_t1 --eval $dump_t2 UPDATE t1, t2 SET t1.j = JSON_SET(t1.j, '$.a', t2.x), t2.j = JSON_SET(t2.j, '$.b', t1.x) WHERE t1.id = t2.id; --eval $dump_t1 --eval $dump_t2 UPDATE t1, t2 SET t1.j = '[123]', t2.j = JSON_SET(t2.j, '$.b', 99); --eval $dump_t1 --eval $dump_t2 DROP TABLE t1, t2; --echo # --echo # WL#9692: Add JSON_MERGE_PATCH --echo # CREATE TABLE merge_t( id INT PRIMARY KEY AUTO_INCREMENT, target VARCHAR(100), patch VARCHAR(100) ); INSERT INTO merge_t(target, patch) VALUES ('{"a":"b"}', '{"a":"c"}'), ('{"a":"b"}', '{"b":"c"}'), ('{"a":"b"}', '{"a":null}'), ('{"a":"b", "b":"c"}', '{"a":null}'), ('{"a":["b"]}', '{"a":"c"}'), ('{"a":"c"}', '{"a":["b"]}'), ('{"a": {"b":"c"}}', '{"a": {"b":"d", "c":null}}'), ('{"a":[{"b":"c"}]}', '{"a": [1]}'), ('["a","b"]', '["c","d"]'), ('{"a":"b"}', '["c"]'), ('{"a":"foo"}', 'null'), ('{"a":"foo"}', '"bar"'), ('{"e":null}', '{"a":1}'), ('[1,2]', '{"a":"b", "c":null}'), ('{}', '{"a":{"bb":{"ccc":null}}}'), (NULL, '{}'), ('{}', NULL); SELECT id, target, patch, JSON_MERGE_PATCH(target, patch) AS merged, JSON_EXTRACT(JSON_MERGE_PATCH(target, patch), '$.a') AS a FROM merge_t ORDER BY id; DROP TABLE merge_t; SELECT JSON_MERGE_PATCH('{"a":"b"}', NULL, '{"c":"d"}'); SELECT JSON_MERGE_PATCH(NULL, '[1,2,3]'); SELECT JSON_MERGE_PATCH('{"a":"b"}', NULL, '[1,2,3]', '{"c":null,"d":"e"}'); --error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT SELECT JSON_MERGE_PATCH(); --error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT SELECT JSON_MERGE_PATCH('{}'); --error ER_INVALID_JSON_TEXT_IN_PARAM SELECT JSON_MERGE_PATCH('{', '[1,2,3]'); --error ER_INVALID_JSON_TEXT_IN_PARAM SELECT JSON_MERGE_PATCH('{"a":"b"}', '[1,'); # Local Variables: # mode: sql # sql-product: mysql # comment-column: 48 # comment-start: "# " # fill-column: 80 # End:
Close