diff --git a/mysql-test/main/check_constraint.result b/mysql-test/main/check_constraint.result index 4ccb0d7f9d061..60df5537371af 100644 --- a/mysql-test/main/check_constraint.result +++ b/mysql-test/main/check_constraint.result @@ -449,7 +449,7 @@ path VARCHAR(100) NOT NULL, json_c1 JSON NOT NULL DEFAULT '{}', CONSTRAINT json_c1 CHECK (path > 0) ); -ERROR HY000: Duplicate CHECK constraint name 'json_c1' +DROP TABLE t2; CREATE TABLE t3 (a INT, CONSTRAINT c1 CHECK (a > 0), CONSTRAINT c1 CHECK (a < 100)); ERROR HY000: Duplicate CHECK constraint name 'c1' diff --git a/mysql-test/main/check_constraint.test b/mysql-test/main/check_constraint.test index e368fbf859e2c..f05fb43424efa 100644 --- a/mysql-test/main/check_constraint.test +++ b/mysql-test/main/check_constraint.test @@ -350,12 +350,13 @@ drop table t1; --error ER_DUP_CONSTRAINT_NAME CREATE TABLE t1 (a INT CHECK (a>2), CONSTRAINT a CHECK (a < 5)); ---error ER_DUP_CONSTRAINT_NAME +# MDEV-38740: JSON is a native type now, so it no longer generates a conflicting implicit CHECK constraint CREATE TABLE t2 ( path VARCHAR(100) NOT NULL, json_c1 JSON NOT NULL DEFAULT '{}', CONSTRAINT json_c1 CHECK (path > 0) ); +DROP TABLE t2; --error ER_DUP_CONSTRAINT_NAME CREATE TABLE t3 (a INT, CONSTRAINT c1 CHECK (a > 0), diff --git a/mysql-test/main/column_compression.result b/mysql-test/main/column_compression.result index 470eba01d1303..45975d9d39716 100644 --- a/mysql-test/main/column_compression.result +++ b/mysql-test/main/column_compression.result @@ -1722,7 +1722,7 @@ d TINYTEXT COMPRESSED BINARY SHOW CREATE TABLE t1; Table Create Table t1 CREATE TABLE `t1` ( - `a` longtext /*M!100301 COMPRESSED*/ CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL CHECK (json_valid(`a`)), + `a` json DEFAULT NULL, `b` varchar(1000) /*M!100301 COMPRESSED*/ CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL, `c` varchar(1000) /*M!100301 COMPRESSED*/ CHARACTER SET utf8mb3 COLLATE utf8mb3_bin DEFAULT NULL, `d` tinytext /*M!100301 COMPRESSED*/ CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL diff --git a/mysql-test/main/ctype_binary.result b/mysql-test/main/ctype_binary.result index 4148b247c219a..df354d99aa422 100644 --- a/mysql-test/main/ctype_binary.result +++ b/mysql-test/main/ctype_binary.result @@ -3244,7 +3244,7 @@ SHOW CREATE TABLE t1; Table Create Table t1 CREATE TABLE `t1` ( `c` enum('\0a') CHARACTER SET binary DEFAULT NULL, - `d` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL CHECK (json_valid(`d`)) + `d` json DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci INSERT INTO t1 (c) VALUES (1); SELECT HEX(c) FROM t1; diff --git a/mysql-test/main/ctype_utf16_uca.result b/mysql-test/main/ctype_utf16_uca.result index 218ca4737c9b6..672251c779f66 100644 --- a/mysql-test/main/ctype_utf16_uca.result +++ b/mysql-test/main/ctype_utf16_uca.result @@ -7908,7 +7908,7 @@ SHOW CREATE TABLE t1; Table Create Table t1 CREATE TABLE `t1` ( `c` enum('\0a\0a\0a\0a\0a\0a\0a\0a') CHARACTER SET binary DEFAULT NULL, - `d` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL CHECK (json_valid(`d`)) + `d` json DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci INSERT INTO t1 (c) VALUES (1); SELECT HEX(c) FROM t1; @@ -7920,7 +7920,7 @@ SHOW CREATE TABLE t1; Table Create Table t1 CREATE TABLE `t1` ( `c` enum('\0a\0a\0a\0a\0a\0a\0a\0a\0a') CHARACTER SET binary DEFAULT NULL, - `d` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL CHECK (json_valid(`d`)) + `d` json DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci INSERT INTO t1 (c) VALUES (1); SELECT HEX(c) FROM t1; @@ -7932,7 +7932,7 @@ SHOW CREATE TABLE t1; Table Create Table t1 CREATE TABLE `t1` ( `c` enum('\0a\0a\0a\0a\0a\0a\0a\0a\0a\0a') CHARACTER SET binary DEFAULT NULL, - `d` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL CHECK (json_valid(`d`)) + `d` json DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci INSERT INTO t1 (c) VALUES (1); SELECT HEX(c) FROM t1; diff --git a/mysql-test/main/ctype_utf32.result b/mysql-test/main/ctype_utf32.result index 53fd5179d1e8e..ff37b5a7dbae7 100644 --- a/mysql-test/main/ctype_utf32.result +++ b/mysql-test/main/ctype_utf32.result @@ -3120,7 +3120,7 @@ SHOW CREATE TABLE t1; Table Create Table t1 CREATE TABLE `t1` ( `c1` enum('\0\0\0a','\0\0\0b','\0\0\0a\0\0\0c') CHARACTER SET binary DEFAULT NULL, - `c2` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL CHECK (json_valid(`c2`)), + `c2` json DEFAULT NULL, `c3` int(11) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci INSERT INTO t1 (c1) VALUES (1),(2),(3); diff --git a/mysql-test/main/ctype_utf32_uca.result b/mysql-test/main/ctype_utf32_uca.result index 09eaf02e8af5e..d4b09f42b33e4 100644 --- a/mysql-test/main/ctype_utf32_uca.result +++ b/mysql-test/main/ctype_utf32_uca.result @@ -7970,7 +7970,7 @@ SHOW CREATE TABLE t1; Table Create Table t1 CREATE TABLE `t1` ( `c1` set('\0\0\0a') CHARACTER SET binary DEFAULT NULL, - `c2` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL CHECK (json_valid(`c2`)) + `c2` json DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci DROP TABLE t1; SET NAMES utf8; diff --git a/mysql-test/main/func_json.result b/mysql-test/main/func_json.result index 5d7c3268bf9d4..cd6fff68f7f2a 100644 --- a/mysql-test/main/func_json.result +++ b/mysql-test/main/func_json.result @@ -3921,7 +3921,7 @@ ERROR 23000: CONSTRAINT `obj_table.val_obj` failed for `test`.`obj_table` INSERT INTO obj_table VALUES('{"number1":3, "string1":"abcd"}'); ERROR 23000: CONSTRAINT `obj_table.val_obj` failed for `test`.`obj_table` INSERT INTO obj_table VALUES('{"number1":3, "string1":"abcd", "object1":{"key1":"val1", "key2":[1,2,3, "string1"]}'); -ERROR 23000: CONSTRAINT `obj_table.val_obj` failed for `test`.`obj_table` +ERROR 22007: Incorrect json value: '{"number1":3, "string1":"abcd", "object1":{"key1":"val1", "key2":[1,2,3, "string1"]}' for column `test`.`obj_table`.`val_obj` at row 1 SELECT * FROM obj_table; val_obj {"number1":4, "string1":"abcd", "object1":{"key1":"val1", "key2":[1,2,3, "string1"], "key3":4}} @@ -6003,7 +6003,7 @@ INSERT INTO test_check_json VALUES ('[1, 2, 3]', '[1, 2]', '{"key": "value"}', '{"key": "value"}'), ('{"key": "value"}', '[1, 2]', '{"key": "value"}', '{"key": "value", "key2": "value2"}'); INSERT INTO test_check_json VALUES ('[1, 2, 3]', '{1, 2}', '{"key": "value"}', 'invalid'); -ERROR 23000: CONSTRAINT `test_check_json.j_array` failed for `test`.`test_check_json` +ERROR 22007: Incorrect json value: '{1, 2}' for column `test`.`test_check_json`.`j_array` at row 1 INSERT INTO test_check_json VALUES ('[1, 2, 3]', '[1, 2]', '{"key": "value"}', '{"key": "value", "key": "value2"}'); ERROR 23000: CONSTRAINT `test_check_json.j_object_with_unique_keys` failed for `test`.`test_check_json` DROP TABLE test_check_json; diff --git a/mysql-test/main/func_json.test b/mysql-test/main/func_json.test index cc679cc81c021..a4eb6822b524e 100644 --- a/mysql-test/main/func_json.test +++ b/mysql-test/main/func_json.test @@ -2878,7 +2878,7 @@ INSERT INTO obj_table VALUES('{"number1":4, "string1":"abcd", "object1":{"key1": INSERT INTO obj_table VALUES('{"number1":3, "string1":"abcd", "object1":{"key1":"val1", "key2":[1,2,3, "string1"], "key3":4}}'); --error ER_CONSTRAINT_FAILED INSERT INTO obj_table VALUES('{"number1":3, "string1":"abcd"}'); ---error ER_CONSTRAINT_FAILED +--error ER_TRUNCATED_WRONG_VALUE_FOR_FIELD INSERT INTO obj_table VALUES('{"number1":3, "string1":"abcd", "object1":{"key1":"val1", "key2":[1,2,3, "string1"]}'); SELECT * FROM obj_table; @@ -4622,7 +4622,7 @@ INSERT INTO test_check_json VALUES ('[1, 2, 3]', '[1, 2]', '{"key": "value"}', '{"key": "value"}'), ('{"key": "value"}', '[1, 2]', '{"key": "value"}', '{"key": "value", "key2": "value2"}'); ---error ER_CONSTRAINT_FAILED +--error ER_TRUNCATED_WRONG_VALUE_FOR_FIELD INSERT INTO test_check_json VALUES ('[1, 2, 3]', '{1, 2}', '{"key": "value"}', 'invalid'); --error ER_CONSTRAINT_FAILED INSERT INTO test_check_json VALUES ('[1, 2, 3]', '[1, 2]', '{"key": "value"}', '{"key": "value", "key": "value2"}'); diff --git a/mysql-test/main/information_schema.result b/mysql-test/main/information_schema.result index f2796011ab538..b58d67ba85621 100644 --- a/mysql-test/main/information_schema.result +++ b/mysql-test/main/information_schema.result @@ -916,14 +916,12 @@ information_schema SYSTEM_VARIABLES ENUM_VALUE_LIST information_schema TRIGGERS ACTION_CONDITION information_schema TRIGGERS ACTION_STATEMENT information_schema VIEWS VIEW_DEFINITION -mysql global_priv Priv sys innodb_lock_waits waiting_query sys innodb_lock_waits blocking_query sys processlist current_statement sys processlist last_statement sys schema_auto_increment_columns column_type sys schema_table_lock_waits waiting_query -mysql servers Options sys session current_statement sys session last_statement sys statement_analysis query diff --git a/mysql-test/main/json_normalize.result b/mysql-test/main/json_normalize.result index f414e992982f9..c960066d7e69e 100644 --- a/mysql-test/main/json_normalize.result +++ b/mysql-test/main/json_normalize.result @@ -3,7 +3,7 @@ create table t1 (json json); show create table t1; Table Create Table t1 CREATE TABLE `t1` ( - `json` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL CHECK (json_valid(`json`)) + `json` json DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci insert into t1 values ('{ }'), diff --git a/mysql-test/main/mysql-metadata.result b/mysql-test/main/mysql-metadata.result index 1530465eaf8bd..34059dea7399a 100644 --- a/mysql-test/main/mysql-metadata.result +++ b/mysql-test/main/mysql-metadata.result @@ -18,7 +18,7 @@ Catalog: `def` Database: `test` Table: `t1` Org_table: `t1` -Type: BLOB (format=json) +Type: LONG_BLOB (type=json) Collation: latin1_swedish_ci (8) Length: 4294967295 Max_length: 0 diff --git a/mysql-test/main/mysql_json_table_recreate.result b/mysql-test/main/mysql_json_table_recreate.result index ffeee64b6ddeb..81d445e64080e 100644 --- a/mysql-test/main/mysql_json_table_recreate.result +++ b/mysql-test/main/mysql_json_table_recreate.result @@ -192,25 +192,15 @@ create table t1(j json); show create table t1; Table Create Table t1 CREATE TABLE `t1` ( - `j` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL CHECK (json_valid(`j`)) + `j` json DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci drop table t1; create table t1(j mysql_json); ERROR HY000: 'MYSQL_JSON' is not allowed in this context create table `testjson` ( -`t` json /* JSON from MySQL 5.7*/ CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL -) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci; -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL -) ENGINE=InnoDB DEFAULT CH...' at line 2 -create table `testjson` ( `t` json /* JSON from MySQL 5.7*/ COLLATE utf8mb4_bin NOT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci; -show create table testjson; -Table Create Table -testjson CREATE TABLE `testjson` ( - `t` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL CHECK (json_valid(`t`)) -) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci -drop table testjson; +ERROR HY000: Data type 'json' doesn't support CHARACTER SET attribute. create table `testjson` ( `t` longtext /* JSON from MySQL 5.7 */ CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci; diff --git a/mysql-test/main/mysql_json_table_recreate.test b/mysql-test/main/mysql_json_table_recreate.test index 94477d4f328f5..1245e9b02adf1 100644 --- a/mysql-test/main/mysql_json_table_recreate.test +++ b/mysql-test/main/mysql_json_table_recreate.test @@ -109,19 +109,14 @@ show create table t1; drop table t1; --error ER_NOT_ALLOWED_IN_THIS_CONTEXT create table t1(j mysql_json); -# `json` type should not have character set and collation other than utf8mb4_bin ---error ER_PARSE_ERROR -create table `testjson` ( - `t` json /* JSON from MySQL 5.7*/ CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL -) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci; -# By removing character set from `json` field query should work and -# expand to `longtext` with characterset +# Even if only collation is provided without character set, the native `json` +# type should reject it as it does not support character set/collation attributes +--error ER_UNSUPPORTED_DATA_TYPE_ATTRIBUTE create table `testjson` ( `t` json /* JSON from MySQL 5.7*/ COLLATE utf8mb4_bin NOT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci; -show create table testjson; -drop table testjson; + # `longtext` that is alias can have character set create table `testjson` ( diff --git a/mysql-test/main/system_mysql_db.result b/mysql-test/main/system_mysql_db.result index 9bf7436bc442e..e1a85917b720d 100644 --- a/mysql-test/main/system_mysql_db.result +++ b/mysql-test/main/system_mysql_db.result @@ -78,7 +78,7 @@ Table Create Table global_priv CREATE TABLE `global_priv` ( `Host` char(255) NOT NULL DEFAULT '', `User` char(128) NOT NULL DEFAULT '', - `Priv` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL DEFAULT '{}' CHECK (json_valid(`Priv`)), + `Priv` json NOT NULL DEFAULT '{}' CHECK (json_valid(`Priv`)), PRIMARY KEY (`Host`,`User`) ) ENGINE=Aria DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_bin PAGE_CHECKSUM=1 TRANSACTIONAL=1 COMMENT='Users and global privileges' show create table tables_priv; @@ -133,7 +133,7 @@ servers CREATE TABLE `servers` ( `Socket` char(108) NOT NULL DEFAULT '', `Wrapper` char(64) NOT NULL DEFAULT '', `Owner` varchar(512) NOT NULL DEFAULT '', - `Options` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL DEFAULT '{}' CHECK (json_valid(`Options`)), + `Options` json NOT NULL DEFAULT '{}' CHECK (json_valid(`Options`)), PRIMARY KEY (`Server_name`) ) ENGINE=Aria DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_general_ci PAGE_CHECKSUM=1 TRANSACTIONAL=1 COMMENT='MySQL Foreign Servers table' show create table proc; diff --git a/mysql-test/main/system_mysql_db_fix40123.result b/mysql-test/main/system_mysql_db_fix40123.result index 9cff853d3d98f..1976701189ec6 100644 --- a/mysql-test/main/system_mysql_db_fix40123.result +++ b/mysql-test/main/system_mysql_db_fix40123.result @@ -116,7 +116,7 @@ Table Create Table global_priv CREATE TABLE `global_priv` ( `Host` char(255) NOT NULL DEFAULT '', `User` char(128) NOT NULL DEFAULT '', - `Priv` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL DEFAULT '{}' CHECK (json_valid(`Priv`)), + `Priv` json NOT NULL DEFAULT '{}' CHECK (json_valid(`Priv`)), PRIMARY KEY (`Host`,`User`) ) ENGINE=Aria DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_bin PAGE_CHECKSUM=1 TRANSACTIONAL=1 COMMENT='Users and global privileges' show create table tables_priv; @@ -171,7 +171,7 @@ servers CREATE TABLE `servers` ( `Socket` char(108) NOT NULL DEFAULT '', `Wrapper` char(64) NOT NULL DEFAULT '', `Owner` varchar(512) NOT NULL DEFAULT '', - `Options` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL DEFAULT '{}' CHECK (json_valid(`Options`)), + `Options` json NOT NULL DEFAULT '{}' CHECK (json_valid(`Options`)), PRIMARY KEY (`Server_name`) ) ENGINE=Aria DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_general_ci PAGE_CHECKSUM=1 TRANSACTIONAL=1 COMMENT='MySQL Foreign Servers table' show create table proc; diff --git a/mysql-test/main/system_mysql_db_fix50030.result b/mysql-test/main/system_mysql_db_fix50030.result index a14687557c135..8018a1e3c35a1 100644 --- a/mysql-test/main/system_mysql_db_fix50030.result +++ b/mysql-test/main/system_mysql_db_fix50030.result @@ -120,7 +120,7 @@ Table Create Table global_priv CREATE TABLE `global_priv` ( `Host` char(255) NOT NULL DEFAULT '', `User` char(128) NOT NULL DEFAULT '', - `Priv` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL DEFAULT '{}' CHECK (json_valid(`Priv`)), + `Priv` json NOT NULL DEFAULT '{}' CHECK (json_valid(`Priv`)), PRIMARY KEY (`Host`,`User`) ) ENGINE=Aria DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_bin PAGE_CHECKSUM=1 TRANSACTIONAL=1 COMMENT='Users and global privileges' show create table tables_priv; @@ -175,7 +175,7 @@ servers CREATE TABLE `servers` ( `Socket` char(108) NOT NULL DEFAULT '', `Wrapper` char(64) NOT NULL DEFAULT '', `Owner` varchar(512) NOT NULL DEFAULT '', - `Options` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL DEFAULT '{}' CHECK (json_valid(`Options`)), + `Options` json NOT NULL DEFAULT '{}' CHECK (json_valid(`Options`)), PRIMARY KEY (`Server_name`) ) ENGINE=Aria DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_general_ci PAGE_CHECKSUM=1 TRANSACTIONAL=1 COMMENT='MySQL Foreign Servers table' show create table proc; diff --git a/mysql-test/main/system_mysql_db_fix50117.result b/mysql-test/main/system_mysql_db_fix50117.result index acc7d3b3728a4..2cbe254d3b91e 100644 --- a/mysql-test/main/system_mysql_db_fix50117.result +++ b/mysql-test/main/system_mysql_db_fix50117.result @@ -100,7 +100,7 @@ Table Create Table global_priv CREATE TABLE `global_priv` ( `Host` char(255) NOT NULL DEFAULT '', `User` char(128) NOT NULL DEFAULT '', - `Priv` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL DEFAULT '{}' CHECK (json_valid(`Priv`)), + `Priv` json NOT NULL DEFAULT '{}' CHECK (json_valid(`Priv`)), PRIMARY KEY (`Host`,`User`) ) ENGINE=Aria DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_bin PAGE_CHECKSUM=1 TRANSACTIONAL=1 COMMENT='Users and global privileges' show create table tables_priv; @@ -155,7 +155,7 @@ servers CREATE TABLE `servers` ( `Socket` char(108) NOT NULL DEFAULT '', `Wrapper` char(64) NOT NULL DEFAULT '', `Owner` varchar(512) NOT NULL DEFAULT '', - `Options` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL DEFAULT '{}' CHECK (json_valid(`Options`)), + `Options` json NOT NULL DEFAULT '{}' CHECK (json_valid(`Options`)), PRIMARY KEY (`Server_name`) ) ENGINE=Aria DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_general_ci PAGE_CHECKSUM=1 TRANSACTIONAL=1 COMMENT='MySQL Foreign Servers table' show create table proc; diff --git a/mysql-test/main/system_mysql_db_fix50568.result b/mysql-test/main/system_mysql_db_fix50568.result index 1ca8a75d0abf9..8847e1651bf72 100644 --- a/mysql-test/main/system_mysql_db_fix50568.result +++ b/mysql-test/main/system_mysql_db_fix50568.result @@ -121,7 +121,7 @@ Table Create Table global_priv CREATE TABLE `global_priv` ( `Host` char(255) NOT NULL DEFAULT '', `User` char(128) NOT NULL DEFAULT '', - `Priv` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL DEFAULT '{}' CHECK (json_valid(`Priv`)), + `Priv` json NOT NULL DEFAULT '{}' CHECK (json_valid(`Priv`)), PRIMARY KEY (`Host`,`User`) ) ENGINE=Aria DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_bin PAGE_CHECKSUM=1 TRANSACTIONAL=1 COMMENT='Users and global privileges' show create table tables_priv; @@ -176,7 +176,7 @@ servers CREATE TABLE `servers` ( `Socket` char(108) NOT NULL DEFAULT '', `Wrapper` char(64) NOT NULL DEFAULT '', `Owner` varchar(512) NOT NULL DEFAULT '', - `Options` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL DEFAULT '{}' CHECK (json_valid(`Options`)), + `Options` json NOT NULL DEFAULT '{}' CHECK (json_valid(`Options`)), PRIMARY KEY (`Server_name`) ) ENGINE=Aria DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_general_ci PAGE_CHECKSUM=1 TRANSACTIONAL=1 COMMENT='MySQL Foreign Servers table' show create table proc; diff --git a/mysql-test/main/type_json.result b/mysql-test/main/type_json.result index d1bd3f7a97828..100b2d0f11ee4 100644 --- a/mysql-test/main/type_json.result +++ b/mysql-test/main/type_json.result @@ -2,40 +2,40 @@ create or replace table t1(a json); show create table t1; Table Create Table t1 CREATE TABLE `t1` ( - `a` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL CHECK (json_valid(`a`)) + `a` json DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci create or replace table t1(a json character set utf8); -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'character set utf8)' at line 1 -create or replace table t1(a json default '{a:1}'); +ERROR HY000: Data type 'json' doesn't support CHARACTER SET attribute. +create or replace table t1(a json default '{"a":1}'); show create table t1; Table Create Table t1 CREATE TABLE `t1` ( - `a` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT '{a:1}' CHECK (json_valid(`a`)) + `a` json DEFAULT '{"a":1}' ) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci create or replace table t1(a json not null check (json_valid(a))); show create table t1; Table Create Table t1 CREATE TABLE `t1` ( - `a` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL CHECK (json_valid(`a`)) + `a` json NOT NULL CHECK (json_valid(`a`)) ) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci insert t1 values ('[]'); insert t1 values ('a'); -ERROR 23000: CONSTRAINT `t1.a` failed for `test`.`t1` +ERROR 22007: Incorrect json value: 'a' for column `test`.`t1`.`a` at row 1 create or replace table t1(a json not null); show create table t1; Table Create Table t1 CREATE TABLE `t1` ( - `a` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL CHECK (json_valid(`a`)) + `a` json NOT NULL ) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci insert t1 values ('[]'); insert t1 values ('a'); -ERROR 23000: CONSTRAINT `t1.a` failed for `test`.`t1` +ERROR 22007: Incorrect json value: 'a' for column `test`.`t1`.`a` at row 1 set timestamp=unix_timestamp('2010:11:12 13:14:15'); create or replace table t1(a json default(json_object('now', now()))); show create table t1; Table Create Table t1 CREATE TABLE `t1` ( - `a` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT json_object('now',current_timestamp()) CHECK (json_valid(`a`)) + `a` json DEFAULT json_object('now',current_timestamp()) ) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci insert t1 values (); select * from t1; @@ -51,31 +51,38 @@ t show create table t1; Table Create Table t1 CREATE TABLE `t1` ( - `t` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL CHECK (json_valid(`t`)) + `t` json DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci show create table t2; Table Create Table t2 CREATE TABLE `t2` ( - `a` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL CHECK (json_valid(`a`)), + `a` json DEFAULT NULL, `t` varchar(38) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci show create table t3; Table Create Table t3 CREATE TABLE `t3` ( - `t` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL CHECK (json_valid(`t`)) + `t` json DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci drop table t1,t2,t3; create table t1 (t json check (length(t) > 0)); show create table t1; Table Create Table t1 CREATE TABLE `t1` ( - `t` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL CHECK (octet_length(`t`) > 0) + `t` json DEFAULT NULL CHECK (octet_length(`t`) > 0) ) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci drop table t1; create table t1 (t text) engine=myisam; insert into t1 values ("{}"),(""); create table t2 (t json) select t from t1; -ERROR 23000: CONSTRAINT `t2.t` failed for `test`.`t2` +ERROR 22007: Incorrect json value: '' for column `test`.`t2`.`t` at row 2 +select * from t2; +ERROR 42S02: Table 'test.t2' doesn't exist +drop table t1; +create table t1 (t text) engine=myisam; +insert into t1 values (""),("{}"); +create table t2 (t json) select t from t1; +ERROR 22007: Incorrect json value: '' for column `test`.`t2`.`t` at row 1 select * from t2; ERROR 42S02: Table 'test.t2' doesn't exist drop table t1; @@ -83,7 +90,7 @@ create or replace table t1(a json default(json_object('now', 1)) check (json_val insert into t1 values (); insert into t1 values ("{}"); insert into t1 values ("xxx"); -ERROR 23000: CONSTRAINT `t1.a` failed for `test`.`t1` +ERROR 22007: Incorrect json value: 'xxx' for column `test`.`t1`.`a` at row 1 select * from t1; a {"now": 1} @@ -91,13 +98,120 @@ a show create table t1; Table Create Table t1 CREATE TABLE `t1` ( - `a` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT json_object('now',1) CHECK (json_valid(`a`)) + `a` json DEFAULT json_object('now',1) CHECK (json_valid(`a`)) ) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci drop table t1; +SELECT CAST('{"a":1}' AS JSON); +CAST('{"a":1}' AS JSON) +{"a":1} +SELECT CAST('[]' AS JSON); +CAST('[]' AS JSON) +[] +SELECT CAST('xxx' AS JSON); +CAST('xxx' AS JSON) +NULL +Warnings: +Warning 1292 Truncated incorrect JSON value: 'xxx' +SHOW WARNINGS; +Level Code Message +Warning 1292 Truncated incorrect JSON value: 'xxx' +SELECT CAST(NULL AS JSON); +CAST(NULL AS JSON) +NULL +SELECT CAST('{"a":1}' AS JSON); +Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr +def CAST('{"a":1}' AS JSON) 251 (type=json) 7 7 Y 0 0 8 +CAST('{"a":1}' AS JSON) +{"a":1} +CREATE TABLE t1 (a JSON); +INSERT INTO t1 SELECT CAST('{"x":1}' AS JSON); +SELECT * FROM t1; +a +{"x":1} +INSERT INTO t1 SELECT CAST('bad' AS JSON); +ERROR 22007: Truncated incorrect JSON value: 'bad' +DROP TABLE t1; +SELECT CAST('{}' AS JSON CHARACTER SET utf8); +ERROR HY000: Data type 'JSON' doesn't support CHARACTER SET attribute. +CREATE TABLE t1 (a TEXT); +INSERT INTO t1 VALUES ('{"ok":1}'), ('bad'); +SELECT a FROM t1 WHERE CAST(a AS JSON) IS NOT NULL; +a +{"ok":1} +Warnings: +Warning 1292 Truncated incorrect JSON value: 'bad' +DROP TABLE t1; +SELECT CAST('{"a":1}' AS JSON) UNION ALL SELECT CAST('{"b":2}' AS JSON); +CAST('{"a":1}' AS JSON) +{"a":1} +{"b":2} +EXPLAIN EXTENDED SELECT CAST('{}' AS JSON); +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used +Warnings: +Note 1003 select cast('{}' as json charset latin1) AS `CAST('{}' AS JSON)` +EXPLAIN EXTENDED SELECT `JSON`('{}'); +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used +Warnings: +Note 1003 select cast('{}' as json charset latin1) AS ```JSON``('{}')` +SELECT `JSON`('{"a":1}'); +`JSON`('{"a":1}') +{"a":1} +SELECT `JSON`('[]'); +`JSON`('[]') +[] +SELECT `JSON`('not-json'); +`JSON`('not-json') +NULL +Warnings: +Warning 1292 Truncated incorrect JSON value: 'not-json' +SHOW WARNINGS; +Level Code Message +Warning 1292 Truncated incorrect JSON value: 'not-json' select cast('{a:1}' as text); ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'text)' at line 1 select cast('{a:1}' as json); -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'json)' at line 1 +cast('{a:1}' as json) +NULL +Warnings: +Warning 1292 Truncated incorrect JSON value: '{a:1}' +# +# Prohibit numeric aggregate functions and arithmetic on JSON data type +# +CREATE TABLE t1 (j JSON); +INSERT INTO t1 VALUES ('{"a": 10}'), ('{"a": 20}'), ('[1, 2, 3]'); +SELECT SUM(j) FROM t1; +ERROR HY000: Illegal parameter data type json for operation 'sum' +SELECT AVG(j) FROM t1; +ERROR HY000: Illegal parameter data type json for operation 'avg' +SELECT VARIANCE(j) FROM t1; +ERROR HY000: Illegal parameter data type json for operation 'variance(' +SELECT VAR_SAMP(j) FROM t1; +ERROR HY000: Illegal parameter data type json for operation 'var_samp(' +SELECT STD(j) FROM t1; +ERROR HY000: Illegal parameter data type json for operation 'std(' +SELECT STDDEV_SAMP(j) FROM t1; +ERROR HY000: Illegal parameter data type json for operation 'stddev_samp(' +SELECT BIT_AND(j) FROM t1; +ERROR HY000: Illegal parameter data type json for operation 'bit_and(' +SELECT BIT_OR(j) FROM t1; +ERROR HY000: Illegal parameter data type json for operation 'bit_or(' +SELECT BIT_XOR(j) FROM t1; +ERROR HY000: Illegal parameter data type json for operation 'bit_xor(' +SELECT -j FROM t1; +ERROR HY000: Illegal parameter data type json for operation '-' +SELECT ABS(j) FROM t1; +ERROR HY000: Illegal parameter data type json for operation 'abs' +SELECT ROUND(j) FROM t1; +ERROR HY000: Illegal parameter data type json for operation 'round' +SELECT TRUNCATE(j, 1) FROM t1; +ERROR HY000: Illegal parameter data type json for operation 'truncate' +SELECT CEIL(j) FROM t1; +ERROR HY000: Illegal parameter data type json for operation 'ceiling' +SELECT FLOOR(j) FROM t1; +ERROR HY000: Illegal parameter data type json for operation 'floor' +DROP TABLE t1; # # Start of 10.5 tests # @@ -113,14 +227,14 @@ js3 TEXT CHECK (LENGTH(js2) > 0 OR JSON_VALID(js2)) ) CHARACTER SET utf8; SELECT * FROM t1; Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr -def test t1 t1 js0 js0 252 (format=json) 4294967295 0 Y 144 0 224 +def test t1 t1 js0 js0 251 (type=json) 4294967295 0 Y 144 0 224 def test t1 t1 js1 js1 252 (format=json) 262140 0 Y 16 0 224 def test t1 t1 js2 js2 252 (format=json) 262140 0 Y 16 0 224 def test t1 t1 js3 js3 252 262140 0 Y 16 0 224 js0 js1 js2 js3 SELECT js0, JSON_COMPACT(js0), JSON_COMPACT('{}') FROM t1; Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr -def test t1 t1 js0 js0 252 (format=json) 4294967295 0 Y 144 0 224 +def test t1 t1 js0 js0 251 (type=json) 4294967295 0 Y 144 0 224 def JSON_COMPACT(js0) 251 (format=json) 4294967295 0 Y 128 0 224 def JSON_COMPACT('{}') 253 (format=json) 8 0 Y 0 0 224 js0 JSON_COMPACT(js0) JSON_COMPACT('{}') @@ -132,9 +246,9 @@ CREATE TABLE t1 (a JSON); INSERT INTO t1 VALUES ('{"a":"b"}'); SELECT a, JSON_COMPACT(a), COALESCE(a) FROM t1; Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr -def test t1 t1 a a 252 (format=json) 4294967295 9 Y 144 0 224 +def test t1 t1 a a 251 (type=json) 4294967295 9 Y 144 0 224 def JSON_COMPACT(a) 251 (format=json) 4294967295 9 Y 128 0 224 -def COALESCE(a) 251 (format=json) 4294967295 9 Y 128 39 224 +def COALESCE(a) 251 (type=json) 4294967295 9 Y 128 39 224 a JSON_COMPACT(a) COALESCE(a) {"a":"b"} {"a":"b"} {"a":"b"} SELECT JSON_ARRAYAGG(1), JSON_ARRAYAGG(a) FROM t1; @@ -176,6 +290,16 @@ select json_arrayagg(v1_json) from v1; json_arrayagg(v1_json) [{"a": "b"}] drop view v1; +create table t1 (a json); +insert into t1 values (777); +insert into t1 values (123.45); +insert into t1 values (true); +select * from t1; +a +777 +123.45 +1 +drop table t1; # # End of 10.5 tests # diff --git a/mysql-test/main/type_json.test b/mysql-test/main/type_json.test index 8effe78f803d4..02cd792054be6 100644 --- a/mysql-test/main/type_json.test +++ b/mysql-test/main/type_json.test @@ -5,22 +5,23 @@ create or replace table t1(a json); show create table t1; ---error ER_PARSE_ERROR +--error ER_UNSUPPORTED_DATA_TYPE_ATTRIBUTE create or replace table t1(a json character set utf8); -create or replace table t1(a json default '{a:1}'); +create or replace table t1(a json default '{"a":1}'); show create table t1; + create or replace table t1(a json not null check (json_valid(a))); show create table t1; insert t1 values ('[]'); ---error ER_CONSTRAINT_FAILED +--error ER_TRUNCATED_WRONG_VALUE_FOR_FIELD insert t1 values ('a'); create or replace table t1(a json not null); show create table t1; insert t1 values ('[]'); ---error ER_CONSTRAINT_FAILED +--error ER_TRUNCATED_WRONG_VALUE_FOR_FIELD insert t1 values ('a'); set timestamp=unix_timestamp('2010:11:12 13:14:15'); @@ -45,7 +46,15 @@ drop table t1; create table t1 (t text) engine=myisam; insert into t1 values ("{}"),(""); ---error ER_CONSTRAINT_FAILED +--error ER_TRUNCATED_WRONG_VALUE_FOR_FIELD +create table t2 (t json) select t from t1; +--error ER_NO_SUCH_TABLE +select * from t2; +drop table t1; + +create table t1 (t text) engine=myisam; +insert into t1 values (""),("{}"); +--error ER_TRUNCATED_WRONG_VALUE_FOR_FIELD create table t2 (t json) select t from t1; --error ER_NO_SUCH_TABLE select * from t2; @@ -54,17 +63,112 @@ drop table t1; create or replace table t1(a json default(json_object('now', 1)) check (json_valid(a))); insert into t1 values (); insert into t1 values ("{}"); ---error ER_CONSTRAINT_FAILED +--error ER_TRUNCATED_WRONG_VALUE_FOR_FIELD insert into t1 values ("xxx"); select * from t1; show create table t1; drop table t1; +# Casting + +# Basic valid cast +SELECT CAST('{"a":1}' AS JSON); +SELECT CAST('[]' AS JSON); + + +# null with warning +SELECT CAST('xxx' AS JSON); +SHOW WARNINGS; + +# Null +SELECT CAST(NULL AS JSON); + +--enable_metadata +SELECT CAST('{"a":1}' AS JSON); +--disable_metadata + +CREATE TABLE t1 (a JSON); +INSERT INTO t1 SELECT CAST('{"x":1}' AS JSON); +SELECT * FROM t1; +--error ER_TRUNCATED_WRONG_VALUE +INSERT INTO t1 SELECT CAST('bad' AS JSON); +DROP TABLE t1; + + +# test failing to assign charset even it's utf8 +--error ER_UNSUPPORTED_DATA_TYPE_ATTRIBUTE +SELECT CAST('{}' AS JSON CHARACTER SET utf8); + + +CREATE TABLE t1 (a TEXT); +INSERT INTO t1 VALUES ('{"ok":1}'), ('bad'); +SELECT a FROM t1 WHERE CAST(a AS JSON) IS NOT NULL; +DROP TABLE t1; + +SELECT CAST('{"a":1}' AS JSON) UNION ALL SELECT CAST('{"b":2}' AS JSON); + +EXPLAIN EXTENDED SELECT CAST('{}' AS JSON); +EXPLAIN EXTENDED SELECT `JSON`('{}'); + + +# test make_constructor_item + +SELECT `JSON`('{"a":1}'); +SELECT `JSON`('[]'); + +# Invalid JSON returns NULL and throws a warning +SELECT `JSON`('not-json'); +SHOW WARNINGS; + --error ER_PARSE_ERROR select cast('{a:1}' as text); ---error ER_PARSE_ERROR + select cast('{a:1}' as json); + +--echo # +--echo # Prohibit numeric aggregate functions and arithmetic on JSON data type +--echo # + +CREATE TABLE t1 (j JSON); +INSERT INTO t1 VALUES ('{"a": 10}'), ('{"a": 20}'), ('[1, 2, 3]'); + +--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION +SELECT SUM(j) FROM t1; +--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION +SELECT AVG(j) FROM t1; +--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION +SELECT VARIANCE(j) FROM t1; +--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION +SELECT VAR_SAMP(j) FROM t1; +--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION +SELECT STD(j) FROM t1; +--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION +SELECT STDDEV_SAMP(j) FROM t1; + +--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION +SELECT BIT_AND(j) FROM t1; +--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION +SELECT BIT_OR(j) FROM t1; +--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION +SELECT BIT_XOR(j) FROM t1; + + +--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION +SELECT -j FROM t1; +--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION +SELECT ABS(j) FROM t1; +--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION +SELECT ROUND(j) FROM t1; +--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION +SELECT TRUNCATE(j, 1) FROM t1; +--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION +SELECT CEIL(j) FROM t1; +--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION +SELECT FLOOR(j) FROM t1; + +DROP TABLE t1; + --echo # --echo # Start of 10.5 tests --echo # @@ -135,6 +239,13 @@ select v1_json from v1; select json_arrayagg(v1_json) from v1; drop view v1; +create table t1 (a json); +insert into t1 values (777); +insert into t1 values (123.45); +insert into t1 values (true); +select * from t1; +drop table t1; + --echo # --echo # End of 10.5 tests --echo # diff --git a/mysql-test/suite/compat/oracle/r/column_compression.result b/mysql-test/suite/compat/oracle/r/column_compression.result index a8bf52817a422..a2e40c10a741e 100644 --- a/mysql-test/suite/compat/oracle/r/column_compression.result +++ b/mysql-test/suite/compat/oracle/r/column_compression.result @@ -25,7 +25,7 @@ d TINYTEXT COMPRESSED BINARY SHOW CREATE TABLE t1; Table Create Table t1 CREATE TABLE "t1" ( - "a" longtext /*M!100301 COMPRESSED*/ CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL CHECK (json_valid("a")), + "a" json DEFAULT NULL, "b" varchar(1000) /*M!100301 COMPRESSED*/ CHARACTER SET latin1 COLLATE latin1_bin DEFAULT NULL, "c" varchar(1000) /*M!100301 COMPRESSED*/ CHARACTER SET utf8mb3 COLLATE utf8mb3_bin DEFAULT NULL, "d" tinytext /*M!100301 COMPRESSED*/ CHARACTER SET latin1 COLLATE latin1_bin DEFAULT NULL diff --git a/mysql-test/suite/funcs_1/r/is_columns_mysql.result b/mysql-test/suite/funcs_1/r/is_columns_mysql.result index ca8acc663af84..5ead813877fc7 100644 --- a/mysql-test/suite/funcs_1/r/is_columns_mysql.result +++ b/mysql-test/suite/funcs_1/r/is_columns_mysql.result @@ -77,7 +77,7 @@ def mysql general_log server_id 4 NULL NO int NULL NULL 10 0 NULL NULL NULL int( def mysql general_log thread_id 3 NULL NO bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned select,insert,update,references NEVER NULL NO NO def mysql general_log user_host 2 NULL NO mediumtext 16777215 16777215 NULL NULL NULL utf8mb3 utf8mb3_general_ci mediumtext select,insert,update,references NEVER NULL NO NO def mysql global_priv Host 1 '' NO char 255 765 NULL NULL NULL utf8mb3 utf8mb3_bin char(255) PRI select,insert,update,references NEVER NULL NO NO -def mysql global_priv Priv 3 '{}' NO longtext 4294967295 4294967295 NULL NULL NULL utf8mb4 utf8mb4_bin longtext select,insert,update,references NEVER NULL NO NO +def mysql global_priv Priv 3 '{}' NO json 4294967295 4294967295 NULL NULL NULL NULL NULL json select,insert,update,references NEVER NULL NO NO def mysql global_priv User 2 '' NO char 128 384 NULL NULL NULL utf8mb3 utf8mb3_bin char(128) PRI select,insert,update,references NEVER NULL NO NO def mysql gtid_slave_pos domain_id 1 NULL NO int NULL NULL 10 0 NULL NULL NULL int(10) unsigned PRI select,insert,update,references NEVER NULL NO NO def mysql gtid_slave_pos seq_no 4 NULL NO bigint NULL NULL 20 0 NULL NULL NULL bigint(20) unsigned select,insert,update,references NEVER NULL NO NO @@ -161,7 +161,7 @@ def mysql roles_mapping Role 3 '' NO char 128 384 NULL NULL NULL utf8mb3 utf8mb3 def mysql roles_mapping User 2 '' NO char 128 384 NULL NULL NULL utf8mb3 utf8mb3_bin char(128) PRI select,insert,update,references NEVER NULL NO NO def mysql servers Db 3 '' NO char 64 192 NULL NULL NULL utf8mb3 utf8mb3_general_ci char(64) select,insert,update,references NEVER NULL NO NO def mysql servers Host 2 '' NO varchar 2048 6144 NULL NULL NULL utf8mb3 utf8mb3_general_ci varchar(2048) select,insert,update,references NEVER NULL NO NO -def mysql servers Options 10 '{}' NO longtext 4294967295 4294967295 NULL NULL NULL utf8mb4 utf8mb4_bin longtext select,insert,update,references NEVER NULL NO NO +def mysql servers Options 10 '{}' NO json 4294967295 4294967295 NULL NULL NULL NULL NULL json select,insert,update,references NEVER NULL NO NO def mysql servers Owner 9 '' NO varchar 512 1536 NULL NULL NULL utf8mb3 utf8mb3_general_ci varchar(512) select,insert,update,references NEVER NULL NO NO def mysql servers Password 5 '' NO char 64 192 NULL NULL NULL utf8mb3 utf8mb3_general_ci char(64) select,insert,update,references NEVER NULL NO NO def mysql servers Port 6 0 NO int NULL NULL 10 0 NULL NULL NULL int(4) select,insert,update,references NEVER NULL NO NO @@ -273,6 +273,7 @@ AND CHARACTER_OCTET_LENGTH / CHARACTER_MAXIMUM_LENGTH = 1 ORDER BY CHARACTER_SET_NAME, COLLATION_NAME, COL_CML; COL_CML DATA_TYPE CHARACTER_SET_NAME COLLATION_NAME 1.0000 blob NULL NULL +1.0000 json NULL NULL 1.0000 longblob NULL NULL 1.0000 varbinary NULL NULL 1.0000 char latin1 latin1_swedish_ci @@ -408,7 +409,7 @@ NULL mysql general_log server_id int NULL NULL NULL NULL int(10) unsigned 1.0000 mysql general_log argument mediumtext 16777215 16777215 utf8mb3 utf8mb3_general_ci mediumtext 3.0000 mysql global_priv Host char 255 765 utf8mb3 utf8mb3_bin char(255) 3.0000 mysql global_priv User char 128 384 utf8mb3 utf8mb3_bin char(128) -1.0000 mysql global_priv Priv longtext 4294967295 4294967295 utf8mb4 utf8mb4_bin longtext +1.0000 mysql global_priv Priv json 4294967295 4294967295 NULL NULL json NULL mysql gtid_slave_pos domain_id int NULL NULL NULL NULL int(10) unsigned NULL mysql gtid_slave_pos sub_id bigint NULL NULL NULL NULL bigint(20) unsigned NULL mysql gtid_slave_pos server_id int NULL NULL NULL NULL int(10) unsigned @@ -498,7 +499,7 @@ NULL mysql servers Port int NULL NULL NULL NULL int(4) 3.0000 mysql servers Socket char 108 324 utf8mb3 utf8mb3_general_ci char(108) 3.0000 mysql servers Wrapper char 64 192 utf8mb3 utf8mb3_general_ci char(64) 3.0000 mysql servers Owner varchar 512 1536 utf8mb3 utf8mb3_general_ci varchar(512) -1.0000 mysql servers Options longtext 4294967295 4294967295 utf8mb4 utf8mb4_bin longtext +1.0000 mysql servers Options json 4294967295 4294967295 NULL NULL json NULL mysql slow_log start_time timestamp NULL NULL NULL NULL timestamp(6) 1.0000 mysql slow_log user_host mediumtext 16777215 16777215 utf8mb3 utf8mb3_general_ci mediumtext NULL mysql slow_log query_time time NULL NULL NULL NULL time(6) diff --git a/mysql-test/suite/funcs_1/r/is_columns_mysql_embedded.result b/mysql-test/suite/funcs_1/r/is_columns_mysql_embedded.result index de070ce0bb0c0..aa07b64f92601 100644 --- a/mysql-test/suite/funcs_1/r/is_columns_mysql_embedded.result +++ b/mysql-test/suite/funcs_1/r/is_columns_mysql_embedded.result @@ -77,7 +77,7 @@ def mysql general_log server_id 4 NULL NO int NULL NULL 10 0 NULL NULL NULL int( def mysql general_log thread_id 3 NULL NO bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned NEVER NULL NO NO def mysql general_log user_host 2 NULL NO mediumtext 16777215 16777215 NULL NULL NULL utf8mb3 utf8mb3_general_ci mediumtext NEVER NULL NO NO def mysql global_priv Host 1 '' NO char 255 765 NULL NULL NULL utf8mb3 utf8mb3_bin char(255) PRI NEVER NULL NO NO -def mysql global_priv Priv 3 '{}' NO longtext 4294967295 4294967295 NULL NULL NULL utf8mb4 utf8mb4_bin longtext NEVER NULL NO NO +def mysql global_priv Priv 3 '{}' NO json 4294967295 4294967295 NULL NULL NULL NULL NULL json NEVER NULL NO NO def mysql global_priv User 2 '' NO char 128 384 NULL NULL NULL utf8mb3 utf8mb3_bin char(128) PRI NEVER NULL NO NO def mysql gtid_slave_pos domain_id 1 NULL NO int NULL NULL 10 0 NULL NULL NULL int(10) unsigned PRI NEVER NULL NO NO def mysql gtid_slave_pos seq_no 4 NULL NO bigint NULL NULL 20 0 NULL NULL NULL bigint(20) unsigned NEVER NULL NO NO @@ -147,7 +147,7 @@ def mysql roles_mapping Role 3 '' NO char 128 384 NULL NULL NULL utf8mb3 utf8mb3 def mysql roles_mapping User 2 '' NO char 128 384 NULL NULL NULL utf8mb3 utf8mb3_bin char(128) PRI NEVER NULL NO NO def mysql servers Db 3 '' NO char 64 192 NULL NULL NULL utf8mb3 utf8mb3_general_ci char(64) NEVER NULL NO NO def mysql servers Host 2 '' NO varchar 2048 6144 NULL NULL NULL utf8mb3 utf8mb3_general_ci varchar(2048) NEVER NULL NO NO -def mysql servers Options 10 '{}' NO longtext 4294967295 4294967295 NULL NULL NULL utf8mb4 utf8mb4_bin longtext NEVER NULL NO NO +def mysql servers Options 10 '{}' NO json 4294967295 4294967295 NULL NULL NULL NULL NULL json NEVER NULL NO NO def mysql servers Owner 9 '' NO varchar 512 1536 NULL NULL NULL utf8mb3 utf8mb3_general_ci varchar(512) NEVER NULL NO NO def mysql servers Password 5 '' NO char 64 192 NULL NULL NULL utf8mb3 utf8mb3_general_ci char(64) NEVER NULL NO NO def mysql servers Port 6 0 NO int NULL NULL 10 0 NULL NULL NULL int(4) NEVER NULL NO NO @@ -258,6 +258,7 @@ AND CHARACTER_OCTET_LENGTH / CHARACTER_MAXIMUM_LENGTH = 1 ORDER BY CHARACTER_SET_NAME, COLLATION_NAME, COL_CML; COL_CML DATA_TYPE CHARACTER_SET_NAME COLLATION_NAME 1.0000 blob NULL NULL +1.0000 json NULL NULL 1.0000 longblob NULL NULL 1.0000 varbinary NULL NULL 1.0000 char latin1 latin1_swedish_ci @@ -405,7 +406,7 @@ NULL mysql general_log server_id int NULL NULL NULL NULL int(10) unsigned 1.0000 mysql general_log argument mediumtext 16777215 16777215 utf8mb3 utf8mb3_general_ci mediumtext 3.0000 mysql global_priv Host char 255 765 utf8mb3 utf8mb3_bin char(255) 3.0000 mysql global_priv User char 128 384 utf8mb3 utf8mb3_bin char(128) -1.0000 mysql global_priv Priv longtext 4294967295 4294967295 utf8mb4 utf8mb4_bin longtext +1.0000 mysql global_priv Priv json 4294967295 4294967295 NULL NULL json NULL mysql gtid_slave_pos domain_id int NULL NULL NULL NULL int(10) unsigned NULL mysql gtid_slave_pos sub_id bigint NULL NULL NULL NULL bigint(20) unsigned NULL mysql gtid_slave_pos server_id int NULL NULL NULL NULL int(10) unsigned @@ -481,7 +482,7 @@ NULL mysql servers Port int NULL NULL NULL NULL int(4) 3.0000 mysql servers Socket char 108 324 utf8mb3 utf8mb3_general_ci char(108) 3.0000 mysql servers Wrapper char 64 192 utf8mb3 utf8mb3_general_ci char(64) 3.0000 mysql servers Owner varchar 512 1536 utf8mb3 utf8mb3_general_ci varchar(512) -1.0000 mysql servers Options longtext 4294967295 4294967295 utf8mb4 utf8mb4_bin longtext +1.0000 mysql servers Options json 4294967295 4294967295 NULL NULL json NULL mysql slow_log start_time timestamp NULL NULL NULL NULL timestamp(6) 1.0000 mysql slow_log user_host mediumtext 16777215 16777215 utf8mb3 utf8mb3_general_ci mediumtext NULL mysql slow_log query_time time NULL NULL NULL NULL time(6) diff --git a/mysql-test/suite/json/r/json_table_mysql.result b/mysql-test/suite/json/r/json_table_mysql.result index 41ecc786b9321..76c6dbe663db1 100644 --- a/mysql-test/suite/json/r/json_table_mysql.result +++ b/mysql-test/suite/json/r/json_table_mysql.result @@ -1122,8 +1122,9 @@ SELECT * FROM (SELECT CAST(blb AS JSON) jf FROM JSON_TABLE('"asd123"', '$' COLUMNS (blb BLOB PATH '$')) AS jti) AS dt, JSON_TABLE(jf, '$' COLUMNS (blb BLOB PATH '$')) AS jto; -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'JSON) jf FROM -JSON_TABLE('"asd123"', '$' COLUMNS (blb BLOB PATH '$')) AS jti)...' at line 2 +jf blb +Warnings: +Warning 1292 Truncated incorrect JSON value: 'asd123' DROP TABLE t1; # # Bug#26500384: ASSERT FAILURE IN QUERY WITH WINDOW FUNCTION AND diff --git a/mysql-test/suite/json/t/json_table_mysql.test b/mysql-test/suite/json/t/json_table_mysql.test index 93881703b450f..8fc1dc35c658f 100644 --- a/mysql-test/suite/json/t/json_table_mysql.test +++ b/mysql-test/suite/json/t/json_table_mysql.test @@ -947,8 +947,7 @@ EXPLAIN SELECT alias.* FROM JSON_TABLE('"asd123"', '$' COLUMNS (blb TINYTEXT PAT EXPLAIN SELECT alias.* FROM JSON_TABLE('"asd123"', '$' COLUMNS (blb MEDIUMTEXT PATH '$')) as alias; EXPLAIN SELECT alias.* FROM JSON_TABLE('"asd123"', '$' COLUMNS (blb LONGTEXT PATH '$')) as alias; # But can't be used as a data source -#--error ER_WRONG_ARGUMENTS ---error ER_PARSE_ERROR + SELECT * FROM (SELECT CAST(blb AS JSON) jf FROM JSON_TABLE('"asd123"', '$' COLUMNS (blb BLOB PATH '$')) AS jti) AS dt, diff --git a/mysql-test/suite/plugins/r/feedback_plugin_load.result b/mysql-test/suite/plugins/r/feedback_plugin_load.result index 0f5f56c6f476f..afa289ef53fba 100644 --- a/mysql-test/suite/plugins/r/feedback_plugin_load.result +++ b/mysql-test/suite/plugins/r/feedback_plugin_load.result @@ -30,7 +30,6 @@ VARIABLE_VALUE>0 VARIABLE_NAME 1 Collation used utf8mb3_bin 1 Collation used utf8mb3_general_ci 1 Collation used utf8mb3_uca1400_ai_ci -1 Collation used utf8mb4_bin 1 Collation used utf8mb4_general_ci 1 Collation used utf8mb4_uca1400_ai_ci prepare stmt from "SELECT VARIABLE_VALUE>0, VARIABLE_NAME FROM INFORMATION_SCHEMA.FEEDBACK WHERE VARIABLE_NAME LIKE 'Collation used %' ORDER BY VARIABLE_NAME"; @@ -47,7 +46,6 @@ VARIABLE_VALUE>0 VARIABLE_NAME 1 Collation used utf8mb3_bin 1 Collation used utf8mb3_general_ci 1 Collation used utf8mb3_uca1400_ai_ci -1 Collation used utf8mb4_bin 1 Collation used utf8mb4_general_ci 1 Collation used utf8mb4_uca1400_ai_ci execute stmt; @@ -63,7 +61,6 @@ VARIABLE_VALUE>0 VARIABLE_NAME 1 Collation used utf8mb3_bin 1 Collation used utf8mb3_general_ci 1 Collation used utf8mb3_uca1400_ai_ci -1 Collation used utf8mb4_bin 1 Collation used utf8mb4_general_ci 1 Collation used utf8mb4_uca1400_ai_ci deallocate prepare stmt; diff --git a/plugin/type_inet/mysql-test/type_inet/type_inet6_mix_json.result b/plugin/type_inet/mysql-test/type_inet/type_inet6_mix_json.result index 8b291b9542ef8..bd5808c62a882 100644 --- a/plugin/type_inet/mysql-test/type_inet/type_inet6_mix_json.result +++ b/plugin/type_inet/mysql-test/type_inet/type_inet6_mix_json.result @@ -3,40 +3,38 @@ # CREATE TABLE t1 (a INET6, b JSON, c LONGTEXT); INSERT INTO t1 VALUES ('::', '{"b": "b"}', '{"c": "c"}'); +SELECT COALESCE(a,b) FROM t1 LIMIT 0; +ERROR HY000: Illegal parameter data types inet6 and json for operation 'coalesce' +SELECT LEAST(a,b) FROM t1 LIMIT 0; +ERROR HY000: Illegal parameter data types inet6 and json for operation 'least' SELECT -COALESCE(a,b), COALESCE(a,c), -LEAST(a,b), LEAST(a,c) +COALESCE(a,c), +LEAST(a,c) FROM t1 LIMIT 0; Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr -def COALESCE(a,b) 254 (type=inet6) 39 0 Y 32 0 8 def COALESCE(a,c) 254 (type=inet6) 39 0 Y 32 0 8 -def LEAST(a,b) 254 (type=inet6) 39 0 Y 32 0 8 def LEAST(a,c) 254 (type=inet6) 39 0 Y 32 0 8 -COALESCE(a,b) COALESCE(a,c) LEAST(a,b) LEAST(a,c) +COALESCE(a,c) LEAST(a,c) CREATE TABLE t2 AS SELECT -COALESCE(a,b), COALESCE(a,c), -LEAST(a,b), LEAST(a,c) +COALESCE(a,c), +LEAST(a,c) FROM t1 LIMIT 0; SHOW CREATE TABLE t2; Table Create Table t2 CREATE TABLE `t2` ( - `COALESCE(a,b)` inet6 DEFAULT NULL, `COALESCE(a,c)` inet6 DEFAULT NULL, - `LEAST(a,b)` inet6 DEFAULT NULL, `LEAST(a,c)` inet6 DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci DROP TABLE t2; SELECT * FROM t1 WHERE a=b; -a b c -Warnings: -Warning 1292 Incorrect inet6 value: '{"b": "b"}' +ERROR HY000: Illegal parameter data types inet6 and json for operation '=' SELECT * FROM t1 WHERE a=c; a b c Warnings: Warning 1292 Incorrect inet6 value: '{"c": "c"}' SELECT a+b FROM t1; -ERROR HY000: Illegal parameter data types inet6 and longblob/json for operation '+' +ERROR HY000: Illegal parameter data types inet6 and json for operation '+' SELECT a+c FROM t1; ERROR HY000: Illegal parameter data types inet6 and longblob for operation '+' DROP TABLE t1; diff --git a/plugin/type_inet/mysql-test/type_inet/type_inet6_mix_json.test b/plugin/type_inet/mysql-test/type_inet/type_inet6_mix_json.test index 74a91ff9a054c..9f472d771ffbf 100644 --- a/plugin/type_inet/mysql-test/type_inet/type_inet6_mix_json.test +++ b/plugin/type_inet/mysql-test/type_inet/type_inet6_mix_json.test @@ -3,42 +3,48 @@ --echo # # -# Testing that JSON data types inherit properties -# from their non-JSON counterparts when mixed to INET6. +# Testing that JSON data type is NOT compatible with INET6. # -# E.g. JSON acts exactly like LONGTEXT when mixed to INET6: +# JSON is a distinct type, mixing it with INET6 always returns an error: # -# - COALESCE(inet6,json) returns inet6 (type aggregation for result) -# - LEAST(inet6,json) returns inet6 (type aggregation for min/max) -# - inet6=json is compared as inet6 (type aggregation for comparison) -# - inet6+json returns an error (type aggregation for numeric op) +# - COALESCE(inet6,json) returns an error (type aggregation for result) +# - LEAST(inet6,json) returns an error (type aggregation for min/max) +# - inet6=json returns an error (type aggregation for comparison) +# - inet6+json returns an error (type aggregation for numeric op) # # Mixing INET6 and JSON is actually meaningless: # Non of valid JSON values are valid INET6. -# +# # Some queries below intentionally use LIMIT 0 to avoid errors. # CREATE TABLE t1 (a INET6, b JSON, c LONGTEXT); INSERT INTO t1 VALUES ('::', '{"b": "b"}', '{"c": "c"}'); +--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION +SELECT COALESCE(a,b) FROM t1 LIMIT 0; + +--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION +SELECT LEAST(a,b) FROM t1 LIMIT 0; + --disable_ps_protocol --enable_metadata SELECT - COALESCE(a,b), COALESCE(a,c), - LEAST(a,b), LEAST(a,c) + COALESCE(a,c), + LEAST(a,c) FROM t1 LIMIT 0; --disable_metadata --enable_ps_protocol CREATE TABLE t2 AS SELECT - COALESCE(a,b), COALESCE(a,c), - LEAST(a,b), LEAST(a,c) + COALESCE(a,c), + LEAST(a,c) FROM t1 LIMIT 0; SHOW CREATE TABLE t2; DROP TABLE t2; +--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION SELECT * FROM t1 WHERE a=b; SELECT * FROM t1 WHERE a=c; diff --git a/plugin/type_json/CMakeLists.txt b/plugin/type_json/CMakeLists.txt new file mode 100644 index 0000000000000..d10311a49ff69 --- /dev/null +++ b/plugin/type_json/CMakeLists.txt @@ -0,0 +1,3 @@ +MYSQL_ADD_PLUGIN(type_json + plugin.cc sql_type_json.cc + MANDATORY RECOMPILE_FOR_EMBEDDED) diff --git a/plugin/type_json/plugin.cc b/plugin/type_json/plugin.cc new file mode 100644 index 0000000000000..7a95d98b2688b --- /dev/null +++ b/plugin/type_json/plugin.cc @@ -0,0 +1,31 @@ +#define MYSQL_SERVER +#include "mariadb.h" +#include "sql_class.h" +#include "sql_type_json.h" +#include +#include + +static struct st_mariadb_data_type plugin_descriptor_json= +{ + MariaDB_DATA_TYPE_INTERFACE_VERSION, + &type_handler_json +}; + +maria_declare_plugin(type_json) +{ + MariaDB_DATA_TYPE_PLUGIN, // the plugin type (see include/mysql/plugin.h) + &plugin_descriptor_json, // pointer to type-specific plugin descriptor + "json", // plugin name + "Hadeer Ramadan", // plugin author + "Data type json", // the plugin description + PLUGIN_LICENSE_GPL, // the plugin license (see include/mysql/plugin.h) + 0, // Pointer to plugin initialization function + 0, // Pointer to plugin deinitialization function + 0x0100, // Numeric version 0xAABB means AA.BB version + NULL, // Status variables + NULL, // System variables + "1.0", // String version representation + MariaDB_PLUGIN_MATURITY_GAMMA // Maturity(see include/mysql/plugin.h) +} +maria_declare_plugin_end; + diff --git a/plugin/type_json/sql_type_json.cc b/plugin/type_json/sql_type_json.cc new file mode 100644 index 0000000000000..ff8b45b3ac0bf --- /dev/null +++ b/plugin/type_json/sql_type_json.cc @@ -0,0 +1,342 @@ +#define MYSQL_SERVER +#include "mariadb.h" +#include "sql_class.h" +#include "sql_lex.h" +#include "sql_type_json.h" + +Type_handler_json type_handler_json; +Type_collection_json_plugin type_collection_json; + +const Type_collection *Type_handler_json::type_collection() const +{ + return &type_collection_json; +} + + + +Field *Type_handler_json::make_table_field(MEM_ROOT *root, + const LEX_CSTRING *name, + const Record_addr &addr, + const Type_all_attributes &attr, + TABLE_SHARE *share) const +{ + return new (root) Field_json(addr.ptr(), addr.null_ptr(), addr.null_bit(), + Field::NONE, name, share); +} + +Field *Type_handler_json::make_table_field_from_def( + TABLE_SHARE *share, MEM_ROOT *root, const LEX_CSTRING *name, + const Record_addr &rec, const Bit_addr &bit, + const Column_definition_attributes *attr, uint32 flags) const +{ + return new (root) Field_json(rec.ptr(), rec.null_ptr(), rec.null_bit(), + attr->unireg_check, name, share); +} + +Field *Type_handler_json::make_conversion_table_field( + MEM_ROOT *root, TABLE *table, uint metadata, const Field *target) const +{ + /* A JSON field uses 4 bytes for length as json file is a long blob*/ + uint pack_length= metadata & 0x00ff; + if (pack_length != 4) + return NULL; + + return new (root) Field_json(NULL, (uchar *) "", 1, Field::NONE, + &empty_clex_str, table->s); +} + +const Type_handler *Type_handler_json::type_handler_for_comparison() const +{ + return &type_handler_json; +} + +const Type_handler * +Type_handler_json::type_handler_for_tmp_table(const Item *item) const +{ + return &type_handler_json; +} + +bool Type_handler_json::Item_hybrid_func_fix_attributes( + THD *thd, const LEX_CSTRING &func_name, + Type_handler_hybrid_field_type *handler, Type_all_attributes *func, + Item **items, uint nitems) const +{ + if (func->aggregate_attributes_string(func_name, items, nitems)) + return true; + + handler->set_handler(&type_handler_json); + return false; +} + +Item * +Type_handler_json::create_typecast_item(THD *thd, Item *item, + const Type_cast_attributes &attr) const +{ + CHARSET_INFO *real_cs= + attr.charset() ? attr.charset() : thd->variables.collation_connection; + return new (thd->mem_root) Item_json_typecast(thd, item, real_cs); +} + +Item *Type_handler_json::make_constructor_item(THD *thd, + List *args) const +{ + if (!args || args->elements != 1) + return nullptr; + Item_args tmp(thd, *args); + return new (thd->mem_root) Item_json_typecast( + thd, tmp.arguments()[0], thd->variables.collation_connection); +} +/********************Type collection json *******************/ + +const Type_handler * +Type_collection_json_plugin::aggregate_for_comparison(const Type_handler *a, + const Type_handler *b) const +{ + if (a->type_collection() == this) + swap_variables(const Type_handler *, a, b); + if (a->is_scalar_type() || a == &type_handler_null) + return b; + return NULL; +} + +const Type_handler * +Type_collection_json_plugin::aggregate_for_result(const Type_handler *a, + const Type_handler *b) const +{ + return aggregate_for_comparison(a, b); +} + +const Type_handler * +Type_collection_json_plugin::aggregate_for_min_max(const Type_handler *a, + const Type_handler *b) const +{ + return aggregate_for_comparison(a, b); +} + +const Type_handler * +Type_collection_json_plugin::aggregate_for_num_op(const Type_handler *a, + const Type_handler *b) const +{ + return NULL; +} + +bool Type_handler_json:: + Item_func_round_fix_length_and_dec(Item_func_round *item) const +{ + return Item_func_or_sum_illegal_param(item); +} + +bool Type_handler_json:: + Item_func_int_val_fix_length_and_dec(Item_func_int_val *item) const +{ + return Item_func_or_sum_illegal_param(item); +} + +bool Type_handler_json:: + Item_func_abs_fix_length_and_dec(Item_func_abs *item) const +{ + return Item_func_or_sum_illegal_param(item); +} + +bool Type_handler_json:: + Item_func_neg_fix_length_and_dec(Item_func_neg *item) const +{ + return Item_func_or_sum_illegal_param(item); +} + +bool Type_handler_json:: + Item_sum_sum_fix_length_and_dec(Item_sum_sum *item) const +{ + LEX_CSTRING name= {STRING_WITH_LEN("sum")}; + return Item_func_or_sum_illegal_param(name); +} + +bool Type_handler_json:: + Item_sum_avg_fix_length_and_dec(Item_sum_avg *item) const +{ + LEX_CSTRING name= {STRING_WITH_LEN("avg")}; + return Item_func_or_sum_illegal_param(name); +} + +bool Type_handler_json:: + Item_sum_variance_fix_length_and_dec(Item_sum_variance *item) const +{ + return Item_func_or_sum_illegal_param(item); +} + +bool Type_handler_json:: + Item_func_signed_fix_length_and_dec(Item_func_signed *item) const +{ + return Item_func_or_sum_illegal_param(item); +} + +bool Type_handler_json:: + Item_func_unsigned_fix_length_and_dec(Item_func_unsigned *item) const +{ + return Item_func_or_sum_illegal_param(item); +} + +bool Type_handler_json:: + Item_double_typecast_fix_length_and_dec(Item_double_typecast *item) const +{ + return Item_func_or_sum_illegal_param(item); +} + +bool Type_handler_json:: + Item_float_typecast_fix_length_and_dec(Item_float_typecast *item) const +{ + return Item_func_or_sum_illegal_param(item); +} + +bool Type_handler_json:: + Item_decimal_typecast_fix_length_and_dec(Item_decimal_typecast *item) const +{ + return Item_func_or_sum_illegal_param(item); +} + +bool Type_handler_json:: + Item_time_typecast_fix_length_and_dec(Item_time_typecast *item) const +{ + return Item_func_or_sum_illegal_param(item); +} + +bool Type_handler_json:: + Item_date_typecast_fix_length_and_dec(Item_date_typecast *item) const +{ + return Item_func_or_sum_illegal_param(item); +} + +bool Type_handler_json:: + Item_datetime_typecast_fix_length_and_dec(Item_datetime_typecast *item) + const +{ + return Item_func_or_sum_illegal_param(item); +} + +/********************** Field_json *************************/ + +void Field_json::sql_type(String &res) const +{ + res.set_ascii(STRING_WITH_LEN("json")); +} + +int Field_json::report_wrong_value(const ErrConv &val) +{ + THD *thd= get_thd(); + my_error(ER_TRUNCATED_WRONG_VALUE_FOR_FIELD, MYF(0), + "json", val.ptr(), table ? table->s->db.str : nullptr, + table ? table->s->table_name.str : nullptr, field_name.str, + static_cast(thd->get_stmt_da()->current_row_for_warning())); + reset(); + return 1; +} + +int Field_json::store(const char *from, size_t length, CHARSET_INFO *cs) +{ + if (get_thd()->count_cuted_fields != CHECK_FIELD_IGNORE) + { + THD *thd= get_thd(); + json_engine_t je; + int stack_buf[JSON_DEPTH_LIMIT]; + mem_root_dynamic_array_init(thd->mem_root, PSI_INSTRUMENT_MEM, + &je.stack, sizeof(int), stack_buf, + JSON_DEPTH_LIMIT, JSON_DEPTH_INC, MYF(0)); + je.killed_ptr= (const uint32_t *) &thd->killed; + + if (!json_valid(from, length, cs, &je)) + { + return report_wrong_value(ErrConvString(from, length, cs)); + } + } + + return Field_blob::store(from, length, cs); +} + +enum_conv_type Field_json::rpl_conv_type_from(const Conv_source &source, + const Relay_log_info *rli, + const Conv_param ¶m) const +{ + const Type_handler *th= source.type_handler(); + if (th == &type_handler_tiny_blob || th == &type_handler_medium_blob || + th == &type_handler_long_blob || th == &type_handler_blob || + th == &type_handler_blob_compressed || th == &type_handler_string || + th == &type_handler_var_string || th == &type_handler_varchar || + th == &type_handler_varchar_compressed) + { + return CONV_TYPE_PRECISE; + } + + return CONV_TYPE_IMPOSSIBLE; +} + +/***************************************************/ + +class Item_json_typecast_func_handler : public Item_handled_func::Handler_str +{ +public: + const Type_handler * + return_type_handler(const Item_handled_func *item) const override + { + return &type_handler_json; + } + + const Type_handler * + type_handler_for_create_select(const Item_handled_func *item) const override + { + return &type_handler_json; + } + + bool fix_length_and_dec(Item_handled_func *item) const override + { + return false; + } + String *val_str(Item_handled_func *item, String *to) const override + { + DBUG_ASSERT(dynamic_cast(item)); + return static_cast(item)->val_str_generic(to); + } +}; + +static Item_json_typecast_func_handler item_json_typecast_func_handler; + +bool Item_json_typecast::fix_length_and_dec(THD *thd) +{ + set_maybe_null(); + Item_char_typecast::fix_length_and_dec_str(); + set_func_handler(&item_json_typecast_func_handler); + return false; +} + +String *Item_json_typecast::val_str(String *to) +{ + String *res= Item_char_typecast::val_str(to); + if (!res) + return nullptr; + + THD *thd= current_thd; + json_engine_t je; + int stack_buf[JSON_DEPTH_LIMIT]; + mem_root_dynamic_array_init(thd->mem_root, PSI_INSTRUMENT_MEM, + &je.stack, sizeof(int), stack_buf, + JSON_DEPTH_LIMIT, JSON_DEPTH_INC, MYF(0)); + je.killed_ptr= (const uint32_t *) &thd->killed; + if (!json_valid(res->ptr(), res->length(), res->charset(), &je)) + { + ErrConvString err(res->ptr(), res->length(), res->charset()); + push_warning_printf( + thd, Sql_condition::WARN_LEVEL_WARN, ER_TRUNCATED_WRONG_VALUE, + ER_THD(thd, ER_TRUNCATED_WRONG_VALUE), "JSON", err.ptr()); + null_value= true; + return nullptr; + } + return res; +} + +void Item_json_typecast::print(String *str, enum_query_type query_type) +{ + str->append(STRING_WITH_LEN("cast(")); + args[0]->print(str, query_type); + str->append(STRING_WITH_LEN(" as json")); + print_charset(str); + str->append(')'); +} diff --git a/plugin/type_json/sql_type_json.h b/plugin/type_json/sql_type_json.h new file mode 100644 index 0000000000000..b46772d5fda35 --- /dev/null +++ b/plugin/type_json/sql_type_json.h @@ -0,0 +1,150 @@ +#ifndef SQL_TYPE_JSON_PLUGIN_INCLUDED +#define SQL_TYPE_JSON_PLUGIN_INCLUDED + +#include "mariadb.h" +#include "sql_type.h" + +class Type_handler_json : public Type_handler_long_blob +{ +public: + static constexpr LEX_CSTRING name_on_client{STRING_WITH_LEN("json")}; + virtual ~Type_handler_json() {} + bool Item_append_extended_type_info(Send_field_extended_metadata *to, + const Item *item) const override + { + return to->set_data_type_name(name_on_client); + } + + const Type_collection *type_collection() const override; + uint get_column_attributes() const override { return ATTR_NONE; } + + Field *make_table_field(MEM_ROOT *root, const LEX_CSTRING *name, + const Record_addr &addr, + const Type_all_attributes &attr, + TABLE_SHARE *share) const override; + + Field *make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root, + const LEX_CSTRING *name, + const Record_addr &addr, + const Bit_addr &bit, + const Column_definition_attributes *attr, + uint32 flags) const override; + Field *make_conversion_table_field(MEM_ROOT *root, TABLE *table, + uint metadata, + const Field *target) const override; + const Type_handler *type_handler_for_comparison() const override; + const Type_handler *type_handler_for_tmp_table(const Item *item) const override; + bool Item_hybrid_func_fix_attributes(THD *thd, const LEX_CSTRING &func_name, + Type_handler_hybrid_field_type *handler, Type_all_attributes *func, + Item **items, uint nitems) const override; + + virtual Item *create_typecast_item(THD *thd, Item *item, + const Type_cast_attributes &attr) const override; + + Item *make_constructor_item(THD *thd, List *args) const override; + + bool can_return_int() const override { return false; } + bool can_return_decimal() const override { return false; } + bool can_return_real() const override { return false; } + bool can_return_date() const override { return false; } + bool can_return_time() const override { return false; } + + bool Item_func_round_fix_length_and_dec(Item_func_round *) const override; + bool Item_func_int_val_fix_length_and_dec(Item_func_int_val *) const override; + bool Item_func_abs_fix_length_and_dec(Item_func_abs *) const override; + bool Item_func_neg_fix_length_and_dec(Item_func_neg *) const override; + bool Item_sum_sum_fix_length_and_dec(Item_sum_sum *) const override; + bool Item_sum_avg_fix_length_and_dec(Item_sum_avg *) const override; + bool Item_sum_variance_fix_length_and_dec(Item_sum_variance *) const override; + + bool Item_func_signed_fix_length_and_dec(Item_func_signed *) const override; + bool Item_func_unsigned_fix_length_and_dec(Item_func_unsigned *) const override; + bool Item_double_typecast_fix_length_and_dec(Item_double_typecast *) const override; + bool Item_float_typecast_fix_length_and_dec(Item_float_typecast *) const override; + bool Item_decimal_typecast_fix_length_and_dec(Item_decimal_typecast *) const override; + bool Item_time_typecast_fix_length_and_dec(Item_time_typecast *) const override; + bool Item_date_typecast_fix_length_and_dec(Item_date_typecast *) const override; + bool Item_datetime_typecast_fix_length_and_dec(Item_datetime_typecast *) const override; +}; + +extern Type_handler_json type_handler_json; + +class Type_collection_json_plugin : public Type_collection +{ +public: + const Type_handler * + aggregate_for_result(const Type_handler *a, + const Type_handler *b) const override; + + const Type_handler * + aggregate_for_min_max(const Type_handler *a, + const Type_handler *b) const override; + + const Type_handler * + aggregate_for_comparison(const Type_handler *a, + const Type_handler *b) const override; + + const Type_handler * + aggregate_for_num_op(const Type_handler *a, + const Type_handler *b) const override; +}; + +#include "field.h" + +class Field_json : public Field_blob +{ + int report_wrong_value(const ErrConv &val); + +public: + Field_json(uchar *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg, + enum utype unireg_check_arg, const LEX_CSTRING *field_name_arg, + TABLE_SHARE *share) + : Field_blob(ptr_arg, null_ptr_arg, null_bit_arg, unireg_check_arg, + field_name_arg, share, 4 /* blob_pack_length */, + &my_charset_utf8mb4_bin) + { + } + bool has_charset() const override { return false; } + const Type_handler *type_handler() const override + { + return &type_handler_json; + } + using Field_blob::store; + int store(const char *to, size_t length, CHARSET_INFO *charset) override; + void sql_type(String &str) const override; + void make_send_field(Send_field *to) override + { + Field_longstr::make_send_field(to); + to->set_data_type_name(Type_handler_json::name_on_client); + } + uint size_of() const override { return sizeof(*this); } + + enum_conv_type rpl_conv_type_from(const Conv_source &source, + const Relay_log_info *rli, + const Conv_param ¶m) const override; + +}; + +class Item_json_typecast : public Item_char_typecast +{ +public: + Item_json_typecast(THD *thd, Item *a, CHARSET_INFO *cs_arg): + Item_char_typecast(thd, a, -1, cs_arg) {} + + const Type_handler *type_handler() const override + { return &type_handler_json; } + + LEX_CSTRING func_name_cstring() const override + { + static LEX_CSTRING name= {STRING_WITH_LEN("cast_as_json")}; + return name; + } + bool fix_length_and_dec(THD *thd) override; + String *val_str(String *to) override; + Item *shallow_copy(THD *thd) const override + { return get_item_copy(thd, this); } + + void print(String *str, enum_query_type query_type) override; +}; + +#endif // SQL_TYPE_JSON_PLUGIN_INCLUDED diff --git a/sql/sql_type_json.cc b/sql/sql_type_json.cc index c3dfd79668fde..9f92bca84e606 100644 --- a/sql/sql_type_json.cc +++ b/sql/sql_type_json.cc @@ -148,6 +148,8 @@ bool Type_handler_json_common::make_json_valid_expr_if_needed(THD *thd, } + + class Type_collection_json: public Type_collection { const Type_handler *aggregate_common(const Type_handler *a, @@ -236,6 +238,8 @@ class Type_collection_json: public Type_collection }; + + const Type_collection *Type_handler_json_common::type_collection() { static Type_collection_json type_collection_json; diff --git a/sql/sql_type_json.h b/sql/sql_type_json.h index b7fe5c8aa64a3..cdbf2d6d258a2 100644 --- a/sql/sql_type_json.h +++ b/sql/sql_type_json.h @@ -41,7 +41,10 @@ class Type_handler_json_common static const Type_collection *type_collection(); static bool is_json_type_handler(const Type_handler *handler) { - return handler->type_collection() == type_collection(); + if (handler->type_collection() == type_collection()) + return true; + static const Lex_cstring fmt(STRING_WITH_LEN("json")); + return handler->name().eq(fmt); } }; diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index c2fe9974c42df..de73f7204cd51 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -6731,7 +6731,7 @@ field_type_all_builtin: field_type_all: field_type_all_builtin - | udt_name float_options srid_option opt_binary + | udt_name float_options srid_option opt_binary_and_compression { if (Lex->set_field_type_udt(&$$, $1, $2, $4)) MYSQL_YYABORT; @@ -6931,10 +6931,6 @@ field_type_lob: { $$.set(&type_handler_long_blob, $2); } | LONG_SYM opt_binary_and_compression { $$.set(&type_handler_medium_blob, $2); } - | JSON_SYM opt_compressed - { - $$.set(&type_handler_long_blob_json, &MY_CHARSET_UTF8MB4_BIN); - } ; field_type_misc: @@ -12507,6 +12503,12 @@ json_table_field_type: | field_type_temporal | field_type_string | field_type_lob + | JSON_SYM opt_binary_and_compression + { + if (Lex->set_field_type_udt(&$$, Lex_cstring("json", 4), + Lex_length_and_dec_st(), $2)) + MYSQL_YYABORT; + } ; json_opt_on_empty_or_error: @@ -17510,6 +17512,7 @@ reserved_keyword_udt_not_param_type: | IS | ITERATE_SYM | JOIN_SYM + | JSON_SYM | KEYS | KEY_SYM | KILL_SYM