diff --git a/mysql-test/include/dd_schema_assert_and_fill_table_names.inc b/mysql-test/include/dd_schema_assert_and_fill_table_names.inc index 7993c9aa1584..cd75236da514 100644 --- a/mysql-test/include/dd_schema_assert_and_fill_table_names.inc +++ b/mysql-test/include/dd_schema_assert_and_fill_table_names.inc @@ -9,11 +9,11 @@ SET debug = '+d,skip_dd_table_access_check'; --echo ######################################################################## --echo # The number of hidden DD/DDSE tables must be as expected. --echo ######################################################################## -let $number_of_hidden_dd_tables = 31; +let $number_of_hidden_dd_tables = 32; let $assert_cond = "[SELECT COUNT(*) from mysql.tables WHERE schema_id = 1 AND hidden = \'System\']" = $number_of_hidden_dd_tables; ---let $assert_text = There are 31 hidden DD/DDSE tables. +--let $assert_text = There are 32 hidden DD/DDSE tables. --source include/assert.inc # Fill two help tables with the names of the DDSE and DD tables. @@ -46,6 +46,7 @@ eval INSERT INTO $dd_table_names (name) VALUES ('catalogs'), ('character_sets'), ('collations'), + ('check_constraints'), ('column_statistics'), ('column_type_elements'), ('columns'), @@ -78,7 +79,7 @@ eval INSERT INTO $dd_table_names (name) VALUES let $assert_cond = "[SELECT (SELECT COUNT(*) FROM $dd_table_names) + (SELECT COUNT(*) FROM $ddse_table_names)]" = $number_of_hidden_dd_tables + 2; ---let $assert_text = There are 33 DD/DDSE tables in total. +--let $assert_text = There are 34 DD/DDSE tables in total. --source include/assert.inc --echo ######################################################################## diff --git a/mysql-test/r/check_constraints.result b/mysql-test/r/check_constraints.result new file mode 100644 index 000000000000..9cbefeabd020 --- /dev/null +++ b/mysql-test/r/check_constraints.result @@ -0,0 +1,2613 @@ +#------------------------------------------------------------------------ +# Test cases to verify column check constraint syntax. +#------------------------------------------------------------------------ +CREATE TABLE t1(f1 int CHECK); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ')' at line 1 +CREATE TABLE t1(f1 int CHECK()); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '))' at line 1 +CREATE TABLE t1(f1 int CONSTRAINT CHECK()); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '))' at line 1 +CREATE TABLE t1(f1 int t1_ck CHECK()); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 't1_ck CHECK())' at line 1 +CREATE TABLE t1(f1 int CONSTRAINT t1_ck CHECK()); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '))' at line 1 +CREATE TABLE t1(f1 int CONSTRAINT t1_ck CHECK( f1 < 10) NOT); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ')' at line 1 +CREATE TABLE t1(f1 int CHECK(f1)); +ERROR HY000: An expression of non-boolean type specified to a check constraint 't1_chk_1'. +CREATE TABLE t1(f1 int CHECK(f1 + 10)); +ERROR HY000: An expression of non-boolean type specified to a check constraint 't1_chk_1'. +CREATE TABLE t1(f1 int CHECK(f2 < 10)); +ERROR HY000: Column check constraint 't1_chk_1' references other column. +CREATE TABLE t1 (f1 int CHECK(f1 < 10), +f2 int CONSTRAINT t1_f2_ck CHECK (f2 < 10)); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) DEFAULT NULL, + `f2` int(11) DEFAULT NULL, + CONSTRAINT `t1_chk_1` CHECK ((`f1` < 10)), + CONSTRAINT `t1_f2_ck` CHECK ((`f2` < 10)) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci +DROP TABLE t1; +CREATE TABLE t1(f1 int CHECK(f1 < 10), f2 int CHECK); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ')' at line 1 +CREATE TABLE t1(f1 int CHECK(f1 < 10), f2 int CHECK()); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '))' at line 1 +CREATE TABLE t1(f1 int CHECK(f1 < 10), f2 int CONSTRAINT CHECK()); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '))' at line 1 +CREATE TABLE t1(f1 int CHECK(f1 < 10), f2 int t1_f2_ck CHECK(f2 < 10)); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 't1_f2_ck CHECK(f2 < 10))' at line 1 +CREATE TABLE t1(f1 int CHECK(f1 < 10), f2 int CONSTRAINT t1_f2_ck CHECK(f2 < 10) NOT); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ')' at line 1 +CREATE TABLE t1(f1 int CHECK(f1 < 10), f2 int CHECK(f2 < 10) NOT); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ')' at line 1 +CREATE TABLE t1(f1 int CHECK(f1 < 10), f2 int CHECK(f2)); +ERROR HY000: An expression of non-boolean type specified to a check constraint 't1_chk_2'. +CREATE TABLE t1(f1 int CHECK(f1 < 10), f2 int CHECK(f2 + 10)); +ERROR HY000: An expression of non-boolean type specified to a check constraint 't1_chk_2'. +CREATE TABLE t1(f1 int CHECK(f1 < 10), f2 int CHECK(f3 < 10)); +ERROR HY000: Column check constraint 't1_chk_2' references other column. +CREATE TABLE t1 (f1 int CHECK(f1 < 10), f2 int CHECK(f2 < 10), +f3 int CONSTRAINT t1_f3_ck CHECK (f3 < 10)); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) DEFAULT NULL, + `f2` int(11) DEFAULT NULL, + `f3` int(11) DEFAULT NULL, + CONSTRAINT `t1_chk_1` CHECK ((`f1` < 10)), + CONSTRAINT `t1_chk_2` CHECK ((`f2` < 10)), + CONSTRAINT `t1_f3_ck` CHECK ((`f3` < 10)) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci +DROP TABLE t1; +#------------------------------------------------------------------------ +# Test cases to verify table check constraint syntax. +#------------------------------------------------------------------------ +CREATE TABLE t1(f1 int, CONSTRAINT t1_ck CHECK); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ')' at line 1 +CREATE TABLE t1(f1 int, CONSTRAINT t1_ck CHECK(); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ')' at line 1 +CREATE TABLE t1(f1 int, CONSTRAINT t1_ck CHECK()); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '))' at line 1 +CREATE TABLE t1(f1 int, CONSTRAINT t1_ck CHECK(f1)); +ERROR HY000: An expression of non-boolean type specified to a check constraint 't1_ck'. +CREATE TABLE t1(f1 int, CONSTRAINT t1_ck CHECK(f1 + 10)); +ERROR HY000: An expression of non-boolean type specified to a check constraint 't1_ck'. +CREATE TABLE t1(f1 int, CONSTRAINT t1_ck CHECK(f2 < 10)); +ERROR HY000: Check constraint 't1_ck' refers to non-existing column 'f2'. +CREATE TABLE t1(f1 int, CONSTRAINT t1_ck CHECK(f1 < 10)); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) DEFAULT NULL, + CONSTRAINT `t1_ck` CHECK ((`f1` < 10)) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci +DROP TABLE t1; +CREATE TABLE t1(f1 int, CONSTRAINT t1_ck CHECK(f1<10), CONSTRAINT t2_ck CHECK); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ')' at line 1 +CREATE TABLE t1(f1 int, CONSTRAINT t1_ck CHECK(f1<10), CONSTRAINT t2_ck CHECK(); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ')' at line 1 +CREATE TABLE t1(f1 int, CONSTRAINT t1_ck CHECK(f1<10), CONSTRAINT t2_ck CHECK(f2 > 0) NOT); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ')' at line 1 +CREATE TABLE t1(f1 int, CONSTRAINT t1_ck CHECK(f1<10), CONSTRAINT t2_ck CHECK(f1)); +ERROR HY000: An expression of non-boolean type specified to a check constraint 't2_ck'. +CREATE TABLE t1(f1 int, CONSTRAINT t1_ck CHECK(f1<10), CONSTRAINT t2_ck CHECK(f1 + 10)); +ERROR HY000: An expression of non-boolean type specified to a check constraint 't2_ck'. +CREATE TABLE t1(f1 int, CONSTRAINT t1_ck CHECK(f1<10), CONSTRAINT t2_ck CHECK(f2 > 1)); +ERROR HY000: Check constraint 't2_ck' refers to non-existing column 'f2'. +CREATE TABLE t1(f1 int, CHECK(f1<10), CONSTRAINT t2_ck CHECK(f1 > 1)); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) DEFAULT NULL, + CONSTRAINT `t1_chk_1` CHECK ((`f1` < 10)), + CONSTRAINT `t2_ck` CHECK ((`f1` > 1)) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci +DROP TABLE t1; +#----------------------------------------------------------------------- +# Test case to verify check constraint name with special charecters. +#----------------------------------------------------------------------- +CREATE TABLE t1(c1 INT, c2 INT, CONSTRAINT `ck_1$` CHECK (c2 < 10)); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c1` int(11) DEFAULT NULL, + `c2` int(11) DEFAULT NULL, + CONSTRAINT `ck_1$` CHECK ((`c2` < 10)) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci +DROP TABLE t1; +#----------------------------------------------------------------------- +# Test case to verify check constraint name with white spaces. +#----------------------------------------------------------------------- +CREATE TABLE t1(c1 INT, c2 INT, CONSTRAINT ` ck_2$ ` CHECK (c2 < 10)); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c1` int(11) DEFAULT NULL, + `c2` int(11) DEFAULT NULL, + CONSTRAINT ` ck_2$ ` CHECK ((`c2` < 10)) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci +ALTER TABLE t1 DROP CHECK ck_2$; +ERROR HY000: Check constraint 'ck_2$' is not found in the table. +ALTER TABLE t1 DROP CHECK ` ck_2$ `; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c1` int(11) DEFAULT NULL, + `c2` int(11) DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci +ALTER TABLE t1 ADD COLUMN c3 INTEGER , ADD CONSTRAINT ` c 3 ` CHECK ( c3 > 10 ); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c1` int(11) DEFAULT NULL, + `c2` int(11) DEFAULT NULL, + `c3` int(11) DEFAULT NULL, + CONSTRAINT ` c 3 ` CHECK ((`c3` > 10)) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci +DROP TABLE t1; +#----------------------------------------------------------------------- +# Test case to verify check constraint name with reserved words. +#----------------------------------------------------------------------- +CREATE TABLE t1(c1 INT, c2 INT, CONSTRAINT FLOAT CHECK (c2 < 10)); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'FLOAT CHECK (c2 < 10))' at line 1 +CREATE TABLE t1(c1 INT, c2 INT, CONSTRAINT `FLOAT` CHECK (c2 < 10)); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c1` int(11) DEFAULT NULL, + `c2` int(11) DEFAULT NULL, + CONSTRAINT `FLOAT` CHECK ((`c2` < 10)) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci +DROP TABLE t1; +#----------------------------------------------------------------------- +# Test case to verify check constraint with long name. +#----------------------------------------------------------------------- +CREATE TABLE t1(c1 INT, c2 INT, +CONSTRAINT ckkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk +CHECK (c2 < 10)); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c1` int(11) DEFAULT NULL, + `c2` int(11) DEFAULT NULL, + CONSTRAINT `ckkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk` CHECK ((`c2` < 10)) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci +CREATE TABLE t2(c1 INT, c2 INT, +CONSTRAINT ckkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk1 +CHECK (c2 < 10)); +ERROR 42000: Identifier name 'ckkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk1' is too long +DROP TABLE t1; +#----------------------------------------------------------------------- +# Test case to verify check constraint with too long generated name. +#----------------------------------------------------------------------- +CREATE TABLE t1 (f1 INT CHECK (f1 < 10)); +RENAME TABLE t1 TO t123456789012345678901234567890123456789012345678901234567890; +ERROR 42000: Identifier name 't123456789012345678901234567890123456789012345678901234567890_chk_1' is too long +DROP TABLE t1; +CREATE TABLE t123456789012345678901234567890123456789012345678901234567890(f1 INT CHECK(f1 < 10)); +ERROR 42000: Identifier name 't123456789012345678901234567890123456789012345678901234567890_chk_1' is too long +CREATE TABLE t123456789012345678901234567890123456789012345678901234567890(f1 INT); +ALTER TABLE t123456789012345678901234567890123456789012345678901234567890 ADD CONSTRAINT CHECK (f1 < 10); +ERROR 42000: Identifier name 't123456789012345678901234567890123456789012345678901234567890_chk_1' is too long +DROP TABLE t123456789012345678901234567890123456789012345678901234567890; +#----------------------------------------------------------------------- +# Test case to verify duplicate check constraint name under same +# database. Check constraints with same name are not allowed under +# same database. +#----------------------------------------------------------------------- +CREATE TABLE t(c1 INT CONSTRAINT t2_chk_1 CHECK (c1 > 10)); +CREATE TABLE t1(c1 INT CHECK (c1 > 10), CONSTRAINT ck CHECK(c1 > 10)); +CREATE TABLE t2(c1 INT, CONSTRAINT ck CHECK(c1 > 10)); +ERROR HY000: Duplicate check constraint name 'ck'. +ALTER TABLE t1 ADD CONSTRAINT ck CHECK(c1 > 10); +ERROR HY000: Duplicate check constraint name 'ck'. +ALTER TABLE t1 RENAME TO t2; +ERROR HY000: Duplicate check constraint name 't2_chk_1'. +ALTER TABLE t1 ADD c2 INT, RENAME TO t2; +ERROR HY000: Duplicate check constraint name 't2_chk_1'. +DROP TABLE t; +CREATE DATABASE db1; +CREATE TABLE db1.t(c1 INT CONSTRAINT t2_chk_1 CHECK (c1 > 10)); +ALTER TABLE t1 ADD c2 INT, RENAME TO db1.t2; +ERROR HY000: Duplicate check constraint name 't2_chk_1'. +ALTER TABLE t1 RENAME TO db1.t2; +ERROR HY000: Duplicate check constraint name 't2_chk_1'. +DROP DATABASE db1; +DROP TABLE t1; +#----------------------------------------------------------------------- +# Check constraint names are case insenitive and accent sensitive. Test +# case to verify the same. +#----------------------------------------------------------------------- +CREATE TABLE t1 (f1 INT, +CONSTRAINT cafe CHECK (f1 < 10), +CONSTRAINT CAFE CHECK (f1 < 10)); +ERROR HY000: Duplicate check constraint name 'CAFE'. +create table t1 (f1 int, +CONSTRAINT cafe CHECK (f1 < 10), +CONSTRAINT café CHECK (f1 < 10)); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) DEFAULT NULL, + CONSTRAINT `cafe` CHECK ((`f1` < 10)), + CONSTRAINT `café` CHECK ((`f1` < 10)) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci +DROP TABLE t1; +#------------------------------------------------------------------------ +# Test cases to verify forward reference of columns in the constraint. +#------------------------------------------------------------------------ +CREATE TABLE t1(CHECK((f1 + f3) > 10), f1 int CHECK (f1 < 10), f2 int); +ERROR HY000: Check constraint 't1_chk_1' refers to non-existing column 'f3'. +CREATE TABLE t1(CHECK((f1 + f2) > 10), f1 int CHECK (f1 < 10), f2 int); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) DEFAULT NULL, + `f2` int(11) DEFAULT NULL, + CONSTRAINT `t1_chk_1` CHECK (((`f1` + `f2`) > 10)), + CONSTRAINT `t1_chk_2` CHECK ((`f1` < 10)) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci +SELECT * FROM INFORMATION_SCHEMA.CHECK_CONSTRAINTS; +CONSTRAINT_CATALOG CONSTRAINT_SCHEMA CONSTRAINT_NAME CHECK_CLAUSE +def test t1_chk_1 ((`f1` + `f2`) > 10) +def test t1_chk_2 (`f1` < 10) +DROP TABLE t1; +#----------------------------------------------------------------------- +# Test case to verify creation of multiple check constraint on table. +#----------------------------------------------------------------------- +CREATE TABLE t1(c1 INT, c2 INT, c3 INT, c4 INT); +ALTER TABLE t1 ADD CONSTRAINT ck11 CHECK(c1 > 1), +ADD CONSTRAINT ck12 CHECK(c1 < 1), +ADD CONSTRAINT ck21 CHECK(c2 > 1), +ADD CONSTRAINT ck22 CHECK(c2 < 1), +ADD CONSTRAINT ck31 CHECK(c3 > 1), +ADD CONSTRAINT ck32 CHECK(c3 < 1), +ADD CONSTRAINT ck41 CHECK(c4 > 1), +ADD CONSTRAINT ck42 CHECK(c4 < 1); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c1` int(11) DEFAULT NULL, + `c2` int(11) DEFAULT NULL, + `c3` int(11) DEFAULT NULL, + `c4` int(11) DEFAULT NULL, + CONSTRAINT `ck11` CHECK ((`c1` > 1)), + CONSTRAINT `ck12` CHECK ((`c1` < 1)), + CONSTRAINT `ck21` CHECK ((`c2` > 1)), + CONSTRAINT `ck22` CHECK ((`c2` < 1)), + CONSTRAINT `ck31` CHECK ((`c3` > 1)), + CONSTRAINT `ck32` CHECK ((`c3` < 1)), + CONSTRAINT `ck41` CHECK ((`c4` > 1)), + CONSTRAINT `ck42` CHECK ((`c4` < 1)) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci +DROP TABLE t1; +#----------------------------------------------------------------------- +# Test case to verify check constraints with generated columns +#----------------------------------------------------------------------- +CREATE TABLE t1(c1 INT, +c2 INT, +c3 INT GENERATED ALWAYS AS (c1 + c2), +CONSTRAINT ck CHECK (c3 > 10) +); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c1` int(11) DEFAULT NULL, + `c2` int(11) DEFAULT NULL, + `c3` int(11) GENERATED ALWAYS AS ((`c1` + `c2`)) VIRTUAL, + CONSTRAINT `ck` CHECK ((`c3` > 10)) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci +INSERT INTO t1(c1,c2) VALUES(1,1); +ERROR HY000: Check constraint 'ck' is violated. +INSERT INTO t1(c1,c2) VALUES(10,10); +DROP TABLE t1; +#------------------------------------------------------------------------ +# Test case to verify check constraints with DEFAULT column value. +#------------------------------------------------------------------------ +CREATE TABLE t1(c1 INT DEFAULT 100 CHECK(c1 > 10)); +INSERT INTO t1() VALUES(1); +ERROR HY000: Check constraint 't1_chk_1' is violated. +INSERT INTO t1() VALUES(); +DROP TABLE t1; +CREATE TABLE t1(c1 int DEFAULT 1, CONSTRAINT CHECK(c1 IS NOT NULL)); +INSERT INTO t1() VALUES(); +INSERT INTO t1() VALUES(NULL); +ERROR HY000: Check constraint 't1_chk_1' is violated. +DROP TABLE t1; +#----------------------------------------------------------------------- +# Test case to verify check constraint behaviour with ascii charset +#----------------------------------------------------------------------- +CREATE TABLE t1(c1 VARCHAR(1) CHARSET ASCII CHECK(c1 = 'a'), +c2 VARCHAR(1) CHARSET ASCII DEFAULT('b')); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c1` varchar(1) CHARACTER SET ascii COLLATE ascii_general_ci DEFAULT NULL, + `c2` varchar(1) CHARACTER SET ascii COLLATE ascii_general_ci DEFAULT (_utf8mb4'b'), + CONSTRAINT `t1_chk_1` CHECK ((`c1` = _utf8mb4'a')) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci +INSERT INTO t1(c1) VALUES('b'); +ERROR HY000: Check constraint 't1_chk_1' is violated. +INSERT INTO t1(c1) VALUES('a'); +DROP TABLE t1; +#----------------------------------------------------------------------- +# Test case to verify check constraint with an expression evaluated to +# FALSE always. +#----------------------------------------------------------------------- +CREATE TABLE t1 (CHECK (1 < 1), f1 int); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) DEFAULT NULL, + CONSTRAINT `t1_chk_1` CHECK ((1 < 1)) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci +INSERT INTO t1 VALUES(1); +ERROR HY000: Check constraint 't1_chk_1' is violated. +INSERT INTO t1 VALUES(10); +ERROR HY000: Check constraint 't1_chk_1' is violated. +INSERT INTO t1 VALUES(); +ERROR HY000: Check constraint 't1_chk_1' is violated. +DROP TABLE t1; +#------------------------------------------------------------------------ +# Test case to verify INFORMATION_SCHEMA.CHECK_CONSTRAINTS and +# INFORMATION_SCHEMA.TABLE_CONSTRAINTS result set. +#------------------------------------------------------------------------ +CREATE TABLE t1(f1 INT PRIMARY KEY, f2 INT CHECK (f2 < 10), +CONSTRAINT t2_cc1 CHECK (f1 + SQRT(f2) > 6174)); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) NOT NULL, + `f2` int(11) DEFAULT NULL, + PRIMARY KEY (`f1`), + CONSTRAINT `t1_chk_1` CHECK ((`f2` < 10)), + CONSTRAINT `t2_cc1` CHECK (((`f1` + sqrt(`f2`)) > 6174)) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci +SELECT * FROM INFORMATION_SCHEMA.CHECK_CONSTRAINTS; +CONSTRAINT_CATALOG CONSTRAINT_SCHEMA CONSTRAINT_NAME CHECK_CLAUSE +def test t1_chk_1 (`f2` < 10) +def test t2_cc1 ((`f1` + sqrt(`f2`)) > 6174) +SELECT * FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE TABLE_NAME='t1'; +CONSTRAINT_CATALOG CONSTRAINT_SCHEMA CONSTRAINT_NAME TABLE_SCHEMA TABLE_NAME CONSTRAINT_TYPE ENFORCED +def test PRIMARY test t1 PRIMARY KEY YES +def test t1_chk_1 test t1 CHECK YES +def test t2_cc1 test t1 CHECK YES +DROP TABLE t1; +#------------------------------------------------------------------------ +# Test cases to verify check constraints in temporary table. +#------------------------------------------------------------------------ +CREATE TEMPORARY TABLE tmp_t1(CHECK((f1 + f2) > 10), f1 int CHECK (f1 < 12), +f2 int); +SHOW CREATE TABLE tmp_t1; +Table Create Table +tmp_t1 CREATE TEMPORARY TABLE `tmp_t1` ( + `f1` int(11) DEFAULT NULL, + `f2` int(11) DEFAULT NULL, + CONSTRAINT `tmp_t1_chk_1` CHECK (((`f1` + `f2`) > 10)), + CONSTRAINT `tmp_t1_chk_2` CHECK ((`f1` < 12)) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci +SELECT * FROM INFORMATION_SCHEMA.CHECK_CONSTRAINTS; +CONSTRAINT_CATALOG CONSTRAINT_SCHEMA CONSTRAINT_NAME CHECK_CLAUSE +DROP TABLE tmp_t1; +#------------------------------------------------------------------------ +# Test cases to verify check constraints with CREATE TABLE LIKE +#------------------------------------------------------------------------ +CREATE TABLE t1(f1 INT CHECK (f1 < 10), f2 INT, CHECK (f2 < 10), +CONSTRAINT min CHECK (f1 + f2 > 10), +CONSTRAINT max CHECK (f1 + f2 < 929)); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) DEFAULT NULL, + `f2` int(11) DEFAULT NULL, + CONSTRAINT `max` CHECK (((`f1` + `f2`) < 929)), + CONSTRAINT `min` CHECK (((`f1` + `f2`) > 10)), + CONSTRAINT `t1_chk_1` CHECK ((`f1` < 10)), + CONSTRAINT `t1_chk_2` CHECK ((`f2` < 10)) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci +CREATE TABLE t2 LIKE t1; +SHOW CREATE TABLE t2; +Table Create Table +t2 CREATE TABLE `t2` ( + `f1` int(11) DEFAULT NULL, + `f2` int(11) DEFAULT NULL, + CONSTRAINT `t2_chk_1` CHECK (((`f1` + `f2`) < 929)), + CONSTRAINT `t2_chk_2` CHECK (((`f1` + `f2`) > 10)), + CONSTRAINT `t2_chk_3` CHECK ((`f1` < 10)), + CONSTRAINT `t2_chk_4` CHECK ((`f2` < 10)) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci +CREATE TEMPORARY TABLE tmp_t2 LIKE t2; +SHOW CREATE TABLE tmp_t2; +Table Create Table +tmp_t2 CREATE TEMPORARY TABLE `tmp_t2` ( + `f1` int(11) DEFAULT NULL, + `f2` int(11) DEFAULT NULL, + CONSTRAINT `tmp_t2_chk_1` CHECK (((`f1` + `f2`) < 929)), + CONSTRAINT `tmp_t2_chk_2` CHECK (((`f1` + `f2`) > 10)), + CONSTRAINT `tmp_t2_chk_3` CHECK ((`f1` < 10)), + CONSTRAINT `tmp_t2_chk_4` CHECK ((`f2` < 10)) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci +CREATE TABLE t3 LIKE tmp_t2; +SHOW CREATE TABLE t3; +Table Create Table +t3 CREATE TABLE `t3` ( + `f1` int(11) DEFAULT NULL, + `f2` int(11) DEFAULT NULL, + CONSTRAINT `t3_chk_1` CHECK (((`f1` + `f2`) < 929)), + CONSTRAINT `t3_chk_2` CHECK (((`f1` + `f2`) > 10)), + CONSTRAINT `t3_chk_3` CHECK ((`f1` < 10)), + CONSTRAINT `t3_chk_4` CHECK ((`f2` < 10)) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci +DROP TABLE t1, t2, t3, tmp_t2; +#------------------------------------------------------------------------ +# Test cases to verify effect of check constraint in DML operations. +#------------------------------------------------------------------------ +CREATE TABLE t1(f1 INT PRIMARY KEY, f2 INT CHECK (f2 < 10)); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) NOT NULL, + `f2` int(11) DEFAULT NULL, + PRIMARY KEY (`f1`), + CONSTRAINT `t1_chk_1` CHECK ((`f2` < 10)) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci +CREATE TABLE t2(f1 INT, f2 INT); +INSERT INTO t2 VALUES(101, 1); +INSERT INTO t2 VALUES(102, NULL); +INSERT INTO t2 VALUES(103, 1000); +# INSERT operations. +INSERT INTO t1 VALUES(1, 1); +INSERT INTO t1 VALUES(2, NULL); +INSERT INTO t1 VALUES(3, 1000); +ERROR HY000: Check constraint 't1_chk_1' is violated. +INSERT IGNORE INTO t1 VALUES (3, 1000); +Warnings: +Warning 3820 Check constraint 't1_chk_1' is violated. +SELECT * FROM t1; +f1 f2 +1 1 +2 NULL +INSERT INTO t1 SELECT * FROM t2; +ERROR HY000: Check constraint 't1_chk_1' is violated. +SELECT * FROM t1; +f1 f2 +1 1 +2 NULL +INSERT IGNORE INTO t1 SELECT * FROM t2; +Warnings: +Warning 3820 Check constraint 't1_chk_1' is violated. +SELECT * FROM t1; +f1 f2 +1 1 +2 NULL +101 1 +102 NULL +# REPLACE operations. +REPLACE INTO t1 VALUES(4, 1); +REPLACE INTO t1 VALUES(5, NULL); +REPLACE INTO t1 VALUES(6, 100); +ERROR HY000: Check constraint 't1_chk_1' is violated. +REPLACE INTO t1 VALUES(2, 10); +ERROR HY000: Check constraint 't1_chk_1' is violated. +REPLACE INTO t1 VALUES(2, 2); +SELECT * FROM t1; +f1 f2 +1 1 +2 2 +4 1 +5 NULL +101 1 +102 NULL +# UPDATE operations. +UPDATE t1 SET f2 = 2; +SELECT * FROM t1; +f1 f2 +1 2 +2 2 +4 2 +5 2 +101 2 +102 2 +UPDATE t1 SET f2 = NULL; +UPDATE t1 SET f2 = 1000; +ERROR HY000: Check constraint 't1_chk_1' is violated. +UPDATE IGNORE t1 SET f2 = 1000; +Warnings: +Warning 3820 Check constraint 't1_chk_1' is violated. +Warning 3820 Check constraint 't1_chk_1' is violated. +Warning 3820 Check constraint 't1_chk_1' is violated. +Warning 3820 Check constraint 't1_chk_1' is violated. +Warning 3820 Check constraint 't1_chk_1' is violated. +Warning 3820 Check constraint 't1_chk_1' is violated. +SELECT * FROM t1; +f1 f2 +1 NULL +2 NULL +4 NULL +5 NULL +101 NULL +102 NULL +DROP TABLE t1, t2; +# LOAD DATA operations. +CREATE TABLE t2(f1 INT,f2 INT); +INSERT INTO t2 VALUES(1,1); +INSERT INTO t2 VALUES(2,NULL); +CREATE TABLE t1(f1 INT PRIMARY KEY, f2 INT CHECK (f2 < 10)); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) NOT NULL, + `f2` int(11) DEFAULT NULL, + PRIMARY KEY (`f1`), + CONSTRAINT `t1_chk_1` CHECK ((`f2` < 10)) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci +SELECT * FROM t2; +f1 f2 +1 1 +2 NULL +SELECT * FROM t2 INTO OUTFILE 'tmp1.txt'; +LOAD DATA INFILE 'tmp1.txt' INTO TABLE t1; +SELECT * FROM t1; +f1 f2 +1 1 +2 NULL +DELETE FROM t1; +INSERT INTO t2 VALUES(3,20); +SELECT * FROM t2; +f1 f2 +1 1 +2 NULL +3 20 +SELECT * FROM t2 INTO OUTFILE 'tmp2.txt'; +LOAD DATA INFILE 'tmp2.txt' INTO TABLE t1; +ERROR HY000: Check constraint 't1_chk_1' is violated. +SELECT * FROM t1; +f1 f2 +LOAD DATA INFILE 'tmp2.txt' IGNORE INTO TABLE t1; +Warnings: +Warning 3820 Check constraint 't1_chk_1' is violated. +SELECT * FROM t1; +f1 f2 +1 1 +2 NULL +DROP TABLE t1,t2; +CREATE TABLE t1 (a INT CHECK(a < 3), b CHAR(10)) CHARSET latin1; +LOAD DATA INFILE '../../std_data/loaddata3.dat' IGNORE INTO TABLE t1 +FIELDS TERMINATED BY '' ENCLOSED BY '' IGNORE 1 LINES; +Warnings: +Warning 1366 Incorrect integer value: 'error ' for column 'a' at row 3 +Warning 1262 Row 3 was truncated; it contained more data than there were input columns +Warning 3820 Check constraint 't1_chk_1' is violated. +Warning 1261 Row 4 doesn't contain data for all columns +Warning 1261 Row 4 doesn't contain data for all columns +Warning 1366 Incorrect integer value: 'wrong end ' for column 'a' at row 5 +Warning 1262 Row 5 was truncated; it contained more data than there were input columns +DROP TABLE t1; +# LOAD XML operations. +CREATE TABLE t2(f1 INT,f2 INT); +INSERT INTO t2 VALUES(1,1); +INSERT INTO t2 VALUES(2,NULL); +CREATE TABLE t1(f1 INT PRIMARY KEY, f2 INT CHECK (f2 < 10)); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) NOT NULL, + `f2` int(11) DEFAULT NULL, + PRIMARY KEY (`f1`), + CONSTRAINT `t1_chk_1` CHECK ((`f2` < 10)) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci +SELECT * FROM t2; +f1 f2 +1 1 +2 NULL +LOAD XML INFILE "MYSQLTEST_VARDIR/tmp/tmp1.xml" INTO TABLE t1;; +SELECT * FROM t1; +f1 f2 +1 1 +2 NULL +DELETE FROM t1; +INSERT INTO t2 VALUES(3,20); +SELECT * FROM t2; +f1 f2 +1 1 +2 NULL +3 20 +LOAD XML INFILE "MYSQLTEST_VARDIR/tmp/tmp2.xml" INTO TABLE t1;; +ERROR HY000: Check constraint 't1_chk_1' is violated. +SELECT * FROM t1; +f1 f2 +LOAD XML INFILE "MYSQLTEST_VARDIR/tmp/tmp2.xml" IGNORE INTO TABLE t1;; +Warnings: +Warning 3820 Check constraint 't1_chk_1' is violated. +SELECT * FROM t1; +f1 f2 +1 1 +2 NULL +DROP TABLE t1,t2; +#----------------------------------------------------------------------- +# Test case to verify check constraint with INSERT ON DUPLICATE +#----------------------------------------------------------------------- +CREATE TABLE t1(f1 INT PRIMARY KEY, f2 INT CHECK (f2 < 10)); +INSERT INTO t1 VALUES (1, 1); +INSERT INTO t1 VALUES (1, 2) ON DUPLICATE KEY UPDATE f2 = 4; +SELECT * FROM t1; +f1 f2 +1 4 +INSERT IGNORE INTO t1 VALUES (1, 1) ON DUPLICATE KEY UPDATE f2 = 20; +Warnings: +Warning 3820 Check constraint 't1_chk_1' is violated. +INSERT INTO t1 VALUES (1, 1) ON DUPLICATE KEY UPDATE f2 = 20; +ERROR HY000: Check constraint 't1_chk_1' is violated. +DROP TABLE t1; +#----------------------------------------------------------------------- +# Test case to verify check constraints with multi-table update. +#----------------------------------------------------------------------- +CREATE TABLE t1(f1 INT, f2 INT CHECK(f2 < 20)); +INSERT INTO t1 VALUES (4, 4); +CREATE TABLE t2(f1 INT, f2 INT); +INSERT INTO t2 VALUES (4, 24); +UPDATE t1,t2 SET t1.f2 = t1.f2 + 20 WHERE t1.f1 = t2.f1; +ERROR HY000: Check constraint 't1_chk_1' is violated. +UPDATE IGNORE t1,t2 SET t1.f2 = t1.f2 + 20 WHERE t1.f1 = t2.f1; +Warnings: +Warning 3820 Check constraint 't1_chk_1' is violated. +DROP TABLE t1, t2; +CREATE TABLE t1 ( +`f1` int(10) unsigned NOT NULL auto_increment, +`f2` int(11) NOT NULL default '0', +PRIMARY KEY (`f1`) +); +INSERT INTO t1 VALUES (4433,5424); +CREATE TABLE t2 ( +`f3` int(10) unsigned NOT NULL default '0', +`f4` int(10) unsigned NOT NULL default '0' CHECK (f4 <= 500), +PRIMARY KEY (`f3`,`f4`) +); +INSERT INTO t2 VALUES (495,500); +INSERT INTO t2 VALUES (496,500); +UPDATE t2,t1 set t2.f4 = t2.f4 + 1; +ERROR HY000: Check constraint 't2_chk_1' is violated. +UPDATE IGNORE t2,t1 set t2.f4 = t2.f4 + 1; +Warnings: +Warning 3820 Check constraint 't2_chk_1' is violated. +Warning 3820 Check constraint 't2_chk_1' is violated. +DROP TABLE t1, t2; +#------------------------------------------------------------------------ +# Test cases to verify generated check constraint name updates due to +# RENAME TABLE operation. +#------------------------------------------------------------------------ +CREATE TABLE t1 (f1 INT CHECK(f1 < 10)); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) DEFAULT NULL, + CONSTRAINT `t1_chk_1` CHECK ((`f1` < 10)) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci +RENAME TABLE t1 TO t2; +SHOW CREATE TABLE t2; +Table Create Table +t2 CREATE TABLE `t2` ( + `f1` int(11) DEFAULT NULL, + CONSTRAINT `t2_chk_1` CHECK ((`f1` < 10)) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci +CREATE TABLE t1(f1 INT CHECK (f1>10), f11 INT CHECK (f11 < 1000)); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) DEFAULT NULL, + `f11` int(11) DEFAULT NULL, + CONSTRAINT `t1_chk_1` CHECK ((`f1` > 10)), + CONSTRAINT `t1_chk_2` CHECK ((`f11` < 1000)) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci +RENAME TABLE t1 TO t3, t2 TO t1, t3 TO t2; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) DEFAULT NULL, + CONSTRAINT `t1_chk_1` CHECK ((`f1` < 10)) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci +SHOW CREATE TABLE t2; +Table Create Table +t2 CREATE TABLE `t2` ( + `f1` int(11) DEFAULT NULL, + `f11` int(11) DEFAULT NULL, + CONSTRAINT `t2_chk_1` CHECK ((`f1` > 10)), + CONSTRAINT `t2_chk_2` CHECK ((`f11` < 1000)) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci +DROP TABLE t1, t2; +#------------------------------------------------------------------------ +# Test case to verify check constraints removal on DROP table operation. +#------------------------------------------------------------------------ +CREATE TABLE t1(f1 INT PRIMARY KEY, f2 INT CHECK (f2 < 10)); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) NOT NULL, + `f2` int(11) DEFAULT NULL, + PRIMARY KEY (`f1`), + CONSTRAINT `t1_chk_1` CHECK ((`f2` < 10)) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci +SELECT * FROM INFORMATION_SCHEMA.CHECK_CONSTRAINTS; +CONSTRAINT_CATALOG CONSTRAINT_SCHEMA CONSTRAINT_NAME CHECK_CLAUSE +def test t1_chk_1 (`f2` < 10) +SELECT * FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE TABLE_NAME='t1'; +CONSTRAINT_CATALOG CONSTRAINT_SCHEMA CONSTRAINT_NAME TABLE_SCHEMA TABLE_NAME CONSTRAINT_TYPE ENFORCED +def test PRIMARY test t1 PRIMARY KEY YES +def test t1_chk_1 test t1 CHECK YES +DROP TABLE t1; +#------------------------------------------------------------------------ +# Test case to verify check constraints creation with ALTER TABLE ADD +# CONSTRAINT operation. +#------------------------------------------------------------------------ +CREATE TABLE t1 (f1 INT CHECK (f1 < 10)); +CREATE TEMPORARY TABLE t3(f1 INT CHECK (f1 < 10)); +ALTER TABLE t1 ADD CONSTRAINT CHECK (f1 > 1), ADD CONSTRAINT `t1_p_ck` CHECK (f1 > 1); +ALTER TABLE t3 ADD CONSTRAINT CHECK (f1 > 1), ADD CONSTRAINT `t3_p_ck` CHECK (f1 > 1); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) DEFAULT NULL, + CONSTRAINT `t1_chk_1` CHECK ((`f1` < 10)), + CONSTRAINT `t1_chk_2` CHECK ((`f1` > 1)), + CONSTRAINT `t1_p_ck` CHECK ((`f1` > 1)) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci +SHOW CREATE TABLE t3; +Table Create Table +t3 CREATE TEMPORARY TABLE `t3` ( + `f1` int(11) DEFAULT NULL, + CONSTRAINT `t3_chk_1` CHECK ((`f1` < 10)), + CONSTRAINT `t3_chk_2` CHECK ((`f1` > 1)), + CONSTRAINT `t3_p_ck` CHECK ((`f1` > 1)) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci +# Test case to verify check constraint creation with ALTER TABLE ADD +# constraint and generated name updates with RENAME TO in +# ALTER operation. +ALTER TABLE t1 ADD f2 INT CHECK (f2 < 10), RENAME TO t6, ALGORITHM=COPY; +SHOW CREATE TABLE t6; +Table Create Table +t6 CREATE TABLE `t6` ( + `f1` int(11) DEFAULT NULL, + `f2` int(11) DEFAULT NULL, + CONSTRAINT `t1_p_ck` CHECK ((`f1` > 1)), + CONSTRAINT `t6_chk_1` CHECK ((`f1` < 10)), + CONSTRAINT `t6_chk_2` CHECK ((`f1` > 1)), + CONSTRAINT `t6_chk_3` CHECK ((`f2` < 10)) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci +ALTER TABLE t3 ADD f2 INT CHECK (f2 < 10), RENAME TO t7, ALGORITHM=COPY; +SHOW CREATE TABLE t7; +Table Create Table +t7 CREATE TEMPORARY TABLE `t7` ( + `f1` int(11) DEFAULT NULL, + `f2` int(11) DEFAULT NULL, + CONSTRAINT `t7_chk_1` CHECK ((`f1` < 10)), + CONSTRAINT `t7_chk_2` CHECK ((`f1` > 1)), + CONSTRAINT `t3_p_ck` CHECK ((`f1` > 1)), + CONSTRAINT `t7_chk_3` CHECK ((`f2` < 10)) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci +ALTER TABLE t6 RENAME TO t1; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) DEFAULT NULL, + `f2` int(11) DEFAULT NULL, + CONSTRAINT `t1_chk_1` CHECK ((`f1` < 10)), + CONSTRAINT `t1_chk_2` CHECK ((`f1` > 1)), + CONSTRAINT `t1_chk_3` CHECK ((`f2` < 10)), + CONSTRAINT `t1_p_ck` CHECK ((`f1` > 1)) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci +ALTER TABLE t7 RENAME TO t3; +SHOW CREATE TABLE t3; +Table Create Table +t3 CREATE TEMPORARY TABLE `t3` ( + `f1` int(11) DEFAULT NULL, + `f2` int(11) DEFAULT NULL, + CONSTRAINT `t3_chk_1` CHECK ((`f1` < 10)), + CONSTRAINT `t3_chk_2` CHECK ((`f1` > 1)), + CONSTRAINT `t3_p_ck` CHECK ((`f1` > 1)), + CONSTRAINT `t3_chk_3` CHECK ((`f2` < 10)) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci +# Test case to verify add check constraint with INPLACE alter algorithm. +ALTER TABLE t1 ADD f2 INT CHECK (f2 < 10), ALGORITHM=INPLACE; +ERROR 0A000: ALGORITHM=INPLACE is not supported for this operation. Try ALGORITHM=COPY. +ALTER TABLE t3 ADD f2 INT CHECK (f2 < 10), ALGORITHM=INPLACE; +ERROR 0A000: ALGORITHM=INPLACE is not supported for this operation. Try ALGORITHM=COPY. +ALTER TABLE t1 ADD f3 INT CHECK (f3 < 10) NOT ENFORCED, ALGORITHM=INPLACE; +ALTER TABLE t1 ADD CONSTRAINT CHECK (f2 < 10) NOT ENFORCED, ALGORITHM=INPLACE; +ALTER TABLE t1 RENAME COLUMN f1 TO f10; +ERROR 42S22: Unknown column 'f1' in 'check constraint t1_chk_1 expression' +#------------------------------------------------------------------------ +# Test case to verify check constraints creation with ALTER TABLE DROP +# CONSTRAINT operation. +#------------------------------------------------------------------------ +SHOW CREATE TABLE t3; +Table Create Table +t3 CREATE TEMPORARY TABLE `t3` ( + `f1` int(11) DEFAULT NULL, + `f2` int(11) DEFAULT NULL, + CONSTRAINT `t3_chk_1` CHECK ((`f1` < 10)), + CONSTRAINT `t3_chk_2` CHECK ((`f1` > 1)), + CONSTRAINT `t3_p_ck` CHECK ((`f1` > 1)), + CONSTRAINT `t3_chk_3` CHECK ((`f2` < 10)) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci +ALTER TABLE t3 DROP CHECK t3_chk_3; +SHOW CREATE TABLE t3; +Table Create Table +t3 CREATE TEMPORARY TABLE `t3` ( + `f1` int(11) DEFAULT NULL, + `f2` int(11) DEFAULT NULL, + CONSTRAINT `t3_chk_1` CHECK ((`f1` < 10)), + CONSTRAINT `t3_chk_2` CHECK ((`f1` > 1)), + CONSTRAINT `t3_p_ck` CHECK ((`f1` > 1)) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci +ALTER TABLE t3 DROP CHECK t3_p_ck, ADD CONSTRAINT t3_p_ck CHECK (f1 > 38); +SHOW CREATE TABLE t3; +Table Create Table +t3 CREATE TEMPORARY TABLE `t3` ( + `f1` int(11) DEFAULT NULL, + `f2` int(11) DEFAULT NULL, + CONSTRAINT `t3_chk_1` CHECK ((`f1` < 10)), + CONSTRAINT `t3_chk_2` CHECK ((`f1` > 1)), + CONSTRAINT `t3_p_ck` CHECK ((`f1` > 38)) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci +#------------------------------------------------------------------------ +# Test case to verify check constraints alter operations. +#------------------------------------------------------------------------ +INSERT INTO t1 VALUES (5, 5, 5); +ALTER TABLE t1 ALTER CHECK t1_chk_1 NOT ENFORCED, ALGORITHM=INPLACE; +INSERT INTO t1 VALUES (8, 8, 8); +ALTER TABLE t1 ALTER CHECK t1_chk_1 ENFORCED, ALGORITHM=INPLACE; +ERROR 0A000: ALGORITHM=INPLACE is not supported for this operation. Try ALGORITHM=COPY. +ALTER TABLE t1 ALTER CHECK t1_chk_1 ENFORCED, ALGORITHM=COPY; +ALTER TABLE t1 ALTER CHECK t1_chk_1 ENFORCED, ALGORITHM=INPLACE; +INSERT INTO t1 VALUES (12, 5, 5); +ERROR HY000: Check constraint 't1_chk_1' is violated. +ALTER TABLE t1 ALTER CHECK t1_chk_1 NOT ENFORCED, ALGORITHM=INPLACE; +INSERT INTO t1 VALUES (12, 5, 5); +ALTER TABLE t1 ALTER CHECK t1_chk_1 ENFORCED, ALGORITHM=COPY; +ERROR HY000: Check constraint 't1_chk_1' is violated. +DROP TABLE t1, t3; +#----------------------------------------------------------------------- +# Test case to add check constraint with copy,instant,inplace algorithm +#----------------------------------------------------------------------- +CREATE TABLE t1(c1 INT); +ALTER TABLE t1 ADD CONSTRAINT CHECK (C1 > 10), ALGORITHM=COPY; +ALTER TABLE t1 ADD CONSTRAINT CHECK (C1 > 10), ALGORITHM=INPLACE; +ERROR 0A000: ALGORITHM=INPLACE is not supported for this operation. Try ALGORITHM=COPY. +ALTER TABLE t1 ADD CONSTRAINT CHECK (C1 > 10), ALGORITHM=INSTANT; +ERROR 0A000: ALGORITHM=INSTANT is not supported for this operation. Try ALGORITHM=COPY. +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c1` int(11) DEFAULT NULL, + CONSTRAINT `t1_chk_1` CHECK ((`C1` > 10)) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci +DROP TABLE t1; +#----------------------------------------------------------------------- +# Test case to verify drop check constraint with inplace algorithm. +#----------------------------------------------------------------------- +CREATE TABLE t1 (f1 INT CHECK (f1 < 10)); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) DEFAULT NULL, + CONSTRAINT `t1_chk_1` CHECK ((`f1` < 10)) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci +ALTER TABLE t1 DROP CHECK t1_chk_1, ALGORITHM=INPLACE; +ALTER TABLE t1 ADD CONSTRAINT t1_chk_1 CHECK (f1 < 10), DROP CHECK t1_chk_1, ALGORITHM=INPLACE; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci +DROP TABLE t1; +#----------------------------------------------------------------------- +# Test case to alter table to add/drop column with the check constraint. +#----------------------------------------------------------------------- +CREATE TABLE t1 (c1 INT, CONSTRAINT ck1 CHECK (c1 > 10)); +ALTER TABLE t1 ADD COLUMN c2 INT, +ADD CONSTRAINT ck2 CHECK (c2 > 10); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c1` int(11) DEFAULT NULL, + `c2` int(11) DEFAULT NULL, + CONSTRAINT `ck1` CHECK ((`c1` > 10)), + CONSTRAINT `ck2` CHECK ((`c2` > 10)) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci +INSERT INTO t1 VALUES(20,10); +ERROR HY000: Check constraint 'ck2' is violated. +ALTER TABLE t1 DROP CHECK ck2, DROP COLUMN c2; +ALTER TABLE t1 ADD COLUMN c3 INT, +ADD CONSTRAINT ck3 CHECK (c3 < 10); +ALTER TABLE t1 DROP CHECK ck3, DROP COLUMN c3, +ADD COLUMN c4 INT, ADD CONSTRAINT ck4 CHECK( c4 > 10); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c1` int(11) DEFAULT NULL, + `c4` int(11) DEFAULT NULL, + CONSTRAINT `ck1` CHECK ((`c1` > 10)), + CONSTRAINT `ck4` CHECK ((`c4` > 10)) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci +DROP TABLE t1; +#----------------------------------------------------------------------- +# Test case to verify +# - Creation of check constraint with NOT ENFORCED state. +# - Listing state of the check constraints with SHOW and +# INFORMATION_SCHEMA.CHECK_CONSTRAINTS table. +# - State updates with ALTER TABLE statement to ALTER +# check constraints. +#----------------------------------------------------------------------- +CREATE TABLE t1(f1 INT, +f2 INT CHECK (f2 < 10), +f3 INT CHECK (f3 < 10) NOT ENFORCED, +CONSTRAINT ck CHECK (f1 > 10), +CONSTRAINT CHECK (f1 > 10) NOT ENFORCED); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) DEFAULT NULL, + `f2` int(11) DEFAULT NULL, + `f3` int(11) DEFAULT NULL, + CONSTRAINT `ck` CHECK ((`f1` > 10)), + CONSTRAINT `t1_chk_1` CHECK ((`f2` < 10)), + CONSTRAINT `t1_chk_2` CHECK ((`f3` < 10)) /*!80015 NOT ENFORCED */, + CONSTRAINT `t1_chk_3` CHECK ((`f1` > 10)) /*!80015 NOT ENFORCED */ +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci +SELECT * FROM INFORMATION_SCHEMA.CHECK_CONSTRAINTS; +CONSTRAINT_CATALOG CONSTRAINT_SCHEMA CONSTRAINT_NAME CHECK_CLAUSE +def test t1_chk_1 (`f2` < 10) +def test t1_chk_2 (`f3` < 10) +def test ck (`f1` > 10) +def test t1_chk_3 (`f1` > 10) +# REVOKE check constraint ck. +ALTER TABLE t1 ALTER CHECK ck NOT ENFORCED; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) DEFAULT NULL, + `f2` int(11) DEFAULT NULL, + `f3` int(11) DEFAULT NULL, + CONSTRAINT `ck` CHECK ((`f1` > 10)) /*!80015 NOT ENFORCED */, + CONSTRAINT `t1_chk_1` CHECK ((`f2` < 10)), + CONSTRAINT `t1_chk_2` CHECK ((`f3` < 10)) /*!80015 NOT ENFORCED */, + CONSTRAINT `t1_chk_3` CHECK ((`f1` > 10)) /*!80015 NOT ENFORCED */ +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci +SELECT * FROM INFORMATION_SCHEMA.CHECK_CONSTRAINTS; +CONSTRAINT_CATALOG CONSTRAINT_SCHEMA CONSTRAINT_NAME CHECK_CLAUSE +def test ck (`f1` > 10) +def test t1_chk_1 (`f2` < 10) +def test t1_chk_2 (`f3` < 10) +def test t1_chk_3 (`f1` > 10) +# ENFORCE check constraint ck. +ALTER TABLE t1 ALTER CHECK ck ENFORCED; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) DEFAULT NULL, + `f2` int(11) DEFAULT NULL, + `f3` int(11) DEFAULT NULL, + CONSTRAINT `ck` CHECK ((`f1` > 10)), + CONSTRAINT `t1_chk_1` CHECK ((`f2` < 10)), + CONSTRAINT `t1_chk_2` CHECK ((`f3` < 10)) /*!80015 NOT ENFORCED */, + CONSTRAINT `t1_chk_3` CHECK ((`f1` > 10)) /*!80015 NOT ENFORCED */ +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci +SELECT * FROM INFORMATION_SCHEMA.CHECK_CONSTRAINTS; +CONSTRAINT_CATALOG CONSTRAINT_SCHEMA CONSTRAINT_NAME CHECK_CLAUSE +def test ck (`f1` > 10) +def test t1_chk_1 (`f2` < 10) +def test t1_chk_2 (`f3` < 10) +def test t1_chk_3 (`f1` > 10) +# Add new constraint in NOT ENFORCED state. +ALTER TABLE t1 ADD CONSTRAINT ck1 CHECK(f1<10) NOT ENFORCED; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) DEFAULT NULL, + `f2` int(11) DEFAULT NULL, + `f3` int(11) DEFAULT NULL, + CONSTRAINT `ck` CHECK ((`f1` > 10)), + CONSTRAINT `ck1` CHECK ((`f1` < 10)) /*!80015 NOT ENFORCED */, + CONSTRAINT `t1_chk_1` CHECK ((`f2` < 10)), + CONSTRAINT `t1_chk_2` CHECK ((`f3` < 10)) /*!80015 NOT ENFORCED */, + CONSTRAINT `t1_chk_3` CHECK ((`f1` > 10)) /*!80015 NOT ENFORCED */ +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci +SELECT * FROM INFORMATION_SCHEMA.CHECK_CONSTRAINTS; +CONSTRAINT_CATALOG CONSTRAINT_SCHEMA CONSTRAINT_NAME CHECK_CLAUSE +def test ck (`f1` > 10) +def test t1_chk_1 (`f2` < 10) +def test t1_chk_2 (`f3` < 10) +def test t1_chk_3 (`f1` > 10) +def test ck1 (`f1` < 10) +# ENFORCE check constraint ck1 +ALTER TABLE t1 ALTER CHECK ck1 ENFORCED; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) DEFAULT NULL, + `f2` int(11) DEFAULT NULL, + `f3` int(11) DEFAULT NULL, + CONSTRAINT `ck` CHECK ((`f1` > 10)), + CONSTRAINT `ck1` CHECK ((`f1` < 10)), + CONSTRAINT `t1_chk_1` CHECK ((`f2` < 10)), + CONSTRAINT `t1_chk_2` CHECK ((`f3` < 10)) /*!80015 NOT ENFORCED */, + CONSTRAINT `t1_chk_3` CHECK ((`f1` > 10)) /*!80015 NOT ENFORCED */ +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci +SELECT * FROM INFORMATION_SCHEMA.CHECK_CONSTRAINTS; +CONSTRAINT_CATALOG CONSTRAINT_SCHEMA CONSTRAINT_NAME CHECK_CLAUSE +def test ck (`f1` > 10) +def test ck1 (`f1` < 10) +def test t1_chk_1 (`f2` < 10) +def test t1_chk_2 (`f3` < 10) +def test t1_chk_3 (`f1` > 10) +# ENFORCE check constraint t1_chk_2 +ALTER TABLE t1 ALTER CHECK t1_chk_2 ENFORCED; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) DEFAULT NULL, + `f2` int(11) DEFAULT NULL, + `f3` int(11) DEFAULT NULL, + CONSTRAINT `ck` CHECK ((`f1` > 10)), + CONSTRAINT `ck1` CHECK ((`f1` < 10)), + CONSTRAINT `t1_chk_1` CHECK ((`f2` < 10)), + CONSTRAINT `t1_chk_2` CHECK ((`f3` < 10)), + CONSTRAINT `t1_chk_3` CHECK ((`f1` > 10)) /*!80015 NOT ENFORCED */ +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci +SELECT * FROM INFORMATION_SCHEMA.CHECK_CONSTRAINTS; +CONSTRAINT_CATALOG CONSTRAINT_SCHEMA CONSTRAINT_NAME CHECK_CLAUSE +def test ck (`f1` > 10) +def test ck1 (`f1` < 10) +def test t1_chk_1 (`f2` < 10) +def test t1_chk_2 (`f3` < 10) +def test t1_chk_3 (`f1` > 10) +# ADD column check constraint in NOT ENFORCED state. +ALTER TABLE t1 ADD f4 INT CONSTRAINT t1_f4_chk CHECK (f4 < 10) NOT ENFORCED; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) DEFAULT NULL, + `f2` int(11) DEFAULT NULL, + `f3` int(11) DEFAULT NULL, + `f4` int(11) DEFAULT NULL, + CONSTRAINT `ck` CHECK ((`f1` > 10)), + CONSTRAINT `ck1` CHECK ((`f1` < 10)), + CONSTRAINT `t1_chk_1` CHECK ((`f2` < 10)), + CONSTRAINT `t1_chk_2` CHECK ((`f3` < 10)), + CONSTRAINT `t1_chk_3` CHECK ((`f1` > 10)) /*!80015 NOT ENFORCED */, + CONSTRAINT `t1_f4_chk` CHECK ((`f4` < 10)) /*!80015 NOT ENFORCED */ +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci +SELECT * FROM INFORMATION_SCHEMA.CHECK_CONSTRAINTS; +CONSTRAINT_CATALOG CONSTRAINT_SCHEMA CONSTRAINT_NAME CHECK_CLAUSE +def test ck (`f1` > 10) +def test ck1 (`f1` < 10) +def test t1_chk_1 (`f2` < 10) +def test t1_chk_2 (`f3` < 10) +def test t1_chk_3 (`f1` > 10) +def test t1_f4_chk (`f4` < 10) +# ENFORCE check constraint t1_f4_chk +ALTER TABLE t1 ALTER CHECK t1_f4_chk ENFORCED; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) DEFAULT NULL, + `f2` int(11) DEFAULT NULL, + `f3` int(11) DEFAULT NULL, + `f4` int(11) DEFAULT NULL, + CONSTRAINT `ck` CHECK ((`f1` > 10)), + CONSTRAINT `ck1` CHECK ((`f1` < 10)), + CONSTRAINT `t1_chk_1` CHECK ((`f2` < 10)), + CONSTRAINT `t1_chk_2` CHECK ((`f3` < 10)), + CONSTRAINT `t1_chk_3` CHECK ((`f1` > 10)) /*!80015 NOT ENFORCED */, + CONSTRAINT `t1_f4_chk` CHECK ((`f4` < 10)) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci +SELECT * FROM INFORMATION_SCHEMA.CHECK_CONSTRAINTS; +CONSTRAINT_CATALOG CONSTRAINT_SCHEMA CONSTRAINT_NAME CHECK_CLAUSE +def test ck (`f1` > 10) +def test ck1 (`f1` < 10) +def test t1_chk_1 (`f2` < 10) +def test t1_chk_2 (`f3` < 10) +def test t1_chk_3 (`f1` > 10) +def test t1_f4_chk (`f4` < 10) +DROP TABLE t1; +#----------------------------------------------------------------------- +# Test case to verify alter statement with drop and alter constraint +# on non-existing check constraint. +#----------------------------------------------------------------------- +CREATE TABLE t1(c1 INT, c2 INT, c3 INT, c4 INT); +ALTER TABLE t1 DROP CHECK ck13; +ERROR HY000: Check constraint 'ck13' is not found in the table. +ALTER TABLE t1 ALTER CHECK ck13 ENFORCED; +ERROR HY000: Check constraint 'ck13' is not found in the table. +DROP TABLE t1; +#----------------------------------------------------------------------- +# Test case to verify alter statement with multiple add, drop, enforce, +# revoke check constraints. +#----------------------------------------------------------------------- +CREATE TABLE t1(c1 INT, c2 INT, c3 INT, c4 INT); +ALTER TABLE t1 ADD CONSTRAINT ck11 CHECK(c1 > 1), +ADD CONSTRAINT ck12 CHECK(c1 < 1), +ADD CONSTRAINT ck21 CHECK(c2 > 1), +ADD CONSTRAINT ck22 CHECK(c2 < 1), +ADD CONSTRAINT ck31 CHECK(c3 > 1), +ADD CONSTRAINT ck32 CHECK(c3 < 1), +ADD CONSTRAINT ck41 CHECK(c4 > 1), +ADD CONSTRAINT ck42 CHECK(c4 < 1); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c1` int(11) DEFAULT NULL, + `c2` int(11) DEFAULT NULL, + `c3` int(11) DEFAULT NULL, + `c4` int(11) DEFAULT NULL, + CONSTRAINT `ck11` CHECK ((`c1` > 1)), + CONSTRAINT `ck12` CHECK ((`c1` < 1)), + CONSTRAINT `ck21` CHECK ((`c2` > 1)), + CONSTRAINT `ck22` CHECK ((`c2` < 1)), + CONSTRAINT `ck31` CHECK ((`c3` > 1)), + CONSTRAINT `ck32` CHECK ((`c3` < 1)), + CONSTRAINT `ck41` CHECK ((`c4` > 1)), + CONSTRAINT `ck42` CHECK ((`c4` < 1)) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci +ALTER TABLE t1 +DROP CHECK ck11, ADD CONSTRAINT ck11 CHECK (c1 > 10), +DROP CHECK ck12, ADD CONSTRAINT ck12 CHECK (c1 < 10), +DROP CHECK ck21, ADD CONSTRAINT ck21 CHECK (c1 > 10), +DROP CHECK ck22, ADD CONSTRAINT ck22 CHECK (c1 < 10), +DROP CHECK ck31, ADD CONSTRAINT ck31 CHECK (c1 > 10), +DROP CHECK ck32, ADD CONSTRAINT ck32 CHECK (c1 < 10), +DROP CHECK ck41, ADD CONSTRAINT ck41 CHECK (c1 > 10), +DROP CHECK ck42, ADD CONSTRAINT ck42 CHECK (c1 < 10), +ALTER CHECK ck11 NOT ENFORCED, +ALTER CHECK ck12 NOT ENFORCED, +ALTER CHECK ck21 NOT ENFORCED, +ALTER CHECK ck22 NOT ENFORCED, +ALTER CHECK ck11 ENFORCED; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c1` int(11) DEFAULT NULL, + `c2` int(11) DEFAULT NULL, + `c3` int(11) DEFAULT NULL, + `c4` int(11) DEFAULT NULL, + CONSTRAINT `ck11` CHECK ((`c1` > 10)), + CONSTRAINT `ck12` CHECK ((`c1` < 10)) /*!80015 NOT ENFORCED */, + CONSTRAINT `ck21` CHECK ((`c1` > 10)) /*!80015 NOT ENFORCED */, + CONSTRAINT `ck22` CHECK ((`c1` < 10)) /*!80015 NOT ENFORCED */, + CONSTRAINT `ck31` CHECK ((`c1` > 10)), + CONSTRAINT `ck32` CHECK ((`c1` < 10)), + CONSTRAINT `ck41` CHECK ((`c1` > 10)), + CONSTRAINT `ck42` CHECK ((`c1` < 10)) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci +DROP TABLE t1; +#----------------------------------------------------------------------- +# Test case to verify auto-drop of check constraint on column drop. +#----------------------------------------------------------------------- +CREATE TABLE t1 (f1 INT check (f1 < 10), f2 INT); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) DEFAULT NULL, + `f2` int(11) DEFAULT NULL, + CONSTRAINT `t1_chk_1` CHECK ((`f1` < 10)) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci +# Drops check constraint t1_chk_1 too. +ALTER TABLE t1 DROP COLUMN f1; +ALTER TABLE t1 ADD COLUMN f1 INT check(f1 < 10), +ADD CONSTRAINT check(f1 + f2 < 10), +ADD CONSTRAINT check(f2 < 10); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f2` int(11) DEFAULT NULL, + `f1` int(11) DEFAULT NULL, + CONSTRAINT `t1_chk_1` CHECK ((`f1` < 10)), + CONSTRAINT `t1_chk_2` CHECK (((`f1` + `f2`) < 10)), + CONSTRAINT `t1_chk_3` CHECK ((`f2` < 10)) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci +ALTER TABLE t1 DROP COLUMN f1; +ERROR 42S22: Unknown column 'f1' in 'check constraint t1_chk_2 expression' +ALTER TABLE t1 RENAME COLUMN f1 to f3; +ERROR 42S22: Unknown column 'f1' in 'check constraint t1_chk_1 expression' +# Drops column f1 and constraints t1_chk_1, t1_chk_2. +ALTER TABLE t1 DROP CHECK t1_chk_2, DROP COLUMN f1; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f2` int(11) DEFAULT NULL, + CONSTRAINT `t1_chk_3` CHECK ((`f2` < 10)) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci +DROP TABLE t1; +#----------------------------------------------------------------------- +# Test case to verify check constraint with MODIFY COLUMN syntax. +#----------------------------------------------------------------------- +CREATE TABLE t1(c1 CHAR(1), CHECK (c1 > 'A')); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c1` char(1) DEFAULT NULL, + CONSTRAINT `t1_chk_1` CHECK ((`c1` > _utf8mb4'A')) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci +INSERT INTO t1 VALUES('A'); +ERROR HY000: Check constraint 't1_chk_1' is violated. +INSERT INTO t1 VALUES('B'); +DELETE FROM t1; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c1` char(1) DEFAULT NULL, + CONSTRAINT `t1_chk_1` CHECK ((`c1` > _utf8mb4'A')) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci +ALTER TABLE t1 MODIFY COLUMN c1 FLOAT(10.3), DROP CHECK t1_chk_1, ADD CONSTRAINT CHECK(C1 > 10.1) ENFORCED; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c1` float DEFAULT NULL, + CONSTRAINT `t1_chk_2` CHECK ((`C1` > 10.1)) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci +DROP TABLE t1; +CREATE TABLE t1 (f1 INT CHECK (f1 = default(f1))); +INSERT INTO t1 VALUES (10); +ALTER TABLE t1 MODIFY COLUMN f1 INT DEFAULT 20, algorithm=inplace; +ERROR 0A000: ALGORITHM=INPLACE is not supported for this operation. Try ALGORITHM=COPY. +ALTER TABLE t1 ALTER f1 SET DEFAULT 20, algorithm=inplace; +ERROR 0A000: ALGORITHM=INPLACE is not supported for this operation. Try ALGORITHM=COPY. +ALTER TABLE t1 MODIFY COLUMN f1 INT DEFAULT 20, algorithm=copy; +ERROR HY000: Check constraint 't1_chk_1' is violated. +DROP TABLE t1; +#----------------------------------------------------------------------- +# Test case to verify check constraint with CHANGE COLUMN syntax. +#----------------------------------------------------------------------- +CREATE TABLE t1(c1 CHAR(1), CHECK (c1 > 'A')); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c1` char(1) DEFAULT NULL, + CONSTRAINT `t1_chk_1` CHECK ((`c1` > _utf8mb4'A')) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci +ALTER TABLE t1 CHANGE c1 c1 FLOAT, ALGORITHM=INPLACE; +ERROR 0A000: ALGORITHM=INPLACE is not supported for this operation. Try ALGORITHM=COPY. +ALTER TABLE t1 DROP CHECK t1_chk_1, CHANGE c1 c2 VARCHAR(20), ADD CONSTRAINT CHECK(c2 > 'B'); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c2` varchar(20) DEFAULT NULL, + CONSTRAINT `t1_chk_2` CHECK ((`c2` > _utf8mb4'B')) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci +DROP TABLE t1; +CREATE TABLE t (a INT, b INT, CHECK(a != b)); +INSERT INTO t VALUES (2000000000, 2000000001); +ALTER TABLE t CHANGE a a FLOAT, CHANGE b b FLOAT; +ERROR HY000: Check constraint 't_chk_1' is violated. +ALTER TABLE t ADD CONSTRAINT CHECK(a > b); +ERROR HY000: Check constraint 't_chk_2' is violated. +DROP TABLE t; +#------------------------------------------------------------------------ +# Test case to verify check constraints with IN operator. +#------------------------------------------------------------------------ +CREATE TABLE t1(f1 int CHECK (f1 IN (10, 20, 30)), f2 int, CHECK(f2 IN (100, 120, 450))); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) DEFAULT NULL, + `f2` int(11) DEFAULT NULL, + CONSTRAINT `t1_chk_1` CHECK ((`f1` in (10,20,30))), + CONSTRAINT `t1_chk_2` CHECK ((`f2` in (100,120,450))) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci +INSERT INTO t1 VALUES(10, 100); +INSERT INTO t1 VALUES(15, 100); +ERROR HY000: Check constraint 't1_chk_1' is violated. +INSERT INTO t1 VALUES(10, 105); +ERROR HY000: Check constraint 't1_chk_2' is violated. +DROP TABLE t1; +#------------------------------------------------------------------------ +# Test case to verify check constraints with BETWEEN operator. +#------------------------------------------------------------------------ +CREATE TABLE t1(f1 int CHECK(f1 BETWEEN 10 AND 30), +f2 int, CHECK(f2 BETWEEN 100 AND 450)); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) DEFAULT NULL, + `f2` int(11) DEFAULT NULL, + CONSTRAINT `t1_chk_1` CHECK ((`f1` between 10 and 30)), + CONSTRAINT `t1_chk_2` CHECK ((`f2` between 100 and 450)) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci +INSERT INTO t1 VALUES(20, 200); +INSERT INTO t1 VALUES(2, 200); +ERROR HY000: Check constraint 't1_chk_1' is violated. +INSERT INTO t1 VALUES(20, 2000); +ERROR HY000: Check constraint 't1_chk_2' is violated. +DROP TABLE t1; +#------------------------------------------------------------------------ +# Test case to verify check constraints with IS NOT NULL. +#------------------------------------------------------------------------ +CREATE TABLE t1 (f1 int CHECK(f1 IS NOT NULL)); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) DEFAULT NULL, + CONSTRAINT `t1_chk_1` CHECK ((`f1` is not null)) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci +INSERT INTO t1 VALUES(10); +INSERT INTO t1 VALUES(NULL); +ERROR HY000: Check constraint 't1_chk_1' is violated. +DROP TABLE t1; +#------------------------------------------------------------------------ +# Test case to verify check constraints with IS NULL. +#------------------------------------------------------------------------ +CREATE TABLE t1 (f1 int CHECK(f1 IS NULL)); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) DEFAULT NULL, + CONSTRAINT `t1_chk_1` CHECK (isnull(`f1`)) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci +INSERT INTO t1 VALUES(NULL); +INSERT INTO t1 VALUES(10); +ERROR HY000: Check constraint 't1_chk_1' is violated. +DROP TABLE t1; +#----------------------------------------------------------------------- +# Test case to verify check constraint with CASE Statement +#----------------------------------------------------------------------- +CREATE TABLE t1(c1 INT, c2 INT); +ALTER TABLE t1 ADD CONSTRAINT CHECK( (CASE WHEN c1 > 10 THEN c2 = 20 END) = 1); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c1` int(11) DEFAULT NULL, + `c2` int(11) DEFAULT NULL, + CONSTRAINT `t1_chk_1` CHECK (((case when (`c1` > 10) then (`c2` = 20) end) = 1)) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci +INSERT INTO t1 VALUES(1,1); +INSERT INTO t1 VALUES(15,1); +ERROR HY000: Check constraint 't1_chk_1' is violated. +INSERT INTO t1 VALUES(15,20); +SELECT * FROM t1; +c1 c2 +1 1 +15 20 +DROP TABLE t1; +#------------------------------------------------------------------------ +# Test case to verify check constraints restrictions. +#------------------------------------------------------------------------ +# Check constraint using column with AUTO_INCREMENT attribute. +CREATE TABLE t1 (f1 int primary key auto_increment, f2 int, CHECK (f1 != f2)); +ERROR HY000: Check constraint 't1_chk_1' cannot refer to an auto-increment column. +CREATE TABLE t1 (f1 int primary key auto_increment CHECK (f1 < 10), f2 int, CHECK (f1 != f2)); +ERROR HY000: Check constraint 't1_chk_1' cannot refer to an auto-increment column. +# Check constraint using non-deterministic builtin functions. +# NOW() +CREATE TABLE t1 (f1 TIMESTAMP CHECK (f1 + NOW() > '2011-11-21')); +ERROR HY000: An expression of a check constraint 't1_chk_1' contains disallowed function: now. +# CURRENT_TIMESTAMP() +CREATE TABLE t1 (f1 TIMESTAMP CHECK (f1 + CURRENT_TIMESTAMP() > '2011-11-21 01:02:03')); +ERROR HY000: An expression of a check constraint 't1_chk_1' contains disallowed function: now. +# CURRENT_TIMESTAMP +CREATE TABLE t1 (f1 TIMESTAMP CHECK (f1 + CURRENT_TIMESTAMP > '2011-11-21 01:02:03')); +ERROR HY000: An expression of a check constraint 't1_chk_1' contains disallowed function: now. +# CURDATE() +CREATE TABLE t1 (f1 DATETIME CHECK (f1 + CURDATE() > '2011-11-21')); +ERROR HY000: An expression of a check constraint 't1_chk_1' contains disallowed function: curdate. +# CURTIME() +CREATE TABLE t1 (f1 DATETIME CHECK (f1 + CURTIME() > '23:11:21')); +ERROR HY000: An expression of a check constraint 't1_chk_1' contains disallowed function: curtime. +# CURTIME +CREATE TABLE t1 (f1 TIMESTAMP CHECK (f1 + CURRENT_TIME > '01:02:03')); +ERROR HY000: An expression of a check constraint 't1_chk_1' contains disallowed function: curtime. +# CURRENT_DATE() +CREATE TABLE t1 (f1 TIMESTAMP CHECK (f1 + CURRENT_DATE() > '2011-11-21')); +ERROR HY000: An expression of a check constraint 't1_chk_1' contains disallowed function: curdate. +# CURRENT_DATE +CREATE TABLE t1 (f1 TIMESTAMP CHECK (f1 + CURRENT_DATE > '2011-11-21')); +ERROR HY000: An expression of a check constraint 't1_chk_1' contains disallowed function: curdate. +# CURRENT_TIME() +CREATE TABLE t1 (f1 TIMESTAMP CHECK (f1 + CURRENT_TIME() > '01:02:03')); +ERROR HY000: An expression of a check constraint 't1_chk_1' contains disallowed function: curtime. +# CURRENT_TIME +CREATE TABLE t1 (f1 TIMESTAMP CHECK (f1 + CURRENT_TIME > '01:02:03')); +ERROR HY000: An expression of a check constraint 't1_chk_1' contains disallowed function: curtime. +# LOCALTIME() +CREATE TABLE t1 (f1 DATETIME CHECK (f1 + LOCALTIME() > '23:11:21')); +ERROR HY000: An expression of a check constraint 't1_chk_1' contains disallowed function: now. +# LOCALTIME +CREATE TABLE t1 (f1 DATETIME CHECK (f1 + LOCALTIME > '23:11:21')); +ERROR HY000: An expression of a check constraint 't1_chk_1' contains disallowed function: now. +# LOCALTIMESTAMP() +CREATE TABLE t1 (f1 TIMESTAMP CHECK (f1 + LOCALTIMESTAMP() > '2011-11-21 01:02:03')); +ERROR HY000: An expression of a check constraint 't1_chk_1' contains disallowed function: now. +# LOCALTIMESTAMP +CREATE TABLE t1 (f1 TIMESTAMP CHECK (f1 + LOCALTIMESTAMP > '2011-11-21 01:02:03')); +ERROR HY000: An expression of a check constraint 't1_chk_1' contains disallowed function: now. +# UNIX_TIMESTAMP() +CREATE TABLE t1 (f1 TIMESTAMP CHECK (f1 + UNIX_TIMESTAMP() > '2011-11-21 01:02:03')); +ERROR HY000: An expression of a check constraint 't1_chk_1' contains disallowed function: unix_timestamp. +# UNIX_DATE() +CREATE TABLE t1 (f1 DATETIME CHECK (f1 + UTC_DATE() > '2011-11-21')); +ERROR HY000: An expression of a check constraint 't1_chk_1' contains disallowed function: utc_date. +# UNIX_TIMESTAMP() +CREATE TABLE t1 (f1 TIMESTAMP CHECK (f1 + UTC_TIMESTAMP() > '2011-11-21 01:02:03')); +ERROR HY000: An expression of a check constraint 't1_chk_1' contains disallowed function: utc_timestamp. +# UNIX_TIME() +CREATE TABLE t1 (f1 DATETIME CHECK (f1 + UTC_TIME() > '23:11:21')); +ERROR HY000: An expression of a check constraint 't1_chk_1' contains disallowed function: utc_time. +# CONNECTION_ID +CREATE TABLE t1 (f1 INT CHECK (f1 + CONNECTION_ID() < 929)); +ERROR HY000: An expression of a check constraint 't1_chk_1' contains disallowed function: connection_id. +# CURRENT_USER() +CREATE TABLE t1 (a VARCHAR(32) CHECK (CURRENT_USER() != a)); +ERROR HY000: An expression of a check constraint 't1_chk_1' contains disallowed function: current_user. +# CURRENT_USER +CREATE TABLE t1 (a VARCHAR(32) CHECK (CURRENT_USER != a)); +ERROR HY000: An expression of a check constraint 't1_chk_1' contains disallowed function: current_user. +# SESSION_USER() +CREATE TABLE t1 (a VARCHAR(32) CHECK (SESSION_USER() != a)); +ERROR HY000: An expression of a check constraint 't1_chk_1' contains disallowed function: user. +# VERSION() +CREATE TABLE t1 (a VARCHAR(32) CHECK (VERSION() != a)); +ERROR HY000: An expression of a check constraint 't1_chk_1' contains disallowed function: version(). +# FOUND_ROWS +CREATE TABLE t1 (a VARCHAR(1024), b INT CHECK (b + FOUND_ROWS() > 2000)); +ERROR HY000: An expression of a check constraint 't1_chk_1' contains disallowed function: found_rows. +# LAST_INSERT_ID +CREATE TABLE t1 (a INT CHECK ((a + LAST_INSERT_ID()) < 929)); +ERROR HY000: An expression of a check constraint 't1_chk_1' contains disallowed function: last_insert_id. +# SYSTEM_USER +CREATE TABLE t1 (a VARCHAR(32) CHECK (SYSTEM_USER() != a)); +ERROR HY000: An expression of a check constraint 't1_chk_1' contains disallowed function: user. +# USER +CREATE TABLE t1 (a VARCHAR(32) CHECK (USER() != a)); +ERROR HY000: An expression of a check constraint 't1_chk_1' contains disallowed function: user. +# RAND() +CREATE TABLE t1 (f1 FLOAT CHECK (f1 + RAND() < 929.929)); +ERROR HY000: An expression of a check constraint 't1_chk_1' contains disallowed function: rand. +# ROW_COUNT() +CREATE TABLE t1 (a INT CHECK (a + ROW_COUNT() > 1000)); +ERROR HY000: An expression of a check constraint 't1_chk_1' contains disallowed function: row_count. +# GET_LOCK() +CREATE TABLE t1 (a VARCHAR(1024), b VARCHAR(1024) CHECK (GET_LOCK(b,10) != 0)); +ERROR HY000: An expression of a check constraint 't1_chk_1' contains disallowed function: get_lock. +# IS_FREE_LOCK() +CREATE TABLE t1 (a VARCHAR(1024), b VARCHAR(1024) CHECK (IS_FREE_LOCK(b) != 0)); +ERROR HY000: An expression of a check constraint 't1_chk_1' contains disallowed function: is_free_lock. +# IS_USED_LOCK() +CREATE TABLE t1 (a VARCHAR(1024), b VARCHAR(1024) CHECK (IS_USED_LOCK(b) != 0)); +ERROR HY000: An expression of a check constraint 't1_chk_1' contains disallowed function: is_used_lock. +# RELEASE_LOCK() +CREATE TABLE t1 (a VARCHAR(1024), b VARCHAR(1024) CHECK (RELEASE_LOCK(b) != 0)); +ERROR HY000: An expression of a check constraint 't1_chk_1' contains disallowed function: release_lock. +# RELEASE_ALL_LOCK() +CREATE TABLE t1 (a VARCHAR(1024), b VARCHAR(1024), CHECK (RELEASE_ALL_LOCKS() != 0)); +ERROR HY000: An expression of a check constraint 't1_chk_1' contains disallowed function: release_all_locks. +# LOAD_FILE +CREATE TABLE t1 (f1 VARCHAR(1024), f2 VARCHAR(1024) CHECK (LOAD_FILE(f2) != NULL)); +ERROR HY000: An expression of a check constraint 't1_chk_1' contains disallowed function: load_file. +# UUID() +CREATE TABLE t1 (id CHAR(40) CHECK(UUID() != id)); +ERROR HY000: An expression of a check constraint 't1_chk_1' contains disallowed function: uuid. +# UUID_SHORT +CREATE TABLE t1 (id INT CHECK(UUID_SHORT() != id)); +ERROR HY000: An expression of a check constraint 't1_chk_1' contains disallowed function: uuid_short. +# SLEEP +CREATE TABLE t1 (id INT CHECK(SLEEP(id) != 0)); +ERROR HY000: An expression of a check constraint 't1_chk_1' contains disallowed function: sleep. +# Stored function +CREATE FUNCTION func() RETURNS INT DETERMINISTIC return 1; +CREATE TABLE t1 (id INT CHECK(id = func())); +ERROR HY000: An expression of a check constraint 't1_chk_1' contains disallowed function: `func`. +DROP FUNCTION func; +# Stored procedure +CREATE PROCEDURE proc() SELECT 1; +CREATE TABLE t1 (id INT CHECK(id = proc())); +ERROR HY000: An expression of a check constraint 't1_chk_1' contains disallowed function: `proc`. +DROP PROCEDURE proc; +# User variable +SET @v = 10; +CREATE TABLE t1 (id INT CHECK (id != @v)); +ERROR HY000: An expression of a check constraint 't1_chk_1' cannot refer to a user or system variables. +# System variables. +CREATE TABLE t1 (id INT CHECK (id != @@global.max_execution_time)); +ERROR HY000: An expression of a check constraint 't1_chk_1' cannot refer to a user or system variables. +CREATE TABLE t1 (id INt CHECK (id != @@session.max_execution_time)); +ERROR HY000: An expression of a check constraint 't1_chk_1' cannot refer to a user or system variables. +# Subquery +CREATE TABLE t1 (id INT CHECK (id != (SELECT 1))); +ERROR HY000: An expression of a check constraint 't1_chk_1' contains disallowed function. +# Parameter +PREPARE stmt FROM 'CREATE TABLE t1 (id INT CHECK(id != ?))'; +EXECUTE stmt using @v; +ERROR HY000: An expression of a check constraint 't1_chk_1' contains disallowed function. +DEALLOCATE PREPARE stmt; +#------------------------------------------------------------------------ +# Test case to verify check constraints with numeric data types. +#------------------------------------------------------------------------ +CREATE TABLE t1 ( +c1 BIT(7) CHECK(c1 < B'1111100'), +c2 BOOLEAN CHECK(c2 > 0), +c3 TINYINT CHECK(c3 > 10), +c4 SMALLINT CHECK(c4 > 10), +c5 MEDIUMINT CHECK(c5 > 10), +c6 INT CHECK(c6 > 10), +c7 BIGINT CHECK(c7 > 10), +c8 DECIMAL(6,2) CHECK(c8 > 10.1), +c9 FLOAT(6,2) CHECK(c9 > 10.1), +c10 DOUBLE(6,2) CHECK(c10 > 10.1)); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c1` bit(7) DEFAULT NULL, + `c2` tinyint(1) DEFAULT NULL, + `c3` tinyint(4) DEFAULT NULL, + `c4` smallint(6) DEFAULT NULL, + `c5` mediumint(9) DEFAULT NULL, + `c6` int(11) DEFAULT NULL, + `c7` bigint(20) DEFAULT NULL, + `c8` decimal(6,2) DEFAULT NULL, + `c9` float(6,2) DEFAULT NULL, + `c10` double(6,2) DEFAULT NULL, + CONSTRAINT `t1_chk_1` CHECK ((`c1` < 0x7c)), + CONSTRAINT `t1_chk_10` CHECK ((`c10` > 10.1)), + CONSTRAINT `t1_chk_2` CHECK ((`c2` > 0)), + CONSTRAINT `t1_chk_3` CHECK ((`c3` > 10)), + CONSTRAINT `t1_chk_4` CHECK ((`c4` > 10)), + CONSTRAINT `t1_chk_5` CHECK ((`c5` > 10)), + CONSTRAINT `t1_chk_6` CHECK ((`c6` > 10)), + CONSTRAINT `t1_chk_7` CHECK ((`c7` > 10)), + CONSTRAINT `t1_chk_8` CHECK ((`c8` > 10.1)), + CONSTRAINT `t1_chk_9` CHECK ((`c9` > 10.1)) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci +INSERT INTO t1(c1) VALUES(B'1111110'); +ERROR HY000: Check constraint 't1_chk_1' is violated. +INSERT INTO t1(c2) VALUES(0); +ERROR HY000: Check constraint 't1_chk_2' is violated. +INSERT INTO t1(c3) VALUES(1); +ERROR HY000: Check constraint 't1_chk_3' is violated. +INSERT INTO t1(c4) VALUES(1); +ERROR HY000: Check constraint 't1_chk_4' is violated. +INSERT INTO t1(c5) VALUES(1); +ERROR HY000: Check constraint 't1_chk_5' is violated. +INSERT INTO t1(c6) VALUES(1); +ERROR HY000: Check constraint 't1_chk_6' is violated. +INSERT INTO t1(c7) VALUES(1); +ERROR HY000: Check constraint 't1_chk_7' is violated. +INSERT INTO t1(c8) VALUES(10.0); +ERROR HY000: Check constraint 't1_chk_8' is violated. +INSERT INTO t1(c9) VALUES(10.0); +ERROR HY000: Check constraint 't1_chk_9' is violated. +INSERT INTO t1(c10) VALUES(10.0); +ERROR HY000: Check constraint 't1_chk_10' is violated. +INSERT INTO t1(c1,c2,c3,c4,c5,c6,c7,c8,c9,c10) +VALUES(B'1111000',1,11,11,11,11,11,10.2,10.2,10.2); +DROP TABLE t1; +#------------------------------------------------------------------------ +# Test case to verify check constraints with string data types. +#------------------------------------------------------------------------ +CREATE TABLE t1(c1 CHAR(1) CHECK(c1 > 'a'), +c2 VARCHAR(1) CHECK(c2 > 'a'), +c3 BINARY(1) CHECK(c3 > 'a'), +c4 VARBINARY(1) CHECK(c4 > 'a'), +c5 TINYBLOB CHECK(c5 > 'a'), +c6 TINYTEXT CHECK(c6 > 'a'), +c7 BLOB CHECK(c7 > 'a'), +c8 TEXT CHECK(c8 > 'a'), +c9 MEDIUMBLOB CHECK(c9 > 'a'), +c10 MEDIUMTEXT CHECK(c10 > 'a'), +c11 LONGBLOB CHECK(c11 > 'a'), +c12 LONGTEXT CHECK(c12 > 'a')); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c1` char(1) DEFAULT NULL, + `c2` varchar(1) DEFAULT NULL, + `c3` binary(1) DEFAULT NULL, + `c4` varbinary(1) DEFAULT NULL, + `c5` tinyblob, + `c6` tinytext, + `c7` blob, + `c8` text, + `c9` mediumblob, + `c10` mediumtext, + `c11` longblob, + `c12` longtext, + CONSTRAINT `t1_chk_1` CHECK ((`c1` > _utf8mb4'a')), + CONSTRAINT `t1_chk_10` CHECK ((`c10` > _utf8mb4'a')), + CONSTRAINT `t1_chk_11` CHECK ((`c11` > _utf8mb4'a')), + CONSTRAINT `t1_chk_12` CHECK ((`c12` > _utf8mb4'a')), + CONSTRAINT `t1_chk_2` CHECK ((`c2` > _utf8mb4'a')), + CONSTRAINT `t1_chk_3` CHECK ((`c3` > _utf8mb4'a')), + CONSTRAINT `t1_chk_4` CHECK ((`c4` > _utf8mb4'a')), + CONSTRAINT `t1_chk_5` CHECK ((`c5` > _utf8mb4'a')), + CONSTRAINT `t1_chk_6` CHECK ((`c6` > _utf8mb4'a')), + CONSTRAINT `t1_chk_7` CHECK ((`c7` > _utf8mb4'a')), + CONSTRAINT `t1_chk_8` CHECK ((`c8` > _utf8mb4'a')), + CONSTRAINT `t1_chk_9` CHECK ((`c9` > _utf8mb4'a')) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci +INSERT INTO t1(c1) VALUES('a'); +ERROR HY000: Check constraint 't1_chk_1' is violated. +INSERT INTO t1(c2) VALUES('a'); +ERROR HY000: Check constraint 't1_chk_2' is violated. +INSERT INTO t1(c3) VALUES('a'); +ERROR HY000: Check constraint 't1_chk_3' is violated. +INSERT INTO t1(c4) VALUES('a'); +ERROR HY000: Check constraint 't1_chk_4' is violated. +INSERT INTO t1(c5) VALUES('a'); +ERROR HY000: Check constraint 't1_chk_5' is violated. +INSERT INTO t1(c6) VALUES('a'); +ERROR HY000: Check constraint 't1_chk_6' is violated. +INSERT INTO t1(c7) VALUES('a'); +ERROR HY000: Check constraint 't1_chk_7' is violated. +INSERT INTO t1(c8) VALUES('a'); +ERROR HY000: Check constraint 't1_chk_8' is violated. +INSERT INTO t1(c9) VALUES('a'); +ERROR HY000: Check constraint 't1_chk_9' is violated. +INSERT INTO t1(c10) VALUES('a'); +ERROR HY000: Check constraint 't1_chk_10' is violated. +INSERT INTO t1(c11) VALUES('a'); +ERROR HY000: Check constraint 't1_chk_11' is violated. +INSERT INTO t1(c12) VALUES('a'); +ERROR HY000: Check constraint 't1_chk_12' is violated. +INSERT INTO t1(c1,c2,c3,c4,c5,c6,c7,c8,c9,c10,c11,c12) +VALUES('b',"b","b","b","b","b","b","b","b","b","b","b"); +DROP TABLE t1; +#------------------------------------------------------------------------ +# Test case to verify check constraints with date and time data types. +#------------------------------------------------------------------------ +CREATE TABLE t1 (c1 DATE CHECK(c1 > '2007-01-01'), +c2 DATETIME CHECK(c2 > '2007-01-01 12:00:01'), +c3 TIMESTAMP CHECK(c3 > '2007-01-01 00:00:01.000000'), +c4 TIME CHECK(c4 > '12:00:01.000000'), +c5 YEAR CHECK(c5 > '2007')); +INSERT INTO t1(c1) VALUES('2006-01-01'); +ERROR HY000: Check constraint 't1_chk_1' is violated. +INSERT INTO t1(c2) VALUES('2007-01-01 11:00:01'); +ERROR HY000: Check constraint 't1_chk_2' is violated. +INSERT INTO t1(c3) VALUES('2007-01-01 00:00:00.000000'); +ERROR HY000: Check constraint 't1_chk_3' is violated. +INSERT INTO t1(c4) VALUES('12:00:00.000000'); +ERROR HY000: Check constraint 't1_chk_4' is violated. +INSERT INTO t1(c5) VALUES('2006'); +ERROR HY000: Check constraint 't1_chk_5' is violated. +INSERT INTO t1(c1,c2,c3,c4,c5) +VALUES('2008-01-01','2007-01-01 12:00:02','2007-01-01 00:00:02.000000', +'12:00:02.000000','2008'); +DROP TABLE t1; +#------------------------------------------------------------------------ +# Test case to verify check constraints with JSON data type. +#------------------------------------------------------------------------ +CREATE TABLE t1( +id INT AUTO_INCREMENT PRIMARY KEY, +name VARCHAR(255), +browser JSON CHECK( browser->'$.name' = "Chrome" )); +INSERT INTO t1(name,browser) +VALUES('pageview','{ "name": "Safari", "os": "Mac" }'); +ERROR HY000: Check constraint 't1_chk_1' is violated. +INSERT INTO t1(name,browser) +VALUES('pageview','{ "name": "Chrome", "os": "Mac" }'); +SELECT * FROM t1; +id name browser +1 pageview {"os": "Mac", "name": "Chrome"} +DROP TABLE t1; +#----------------------------------------------------------------------- +# check constraint with ENUM data type +#----------------------------------------------------------------------- +CREATE TABLE t1 (c1 ENUM ('a','b') CHECK (c1 IN ('c', 'd')) ); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c1` enum('a','b') DEFAULT NULL, + CONSTRAINT `t1_chk_1` CHECK ((`c1` in (_utf8mb4'c',_utf8mb4'd'))) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci +INSERT INTO t1 VALUES('a'); +ERROR HY000: Check constraint 't1_chk_1' is violated. +INSERT INTO t1 VALUES('b'); +ERROR HY000: Check constraint 't1_chk_1' is violated. +INSERT INTO t1 VALUES('c'); +ERROR 01000: Data truncated for column 'c1' at row 1 +INSERT INTO t1 VALUES('d'); +ERROR 01000: Data truncated for column 'c1' at row 1 +DROP TABLE t1; +#----------------------------------------------------------------------- +# check constraint with SET data type +#----------------------------------------------------------------------- +CREATE TABLE t1 (c1 SET ('a','b') CHECK (c1 IN ('c', 'd')) ); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c1` set('a','b') DEFAULT NULL, + CONSTRAINT `t1_chk_1` CHECK ((`c1` in (_utf8mb4'c',_utf8mb4'd'))) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci +INSERT INTO t1 VALUES('a'); +ERROR HY000: Check constraint 't1_chk_1' is violated. +INSERT INTO t1 VALUES('b'); +ERROR HY000: Check constraint 't1_chk_1' is violated. +INSERT INTO t1 VALUES('c'); +ERROR 01000: Data truncated for column 'c1' at row 1 +INSERT INTO t1 VALUES('d'); +ERROR 01000: Data truncated for column 'c1' at row 1 +DROP TABLE t1; +#------------------------------------------------------------------------ +# Test case to verify check constraints with spatial data type. +#------------------------------------------------------------------------ +CREATE TABLE t1( +pt POINT CHECK(ST_Equals(pt, ST_GEOMFROMTEXT('POINT(10 20)')) = TRUE), +lnstr LINESTRING CHECK(ST_Equals(lnstr, ST_GEOMFROMTEXT('LINESTRING(0 0,5 5,6 6)'))), +mlnstr MULTILINESTRING CHECK(ST_Equals(mlnstr, ST_GEOMFROMTEXT('MULTILINESTRING((0 0,2 3,4 5), + (6 6,8 8,9 9,10 10))'))), +poly POLYGON CHECK(ST_Equals(poly, ST_GEOMFROMTEXT('POLYGON((0 0,6 7,8 8,3 9,0 0), + (3 6,4 6,4 7,3 6))'))), +mpoly MULTIPOLYGON CHECK(ST_Equals(mpoly, ST_GEOMFROMTEXT('MULTIPOLYGON(((0 0,0 5,5 5,5 0,0 0)), + ((2 2,4 5,6 2,2 2)))')))); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `pt` point DEFAULT NULL, + `lnstr` linestring DEFAULT NULL, + `mlnstr` multilinestring DEFAULT NULL, + `poly` polygon DEFAULT NULL, + `mpoly` multipolygon DEFAULT NULL, + CONSTRAINT `t1_chk_1` CHECK ((st_equals(`pt`,st_geomfromtext(_utf8mb4'POINT(10 20)')) = TRUE)), + CONSTRAINT `t1_chk_2` CHECK (st_equals(`lnstr`,st_geomfromtext(_utf8mb4'LINESTRING(0 0,5 5,6 6)'))), + CONSTRAINT `t1_chk_3` CHECK (st_equals(`mlnstr`,st_geomfromtext(_utf8mb4'MULTILINESTRING((0 0,2 3,4 5),\n (6 6,8 8,9 9,10 10))'))), + CONSTRAINT `t1_chk_4` CHECK (st_equals(`poly`,st_geomfromtext(_utf8mb4'POLYGON((0 0,6 7,8 8,3 9,0 0),\n (3 6,4 6,4 7,3 6))'))), + CONSTRAINT `t1_chk_5` CHECK (st_equals(`mpoly`,st_geomfromtext(_utf8mb4'MULTIPOLYGON(((0 0,0 5,5 5,5 0,0 0)),\n ((2 2,4 5,6 2,2 2)))'))) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci +INSERT INTO t1(pt) VALUES (ST_GEOMFROMTEXT('POINT(10 21)')); +ERROR HY000: Check constraint 't1_chk_1' is violated. +INSERT INTO t1(lnstr) VALUES (ST_GEOMFROMTEXT('LINESTRING(0 0,5 5,6 7)')); +ERROR HY000: Check constraint 't1_chk_2' is violated. +INSERT INTO t1(mlnstr) VALUES (ST_GEOMFROMTEXT('MULTILINESTRING((0 0,2 3,4 5),(6 6,8 8,9 9,10 11))')); +ERROR HY000: Check constraint 't1_chk_3' is violated. +INSERT INTO t1(poly) VALUES (ST_GEOMFROMTEXT('POLYGON((0 0,6 7,8 8,3 9,0 0),(3 6,4 6,4 8,3 6))')); +ERROR HY000: Check constraint 't1_chk_4' is violated. +INSERT INTO t1(mpoly) VALUES (ST_GEOMFROMTEXT('MULTIPOLYGON(((0 0,0 5,5 5,5 0,0 0)),((2 2,4 5,6 3,2 2)))')); +ERROR HY000: Check constraint 't1_chk_5' is violated. +INSERT INTO t1(pt) VALUES (ST_GEOMFROMTEXT('POINT(10 20)')); +INSERT INTO t1(lnstr) VALUES (ST_GEOMFROMTEXT('LINESTRING(0 0,5 5,6 6)')); +INSERT INTO t1(mlnstr) VALUES (ST_GEOMFROMTEXT('MULTILINESTRING((0 0,2 3,4 5),(6 6,8 8,9 9,10 10))')); +INSERT INTO t1(poly) VALUES (ST_GEOMFROMTEXT('POLYGON((0 0,6 7,8 8,3 9,0 0),(3 6,4 6,4 7,3 6))')); +INSERT INTO t1(mpoly) VALUES (ST_GEOMFROMTEXT('MULTIPOLYGON(((0 0,0 5,5 5,5 0,0 0)),((2 2,4 5,6 2,2 2)))')); +DROP TABLE t1; +#----------------------------------------------------------------------- +# Test case to verify check constraint with REGEX +#----------------------------------------------------------------------- +CREATE TABLE student +( +id INT, +stu_code VARCHAR(10), +name VARCHAR(14), +email VARCHAR(20), +scholarship INT, +country VARCHAR(20), +CONSTRAINT ck1 CHECK (id != 0), +CONSTRAINT ck2 CHECK (stu_code like 'j%'), +CONSTRAINT ck3 CHECK (lower(name) != "noname"), +CONSTRAINT ck4 CHECK (REGEXP_LIKE(email,'@')), +CONSTRAINT ck5 CHECK (scholarship BETWEEN 5000 AND 20000), +CONSTRAINT ck6 CHECK (country IN ('usa','uk')) +); +SHOW CREATE TABLE student; +Table Create Table +student CREATE TABLE `student` ( + `id` int(11) DEFAULT NULL, + `stu_code` varchar(10) DEFAULT NULL, + `name` varchar(14) DEFAULT NULL, + `email` varchar(20) DEFAULT NULL, + `scholarship` int(11) DEFAULT NULL, + `country` varchar(20) DEFAULT NULL, + CONSTRAINT `ck1` CHECK ((`id` <> 0)), + CONSTRAINT `ck2` CHECK ((`stu_code` like _utf8mb4'j%')), + CONSTRAINT `ck3` CHECK ((lower(`name`) <> _utf8mb4'noname')), + CONSTRAINT `ck4` CHECK (regexp_like(`email`,_utf8mb4'@')), + CONSTRAINT `ck5` CHECK ((`scholarship` between 5000 and 20000)), + CONSTRAINT `ck6` CHECK ((`country` in (_utf8mb4'usa',_utf8mb4'uk'))) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci +INSERT INTO student VALUES(0,"j001","name1","name1@oracle.com",6000,'usa'); +ERROR HY000: Check constraint 'ck1' is violated. +INSERT INTO student VALUES(1,"s001","name1","name1@oracle.com",6000,'usa'); +ERROR HY000: Check constraint 'ck2' is violated. +INSERT INTO student VALUES(1,"j001","NONAME","name1@oracle.com",6000,'usa'); +ERROR HY000: Check constraint 'ck3' is violated. +INSERT INTO student VALUES(1,"j001","name1","name1oracle.com",6000,'usa'); +ERROR HY000: Check constraint 'ck4' is violated. +INSERT INTO student VALUES(1,"j001","name1","name1@oracle.com",4000,'usa'); +ERROR HY000: Check constraint 'ck5' is violated. +INSERT INTO student VALUES(1,"j001","name1","name1@oracle.com",6000,'nocountry'); +ERROR HY000: Check constraint 'ck6' is violated. +INSERT INTO student VALUES(1,"j001","name1","name1@oracle.com",6000,'usa'); +SELECT * FROM student; +id stu_code name email scholarship country +1 j001 name1 name1@oracle.com 6000 usa +DROP TABLE student; +#----------------------------------------------------------------------- +# Test case to verify check constraint with numeric comparator +# operators with varchar columns. +#----------------------------------------------------------------------- +CREATE TABLE t1(c1 INT, c2 VARCHAR(20)); +ALTER TABLE t1 ADD CONSTRAINT ck1 CHECK ( c1 > c2 ); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c1` int(11) DEFAULT NULL, + `c2` varchar(20) DEFAULT NULL, + CONSTRAINT `ck1` CHECK ((`c1` > `c2`)) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci +DROP TABLE t1; +#----------------------------------------------------------------------- +# Test case to verify check constraint with Comparison Functions +# and Operators +#----------------------------------------------------------------------- +CREATE TABLE t1(c1 INT, CHECK ( c1 IN ( SELECT COALESCE(NULL, 1, 1)))); +ERROR HY000: An expression of non-boolean type specified to a check constraint 't1_chk_1'. +CREATE TABLE t1(c1 INT, CHECK ( c1 < ( SELECT COALESCE(NULL, 1, 1)))); +ERROR HY000: An expression of a check constraint 't1_chk_1' contains disallowed function. +CREATE TABLE t1(c1 INT , CHECK ( c1 <=> NULL )); +INSERT INTO t1 VALUES(1); +ERROR HY000: Check constraint 't1_chk_1' is violated. +INSERT INTO t1 VALUES(NULL); +SELECT * FROM t1; +c1 +NULL +ALTER TABLE t1 ADD COLUMN c2 INT, ADD CONSTRAINT CHECK( c2 > 10 ); +INSERT INTO t1(c2) VALUES(10); +ERROR HY000: Check constraint 't1_chk_2' is violated. +INSERT INTO t1(c2) VALUES(11); +ALTER TABLE t1 ADD COLUMN c3 INT, ADD CONSTRAINT CHECK( c3 >= 10 ); +INSERT INTO t1(c3) VALUES(9); +ERROR HY000: Check constraint 't1_chk_3' is violated. +INSERT INTO t1(c3) VALUES(10); +ALTER TABLE t1 ADD COLUMN c4 INT, ADD CONSTRAINT CHECK( c4 < 10 ); +INSERT INTO t1(c4) VALUES(10); +ERROR HY000: Check constraint 't1_chk_4' is violated. +INSERT INTO t1(c4) VALUES(9); +ALTER TABLE t1 ADD COLUMN c5 INT, ADD CONSTRAINT CHECK( c5 <= 10 ); +INSERT INTO t1(c5) VALUES(11); +ERROR HY000: Check constraint 't1_chk_5' is violated. +INSERT INTO t1(c5) VALUES(10); +ALTER TABLE t1 ADD COLUMN c6 INT, ADD CONSTRAINT CHECK( c6 != 10 ); +INSERT INTO t1(c6) VALUES(10); +ERROR HY000: Check constraint 't1_chk_6' is violated. +INSERT INTO t1(c6) VALUES(20); +ALTER TABLE t1 ADD COLUMN c7 INT, ADD CONSTRAINT CHECK( c7 <> 10 ); +INSERT INTO t1(c7) VALUES(10); +ERROR HY000: Check constraint 't1_chk_7' is violated. +INSERT INTO t1(c7) VALUES(20); +ALTER TABLE t1 ADD COLUMN c8 INT, ADD CONSTRAINT CHECK( c8 = GREATEST(1,2,3) ); +INSERT INTO t1(c8) VALUES(1); +ERROR HY000: Check constraint 't1_chk_8' is violated. +INSERT INTO t1(c8) VALUES(3); +ALTER TABLE t1 ADD COLUMN c9 INT, ADD CONSTRAINT CHECK( c9 = LEAST(1,2,3) ); +INSERT INTO t1(c9) VALUES(3); +ERROR HY000: Check constraint 't1_chk_9' is violated. +INSERT INTO t1(c9) VALUES(1); +ALTER TABLE t1 ADD COLUMN c10 INT, ADD CONSTRAINT CHECK( c10 NOT IN (1,2,3) ); +INSERT INTO t1(c10) VALUES(1); +ERROR HY000: Check constraint 't1_chk_10' is violated. +INSERT INTO t1(c10) VALUES(3); +ERROR HY000: Check constraint 't1_chk_10' is violated. +INSERT INTO t1(c10) VALUES(10); +ALTER TABLE t1 ADD COLUMN c11 YEAR, ADD CONSTRAINT CHECK ( c11 > '2007-01-01' + INTERVAL +1 YEAR); +INSERT INTO t1(c11) VALUES(2007); +ERROR HY000: Check constraint 't1_chk_11' is violated. +INSERT INTO t1(c11) VALUES(2008); +ERROR HY000: Check constraint 't1_chk_11' is violated. +INSERT INTO t1(c11) VALUES(2009); +ALTER TABLE t1 ADD COLUMN c12 INT, ADD CONSTRAINT CHECK ( c12 NOT BETWEEN 10 AND 20); +INSERT INTO t1(c12) VALUES(15); +ERROR HY000: Check constraint 't1_chk_12' is violated. +INSERT INTO t1(c12) VALUES(25); +ALTER TABLE t1 ADD COLUMN c13 INT, ADD CONSTRAINT CHECK ( c13 NOT IN (1, 2, 3)); +INSERT INTO t1(c13) VALUES(1); +ERROR HY000: Check constraint 't1_chk_13' is violated. +INSERT INTO t1(c13) VALUES(15); +ALTER TABLE t1 ADD COLUMN c14 CHAR(10), ADD CONSTRAINT CHECK ( c14 LIKE 'A%'); +INSERT INTO t1(c14) VALUES('Good'); +ERROR HY000: Check constraint 't1_chk_14' is violated. +INSERT INTO t1(c14) VALUES('All'); +ALTER TABLE t1 ADD COLUMN c15 INT, ADD CONSTRAINT CHECK ( c15 = STRCMP('A','A')); +INSERT INTO t1(c15) VALUES(1); +ERROR HY000: Check constraint 't1_chk_15' is violated. +INSERT INTO t1(c15) VALUES(0); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c1` int(11) DEFAULT NULL, + `c2` int(11) DEFAULT NULL, + `c3` int(11) DEFAULT NULL, + `c4` int(11) DEFAULT NULL, + `c5` int(11) DEFAULT NULL, + `c6` int(11) DEFAULT NULL, + `c7` int(11) DEFAULT NULL, + `c8` int(11) DEFAULT NULL, + `c9` int(11) DEFAULT NULL, + `c10` int(11) DEFAULT NULL, + `c11` year(4) DEFAULT NULL, + `c12` int(11) DEFAULT NULL, + `c13` int(11) DEFAULT NULL, + `c14` char(10) DEFAULT NULL, + `c15` int(11) DEFAULT NULL, + CONSTRAINT `t1_chk_1` CHECK ((`c1` <=> NULL)), + CONSTRAINT `t1_chk_10` CHECK ((`c10` not in (1,2,3))), + CONSTRAINT `t1_chk_11` CHECK ((`c11` > 2008)), + CONSTRAINT `t1_chk_12` CHECK ((`c12` not between 10 and 20)), + CONSTRAINT `t1_chk_13` CHECK ((`c13` not in (1,2,3))), + CONSTRAINT `t1_chk_14` CHECK ((`c14` like _utf8mb4'A%')), + CONSTRAINT `t1_chk_15` CHECK ((`c15` = strcmp(_utf8mb4'A',_utf8mb4'A'))), + CONSTRAINT `t1_chk_2` CHECK ((`c2` > 10)), + CONSTRAINT `t1_chk_3` CHECK ((`c3` >= 10)), + CONSTRAINT `t1_chk_4` CHECK ((`c4` < 10)), + CONSTRAINT `t1_chk_5` CHECK ((`c5` <= 10)), + CONSTRAINT `t1_chk_6` CHECK ((`c6` <> 10)), + CONSTRAINT `t1_chk_7` CHECK ((`c7` <> 10)), + CONSTRAINT `t1_chk_8` CHECK ((`c8` = greatest(1,2,3))), + CONSTRAINT `t1_chk_9` CHECK ((`c9` = least(1,2,3))) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci +DROP TABLE t1; +#----------------------------------------------------------------------- +# Test case to verify check constraint with Logical Operators +#----------------------------------------------------------------------- +CREATE TABLE t1(c1 INT, c2 INT); +ALTER TABLE t1 ADD CONSTRAINT CHECK( (c1 > 10) AND (c2 < 20) ); +INSERT INTO t1 VALUES(1,10); +ERROR HY000: Check constraint 't1_chk_1' is violated. +ALTER TABLE t1 ADD CONSTRAINT CHECK( (c1 > 10) && (c2 < 20) ); +INSERT INTO t1 VALUES(15,25); +ERROR HY000: Check constraint 't1_chk_1' is violated. +ALTER TABLE t1 DROP CHECK `t1_chk_1`; +ALTER TABLE t1 DROP CHECK `t1_chk_2`; +ALTER TABLE t1 ADD CONSTRAINT CHECK( (c1 > 10) || (c2 < 20) ); +ALTER TABLE t1 ADD CONSTRAINT CHECK( (c1 > 10) OR (c2 < 20) ); +INSERT INTO t1 VALUES(15,25); +INSERT INTO t1 VALUES(5,10); +INSERT INTO t1 VALUES(5,25); +ERROR HY000: Check constraint 't1_chk_1' is violated. +ALTER TABLE t1 DROP CHECK `t1_chk_1`; +ALTER TABLE t1 DROP CHECK `t1_chk_2`; +DELETE FROM t1; +ALTER TABLE t1 ADD CONSTRAINT CHECK( (c1 > 10) XOR (c2 < 20) ); +INSERT INTO t1 VALUES(15,10); +ERROR HY000: Check constraint 't1_chk_1' is violated. +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c1` int(11) DEFAULT NULL, + `c2` int(11) DEFAULT NULL, + CONSTRAINT `t1_chk_1` CHECK (((`c1` > 10) xor (`c2` < 20))) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci +DROP TABLE t1; +#----------------------------------------------------------------------- +# Test case to verify check constraint behaviour with DEFAULT, NULL +# and with LOGICAL operators. +#----------------------------------------------------------------------- +CREATE TABLE t1(c1 INT DEFAULT 2 PRIMARY KEY CHECK(c1 > 1 OR c1 IS NOT NULL)); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c1` int(11) NOT NULL DEFAULT '2', + PRIMARY KEY (`c1`), + CONSTRAINT `t1_chk_1` CHECK (((`c1` > 1) or (`c1` is not null))) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci +INSERT INTO t1 VALUES(NULL); +ERROR 23000: Column 'c1' cannot be null +INSERT INTO t1 VALUES(1); +SELECT * FROM t1; +c1 +1 +DROP TABLE t1; +CREATE TABLE t1(c1 INT DEFAULT 2 PRIMARY KEY CHECK(c1 > 1 OR c1 > 2)); +INSERT INTO t1 VALUES(1); +ERROR HY000: Check constraint 't1_chk_1' is violated. +INSERT INTO t1 VALUES(2); +SELECT * FROM t1; +c1 +2 +DROP TABLE t1; +CREATE TABLE t1(c1 INT DEFAULT 2 PRIMARY KEY CHECK(c1 > 1 AND c1 IS NOT NULL)); +INSERT INTO t1 VALUES(1); +ERROR HY000: Check constraint 't1_chk_1' is violated. +DROP TABLE t1; +#----------------------------------------------------------------------- +# Test case to verify check constraint when table is moved to another DB +#----------------------------------------------------------------------- +CREATE DATABASE test1; +CREATE DATABASE test2; +USE test1; +CREATE TABLE t1(c1 INT, c2 INT CHECK (c2 < 10)); +INSERT INTO t1 VALUES(1,1); +SELECT * FROM INFORMATION_SCHEMA.CHECK_CONSTRAINTS; +CONSTRAINT_CATALOG CONSTRAINT_SCHEMA CONSTRAINT_NAME CHECK_CLAUSE +def test1 t1_chk_1 (`c2` < 10) +SELECT * FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE TABLE_NAME='t1'; +CONSTRAINT_CATALOG CONSTRAINT_SCHEMA CONSTRAINT_NAME TABLE_SCHEMA TABLE_NAME CONSTRAINT_TYPE ENFORCED +def test1 t1_chk_1 test1 t1 CHECK YES +ALTER TABLE test1.t1 rename test2.t1; +USE test2; +SELECT * FROM t1; +c1 c2 +1 1 +SELECT * FROM INFORMATION_SCHEMA.CHECK_CONSTRAINTS; +CONSTRAINT_CATALOG CONSTRAINT_SCHEMA CONSTRAINT_NAME CHECK_CLAUSE +def test2 t1_chk_1 (`c2` < 10) +SELECT * FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE TABLE_NAME='t1'; +CONSTRAINT_CATALOG CONSTRAINT_SCHEMA CONSTRAINT_NAME TABLE_SCHEMA TABLE_NAME CONSTRAINT_TYPE ENFORCED +def test2 t1_chk_1 test2 t1 CHECK YES +DROP DATABASE test2; +DROP DATABASE test1; +#----------------------------------------------------------------------- +# Test case to verify check constraint when table is moved to another DB +# with different name. +#----------------------------------------------------------------------- +CREATE DATABASE test1; +CREATE DATABASE test2; +USE test1; +CREATE TABLE t1(c1 INT, c2 INT CHECK (c2 < 10)); +INSERT INTO t1 VALUES(1,1); +SELECT * FROM INFORMATION_SCHEMA.CHECK_CONSTRAINTS; +CONSTRAINT_CATALOG CONSTRAINT_SCHEMA CONSTRAINT_NAME CHECK_CLAUSE +def test1 t1_chk_1 (`c2` < 10) +SELECT * FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE TABLE_NAME='t1'; +CONSTRAINT_CATALOG CONSTRAINT_SCHEMA CONSTRAINT_NAME TABLE_SCHEMA TABLE_NAME CONSTRAINT_TYPE ENFORCED +def test1 t1_chk_1 test1 t1 CHECK YES +ALTER TABLE test1.t1 rename test2.t2; +USE test2; +SELECT * FROM t2; +c1 c2 +1 1 +SELECT * FROM INFORMATION_SCHEMA.CHECK_CONSTRAINTS; +CONSTRAINT_CATALOG CONSTRAINT_SCHEMA CONSTRAINT_NAME CHECK_CLAUSE +def test2 t2_chk_1 (`c2` < 10) +SELECT * FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE TABLE_NAME='t2'; +CONSTRAINT_CATALOG CONSTRAINT_SCHEMA CONSTRAINT_NAME TABLE_SCHEMA TABLE_NAME CONSTRAINT_TYPE ENFORCED +def test2 t2_chk_1 test2 t2 CHECK YES +DROP DATABASE test2; +DROP DATABASE test1; +use test; +#----------------------------------------------------------------------- +# Test case to verify check constraints with foreign key constraint +#----------------------------------------------------------------------- +CREATE TABLE parent(pid INT NOT NULL PRIMARY KEY CHECK(pid > 1)); +CREATE TABLE child(cid INT CHECK(cid > 1), +FOREIGN KEY fk(cid) REFERENCES parent(pid)); +SHOW CREATE TABLE parent; +Table Create Table +parent CREATE TABLE `parent` ( + `pid` int(11) NOT NULL, + PRIMARY KEY (`pid`), + CONSTRAINT `parent_chk_1` CHECK ((`pid` > 1)) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci +SHOW CREATE TABLE child; +Table Create Table +child CREATE TABLE `child` ( + `cid` int(11) DEFAULT NULL, + KEY `fk` (`cid`), + CONSTRAINT `fk` FOREIGN KEY (`cid`) REFERENCES `parent` (`pid`), + CONSTRAINT `child_chk_1` CHECK ((`cid` > 1)) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci +INSERT INTO parent VALUES(2); +INSERT INTO child VALUES(1); +ERROR HY000: Check constraint 'child_chk_1' is violated. +INSERT INTO child VALUES(3); +ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test`.`child`, CONSTRAINT `fk` FOREIGN KEY (`cid`) REFERENCES `parent` (`pid`)) +INSERT INTO child VALUES(2); +SELECT * FROM parent; +pid +2 +SELECT * FROM child; +cid +2 +DROP TABLE child; +DROP TABLE parent; +#----------------------------------------------------------------------- +# Test case to verify check constraint with FK referential actions. +#----------------------------------------------------------------------- +CREATE TABLE parent (a INT PRIMARY KEY); +CREATE TABLE child ( +b INT, +c INT CHECK (c < 10), +INDEX(b), +FOREIGN KEY (b) REFERENCES parent(a) ON DELETE SET NULL, +CHECK (b IS NOT NULL) +); +ERROR HY000: Column 'b' cannot be used in a check constraint 'child_chk_2': needed in a foreign key constraint 'child_ibfk_1' referential action. +CREATE TABLE child ( +b INT, +c INT CHECK (c < 10), +INDEX(b), +FOREIGN KEY (b) REFERENCES parent(a) ON DELETE SET NULL +); +ALTER TABLE child ADD CONSTRAINT CHECK (b IS NOT NULL); +ERROR HY000: Column 'b' cannot be used in a check constraint 'child_chk_2': needed in a foreign key constraint 'child_ibfk_1' referential action. +ALTER TABLE child DROP FOREIGN KEY child_ibfk_1; +ALTER TABLE child ADD CONSTRAINT FOREIGN KEY (b) REFERENCES parent(a) ON DELETE SET NULL, +ADD CONSTRAINT CHECK (b IS NOT NULL); +ERROR HY000: Column 'b' cannot be used in a check constraint 'child_chk_2': needed in a foreign key constraint 'child_ibfk_1' referential action. +DROP TABLE child; +CREATE TABLE child ( +b INT, +c INT CHECK (c < 10), +INDEX(b), +FOREIGN KEY (b) REFERENCES parent(a) ON UPDATE SET NULL, +CHECK (b IS NOT NULL) +); +ERROR HY000: Column 'b' cannot be used in a check constraint 'child_chk_2': needed in a foreign key constraint 'child_ibfk_1' referential action. +CREATE TABLE child ( +b INT, +c INT CHECK (c < 10), +INDEX(b), +FOREIGN KEY (b) REFERENCES parent(a) ON UPDATE SET NULL +); +ALTER TABLE child ADD CONSTRAINT CHECK (b IS NOT NULL); +ERROR HY000: Column 'b' cannot be used in a check constraint 'child_chk_2': needed in a foreign key constraint 'child_ibfk_1' referential action. +ALTER TABLE child DROP FOREIGN KEY child_ibfk_1; +ALTER TABLE child ADD CONSTRAINT FOREIGN KEY (b) REFERENCES parent(a) ON UPDATE SET NULL, +ADD CONSTRAINT CHECK (b IS NOT NULL); +ERROR HY000: Column 'b' cannot be used in a check constraint 'child_chk_2': needed in a foreign key constraint 'child_ibfk_1' referential action. +DROP TABLE child; +CREATE TABLE child ( +b INT, +c INT CHECK (c < 10), +INDEX(b), +FOREIGN KEY (b) REFERENCES parent(a) ON UPDATE CASCADE, +CHECK (b IS NOT NULL) +); +ERROR HY000: Column 'b' cannot be used in a check constraint 'child_chk_2': needed in a foreign key constraint 'child_ibfk_1' referential action. +CREATE TABLE child ( +b INT, +c INT CHECK (c < 10), +INDEX(b), +FOREIGN KEY (b) REFERENCES parent(a) ON UPDATE CASCADE +); +ALTER TABLE child ADD CONSTRAINT CHECK (b IS NOT NULL); +ERROR HY000: Column 'b' cannot be used in a check constraint 'child_chk_2': needed in a foreign key constraint 'child_ibfk_1' referential action. +ALTER TABLE child DROP FOREIGN KEY child_ibfk_1; +ALTER TABLE child ADD CONSTRAINT FOREIGN KEY (b) REFERENCES parent(a) ON UPDATE CASCADE, +ADD CONSTRAINT CHECK (b IS NOT NULL); +ERROR HY000: Column 'b' cannot be used in a check constraint 'child_chk_2': needed in a foreign key constraint 'child_ibfk_1' referential action. +DROP TABLE child; +DROP TABLE parent; +#----------------------------------------------------------------------- +# Test case to verify check constraint with triggers +#----------------------------------------------------------------------- +CREATE TABLE t1(c1 INT, c2 INT CHECK (c2 < 10)); +CREATE TABLE t2(c1 INT, c2 INT); +CREATE TRIGGER before_t2_insert +BEFORE INSERT ON t2 +FOR EACH ROW +BEGIN +INSERT INTO t1 VALUES(NEW.c1,NEW.c2); +END +// +INSERT INTO t2 VALUES(1,20); +ERROR HY000: Check constraint 't1_chk_1' is violated. +SELECT * FROM t1; +c1 c2 +SELECT * FROM t2; +c1 c2 +DROP TRIGGER before_t2_insert; +CREATE TRIGGER after_t2_insert +AFTER INSERT ON t2 +FOR EACH ROW +BEGIN +INSERT INTO t1 VALUES(NEW.c1,NEW.c2); +END +// +INSERT INTO t2 VALUES(1,30); +ERROR HY000: Check constraint 't1_chk_1' is violated. +SELECT * FROM t1; +c1 c2 +SELECT * FROM t2; +c1 c2 +DROP TRIGGER after_t2_insert; +INSERT INTO t2 VALUES(1,5); +INSERT INTO t1 VALUES(1,5); +CREATE TRIGGER before_t2_update +BEFORE UPDATE ON t2 +FOR EACH ROW +BEGIN +UPDATE t1 SET c2=NEW.c2 WHERE c1=NEW.c1; +END +// +UPDATE t2 SET c2=20 WHERE c1=1; +ERROR HY000: Check constraint 't1_chk_1' is violated. +SELECT * FROM t1; +c1 c2 +1 5 +SELECT * FROM t2; +c1 c2 +1 5 +DROP TRIGGER before_t2_update; +CREATE TRIGGER after_t2_update +AFTER UPDATE ON t2 +FOR EACH ROW +BEGIN +UPDATE t1 SET c2=NEW.c2 WHERE c1=NEW.c1; +END +// +UPDATE t2 SET c2=20 WHERE c1=1; +ERROR HY000: Check constraint 't1_chk_1' is violated. +SELECT * FROM t1; +c1 c2 +1 5 +SELECT * FROM t2; +c1 c2 +1 5 +DROP TRIGGER after_t2_update; +DROP TABLE t1,t2; +#----------------------------------------------------------------------- +# Test case to verify check constraint with triggers old style. +#----------------------------------------------------------------------- +CREATE TABLE t1(c1 int CONSTRAINT ck1 CHECK(c1 < 5)); +CREATE PROCEDURE proc1 (IN val1 INT) +BEGIN +IF val1 < 10 THEN +SIGNAL SQLSTATE '45000' + SET MESSAGE_TEXT = 'check constraint on c1 failed'; +END IF; +END +// +CREATE TRIGGER before_t1_insert +BEFORE INSERT ON t1 +FOR EACH ROW +BEGIN +CALL proc1(new.c1); +END +// +INSERT INTO t1 VALUES(20); +ERROR HY000: Check constraint 'ck1' is violated. +INSERT INTO t1 VALUES(9); +ERROR 45000: check constraint on c1 failed +INSERT INTO t1 VALUES(4); +ERROR 45000: check constraint on c1 failed +DROP PROCEDURE proc1; +DROP TRIGGER before_t1_insert; +DROP TABLE t1; +#----------------------------------------------------------------------- +# Test case to verify check constraint with mysqldump +#----------------------------------------------------------------------- +CREATE DATABASE test1; +USE test1; +CREATE TABLE t1 ( +c1 BIT(7) CHECK(c1 < B'1111100') NOT ENFORCED, +c2 BOOLEAN CHECK(c2 > 0) NOT ENFORCED, +c3 TINYINT CHECK(c3 > 10) NOT ENFORCED, +c4 SMALLINT CHECK(c4 > 10) NOT ENFORCED, +c5 MEDIUMINT CHECK(c5 > 10) NOT ENFORCED, +c6 INT CHECK(c6 > 10), +c7 BIGINT CHECK(c7 > 10), +c8 DECIMAL(6,2) CHECK(c8 > 10.1), +c9 FLOAT(6,2) CHECK(c9 > 10.1), +c10 DOUBLE(6,2) CHECK(c10 > 10.1), +c11 CHAR(6) CHECK (c11 IS NULL)); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c1` bit(7) DEFAULT NULL, + `c2` tinyint(1) DEFAULT NULL, + `c3` tinyint(4) DEFAULT NULL, + `c4` smallint(6) DEFAULT NULL, + `c5` mediumint(9) DEFAULT NULL, + `c6` int(11) DEFAULT NULL, + `c7` bigint(20) DEFAULT NULL, + `c8` decimal(6,2) DEFAULT NULL, + `c9` float(6,2) DEFAULT NULL, + `c10` double(6,2) DEFAULT NULL, + `c11` char(6) DEFAULT NULL, + CONSTRAINT `t1_chk_1` CHECK ((`c1` < 0x7c)) /*!80015 NOT ENFORCED */, + CONSTRAINT `t1_chk_10` CHECK ((`c10` > 10.1)), + CONSTRAINT `t1_chk_11` CHECK (isnull(`c11`)), + CONSTRAINT `t1_chk_2` CHECK ((`c2` > 0)) /*!80015 NOT ENFORCED */, + CONSTRAINT `t1_chk_3` CHECK ((`c3` > 10)) /*!80015 NOT ENFORCED */, + CONSTRAINT `t1_chk_4` CHECK ((`c4` > 10)) /*!80015 NOT ENFORCED */, + CONSTRAINT `t1_chk_5` CHECK ((`c5` > 10)) /*!80015 NOT ENFORCED */, + CONSTRAINT `t1_chk_6` CHECK ((`c6` > 10)), + CONSTRAINT `t1_chk_7` CHECK ((`c7` > 10)), + CONSTRAINT `t1_chk_8` CHECK ((`c8` > 10.1)), + CONSTRAINT `t1_chk_9` CHECK ((`c9` > 10.1)) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci +DROP DATABASE test1; +USE test1; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c1` bit(7) DEFAULT NULL, + `c2` tinyint(1) DEFAULT NULL, + `c3` tinyint(4) DEFAULT NULL, + `c4` smallint(6) DEFAULT NULL, + `c5` mediumint(9) DEFAULT NULL, + `c6` int(11) DEFAULT NULL, + `c7` bigint(20) DEFAULT NULL, + `c8` decimal(6,2) DEFAULT NULL, + `c9` float(6,2) DEFAULT NULL, + `c10` double(6,2) DEFAULT NULL, + `c11` char(6) DEFAULT NULL, + CONSTRAINT `t1_chk_1` CHECK ((`c1` < 0x7c)) /*!80015 NOT ENFORCED */, + CONSTRAINT `t1_chk_10` CHECK ((`c10` > 10.1)), + CONSTRAINT `t1_chk_11` CHECK (isnull(`c11`)), + CONSTRAINT `t1_chk_2` CHECK ((`c2` > 0)) /*!80015 NOT ENFORCED */, + CONSTRAINT `t1_chk_3` CHECK ((`c3` > 10)) /*!80015 NOT ENFORCED */, + CONSTRAINT `t1_chk_4` CHECK ((`c4` > 10)) /*!80015 NOT ENFORCED */, + CONSTRAINT `t1_chk_5` CHECK ((`c5` > 10)) /*!80015 NOT ENFORCED */, + CONSTRAINT `t1_chk_6` CHECK ((`c6` > 10)), + CONSTRAINT `t1_chk_7` CHECK ((`c7` > 10)), + CONSTRAINT `t1_chk_8` CHECK ((`c8` > 10.1)), + CONSTRAINT `t1_chk_9` CHECK ((`c9` > 10.1)) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci +INSERT INTO t1(c1,c2,c3,c4,c5,c6,c7,c8,c9,c10) +VALUES(B'1111111',0,5,5,5,1,1,1.2,1.2,1.2); +ERROR HY000: Check constraint 't1_chk_10' is violated. +INSERT INTO t1(c1,c2,c3,c4,c5,c6,c7,c8,c9,c10) +VALUES(B'1111111',0,5,5,5,11,11,10.2,10.2,10.2); +SELECT * FROM t1; +c1 c2 c3 c4 c5 c6 c7 c8 c9 c10 c11 + 0 5 5 5 11 11 10.20 10.20 10.20 NULL +DROP TABLE t1; +DROP DATABASE test1; +#----------------------------------------------------------------------- +# Test case to verify check constraint with mysqlpump +#----------------------------------------------------------------------- +CREATE DATABASE test2; +USE test2; +CREATE TABLE t2 ( +c1 BIT(7) CHECK(c1 < B'1111100'), +c2 BOOLEAN CHECK(c2 > 0), +c3 TINYINT CHECK(c3 > 10), +c4 SMALLINT CHECK(c4 > 10), +c5 MEDIUMINT CHECK(c5 > 10), +c6 INT CHECK(c6 > 10) NOT ENFORCED, +c7 BIGINT CHECK(c7 > 10) NOT ENFORCED, +c8 DECIMAL(6,2) CHECK(c8 > 10.1) NOT ENFORCED, +c9 FLOAT(6,2) CHECK(c9 > 10.1) NOT ENFORCED, +c10 DOUBLE(6,2) CHECK(c10 > 10.1) NOT ENFORCED); +SHOW CREATE TABLE t2; +Table Create Table +t2 CREATE TABLE `t2` ( + `c1` bit(7) DEFAULT NULL, + `c2` tinyint(1) DEFAULT NULL, + `c3` tinyint(4) DEFAULT NULL, + `c4` smallint(6) DEFAULT NULL, + `c5` mediumint(9) DEFAULT NULL, + `c6` int(11) DEFAULT NULL, + `c7` bigint(20) DEFAULT NULL, + `c8` decimal(6,2) DEFAULT NULL, + `c9` float(6,2) DEFAULT NULL, + `c10` double(6,2) DEFAULT NULL, + CONSTRAINT `t2_chk_1` CHECK ((`c1` < 0x7c)), + CONSTRAINT `t2_chk_10` CHECK ((`c10` > 10.1)) /*!80015 NOT ENFORCED */, + CONSTRAINT `t2_chk_2` CHECK ((`c2` > 0)), + CONSTRAINT `t2_chk_3` CHECK ((`c3` > 10)), + CONSTRAINT `t2_chk_4` CHECK ((`c4` > 10)), + CONSTRAINT `t2_chk_5` CHECK ((`c5` > 10)), + CONSTRAINT `t2_chk_6` CHECK ((`c6` > 10)) /*!80015 NOT ENFORCED */, + CONSTRAINT `t2_chk_7` CHECK ((`c7` > 10)) /*!80015 NOT ENFORCED */, + CONSTRAINT `t2_chk_8` CHECK ((`c8` > 10.1)) /*!80015 NOT ENFORCED */, + CONSTRAINT `t2_chk_9` CHECK ((`c9` > 10.1)) /*!80015 NOT ENFORCED */ +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci +DROP DATABASE test2; +USE test2; +SHOW CREATE TABLE t2; +Table Create Table +t2 CREATE TABLE `t2` ( + `c1` bit(7) DEFAULT NULL, + `c2` tinyint(1) DEFAULT NULL, + `c3` tinyint(4) DEFAULT NULL, + `c4` smallint(6) DEFAULT NULL, + `c5` mediumint(9) DEFAULT NULL, + `c6` int(11) DEFAULT NULL, + `c7` bigint(20) DEFAULT NULL, + `c8` decimal(6,2) DEFAULT NULL, + `c9` float(6,2) DEFAULT NULL, + `c10` double(6,2) DEFAULT NULL, + CONSTRAINT `t2_chk_1` CHECK ((`c1` < 0x7c)), + CONSTRAINT `t2_chk_10` CHECK ((`c10` > 10.1)) /*!80015 NOT ENFORCED */, + CONSTRAINT `t2_chk_2` CHECK ((`c2` > 0)), + CONSTRAINT `t2_chk_3` CHECK ((`c3` > 10)), + CONSTRAINT `t2_chk_4` CHECK ((`c4` > 10)), + CONSTRAINT `t2_chk_5` CHECK ((`c5` > 10)), + CONSTRAINT `t2_chk_6` CHECK ((`c6` > 10)) /*!80015 NOT ENFORCED */, + CONSTRAINT `t2_chk_7` CHECK ((`c7` > 10)) /*!80015 NOT ENFORCED */, + CONSTRAINT `t2_chk_8` CHECK ((`c8` > 10.1)) /*!80015 NOT ENFORCED */, + CONSTRAINT `t2_chk_9` CHECK ((`c9` > 10.1)) /*!80015 NOT ENFORCED */ +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci +INSERT INTO t2(c1,c2,c3,c4,c5,c6,c7,c8,c9,c10) +VALUES(B'1111000',0,10,10,10,5,5,9.1,9.1,9.1); +ERROR HY000: Check constraint 't2_chk_2' is violated. +INSERT INTO t2(c1,c2,c3,c4,c5,c6,c7,c8,c9,c10) +VALUES(B'1111000',1,11,11,11,5,5,9.1,9.1,9.1); +SELECT * FROM t2; +c1 c2 c3 c4 c5 c6 c7 c8 c9 c10 +x 1 11 11 11 5 5 9.10 9.10 9.10 +DROP TABLE t2; +DROP DATABASE test2; +USE test; +#----------------------------------------------------------------------- +# Test case to verify check constraint with PREPARE statement +#----------------------------------------------------------------------- +CREATE TABLE t1(c1 INT CHECK(c1 > 10)); +PREPARE stmt1 FROM 'INSERT INTO t1 VALUES(1)'; +EXECUTE stmt1; +ERROR HY000: Check constraint 't1_chk_1' is violated. +DEALLOCATE PREPARE stmt1; +PREPARE stmt2 FROM 'INSERT INTO t1 VALUES(20)'; +EXECUTE stmt2; +DEALLOCATE PREPARE stmt2; +SELECT * FROM t1; +c1 +20 +DROP TABLE t1; +#----------------------------------------------------------------------- +# Test case to verify check constraint behaviour inside transaction +#----------------------------------------------------------------------- +CREATE TABLE t1(c1 INT); +CREATE TABLE t2(c1 INT CHECK(c1 > 10)); +SET AUTOCOMMIT = OFF; +START TRANSACTION; +INSERT INTO t1 VALUES(1); +INSERT INTO t2 VALUES(1); +ERROR HY000: Check constraint 't2_chk_1' is violated. +ROLLBACK; +SELECT * FROM t1; +c1 +SELECT * FROM t2; +c1 +START TRANSACTION; +ALTER TABLE t1 ADD CONSTRAINT CHECK (C1 > 10); +COMMIT; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c1` int(11) DEFAULT NULL, + CONSTRAINT `t1_chk_1` CHECK ((`C1` > 10)) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci +SET AUTOCOMMIT = ON; +DROP TABLE t1,t2; +#------------------------------------------------------------------------ +# Test case to verify check constraints with Partition table. +#------------------------------------------------------------------------ +# check constraint with range partition +CREATE TABLE t1( +d DATE NOT NULL CHECK(YEAR(d) > '1950') +) +PARTITION BY RANGE( YEAR(d) ) ( +PARTITION p0 VALUES LESS THAN (1960), +PARTITION p1 VALUES LESS THAN (1970), +PARTITION p2 VALUES LESS THAN (1980), +PARTITION p3 VALUES LESS THAN (1990) +); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `d` date NOT NULL, + CONSTRAINT `t1_chk_1` CHECK ((year(`d`) > _utf8mb4'1950')) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci +/*!50100 PARTITION BY RANGE (year(`d`)) +(PARTITION p0 VALUES LESS THAN (1960) ENGINE = InnoDB, + PARTITION p1 VALUES LESS THAN (1970) ENGINE = InnoDB, + PARTITION p2 VALUES LESS THAN (1980) ENGINE = InnoDB, + PARTITION p3 VALUES LESS THAN (1990) ENGINE = InnoDB) */ +INSERT INTO t1 VALUES('1940-01-01'); +ERROR HY000: Check constraint 't1_chk_1' is violated. +INSERT INTO t1 VALUES('1960-01-01'); +SELECT * FROM t1; +d +1960-01-01 +DROP TABLE t1; +# check constraint with list partition +CREATE TABLE t1( +id INT NOT NULL CHECK(id BETWEEN 10 AND 50), +name VARCHAR(10) +) +PARTITION BY LIST(id) ( +PARTITION p0 VALUES IN (10,19), +PARTITION p1 VALUES IN (20,29), +PARTITION p2 VALUES IN (30,39), +PARTITION p3 VALUES IN (40,49) +); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `id` int(11) NOT NULL, + `name` varchar(10) DEFAULT NULL, + CONSTRAINT `t1_chk_1` CHECK ((`id` between 10 and 50)) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci +/*!50100 PARTITION BY LIST (`id`) +(PARTITION p0 VALUES IN (10,19) ENGINE = InnoDB, + PARTITION p1 VALUES IN (20,29) ENGINE = InnoDB, + PARTITION p2 VALUES IN (30,39) ENGINE = InnoDB, + PARTITION p3 VALUES IN (40,49) ENGINE = InnoDB) */ +INSERT INTO t1 VALUES(60,'aaa'); +ERROR HY000: Check constraint 't1_chk_1' is violated. +INSERT INTO t1 VALUES(30,'aaa'); +SELECT * FROM t1; +id name +30 aaa +DROP TABLE t1; +# check constraint with hash partition +CREATE TABLE t1(id INT NOT NULL CHECK(id > 10), +name VARCHAR(40) +) +PARTITION BY HASH(id) +PARTITIONS 4; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `id` int(11) NOT NULL, + `name` varchar(40) DEFAULT NULL, + CONSTRAINT `t1_chk_1` CHECK ((`id` > 10)) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci +/*!50100 PARTITION BY HASH (`id`) +PARTITIONS 4 */ +INSERT INTO t1 VALUES(1,'aaa'); +ERROR HY000: Check constraint 't1_chk_1' is violated. +INSERT INTO t1 VALUES(60,'aaa'); +SELECT * FROM t1; +id name +60 aaa +DROP TABLE t1; +# check constraint with key partition +CREATE TABLE t1(id INT PRIMARY KEY NOT NULL CHECK(id > 10), +name VARCHAR(40) +) +PARTITION BY KEY() +PARTITIONS 4; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `id` int(11) NOT NULL, + `name` varchar(40) DEFAULT NULL, + PRIMARY KEY (`id`), + CONSTRAINT `t1_chk_1` CHECK ((`id` > 10)) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci +/*!50100 PARTITION BY KEY () +PARTITIONS 4 */ +INSERT INTO t1 VALUES(1,'aaa'); +ERROR HY000: Check constraint 't1_chk_1' is violated. +INSERT INTO t1 VALUES(60,'aaa'); +SELECT * FROM t1; +id name +60 aaa +DROP TABLE t1; +#----------------------------------------------------------------------- +# Test case to verify alter operations on non-transactional SE table +# with check constraints. +#----------------------------------------------------------------------- +CREATE TABLE t1(f1 INT CHECK (f1 < 10)) ENGINE = myisam; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) DEFAULT NULL, + CONSTRAINT `t1_chk_1` CHECK ((`f1` < 10)) +) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci +ALTER TABLE t1 ADD f2 INT, ALGORITHM=copy; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) DEFAULT NULL, + `f2` int(11) DEFAULT NULL, + CONSTRAINT `t1_chk_1` CHECK ((`f1` < 10)) +) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci +ALTER TABLE t1 ALTER f1 SET DEFAULT 10, ALGORITHM=INPLACE; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) DEFAULT '10', + `f2` int(11) DEFAULT NULL, + CONSTRAINT `t1_chk_1` CHECK ((`f1` < 10)) +) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci +DROP TABLE t1; +#----------------------------------------------------------------------- +# Test case to verify check constraint with Updatable view +#----------------------------------------------------------------------- +CREATE TABLE t1(c1 INT, c2 INT CHECK (c2 < 10)); +CREATE VIEW v1 AS SELECT * FROM t1; +INSERT INTO v1 VALUES(1,20); +ERROR HY000: Check constraint 't1_chk_1' is violated. +INSERT INTO v1 VALUES(1,5); +SELECT * FROM t1; +c1 c2 +1 5 +SELECT * FROM v1; +c1 c2 +1 5 +DROP VIEW v1; +DROP TABLE t1; diff --git a/mysql-test/r/check_constraints_debug.result b/mysql-test/r/check_constraints_debug.result new file mode 100644 index 000000000000..5f578cdb1c1c --- /dev/null +++ b/mysql-test/r/check_constraints_debug.result @@ -0,0 +1,135 @@ +#------------------------------------------------------------------------ +# Test case to verify MDL locking on check constraints with same names +# in the concurrent CREATE TABLE statements. +#------------------------------------------------------------------------ +SET DEBUG_SYNC="after_acquiring_lock_on_check_constraints SIGNAL cc_locked WAIT_FOR continue"; +CREATE TABLE t1 (f1 INT CHECK (f1 < 10), f2 INT, CONSTRAINT t1_ck CHECK(f2 < 10));; +CONNECT con1, localhost, root; +SET DEBUG_SYNC="now WAIT_FOR cc_locked"; +CREATE TABLE t2 (f1 INT, f2 INT, CONSTRAINT t1_ck CHECK(f2 < 10));; +CONNECT con2, localhost, root; +# default connection acquires MDL lock on the check constraint name 'test.t1_ck'. +# con1 waits for the MDL lock on 'test.t1_ck' at this point. +SET DEBUG_SYNC="now SIGNAL continue"; +connection con1; +ERROR HY000: Duplicate check constraint name 't1_ck'. +connection default; +#------------------------------------------------------------------------ +# Test case to verify MDL locking on check constraints names in the +# RENAME TABLE and CREATE TABLE statements. +#------------------------------------------------------------------------ +SET DEBUG_SYNC="after_acquiring_lock_on_check_constraints_for_rename SIGNAL cc_locked WAIT_FOR continue"; +RENAME TABLE t1 to t2;; +connection con1; +SET DEBUG_SYNC="now WAIT_FOR cc_locked"; +CREATE TABLE t3 (f1 INT, CONSTRAINT t1_chk_1 CHECK (f1 < 10));; +connection con2; +# default connection acquires lock on check constraint 'test.t1_chk_1'. +# Concurrent create operation with same name for check constraint in con1 +# waits for the lock. +SET DEBUG_SYNC="now SIGNAL continue"; +connection con1; +connection default; +SHOW CREATE TABLE t2; +Table Create Table +t2 CREATE TABLE `t2` ( + `f1` int(11) DEFAULT NULL, + `f2` int(11) DEFAULT NULL, + CONSTRAINT `t1_ck` CHECK ((`f2` < 10)), + CONSTRAINT `t2_chk_1` CHECK ((`f1` < 10)) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci +SHOW CREATE TABLE t3; +Table Create Table +t3 CREATE TABLE `t3` ( + `f1` int(11) DEFAULT NULL, + CONSTRAINT `t1_chk_1` CHECK ((`f1` < 10)) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci +DROP TABLE t3; +#------------------------------------------------------------------------ +# Test case to verify MDL locking on generated check constraints names +# in the RENAME TABLE using the target table name and CREATE TABLE +# statements. +#------------------------------------------------------------------------ +SET DEBUG_SYNC="after_acquiring_lock_on_check_constraints_for_rename SIGNAL cc_locked WAIT_FOR continue"; +RENAME TABLE t2 to t1;; +connection con1; +SET DEBUG_SYNC="now WAIT_FOR cc_locked"; +CREATE TABLE t3 (f1 INT, CONSTRAINT t1_chk_1 CHECK (f1 < 10));; +connection con2; +# default connection acquires lock on check constraint name('test.t1_chk_1') +# generated using target table t1. +# concurrent con1 waits for the MDL on test.t1_chk_1 in CREATE TABLE +# statement. +SET DEBUG_SYNC="now SIGNAL continue"; +connection con1; +ERROR HY000: Duplicate check constraint name 't1_chk_1'. +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) DEFAULT NULL, + `f2` int(11) DEFAULT NULL, + CONSTRAINT `t1_chk_1` CHECK ((`f1` < 10)), + CONSTRAINT `t1_ck` CHECK ((`f2` < 10)) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci +connection default; +#------------------------------------------------------------------------ +# Test case to verify MDL locking on check constraint name in ALTER +# TABLE statement to RENAME table and CREATE TABLE statements. +#------------------------------------------------------------------------ +SET DEBUG_SYNC="after_acquiring_lock_on_check_constraints_for_rename SIGNAL cc_locked WAIT_FOR continue"; +ALTER TABLE t1 RENAME TO t3;; +connection con1; +SET DEBUG_SYNC="now WAIT_FOR cc_locked"; +CREATE TABLE t2 (f1 INT, CONSTRAINT t1_chk_1 CHECK (f1 < 10));; +connection con2; +# default connection acquires lock on check constraint 'test.t1_chk_1'. +# Concurrent con1 waits for lock on test.t1_chk_1. +SET DEBUG_SYNC="now SIGNAL continue"; +connection con1; +connection default; +SHOW CREATE TABLE t2; +Table Create Table +t2 CREATE TABLE `t2` ( + `f1` int(11) DEFAULT NULL, + CONSTRAINT `t1_chk_1` CHECK ((`f1` < 10)) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci +SHOW CREATE TABLE t3; +Table Create Table +t3 CREATE TABLE `t3` ( + `f1` int(11) DEFAULT NULL, + `f2` int(11) DEFAULT NULL, + CONSTRAINT `t1_ck` CHECK ((`f2` < 10)), + CONSTRAINT `t3_chk_1` CHECK ((`f1` < 10)) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci +DROP TABLE t2; +#------------------------------------------------------------------------ +# Test case to verify MDL locking on generated check constraint name +# using target table name in ALTER TABLE statement to RENAME table and +# CREATE TABLE statements. +#------------------------------------------------------------------------ +SET DEBUG_SYNC="after_acquiring_lock_on_check_constraints_for_rename SIGNAL cc_locked WAIT_FOR continue"; +ALTER TABLE t3 RENAME TO t1;; +connection con1; +SET DEBUG_SYNC="now WAIT_FOR cc_locked"; +CREATE TABLE t2 (f1 INT, CONSTRAINT t1_chk_1 CHECK (f1 < 10));; +connection con2; +# default connection acquires lock on the generated check constraint +# name('test.t1_chk_1') using target table name t1. con1 waits for +# the lock on same name for check constraint. +SET DEBUG_SYNC="now SIGNAL continue"; +connection con1; +ERROR HY000: Duplicate check constraint name 't1_chk_1'. +connection default; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) DEFAULT NULL, + `f2` int(11) DEFAULT NULL, + CONSTRAINT `t1_chk_1` CHECK ((`f1` < 10)), + CONSTRAINT `t1_ck` CHECK ((`f2` < 10)) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci +connection default; +disconnect con1; +disconnect con2; +DROP TABLE t1; +SET DEBUG_SYNC='RESET'; diff --git a/mysql-test/r/constraints.result b/mysql-test/r/constraints.result index 74dc3457e9ce..ae6069b1182a 100644 --- a/mysql-test/r/constraints.result +++ b/mysql-test/r/constraints.result @@ -2,14 +2,17 @@ drop table if exists t1; create table t1 (a int check (a>0)); insert into t1 values (1); insert into t1 values (0); +ERROR HY000: Check constraint 't1_chk_1' is violated. drop table t1; create table t1 (a int, b int, check (a>b)); insert into t1 values (1,0); insert into t1 values (0,1); +ERROR HY000: Check constraint 't1_chk_1' is violated. drop table t1; create table t1 (a int ,b int, constraint abc check (a>b)); insert into t1 values (1,0); insert into t1 values (0,1); +ERROR HY000: Check constraint 'abc' is violated. drop table t1; create table t1 (a int null); insert into t1 values (1),(NULL); diff --git a/mysql-test/r/dd_is_compatibility_ci.result b/mysql-test/r/dd_is_compatibility_ci.result index fdb596ff3af9..2e2962884f00 100644 --- a/mysql-test/r/dd_is_compatibility_ci.result +++ b/mysql-test/r/dd_is_compatibility_ci.result @@ -154,6 +154,7 @@ WHERE table_schema LIKE 'information_schema' SELECT * FROM v1; table_name CHARACTER_SETS +CHECK_CONSTRAINTS COLLATIONS COLLATION_CHARACTER_SET_APPLICABILITY COLUMNS diff --git a/mysql-test/r/dd_is_compatibility_cs.result b/mysql-test/r/dd_is_compatibility_cs.result index 75aadb51636f..dab6f56f9b65 100644 --- a/mysql-test/r/dd_is_compatibility_cs.result +++ b/mysql-test/r/dd_is_compatibility_cs.result @@ -154,6 +154,7 @@ WHERE table_schema LIKE 'information_schema' SELECT * FROM v1; table_name CHARACTER_SETS +CHECK_CONSTRAINTS COLLATIONS COLLATION_CHARACTER_SET_APPLICABILITY COLUMNS diff --git a/mysql-test/r/dd_schema_definition_after_upgrade_debug.result b/mysql-test/r/dd_schema_definition_after_upgrade_debug.result index f1843d3a7784..c45a0a6cf7d3 100644 --- a/mysql-test/r/dd_schema_definition_after_upgrade_debug.result +++ b/mysql-test/r/dd_schema_definition_after_upgrade_debug.result @@ -50,8 +50,8 @@ SET debug = '+d,skip_dd_table_access_check'; ######################################################################## # The number of hidden DD/DDSE tables must be as expected. ######################################################################## -include/assert.inc [There are 31 hidden DD/DDSE tables.] -include/assert.inc [There are 33 DD/DDSE tables in total.] +include/assert.inc [There are 32 hidden DD/DDSE tables.] +include/assert.inc [There are 34 DD/DDSE tables in total.] ######################################################################## # No unexpected DD tables must be present. ######################################################################## @@ -190,8 +190,8 @@ SET debug = '+d,skip_dd_table_access_check'; ######################################################################## # The number of hidden DD/DDSE tables must be as expected. ######################################################################## -include/assert.inc [There are 31 hidden DD/DDSE tables.] -include/assert.inc [There are 33 DD/DDSE tables in total.] +include/assert.inc [There are 32 hidden DD/DDSE tables.] +include/assert.inc [There are 34 DD/DDSE tables in total.] ######################################################################## # No unexpected DD tables must be present. ######################################################################## @@ -332,8 +332,8 @@ SET debug = '+d,skip_dd_table_access_check'; ######################################################################## # The number of hidden DD/DDSE tables must be as expected. ######################################################################## -include/assert.inc [There are 31 hidden DD/DDSE tables.] -include/assert.inc [There are 33 DD/DDSE tables in total.] +include/assert.inc [There are 32 hidden DD/DDSE tables.] +include/assert.inc [There are 34 DD/DDSE tables in total.] ######################################################################## # No unexpected DD tables must be present. ######################################################################## @@ -474,8 +474,8 @@ SET debug = '+d,skip_dd_table_access_check'; ######################################################################## # The number of hidden DD/DDSE tables must be as expected. ######################################################################## -include/assert.inc [There are 31 hidden DD/DDSE tables.] -include/assert.inc [There are 33 DD/DDSE tables in total.] +include/assert.inc [There are 32 hidden DD/DDSE tables.] +include/assert.inc [There are 34 DD/DDSE tables in total.] ######################################################################## # No unexpected DD tables must be present. ######################################################################## diff --git a/mysql-test/r/dd_schema_definition_debug.result b/mysql-test/r/dd_schema_definition_debug.result index ff63eb44968c..25aa30a17455 100644 --- a/mysql-test/r/dd_schema_definition_debug.result +++ b/mysql-test/r/dd_schema_definition_debug.result @@ -141,8 +141,8 @@ SET debug = '+d,skip_dd_table_access_check'; ######################################################################## # The number of hidden DD/DDSE tables must be as expected. ######################################################################## -include/assert.inc [There are 31 hidden DD/DDSE tables.] -include/assert.inc [There are 33 DD/DDSE tables in total.] +include/assert.inc [There are 32 hidden DD/DDSE tables.] +include/assert.inc [There are 34 DD/DDSE tables in total.] ######################################################################## # No unexpected DD tables must be present. ######################################################################## @@ -165,7 +165,7 @@ SET debug = '+d,skip_dd_table_access_check'; ######################################################################## # The actual DD version stored on disk. ######################################################################## -DD_VERSION=80014 +DD_VERSION=80015 ######################################################################## # List the CREATE TABLE statements for the DD tables. # Mask the AUTO INCREMENT counter, which is not @@ -719,5 +719,5 @@ SET debug = '-d,skip_dd_table_access_check'; SET debug = '+d,skip_dd_table_access_check'; include/assert.inc [The group concat max length is sufficient.] CHECK_STATUS -The schema checksum corresponds to DD version 80014. +The schema checksum corresponds to DD version 80015. include/assert.inc [The schema checksum corresponds to a known DD version.] diff --git a/mysql-test/r/dd_upgrade_test.result b/mysql-test/r/dd_upgrade_test.result index 5ec36ebf45ca..4cd8c0d41e95 100644 --- a/mysql-test/r/dd_upgrade_test.result +++ b/mysql-test/r/dd_upgrade_test.result @@ -864,4 +864,35 @@ t_set CREATE TABLE `t_set` ( # Remove copied files # Restart the server with default options. # restart +#----------------------------------------------------------------------- +# WL#929: CHECK Constraint +# Test case to verify upgrade from version before check +# constraint suppport. +#----------------------------------------------------------------------- +# Copy the remote tablespace & DB zip files from suite location to working location. +# Check that the file exists in the working folder. +# Set different paths for --datadir +CREATE TABLE t1 (f1 INT CHECK (f1 < 10)); +# After upgrade CHECK_CONSTRAINTS table should be present and should list +# check constraints. +SELECT * FROM INFORMATION_SCHEMA.CHECK_CONSTRAINTS; +CONSTRAINT_CATALOG CONSTRAINT_SCHEMA CONSTRAINT_NAME CHECK_CLAUSE +def test t1_chk_1 (`f1` < 10) +# After upgrade TABLE_CONSTRAINTS should list check constraints. +SELECT * FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE TABLE_NAME='t1'; +CONSTRAINT_CATALOG CONSTRAINT_SCHEMA CONSTRAINT_NAME TABLE_SCHEMA TABLE_NAME CONSTRAINT_TYPE ENFORCED +def test t1_chk_1 test t1 CHECK YES +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) DEFAULT NULL, + CONSTRAINT `t1_chk_1` CHECK ((`f1` < 10)) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci +INSERT INTO t1 VALUES (100); +ERROR HY000: Check constraint 't1_chk_1' is violated. +DROP TABLE t1; +# Stop the server +# Remove copied files +# Restart the server with default options. +# restart # end of test diff --git a/mysql-test/r/dictionary_tablespace.result b/mysql-test/r/dictionary_tablespace.result index c678d5e8d206..c6ff45286388 100644 --- a/mysql-test/r/dictionary_tablespace.result +++ b/mysql-test/r/dictionary_tablespace.result @@ -14,6 +14,7 @@ mysql.tablespaces ON tables1.tablespace_id = tablespaces.id WHERE tables1.name NOT IN ('ndb_binlog_index') ORDER BY tables1.name; catalogs mysql character_sets mysql +check_constraints mysql collations mysql column_statistics mysql column_type_elements mysql @@ -82,6 +83,7 @@ name NOT IN ('ndb_binlog_index') ORDER BY name ASC; catalogs character_sets +check_constraints collations column_statistics column_type_elements diff --git a/mysql-test/r/group_min_max.result b/mysql-test/r/group_min_max.result index f94742cbab71..0062052a8118 100644 --- a/mysql-test/r/group_min_max.result +++ b/mysql-test/r/group_min_max.result @@ -2527,7 +2527,7 @@ FLUSH STATUS; CREATE TABLE t2 SELECT max(b), a FROM t1 GROUP BY a; SHOW STATUS LIKE 'handler_read__e%'; Variable_name Value -Handler_read_key 23 +Handler_read_key 24 Handler_read_next 2 FLUSH STATUS; SELECT * FROM (SELECT max(b), a FROM t1 GROUP BY a) b; diff --git a/mysql-test/r/import.result b/mysql-test/r/import.result index de6664d543e4..5a8a277e7dfd 100644 --- a/mysql-test/r/import.result +++ b/mysql-test/r/import.result @@ -499,4 +499,18 @@ IMPORT TABLE FROM 't1_*.sdi'; ERROR HY000: Unable to create or change a table without a primary key, when the system variable 'sql_require_primary_key' is set. Add a primary key to the table or unset this variable to avoid this message. Note that tables without a primary key can cause performance problems in row-based replication, so please consult your DBA before changing this setting. SET SESSION sql_require_primary_key= OFF; # Clean SDI files in $EXPORT_DIR +#----------------------------------------------------------------------- +# WL#929 - Check constraint. +# Test case to verify check constraint import from SDI. +#----------------------------------------------------------------------- +CREATE TABLE t1 (f1 INT CHECK (f1 < 10)) ENGINE=MyISAM; +DROP TABLE t1; +IMPORT TABLE FROM 'test/t1*.sdi'; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) DEFAULT NULL, + CONSTRAINT `t1_chk_1` CHECK ((`f1` < 10)) +) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci +DROP TABLE t1; # Remove 'export' folder created at the beginning of test file. diff --git a/mysql-test/r/information_schema_ci.result b/mysql-test/r/information_schema_ci.result index 472003af61e1..7ea7edbae15e 100644 --- a/mysql-test/r/information_schema_ci.result +++ b/mysql-test/r/information_schema_ci.result @@ -61,6 +61,7 @@ table_name COLLATE utf8_general_ci not like 'innodb_%'; select * from v1; c CHARACTER_SETS +CHECK_CONSTRAINTS COLLATIONS COLLATION_CHARACTER_SET_APPLICABILITY COLUMNS @@ -470,11 +471,11 @@ t1 CREATE TABLE `t1` ( ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci select * from information_schema.TABLE_CONSTRAINTS where TABLE_SCHEMA= "test" order by constraint_name; -CONSTRAINT_CATALOG CONSTRAINT_SCHEMA CONSTRAINT_NAME TABLE_SCHEMA TABLE_NAME CONSTRAINT_TYPE -def test constraint_1 test t1 UNIQUE -def test key_1 test t1 UNIQUE -def test key_2 test t1 UNIQUE -def test PRIMARY test t1 PRIMARY KEY +CONSTRAINT_CATALOG CONSTRAINT_SCHEMA CONSTRAINT_NAME TABLE_SCHEMA TABLE_NAME CONSTRAINT_TYPE ENFORCED +def test constraint_1 test t1 UNIQUE YES +def test key_1 test t1 UNIQUE YES +def test key_2 test t1 UNIQUE YES +def test PRIMARY test t1 PRIMARY KEY YES select * from information_schema.key_column_usage where TABLE_SCHEMA= "test" order by constraint_name; CONSTRAINT_CATALOG CONSTRAINT_SCHEMA CONSTRAINT_NAME TABLE_CATALOG TABLE_SCHEMA TABLE_NAME COLUMN_NAME ORDINAL_POSITION POSITION_IN_UNIQUE_CONSTRAINT REFERENCED_TABLE_SCHEMA REFERENCED_TABLE_NAME REFERENCED_COLUMN_NAME @@ -599,7 +600,7 @@ show index from vo; Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment Visible Expression select * from information_schema.TABLE_CONSTRAINTS where TABLE_NAME= "vo"; -CONSTRAINT_CATALOG CONSTRAINT_SCHEMA CONSTRAINT_NAME TABLE_SCHEMA TABLE_NAME CONSTRAINT_TYPE +CONSTRAINT_CATALOG CONSTRAINT_SCHEMA CONSTRAINT_NAME TABLE_SCHEMA TABLE_NAME CONSTRAINT_TYPE ENFORCED select * from information_schema.key_column_usage where TABLE_NAME= "vo"; CONSTRAINT_CATALOG CONSTRAINT_SCHEMA CONSTRAINT_NAME TABLE_CATALOG TABLE_SCHEMA TABLE_NAME COLUMN_NAME ORDINAL_POSITION POSITION_IN_UNIQUE_CONSTRAINT REFERENCED_TABLE_SCHEMA REFERENCED_TABLE_NAME REFERENCED_COLUMN_NAME @@ -610,7 +611,7 @@ where table_schema='information_schema' order by table_name collate utf8_general_ci limit 2; TABLE_NAME TABLE_TYPE ENGINE CHARACTER_SETS SYSTEM VIEW NULL -COLLATIONS SYSTEM VIEW NULL +CHECK_CONSTRAINTS SYSTEM VIEW NULL show tables from information_schema like "T%"; Tables_in_information_schema (T%) TABLES @@ -761,6 +762,7 @@ select table_schema, table_name, column_name from information_schema.columns where table_schema not in ('performance_schema', 'sys', 'mysql') and data_type = 'longtext' order by table_name, column_name; TABLE_SCHEMA TABLE_NAME COLUMN_NAME +information_schema CHECK_CONSTRAINTS CHECK_CLAUSE information_schema COLUMNS DATA_TYPE information_schema COLUMNS GENERATION_EXPRESSION information_schema EVENTS EVENT_DEFINITION @@ -846,7 +848,7 @@ table_schema IN ('mysql', 'information_schema', 'test', 'mysqltest') AND table_name not like 'ndb%' AND table_name COLLATE utf8_general_ci not like 'innodb_%' GROUP BY TABLE_SCHEMA; TABLE_SCHEMA count(*) -information_schema 35 +information_schema 36 mysql 31 create table t1 (i int, j int); create trigger trg1 before insert on t1 for each row @@ -1288,6 +1290,7 @@ and t.table_name not like 'INNODB_%' group by t.table_name order by num1, t.table_name COLLATE utf8_general_ci; TABLE_NAME group_concat(t.table_schema, '.', t.table_name) num1 CHARACTER_SETS information_schema.CHARACTER_SETS 1 +CHECK_CONSTRAINTS information_schema.CHECK_CONSTRAINTS 1 COLLATIONS information_schema.COLLATIONS 1 COLUMNS information_schema.COLUMNS 1 COLUMN_PRIVILEGES information_schema.COLUMN_PRIVILEGES 1 @@ -1508,9 +1511,9 @@ TABLE_CATALOG TABLE_SCHEMA TABLE_NAME TABLE_TYPE ENGINE VERSION ROW_FORMAT TABLE select * from information_schema.tables where table_name = NULL; TABLE_CATALOG TABLE_SCHEMA TABLE_NAME TABLE_TYPE ENGINE VERSION ROW_FORMAT TABLE_ROWS AVG_ROW_LENGTH DATA_LENGTH MAX_DATA_LENGTH INDEX_LENGTH DATA_FREE AUTO_INCREMENT CREATE_TIME UPDATE_TIME CHECK_TIME TABLE_COLLATION CHECKSUM CREATE_OPTIONS TABLE_COMMENT select * from `information_schema`.`TABLE_CONSTRAINTS` where `TABLE_SCHEMA` = NULL; -CONSTRAINT_CATALOG CONSTRAINT_SCHEMA CONSTRAINT_NAME TABLE_SCHEMA TABLE_NAME CONSTRAINT_TYPE +CONSTRAINT_CATALOG CONSTRAINT_SCHEMA CONSTRAINT_NAME TABLE_SCHEMA TABLE_NAME CONSTRAINT_TYPE ENFORCED select * from `information_schema`.`TABLE_CONSTRAINTS` where `TABLE_NAME` = NULL; -CONSTRAINT_CATALOG CONSTRAINT_SCHEMA CONSTRAINT_NAME TABLE_SCHEMA TABLE_NAME CONSTRAINT_TYPE +CONSTRAINT_CATALOG CONSTRAINT_SCHEMA CONSTRAINT_NAME TABLE_SCHEMA TABLE_NAME CONSTRAINT_TYPE ENFORCED select * from `information_schema`.`TRIGGERS` where `EVENT_OBJECT_SCHEMA` = NULL; TRIGGER_CATALOG TRIGGER_SCHEMA TRIGGER_NAME EVENT_MANIPULATION EVENT_OBJECT_CATALOG EVENT_OBJECT_SCHEMA EVENT_OBJECT_TABLE ACTION_ORDER ACTION_CONDITION ACTION_STATEMENT ACTION_ORIENTATION ACTION_TIMING ACTION_REFERENCE_OLD_TABLE ACTION_REFERENCE_NEW_TABLE ACTION_REFERENCE_OLD_ROW ACTION_REFERENCE_NEW_ROW CREATED SQL_MODE DEFINER CHARACTER_SET_CLIENT COLLATION_CONNECTION DATABASE_COLLATION select * from `information_schema`.`TRIGGERS` where `EVENT_OBJECT_TABLE` = NULL; @@ -2420,6 +2423,7 @@ AND t.table_name NOT LIKE 'ndb%' c1.column_name COLLATE utf8_general_ci; TABLE_NAME COLUMN_NAME CHARACTER_SETS CHARACTER_SET_NAME +CHECK_CONSTRAINTS CONSTRAINT_SCHEMA COLLATIONS COLLATION_NAME COLLATION_CHARACTER_SET_APPLICABILITY COLLATION_NAME COLUMNS TABLE_SCHEMA @@ -2474,6 +2478,7 @@ AND t.table_name NOT LIKE 'ndb%' c1.column_name COLLATE utf8_general_ci; TABLE_NAME COLUMN_NAME CHARACTER_SETS CHARACTER_SET_NAME +CHECK_CONSTRAINTS CONSTRAINT_SCHEMA COLLATIONS COLLATION_NAME COLLATION_CHARACTER_SET_APPLICABILITY COLLATION_NAME COLUMNS TABLE_SCHEMA diff --git a/mysql-test/r/information_schema_cs.result b/mysql-test/r/information_schema_cs.result index 241835b7379f..cab63a3fb4f2 100644 --- a/mysql-test/r/information_schema_cs.result +++ b/mysql-test/r/information_schema_cs.result @@ -61,6 +61,7 @@ table_name COLLATE utf8_general_ci not like 'innodb_%'; select * from v1; c CHARACTER_SETS +CHECK_CONSTRAINTS COLLATIONS COLLATION_CHARACTER_SET_APPLICABILITY COLUMNS @@ -470,11 +471,11 @@ t1 CREATE TABLE `t1` ( ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci select * from information_schema.TABLE_CONSTRAINTS where TABLE_SCHEMA= "test" order by constraint_name; -CONSTRAINT_CATALOG CONSTRAINT_SCHEMA CONSTRAINT_NAME TABLE_SCHEMA TABLE_NAME CONSTRAINT_TYPE -def test constraint_1 test t1 UNIQUE -def test key_1 test t1 UNIQUE -def test key_2 test t1 UNIQUE -def test PRIMARY test t1 PRIMARY KEY +CONSTRAINT_CATALOG CONSTRAINT_SCHEMA CONSTRAINT_NAME TABLE_SCHEMA TABLE_NAME CONSTRAINT_TYPE ENFORCED +def test constraint_1 test t1 UNIQUE YES +def test key_1 test t1 UNIQUE YES +def test key_2 test t1 UNIQUE YES +def test PRIMARY test t1 PRIMARY KEY YES select * from information_schema.key_column_usage where TABLE_SCHEMA= "test" order by constraint_name; CONSTRAINT_CATALOG CONSTRAINT_SCHEMA CONSTRAINT_NAME TABLE_CATALOG TABLE_SCHEMA TABLE_NAME COLUMN_NAME ORDINAL_POSITION POSITION_IN_UNIQUE_CONSTRAINT REFERENCED_TABLE_SCHEMA REFERENCED_TABLE_NAME REFERENCED_COLUMN_NAME @@ -599,7 +600,7 @@ show index from vo; Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment Visible Expression select * from information_schema.TABLE_CONSTRAINTS where TABLE_NAME= "vo"; -CONSTRAINT_CATALOG CONSTRAINT_SCHEMA CONSTRAINT_NAME TABLE_SCHEMA TABLE_NAME CONSTRAINT_TYPE +CONSTRAINT_CATALOG CONSTRAINT_SCHEMA CONSTRAINT_NAME TABLE_SCHEMA TABLE_NAME CONSTRAINT_TYPE ENFORCED select * from information_schema.key_column_usage where TABLE_NAME= "vo"; CONSTRAINT_CATALOG CONSTRAINT_SCHEMA CONSTRAINT_NAME TABLE_CATALOG TABLE_SCHEMA TABLE_NAME COLUMN_NAME ORDINAL_POSITION POSITION_IN_UNIQUE_CONSTRAINT REFERENCED_TABLE_SCHEMA REFERENCED_TABLE_NAME REFERENCED_COLUMN_NAME @@ -610,7 +611,7 @@ where table_schema='information_schema' order by table_name collate utf8_general_ci limit 2; TABLE_NAME TABLE_TYPE ENGINE CHARACTER_SETS SYSTEM VIEW NULL -COLLATIONS SYSTEM VIEW NULL +CHECK_CONSTRAINTS SYSTEM VIEW NULL show tables from information_schema like "T%"; Tables_in_information_schema (T%) TABLES @@ -761,6 +762,7 @@ select table_schema, table_name, column_name from information_schema.columns where table_schema not in ('performance_schema', 'sys', 'mysql') and data_type = 'longtext' order by table_name, column_name; TABLE_SCHEMA TABLE_NAME COLUMN_NAME +information_schema CHECK_CONSTRAINTS CHECK_CLAUSE information_schema COLUMNS DATA_TYPE information_schema COLUMNS GENERATION_EXPRESSION information_schema EVENTS EVENT_DEFINITION @@ -846,7 +848,7 @@ table_schema IN ('mysql', 'information_schema', 'test', 'mysqltest') AND table_name not like 'ndb%' AND table_name COLLATE utf8_general_ci not like 'innodb_%' GROUP BY TABLE_SCHEMA; TABLE_SCHEMA count(*) -information_schema 35 +information_schema 36 mysql 31 create table t1 (i int, j int); create trigger trg1 before insert on t1 for each row @@ -1288,6 +1290,7 @@ and t.table_name not like 'INNODB_%' group by t.table_name order by num1, t.table_name COLLATE utf8_general_ci; TABLE_NAME group_concat(t.table_schema, '.', t.table_name) num1 CHARACTER_SETS information_schema.CHARACTER_SETS 1 +CHECK_CONSTRAINTS information_schema.CHECK_CONSTRAINTS 1 COLLATIONS information_schema.COLLATIONS 1 COLUMNS information_schema.COLUMNS 1 COLUMN_PRIVILEGES information_schema.COLUMN_PRIVILEGES 1 @@ -1508,9 +1511,9 @@ TABLE_CATALOG TABLE_SCHEMA TABLE_NAME TABLE_TYPE ENGINE VERSION ROW_FORMAT TABLE select * from information_schema.tables where table_name = NULL; TABLE_CATALOG TABLE_SCHEMA TABLE_NAME TABLE_TYPE ENGINE VERSION ROW_FORMAT TABLE_ROWS AVG_ROW_LENGTH DATA_LENGTH MAX_DATA_LENGTH INDEX_LENGTH DATA_FREE AUTO_INCREMENT CREATE_TIME UPDATE_TIME CHECK_TIME TABLE_COLLATION CHECKSUM CREATE_OPTIONS TABLE_COMMENT select * from `information_schema`.`TABLE_CONSTRAINTS` where `TABLE_SCHEMA` = NULL; -CONSTRAINT_CATALOG CONSTRAINT_SCHEMA CONSTRAINT_NAME TABLE_SCHEMA TABLE_NAME CONSTRAINT_TYPE +CONSTRAINT_CATALOG CONSTRAINT_SCHEMA CONSTRAINT_NAME TABLE_SCHEMA TABLE_NAME CONSTRAINT_TYPE ENFORCED select * from `information_schema`.`TABLE_CONSTRAINTS` where `TABLE_NAME` = NULL; -CONSTRAINT_CATALOG CONSTRAINT_SCHEMA CONSTRAINT_NAME TABLE_SCHEMA TABLE_NAME CONSTRAINT_TYPE +CONSTRAINT_CATALOG CONSTRAINT_SCHEMA CONSTRAINT_NAME TABLE_SCHEMA TABLE_NAME CONSTRAINT_TYPE ENFORCED select * from `information_schema`.`TRIGGERS` where `EVENT_OBJECT_SCHEMA` = NULL; TRIGGER_CATALOG TRIGGER_SCHEMA TRIGGER_NAME EVENT_MANIPULATION EVENT_OBJECT_CATALOG EVENT_OBJECT_SCHEMA EVENT_OBJECT_TABLE ACTION_ORDER ACTION_CONDITION ACTION_STATEMENT ACTION_ORIENTATION ACTION_TIMING ACTION_REFERENCE_OLD_TABLE ACTION_REFERENCE_NEW_TABLE ACTION_REFERENCE_OLD_ROW ACTION_REFERENCE_NEW_ROW CREATED SQL_MODE DEFINER CHARACTER_SET_CLIENT COLLATION_CONNECTION DATABASE_COLLATION select * from `information_schema`.`TRIGGERS` where `EVENT_OBJECT_TABLE` = NULL; @@ -2420,6 +2423,7 @@ AND t.table_name NOT LIKE 'ndb%' c1.column_name COLLATE utf8_general_ci; TABLE_NAME COLUMN_NAME CHARACTER_SETS CHARACTER_SET_NAME +CHECK_CONSTRAINTS CONSTRAINT_SCHEMA COLLATIONS COLLATION_NAME COLLATION_CHARACTER_SET_APPLICABILITY COLLATION_NAME COLUMNS TABLE_SCHEMA @@ -2474,6 +2478,7 @@ AND t.table_name NOT LIKE 'ndb%' c1.column_name COLLATE utf8_general_ci; TABLE_NAME COLUMN_NAME CHARACTER_SETS CHARACTER_SET_NAME +CHECK_CONSTRAINTS CONSTRAINT_SCHEMA COLLATIONS COLLATION_NAME COLLATION_CHARACTER_SET_APPLICABILITY COLLATION_NAME COLUMNS TABLE_SCHEMA diff --git a/mysql-test/r/information_schema_db.result b/mysql-test/r/information_schema_db.result index 2088bd57ea55..8110a33f203d 100644 --- a/mysql-test/r/information_schema_db.result +++ b/mysql-test/r/information_schema_db.result @@ -7,6 +7,7 @@ use INFORMATION_SCHEMA; show tables where Tables_in_information_schema NOT LIKE 'INNODB%' and Tables_in_information_schema NOT LIKE 'ndb%'; Tables_in_information_schema CHARACTER_SETS +CHECK_CONSTRAINTS COLLATIONS COLLATION_CHARACTER_SET_APPLICABILITY COLUMNS diff --git a/mysql-test/r/information_schema_inno.result b/mysql-test/r/information_schema_inno.result index 2301f6435271..cd4dd5bfd9d7 100644 --- a/mysql-test/r/information_schema_inno.result +++ b/mysql-test/r/information_schema_inno.result @@ -7,13 +7,13 @@ CREATE TABLE t3 (id INT PRIMARY KEY, t2_id INT, INDEX par_ind (t2_id), FOREIGN KEY (id, t2_id) REFERENCES t2(t1_id, id) ON DELETE CASCADE) ENGINE=INNODB; select * from information_schema.TABLE_CONSTRAINTS where TABLE_SCHEMA= "test" order by TABLE_SCHEMA, TABLE_NAME, CONSTRAINT_NAME; -CONSTRAINT_CATALOG CONSTRAINT_SCHEMA CONSTRAINT_NAME TABLE_SCHEMA TABLE_NAME CONSTRAINT_TYPE -def test PRIMARY test t1 PRIMARY KEY -def test PRIMARY test t2 PRIMARY KEY -def test t2_ibfk_1 test t2 FOREIGN KEY -def test t2_ibfk_2 test t2 FOREIGN KEY -def test PRIMARY test t3 PRIMARY KEY -def test t3_ibfk_1 test t3 FOREIGN KEY +CONSTRAINT_CATALOG CONSTRAINT_SCHEMA CONSTRAINT_NAME TABLE_SCHEMA TABLE_NAME CONSTRAINT_TYPE ENFORCED +def test PRIMARY test t1 PRIMARY KEY YES +def test PRIMARY test t2 PRIMARY KEY YES +def test t2_ibfk_1 test t2 FOREIGN KEY YES +def test t2_ibfk_2 test t2 FOREIGN KEY YES +def test PRIMARY test t3 PRIMARY KEY YES +def test t3_ibfk_1 test t3 FOREIGN KEY YES select * from information_schema.KEY_COLUMN_USAGE where TABLE_SCHEMA= "test" order by TABLE_SCHEMA, TABLE_NAME, CONSTRAINT_NAME, COLUMN_NAME; CONSTRAINT_CATALOG CONSTRAINT_SCHEMA CONSTRAINT_NAME TABLE_CATALOG TABLE_SCHEMA TABLE_NAME COLUMN_NAME ORDINAL_POSITION POSITION_IN_UNIQUE_CONSTRAINT REFERENCED_TABLE_SCHEMA REFERENCED_TABLE_NAME REFERENCED_COLUMN_NAME diff --git a/mysql-test/r/information_schema_keywords.result b/mysql-test/r/information_schema_keywords.result index 6372616f9073..85831b7cc045 100644 --- a/mysql-test/r/information_schema_keywords.result +++ b/mysql-test/r/information_schema_keywords.result @@ -156,6 +156,7 @@ ENCLOSED 1 ENCRYPTION 0 END 0 ENDS 0 +ENFORCED 0 ENGINE 0 ENGINES 0 ENUM 0 diff --git a/mysql-test/r/mysqlshow_ci.result b/mysql-test/r/mysqlshow_ci.result index 0f04465635a6..c85882812400 100644 --- a/mysql-test/r/mysqlshow_ci.result +++ b/mysql-test/r/mysqlshow_ci.result @@ -80,6 +80,7 @@ Database: information_schema | Tables | +---------------------------------------+ | CHARACTER_SETS | +| CHECK_CONSTRAINTS | | COLLATION_CHARACTER_SET_APPLICABILITY | | COLLATIONS | | COLUMN_PRIVILEGES | @@ -151,6 +152,7 @@ Database: INFORMATION_SCHEMA | Tables | +---------------------------------------+ | CHARACTER_SETS | +| CHECK_CONSTRAINTS | | COLLATION_CHARACTER_SET_APPLICABILITY | | COLLATIONS | | COLUMN_PRIVILEGES | diff --git a/mysql-test/r/mysqlshow_cs.result b/mysql-test/r/mysqlshow_cs.result index 2b825a151511..1c470c184236 100644 --- a/mysql-test/r/mysqlshow_cs.result +++ b/mysql-test/r/mysqlshow_cs.result @@ -80,6 +80,7 @@ Database: information_schema | Tables | +---------------------------------------+ | CHARACTER_SETS | +| CHECK_CONSTRAINTS | | COLLATIONS | | COLLATION_CHARACTER_SET_APPLICABILITY | | COLUMNS | @@ -151,6 +152,7 @@ Database: INFORMATION_SCHEMA | Tables | +---------------------------------------+ | CHARACTER_SETS | +| CHECK_CONSTRAINTS | | COLLATIONS | | COLLATION_CHARACTER_SET_APPLICABILITY | | COLUMNS | diff --git a/mysql-test/r/partition_locking.result b/mysql-test/r/partition_locking.result index 18a216ffb168..2f2f15483009 100644 --- a/mysql-test/r/partition_locking.result +++ b/mysql-test/r/partition_locking.result @@ -2748,7 +2748,7 @@ FLUSH STATUS; CREATE VIEW v1_25 AS SELECT a, b FROM t1 PARTITION (p2, p5); VARIABLE_NAME VARIABLE_VALUE Handler_commit 7 -Handler_external_lock 68 +Handler_external_lock 72 Handler_prepare 4 Handler_read_key 3 Handler_write 4 @@ -2757,7 +2757,7 @@ FLUSH STATUS; CREATE VIEW v1_25_check AS SELECT a, b FROM t1 PARTITION (p2, p5) t1_alias WITH CHECK OPTION; VARIABLE_NAME VARIABLE_VALUE Handler_commit 7 -Handler_external_lock 68 +Handler_external_lock 72 Handler_prepare 4 Handler_read_key 3 Handler_write 4 @@ -2766,7 +2766,7 @@ FLUSH STATUS; CREATE VIEW v1_9 AS SELECT a, b FROM t1 WHERE a = 9; VARIABLE_NAME VARIABLE_VALUE Handler_commit 7 -Handler_external_lock 68 +Handler_external_lock 72 Handler_prepare 4 Handler_read_key 3 Handler_write 4 @@ -2775,7 +2775,7 @@ FLUSH STATUS; CREATE VIEW v1_9_check AS SELECT a, b FROM t1 WHERE a = 9 WITH CHECK OPTION; VARIABLE_NAME VARIABLE_VALUE Handler_commit 7 -Handler_external_lock 68 +Handler_external_lock 72 Handler_prepare 4 Handler_read_key 3 Handler_write 4 @@ -2784,7 +2784,7 @@ FLUSH STATUS; CREATE VIEW v1_all AS SELECT a, b FROM t1; VARIABLE_NAME VARIABLE_VALUE Handler_commit 7 -Handler_external_lock 68 +Handler_external_lock 72 Handler_prepare 4 Handler_read_key 3 Handler_write 4 @@ -2975,7 +2975,7 @@ FLUSH STATUS; CREATE TABLE t3 SELECT a, b FROM t1 WHERE a IN (0, 1, 13, 113, 26); VARIABLE_NAME VARIABLE_VALUE Handler_commit 12 -Handler_external_lock 150 +Handler_external_lock 160 Handler_prepare 4 Handler_read_first 3 Handler_read_key 24 @@ -2993,7 +2993,7 @@ FLUSH STATUS; CREATE TABLE t3 SELECT a, b FROM t1 WHERE b LIKE 'First%'; VARIABLE_NAME VARIABLE_VALUE Handler_commit 12 -Handler_external_lock 150 +Handler_external_lock 160 Handler_prepare 4 Handler_read_key 34 Handler_read_next 5 @@ -4645,7 +4645,7 @@ FLUSH STATUS; ALTER TABLE t2 EXCHANGE PARTITION p1 WITH TABLE t1; VARIABLE_NAME VARIABLE_VALUE Handler_commit 20 -Handler_external_lock 128 +Handler_external_lock 132 Handler_prepare 4 Handler_read_first 1 Handler_read_key 66 @@ -4862,7 +4862,7 @@ FLUSH STATUS; CREATE TABLE t2 SELECT * FROM t1 PARTITION (p1, p2); VARIABLE_NAME VARIABLE_VALUE Handler_commit 11 -Handler_external_lock 148 +Handler_external_lock 158 Handler_prepare 4 Handler_read_first 2 Handler_read_key 20 @@ -4880,7 +4880,7 @@ FLUSH STATUS; CREATE TABLE t2 SELECT * FROM t1 WHERE a IN (1, 3, 9); VARIABLE_NAME VARIABLE_VALUE Handler_commit 11 -Handler_external_lock 148 +Handler_external_lock 158 Handler_prepare 4 Handler_read_first 2 Handler_read_key 20 diff --git a/mysql-test/r/partition_locking_ps_protocol.result b/mysql-test/r/partition_locking_ps_protocol.result index a5ea3513aa01..22d256f0edb2 100644 --- a/mysql-test/r/partition_locking_ps_protocol.result +++ b/mysql-test/r/partition_locking_ps_protocol.result @@ -16,7 +16,7 @@ FLUSH STATUS; CREATE TABLE t2 SELECT a, b FROM t1 WHERE a in (0, 1, 13, 113); VARIABLE_NAME VARIABLE_VALUE Handler_commit 13 -Handler_external_lock 179 +Handler_external_lock 191 Handler_prepare 4 Handler_read_first 3 Handler_read_key 25 @@ -33,7 +33,7 @@ FLUSH STATUS; CREATE TABLE t2 SELECT a, b FROM t1 WHERE b LIKE 'First%'; VARIABLE_NAME VARIABLE_VALUE Handler_commit 13 -Handler_external_lock 179 +Handler_external_lock 191 Handler_prepare 4 Handler_read_key 35 Handler_read_next 5 @@ -54,7 +54,7 @@ FLUSH STATUS; CREATE TABLE t2 SELECT * FROM t1 PARTITION (p1, p2); VARIABLE_NAME VARIABLE_VALUE Handler_commit 12 -Handler_external_lock 177 +Handler_external_lock 189 Handler_prepare 4 Handler_read_first 2 Handler_read_key 21 @@ -72,7 +72,7 @@ FLUSH STATUS; CREATE TABLE t2 SELECT * FROM t1 WHERE a IN (1, 3, 9); VARIABLE_NAME VARIABLE_VALUE Handler_commit 12 -Handler_external_lock 177 +Handler_external_lock 189 Handler_prepare 4 Handler_read_first 2 Handler_read_key 21 diff --git a/mysql-test/r/show_check_ci.result b/mysql-test/r/show_check_ci.result index 5758f2ab00d8..c14c10f77a28 100644 --- a/mysql-test/r/show_check_ci.result +++ b/mysql-test/r/show_check_ci.result @@ -272,6 +272,7 @@ create table t1(n int); insert into t1 values (1); show open tables; Database Table In_use Name_locked +mysql check_constraints 0 0 mysql column_statistics 0 0 mysql column_type_elements 0 0 mysql columns 0 0 @@ -1738,8 +1739,8 @@ TABLE_SCHEMA TABLE_NAME INDEX_NAME COLUMN_NAME test t1 c2d c2 test t1 PRIMARY c1 SELECT * FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE table_name='t1'; -CONSTRAINT_CATALOG CONSTRAINT_SCHEMA CONSTRAINT_NAME TABLE_SCHEMA TABLE_NAME CONSTRAINT_TYPE -def test PRIMARY test t1 PRIMARY KEY +CONSTRAINT_CATALOG CONSTRAINT_SCHEMA CONSTRAINT_NAME TABLE_SCHEMA TABLE_NAME CONSTRAINT_TYPE ENFORCED +def test PRIMARY test t1 PRIMARY KEY YES SELECT constraint_schema, constraint_name, table_name, column_name FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE WHERE table_name='t1'; constraint_schema constraint_name table_name column_name diff --git a/mysql-test/r/show_check_cs.result b/mysql-test/r/show_check_cs.result index 2ed7f347d102..dc3e91e1e102 100644 --- a/mysql-test/r/show_check_cs.result +++ b/mysql-test/r/show_check_cs.result @@ -272,6 +272,7 @@ create table t1(n int); insert into t1 values (1); show open tables; Database Table In_use Name_locked +mysql check_constraints 0 0 mysql column_statistics 0 0 mysql column_type_elements 0 0 mysql columns 0 0 @@ -1736,8 +1737,8 @@ TABLE_SCHEMA TABLE_NAME INDEX_NAME COLUMN_NAME test t1 c2d c2 test t1 PRIMARY c1 SELECT * FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE table_name='t1'; -CONSTRAINT_CATALOG CONSTRAINT_SCHEMA CONSTRAINT_NAME TABLE_SCHEMA TABLE_NAME CONSTRAINT_TYPE -def test PRIMARY test t1 PRIMARY KEY +CONSTRAINT_CATALOG CONSTRAINT_SCHEMA CONSTRAINT_NAME TABLE_SCHEMA TABLE_NAME CONSTRAINT_TYPE ENFORCED +def test PRIMARY test t1 PRIMARY KEY YES SELECT constraint_schema, constraint_name, table_name, column_name FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE WHERE table_name='t1'; constraint_schema constraint_name table_name column_name diff --git a/mysql-test/r/slow_log_extra.result b/mysql-test/r/slow_log_extra.result index 4ad3af17da29..c9624096f43f 100644 --- a/mysql-test/r/slow_log_extra.result +++ b/mysql-test/r/slow_log_extra.result @@ -69,11 +69,11 @@ DROP TABLE mslow; # We strip off time related fields (non-deterministic) and # verify the rest are correct. # -Rows_sent: 0 Rows_examined: 0 Thread_id: 0 Errno: 0 Killed: 0 Bytes_received: 0 Bytes_sent: 11 Read_first: 0 Read_last: 0 Read_key: 4 Read_next: 0 Read_prev: 0 Read_rnd: 0 Read_rnd_next: 0 Sort_merge_passes: 0 Sort_range_count: 0 Sort_rows: 0 Sort_scan_count: 0 Created_tmp_disk_tables: 0 Created_tmp_tables: 0 -Rows_sent: 0 Rows_examined: 0 Thread_id: 0 Errno: 0 Killed: 0 Bytes_received: 0 Bytes_sent: 11 Read_first: 0 Read_last: 0 Read_key: 4 Read_next: 0 Read_prev: 0 Read_rnd: 0 Read_rnd_next: 0 Sort_merge_passes: 0 Sort_range_count: 0 Sort_rows: 0 Sort_scan_count: 0 Created_tmp_disk_tables: 0 Created_tmp_tables: 0 +Rows_sent: 0 Rows_examined: 0 Thread_id: 0 Errno: 0 Killed: 0 Bytes_received: 0 Bytes_sent: 11 Read_first: 0 Read_last: 0 Read_key: 5 Read_next: 0 Read_prev: 0 Read_rnd: 0 Read_rnd_next: 0 Sort_merge_passes: 0 Sort_range_count: 0 Sort_rows: 0 Sort_scan_count: 0 Created_tmp_disk_tables: 0 Created_tmp_tables: 0 +Rows_sent: 0 Rows_examined: 0 Thread_id: 0 Errno: 0 Killed: 0 Bytes_received: 0 Bytes_sent: 11 Read_first: 0 Read_last: 0 Read_key: 5 Read_next: 0 Read_prev: 0 Read_rnd: 0 Read_rnd_next: 0 Sort_merge_passes: 0 Sort_range_count: 0 Sort_rows: 0 Sort_scan_count: 0 Created_tmp_disk_tables: 0 Created_tmp_tables: 0 Rows_sent: 0 Rows_examined: 0 Thread_id: 0 Errno: 0 Killed: 0 Bytes_received: 0 Bytes_sent: 11 Read_first: 0 Read_last: 0 Read_key: 17 Read_next: 0 Read_prev: 0 Read_rnd: 0 Read_rnd_next: 0 Sort_merge_passes: 0 Sort_range_count: 0 Sort_rows: 0 Sort_scan_count: 0 Created_tmp_disk_tables: 0 Created_tmp_tables: 0 -Rows_sent: 0 Rows_examined: 0 Thread_id: 0 Errno: 0 Killed: 0 Bytes_received: 0 Bytes_sent: 50 Read_first: 0 Read_last: 0 Read_key: 10 Read_next: 9 Read_prev: 0 Read_rnd: 0 Read_rnd_next: 0 Sort_merge_passes: 0 Sort_range_count: 0 Sort_rows: 0 Sort_scan_count: 0 Created_tmp_disk_tables: 0 Created_tmp_tables: 0 -Rows_sent: 0 Rows_examined: 0 Thread_id: 0 Errno: 0 Killed: 0 Bytes_received: 0 Bytes_sent: 11 Read_first: 0 Read_last: 0 Read_key: 11 Read_next: 1 Read_prev: 0 Read_rnd: 0 Read_rnd_next: 0 Sort_merge_passes: 0 Sort_range_count: 0 Sort_rows: 0 Sort_scan_count: 0 Created_tmp_disk_tables: 0 Created_tmp_tables: 0 +Rows_sent: 0 Rows_examined: 0 Thread_id: 0 Errno: 0 Killed: 0 Bytes_received: 0 Bytes_sent: 50 Read_first: 0 Read_last: 0 Read_key: 11 Read_next: 9 Read_prev: 0 Read_rnd: 0 Read_rnd_next: 0 Sort_merge_passes: 0 Sort_range_count: 0 Sort_rows: 0 Sort_scan_count: 0 Created_tmp_disk_tables: 0 Created_tmp_tables: 0 +Rows_sent: 0 Rows_examined: 0 Thread_id: 0 Errno: 0 Killed: 0 Bytes_received: 0 Bytes_sent: 11 Read_first: 0 Read_last: 0 Read_key: 12 Read_next: 1 Read_prev: 0 Read_rnd: 0 Read_rnd_next: 0 Sort_merge_passes: 0 Sort_range_count: 0 Sort_rows: 0 Sort_scan_count: 0 Created_tmp_disk_tables: 0 Created_tmp_tables: 0 Rows_sent: 0 Rows_examined: 0 Thread_id: 0 Errno: 0 Killed: 0 Bytes_received: 0 Bytes_sent: 50 Read_first: 0 Read_last: 0 Read_key: 1 Read_next: 0 Read_prev: 0 Read_rnd: 0 Read_rnd_next: 0 Sort_merge_passes: 0 Sort_range_count: 0 Sort_rows: 0 Sort_scan_count: 0 Created_tmp_disk_tables: 0 Created_tmp_tables: 0 Rows_sent: 8 Rows_examined: 8 Thread_id: 0 Errno: 0 Killed: 0 Bytes_received: 0 Bytes_sent: 106 Read_first: 1 Read_last: 0 Read_key: 1 Read_next: 0 Read_prev: 0 Read_rnd: 0 Read_rnd_next: 9 Sort_merge_passes: 0 Sort_range_count: 0 Sort_rows: 0 Sort_scan_count: 0 Created_tmp_disk_tables: 0 Created_tmp_tables: 0 Rows_sent: 8 Rows_examined: 8 Thread_id: 0 Errno: 0 Killed: 0 Bytes_received: 0 Bytes_sent: 106 Read_first: 1 Read_last: 0 Read_key: 1 Read_next: 0 Read_prev: 0 Read_rnd: 0 Read_rnd_next: 9 Sort_merge_passes: 0 Sort_range_count: 0 Sort_rows: 0 Sort_scan_count: 0 Created_tmp_disk_tables: 0 Created_tmp_tables: 0 diff --git a/mysql-test/r/status.result b/mysql-test/r/status.result index 73b3191feb4b..8d691460838e 100644 --- a/mysql-test/r/status.result +++ b/mysql-test/r/status.result @@ -263,7 +263,7 @@ i show status like 'table_open_cache_%'; Variable_name Value Table_open_cache_hits 1 -Table_open_cache_misses 15 +Table_open_cache_misses 16 Table_open_cache_overflows 0 # The second statement accessing the same table should # result in table cache hit. @@ -272,23 +272,23 @@ i show status like 'table_open_cache_%'; Variable_name Value Table_open_cache_hits 2 -Table_open_cache_misses 15 +Table_open_cache_misses 16 Table_open_cache_overflows 0 # Again table cache miss if accessing different table. select * from t2; j show status like 'table_open_cache_%'; Variable_name Value -Table_open_cache_hits 17 -Table_open_cache_misses 16 +Table_open_cache_hits 18 +Table_open_cache_misses 17 Table_open_cache_overflows 0 # And cache hit then accessing it second time. select * from t2; j show status like 'table_open_cache_%'; Variable_name Value -Table_open_cache_hits 18 -Table_open_cache_misses 16 +Table_open_cache_hits 19 +Table_open_cache_misses 17 Table_open_cache_overflows 0 # The below statement should result in 2 cache hits and # 4 cache misses since it needs 6 table instances in total. @@ -296,8 +296,8 @@ select * from t1 as a, t2 as b, t1 as c, t2 as d, t1 as e, t2 as f; i j i j i j show status like 'table_open_cache_%'; Variable_name Value -Table_open_cache_hits 20 -Table_open_cache_misses 20 +Table_open_cache_hits 21 +Table_open_cache_misses 21 Table_open_cache_overflows 0 # Reduce size of table cache to check that status # variable tracking cache overflows works. @@ -310,18 +310,18 @@ select * from t1; i show status like 'table_open_cache_%'; Variable_name Value -Table_open_cache_hits 21 -Table_open_cache_misses 20 -Table_open_cache_overflows 18 +Table_open_cache_hits 22 +Table_open_cache_misses 21 +Table_open_cache_overflows 19 # This statement should result in 4 cache hits, 2 cache misses/ # overflows. select * from t1 as a, t2 as b, t1 as c, t2 as d, t1 as e, t2 as f; i j i j i j show status like 'table_open_cache_%'; Variable_name Value -Table_open_cache_hits 24 -Table_open_cache_misses 23 -Table_open_cache_overflows 21 +Table_open_cache_hits 25 +Table_open_cache_misses 24 +Table_open_cache_overflows 22 # Finally, the below statement should result in 1 cache miss # and 1 overflow since it accesses table which is not yet in # cache and table cache is full. @@ -329,9 +329,9 @@ select * from t3; k show status like 'table_open_cache_%'; Variable_name Value -Table_open_cache_hits 24 -Table_open_cache_misses 39 -Table_open_cache_overflows 37 +Table_open_cache_hits 25 +Table_open_cache_misses 41 +Table_open_cache_overflows 39 # Cleanup set @@global.table_open_cache= @old_table_open_cache; drop tables t1, t2, t3; diff --git a/mysql-test/r/temptable.result b/mysql-test/r/temptable.result index 745344f7a4da..22986744e4db 100644 --- a/mysql-test/r/temptable.result +++ b/mysql-test/r/temptable.result @@ -4,41 +4,41 @@ USE temptable_test; SELECT * FROM information_schema.table_constraints WHERE table_schema = 'mysql' AND table_name != 'ndb_binlog_index' ORDER BY table_schema,table_name,constraint_name COLLATE utf8_general_ci; -CONSTRAINT_CATALOG CONSTRAINT_SCHEMA CONSTRAINT_NAME TABLE_SCHEMA TABLE_NAME CONSTRAINT_TYPE -def mysql PRIMARY mysql columns_priv PRIMARY KEY -def mysql PRIMARY mysql component PRIMARY KEY -def mysql PRIMARY mysql db PRIMARY KEY -def mysql PRIMARY mysql default_roles PRIMARY KEY -def mysql PRIMARY mysql engine_cost PRIMARY KEY -def mysql PRIMARY mysql func PRIMARY KEY -def mysql PRIMARY mysql global_grants PRIMARY KEY -def mysql PRIMARY mysql gtid_executed PRIMARY KEY -def mysql PRIMARY mysql help_category PRIMARY KEY -def mysql PRIMARY mysql help_keyword PRIMARY KEY -def mysql PRIMARY mysql help_relation PRIMARY KEY -def mysql PRIMARY mysql help_topic PRIMARY KEY -def mysql PRIMARY mysql innodb_index_stats PRIMARY KEY -def mysql PRIMARY mysql innodb_table_stats PRIMARY KEY -def mysql PRIMARY mysql password_history PRIMARY KEY -def mysql PRIMARY mysql plugin PRIMARY KEY -def mysql PRIMARY mysql procs_priv PRIMARY KEY -def mysql PRIMARY mysql proxies_priv PRIMARY KEY -def mysql PRIMARY mysql role_edges PRIMARY KEY -def mysql PRIMARY mysql server_cost PRIMARY KEY -def mysql PRIMARY mysql servers PRIMARY KEY -def mysql PRIMARY mysql slave_master_info PRIMARY KEY -def mysql PRIMARY mysql slave_relay_log_info PRIMARY KEY -def mysql PRIMARY mysql slave_worker_info PRIMARY KEY -def mysql PRIMARY mysql tables_priv PRIMARY KEY -def mysql PRIMARY mysql time_zone PRIMARY KEY -def mysql PRIMARY mysql time_zone_leap_second PRIMARY KEY -def mysql PRIMARY mysql time_zone_name PRIMARY KEY -def mysql PRIMARY mysql time_zone_transition PRIMARY KEY -def mysql PRIMARY mysql time_zone_transition_type PRIMARY KEY -def mysql PRIMARY mysql user PRIMARY KEY -def mysql name mysql help_category UNIQUE -def mysql name mysql help_keyword UNIQUE -def mysql name mysql help_topic UNIQUE +CONSTRAINT_CATALOG CONSTRAINT_SCHEMA CONSTRAINT_NAME TABLE_SCHEMA TABLE_NAME CONSTRAINT_TYPE ENFORCED +def mysql PRIMARY mysql columns_priv PRIMARY KEY YES +def mysql PRIMARY mysql component PRIMARY KEY YES +def mysql PRIMARY mysql db PRIMARY KEY YES +def mysql PRIMARY mysql default_roles PRIMARY KEY YES +def mysql PRIMARY mysql engine_cost PRIMARY KEY YES +def mysql PRIMARY mysql func PRIMARY KEY YES +def mysql PRIMARY mysql global_grants PRIMARY KEY YES +def mysql PRIMARY mysql gtid_executed PRIMARY KEY YES +def mysql PRIMARY mysql help_category PRIMARY KEY YES +def mysql PRIMARY mysql help_keyword PRIMARY KEY YES +def mysql PRIMARY mysql help_relation PRIMARY KEY YES +def mysql PRIMARY mysql help_topic PRIMARY KEY YES +def mysql PRIMARY mysql innodb_index_stats PRIMARY KEY YES +def mysql PRIMARY mysql innodb_table_stats PRIMARY KEY YES +def mysql PRIMARY mysql password_history PRIMARY KEY YES +def mysql PRIMARY mysql plugin PRIMARY KEY YES +def mysql PRIMARY mysql procs_priv PRIMARY KEY YES +def mysql PRIMARY mysql proxies_priv PRIMARY KEY YES +def mysql PRIMARY mysql role_edges PRIMARY KEY YES +def mysql PRIMARY mysql server_cost PRIMARY KEY YES +def mysql PRIMARY mysql servers PRIMARY KEY YES +def mysql PRIMARY mysql slave_master_info PRIMARY KEY YES +def mysql PRIMARY mysql slave_relay_log_info PRIMARY KEY YES +def mysql PRIMARY mysql slave_worker_info PRIMARY KEY YES +def mysql PRIMARY mysql tables_priv PRIMARY KEY YES +def mysql PRIMARY mysql time_zone PRIMARY KEY YES +def mysql PRIMARY mysql time_zone_leap_second PRIMARY KEY YES +def mysql PRIMARY mysql time_zone_name PRIMARY KEY YES +def mysql PRIMARY mysql time_zone_transition PRIMARY KEY YES +def mysql PRIMARY mysql time_zone_transition_type PRIMARY KEY YES +def mysql PRIMARY mysql user PRIMARY KEY YES +def mysql name mysql help_category UNIQUE YES +def mysql name mysql help_keyword UNIQUE YES +def mysql name mysql help_topic UNIQUE YES # Test 02 SET optimizer_switch = "derived_merge=off"; CREATE TABLE t1 ( diff --git a/mysql-test/std_data/dd/sdi/innodb_index_debug/t1.json b/mysql-test/std_data/dd/sdi/innodb_index_debug/t1.json index c4f4687b1dc9..6cacfdd644ba 100644 --- a/mysql-test/std_data/dd/sdi/innodb_index_debug/t1.json +++ b/mysql-test/std_data/dd/sdi/innodb_index_debug/t1.json @@ -263,6 +263,7 @@ } ], "foreign_keys": [], + "check_constraints": [], "partitions": [], "collation_id": 255 } diff --git a/mysql-test/std_data/dd/sdi/innodb_sdi/ibdata1.json b/mysql-test/std_data/dd/sdi/innodb_sdi/ibdata1.json index f061c9e6aac4..67685831d4af 100644 --- a/mysql-test/std_data/dd/sdi/innodb_sdi/ibdata1.json +++ b/mysql-test/std_data/dd/sdi/innodb_sdi/ibdata1.json @@ -505,6 +505,7 @@ } ], "foreign_keys": [], + "check_constraints": [], "partitions": [], "collation_id": 255, "tablespace_ref": "innodb_system" @@ -691,6 +692,7 @@ } ], "foreign_keys": [], + "check_constraints": [], "partitions": [], "collation_id": 255, "tablespace_ref": "innodb_system" diff --git a/mysql-test/std_data/dd/sdi/innodb_sdi/mysql.json b/mysql-test/std_data/dd/sdi/innodb_sdi/mysql.json index 71fce98a1193..cd68efd1bac4 100644 --- a/mysql-test/std_data/dd/sdi/innodb_sdi/mysql.json +++ b/mysql-test/std_data/dd/sdi/innodb_sdi/mysql.json @@ -221,6 +221,7 @@ } ], "foreign_keys": [], + "check_constraints": [], "partitions": [], "collation_id": X, "tablespace_ref": "mysql" @@ -491,6 +492,7 @@ } ], "foreign_keys": [], + "check_constraints": [], "partitions": [], "collation_id": X, "tablespace_ref": "mysql" @@ -887,6 +889,7 @@ } ], "foreign_keys": [], + "check_constraints": [], "partitions": [], "collation_id": X, "tablespace_ref": "mysql" @@ -1367,6 +1370,7 @@ } ], "foreign_keys": [], + "check_constraints": [], "partitions": [], "collation_id": X, "tablespace_ref": "mysql" @@ -1918,6 +1922,7 @@ } ], "foreign_keys": [], + "check_constraints": [], "partitions": [], "collation_id": X, "tablespace_ref": "mysql" @@ -2301,6 +2306,7 @@ } ], "foreign_keys": [], + "check_constraints": [], "partitions": [], "collation_id": X, "tablespace_ref": "mysql" @@ -2773,6 +2779,560 @@ ] } ], + "check_constraints": [], + "partitions": [], + "collation_id": X, + "tablespace_ref": "mysql" + } +} +} +, +{ + "type": 1, + "id": X, + "object": + { + "mysqld_version_id": X, + "dd_version": X, + "sdi_version": 1, + "dd_object_type": "Table", + "dd_object": { + "name": "check_constraints", + "mysql_version_id": X, + "created": NNN, + "last_altered": NNN, + "hidden": 2, + "options": "avg_row_length=0;explicit_tablespace=1;key_block_size=0;keys_disabled=0;pack_record=1;row_type=2;stats_auto_recalc=0;stats_persistent=0;stats_sample_pages=0;", + "columns": [ + { + "name": "id", + "type": 9, + "is_nullable": false, + "is_zerofill": false, + "is_unsigned": true, + "is_auto_increment": true, + "is_virtual": false, + "hidden": 1, + "ordinal_position": 1, + "char_length": 20, + "numeric_precision": 20, + "numeric_scale": 0, + "numeric_scale_null": false, + "datetime_precision": 0, + "datetime_precision_null": 1, + "has_no_default": false, + "default_value_null": false, + "srs_id_null": true, + "srs_id": 0, + "default_value": "", + "default_value_utf8_null": true, + "default_value_utf8": "", + "default_option": "", + "update_option": "", + "comment": "", + "generation_expression": "", + "generation_expression_utf8": "", + "options": "interval_count=0;", + "se_private_data": "table_id=X", + "column_key": 2, + "column_type_utf8": "bigint(20) unsigned", + "elements": [], + "collation_id": X, + "is_explicit_collation": false + }, + { + "name": "schema_id", + "type": 9, + "is_nullable": false, + "is_zerofill": false, + "is_unsigned": true, + "is_auto_increment": false, + "is_virtual": false, + "hidden": 1, + "ordinal_position": 2, + "char_length": 20, + "numeric_precision": 20, + "numeric_scale": 0, + "numeric_scale_null": false, + "datetime_precision": 0, + "datetime_precision_null": 1, + "has_no_default": true, + "default_value_null": false, + "srs_id_null": true, + "srs_id": 0, + "default_value": "", + "default_value_utf8_null": true, + "default_value_utf8": "", + "default_option": "", + "update_option": "", + "comment": "", + "generation_expression": "", + "generation_expression_utf8": "", + "options": "interval_count=0;", + "se_private_data": "table_id=X", + "column_key": 4, + "column_type_utf8": "bigint(20) unsigned", + "elements": [], + "collation_id": X, + "is_explicit_collation": false + }, + { + "name": "table_id", + "type": 9, + "is_nullable": false, + "is_zerofill": false, + "is_unsigned": true, + "is_auto_increment": false, + "is_virtual": false, + "hidden": 1, + "ordinal_position": 3, + "char_length": 20, + "numeric_precision": 20, + "numeric_scale": 0, + "numeric_scale_null": false, + "datetime_precision": 0, + "datetime_precision_null": 1, + "has_no_default": true, + "default_value_null": false, + "srs_id_null": true, + "srs_id": 0, + "default_value": "", + "default_value_utf8_null": true, + "default_value_utf8": "", + "default_option": "", + "update_option": "", + "comment": "", + "generation_expression": "", + "generation_expression_utf8": "", + "options": "interval_count=0;", + "se_private_data": "table_id=X", + "column_key": 4, + "column_type_utf8": "bigint(20) unsigned", + "elements": [], + "collation_id": X, + "is_explicit_collation": false + }, + { + "name": "name", + "type": 16, + "is_nullable": false, + "is_zerofill": false, + "is_unsigned": false, + "is_auto_increment": false, + "is_virtual": false, + "hidden": 1, + "ordinal_position": 4, + "char_length": 192, + "numeric_precision": 0, + "numeric_scale": 0, + "numeric_scale_null": true, + "datetime_precision": 0, + "datetime_precision_null": 1, + "has_no_default": true, + "default_value_null": false, + "srs_id_null": true, + "srs_id": 0, + "default_value": "", + "default_value_utf8_null": true, + "default_value_utf8": "", + "default_option": "", + "update_option": "", + "comment": "", + "generation_expression": "", + "generation_expression_utf8": "", + "options": "interval_count=0;", + "se_private_data": "table_id=X", + "column_key": 1, + "column_type_utf8": "varchar(64)", + "elements": [], + "collation_id": X, + "is_explicit_collation": true + }, + { + "name": "enforced", + "type": 22, + "is_nullable": false, + "is_zerofill": false, + "is_unsigned": false, + "is_auto_increment": false, + "is_virtual": false, + "hidden": 1, + "ordinal_position": 5, + "char_length": 9, + "numeric_precision": 0, + "numeric_scale": 0, + "numeric_scale_null": true, + "datetime_precision": 0, + "datetime_precision_null": 1, + "has_no_default": true, + "default_value_null": false, + "srs_id_null": true, + "srs_id": 0, + "default_value": "", + "default_value_utf8_null": true, + "default_value_utf8": "", + "default_option": "", + "update_option": "", + "comment": "", + "generation_expression": "", + "generation_expression_utf8": "", + "options": "interval_count=2;", + "se_private_data": "table_id=X", + "column_key": 1, + "column_type_utf8": "enum('NO','YES')", + "elements": [ + { + "name": "Tk8=", "decoded-name": "NO", + "index": 1 + }, + { + "name": "WUVT", "decoded-name": "YES", + "index": 2 + } + ], + "collation_id": X, + "is_explicit_collation": false + }, + { + "name": "check_clause", + "type": 26, + "is_nullable": false, + "is_zerofill": false, + "is_unsigned": false, + "is_auto_increment": false, + "is_virtual": false, + "hidden": 1, + "ordinal_position": 6, + "char_length": 4294967295, + "numeric_precision": 0, + "numeric_scale": 0, + "numeric_scale_null": true, + "datetime_precision": 0, + "datetime_precision_null": 1, + "has_no_default": true, + "default_value_null": false, + "srs_id_null": true, + "srs_id": 0, + "default_value": "", + "default_value_utf8_null": true, + "default_value_utf8": "", + "default_option": "", + "update_option": "", + "comment": "", + "generation_expression": "", + "generation_expression_utf8": "", + "options": "interval_count=0;", + "se_private_data": "table_id=X", + "column_key": 1, + "column_type_utf8": "longblob", + "elements": [], + "collation_id": X, + "is_explicit_collation": true + }, + { + "name": "check_clause_utf8", + "type": 26, + "is_nullable": false, + "is_zerofill": false, + "is_unsigned": false, + "is_auto_increment": false, + "is_virtual": false, + "hidden": 1, + "ordinal_position": 7, + "char_length": 4294967295, + "numeric_precision": 0, + "numeric_scale": 0, + "numeric_scale_null": true, + "datetime_precision": 0, + "datetime_precision_null": 1, + "has_no_default": true, + "default_value_null": false, + "srs_id_null": true, + "srs_id": 0, + "default_value": "", + "default_value_utf8_null": true, + "default_value_utf8": "", + "default_option": "", + "update_option": "", + "comment": "", + "generation_expression": "", + "generation_expression_utf8": "", + "options": "interval_count=0;", + "se_private_data": "table_id=X", + "column_key": 1, + "column_type_utf8": "longtext", + "elements": [], + "collation_id": X, + "is_explicit_collation": false + }, + { + "name": "DB_TRX_ID", + "type": 10, + "is_nullable": false, + "is_zerofill": false, + "is_unsigned": false, + "is_auto_increment": false, + "is_virtual": false, + "hidden": 2, + "ordinal_position": 8, + "char_length": 6, + "numeric_precision": 0, + "numeric_scale": 0, + "numeric_scale_null": true, + "datetime_precision": 0, + "datetime_precision_null": 1, + "has_no_default": false, + "default_value_null": true, + "srs_id_null": true, + "srs_id": 0, + "default_value": "", + "default_value_utf8_null": true, + "default_value_utf8": "", + "default_option": "", + "update_option": "", + "comment": "", + "generation_expression": "", + "generation_expression_utf8": "", + "options": "", + "se_private_data": "table_id=X", + "column_key": 1, + "column_type_utf8": "", + "elements": [], + "collation_id": X, + "is_explicit_collation": false + }, + { + "name": "DB_ROLL_PTR", + "type": 9, + "is_nullable": false, + "is_zerofill": false, + "is_unsigned": false, + "is_auto_increment": false, + "is_virtual": false, + "hidden": 2, + "ordinal_position": 9, + "char_length": 7, + "numeric_precision": 0, + "numeric_scale": 0, + "numeric_scale_null": true, + "datetime_precision": 0, + "datetime_precision_null": 1, + "has_no_default": false, + "default_value_null": true, + "srs_id_null": true, + "srs_id": 0, + "default_value": "", + "default_value_utf8_null": true, + "default_value_utf8": "", + "default_option": "", + "update_option": "", + "comment": "", + "generation_expression": "", + "generation_expression_utf8": "", + "options": "", + "se_private_data": "table_id=X", + "column_key": 1, + "column_type_utf8": "", + "elements": [], + "collation_id": X, + "is_explicit_collation": false + } + ], + "schema_ref": "mysql", + "se_private_id":NNN, + "engine": "InnoDB", + "last_checked_for_upgrade_version_id": X, + "comment": "", + "se_private_data": "autoinc=0;version=0;", + "row_format": 2, + "partition_type": 0, + "partition_expression": "", + "partition_expression_utf8": "", + "default_partitioning": 0, + "subpartition_type": 0, + "subpartition_expression": "", + "subpartition_expression_utf8": "", + "default_subpartitioning": 0, + "indexes": [ + { + "name": "PRIMARY", + "hidden": false, + "is_generated": false, + "ordinal_position": 1, + "comment": "", + "options": "flags=0;", + "se_private_data": "id=A;root=B;space_id=C;table_id=D;trx_id=E", + "type": 1, + "algorithm": 2, + "is_algorithm_explicit": false, + "is_visible": true, + "engine": "InnoDB", + "elements": [ + { + "ordinal_position": 1, + "length": 8, + "order": 2, + "column_opx": 0 + }, + { + "ordinal_position": 2, + "length": 4294967295, + "order": 2, + "column_opx": 7 + }, + { + "ordinal_position": 3, + "length": 4294967295, + "order": 2, + "column_opx": 8 + }, + { + "ordinal_position": 4, + "length": 4294967295, + "order": 2, + "column_opx": 1 + }, + { + "ordinal_position": 5, + "length": 4294967295, + "order": 2, + "column_opx": 2 + }, + { + "ordinal_position": 6, + "length": 4294967295, + "order": 2, + "column_opx": 3 + }, + { + "ordinal_position": 7, + "length": 4294967295, + "order": 2, + "column_opx": 4 + }, + { + "ordinal_position": 8, + "length": 4294967295, + "order": 2, + "column_opx": 5 + }, + { + "ordinal_position": 9, + "length": 4294967295, + "order": 2, + "column_opx": 6 + } + ], + "tablespace_ref": "mysql" + }, + { + "name": "schema_id", + "hidden": false, + "is_generated": false, + "ordinal_position": 2, + "comment": "", + "options": "flags=0;", + "se_private_data": "id=A;root=B;space_id=C;table_id=D;trx_id=E", + "type": 2, + "algorithm": 2, + "is_algorithm_explicit": false, + "is_visible": true, + "engine": "InnoDB", + "elements": [ + { + "ordinal_position": 1, + "length": 8, + "order": 2, + "column_opx": 1 + }, + { + "ordinal_position": 2, + "length": 192, + "order": 2, + "column_opx": 3 + }, + { + "ordinal_position": 3, + "length": 4294967295, + "order": 2, + "column_opx": 0 + } + ], + "tablespace_ref": "mysql" + }, + { + "name": "table_id", + "hidden": false, + "is_generated": false, + "ordinal_position": 3, + "comment": "", + "options": "flags=0;", + "se_private_data": "id=A;root=B;space_id=C;table_id=D;trx_id=E", + "type": 2, + "algorithm": 2, + "is_algorithm_explicit": false, + "is_visible": true, + "engine": "InnoDB", + "elements": [ + { + "ordinal_position": 1, + "length": 8, + "order": 2, + "column_opx": 2 + }, + { + "ordinal_position": 2, + "length": 192, + "order": 2, + "column_opx": 3 + }, + { + "ordinal_position": 3, + "length": 4294967295, + "order": 2, + "column_opx": 0 + } + ], + "tablespace_ref": "mysql" + } + ], + "foreign_keys": [ + { + "name": "check_constraints_ibfk_1", + "match_option": 1, + "update_rule": 1, + "delete_rule": 1, + "unique_constraint_name": "", + "referenced_table_catalog_name": "def", + "referenced_table_schema_name": "mysql", + "referenced_table_name": "schemata", + "elements": [ + { + "column_opx": 1, + "ordinal_position": 1, + "referenced_column_name": "id" + } + ] + }, + { + "name": "check_constraints_ibfk_2", + "match_option": 1, + "update_rule": 1, + "delete_rule": 1, + "unique_constraint_name": "", + "referenced_table_catalog_name": "def", + "referenced_table_schema_name": "mysql", + "referenced_table_name": "tables", + "elements": [ + { + "column_opx": 2, + "ordinal_position": 1, + "referenced_column_name": "id" + } + ] + } + ], + "check_constraints": [], "partitions": [], "collation_id": X, "tablespace_ref": "mysql" @@ -3296,6 +3856,7 @@ ] } ], + "check_constraints": [], "partitions": [], "collation_id": X, "tablespace_ref": "mysql" @@ -3876,6 +4437,7 @@ ] } ], + "check_constraints": [], "partitions": [], "collation_id": X, "tablespace_ref": "mysql" @@ -4164,6 +4726,7 @@ ] } ], + "check_constraints": [], "partitions": [], "collation_id": X, "tablespace_ref": "mysql" @@ -5903,6 +6466,7 @@ ] } ], + "check_constraints": [], "partitions": [], "collation_id": X, "tablespace_ref": "mysql" @@ -7482,6 +8046,7 @@ ] } ], + "check_constraints": [], "partitions": [], "collation_id": X, "tablespace_ref": "mysql" @@ -7905,6 +8470,7 @@ ] } ], + "check_constraints": [], "partitions": [], "collation_id": X, "tablespace_ref": "mysql" @@ -8737,6 +9303,7 @@ ] } ], + "check_constraints": [], "partitions": [], "collation_id": X, "tablespace_ref": "mysql" @@ -9257,6 +9824,7 @@ ] } ], + "check_constraints": [], "partitions": [], "collation_id": X, "tablespace_ref": "mysql" @@ -9727,6 +10295,7 @@ ] } ], + "check_constraints": [], "partitions": [], "collation_id": X, "tablespace_ref": "mysql" @@ -10123,6 +10692,7 @@ } ], "foreign_keys": [], + "check_constraints": [], "partitions": [], "collation_id": X, "tablespace_ref": "mysql" @@ -11038,6 +11608,7 @@ ] } ], + "check_constraints": [], "partitions": [], "collation_id": X, "tablespace_ref": "mysql" @@ -11326,6 +11897,7 @@ ] } ], + "check_constraints": [], "partitions": [], "collation_id": X, "tablespace_ref": "mysql" @@ -12337,6 +12909,7 @@ ] } ], + "check_constraints": [], "partitions": [], "collation_id": X, "tablespace_ref": "mysql" @@ -12813,6 +13386,7 @@ } ], "foreign_keys": [], + "check_constraints": [], "partitions": [], "collation_id": X, "tablespace_ref": "mysql" @@ -14715,6 +15289,7 @@ ] } ], + "check_constraints": [], "partitions": [], "collation_id": X, "tablespace_ref": "mysql" @@ -15252,6 +15827,7 @@ ] } ], + "check_constraints": [], "partitions": [], "collation_id": X, "tablespace_ref": "mysql" @@ -15910,6 +16486,7 @@ ] } ], + "check_constraints": [], "partitions": [], "collation_id": X, "tablespace_ref": "mysql" @@ -16282,6 +16859,7 @@ ] } ], + "check_constraints": [], "partitions": [], "collation_id": X, "tablespace_ref": "mysql" @@ -17180,6 +17758,7 @@ ] } ], + "check_constraints": [], "partitions": [], "collation_id": X, "tablespace_ref": "mysql" @@ -17870,6 +18449,7 @@ } ], "foreign_keys": [], + "check_constraints": [], "partitions": [], "collation_id": X, "tablespace_ref": "mysql" @@ -20017,6 +20597,7 @@ ] } ], + "check_constraints": [], "partitions": [], "collation_id": X, "tablespace_ref": "mysql" @@ -20382,6 +20963,7 @@ ] } ], + "check_constraints": [], "partitions": [], "collation_id": X, "tablespace_ref": "mysql" @@ -20807,6 +21389,7 @@ } ], "foreign_keys": [], + "check_constraints": [], "partitions": [], "collation_id": X, "tablespace_ref": "mysql" @@ -22075,6 +22658,7 @@ ] } ], + "check_constraints": [], "partitions": [], "collation_id": X, "tablespace_ref": "mysql" @@ -22446,6 +23030,7 @@ ] } ], + "check_constraints": [], "partitions": [], "collation_id": X, "tablespace_ref": "mysql" @@ -22817,6 +23402,7 @@ ] } ], + "check_constraints": [], "partitions": [], "collation_id": X, "tablespace_ref": "mysql" @@ -24091,6 +24677,7 @@ } ], "foreign_keys": [], + "check_constraints": [], "partitions": [], "collation_id": X, "tablespace_ref": "mysql" @@ -26700,6 +27287,7 @@ } ], "foreign_keys": [], + "check_constraints": [], "partitions": [], "collation_id": X, "tablespace_ref": "mysql" @@ -27012,6 +27600,7 @@ } ], "foreign_keys": [], + "check_constraints": [], "partitions": [], "collation_id": X, "tablespace_ref": "mysql" @@ -27375,6 +27964,7 @@ } ], "foreign_keys": [], + "check_constraints": [], "partitions": [], "collation_id": X, "tablespace_ref": "mysql" @@ -27696,6 +28286,7 @@ } ], "foreign_keys": [], + "check_constraints": [], "partitions": [], "collation_id": X, "tablespace_ref": "mysql" @@ -28008,6 +28599,7 @@ } ], "foreign_keys": [], + "check_constraints": [], "partitions": [], "collation_id": X, "tablespace_ref": "mysql" @@ -28329,6 +28921,7 @@ } ], "foreign_keys": [], + "check_constraints": [], "partitions": [], "collation_id": X, "tablespace_ref": "mysql" @@ -28557,6 +29150,7 @@ } ], "foreign_keys": [], + "check_constraints": [], "partitions": [], "collation_id": X, "tablespace_ref": "mysql" @@ -29079,6 +29673,7 @@ } ], "foreign_keys": [], + "check_constraints": [], "partitions": [], "collation_id": X, "tablespace_ref": "mysql" @@ -29676,6 +30271,7 @@ } ], "foreign_keys": [], + "check_constraints": [], "partitions": [], "collation_id": X, "tablespace_ref": "mysql" @@ -30131,6 +30727,7 @@ } ], "foreign_keys": [], + "check_constraints": [], "partitions": [], "collation_id": X, "tablespace_ref": "mysql" @@ -30556,6 +31153,7 @@ } ], "foreign_keys": [], + "check_constraints": [], "partitions": [], "collation_id": X, "tablespace_ref": "mysql" @@ -30897,6 +31495,7 @@ } ], "foreign_keys": [], + "check_constraints": [], "partitions": [], "collation_id": X, "tablespace_ref": "mysql" @@ -31125,6 +31724,7 @@ } ], "foreign_keys": [], + "check_constraints": [], "partitions": [], "collation_id": X, "tablespace_ref": "mysql" @@ -31382,6 +31982,7 @@ } ], "foreign_keys": [], + "check_constraints": [], "partitions": [], "collation_id": X, "tablespace_ref": "mysql" @@ -31610,6 +32211,7 @@ } ], "foreign_keys": [], + "check_constraints": [], "partitions": [], "collation_id": X, "tablespace_ref": "mysql" @@ -31847,6 +32449,7 @@ } ], "foreign_keys": [], + "check_constraints": [], "partitions": [], "collation_id": X, "tablespace_ref": "mysql" @@ -32117,6 +32720,7 @@ } ], "foreign_keys": [], + "check_constraints": [], "partitions": [], "collation_id": X, "tablespace_ref": "mysql" @@ -32471,6 +33075,7 @@ } ], "foreign_keys": [], + "check_constraints": [], "partitions": [], "collation_id": X, "tablespace_ref": "mysql" @@ -32699,6 +33304,7 @@ } ], "foreign_keys": [], + "check_constraints": [], "partitions": [], "collation_id": X, "tablespace_ref": "mysql" @@ -33254,6 +33860,7 @@ } ], "foreign_keys": [], + "check_constraints": [], "partitions": [], "collation_id": X, "tablespace_ref": "mysql" @@ -33524,6 +34131,7 @@ } ], "foreign_keys": [], + "check_constraints": [], "partitions": [], "collation_id": X, "tablespace_ref": "mysql" @@ -34046,6 +34654,7 @@ } ], "foreign_keys": [], + "check_constraints": [], "partitions": [], "collation_id": X, "tablespace_ref": "mysql" @@ -35324,6 +35933,7 @@ } ], "foreign_keys": [], + "check_constraints": [], "partitions": [], "collation_id": X, "tablespace_ref": "mysql" @@ -36014,6 +36624,7 @@ } ], "foreign_keys": [], + "check_constraints": [], "partitions": [], "collation_id": X, "tablespace_ref": "mysql" @@ -36284,6 +36895,7 @@ } ], "foreign_keys": [], + "check_constraints": [], "partitions": [], "collation_id": X, "tablespace_ref": "mysql" @@ -36632,6 +37244,7 @@ } ], "foreign_keys": [], + "check_constraints": [], "partitions": [], "collation_id": X, "tablespace_ref": "mysql" @@ -37064,6 +37677,7 @@ } ], "foreign_keys": [], + "check_constraints": [], "partitions": [], "collation_id": X, "tablespace_ref": "mysql" @@ -37549,6 +38163,7 @@ } ], "foreign_keys": [], + "check_constraints": [], "partitions": [], "collation_id": X, "tablespace_ref": "mysql" diff --git a/mysql-test/std_data/dd/sdi/innodb_sdi/t1.json b/mysql-test/std_data/dd/sdi/innodb_sdi/t1.json index 6cc5ef4e5daf..19e5b3428ca5 100644 --- a/mysql-test/std_data/dd/sdi/innodb_sdi/t1.json +++ b/mysql-test/std_data/dd/sdi/innodb_sdi/t1.json @@ -221,6 +221,7 @@ } ], "foreign_keys": [], + "check_constraints": [], "partitions": [], "collation_id": 255 } diff --git a/mysql-test/std_data/dd/sdi/innodb_sdi/t10.json b/mysql-test/std_data/dd/sdi/innodb_sdi/t10.json index 922c491a8b75..913013a6f5f0 100644 --- a/mysql-test/std_data/dd/sdi/innodb_sdi/t10.json +++ b/mysql-test/std_data/dd/sdi/innodb_sdi/t10.json @@ -389,6 +389,7 @@ } ], "foreign_keys": [], + "check_constraints": [], "partitions": [], "collation_id": 255 } diff --git a/mysql-test/std_data/dd/sdi/innodb_sdi/t10_altered.json b/mysql-test/std_data/dd/sdi/innodb_sdi/t10_altered.json index 029b4a22e7c2..8a55f34feb5a 100644 --- a/mysql-test/std_data/dd/sdi/innodb_sdi/t10_altered.json +++ b/mysql-test/std_data/dd/sdi/innodb_sdi/t10_altered.json @@ -389,6 +389,7 @@ } ], "foreign_keys": [], + "check_constraints": [], "partitions": [], "collation_id": 255 } diff --git a/mysql-test/std_data/dd/sdi/innodb_sdi/t11.json b/mysql-test/std_data/dd/sdi/innodb_sdi/t11.json index ed7bdeab94ef..128f88bfbb31 100644 --- a/mysql-test/std_data/dd/sdi/innodb_sdi/t11.json +++ b/mysql-test/std_data/dd/sdi/innodb_sdi/t11.json @@ -710,6 +710,7 @@ } ], "foreign_keys": [], + "check_constraints": [], "partitions": [], "collation_id": 255 } diff --git a/mysql-test/std_data/dd/sdi/innodb_sdi/t11_altered.json b/mysql-test/std_data/dd/sdi/innodb_sdi/t11_altered.json index 71694f16bc29..a557580b6a1f 100644 --- a/mysql-test/std_data/dd/sdi/innodb_sdi/t11_altered.json +++ b/mysql-test/std_data/dd/sdi/innodb_sdi/t11_altered.json @@ -645,6 +645,7 @@ } ], "foreign_keys": [], + "check_constraints": [], "partitions": [], "collation_id": 255 } diff --git a/mysql-test/std_data/dd/sdi/innodb_sdi/t12#p#p0.json b/mysql-test/std_data/dd/sdi/innodb_sdi/t12#p#p0.json index 76dd307c98fa..7a7212eda993 100644 --- a/mysql-test/std_data/dd/sdi/innodb_sdi/t12#p#p0.json +++ b/mysql-test/std_data/dd/sdi/innodb_sdi/t12#p#p0.json @@ -298,6 +298,7 @@ } ], "foreign_keys": [], + "check_constraints": [], "partitions": [ { "name": "p0", diff --git a/mysql-test/std_data/dd/sdi/innodb_sdi/t13.json b/mysql-test/std_data/dd/sdi/innodb_sdi/t13.json index 032966418817..d93f405aaa2d 100644 --- a/mysql-test/std_data/dd/sdi/innodb_sdi/t13.json +++ b/mysql-test/std_data/dd/sdi/innodb_sdi/t13.json @@ -392,6 +392,7 @@ } ], "foreign_keys": [], + "check_constraints": [], "partitions": [], "collation_id": 255 } diff --git a/mysql-test/std_data/dd/sdi/innodb_sdi/t14.json b/mysql-test/std_data/dd/sdi/innodb_sdi/t14.json index 8efdf41e1b81..a6dc638740df 100644 --- a/mysql-test/std_data/dd/sdi/innodb_sdi/t14.json +++ b/mysql-test/std_data/dd/sdi/innodb_sdi/t14.json @@ -315,6 +315,7 @@ } ], "foreign_keys": [], + "check_constraints": [], "partitions": [], "collation_id": 255 } diff --git a/mysql-test/std_data/dd/sdi/innodb_sdi/t15.json b/mysql-test/std_data/dd/sdi/innodb_sdi/t15.json index 6e9718592529..d12bf5e40349 100644 --- a/mysql-test/std_data/dd/sdi/innodb_sdi/t15.json +++ b/mysql-test/std_data/dd/sdi/innodb_sdi/t15.json @@ -292,6 +292,7 @@ } ], "foreign_keys": [], + "check_constraints": [], "partitions": [], "collation_id": 255 } diff --git a/mysql-test/std_data/dd/sdi/innodb_sdi/t18.json b/mysql-test/std_data/dd/sdi/innodb_sdi/t18.json index 1641024dbf7f..34916902e742 100644 --- a/mysql-test/std_data/dd/sdi/innodb_sdi/t18.json +++ b/mysql-test/std_data/dd/sdi/innodb_sdi/t18.json @@ -263,6 +263,7 @@ } ], "foreign_keys": [], + "check_constraints": [], "partitions": [], "collation_id": 255 } diff --git a/mysql-test/std_data/dd/sdi/innodb_sdi/t1_altered.json b/mysql-test/std_data/dd/sdi/innodb_sdi/t1_altered.json index 5fa90f7802cb..c87de1db1d27 100644 --- a/mysql-test/std_data/dd/sdi/innodb_sdi/t1_altered.json +++ b/mysql-test/std_data/dd/sdi/innodb_sdi/t1_altered.json @@ -263,6 +263,7 @@ } ], "foreign_keys": [], + "check_constraints": [], "partitions": [], "collation_id": 255 } diff --git a/mysql-test/std_data/dd/sdi/innodb_sdi/t2.json b/mysql-test/std_data/dd/sdi/innodb_sdi/t2.json index 34c3927b3662..3068b2e074a7 100644 --- a/mysql-test/std_data/dd/sdi/innodb_sdi/t2.json +++ b/mysql-test/std_data/dd/sdi/innodb_sdi/t2.json @@ -221,6 +221,7 @@ } ], "foreign_keys": [], + "check_constraints": [], "partitions": [], "collation_id": 255 } diff --git a/mysql-test/std_data/dd/sdi/innodb_sdi/t2_altered.json b/mysql-test/std_data/dd/sdi/innodb_sdi/t2_altered.json index ec9a8410c06b..da72232d7155 100644 --- a/mysql-test/std_data/dd/sdi/innodb_sdi/t2_altered.json +++ b/mysql-test/std_data/dd/sdi/innodb_sdi/t2_altered.json @@ -250,6 +250,7 @@ } ], "foreign_keys": [], + "check_constraints": [], "partitions": [], "collation_id": 255 } diff --git a/mysql-test/std_data/dd/sdi/innodb_sdi/t3.json b/mysql-test/std_data/dd/sdi/innodb_sdi/t3.json index a4347f4b9bd2..483db36fb933 100644 --- a/mysql-test/std_data/dd/sdi/innodb_sdi/t3.json +++ b/mysql-test/std_data/dd/sdi/innodb_sdi/t3.json @@ -369,6 +369,7 @@ } ], "foreign_keys": [], + "check_constraints": [], "partitions": [], "collation_id": 255 } diff --git a/mysql-test/std_data/dd/sdi/innodb_sdi/t3_altered.json b/mysql-test/std_data/dd/sdi/innodb_sdi/t3_altered.json index 7cb9acf0155b..037eb5361119 100644 --- a/mysql-test/std_data/dd/sdi/innodb_sdi/t3_altered.json +++ b/mysql-test/std_data/dd/sdi/innodb_sdi/t3_altered.json @@ -334,6 +334,7 @@ } ], "foreign_keys": [], + "check_constraints": [], "partitions": [], "collation_id": 255 } diff --git a/mysql-test/std_data/dd/sdi/innodb_sdi/t4.json b/mysql-test/std_data/dd/sdi/innodb_sdi/t4.json index 7f69c1e05506..e001ed71eb27 100644 --- a/mysql-test/std_data/dd/sdi/innodb_sdi/t4.json +++ b/mysql-test/std_data/dd/sdi/innodb_sdi/t4.json @@ -305,6 +305,7 @@ } ], "foreign_keys": [], + "check_constraints": [], "partitions": [], "collation_id": 255 } diff --git a/mysql-test/std_data/dd/sdi/innodb_sdi/t4_altered.json b/mysql-test/std_data/dd/sdi/innodb_sdi/t4_altered.json index e2ebcda235d0..3c805348479e 100644 --- a/mysql-test/std_data/dd/sdi/innodb_sdi/t4_altered.json +++ b/mysql-test/std_data/dd/sdi/innodb_sdi/t4_altered.json @@ -263,6 +263,7 @@ } ], "foreign_keys": [], + "check_constraints": [], "partitions": [], "collation_id": 255 } diff --git a/mysql-test/std_data/dd/sdi/innodb_sdi/t5.json b/mysql-test/std_data/dd/sdi/innodb_sdi/t5.json index 28401b59201b..c7900d126e81 100644 --- a/mysql-test/std_data/dd/sdi/innodb_sdi/t5.json +++ b/mysql-test/std_data/dd/sdi/innodb_sdi/t5.json @@ -347,6 +347,7 @@ } ], "foreign_keys": [], + "check_constraints": [], "partitions": [], "collation_id": 255 } diff --git a/mysql-test/std_data/dd/sdi/innodb_sdi/t6.json b/mysql-test/std_data/dd/sdi/innodb_sdi/t6.json index 7115a4101e4a..cf3508b22a8c 100644 --- a/mysql-test/std_data/dd/sdi/innodb_sdi/t6.json +++ b/mysql-test/std_data/dd/sdi/innodb_sdi/t6.json @@ -950,6 +950,7 @@ } ], "foreign_keys": [], + "check_constraints": [], "partitions": [], "collation_id": 8 } diff --git a/mysql-test/std_data/dd/sdi/innodb_sdi/t7.json b/mysql-test/std_data/dd/sdi/innodb_sdi/t7.json index 55d860a3ec00..8606056c931d 100644 --- a/mysql-test/std_data/dd/sdi/innodb_sdi/t7.json +++ b/mysql-test/std_data/dd/sdi/innodb_sdi/t7.json @@ -305,6 +305,7 @@ } ], "foreign_keys": [], + "check_constraints": [], "partitions": [], "collation_id": 255 } diff --git a/mysql-test/std_data/dd/sdi/innodb_sdi/ts1.json b/mysql-test/std_data/dd/sdi/innodb_sdi/ts1.json index c25b9753f0be..8945e9cd7682 100644 --- a/mysql-test/std_data/dd/sdi/innodb_sdi/ts1.json +++ b/mysql-test/std_data/dd/sdi/innodb_sdi/ts1.json @@ -179,6 +179,7 @@ } ], "foreign_keys": [], + "check_constraints": [], "partitions": [], "collation_id": 255, "tablespace_ref": "ts1" @@ -519,6 +520,7 @@ ] } ], + "check_constraints": [], "partitions": [], "collation_id": 255, "tablespace_ref": "ts1" diff --git a/mysql-test/std_data/dd/sdi/innodb_sdi/ts1_altered.json b/mysql-test/std_data/dd/sdi/innodb_sdi/ts1_altered.json index c25b9753f0be..8945e9cd7682 100644 --- a/mysql-test/std_data/dd/sdi/innodb_sdi/ts1_altered.json +++ b/mysql-test/std_data/dd/sdi/innodb_sdi/ts1_altered.json @@ -179,6 +179,7 @@ } ], "foreign_keys": [], + "check_constraints": [], "partitions": [], "collation_id": 255, "tablespace_ref": "ts1" @@ -519,6 +520,7 @@ ] } ], + "check_constraints": [], "partitions": [], "collation_id": 255, "tablespace_ref": "ts1" diff --git a/mysql-test/std_data/dd/sdi/upgrade/actor.json b/mysql-test/std_data/dd/sdi/upgrade/actor.json index 77d5815b2b7a..9cad5b9a006b 100644 --- a/mysql-test/std_data/dd/sdi/upgrade/actor.json +++ b/mysql-test/std_data/dd/sdi/upgrade/actor.json @@ -334,6 +334,7 @@ } ], "foreign_keys": [], + "check_constraints": [], "partitions": [], "collation_id": 33 } diff --git a/mysql-test/std_data/dd/sdi/upgrade/address.json b/mysql-test/std_data/dd/sdi/upgrade/address.json index 642c4fa32969..a1a45a3ddb95 100644 --- a/mysql-test/std_data/dd/sdi/upgrade/address.json +++ b/mysql-test/std_data/dd/sdi/upgrade/address.json @@ -591,6 +591,7 @@ ] } ], + "check_constraints": [], "partitions": [], "collation_id": 33 } diff --git a/mysql-test/std_data/dd/sdi/upgrade/category.json b/mysql-test/std_data/dd/sdi/upgrade/category.json index 0c5e6016eabd..852900c46e89 100644 --- a/mysql-test/std_data/dd/sdi/upgrade/category.json +++ b/mysql-test/std_data/dd/sdi/upgrade/category.json @@ -263,6 +263,7 @@ } ], "foreign_keys": [], + "check_constraints": [], "partitions": [], "collation_id": 33 } diff --git a/mysql-test/std_data/dd/sdi/upgrade/city.json b/mysql-test/std_data/dd/sdi/upgrade/city.json index 90378be858d8..3c91e8d17007 100644 --- a/mysql-test/std_data/dd/sdi/upgrade/city.json +++ b/mysql-test/std_data/dd/sdi/upgrade/city.json @@ -352,6 +352,7 @@ ] } ], + "check_constraints": [], "partitions": [], "collation_id": 33 } diff --git a/mysql-test/std_data/dd/sdi/upgrade/country.json b/mysql-test/std_data/dd/sdi/upgrade/country.json index bc947a7faec5..f061e9e6955b 100644 --- a/mysql-test/std_data/dd/sdi/upgrade/country.json +++ b/mysql-test/std_data/dd/sdi/upgrade/country.json @@ -263,6 +263,7 @@ } ], "foreign_keys": [], + "check_constraints": [], "partitions": [], "collation_id": 33 } diff --git a/mysql-test/std_data/dd/sdi/upgrade/customer.json b/mysql-test/std_data/dd/sdi/upgrade/customer.json index 6aa1f3723506..799d55ed0a68 100644 --- a/mysql-test/std_data/dd/sdi/upgrade/customer.json +++ b/mysql-test/std_data/dd/sdi/upgrade/customer.json @@ -637,6 +637,7 @@ ] } ], + "check_constraints": [], "partitions": [], "collation_id": 33 } diff --git a/mysql-test/std_data/dd/sdi/upgrade/film.json b/mysql-test/std_data/dd/sdi/upgrade/film.json index bce83bee0739..bff5277a04ec 100644 --- a/mysql-test/std_data/dd/sdi/upgrade/film.json +++ b/mysql-test/std_data/dd/sdi/upgrade/film.json @@ -843,6 +843,7 @@ ] } ], + "check_constraints": [], "partitions": [], "collation_id": 33 } diff --git a/mysql-test/std_data/dd/sdi/upgrade/film_actor.json b/mysql-test/std_data/dd/sdi/upgrade/film_actor.json index 0d4a2680c81d..b1fa2ac41694 100644 --- a/mysql-test/std_data/dd/sdi/upgrade/film_actor.json +++ b/mysql-test/std_data/dd/sdi/upgrade/film_actor.json @@ -327,6 +327,7 @@ ] } ], + "check_constraints": [], "partitions": [], "collation_id": 33 } diff --git a/mysql-test/std_data/dd/sdi/upgrade/film_category.json b/mysql-test/std_data/dd/sdi/upgrade/film_category.json index f9ca52257a24..33c89b580cf8 100644 --- a/mysql-test/std_data/dd/sdi/upgrade/film_category.json +++ b/mysql-test/std_data/dd/sdi/upgrade/film_category.json @@ -327,6 +327,7 @@ ] } ], + "check_constraints": [], "partitions": [], "collation_id": 33 } diff --git a/mysql-test/std_data/dd/sdi/upgrade/film_text.json b/mysql-test/std_data/dd/sdi/upgrade/film_text.json index b488dc022e9a..64fa73ebae66 100644 --- a/mysql-test/std_data/dd/sdi/upgrade/film_text.json +++ b/mysql-test/std_data/dd/sdi/upgrade/film_text.json @@ -363,6 +363,7 @@ } ], "foreign_keys": [], + "check_constraints": [], "partitions": [], "collation_id": 33 } diff --git a/mysql-test/std_data/dd/sdi/upgrade/geom.json b/mysql-test/std_data/dd/sdi/upgrade/geom.json index 25f8637a0339..ed9a7455c240 100644 --- a/mysql-test/std_data/dd/sdi/upgrade/geom.json +++ b/mysql-test/std_data/dd/sdi/upgrade/geom.json @@ -376,6 +376,7 @@ } ], "foreign_keys": [], + "check_constraints": [], "partitions": [], "collation_id": 8 } diff --git a/mysql-test/std_data/dd/sdi/upgrade/inventory.json b/mysql-test/std_data/dd/sdi/upgrade/inventory.json index ae296c1a8e39..62455c6fe0f2 100644 --- a/mysql-test/std_data/dd/sdi/upgrade/inventory.json +++ b/mysql-test/std_data/dd/sdi/upgrade/inventory.json @@ -404,6 +404,7 @@ ] } ], + "check_constraints": [], "partitions": [], "collation_id": 33 } diff --git a/mysql-test/std_data/dd/sdi/upgrade/jemp.json b/mysql-test/std_data/dd/sdi/upgrade/jemp.json index dc5cf4fde224..1a9e536abb5f 100644 --- a/mysql-test/std_data/dd/sdi/upgrade/jemp.json +++ b/mysql-test/std_data/dd/sdi/upgrade/jemp.json @@ -286,6 +286,7 @@ } ], "foreign_keys": [], + "check_constraints": [], "partitions": [], "collation_id": 8 } diff --git a/mysql-test/std_data/dd/sdi/upgrade/language.json b/mysql-test/std_data/dd/sdi/upgrade/language.json index 73ada505b044..a00029d02d26 100644 --- a/mysql-test/std_data/dd/sdi/upgrade/language.json +++ b/mysql-test/std_data/dd/sdi/upgrade/language.json @@ -263,6 +263,7 @@ } ], "foreign_keys": [], + "check_constraints": [], "partitions": [], "collation_id": 33 } diff --git a/mysql-test/std_data/dd/sdi/upgrade/mysql.json b/mysql-test/std_data/dd/sdi/upgrade/mysql.json index 6e73437ca1d7..662dcba2ff3d 100644 --- a/mysql-test/std_data/dd/sdi/upgrade/mysql.json +++ b/mysql-test/std_data/dd/sdi/upgrade/mysql.json @@ -221,6 +221,7 @@ } ], "foreign_keys": [], + "check_constraints": [], "partitions": [], "collation_id": X, "tablespace_ref": "mysql" @@ -491,6 +492,7 @@ } ], "foreign_keys": [], + "check_constraints": [], "partitions": [], "collation_id": X, "tablespace_ref": "mysql" @@ -887,6 +889,7 @@ } ], "foreign_keys": [], + "check_constraints": [], "partitions": [], "collation_id": X, "tablespace_ref": "mysql" @@ -1367,6 +1370,7 @@ } ], "foreign_keys": [], + "check_constraints": [], "partitions": [], "collation_id": X, "tablespace_ref": "mysql" @@ -1918,6 +1922,7 @@ } ], "foreign_keys": [], + "check_constraints": [], "partitions": [], "collation_id": X, "tablespace_ref": "mysql" @@ -2301,6 +2306,7 @@ } ], "foreign_keys": [], + "check_constraints": [], "partitions": [], "collation_id": X, "tablespace_ref": "mysql" @@ -2773,6 +2779,560 @@ ] } ], + "check_constraints": [], + "partitions": [], + "collation_id": X, + "tablespace_ref": "mysql" + } +} +} +, +{ + "type": 1, + "id": X, + "object": + { + "mysqld_version_id": X, + "dd_version": X, + "sdi_version": 1, + "dd_object_type": "Table", + "dd_object": { + "name": "check_constraints", + "mysql_version_id": X, + "created": NNN, + "last_altered": NNN, + "hidden": 2, + "options": "avg_row_length=0;explicit_tablespace=1;key_block_size=0;keys_disabled=0;pack_record=1;row_type=2;stats_auto_recalc=0;stats_persistent=0;stats_sample_pages=0;", + "columns": [ + { + "name": "id", + "type": 9, + "is_nullable": false, + "is_zerofill": false, + "is_unsigned": true, + "is_auto_increment": true, + "is_virtual": false, + "hidden": 1, + "ordinal_position": 1, + "char_length": 20, + "numeric_precision": 20, + "numeric_scale": 0, + "numeric_scale_null": false, + "datetime_precision": 0, + "datetime_precision_null": 1, + "has_no_default": false, + "default_value_null": false, + "srs_id_null": true, + "srs_id": 0, + "default_value": "", + "default_value_utf8_null": true, + "default_value_utf8": "", + "default_option": "", + "update_option": "", + "comment": "", + "generation_expression": "", + "generation_expression_utf8": "", + "options": "interval_count=0;", + "se_private_data": "table_id=X", + "column_key": 2, + "column_type_utf8": "bigint(20) unsigned", + "elements": [], + "collation_id": X, + "is_explicit_collation": false + }, + { + "name": "schema_id", + "type": 9, + "is_nullable": false, + "is_zerofill": false, + "is_unsigned": true, + "is_auto_increment": false, + "is_virtual": false, + "hidden": 1, + "ordinal_position": 2, + "char_length": 20, + "numeric_precision": 20, + "numeric_scale": 0, + "numeric_scale_null": false, + "datetime_precision": 0, + "datetime_precision_null": 1, + "has_no_default": true, + "default_value_null": false, + "srs_id_null": true, + "srs_id": 0, + "default_value": "", + "default_value_utf8_null": true, + "default_value_utf8": "", + "default_option": "", + "update_option": "", + "comment": "", + "generation_expression": "", + "generation_expression_utf8": "", + "options": "interval_count=0;", + "se_private_data": "table_id=X", + "column_key": 4, + "column_type_utf8": "bigint(20) unsigned", + "elements": [], + "collation_id": X, + "is_explicit_collation": false + }, + { + "name": "table_id", + "type": 9, + "is_nullable": false, + "is_zerofill": false, + "is_unsigned": true, + "is_auto_increment": false, + "is_virtual": false, + "hidden": 1, + "ordinal_position": 3, + "char_length": 20, + "numeric_precision": 20, + "numeric_scale": 0, + "numeric_scale_null": false, + "datetime_precision": 0, + "datetime_precision_null": 1, + "has_no_default": true, + "default_value_null": false, + "srs_id_null": true, + "srs_id": 0, + "default_value": "", + "default_value_utf8_null": true, + "default_value_utf8": "", + "default_option": "", + "update_option": "", + "comment": "", + "generation_expression": "", + "generation_expression_utf8": "", + "options": "interval_count=0;", + "se_private_data": "table_id=X", + "column_key": 4, + "column_type_utf8": "bigint(20) unsigned", + "elements": [], + "collation_id": X, + "is_explicit_collation": false + }, + { + "name": "name", + "type": 16, + "is_nullable": false, + "is_zerofill": false, + "is_unsigned": false, + "is_auto_increment": false, + "is_virtual": false, + "hidden": 1, + "ordinal_position": 4, + "char_length": 192, + "numeric_precision": 0, + "numeric_scale": 0, + "numeric_scale_null": true, + "datetime_precision": 0, + "datetime_precision_null": 1, + "has_no_default": true, + "default_value_null": false, + "srs_id_null": true, + "srs_id": 0, + "default_value": "", + "default_value_utf8_null": true, + "default_value_utf8": "", + "default_option": "", + "update_option": "", + "comment": "", + "generation_expression": "", + "generation_expression_utf8": "", + "options": "interval_count=0;", + "se_private_data": "table_id=X", + "column_key": 1, + "column_type_utf8": "varchar(64)", + "elements": [], + "collation_id": X, + "is_explicit_collation": true + }, + { + "name": "enforced", + "type": 22, + "is_nullable": false, + "is_zerofill": false, + "is_unsigned": false, + "is_auto_increment": false, + "is_virtual": false, + "hidden": 1, + "ordinal_position": 5, + "char_length": 9, + "numeric_precision": 0, + "numeric_scale": 0, + "numeric_scale_null": true, + "datetime_precision": 0, + "datetime_precision_null": 1, + "has_no_default": true, + "default_value_null": false, + "srs_id_null": true, + "srs_id": 0, + "default_value": "", + "default_value_utf8_null": true, + "default_value_utf8": "", + "default_option": "", + "update_option": "", + "comment": "", + "generation_expression": "", + "generation_expression_utf8": "", + "options": "interval_count=2;", + "se_private_data": "table_id=X", + "column_key": 1, + "column_type_utf8": "enum('NO','YES')", + "elements": [ + { + "name": "Tk8=", "decoded-name": "NO", + "index": 1 + }, + { + "name": "WUVT", "decoded-name": "YES", + "index": 2 + } + ], + "collation_id": X, + "is_explicit_collation": false + }, + { + "name": "check_clause", + "type": 26, + "is_nullable": false, + "is_zerofill": false, + "is_unsigned": false, + "is_auto_increment": false, + "is_virtual": false, + "hidden": 1, + "ordinal_position": 6, + "char_length": 4294967295, + "numeric_precision": 0, + "numeric_scale": 0, + "numeric_scale_null": true, + "datetime_precision": 0, + "datetime_precision_null": 1, + "has_no_default": true, + "default_value_null": false, + "srs_id_null": true, + "srs_id": 0, + "default_value": "", + "default_value_utf8_null": true, + "default_value_utf8": "", + "default_option": "", + "update_option": "", + "comment": "", + "generation_expression": "", + "generation_expression_utf8": "", + "options": "interval_count=0;", + "se_private_data": "table_id=X", + "column_key": 1, + "column_type_utf8": "longblob", + "elements": [], + "collation_id": X, + "is_explicit_collation": true + }, + { + "name": "check_clause_utf8", + "type": 26, + "is_nullable": false, + "is_zerofill": false, + "is_unsigned": false, + "is_auto_increment": false, + "is_virtual": false, + "hidden": 1, + "ordinal_position": 7, + "char_length": 4294967295, + "numeric_precision": 0, + "numeric_scale": 0, + "numeric_scale_null": true, + "datetime_precision": 0, + "datetime_precision_null": 1, + "has_no_default": true, + "default_value_null": false, + "srs_id_null": true, + "srs_id": 0, + "default_value": "", + "default_value_utf8_null": true, + "default_value_utf8": "", + "default_option": "", + "update_option": "", + "comment": "", + "generation_expression": "", + "generation_expression_utf8": "", + "options": "interval_count=0;", + "se_private_data": "table_id=X", + "column_key": 1, + "column_type_utf8": "longtext", + "elements": [], + "collation_id": X, + "is_explicit_collation": false + }, + { + "name": "DB_TRX_ID", + "type": 10, + "is_nullable": false, + "is_zerofill": false, + "is_unsigned": false, + "is_auto_increment": false, + "is_virtual": false, + "hidden": 2, + "ordinal_position": 8, + "char_length": 6, + "numeric_precision": 0, + "numeric_scale": 0, + "numeric_scale_null": true, + "datetime_precision": 0, + "datetime_precision_null": 1, + "has_no_default": false, + "default_value_null": true, + "srs_id_null": true, + "srs_id": 0, + "default_value": "", + "default_value_utf8_null": true, + "default_value_utf8": "", + "default_option": "", + "update_option": "", + "comment": "", + "generation_expression": "", + "generation_expression_utf8": "", + "options": "", + "se_private_data": "table_id=X", + "column_key": 1, + "column_type_utf8": "", + "elements": [], + "collation_id": X, + "is_explicit_collation": false + }, + { + "name": "DB_ROLL_PTR", + "type": 9, + "is_nullable": false, + "is_zerofill": false, + "is_unsigned": false, + "is_auto_increment": false, + "is_virtual": false, + "hidden": 2, + "ordinal_position": 9, + "char_length": 7, + "numeric_precision": 0, + "numeric_scale": 0, + "numeric_scale_null": true, + "datetime_precision": 0, + "datetime_precision_null": 1, + "has_no_default": false, + "default_value_null": true, + "srs_id_null": true, + "srs_id": 0, + "default_value": "", + "default_value_utf8_null": true, + "default_value_utf8": "", + "default_option": "", + "update_option": "", + "comment": "", + "generation_expression": "", + "generation_expression_utf8": "", + "options": "", + "se_private_data": "table_id=X", + "column_key": 1, + "column_type_utf8": "", + "elements": [], + "collation_id": X, + "is_explicit_collation": false + } + ], + "schema_ref": "mysql", + "se_private_id":NNN, + "engine": "InnoDB", + "last_checked_for_upgrade_version_id": X, + "comment": "", + "se_private_data": "autoinc=0;version=0;", + "row_format": 2, + "partition_type": 0, + "partition_expression": "", + "partition_expression_utf8": "", + "default_partitioning": 0, + "subpartition_type": 0, + "subpartition_expression": "", + "subpartition_expression_utf8": "", + "default_subpartitioning": 0, + "indexes": [ + { + "name": "PRIMARY", + "hidden": false, + "is_generated": false, + "ordinal_position": 1, + "comment": "", + "options": "flags=0;", + "se_private_data": "id=A;root=B;space_id=C;table_id=D;trx_id=E", + "type": 1, + "algorithm": 2, + "is_algorithm_explicit": false, + "is_visible": true, + "engine": "InnoDB", + "elements": [ + { + "ordinal_position": 1, + "length": 8, + "order": 2, + "column_opx": 0 + }, + { + "ordinal_position": 2, + "length": 4294967295, + "order": 2, + "column_opx": 7 + }, + { + "ordinal_position": 3, + "length": 4294967295, + "order": 2, + "column_opx": 8 + }, + { + "ordinal_position": 4, + "length": 4294967295, + "order": 2, + "column_opx": 1 + }, + { + "ordinal_position": 5, + "length": 4294967295, + "order": 2, + "column_opx": 2 + }, + { + "ordinal_position": 6, + "length": 4294967295, + "order": 2, + "column_opx": 3 + }, + { + "ordinal_position": 7, + "length": 4294967295, + "order": 2, + "column_opx": 4 + }, + { + "ordinal_position": 8, + "length": 4294967295, + "order": 2, + "column_opx": 5 + }, + { + "ordinal_position": 9, + "length": 4294967295, + "order": 2, + "column_opx": 6 + } + ], + "tablespace_ref": "mysql" + }, + { + "name": "schema_id", + "hidden": false, + "is_generated": false, + "ordinal_position": 2, + "comment": "", + "options": "flags=0;", + "se_private_data": "id=A;root=B;space_id=C;table_id=D;trx_id=E", + "type": 2, + "algorithm": 2, + "is_algorithm_explicit": false, + "is_visible": true, + "engine": "InnoDB", + "elements": [ + { + "ordinal_position": 1, + "length": 8, + "order": 2, + "column_opx": 1 + }, + { + "ordinal_position": 2, + "length": 192, + "order": 2, + "column_opx": 3 + }, + { + "ordinal_position": 3, + "length": 4294967295, + "order": 2, + "column_opx": 0 + } + ], + "tablespace_ref": "mysql" + }, + { + "name": "table_id", + "hidden": false, + "is_generated": false, + "ordinal_position": 3, + "comment": "", + "options": "flags=0;", + "se_private_data": "id=A;root=B;space_id=C;table_id=D;trx_id=E", + "type": 2, + "algorithm": 2, + "is_algorithm_explicit": false, + "is_visible": true, + "engine": "InnoDB", + "elements": [ + { + "ordinal_position": 1, + "length": 8, + "order": 2, + "column_opx": 2 + }, + { + "ordinal_position": 2, + "length": 192, + "order": 2, + "column_opx": 3 + }, + { + "ordinal_position": 3, + "length": 4294967295, + "order": 2, + "column_opx": 0 + } + ], + "tablespace_ref": "mysql" + } + ], + "foreign_keys": [ + { + "name": "check_constraints_ibfk_1", + "match_option": 1, + "update_rule": 1, + "delete_rule": 1, + "unique_constraint_name": "", + "referenced_table_catalog_name": "def", + "referenced_table_schema_name": "mysql", + "referenced_table_name": "schemata", + "elements": [ + { + "column_opx": 1, + "ordinal_position": 1, + "referenced_column_name": "id" + } + ] + }, + { + "name": "check_constraints_ibfk_2", + "match_option": 1, + "update_rule": 1, + "delete_rule": 1, + "unique_constraint_name": "", + "referenced_table_catalog_name": "def", + "referenced_table_schema_name": "mysql", + "referenced_table_name": "tables", + "elements": [ + { + "column_opx": 2, + "ordinal_position": 1, + "referenced_column_name": "id" + } + ] + } + ], + "check_constraints": [], "partitions": [], "collation_id": X, "tablespace_ref": "mysql" @@ -3296,6 +3856,7 @@ ] } ], + "check_constraints": [], "partitions": [], "collation_id": X, "tablespace_ref": "mysql" @@ -3876,6 +4437,7 @@ ] } ], + "check_constraints": [], "partitions": [], "collation_id": X, "tablespace_ref": "mysql" @@ -4164,6 +4726,7 @@ ] } ], + "check_constraints": [], "partitions": [], "collation_id": X, "tablespace_ref": "mysql" @@ -5903,6 +6466,7 @@ ] } ], + "check_constraints": [], "partitions": [], "collation_id": X, "tablespace_ref": "mysql" @@ -7482,6 +8046,7 @@ ] } ], + "check_constraints": [], "partitions": [], "collation_id": X, "tablespace_ref": "mysql" @@ -7905,6 +8470,7 @@ ] } ], + "check_constraints": [], "partitions": [], "collation_id": X, "tablespace_ref": "mysql" @@ -8737,6 +9303,7 @@ ] } ], + "check_constraints": [], "partitions": [], "collation_id": X, "tablespace_ref": "mysql" @@ -9257,6 +9824,7 @@ ] } ], + "check_constraints": [], "partitions": [], "collation_id": X, "tablespace_ref": "mysql" @@ -9727,6 +10295,7 @@ ] } ], + "check_constraints": [], "partitions": [], "collation_id": X, "tablespace_ref": "mysql" @@ -10123,6 +10692,7 @@ } ], "foreign_keys": [], + "check_constraints": [], "partitions": [], "collation_id": X, "tablespace_ref": "mysql" @@ -11038,6 +11608,7 @@ ] } ], + "check_constraints": [], "partitions": [], "collation_id": X, "tablespace_ref": "mysql" @@ -11326,6 +11897,7 @@ ] } ], + "check_constraints": [], "partitions": [], "collation_id": X, "tablespace_ref": "mysql" @@ -12337,6 +12909,7 @@ ] } ], + "check_constraints": [], "partitions": [], "collation_id": X, "tablespace_ref": "mysql" @@ -12813,6 +13386,7 @@ } ], "foreign_keys": [], + "check_constraints": [], "partitions": [], "collation_id": X, "tablespace_ref": "mysql" @@ -14715,6 +15289,7 @@ ] } ], + "check_constraints": [], "partitions": [], "collation_id": X, "tablespace_ref": "mysql" @@ -15252,6 +15827,7 @@ ] } ], + "check_constraints": [], "partitions": [], "collation_id": X, "tablespace_ref": "mysql" @@ -15910,6 +16486,7 @@ ] } ], + "check_constraints": [], "partitions": [], "collation_id": X, "tablespace_ref": "mysql" @@ -16282,6 +16859,7 @@ ] } ], + "check_constraints": [], "partitions": [], "collation_id": X, "tablespace_ref": "mysql" @@ -17180,6 +17758,7 @@ ] } ], + "check_constraints": [], "partitions": [], "collation_id": X, "tablespace_ref": "mysql" @@ -17870,6 +18449,7 @@ } ], "foreign_keys": [], + "check_constraints": [], "partitions": [], "collation_id": X, "tablespace_ref": "mysql" @@ -20017,6 +20597,7 @@ ] } ], + "check_constraints": [], "partitions": [], "collation_id": X, "tablespace_ref": "mysql" @@ -20382,6 +20963,7 @@ ] } ], + "check_constraints": [], "partitions": [], "collation_id": X, "tablespace_ref": "mysql" @@ -20807,6 +21389,7 @@ } ], "foreign_keys": [], + "check_constraints": [], "partitions": [], "collation_id": X, "tablespace_ref": "mysql" @@ -22075,6 +22658,7 @@ ] } ], + "check_constraints": [], "partitions": [], "collation_id": X, "tablespace_ref": "mysql" @@ -22446,6 +23030,7 @@ ] } ], + "check_constraints": [], "partitions": [], "collation_id": X, "tablespace_ref": "mysql" @@ -22817,6 +23402,7 @@ ] } ], + "check_constraints": [], "partitions": [], "collation_id": X, "tablespace_ref": "mysql" @@ -23129,6 +23715,7 @@ } ], "foreign_keys": [], + "check_constraints": [], "partitions": [], "collation_id": X, "tablespace_ref": "mysql" @@ -23492,6 +24079,7 @@ } ], "foreign_keys": [], + "check_constraints": [], "partitions": [], "collation_id": X, "tablespace_ref": "mysql" @@ -23813,6 +24401,7 @@ } ], "foreign_keys": [], + "check_constraints": [], "partitions": [], "collation_id": X, "tablespace_ref": "mysql" @@ -24125,6 +24714,7 @@ } ], "foreign_keys": [], + "check_constraints": [], "partitions": [], "collation_id": X, "tablespace_ref": "mysql" @@ -24395,6 +24985,7 @@ } ], "foreign_keys": [], + "check_constraints": [], "partitions": [], "collation_id": X, "tablespace_ref": "mysql" @@ -25669,6 +26260,7 @@ } ], "foreign_keys": [], + "check_constraints": [], "partitions": [], "collation_id": X, "tablespace_ref": "mysql" @@ -28278,6 +28870,7 @@ } ], "foreign_keys": [], + "check_constraints": [], "partitions": [], "collation_id": X, "tablespace_ref": "mysql" @@ -28875,6 +29468,7 @@ } ], "foreign_keys": [], + "check_constraints": [], "partitions": [], "collation_id": X, "tablespace_ref": "mysql" @@ -29330,6 +29924,7 @@ } ], "foreign_keys": [], + "check_constraints": [], "partitions": [], "collation_id": X, "tablespace_ref": "mysql" @@ -29885,6 +30480,7 @@ } ], "foreign_keys": [], + "check_constraints": [], "partitions": [], "collation_id": X, "tablespace_ref": "mysql" @@ -30370,6 +30966,7 @@ } ], "foreign_keys": [], + "check_constraints": [], "partitions": [], "collation_id": X, "tablespace_ref": "mysql" @@ -31018,6 +31615,7 @@ } ], "foreign_keys": [], + "check_constraints": [], "partitions": [], "collation_id": X, "tablespace_ref": "mysql" @@ -31339,6 +31937,7 @@ } ], "foreign_keys": [], + "check_constraints": [], "partitions": [], "collation_id": X, "tablespace_ref": "mysql" @@ -31567,6 +32166,7 @@ } ], "foreign_keys": [], + "check_constraints": [], "partitions": [], "collation_id": X, "tablespace_ref": "mysql" @@ -32089,6 +32689,7 @@ } ], "foreign_keys": [], + "check_constraints": [], "partitions": [], "collation_id": X, "tablespace_ref": "mysql" @@ -32514,6 +33115,7 @@ } ], "foreign_keys": [], + "check_constraints": [], "partitions": [], "collation_id": X, "tablespace_ref": "mysql" @@ -32855,6 +33457,7 @@ } ], "foreign_keys": [], + "check_constraints": [], "partitions": [], "collation_id": X, "tablespace_ref": "mysql" @@ -33083,6 +33686,7 @@ } ], "foreign_keys": [], + "check_constraints": [], "partitions": [], "collation_id": X, "tablespace_ref": "mysql" @@ -33340,6 +33944,7 @@ } ], "foreign_keys": [], + "check_constraints": [], "partitions": [], "collation_id": X, "tablespace_ref": "mysql" @@ -33568,6 +34173,7 @@ } ], "foreign_keys": [], + "check_constraints": [], "partitions": [], "collation_id": X, "tablespace_ref": "mysql" @@ -33805,6 +34411,7 @@ } ], "foreign_keys": [], + "check_constraints": [], "partitions": [], "collation_id": X, "tablespace_ref": "mysql" @@ -34075,6 +34682,7 @@ } ], "foreign_keys": [], + "check_constraints": [], "partitions": [], "collation_id": X, "tablespace_ref": "mysql" @@ -34429,6 +35037,7 @@ } ], "foreign_keys": [], + "check_constraints": [], "partitions": [], "collation_id": X, "tablespace_ref": "mysql" @@ -34657,6 +35266,7 @@ } ], "foreign_keys": [], + "check_constraints": [], "partitions": [], "collation_id": X, "tablespace_ref": "mysql" @@ -35179,6 +35789,7 @@ } ], "foreign_keys": [], + "check_constraints": [], "partitions": [], "collation_id": X, "tablespace_ref": "mysql" @@ -36457,6 +37068,7 @@ } ], "foreign_keys": [], + "check_constraints": [], "partitions": [], "collation_id": X, "tablespace_ref": "mysql" @@ -37147,6 +37759,7 @@ } ], "foreign_keys": [], + "check_constraints": [], "partitions": [], "collation_id": X, "tablespace_ref": "mysql" @@ -37417,6 +38030,7 @@ } ], "foreign_keys": [], + "check_constraints": [], "partitions": [], "collation_id": X, "tablespace_ref": "mysql" @@ -37765,6 +38379,7 @@ } ], "foreign_keys": [], + "check_constraints": [], "partitions": [], "collation_id": X, "tablespace_ref": "mysql" @@ -38197,6 +38812,7 @@ } ], "foreign_keys": [], + "check_constraints": [], "partitions": [], "collation_id": X, "tablespace_ref": "mysql" diff --git a/mysql-test/std_data/dd/sdi/upgrade/opening_lines.json b/mysql-test/std_data/dd/sdi/upgrade/opening_lines.json index 0e09a044fd03..dab7f36b1792 100644 --- a/mysql-test/std_data/dd/sdi/upgrade/opening_lines.json +++ b/mysql-test/std_data/dd/sdi/upgrade/opening_lines.json @@ -399,6 +399,7 @@ } ], "foreign_keys": [], + "check_constraints": [], "partitions": [], "collation_id": 8 } diff --git a/mysql-test/std_data/dd/sdi/upgrade/payment.json b/mysql-test/std_data/dd/sdi/upgrade/payment.json index 536f07e2bb95..128282a7b908 100644 --- a/mysql-test/std_data/dd/sdi/upgrade/payment.json +++ b/mysql-test/std_data/dd/sdi/upgrade/payment.json @@ -570,6 +570,7 @@ ] } ], + "check_constraints": [], "partitions": [], "collation_id": 33 } diff --git a/mysql-test/std_data/dd/sdi/upgrade/rental.json b/mysql-test/std_data/dd/sdi/upgrade/rental.json index efa98d6b2deb..018fdc496b92 100644 --- a/mysql-test/std_data/dd/sdi/upgrade/rental.json +++ b/mysql-test/std_data/dd/sdi/upgrade/rental.json @@ -611,6 +611,7 @@ ] } ], + "check_constraints": [], "partitions": [], "collation_id": 33 } diff --git a/mysql-test/std_data/dd/sdi/upgrade/staff.json b/mysql-test/std_data/dd/sdi/upgrade/staff.json index 97abfd80419f..b8aa51a92321 100644 --- a/mysql-test/std_data/dd/sdi/upgrade/staff.json +++ b/mysql-test/std_data/dd/sdi/upgrade/staff.json @@ -692,6 +692,7 @@ ] } ], + "check_constraints": [], "partitions": [], "collation_id": 33 } diff --git a/mysql-test/std_data/dd/sdi/upgrade/store.json b/mysql-test/std_data/dd/sdi/upgrade/store.json index c715c141f079..db30e7ded969 100644 --- a/mysql-test/std_data/dd/sdi/upgrade/store.json +++ b/mysql-test/std_data/dd/sdi/upgrade/store.json @@ -398,6 +398,7 @@ ] } ], + "check_constraints": [], "partitions": [], "collation_id": 33 } diff --git a/mysql-test/std_data/dd/sdi/upgrade/t_blob.json b/mysql-test/std_data/dd/sdi/upgrade/t_blob.json index a3b783371694..e886b885758d 100644 --- a/mysql-test/std_data/dd/sdi/upgrade/t_blob.json +++ b/mysql-test/std_data/dd/sdi/upgrade/t_blob.json @@ -311,6 +311,7 @@ } ], "foreign_keys": [], + "check_constraints": [], "partitions": [], "collation_id": 8 } diff --git a/mysql-test/std_data/dd/sdi/upgrade/t_blob_myisam.json b/mysql-test/std_data/dd/sdi/upgrade/t_blob_myisam.json index a89b4bb41058..fcca18e126bf 100644 --- a/mysql-test/std_data/dd/sdi/upgrade/t_blob_myisam.json +++ b/mysql-test/std_data/dd/sdi/upgrade/t_blob_myisam.json @@ -311,6 +311,7 @@ } ], "foreign_keys": [], + "check_constraints": [], "partitions": [], "collation_id": 8 } diff --git a/mysql-test/std_data/dd/sdi/upgrade/t_compressed.json b/mysql-test/std_data/dd/sdi/upgrade/t_compressed.json index 331249ff380a..aa9540da398a 100644 --- a/mysql-test/std_data/dd/sdi/upgrade/t_compressed.json +++ b/mysql-test/std_data/dd/sdi/upgrade/t_compressed.json @@ -221,6 +221,7 @@ } ], "foreign_keys": [], + "check_constraints": [], "partitions": [], "collation_id": 8 } diff --git a/mysql-test/std_data/dd/sdi/upgrade/t_compressed2.json b/mysql-test/std_data/dd/sdi/upgrade/t_compressed2.json index afa184a78763..4c07700599be 100644 --- a/mysql-test/std_data/dd/sdi/upgrade/t_compressed2.json +++ b/mysql-test/std_data/dd/sdi/upgrade/t_compressed2.json @@ -221,6 +221,7 @@ } ], "foreign_keys": [], + "check_constraints": [], "partitions": [], "collation_id": 8 } diff --git a/mysql-test/std_data/dd/sdi/upgrade/t_compressed3.json b/mysql-test/std_data/dd/sdi/upgrade/t_compressed3.json index 9b1ffb109c37..832b564fd151 100644 --- a/mysql-test/std_data/dd/sdi/upgrade/t_compressed3.json +++ b/mysql-test/std_data/dd/sdi/upgrade/t_compressed3.json @@ -221,6 +221,7 @@ } ], "foreign_keys": [], + "check_constraints": [], "partitions": [], "collation_id": 8 } diff --git a/mysql-test/std_data/dd/sdi/upgrade/t_dynamic.json b/mysql-test/std_data/dd/sdi/upgrade/t_dynamic.json index 1b74f6bacd56..0832de390a8c 100644 --- a/mysql-test/std_data/dd/sdi/upgrade/t_dynamic.json +++ b/mysql-test/std_data/dd/sdi/upgrade/t_dynamic.json @@ -221,6 +221,7 @@ } ], "foreign_keys": [], + "check_constraints": [], "partitions": [], "collation_id": 8 } diff --git a/mysql-test/std_data/dd/sdi/upgrade/t_gen_stored.json b/mysql-test/std_data/dd/sdi/upgrade/t_gen_stored.json index e0513ee60e1c..4d5a2746bd16 100755 --- a/mysql-test/std_data/dd/sdi/upgrade/t_gen_stored.json +++ b/mysql-test/std_data/dd/sdi/upgrade/t_gen_stored.json @@ -263,6 +263,7 @@ } ], "foreign_keys": [], + "check_constraints": [], "partitions": [], "collation_id": 8 } diff --git a/mysql-test/std_data/dd/sdi/upgrade/t_json.json b/mysql-test/std_data/dd/sdi/upgrade/t_json.json index 1b9dc627a954..21a0653d12ef 100644 --- a/mysql-test/std_data/dd/sdi/upgrade/t_json.json +++ b/mysql-test/std_data/dd/sdi/upgrade/t_json.json @@ -221,6 +221,7 @@ } ], "foreign_keys": [], + "check_constraints": [], "partitions": [], "collation_id": 8 } diff --git a/mysql-test/std_data/dd/sdi/upgrade/test_tablespace_2.json b/mysql-test/std_data/dd/sdi/upgrade/test_tablespace_2.json index c344e03286f2..b05f8f915bfe 100644 --- a/mysql-test/std_data/dd/sdi/upgrade/test_tablespace_2.json +++ b/mysql-test/std_data/dd/sdi/upgrade/test_tablespace_2.json @@ -263,6 +263,7 @@ } ], "foreign_keys": [], + "check_constraints": [], "partitions": [], "collation_id": 8, "tablespace_ref": "tbsp1" @@ -533,6 +534,7 @@ } ], "foreign_keys": [], + "check_constraints": [], "partitions": [], "collation_id": 8, "tablespace_ref": "tbsp1" diff --git a/mysql-test/std_data/dd/sdi/upgrade/test_tablespace_3.json b/mysql-test/std_data/dd/sdi/upgrade/test_tablespace_3.json index 7bc577bb2c3a..d440b580ab27 100644 --- a/mysql-test/std_data/dd/sdi/upgrade/test_tablespace_3.json +++ b/mysql-test/std_data/dd/sdi/upgrade/test_tablespace_3.json @@ -221,6 +221,7 @@ } ], "foreign_keys": [], + "check_constraints": [], "partitions": [], "collation_id": 8, "tablespace_ref": "tbsp2" diff --git a/mysql-test/std_data/dd/sdi/upgrade/vt2.json b/mysql-test/std_data/dd/sdi/upgrade/vt2.json index 685ae82d29c7..46bd5f0ceae3 100644 --- a/mysql-test/std_data/dd/sdi/upgrade/vt2.json +++ b/mysql-test/std_data/dd/sdi/upgrade/vt2.json @@ -250,6 +250,7 @@ } ], "foreign_keys": [], + "check_constraints": [], "partitions": [], "collation_id": 8 } diff --git a/mysql-test/std_data/dd/sdi/upgrade_partition/sys_config.json b/mysql-test/std_data/dd/sdi/upgrade_partition/sys_config.json index 463418e8b3ef..c53ed917bfd6 100755 --- a/mysql-test/std_data/dd/sdi/upgrade_partition/sys_config.json +++ b/mysql-test/std_data/dd/sdi/upgrade_partition/sys_config.json @@ -305,6 +305,7 @@ } ], "foreign_keys": [], + "check_constraints": [], "partitions": [], "collation_id": 33 } diff --git a/mysql-test/std_data/dd/sdi/upgrade_partition/t1#p#p0.json b/mysql-test/std_data/dd/sdi/upgrade_partition/t1#p#p0.json index fa4c021db206..23d697a84007 100755 --- a/mysql-test/std_data/dd/sdi/upgrade_partition/t1#p#p0.json +++ b/mysql-test/std_data/dd/sdi/upgrade_partition/t1#p#p0.json @@ -262,6 +262,7 @@ } ], "foreign_keys": [], + "check_constraints": [], "partitions": [ { "name": "p0", diff --git a/mysql-test/std_data/upgrade/data_80014.zip b/mysql-test/std_data/upgrade/data_80014.zip new file mode 100644 index 000000000000..167f0b4eb050 Binary files /dev/null and b/mysql-test/std_data/upgrade/data_80014.zip differ diff --git a/mysql-test/suite/funcs_1/r/is_columns_is_ci.result b/mysql-test/suite/funcs_1/r/is_columns_is_ci.result index fa417c6b0844..f1bdb22d2e85 100644 --- a/mysql-test/suite/funcs_1/r/is_columns_is_ci.result +++ b/mysql-test/suite/funcs_1/r/is_columns_is_ci.result @@ -10,6 +10,10 @@ def information_schema CHARACTER_SETS CHARACTER_SET_NAME 1 NULL NO varchar 64 19 def information_schema CHARACTER_SETS DEFAULT_COLLATE_NAME 2 NULL NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NULL def information_schema CHARACTER_SETS DESCRIPTION 3 NULL NO varchar 2048 6144 NULL NULL NULL utf8 utf8_general_ci varchar(2048) select NULL def information_schema CHARACTER_SETS MAXLEN 4 NULL NO int NULL NULL 10 0 NULL NULL NULL int(10) unsigned select NULL +def information_schema CHECK_CONSTRAINTS CONSTRAINT_CATALOG 1 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_bin varchar(64) select NULL +def information_schema CHECK_CONSTRAINTS CONSTRAINT_SCHEMA 2 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_bin varchar(64) select NULL +def information_schema CHECK_CONSTRAINTS CONSTRAINT_NAME 3 NULL NO varchar 64 192 NULL NULL NULL utf8 utf8_bin varchar(64) select NULL +def information_schema CHECK_CONSTRAINTS CHECK_CLAUSE 4 NULL NO longtext 4294967295 4294967295 NULL NULL NULL utf8 utf8_bin longtext select NULL def information_schema COLLATIONS COLLATION_NAME 1 NULL NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NULL def information_schema COLLATIONS CHARACTER_SET_NAME 2 NULL NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NULL def information_schema COLLATIONS ID 3 0 NO bigint NULL NULL 20 0 NULL NULL NULL bigint(20) unsigned select NULL @@ -326,6 +330,7 @@ def information_schema TABLE_CONSTRAINTS CONSTRAINT_NAME 3 NULL NO varchar 64 19 def information_schema TABLE_CONSTRAINTS TABLE_SCHEMA 4 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_bin varchar(64) select NULL def information_schema TABLE_CONSTRAINTS TABLE_NAME 5 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_bin varchar(64) select NULL def information_schema TABLE_CONSTRAINTS CONSTRAINT_TYPE 6 NO varchar 11 33 NULL NULL NULL utf8 utf8_bin varchar(11) select NULL +def information_schema TABLE_CONSTRAINTS ENFORCED 7 NO varchar 3 9 NULL NULL NULL utf8 utf8_general_ci varchar(3) select NULL def information_schema TABLE_PRIVILEGES GRANTEE 1 NO varchar 27 81 NULL NULL NULL utf8 utf8_general_ci varchar(81) select NULL def information_schema TABLE_PRIVILEGES TABLE_CATALOG 2 NO varchar 170 512 NULL NULL NULL utf8 utf8_general_ci varchar(512) select NULL def information_schema TABLE_PRIVILEGES TABLE_SCHEMA 3 NO varchar 21 64 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NULL @@ -462,6 +467,10 @@ COL_CML TABLE_SCHEMA TABLE_NAME COLUMN_NAME DATA_TYPE CHARACTER_MAXIMUM_LENGTH C 3.0000 information_schema CHARACTER_SETS DEFAULT_COLLATE_NAME varchar 64 192 utf8 utf8_general_ci varchar(64) 3.0000 information_schema CHARACTER_SETS DESCRIPTION varchar 2048 6144 utf8 utf8_general_ci varchar(2048) NULL information_schema CHARACTER_SETS MAXLEN int NULL NULL NULL NULL int(10) unsigned +3.0000 information_schema CHECK_CONSTRAINTS CONSTRAINT_CATALOG varchar 64 192 utf8 utf8_bin varchar(64) +3.0000 information_schema CHECK_CONSTRAINTS CONSTRAINT_SCHEMA varchar 64 192 utf8 utf8_bin varchar(64) +3.0000 information_schema CHECK_CONSTRAINTS CONSTRAINT_NAME varchar 64 192 utf8 utf8_bin varchar(64) +1.0000 information_schema CHECK_CONSTRAINTS CHECK_CLAUSE longtext 4294967295 4294967295 utf8 utf8_bin longtext 3.0000 information_schema COLLATIONS COLLATION_NAME varchar 64 192 utf8 utf8_general_ci varchar(64) 3.0000 information_schema COLLATIONS CHARACTER_SET_NAME varchar 64 192 utf8 utf8_general_ci varchar(64) NULL information_schema COLLATIONS ID bigint NULL NULL NULL NULL bigint(20) unsigned @@ -778,6 +787,7 @@ NULL information_schema TABLESPACES NODEGROUP_ID bigint NULL NULL NULL NULL bigi 3.0000 information_schema TABLE_CONSTRAINTS TABLE_SCHEMA varchar 64 192 utf8 utf8_bin varchar(64) 3.0000 information_schema TABLE_CONSTRAINTS TABLE_NAME varchar 64 192 utf8 utf8_bin varchar(64) 3.0000 information_schema TABLE_CONSTRAINTS CONSTRAINT_TYPE varchar 11 33 utf8 utf8_bin varchar(11) +3.0000 information_schema TABLE_CONSTRAINTS ENFORCED varchar 3 9 utf8 utf8_general_ci varchar(3) 3.0000 information_schema TABLE_PRIVILEGES GRANTEE varchar 27 81 utf8 utf8_general_ci varchar(81) 3.0118 information_schema TABLE_PRIVILEGES TABLE_CATALOG varchar 170 512 utf8 utf8_general_ci varchar(512) 3.0476 information_schema TABLE_PRIVILEGES TABLE_SCHEMA varchar 21 64 utf8 utf8_general_ci varchar(64) diff --git a/mysql-test/suite/funcs_1/r/is_columns_is_cs.result b/mysql-test/suite/funcs_1/r/is_columns_is_cs.result index 5ed3f804bfcd..4ee9575c6ace 100644 --- a/mysql-test/suite/funcs_1/r/is_columns_is_cs.result +++ b/mysql-test/suite/funcs_1/r/is_columns_is_cs.result @@ -10,6 +10,10 @@ def information_schema CHARACTER_SETS CHARACTER_SET_NAME 1 NULL NO varchar 64 19 def information_schema CHARACTER_SETS DEFAULT_COLLATE_NAME 2 NULL NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NULL def information_schema CHARACTER_SETS DESCRIPTION 3 NULL NO varchar 2048 6144 NULL NULL NULL utf8 utf8_general_ci varchar(2048) select NULL def information_schema CHARACTER_SETS MAXLEN 4 NULL NO int NULL NULL 10 0 NULL NULL NULL int(10) unsigned select NULL +def information_schema CHECK_CONSTRAINTS CONSTRAINT_CATALOG 1 NULL NO varchar 64 192 NULL NULL NULL utf8 utf8_bin varchar(64) select NULL +def information_schema CHECK_CONSTRAINTS CONSTRAINT_SCHEMA 2 NULL NO varchar 64 192 NULL NULL NULL utf8 utf8_bin varchar(64) select NULL +def information_schema CHECK_CONSTRAINTS CONSTRAINT_NAME 3 NULL NO varchar 64 192 NULL NULL NULL utf8 utf8_bin varchar(64) select NULL +def information_schema CHECK_CONSTRAINTS CHECK_CLAUSE 4 NULL NO longtext 4294967295 4294967295 NULL NULL NULL utf8 utf8_bin longtext select NULL def information_schema COLLATIONS COLLATION_NAME 1 NULL NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NULL def information_schema COLLATIONS CHARACTER_SET_NAME 2 NULL NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NULL def information_schema COLLATIONS ID 3 0 NO bigint NULL NULL 20 0 NULL NULL NULL bigint(20) unsigned select NULL @@ -326,6 +330,7 @@ def information_schema TABLE_CONSTRAINTS CONSTRAINT_NAME 3 NULL NO varchar 64 19 def information_schema TABLE_CONSTRAINTS TABLE_SCHEMA 4 NULL NO varchar 64 192 NULL NULL NULL utf8 utf8_bin varchar(64) select NULL def information_schema TABLE_CONSTRAINTS TABLE_NAME 5 NULL NO varchar 64 192 NULL NULL NULL utf8 utf8_bin varchar(64) select NULL def information_schema TABLE_CONSTRAINTS CONSTRAINT_TYPE 6 NO varchar 11 33 NULL NULL NULL utf8 utf8_bin varchar(11) select NULL +def information_schema TABLE_CONSTRAINTS ENFORCED 7 NO varchar 3 9 NULL NULL NULL utf8 utf8_general_ci varchar(3) select NULL def information_schema TABLE_PRIVILEGES GRANTEE 1 NO varchar 27 81 NULL NULL NULL utf8 utf8_general_ci varchar(81) select NULL def information_schema TABLE_PRIVILEGES TABLE_CATALOG 2 NO varchar 170 512 NULL NULL NULL utf8 utf8_general_ci varchar(512) select NULL def information_schema TABLE_PRIVILEGES TABLE_SCHEMA 3 NO varchar 21 64 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NULL @@ -462,6 +467,10 @@ COL_CML TABLE_SCHEMA TABLE_NAME COLUMN_NAME DATA_TYPE CHARACTER_MAXIMUM_LENGTH C 3.0000 information_schema CHARACTER_SETS DEFAULT_COLLATE_NAME varchar 64 192 utf8 utf8_general_ci varchar(64) 3.0000 information_schema CHARACTER_SETS DESCRIPTION varchar 2048 6144 utf8 utf8_general_ci varchar(2048) NULL information_schema CHARACTER_SETS MAXLEN int NULL NULL NULL NULL int(10) unsigned +3.0000 information_schema CHECK_CONSTRAINTS CONSTRAINT_CATALOG varchar 64 192 utf8 utf8_bin varchar(64) +3.0000 information_schema CHECK_CONSTRAINTS CONSTRAINT_SCHEMA varchar 64 192 utf8 utf8_bin varchar(64) +3.0000 information_schema CHECK_CONSTRAINTS CONSTRAINT_NAME varchar 64 192 utf8 utf8_bin varchar(64) +1.0000 information_schema CHECK_CONSTRAINTS CHECK_CLAUSE longtext 4294967295 4294967295 utf8 utf8_bin longtext 3.0000 information_schema COLLATIONS COLLATION_NAME varchar 64 192 utf8 utf8_general_ci varchar(64) 3.0000 information_schema COLLATIONS CHARACTER_SET_NAME varchar 64 192 utf8 utf8_general_ci varchar(64) NULL information_schema COLLATIONS ID bigint NULL NULL NULL NULL bigint(20) unsigned @@ -778,6 +787,7 @@ NULL information_schema TABLESPACES NODEGROUP_ID bigint NULL NULL NULL NULL bigi 3.0000 information_schema TABLE_CONSTRAINTS TABLE_SCHEMA varchar 64 192 utf8 utf8_bin varchar(64) 3.0000 information_schema TABLE_CONSTRAINTS TABLE_NAME varchar 64 192 utf8 utf8_bin varchar(64) 3.0000 information_schema TABLE_CONSTRAINTS CONSTRAINT_TYPE varchar 11 33 utf8 utf8_bin varchar(11) +3.0000 information_schema TABLE_CONSTRAINTS ENFORCED varchar 3 9 utf8 utf8_general_ci varchar(3) 3.0000 information_schema TABLE_PRIVILEGES GRANTEE varchar 27 81 utf8 utf8_general_ci varchar(81) 3.0118 information_schema TABLE_PRIVILEGES TABLE_CATALOG varchar 170 512 utf8 utf8_general_ci varchar(512) 3.0476 information_schema TABLE_PRIVILEGES TABLE_SCHEMA varchar 21 64 utf8 utf8_general_ci varchar(64) diff --git a/mysql-test/suite/funcs_1/r/is_table_constraints.result b/mysql-test/suite/funcs_1/r/is_table_constraints.result index a333771bd5d4..b51450b0eb32 100644 --- a/mysql-test/suite/funcs_1/r/is_table_constraints.result +++ b/mysql-test/suite/funcs_1/r/is_table_constraints.result @@ -34,9 +34,10 @@ CONSTRAINT_NAME varchar(64) NO NULL TABLE_SCHEMA varchar(64) NO NULL TABLE_NAME varchar(64) NO NULL CONSTRAINT_TYPE varchar(11) NO +ENFORCED varchar(3) NO SHOW CREATE TABLE information_schema.TABLE_CONSTRAINTS; View Create View character_set_client collation_connection -TABLE_CONSTRAINTS CREATE ALGORITHM=UNDEFINED DEFINER=`mysql.infoschema`@`localhost` SQL SECURITY DEFINER VIEW `information_schema`.`TABLE_CONSTRAINTS` AS (select `cat`.`name` AS `CONSTRAINT_CATALOG`,`sch`.`name` AS `CONSTRAINT_SCHEMA`,`idx`.`name` AS `CONSTRAINT_NAME`,`sch`.`name` AS `TABLE_SCHEMA`,`tbl`.`name` AS `TABLE_NAME`,if((`idx`.`type` = 'PRIMARY'),'PRIMARY KEY',`idx`.`type`) AS `CONSTRAINT_TYPE` from (((`mysql`.`indexes` `idx` join `mysql`.`tables` `tbl` on((`idx`.`table_id` = `tbl`.`id`))) join `mysql`.`schemata` `sch` on((`tbl`.`schema_id` = `sch`.`id`))) join `mysql`.`catalogs` `cat` on(((`cat`.`id` = `sch`.`catalog_id`) and (`idx`.`type` in ('PRIMARY','UNIQUE'))))) where (can_access_table(`sch`.`name`,`tbl`.`name`) and is_visible_dd_object(`tbl`.`hidden`,`idx`.`hidden`))) union (select `cat`.`name` AS `CONSTRAINT_CATALOG`,`sch`.`name` AS `CONSTRAINT_SCHEMA`,(`fk`.`name` collate utf8_tolower_ci) AS `CONSTRAINT_NAME`,`sch`.`name` AS `TABLE_SCHEMA`,`tbl`.`name` AS `TABLE_NAME`,'FOREIGN KEY' AS `CONSTRAINT_TYPE` from (((`mysql`.`foreign_keys` `fk` join `mysql`.`tables` `tbl` on((`fk`.`table_id` = `tbl`.`id`))) join `mysql`.`schemata` `sch` on((`tbl`.`schema_id` = `sch`.`id`))) join `mysql`.`catalogs` `cat` on((`cat`.`id` = `sch`.`catalog_id`))) where (can_access_table(`sch`.`name`,`tbl`.`name`) and is_visible_dd_object(`tbl`.`hidden`))) utf8 utf8_general_ci +TABLE_CONSTRAINTS CREATE ALGORITHM=UNDEFINED DEFINER=`mysql.infoschema`@`localhost` SQL SECURITY DEFINER VIEW `information_schema`.`TABLE_CONSTRAINTS` AS (select `cat`.`name` AS `CONSTRAINT_CATALOG`,`sch`.`name` AS `CONSTRAINT_SCHEMA`,`idx`.`name` AS `CONSTRAINT_NAME`,`sch`.`name` AS `TABLE_SCHEMA`,`tbl`.`name` AS `TABLE_NAME`,if((`idx`.`type` = 'PRIMARY'),'PRIMARY KEY',`idx`.`type`) AS `CONSTRAINT_TYPE`,'YES' AS `ENFORCED` from (((`mysql`.`indexes` `idx` join `mysql`.`tables` `tbl` on((`idx`.`table_id` = `tbl`.`id`))) join `mysql`.`schemata` `sch` on((`tbl`.`schema_id` = `sch`.`id`))) join `mysql`.`catalogs` `cat` on(((`cat`.`id` = `sch`.`catalog_id`) and (`idx`.`type` in ('PRIMARY','UNIQUE'))))) where (can_access_table(`sch`.`name`,`tbl`.`name`) and is_visible_dd_object(`tbl`.`hidden`,`idx`.`hidden`))) union (select `cat`.`name` AS `CONSTRAINT_CATALOG`,`sch`.`name` AS `CONSTRAINT_SCHEMA`,(`fk`.`name` collate utf8_tolower_ci) AS `CONSTRAINT_NAME`,`sch`.`name` AS `TABLE_SCHEMA`,`tbl`.`name` AS `TABLE_NAME`,'FOREIGN KEY' AS `CONSTRAINT_TYPE`,'YES' AS `ENFORCED` from (((`mysql`.`foreign_keys` `fk` join `mysql`.`tables` `tbl` on((`fk`.`table_id` = `tbl`.`id`))) join `mysql`.`schemata` `sch` on((`tbl`.`schema_id` = `sch`.`id`))) join `mysql`.`catalogs` `cat` on((`cat`.`id` = `sch`.`catalog_id`))) where (can_access_table(`sch`.`name`,`tbl`.`name`) and is_visible_dd_object(`tbl`.`hidden`))) union (select `cat`.`name` AS `CONSTRAINT_CATALOG`,`sch`.`name` AS `CONSTRAINT_SCHEMA`,`cc`.`name` AS `CONSTRAINT_NAME`,`sch`.`name` AS `TABLE_SCHEMA`,`tbl`.`name` AS `TABLE_NAME`,'CHECK' AS `CONSTRAINT_TYPE`,`cc`.`enforced` AS `ENFORCED` from (((`mysql`.`check_constraints` `cc` join `mysql`.`tables` `tbl` on((`cc`.`table_id` = `tbl`.`id`))) join `mysql`.`schemata` `sch` on((`tbl`.`schema_id` = `sch`.`id`))) join `mysql`.`catalogs` `cat` on((`cat`.`id` = `sch`.`catalog_id`))) where (can_access_table(`sch`.`name`,`tbl`.`name`) and is_visible_dd_object(`tbl`.`hidden`))) utf8 utf8_general_ci SHOW COLUMNS FROM information_schema.TABLE_CONSTRAINTS; Field Type Null Key Default Extra CONSTRAINT_CATALOG varchar(64) NO NULL @@ -45,6 +46,7 @@ CONSTRAINT_NAME varchar(64) NO NULL TABLE_SCHEMA varchar(64) NO NULL TABLE_NAME varchar(64) NO NULL CONSTRAINT_TYPE varchar(11) NO +ENFORCED varchar(3) NO SELECT constraint_catalog, constraint_schema, constraint_name, table_schema, table_name FROM information_schema.table_constraints @@ -201,11 +203,11 @@ GRANT SELECT (`f5`) ON `db_datadict`.`t1` TO `testuser1`@`localhost` SELECT * FROM information_schema.table_constraints WHERE table_schema = 'db_datadict' ORDER BY table_schema,table_name, constraint_name; -CONSTRAINT_CATALOG CONSTRAINT_SCHEMA CONSTRAINT_NAME TABLE_SCHEMA TABLE_NAME CONSTRAINT_TYPE -def db_datadict my_idx1 db_datadict t1 UNIQUE -def db_datadict my_idx2 db_datadict t1 UNIQUE -def db_datadict PRIMARY db_datadict t1 PRIMARY KEY -def db_datadict PRIMARY db_datadict t2 PRIMARY KEY +CONSTRAINT_CATALOG CONSTRAINT_SCHEMA CONSTRAINT_NAME TABLE_SCHEMA TABLE_NAME CONSTRAINT_TYPE ENFORCED +def db_datadict my_idx1 db_datadict t1 UNIQUE YES +def db_datadict my_idx2 db_datadict t1 UNIQUE YES +def db_datadict PRIMARY db_datadict t1 PRIMARY KEY YES +def db_datadict PRIMARY db_datadict t2 PRIMARY KEY YES SHOW INDEXES FROM db_datadict.t1; Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment Visible Expression t1 0 PRIMARY 1 f1 ### ### ### ### ### ### ### YES NULL @@ -225,10 +227,10 @@ GRANT SELECT (`f5`) ON `db_datadict`.`t1` TO `testuser1`@`localhost` SELECT * FROM information_schema.table_constraints WHERE table_schema = 'db_datadict' ORDER BY table_schema,table_name, constraint_name; -CONSTRAINT_CATALOG CONSTRAINT_SCHEMA CONSTRAINT_NAME TABLE_SCHEMA TABLE_NAME CONSTRAINT_TYPE -def db_datadict my_idx1 db_datadict t1 UNIQUE -def db_datadict my_idx2 db_datadict t1 UNIQUE -def db_datadict PRIMARY db_datadict t1 PRIMARY KEY +CONSTRAINT_CATALOG CONSTRAINT_SCHEMA CONSTRAINT_NAME TABLE_SCHEMA TABLE_NAME CONSTRAINT_TYPE ENFORCED +def db_datadict my_idx1 db_datadict t1 UNIQUE YES +def db_datadict my_idx2 db_datadict t1 UNIQUE YES +def db_datadict PRIMARY db_datadict t1 PRIMARY KEY YES SHOW INDEXES FROM db_datadict.t1; Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment Visible Expression t1 0 PRIMARY 1 f1 ### ### ### ### ### ### ### YES NULL diff --git a/mysql-test/suite/funcs_1/r/is_table_constraints_ci.result b/mysql-test/suite/funcs_1/r/is_table_constraints_ci.result index 9f87e5972626..37352579fe6f 100644 --- a/mysql-test/suite/funcs_1/r/is_table_constraints_ci.result +++ b/mysql-test/suite/funcs_1/r/is_table_constraints_ci.result @@ -34,9 +34,10 @@ CONSTRAINT_NAME varchar(64) NO NULL TABLE_SCHEMA varchar(64) YES NULL TABLE_NAME varchar(64) YES NULL CONSTRAINT_TYPE varchar(11) NO +ENFORCED varchar(3) NO SHOW CREATE TABLE information_schema.TABLE_CONSTRAINTS; View Create View character_set_client collation_connection -TABLE_CONSTRAINTS CREATE ALGORITHM=UNDEFINED DEFINER=`mysql.infoschema`@`localhost` SQL SECURITY DEFINER VIEW `information_schema`.`TABLE_CONSTRAINTS` AS (select (`cat`.`name` collate utf8_tolower_ci) AS `CONSTRAINT_CATALOG`,(`sch`.`name` collate utf8_tolower_ci) AS `CONSTRAINT_SCHEMA`,`idx`.`name` AS `CONSTRAINT_NAME`,(`sch`.`name` collate utf8_tolower_ci) AS `TABLE_SCHEMA`,(`tbl`.`name` collate utf8_tolower_ci) AS `TABLE_NAME`,if((`idx`.`type` = 'PRIMARY'),'PRIMARY KEY',`idx`.`type`) AS `CONSTRAINT_TYPE` from (((`mysql`.`indexes` `idx` join `mysql`.`tables` `tbl` on((`idx`.`table_id` = `tbl`.`id`))) join `mysql`.`schemata` `sch` on((`tbl`.`schema_id` = `sch`.`id`))) join `mysql`.`catalogs` `cat` on(((`cat`.`id` = `sch`.`catalog_id`) and (`idx`.`type` in ('PRIMARY','UNIQUE'))))) where (can_access_table(`sch`.`name`,`tbl`.`name`) and is_visible_dd_object(`tbl`.`hidden`,`idx`.`hidden`))) union (select (`cat`.`name` collate utf8_tolower_ci) AS `CONSTRAINT_CATALOG`,(`sch`.`name` collate utf8_tolower_ci) AS `CONSTRAINT_SCHEMA`,(`fk`.`name` collate utf8_tolower_ci) AS `CONSTRAINT_NAME`,(`sch`.`name` collate utf8_tolower_ci) AS `TABLE_SCHEMA`,(`tbl`.`name` collate utf8_tolower_ci) AS `TABLE_NAME`,'FOREIGN KEY' AS `CONSTRAINT_TYPE` from (((`mysql`.`foreign_keys` `fk` join `mysql`.`tables` `tbl` on((`fk`.`table_id` = `tbl`.`id`))) join `mysql`.`schemata` `sch` on((`tbl`.`schema_id` = `sch`.`id`))) join `mysql`.`catalogs` `cat` on((`cat`.`id` = `sch`.`catalog_id`))) where (can_access_table(`sch`.`name`,`tbl`.`name`) and is_visible_dd_object(`tbl`.`hidden`))) utf8 utf8_general_ci +TABLE_CONSTRAINTS CREATE ALGORITHM=UNDEFINED DEFINER=`mysql.infoschema`@`localhost` SQL SECURITY DEFINER VIEW `information_schema`.`TABLE_CONSTRAINTS` AS (select (`cat`.`name` collate utf8_tolower_ci) AS `CONSTRAINT_CATALOG`,(`sch`.`name` collate utf8_tolower_ci) AS `CONSTRAINT_SCHEMA`,`idx`.`name` AS `CONSTRAINT_NAME`,(`sch`.`name` collate utf8_tolower_ci) AS `TABLE_SCHEMA`,(`tbl`.`name` collate utf8_tolower_ci) AS `TABLE_NAME`,if((`idx`.`type` = 'PRIMARY'),'PRIMARY KEY',`idx`.`type`) AS `CONSTRAINT_TYPE`,'YES' AS `ENFORCED` from (((`mysql`.`indexes` `idx` join `mysql`.`tables` `tbl` on((`idx`.`table_id` = `tbl`.`id`))) join `mysql`.`schemata` `sch` on((`tbl`.`schema_id` = `sch`.`id`))) join `mysql`.`catalogs` `cat` on(((`cat`.`id` = `sch`.`catalog_id`) and (`idx`.`type` in ('PRIMARY','UNIQUE'))))) where (can_access_table(`sch`.`name`,`tbl`.`name`) and is_visible_dd_object(`tbl`.`hidden`,`idx`.`hidden`))) union (select (`cat`.`name` collate utf8_tolower_ci) AS `CONSTRAINT_CATALOG`,(`sch`.`name` collate utf8_tolower_ci) AS `CONSTRAINT_SCHEMA`,(`fk`.`name` collate utf8_tolower_ci) AS `CONSTRAINT_NAME`,(`sch`.`name` collate utf8_tolower_ci) AS `TABLE_SCHEMA`,(`tbl`.`name` collate utf8_tolower_ci) AS `TABLE_NAME`,'FOREIGN KEY' AS `CONSTRAINT_TYPE`,'YES' AS `ENFORCED` from (((`mysql`.`foreign_keys` `fk` join `mysql`.`tables` `tbl` on((`fk`.`table_id` = `tbl`.`id`))) join `mysql`.`schemata` `sch` on((`tbl`.`schema_id` = `sch`.`id`))) join `mysql`.`catalogs` `cat` on((`cat`.`id` = `sch`.`catalog_id`))) where (can_access_table(`sch`.`name`,`tbl`.`name`) and is_visible_dd_object(`tbl`.`hidden`))) union (select (`cat`.`name` collate utf8_tolower_ci) AS `CONSTRAINT_CATALOG`,(`sch`.`name` collate utf8_tolower_ci) AS `CONSTRAINT_SCHEMA`,`cc`.`name` AS `CONSTRAINT_NAME`,(`sch`.`name` collate utf8_tolower_ci) AS `TABLE_SCHEMA`,(`tbl`.`name` collate utf8_tolower_ci) AS `TABLE_NAME`,'CHECK' AS `CONSTRAINT_TYPE`,`cc`.`enforced` AS `ENFORCED` from (((`mysql`.`check_constraints` `cc` join `mysql`.`tables` `tbl` on((`cc`.`table_id` = `tbl`.`id`))) join `mysql`.`schemata` `sch` on((`tbl`.`schema_id` = `sch`.`id`))) join `mysql`.`catalogs` `cat` on((`cat`.`id` = `sch`.`catalog_id`))) where (can_access_table(`sch`.`name`,`tbl`.`name`) and is_visible_dd_object(`tbl`.`hidden`))) utf8 utf8_general_ci SHOW COLUMNS FROM information_schema.TABLE_CONSTRAINTS; Field Type Null Key Default Extra CONSTRAINT_CATALOG varchar(64) YES NULL @@ -45,6 +46,7 @@ CONSTRAINT_NAME varchar(64) NO NULL TABLE_SCHEMA varchar(64) YES NULL TABLE_NAME varchar(64) YES NULL CONSTRAINT_TYPE varchar(11) NO +ENFORCED varchar(3) NO SELECT constraint_catalog, constraint_schema, constraint_name, table_schema, table_name FROM information_schema.table_constraints @@ -201,11 +203,11 @@ GRANT SELECT (`f5`) ON `db_datadict`.`t1` TO `testuser1`@`localhost` SELECT * FROM information_schema.table_constraints WHERE table_schema = 'db_datadict' ORDER BY table_schema,table_name, constraint_name; -CONSTRAINT_CATALOG CONSTRAINT_SCHEMA CONSTRAINT_NAME TABLE_SCHEMA TABLE_NAME CONSTRAINT_TYPE -def db_datadict my_idx1 db_datadict t1 UNIQUE -def db_datadict my_idx2 db_datadict t1 UNIQUE -def db_datadict PRIMARY db_datadict t1 PRIMARY KEY -def db_datadict PRIMARY db_datadict t2 PRIMARY KEY +CONSTRAINT_CATALOG CONSTRAINT_SCHEMA CONSTRAINT_NAME TABLE_SCHEMA TABLE_NAME CONSTRAINT_TYPE ENFORCED +def db_datadict my_idx1 db_datadict t1 UNIQUE YES +def db_datadict my_idx2 db_datadict t1 UNIQUE YES +def db_datadict PRIMARY db_datadict t1 PRIMARY KEY YES +def db_datadict PRIMARY db_datadict t2 PRIMARY KEY YES SHOW INDEXES FROM db_datadict.t1; Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment Visible Expression t1 0 PRIMARY 1 f1 ### ### ### ### ### ### ### YES NULL @@ -225,10 +227,10 @@ GRANT SELECT (`f5`) ON `db_datadict`.`t1` TO `testuser1`@`localhost` SELECT * FROM information_schema.table_constraints WHERE table_schema = 'db_datadict' ORDER BY table_schema,table_name, constraint_name; -CONSTRAINT_CATALOG CONSTRAINT_SCHEMA CONSTRAINT_NAME TABLE_SCHEMA TABLE_NAME CONSTRAINT_TYPE -def db_datadict my_idx1 db_datadict t1 UNIQUE -def db_datadict my_idx2 db_datadict t1 UNIQUE -def db_datadict PRIMARY db_datadict t1 PRIMARY KEY +CONSTRAINT_CATALOG CONSTRAINT_SCHEMA CONSTRAINT_NAME TABLE_SCHEMA TABLE_NAME CONSTRAINT_TYPE ENFORCED +def db_datadict my_idx1 db_datadict t1 UNIQUE YES +def db_datadict my_idx2 db_datadict t1 UNIQUE YES +def db_datadict PRIMARY db_datadict t1 PRIMARY KEY YES SHOW INDEXES FROM db_datadict.t1; Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment Visible Expression t1 0 PRIMARY 1 f1 ### ### ### ### ### ### ### YES NULL diff --git a/mysql-test/suite/funcs_1/r/is_table_constraints_is.result b/mysql-test/suite/funcs_1/r/is_table_constraints_is.result index 202170b81eb1..1d7994afe650 100644 --- a/mysql-test/suite/funcs_1/r/is_table_constraints_is.result +++ b/mysql-test/suite/funcs_1/r/is_table_constraints_is.result @@ -6,12 +6,12 @@ GRANT SELECT ON db_datadict.* TO testuser1@localhost; SELECT * FROM information_schema.table_constraints WHERE table_schema = 'information_schema' AND table_name != 'ndb_binlog_index' ORDER BY table_schema,table_name,constraint_name COLLATE utf8_general_ci; -CONSTRAINT_CATALOG CONSTRAINT_SCHEMA CONSTRAINT_NAME TABLE_SCHEMA TABLE_NAME CONSTRAINT_TYPE +CONSTRAINT_CATALOG CONSTRAINT_SCHEMA CONSTRAINT_NAME TABLE_SCHEMA TABLE_NAME CONSTRAINT_TYPE ENFORCED # Establish connection testuser1 (user=testuser1) SELECT * FROM information_schema.table_constraints WHERE table_schema = 'information_schema' AND table_name != 'ndb_binlog_index' ORDER BY table_schema,table_name,constraint_name COLLATE utf8_general_ci; -CONSTRAINT_CATALOG CONSTRAINT_SCHEMA CONSTRAINT_NAME TABLE_SCHEMA TABLE_NAME CONSTRAINT_TYPE +CONSTRAINT_CATALOG CONSTRAINT_SCHEMA CONSTRAINT_NAME TABLE_SCHEMA TABLE_NAME CONSTRAINT_TYPE ENFORCED # Switch to connection default and close connection testuser1 DROP USER testuser1@localhost; DROP DATABASE db_datadict; diff --git a/mysql-test/suite/funcs_1/r/is_table_constraints_mysql.result b/mysql-test/suite/funcs_1/r/is_table_constraints_mysql.result index 4dda5be2116b..6d67d23c8aa2 100644 --- a/mysql-test/suite/funcs_1/r/is_table_constraints_mysql.result +++ b/mysql-test/suite/funcs_1/r/is_table_constraints_mysql.result @@ -6,46 +6,46 @@ GRANT SELECT ON db_datadict.* TO testuser1@localhost; SELECT * FROM information_schema.table_constraints WHERE table_schema = 'mysql' AND table_name != 'ndb_binlog_index' ORDER BY table_schema,table_name,constraint_name COLLATE utf8_general_ci; -CONSTRAINT_CATALOG CONSTRAINT_SCHEMA CONSTRAINT_NAME TABLE_SCHEMA TABLE_NAME CONSTRAINT_TYPE -def mysql PRIMARY mysql columns_priv PRIMARY KEY -def mysql PRIMARY mysql component PRIMARY KEY -def mysql PRIMARY mysql db PRIMARY KEY -def mysql PRIMARY mysql default_roles PRIMARY KEY -def mysql PRIMARY mysql engine_cost PRIMARY KEY -def mysql PRIMARY mysql func PRIMARY KEY -def mysql PRIMARY mysql global_grants PRIMARY KEY -def mysql PRIMARY mysql gtid_executed PRIMARY KEY -def mysql name mysql help_category UNIQUE -def mysql PRIMARY mysql help_category PRIMARY KEY -def mysql name mysql help_keyword UNIQUE -def mysql PRIMARY mysql help_keyword PRIMARY KEY -def mysql PRIMARY mysql help_relation PRIMARY KEY -def mysql name mysql help_topic UNIQUE -def mysql PRIMARY mysql help_topic PRIMARY KEY -def mysql PRIMARY mysql innodb_index_stats PRIMARY KEY -def mysql PRIMARY mysql innodb_table_stats PRIMARY KEY -def mysql PRIMARY mysql password_history PRIMARY KEY -def mysql PRIMARY mysql plugin PRIMARY KEY -def mysql PRIMARY mysql procs_priv PRIMARY KEY -def mysql PRIMARY mysql proxies_priv PRIMARY KEY -def mysql PRIMARY mysql role_edges PRIMARY KEY -def mysql PRIMARY mysql server_cost PRIMARY KEY -def mysql PRIMARY mysql servers PRIMARY KEY -def mysql PRIMARY mysql slave_master_info PRIMARY KEY -def mysql PRIMARY mysql slave_relay_log_info PRIMARY KEY -def mysql PRIMARY mysql slave_worker_info PRIMARY KEY -def mysql PRIMARY mysql tables_priv PRIMARY KEY -def mysql PRIMARY mysql time_zone PRIMARY KEY -def mysql PRIMARY mysql time_zone_leap_second PRIMARY KEY -def mysql PRIMARY mysql time_zone_name PRIMARY KEY -def mysql PRIMARY mysql time_zone_transition PRIMARY KEY -def mysql PRIMARY mysql time_zone_transition_type PRIMARY KEY -def mysql PRIMARY mysql user PRIMARY KEY +CONSTRAINT_CATALOG CONSTRAINT_SCHEMA CONSTRAINT_NAME TABLE_SCHEMA TABLE_NAME CONSTRAINT_TYPE ENFORCED +def mysql PRIMARY mysql columns_priv PRIMARY KEY YES +def mysql PRIMARY mysql component PRIMARY KEY YES +def mysql PRIMARY mysql db PRIMARY KEY YES +def mysql PRIMARY mysql default_roles PRIMARY KEY YES +def mysql PRIMARY mysql engine_cost PRIMARY KEY YES +def mysql PRIMARY mysql func PRIMARY KEY YES +def mysql PRIMARY mysql global_grants PRIMARY KEY YES +def mysql PRIMARY mysql gtid_executed PRIMARY KEY YES +def mysql name mysql help_category UNIQUE YES +def mysql PRIMARY mysql help_category PRIMARY KEY YES +def mysql name mysql help_keyword UNIQUE YES +def mysql PRIMARY mysql help_keyword PRIMARY KEY YES +def mysql PRIMARY mysql help_relation PRIMARY KEY YES +def mysql name mysql help_topic UNIQUE YES +def mysql PRIMARY mysql help_topic PRIMARY KEY YES +def mysql PRIMARY mysql innodb_index_stats PRIMARY KEY YES +def mysql PRIMARY mysql innodb_table_stats PRIMARY KEY YES +def mysql PRIMARY mysql password_history PRIMARY KEY YES +def mysql PRIMARY mysql plugin PRIMARY KEY YES +def mysql PRIMARY mysql procs_priv PRIMARY KEY YES +def mysql PRIMARY mysql proxies_priv PRIMARY KEY YES +def mysql PRIMARY mysql role_edges PRIMARY KEY YES +def mysql PRIMARY mysql server_cost PRIMARY KEY YES +def mysql PRIMARY mysql servers PRIMARY KEY YES +def mysql PRIMARY mysql slave_master_info PRIMARY KEY YES +def mysql PRIMARY mysql slave_relay_log_info PRIMARY KEY YES +def mysql PRIMARY mysql slave_worker_info PRIMARY KEY YES +def mysql PRIMARY mysql tables_priv PRIMARY KEY YES +def mysql PRIMARY mysql time_zone PRIMARY KEY YES +def mysql PRIMARY mysql time_zone_leap_second PRIMARY KEY YES +def mysql PRIMARY mysql time_zone_name PRIMARY KEY YES +def mysql PRIMARY mysql time_zone_transition PRIMARY KEY YES +def mysql PRIMARY mysql time_zone_transition_type PRIMARY KEY YES +def mysql PRIMARY mysql user PRIMARY KEY YES # Establish connection testuser1 (user=testuser1) SELECT * FROM information_schema.table_constraints WHERE table_schema = 'mysql' AND table_name != 'ndb_binlog_index' ORDER BY table_schema,table_name,constraint_name COLLATE utf8_general_ci; -CONSTRAINT_CATALOG CONSTRAINT_SCHEMA CONSTRAINT_NAME TABLE_SCHEMA TABLE_NAME CONSTRAINT_TYPE +CONSTRAINT_CATALOG CONSTRAINT_SCHEMA CONSTRAINT_NAME TABLE_SCHEMA TABLE_NAME CONSTRAINT_TYPE ENFORCED # Switch to connection default and close connection testuser1 DROP USER testuser1@localhost; DROP DATABASE db_datadict; diff --git a/mysql-test/suite/funcs_1/r/is_tables_is.result b/mysql-test/suite/funcs_1/r/is_tables_is.result index dcacee98a432..e1084cc2aa25 100644 --- a/mysql-test/suite/funcs_1/r/is_tables_is.result +++ b/mysql-test/suite/funcs_1/r/is_tables_is.result @@ -40,6 +40,29 @@ user_comment Separator ----------------------------------------------------- TABLE_CATALOG def TABLE_SCHEMA information_schema +TABLE_NAME CHECK_CONSTRAINTS +TABLE_TYPE SYSTEM VIEW +ENGINE NULL +VERSION 10 +ROW_FORMAT NULL +TABLE_ROWS #TBLR# +AVG_ROW_LENGTH #ARL# +DATA_LENGTH #DL# +MAX_DATA_LENGTH #MDL# +INDEX_LENGTH #IL# +DATA_FREE #DF# +AUTO_INCREMENT #AI# +CREATE_TIME #CRT# +UPDATE_TIME #UT# +CHECK_TIME #CT# +TABLE_COLLATION NULL +CHECKSUM NULL +CREATE_OPTIONS #CO# +TABLE_COMMENT #TC# +user_comment +Separator ----------------------------------------------------- +TABLE_CATALOG def +TABLE_SCHEMA information_schema TABLE_NAME COLLATIONS TABLE_TYPE SYSTEM VIEW ENGINE NULL @@ -841,6 +864,29 @@ user_comment Separator ----------------------------------------------------- TABLE_CATALOG def TABLE_SCHEMA information_schema +TABLE_NAME CHECK_CONSTRAINTS +TABLE_TYPE SYSTEM VIEW +ENGINE NULL +VERSION 10 +ROW_FORMAT NULL +TABLE_ROWS #TBLR# +AVG_ROW_LENGTH #ARL# +DATA_LENGTH #DL# +MAX_DATA_LENGTH #MDL# +INDEX_LENGTH #IL# +DATA_FREE #DF# +AUTO_INCREMENT #AI# +CREATE_TIME #CRT# +UPDATE_TIME #UT# +CHECK_TIME #CT# +TABLE_COLLATION NULL +CHECKSUM NULL +CREATE_OPTIONS #CO# +TABLE_COMMENT #TC# +user_comment +Separator ----------------------------------------------------- +TABLE_CATALOG def +TABLE_SCHEMA information_schema TABLE_NAME COLLATIONS TABLE_TYPE SYSTEM VIEW ENGINE NULL diff --git a/mysql-test/suite/innodb/r/import_5_7.result b/mysql-test/suite/innodb/r/import_5_7.result index 9c77c865a50f..1fca75a011a8 100644 --- a/mysql-test/suite/innodb/r/import_5_7.result +++ b/mysql-test/suite/innodb/r/import_5_7.result @@ -316,6 +316,7 @@ a b c d } ], "foreign_keys": [], + "check_constraints": [], "partitions": [], "collation_id": 8 } diff --git a/mysql-test/suite/innodb/r/sdi_delete_marked.result b/mysql-test/suite/innodb/r/sdi_delete_marked.result index 58078d2e99ca..b45aa58ae4f3 100644 --- a/mysql-test/suite/innodb/r/sdi_delete_marked.result +++ b/mysql-test/suite/innodb/r/sdi_delete_marked.result @@ -405,6 +405,7 @@ SET GLOBAL DEBUG= '+d, skip_purge_check_shutdown'; } ], "foreign_keys": [], + "check_constraints": [], "partitions": [], "collation_id": 255 } diff --git a/mysql-test/suite/innodb_gis/r/create_spatial_index.result b/mysql-test/suite/innodb_gis/r/create_spatial_index.result index 03a75cbd647d..4dfa9f3c23ca 100644 --- a/mysql-test/suite/innodb_gis/r/create_spatial_index.result +++ b/mysql-test/suite/innodb_gis/r/create_spatial_index.result @@ -1625,13 +1625,17 @@ CHECK TABLE tab; Table Op Msg_type Msg_text test.tab check status OK DROP TABLE tab; -CREATE TABLE tab(c1 POINT NOT NULL SRID 0,CONSTRAINT tab_const check(c1 > 0) ) ENGINE=InnoDB; +CREATE TABLE tab(c1 POINT NOT NULL SRID 0, +CONSTRAINT tab_const +CHECK(ST_Equals(c1, ST_GeomFromText("POINT(0 0)") = FALSE)) +) ENGINE=InnoDB; CREATE SPATIAL INDEX idx1 ON tab(c1) ; SHOW CREATE TABLE tab; Table Create Table tab CREATE TABLE `tab` ( `c1` point NOT NULL /*!80003 SRID 0 */, - SPATIAL KEY `idx1` (`c1`) + SPATIAL KEY `idx1` (`c1`), + CONSTRAINT `tab_const` CHECK (st_equals(`c1`,(st_geomfromtext(_utf8mb4'POINT(0 0)') = FALSE))) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ANALYZE TABLE tab; Table Op Msg_type Msg_text diff --git a/mysql-test/suite/innodb_gis/t/create_spatial_index.test b/mysql-test/suite/innodb_gis/t/create_spatial_index.test index e321027dbbb5..ff4ab9adeb29 100644 --- a/mysql-test/suite/innodb_gis/t/create_spatial_index.test +++ b/mysql-test/suite/innodb_gis/t/create_spatial_index.test @@ -1121,7 +1121,10 @@ DROP TABLE tab; # End of Testcase compress table with Auto_increment # Test check constraint on spatial column -CREATE TABLE tab(c1 POINT NOT NULL SRID 0,CONSTRAINT tab_const check(c1 > 0) ) ENGINE=InnoDB; +CREATE TABLE tab(c1 POINT NOT NULL SRID 0, + CONSTRAINT tab_const + CHECK(ST_Equals(c1, ST_GeomFromText("POINT(0 0)") = FALSE)) + ) ENGINE=InnoDB; CREATE SPATIAL INDEX idx1 ON tab(c1) ; diff --git a/mysql-test/suite/ndbcluster/information_schema_fk.result b/mysql-test/suite/ndbcluster/information_schema_fk.result index f829f88ea407..728002a5409a 100644 --- a/mysql-test/suite/ndbcluster/information_schema_fk.result +++ b/mysql-test/suite/ndbcluster/information_schema_fk.result @@ -32,14 +32,14 @@ foreign key emp_fk1 (manager) references emp (id) select * from information_schema.table_constraints where table_schema = 'test' order by table_name, constraint_type, constraint_name; -CONSTRAINT_CATALOG CONSTRAINT_SCHEMA CONSTRAINT_NAME TABLE_SCHEMA TABLE_NAME CONSTRAINT_TYPE -def test PRIMARY test customer PRIMARY KEY -def test emp_fk1 test emp FOREIGN KEY -def test PRIMARY test emp PRIMARY KEY -def test PRIMARY test product PRIMARY KEY -def test fk1 test product_order FOREIGN KEY -def test fk2 test product_order FOREIGN KEY -def test PRIMARY test product_order PRIMARY KEY +CONSTRAINT_CATALOG CONSTRAINT_SCHEMA CONSTRAINT_NAME TABLE_SCHEMA TABLE_NAME CONSTRAINT_TYPE ENFORCED +def test PRIMARY test customer PRIMARY KEY YES +def test emp_fk1 test emp FOREIGN KEY YES +def test PRIMARY test emp PRIMARY KEY YES +def test PRIMARY test product PRIMARY KEY YES +def test fk1 test product_order FOREIGN KEY YES +def test fk2 test product_order FOREIGN KEY YES +def test PRIMARY test product_order PRIMARY KEY YES select CONCAT_WS('.', TABLE_NAME, COLUMN_NAME) as COL, ORDINAL_POSITION, POSITION_IN_UNIQUE_CONSTRAINT, @@ -93,15 +93,15 @@ select * from information_schema.table_constraints where table_schema like 'mydb%' order by table_name, constraint_type, constraint_name; -CONSTRAINT_CATALOG CONSTRAINT_SCHEMA CONSTRAINT_NAME TABLE_SCHEMA TABLE_NAME CONSTRAINT_TYPE -def mydb1 fk_b1a1 mydb1 t1 FOREIGN KEY -def mydb1 fk_b1b2 mydb1 t1 FOREIGN KEY -def mydb1 PRIMARY mydb1 t1 PRIMARY KEY -def mydb1 xb1 mydb1 t1 UNIQUE -def mydb2 fk_b2a2 mydb2 t2 FOREIGN KEY -def mydb2 fk_b2b1 mydb2 t2 FOREIGN KEY -def mydb2 PRIMARY mydb2 t2 PRIMARY KEY -def mydb2 xb2 mydb2 t2 UNIQUE +CONSTRAINT_CATALOG CONSTRAINT_SCHEMA CONSTRAINT_NAME TABLE_SCHEMA TABLE_NAME CONSTRAINT_TYPE ENFORCED +def mydb1 fk_b1a1 mydb1 t1 FOREIGN KEY YES +def mydb1 fk_b1b2 mydb1 t1 FOREIGN KEY YES +def mydb1 PRIMARY mydb1 t1 PRIMARY KEY YES +def mydb1 xb1 mydb1 t1 UNIQUE YES +def mydb2 fk_b2a2 mydb2 t2 FOREIGN KEY YES +def mydb2 fk_b2b1 mydb2 t2 FOREIGN KEY YES +def mydb2 PRIMARY mydb2 t2 PRIMARY KEY YES +def mydb2 xb2 mydb2 t2 UNIQUE YES select * from information_schema.key_column_usage where table_schema like 'mydb%' diff --git a/mysql-test/suite/rpl/r/rpl_check_constraints.result b/mysql-test/suite/rpl/r/rpl_check_constraints.result new file mode 100644 index 000000000000..75f5282a5d9f --- /dev/null +++ b/mysql-test/suite/rpl/r/rpl_check_constraints.result @@ -0,0 +1,55 @@ +include/master-slave.inc +Warnings: +Note #### Sending passwords in plain text without SSL/TLS is extremely insecure. +Note #### Storing MySQL user name or password information in the master info repository is not secure and is therefore not recommended. Please consider using the USER and PASSWORD connection options for START SLAVE; see the 'START SLAVE Syntax' in the MySQL Manual for more information. +[connection master] +CALL mtr.add_suppression("Check constraint 't1_chk_2' is violated."); +CALL mtr.add_suppression("The slave coordinator and worker threads are stopped, possibly leaving data in inconsistent state"); +CREATE TABLE t1 (f1 int primary key, CHECK(f1 < 100)); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) NOT NULL, + PRIMARY KEY (`f1`), + CONSTRAINT `t1_chk_1` CHECK ((`f1` < 100)) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci +INSERT INTO t1 (f1) VALUES(20); +include/sync_slave_sql_with_master.inc +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) NOT NULL, + PRIMARY KEY (`f1`), + CONSTRAINT `t1_chk_1` CHECK ((`f1` < 100)) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci +ALTER TABLE t1 ADD CONSTRAINT CHECK(f1 < 50); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) NOT NULL, + PRIMARY KEY (`f1`), + CONSTRAINT `t1_chk_1` CHECK ((`f1` < 100)), + CONSTRAINT `t1_chk_2` CHECK ((`f1` < 50)) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci +[connection master] +update t1 set f1 = 80; +[connection slave] +# t1_chk_2 check constraint validation for update fails at slave. +include/wait_for_slave_sql_error.inc [errno=3820] +SELECT * from t1; +f1 +20 +[connection master] +insert into t1 values(90); +[connection slave] +# t1_chk_2 check constraint validation for insert fails at slave. +include/wait_for_slave_sql_error.inc [errno=3820] +SELECT * from t1; +f1 +20 +[connection master] +DROP TABLE t1; +[connection slave] +DROP TABLE t1; +include/rpl_reset.inc +include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_check_constraints.test b/mysql-test/suite/rpl/t/rpl_check_constraints.test new file mode 100644 index 000000000000..8363ad021f83 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_check_constraints.test @@ -0,0 +1,45 @@ +################################################################################ +# WL929 - CHECK CONSTRAINTS. # +################################################################################ + +--source include/master-slave.inc + +CALL mtr.add_suppression("Check constraint 't1_chk_2' is violated."); +CALL mtr.add_suppression("The slave coordinator and worker threads are stopped, possibly leaving data in inconsistent state"); + +CREATE TABLE t1 (f1 int primary key, CHECK(f1 < 100)); +SHOW CREATE TABLE t1; +INSERT INTO t1 (f1) VALUES(20); + +--source include/sync_slave_sql_with_master.inc +SHOW CREATE TABLE t1; +ALTER TABLE t1 ADD CONSTRAINT CHECK(f1 < 50); +SHOW CREATE TABLE t1; + +--source include/rpl_connection_master.inc +update t1 set f1 = 80; + +--source include/rpl_connection_slave.inc +--echo # t1_chk_2 check constraint validation for update fails at slave. +--let $slave_sql_errno= convert_error(ER_CHECK_CONSTRAINT_VIOLATED) +--source include/wait_for_slave_sql_error.inc +SELECT * from t1; + +--source include/rpl_connection_master.inc +insert into t1 values(90); + +--source include/rpl_connection_slave.inc +--echo # t1_chk_2 check constraint validation for insert fails at slave. +--let $slave_sql_errno= convert_error(ER_CHECK_CONSTRAINT_VIOLATED) +--source include/wait_for_slave_sql_error.inc +SELECT * from t1; + +--source include/rpl_connection_master.inc +DROP TABLE t1; + +--source include/rpl_connection_slave.inc +DROP TABLE t1; + +--let $rpl_only_running_threads= 1 +--source include/rpl_reset.inc +--source include/rpl_end.inc diff --git a/mysql-test/t/check_constraints.test b/mysql-test/t/check_constraints.test new file mode 100644 index 000000000000..12fad47b0b77 --- /dev/null +++ b/mysql-test/t/check_constraints.test @@ -0,0 +1,1917 @@ +################################################################################ +# WL929 - CHECK CONSTRAINTS. # +# Test file has cases to verify check constraint feature, common # +# restrictions and mysql specific restriction on check constraints. # +################################################################################ + +--echo #------------------------------------------------------------------------ +--echo # Test cases to verify column check constraint syntax. +--echo #------------------------------------------------------------------------ +--error ER_PARSE_ERROR +CREATE TABLE t1(f1 int CHECK); + +--error ER_PARSE_ERROR +CREATE TABLE t1(f1 int CHECK()); + +--error ER_PARSE_ERROR +CREATE TABLE t1(f1 int CONSTRAINT CHECK()); + +--error ER_PARSE_ERROR +CREATE TABLE t1(f1 int t1_ck CHECK()); + +--error ER_PARSE_ERROR +CREATE TABLE t1(f1 int CONSTRAINT t1_ck CHECK()); + +--error ER_PARSE_ERROR +CREATE TABLE t1(f1 int CONSTRAINT t1_ck CHECK( f1 < 10) NOT); + +--error ER_NON_BOOLEAN_EXPR_FOR_CHECK_CONSTRAINT +CREATE TABLE t1(f1 int CHECK(f1)); + +--error ER_NON_BOOLEAN_EXPR_FOR_CHECK_CONSTRAINT +CREATE TABLE t1(f1 int CHECK(f1 + 10)); + +--error ER_COLUMN_CHECK_CONSTRAINT_REFERENCES_OTHER_COLUMN +CREATE TABLE t1(f1 int CHECK(f2 < 10)); + +CREATE TABLE t1 (f1 int CHECK(f1 < 10), + f2 int CONSTRAINT t1_f2_ck CHECK (f2 < 10)); +SHOW CREATE TABLE t1; +DROP TABLE t1; + +--error ER_PARSE_ERROR +CREATE TABLE t1(f1 int CHECK(f1 < 10), f2 int CHECK); + +--error ER_PARSE_ERROR +CREATE TABLE t1(f1 int CHECK(f1 < 10), f2 int CHECK()); + +--error ER_PARSE_ERROR +CREATE TABLE t1(f1 int CHECK(f1 < 10), f2 int CONSTRAINT CHECK()); + +--error ER_PARSE_ERROR +CREATE TABLE t1(f1 int CHECK(f1 < 10), f2 int t1_f2_ck CHECK(f2 < 10)); + +--error ER_PARSE_ERROR +CREATE TABLE t1(f1 int CHECK(f1 < 10), f2 int CONSTRAINT t1_f2_ck CHECK(f2 < 10) NOT); + +--error ER_PARSE_ERROR +CREATE TABLE t1(f1 int CHECK(f1 < 10), f2 int CHECK(f2 < 10) NOT); + +--error ER_NON_BOOLEAN_EXPR_FOR_CHECK_CONSTRAINT +CREATE TABLE t1(f1 int CHECK(f1 < 10), f2 int CHECK(f2)); + +--error ER_NON_BOOLEAN_EXPR_FOR_CHECK_CONSTRAINT +CREATE TABLE t1(f1 int CHECK(f1 < 10), f2 int CHECK(f2 + 10)); + +--error ER_COLUMN_CHECK_CONSTRAINT_REFERENCES_OTHER_COLUMN +CREATE TABLE t1(f1 int CHECK(f1 < 10), f2 int CHECK(f3 < 10)); + +CREATE TABLE t1 (f1 int CHECK(f1 < 10), f2 int CHECK(f2 < 10), + f3 int CONSTRAINT t1_f3_ck CHECK (f3 < 10)); +SHOW CREATE TABLE t1; +DROP TABLE t1; + + +--echo #------------------------------------------------------------------------ +--echo # Test cases to verify table check constraint syntax. +--echo #------------------------------------------------------------------------ +--error ER_PARSE_ERROR +CREATE TABLE t1(f1 int, CONSTRAINT t1_ck CHECK); + +--error ER_PARSE_ERROR +CREATE TABLE t1(f1 int, CONSTRAINT t1_ck CHECK(); + +--error ER_PARSE_ERROR +CREATE TABLE t1(f1 int, CONSTRAINT t1_ck CHECK()); + +--error ER_NON_BOOLEAN_EXPR_FOR_CHECK_CONSTRAINT +CREATE TABLE t1(f1 int, CONSTRAINT t1_ck CHECK(f1)); + +--error ER_NON_BOOLEAN_EXPR_FOR_CHECK_CONSTRAINT +CREATE TABLE t1(f1 int, CONSTRAINT t1_ck CHECK(f1 + 10)); + +--error ER_CHECK_CONSTRAINT_REFERS_UNKNOWN_COLUMN +CREATE TABLE t1(f1 int, CONSTRAINT t1_ck CHECK(f2 < 10)); + +CREATE TABLE t1(f1 int, CONSTRAINT t1_ck CHECK(f1 < 10)); + +SHOW CREATE TABLE t1; +DROP TABLE t1; + +--error ER_PARSE_ERROR +CREATE TABLE t1(f1 int, CONSTRAINT t1_ck CHECK(f1<10), CONSTRAINT t2_ck CHECK); + +--error ER_PARSE_ERROR +CREATE TABLE t1(f1 int, CONSTRAINT t1_ck CHECK(f1<10), CONSTRAINT t2_ck CHECK(); + +--error ER_PARSE_ERROR +CREATE TABLE t1(f1 int, CONSTRAINT t1_ck CHECK(f1<10), CONSTRAINT t2_ck CHECK(f2 > 0) NOT); + +--error ER_NON_BOOLEAN_EXPR_FOR_CHECK_CONSTRAINT +CREATE TABLE t1(f1 int, CONSTRAINT t1_ck CHECK(f1<10), CONSTRAINT t2_ck CHECK(f1)); + +--error ER_NON_BOOLEAN_EXPR_FOR_CHECK_CONSTRAINT +CREATE TABLE t1(f1 int, CONSTRAINT t1_ck CHECK(f1<10), CONSTRAINT t2_ck CHECK(f1 + 10)); + +--error ER_CHECK_CONSTRAINT_REFERS_UNKNOWN_COLUMN +CREATE TABLE t1(f1 int, CONSTRAINT t1_ck CHECK(f1<10), CONSTRAINT t2_ck CHECK(f2 > 1)); + +# Check constraint with specified and generated name. +CREATE TABLE t1(f1 int, CHECK(f1<10), CONSTRAINT t2_ck CHECK(f1 > 1)); +SHOW CREATE TABLE t1; +DROP TABLE t1; + + +--echo #----------------------------------------------------------------------- +--echo # Test case to verify check constraint name with special charecters. +--echo #----------------------------------------------------------------------- +CREATE TABLE t1(c1 INT, c2 INT, CONSTRAINT `ck_1$` CHECK (c2 < 10)); +SHOW CREATE TABLE t1; +DROP TABLE t1; + + +--echo #----------------------------------------------------------------------- +--echo # Test case to verify check constraint name with white spaces. +--echo #----------------------------------------------------------------------- +CREATE TABLE t1(c1 INT, c2 INT, CONSTRAINT ` ck_2$ ` CHECK (c2 < 10)); +SHOW CREATE TABLE t1; +--error ER_CHECK_CONSTRAINT_NOT_FOUND +ALTER TABLE t1 DROP CHECK ck_2$; +ALTER TABLE t1 DROP CHECK ` ck_2$ `; +SHOW CREATE TABLE t1; +ALTER TABLE t1 ADD COLUMN c3 INTEGER , ADD CONSTRAINT ` c 3 ` CHECK ( c3 > 10 ); +SHOW CREATE TABLE t1; +DROP TABLE t1; + + +--echo #----------------------------------------------------------------------- +--echo # Test case to verify check constraint name with reserved words. +--echo #----------------------------------------------------------------------- +--error ER_PARSE_ERROR +CREATE TABLE t1(c1 INT, c2 INT, CONSTRAINT FLOAT CHECK (c2 < 10)); +CREATE TABLE t1(c1 INT, c2 INT, CONSTRAINT `FLOAT` CHECK (c2 < 10)); +SHOW CREATE TABLE t1; +DROP TABLE t1; + + +--echo #----------------------------------------------------------------------- +--echo # Test case to verify check constraint with long name. +--echo #----------------------------------------------------------------------- +CREATE TABLE t1(c1 INT, c2 INT, + CONSTRAINT ckkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk + CHECK (c2 < 10)); +SHOW CREATE TABLE t1; +--error ER_TOO_LONG_IDENT +CREATE TABLE t2(c1 INT, c2 INT, + CONSTRAINT ckkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk1 + CHECK (c2 < 10)); +DROP TABLE t1; + + +--echo #----------------------------------------------------------------------- +--echo # Test case to verify check constraint with too long generated name. +--echo #----------------------------------------------------------------------- +CREATE TABLE t1 (f1 INT CHECK (f1 < 10)); +--error ER_TOO_LONG_IDENT +RENAME TABLE t1 TO t123456789012345678901234567890123456789012345678901234567890; +DROP TABLE t1; + +--error ER_TOO_LONG_IDENT +CREATE TABLE t123456789012345678901234567890123456789012345678901234567890(f1 INT CHECK(f1 < 10)); + +CREATE TABLE t123456789012345678901234567890123456789012345678901234567890(f1 INT); +--error ER_TOO_LONG_IDENT +ALTER TABLE t123456789012345678901234567890123456789012345678901234567890 ADD CONSTRAINT CHECK (f1 < 10); +DROP TABLE t123456789012345678901234567890123456789012345678901234567890; + + +--echo #----------------------------------------------------------------------- +--echo # Test case to verify duplicate check constraint name under same +--echo # database. Check constraints with same name are not allowed under +--echo # same database. +--echo #----------------------------------------------------------------------- +CREATE TABLE t(c1 INT CONSTRAINT t2_chk_1 CHECK (c1 > 10)); +CREATE TABLE t1(c1 INT CHECK (c1 > 10), CONSTRAINT ck CHECK(c1 > 10)); +--error ER_CHECK_CONSTRAINT_DUP_NAME +CREATE TABLE t2(c1 INT, CONSTRAINT ck CHECK(c1 > 10)); +--error ER_CHECK_CONSTRAINT_DUP_NAME +ALTER TABLE t1 ADD CONSTRAINT ck CHECK(c1 > 10); +--error ER_CHECK_CONSTRAINT_DUP_NAME +ALTER TABLE t1 RENAME TO t2; +--error ER_CHECK_CONSTRAINT_DUP_NAME +ALTER TABLE t1 ADD c2 INT, RENAME TO t2; +DROP TABLE t; + +CREATE DATABASE db1; +CREATE TABLE db1.t(c1 INT CONSTRAINT t2_chk_1 CHECK (c1 > 10)); +--error ER_CHECK_CONSTRAINT_DUP_NAME +ALTER TABLE t1 ADD c2 INT, RENAME TO db1.t2; +--error ER_CHECK_CONSTRAINT_DUP_NAME +ALTER TABLE t1 RENAME TO db1.t2; +DROP DATABASE db1; +DROP TABLE t1; + + +--echo #----------------------------------------------------------------------- +--echo # Check constraint names are case insenitive and accent sensitive. Test +--echo # case to verify the same. +--echo #----------------------------------------------------------------------- +--error ER_CHECK_CONSTRAINT_DUP_NAME +CREATE TABLE t1 (f1 INT, + CONSTRAINT cafe CHECK (f1 < 10), + CONSTRAINT CAFE CHECK (f1 < 10)); +create table t1 (f1 int, + CONSTRAINT cafe CHECK (f1 < 10), + CONSTRAINT café CHECK (f1 < 10)); +SHOW CREATE TABLE t1; +DROP TABLE t1; + + +--echo #------------------------------------------------------------------------ +--echo # Test cases to verify forward reference of columns in the constraint. +--echo #------------------------------------------------------------------------ +--error ER_CHECK_CONSTRAINT_REFERS_UNKNOWN_COLUMN +CREATE TABLE t1(CHECK((f1 + f3) > 10), f1 int CHECK (f1 < 10), f2 int); + +CREATE TABLE t1(CHECK((f1 + f2) > 10), f1 int CHECK (f1 < 10), f2 int); +SHOW CREATE TABLE t1; +SELECT * FROM INFORMATION_SCHEMA.CHECK_CONSTRAINTS; +DROP TABLE t1; + + +--echo #----------------------------------------------------------------------- +--echo # Test case to verify creation of multiple check constraint on table. +--echo #----------------------------------------------------------------------- +CREATE TABLE t1(c1 INT, c2 INT, c3 INT, c4 INT); +ALTER TABLE t1 ADD CONSTRAINT ck11 CHECK(c1 > 1), + ADD CONSTRAINT ck12 CHECK(c1 < 1), + ADD CONSTRAINT ck21 CHECK(c2 > 1), + ADD CONSTRAINT ck22 CHECK(c2 < 1), + ADD CONSTRAINT ck31 CHECK(c3 > 1), + ADD CONSTRAINT ck32 CHECK(c3 < 1), + ADD CONSTRAINT ck41 CHECK(c4 > 1), + ADD CONSTRAINT ck42 CHECK(c4 < 1); +SHOW CREATE TABLE t1; +DROP TABLE t1; + + +--echo #----------------------------------------------------------------------- +--echo # Test case to verify check constraints with generated columns +--echo #----------------------------------------------------------------------- +CREATE TABLE t1(c1 INT, + c2 INT, + c3 INT GENERATED ALWAYS AS (c1 + c2), + CONSTRAINT ck CHECK (c3 > 10) +); +SHOW CREATE TABLE t1; +--error ER_CHECK_CONSTRAINT_VIOLATED +INSERT INTO t1(c1,c2) VALUES(1,1); +INSERT INTO t1(c1,c2) VALUES(10,10); +DROP TABLE t1; + + +--echo #------------------------------------------------------------------------ +--echo # Test case to verify check constraints with DEFAULT column value. +--echo #------------------------------------------------------------------------ +CREATE TABLE t1(c1 INT DEFAULT 100 CHECK(c1 > 10)); +--error ER_CHECK_CONSTRAINT_VIOLATED +INSERT INTO t1() VALUES(1); +INSERT INTO t1() VALUES(); +DROP TABLE t1; +CREATE TABLE t1(c1 int DEFAULT 1, CONSTRAINT CHECK(c1 IS NOT NULL)); +INSERT INTO t1() VALUES(); +--error ER_CHECK_CONSTRAINT_VIOLATED +INSERT INTO t1() VALUES(NULL); +DROP TABLE t1; + + +--echo #----------------------------------------------------------------------- +--echo # Test case to verify check constraint behaviour with ascii charset +--echo #----------------------------------------------------------------------- +CREATE TABLE t1(c1 VARCHAR(1) CHARSET ASCII CHECK(c1 = 'a'), + c2 VARCHAR(1) CHARSET ASCII DEFAULT('b')); +SHOW CREATE TABLE t1; +--error ER_CHECK_CONSTRAINT_VIOLATED +INSERT INTO t1(c1) VALUES('b'); +INSERT INTO t1(c1) VALUES('a'); +DROP TABLE t1; + + +--echo #----------------------------------------------------------------------- +--echo # Test case to verify check constraint with an expression evaluated to +--echo # FALSE always. +--echo #----------------------------------------------------------------------- +CREATE TABLE t1 (CHECK (1 < 1), f1 int); +SHOW CREATE TABLE t1; +--error ER_CHECK_CONSTRAINT_VIOLATED +INSERT INTO t1 VALUES(1); +--error ER_CHECK_CONSTRAINT_VIOLATED +INSERT INTO t1 VALUES(10); +--error ER_CHECK_CONSTRAINT_VIOLATED +INSERT INTO t1 VALUES(); +DROP TABLE t1; + + +--echo #------------------------------------------------------------------------ +--echo # Test case to verify INFORMATION_SCHEMA.CHECK_CONSTRAINTS and +--echo # INFORMATION_SCHEMA.TABLE_CONSTRAINTS result set. +--echo #------------------------------------------------------------------------ +CREATE TABLE t1(f1 INT PRIMARY KEY, f2 INT CHECK (f2 < 10), + CONSTRAINT t2_cc1 CHECK (f1 + SQRT(f2) > 6174)); +SHOW CREATE TABLE t1; +SELECT * FROM INFORMATION_SCHEMA.CHECK_CONSTRAINTS; +SELECT * FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE TABLE_NAME='t1'; +DROP TABLE t1; + + +--echo #------------------------------------------------------------------------ +--echo # Test cases to verify check constraints in temporary table. +--echo #------------------------------------------------------------------------ +CREATE TEMPORARY TABLE tmp_t1(CHECK((f1 + f2) > 10), f1 int CHECK (f1 < 12), + f2 int); +SHOW CREATE TABLE tmp_t1; +# Temporary table check constraints are not listed in CHECK_CONSTRAINTS. +SELECT * FROM INFORMATION_SCHEMA.CHECK_CONSTRAINTS; +DROP TABLE tmp_t1; + + +--echo #------------------------------------------------------------------------ +--echo # Test cases to verify check constraints with CREATE TABLE LIKE +--echo #------------------------------------------------------------------------ +CREATE TABLE t1(f1 INT CHECK (f1 < 10), f2 INT, CHECK (f2 < 10), + CONSTRAINT min CHECK (f1 + f2 > 10), + CONSTRAINT max CHECK (f1 + f2 < 929)); +SHOW CREATE TABLE t1; +CREATE TABLE t2 LIKE t1; +# t2 will have check constraints with all generated names. +SHOW CREATE TABLE t2; + +CREATE TEMPORARY TABLE tmp_t2 LIKE t2; +SHOW CREATE TABLE tmp_t2; +CREATE TABLE t3 LIKE tmp_t2; +# t3 will have check constraints with all generated names. +SHOW CREATE TABLE t3; +DROP TABLE t1, t2, t3, tmp_t2; + + +--echo #------------------------------------------------------------------------ +--echo # Test cases to verify effect of check constraint in DML operations. +--echo #------------------------------------------------------------------------ +CREATE TABLE t1(f1 INT PRIMARY KEY, f2 INT CHECK (f2 < 10)); +SHOW CREATE TABLE t1; +CREATE TABLE t2(f1 INT, f2 INT); +INSERT INTO t2 VALUES(101, 1); +INSERT INTO t2 VALUES(102, NULL); +INSERT INTO t2 VALUES(103, 1000); + +--echo # INSERT operations. +INSERT INTO t1 VALUES(1, 1); +INSERT INTO t1 VALUES(2, NULL); +--error ER_CHECK_CONSTRAINT_VIOLATED +INSERT INTO t1 VALUES(3, 1000); +INSERT IGNORE INTO t1 VALUES (3, 1000); +SELECT * FROM t1; +--error ER_CHECK_CONSTRAINT_VIOLATED +INSERT INTO t1 SELECT * FROM t2; +SELECT * FROM t1; +INSERT IGNORE INTO t1 SELECT * FROM t2; +SELECT * FROM t1; + +--echo # REPLACE operations. +REPLACE INTO t1 VALUES(4, 1); +REPLACE INTO t1 VALUES(5, NULL); +--error ER_CHECK_CONSTRAINT_VIOLATED +REPLACE INTO t1 VALUES(6, 100); +--error ER_CHECK_CONSTRAINT_VIOLATED +REPLACE INTO t1 VALUES(2, 10); +REPLACE INTO t1 VALUES(2, 2); +SELECT * FROM t1; + +--echo # UPDATE operations. +UPDATE t1 SET f2 = 2; +SELECT * FROM t1; +UPDATE t1 SET f2 = NULL; +--error ER_CHECK_CONSTRAINT_VIOLATED +UPDATE t1 SET f2 = 1000; +UPDATE IGNORE t1 SET f2 = 1000; +SELECT * FROM t1; +DROP TABLE t1, t2; + +--echo # LOAD DATA operations. +CREATE TABLE t2(f1 INT,f2 INT); +INSERT INTO t2 VALUES(1,1); +INSERT INTO t2 VALUES(2,NULL); +CREATE TABLE t1(f1 INT PRIMARY KEY, f2 INT CHECK (f2 < 10)); +SHOW CREATE TABLE t1; +SELECT * FROM t2; +SELECT * FROM t2 INTO OUTFILE 'tmp1.txt'; +LOAD DATA INFILE 'tmp1.txt' INTO TABLE t1; +SELECT * FROM t1; +DELETE FROM t1; +INSERT INTO t2 VALUES(3,20); +SELECT * FROM t2; +SELECT * FROM t2 INTO OUTFILE 'tmp2.txt'; +--error ER_CHECK_CONSTRAINT_VIOLATED +LOAD DATA INFILE 'tmp2.txt' INTO TABLE t1; +SELECT * FROM t1; +LOAD DATA INFILE 'tmp2.txt' IGNORE INTO TABLE t1; +SELECT * FROM t1; +DROP TABLE t1,t2; +CREATE TABLE t1 (a INT CHECK(a < 3), b CHAR(10)) CHARSET latin1; +LOAD DATA INFILE '../../std_data/loaddata3.dat' IGNORE INTO TABLE t1 + FIELDS TERMINATED BY '' ENCLOSED BY '' IGNORE 1 LINES; +DROP TABLE t1; + +let $MYSQLD_DATADIR= `select @@datadir`; +remove_file $MYSQLD_DATADIR/test/tmp1.txt; +remove_file $MYSQLD_DATADIR/test/tmp2.txt; + +--echo # LOAD XML operations. +CREATE TABLE t2(f1 INT,f2 INT); +INSERT INTO t2 VALUES(1,1); +INSERT INTO t2 VALUES(2,NULL); +CREATE TABLE t1(f1 INT PRIMARY KEY, f2 INT CHECK (f2 < 10)); +SHOW CREATE TABLE t1; +SELECT * FROM t2; +--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +--exec $MYSQL_DUMP --xml test t2 > "$MYSQLTEST_VARDIR/tmp/tmp1.xml" 2>&1 +--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +--eval LOAD XML INFILE "$MYSQLTEST_VARDIR/tmp/tmp1.xml" INTO TABLE t1; +SELECT * FROM t1; +DELETE FROM t1; +INSERT INTO t2 VALUES(3,20); +SELECT * FROM t2; +--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +--exec $MYSQL_DUMP --xml test t2 > "$MYSQLTEST_VARDIR/tmp/tmp2.xml" 2>&1 +--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +--error ER_CHECK_CONSTRAINT_VIOLATED +--eval LOAD XML INFILE "$MYSQLTEST_VARDIR/tmp/tmp2.xml" INTO TABLE t1; +SELECT * FROM t1; +--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +--eval LOAD XML INFILE "$MYSQLTEST_VARDIR/tmp/tmp2.xml" IGNORE INTO TABLE t1; +SELECT * FROM t1; +DROP TABLE t1,t2; + +remove_file $MYSQLTEST_VARDIR/tmp/tmp1.xml; +remove_file $MYSQLTEST_VARDIR/tmp/tmp2.xml; + + +--echo #----------------------------------------------------------------------- +--echo # Test case to verify check constraint with INSERT ON DUPLICATE +--echo #----------------------------------------------------------------------- +CREATE TABLE t1(f1 INT PRIMARY KEY, f2 INT CHECK (f2 < 10)); +INSERT INTO t1 VALUES (1, 1); +INSERT INTO t1 VALUES (1, 2) ON DUPLICATE KEY UPDATE f2 = 4; +SELECT * FROM t1; +INSERT IGNORE INTO t1 VALUES (1, 1) ON DUPLICATE KEY UPDATE f2 = 20; +--error ER_CHECK_CONSTRAINT_VIOLATED +INSERT INTO t1 VALUES (1, 1) ON DUPLICATE KEY UPDATE f2 = 20; +DROP TABLE t1; + + +--echo #----------------------------------------------------------------------- +--echo # Test case to verify check constraints with multi-table update. +--echo #----------------------------------------------------------------------- +CREATE TABLE t1(f1 INT, f2 INT CHECK(f2 < 20)); +INSERT INTO t1 VALUES (4, 4); +CREATE TABLE t2(f1 INT, f2 INT); +INSERT INTO t2 VALUES (4, 24); +--error ER_CHECK_CONSTRAINT_VIOLATED +UPDATE t1,t2 SET t1.f2 = t1.f2 + 20 WHERE t1.f1 = t2.f1; +UPDATE IGNORE t1,t2 SET t1.f2 = t1.f2 + 20 WHERE t1.f1 = t2.f1; +DROP TABLE t1, t2; + +CREATE TABLE t1 ( + `f1` int(10) unsigned NOT NULL auto_increment, + `f2` int(11) NOT NULL default '0', + PRIMARY KEY (`f1`) +); +INSERT INTO t1 VALUES (4433,5424); +CREATE TABLE t2 ( + `f3` int(10) unsigned NOT NULL default '0', + `f4` int(10) unsigned NOT NULL default '0' CHECK (f4 <= 500), + PRIMARY KEY (`f3`,`f4`) +); +INSERT INTO t2 VALUES (495,500); +INSERT INTO t2 VALUES (496,500); +--error ER_CHECK_CONSTRAINT_VIOLATED +UPDATE t2,t1 set t2.f4 = t2.f4 + 1; +UPDATE IGNORE t2,t1 set t2.f4 = t2.f4 + 1; +DROP TABLE t1, t2; + + +--echo #------------------------------------------------------------------------ +--echo # Test cases to verify generated check constraint name updates due to +--echo # RENAME TABLE operation. +--echo #------------------------------------------------------------------------ +CREATE TABLE t1 (f1 INT CHECK(f1 < 10)); +SHOW CREATE TABLE t1; +RENAME TABLE t1 TO t2; +SHOW CREATE TABLE t2; + +CREATE TABLE t1(f1 INT CHECK (f1>10), f11 INT CHECK (f11 < 1000)); +SHOW CREATE TABLE t1; +RENAME TABLE t1 TO t3, t2 TO t1, t3 TO t2; +SHOW CREATE TABLE t1; +SHOW CREATE TABLE t2; +DROP TABLE t1, t2; + + +--echo #------------------------------------------------------------------------ +--echo # Test case to verify check constraints removal on DROP table operation. +--echo #------------------------------------------------------------------------ +CREATE TABLE t1(f1 INT PRIMARY KEY, f2 INT CHECK (f2 < 10)); +SHOW CREATE TABLE t1; +SELECT * FROM INFORMATION_SCHEMA.CHECK_CONSTRAINTS; +SELECT * FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE TABLE_NAME='t1'; +DROP TABLE t1; + + +--echo #------------------------------------------------------------------------ +--echo # Test case to verify check constraints creation with ALTER TABLE ADD +--echo # CONSTRAINT operation. +--echo #------------------------------------------------------------------------ +CREATE TABLE t1 (f1 INT CHECK (f1 < 10)); +CREATE TEMPORARY TABLE t3(f1 INT CHECK (f1 < 10)); +ALTER TABLE t1 ADD CONSTRAINT CHECK (f1 > 1), ADD CONSTRAINT `t1_p_ck` CHECK (f1 > 1); +ALTER TABLE t3 ADD CONSTRAINT CHECK (f1 > 1), ADD CONSTRAINT `t3_p_ck` CHECK (f1 > 1); + +SHOW CREATE TABLE t1; +SHOW CREATE TABLE t3; + +--echo # Test case to verify check constraint creation with ALTER TABLE ADD +--echo # constraint and generated name updates with RENAME TO
in +--echo # ALTER operation. +ALTER TABLE t1 ADD f2 INT CHECK (f2 < 10), RENAME TO t6, ALGORITHM=COPY; +SHOW CREATE TABLE t6; +ALTER TABLE t3 ADD f2 INT CHECK (f2 < 10), RENAME TO t7, ALGORITHM=COPY; +SHOW CREATE TABLE t7; +ALTER TABLE t6 RENAME TO t1; +SHOW CREATE TABLE t1; +ALTER TABLE t7 RENAME TO t3; +SHOW CREATE TABLE t3; + +--echo # Test case to verify add check constraint with INPLACE alter algorithm. +--error ER_ALTER_OPERATION_NOT_SUPPORTED +ALTER TABLE t1 ADD f2 INT CHECK (f2 < 10), ALGORITHM=INPLACE; +--error ER_ALTER_OPERATION_NOT_SUPPORTED +ALTER TABLE t3 ADD f2 INT CHECK (f2 < 10), ALGORITHM=INPLACE; +ALTER TABLE t1 ADD f3 INT CHECK (f3 < 10) NOT ENFORCED, ALGORITHM=INPLACE; +ALTER TABLE t1 ADD CONSTRAINT CHECK (f2 < 10) NOT ENFORCED, ALGORITHM=INPLACE; + +--ERROR ER_BAD_FIELD_ERROR +ALTER TABLE t1 RENAME COLUMN f1 TO f10; + + +--echo #------------------------------------------------------------------------ +--echo # Test case to verify check constraints creation with ALTER TABLE DROP +--echo # CONSTRAINT operation. +--echo #------------------------------------------------------------------------ +SHOW CREATE TABLE t3; +ALTER TABLE t3 DROP CHECK t3_chk_3; +SHOW CREATE TABLE t3; +ALTER TABLE t3 DROP CHECK t3_p_ck, ADD CONSTRAINT t3_p_ck CHECK (f1 > 38); +SHOW CREATE TABLE t3; + + +--echo #------------------------------------------------------------------------ +--echo # Test case to verify check constraints alter operations. +--echo #------------------------------------------------------------------------ +INSERT INTO t1 VALUES (5, 5, 5); +ALTER TABLE t1 ALTER CHECK t1_chk_1 NOT ENFORCED, ALGORITHM=INPLACE; +INSERT INTO t1 VALUES (8, 8, 8); +--error ER_ALTER_OPERATION_NOT_SUPPORTED +ALTER TABLE t1 ALTER CHECK t1_chk_1 ENFORCED, ALGORITHM=INPLACE; +ALTER TABLE t1 ALTER CHECK t1_chk_1 ENFORCED, ALGORITHM=COPY; +ALTER TABLE t1 ALTER CHECK t1_chk_1 ENFORCED, ALGORITHM=INPLACE; + +--error ER_CHECK_CONSTRAINT_VIOLATED +INSERT INTO t1 VALUES (12, 5, 5); +ALTER TABLE t1 ALTER CHECK t1_chk_1 NOT ENFORCED, ALGORITHM=INPLACE; +INSERT INTO t1 VALUES (12, 5, 5); +--error ER_CHECK_CONSTRAINT_VIOLATED +ALTER TABLE t1 ALTER CHECK t1_chk_1 ENFORCED, ALGORITHM=COPY; + +DROP TABLE t1, t3; + + +--echo #----------------------------------------------------------------------- +--echo # Test case to add check constraint with copy,instant,inplace algorithm +--echo #----------------------------------------------------------------------- +CREATE TABLE t1(c1 INT); +ALTER TABLE t1 ADD CONSTRAINT CHECK (C1 > 10), ALGORITHM=COPY; +--error ER_ALTER_OPERATION_NOT_SUPPORTED +ALTER TABLE t1 ADD CONSTRAINT CHECK (C1 > 10), ALGORITHM=INPLACE; +--error ER_ALTER_OPERATION_NOT_SUPPORTED +ALTER TABLE t1 ADD CONSTRAINT CHECK (C1 > 10), ALGORITHM=INSTANT; +SHOW CREATE TABLE t1; +DROP TABLE t1; + + +--echo #----------------------------------------------------------------------- +--echo # Test case to verify drop check constraint with inplace algorithm. +--echo #----------------------------------------------------------------------- +CREATE TABLE t1 (f1 INT CHECK (f1 < 10)); +SHOW CREATE TABLE t1; +ALTER TABLE t1 DROP CHECK t1_chk_1, ALGORITHM=INPLACE; +ALTER TABLE t1 ADD CONSTRAINT t1_chk_1 CHECK (f1 < 10), DROP CHECK t1_chk_1, ALGORITHM=INPLACE; +SHOW CREATE TABLE t1; +DROP TABLE t1; + + +--echo #----------------------------------------------------------------------- +--echo # Test case to alter table to add/drop column with the check constraint. +--echo #----------------------------------------------------------------------- +CREATE TABLE t1 (c1 INT, CONSTRAINT ck1 CHECK (c1 > 10)); +ALTER TABLE t1 ADD COLUMN c2 INT, + ADD CONSTRAINT ck2 CHECK (c2 > 10); +SHOW CREATE TABLE t1; +--error ER_CHECK_CONSTRAINT_VIOLATED +INSERT INTO t1 VALUES(20,10); +ALTER TABLE t1 DROP CHECK ck2, DROP COLUMN c2; +ALTER TABLE t1 ADD COLUMN c3 INT, + ADD CONSTRAINT ck3 CHECK (c3 < 10); +ALTER TABLE t1 DROP CHECK ck3, DROP COLUMN c3, + ADD COLUMN c4 INT, ADD CONSTRAINT ck4 CHECK( c4 > 10); +SHOW CREATE TABLE t1; +DROP TABLE t1; + + +--echo #----------------------------------------------------------------------- +--echo # Test case to verify +--echo # - Creation of check constraint with NOT ENFORCED state. +--echo # - Listing state of the check constraints with SHOW and +--echo # INFORMATION_SCHEMA.CHECK_CONSTRAINTS table. +--echo # - State updates with ALTER TABLE statement to ALTER +--echo # check constraints. +--echo #----------------------------------------------------------------------- +CREATE TABLE t1(f1 INT, + f2 INT CHECK (f2 < 10), + f3 INT CHECK (f3 < 10) NOT ENFORCED, + CONSTRAINT ck CHECK (f1 > 10), + CONSTRAINT CHECK (f1 > 10) NOT ENFORCED); +SHOW CREATE TABLE t1; +SELECT * FROM INFORMATION_SCHEMA.CHECK_CONSTRAINTS; + +--echo # REVOKE check constraint ck. +ALTER TABLE t1 ALTER CHECK ck NOT ENFORCED; +SHOW CREATE TABLE t1; +SELECT * FROM INFORMATION_SCHEMA.CHECK_CONSTRAINTS; + +--echo # ENFORCE check constraint ck. +ALTER TABLE t1 ALTER CHECK ck ENFORCED; +SHOW CREATE TABLE t1; +SELECT * FROM INFORMATION_SCHEMA.CHECK_CONSTRAINTS; + +--echo # Add new constraint in NOT ENFORCED state. +ALTER TABLE t1 ADD CONSTRAINT ck1 CHECK(f1<10) NOT ENFORCED; +SHOW CREATE TABLE t1; +SELECT * FROM INFORMATION_SCHEMA.CHECK_CONSTRAINTS; + +--echo # ENFORCE check constraint ck1 +ALTER TABLE t1 ALTER CHECK ck1 ENFORCED; +SHOW CREATE TABLE t1; +SELECT * FROM INFORMATION_SCHEMA.CHECK_CONSTRAINTS; + +--echo # ENFORCE check constraint t1_chk_2 +ALTER TABLE t1 ALTER CHECK t1_chk_2 ENFORCED; +SHOW CREATE TABLE t1; +SELECT * FROM INFORMATION_SCHEMA.CHECK_CONSTRAINTS; + +--echo # ADD column check constraint in NOT ENFORCED state. +ALTER TABLE t1 ADD f4 INT CONSTRAINT t1_f4_chk CHECK (f4 < 10) NOT ENFORCED; +SHOW CREATE TABLE t1; +SELECT * FROM INFORMATION_SCHEMA.CHECK_CONSTRAINTS; + +--echo # ENFORCE check constraint t1_f4_chk +ALTER TABLE t1 ALTER CHECK t1_f4_chk ENFORCED; +SHOW CREATE TABLE t1; +SELECT * FROM INFORMATION_SCHEMA.CHECK_CONSTRAINTS; + +DROP TABLE t1; + + +--echo #----------------------------------------------------------------------- +--echo # Test case to verify alter statement with drop and alter constraint +--echo # on non-existing check constraint. +--echo #----------------------------------------------------------------------- +CREATE TABLE t1(c1 INT, c2 INT, c3 INT, c4 INT); +--error ER_CHECK_CONSTRAINT_NOT_FOUND +ALTER TABLE t1 DROP CHECK ck13; +--error ER_CHECK_CONSTRAINT_NOT_FOUND +ALTER TABLE t1 ALTER CHECK ck13 ENFORCED; +DROP TABLE t1; + + +--echo #----------------------------------------------------------------------- +--echo # Test case to verify alter statement with multiple add, drop, enforce, +--echo # revoke check constraints. +--echo #----------------------------------------------------------------------- +CREATE TABLE t1(c1 INT, c2 INT, c3 INT, c4 INT); +ALTER TABLE t1 ADD CONSTRAINT ck11 CHECK(c1 > 1), + ADD CONSTRAINT ck12 CHECK(c1 < 1), + ADD CONSTRAINT ck21 CHECK(c2 > 1), + ADD CONSTRAINT ck22 CHECK(c2 < 1), + ADD CONSTRAINT ck31 CHECK(c3 > 1), + ADD CONSTRAINT ck32 CHECK(c3 < 1), + ADD CONSTRAINT ck41 CHECK(c4 > 1), + ADD CONSTRAINT ck42 CHECK(c4 < 1); +SHOW CREATE TABLE t1; + +ALTER TABLE t1 + DROP CHECK ck11, ADD CONSTRAINT ck11 CHECK (c1 > 10), + DROP CHECK ck12, ADD CONSTRAINT ck12 CHECK (c1 < 10), + DROP CHECK ck21, ADD CONSTRAINT ck21 CHECK (c1 > 10), + DROP CHECK ck22, ADD CONSTRAINT ck22 CHECK (c1 < 10), + DROP CHECK ck31, ADD CONSTRAINT ck31 CHECK (c1 > 10), + DROP CHECK ck32, ADD CONSTRAINT ck32 CHECK (c1 < 10), + DROP CHECK ck41, ADD CONSTRAINT ck41 CHECK (c1 > 10), + DROP CHECK ck42, ADD CONSTRAINT ck42 CHECK (c1 < 10), + ALTER CHECK ck11 NOT ENFORCED, + ALTER CHECK ck12 NOT ENFORCED, + ALTER CHECK ck21 NOT ENFORCED, + ALTER CHECK ck22 NOT ENFORCED, + ALTER CHECK ck11 ENFORCED; + +SHOW CREATE TABLE t1; +DROP TABLE t1; + + +--echo #----------------------------------------------------------------------- +--echo # Test case to verify auto-drop of check constraint on column drop. +--echo #----------------------------------------------------------------------- +CREATE TABLE t1 (f1 INT check (f1 < 10), f2 INT); +SHOW CREATE TABLE t1; +--echo # Drops check constraint t1_chk_1 too. +ALTER TABLE t1 DROP COLUMN f1; + +ALTER TABLE t1 ADD COLUMN f1 INT check(f1 < 10), + ADD CONSTRAINT check(f1 + f2 < 10), + ADD CONSTRAINT check(f2 < 10); +SHOW CREATE TABLE t1; +--error ER_BAD_FIELD_ERROR +ALTER TABLE t1 DROP COLUMN f1; +--error ER_BAD_FIELD_ERROR +ALTER TABLE t1 RENAME COLUMN f1 to f3; +--echo # Drops column f1 and constraints t1_chk_1, t1_chk_2. +ALTER TABLE t1 DROP CHECK t1_chk_2, DROP COLUMN f1; +SHOW CREATE TABLE t1; +DROP TABLE t1; + + +--echo #----------------------------------------------------------------------- +--echo # Test case to verify check constraint with MODIFY COLUMN syntax. +--echo #----------------------------------------------------------------------- +CREATE TABLE t1(c1 CHAR(1), CHECK (c1 > 'A')); +SHOW CREATE TABLE t1; +--error ER_CHECK_CONSTRAINT_VIOLATED +INSERT INTO t1 VALUES('A'); +INSERT INTO t1 VALUES('B'); +DELETE FROM t1; +SHOW CREATE TABLE t1; +ALTER TABLE t1 MODIFY COLUMN c1 FLOAT(10.3), DROP CHECK t1_chk_1, ADD CONSTRAINT CHECK(C1 > 10.1) ENFORCED; +SHOW CREATE TABLE t1; +DROP TABLE t1; + +CREATE TABLE t1 (f1 INT CHECK (f1 = default(f1))); +INSERT INTO t1 VALUES (10); +--error ER_ALTER_OPERATION_NOT_SUPPORTED +ALTER TABLE t1 MODIFY COLUMN f1 INT DEFAULT 20, algorithm=inplace; +--error ER_ALTER_OPERATION_NOT_SUPPORTED +ALTER TABLE t1 ALTER f1 SET DEFAULT 20, algorithm=inplace; +--error ER_CHECK_CONSTRAINT_VIOLATED +ALTER TABLE t1 MODIFY COLUMN f1 INT DEFAULT 20, algorithm=copy; +DROP TABLE t1; + + +--echo #----------------------------------------------------------------------- +--echo # Test case to verify check constraint with CHANGE COLUMN syntax. +--echo #----------------------------------------------------------------------- +CREATE TABLE t1(c1 CHAR(1), CHECK (c1 > 'A')); +SHOW CREATE TABLE t1; +--error ER_ALTER_OPERATION_NOT_SUPPORTED +ALTER TABLE t1 CHANGE c1 c1 FLOAT, ALGORITHM=INPLACE; +ALTER TABLE t1 DROP CHECK t1_chk_1, CHANGE c1 c2 VARCHAR(20), ADD CONSTRAINT CHECK(c2 > 'B'); +SHOW CREATE TABLE t1; +DROP TABLE t1; + +CREATE TABLE t (a INT, b INT, CHECK(a != b)); +INSERT INTO t VALUES (2000000000, 2000000001); +--error ER_CHECK_CONSTRAINT_VIOLATED +ALTER TABLE t CHANGE a a FLOAT, CHANGE b b FLOAT; +--error ER_CHECK_CONSTRAINT_VIOLATED +ALTER TABLE t ADD CONSTRAINT CHECK(a > b); +DROP TABLE t; + + +--echo #------------------------------------------------------------------------ +--echo # Test case to verify check constraints with IN operator. +--echo #------------------------------------------------------------------------ +CREATE TABLE t1(f1 int CHECK (f1 IN (10, 20, 30)), f2 int, CHECK(f2 IN (100, 120, 450))); +SHOW CREATE TABLE t1; +INSERT INTO t1 VALUES(10, 100); +--error ER_CHECK_CONSTRAINT_VIOLATED +INSERT INTO t1 VALUES(15, 100); +--error ER_CHECK_CONSTRAINT_VIOLATED +INSERT INTO t1 VALUES(10, 105); +DROP TABLE t1; + + +--echo #------------------------------------------------------------------------ +--echo # Test case to verify check constraints with BETWEEN operator. +--echo #------------------------------------------------------------------------ +CREATE TABLE t1(f1 int CHECK(f1 BETWEEN 10 AND 30), + f2 int, CHECK(f2 BETWEEN 100 AND 450)); +SHOW CREATE TABLE t1; +INSERT INTO t1 VALUES(20, 200); +--error ER_CHECK_CONSTRAINT_VIOLATED +INSERT INTO t1 VALUES(2, 200); +--error ER_CHECK_CONSTRAINT_VIOLATED +INSERT INTO t1 VALUES(20, 2000); +DROP TABLE t1; + + +--echo #------------------------------------------------------------------------ +--echo # Test case to verify check constraints with IS NOT NULL. +--echo #------------------------------------------------------------------------ +CREATE TABLE t1 (f1 int CHECK(f1 IS NOT NULL)); +SHOW CREATE TABLE t1; +INSERT INTO t1 VALUES(10); +--error ER_CHECK_CONSTRAINT_VIOLATED +INSERT INTO t1 VALUES(NULL); +DROP TABLE t1; + + +--echo #------------------------------------------------------------------------ +--echo # Test case to verify check constraints with IS NULL. +--echo #------------------------------------------------------------------------ +CREATE TABLE t1 (f1 int CHECK(f1 IS NULL)); +SHOW CREATE TABLE t1; +INSERT INTO t1 VALUES(NULL); +--error ER_CHECK_CONSTRAINT_VIOLATED +INSERT INTO t1 VALUES(10); +DROP TABLE t1; + + +--echo #----------------------------------------------------------------------- +--echo # Test case to verify check constraint with CASE Statement +--echo #----------------------------------------------------------------------- +CREATE TABLE t1(c1 INT, c2 INT); +ALTER TABLE t1 ADD CONSTRAINT CHECK( (CASE WHEN c1 > 10 THEN c2 = 20 END) = 1); +SHOW CREATE TABLE t1; +INSERT INTO t1 VALUES(1,1); +--error ER_CHECK_CONSTRAINT_VIOLATED +INSERT INTO t1 VALUES(15,1); +INSERT INTO t1 VALUES(15,20); +SELECT * FROM t1; +DROP TABLE t1; + + +--echo #------------------------------------------------------------------------ +--echo # Test case to verify check constraints restrictions. +--echo #------------------------------------------------------------------------ + +--echo # Check constraint using column with AUTO_INCREMENT attribute. +--error ER_CHECK_CONSTRAINT_REFERS_AUTO_INCREMENT_COLUMN +CREATE TABLE t1 (f1 int primary key auto_increment, f2 int, CHECK (f1 != f2)); + +--error ER_CHECK_CONSTRAINT_REFERS_AUTO_INCREMENT_COLUMN +CREATE TABLE t1 (f1 int primary key auto_increment CHECK (f1 < 10), f2 int, CHECK (f1 != f2)); + +--echo # Check constraint using non-deterministic builtin functions. +--echo # NOW() +--error ER_CHECK_CONSTRAINT_NAMED_FUNCTION_IS_NOT_ALLOWED +CREATE TABLE t1 (f1 TIMESTAMP CHECK (f1 + NOW() > '2011-11-21')); + +--echo # CURRENT_TIMESTAMP() +--error ER_CHECK_CONSTRAINT_NAMED_FUNCTION_IS_NOT_ALLOWED +CREATE TABLE t1 (f1 TIMESTAMP CHECK (f1 + CURRENT_TIMESTAMP() > '2011-11-21 01:02:03')); + +--echo # CURRENT_TIMESTAMP +--error ER_CHECK_CONSTRAINT_NAMED_FUNCTION_IS_NOT_ALLOWED +CREATE TABLE t1 (f1 TIMESTAMP CHECK (f1 + CURRENT_TIMESTAMP > '2011-11-21 01:02:03')); + +--echo # CURDATE() +--error ER_CHECK_CONSTRAINT_NAMED_FUNCTION_IS_NOT_ALLOWED +CREATE TABLE t1 (f1 DATETIME CHECK (f1 + CURDATE() > '2011-11-21')); + +--echo # CURTIME() +--error ER_CHECK_CONSTRAINT_NAMED_FUNCTION_IS_NOT_ALLOWED +CREATE TABLE t1 (f1 DATETIME CHECK (f1 + CURTIME() > '23:11:21')); + +--echo # CURTIME +--error ER_CHECK_CONSTRAINT_NAMED_FUNCTION_IS_NOT_ALLOWED +CREATE TABLE t1 (f1 TIMESTAMP CHECK (f1 + CURRENT_TIME > '01:02:03')); + +--echo # CURRENT_DATE() +--error ER_CHECK_CONSTRAINT_NAMED_FUNCTION_IS_NOT_ALLOWED +CREATE TABLE t1 (f1 TIMESTAMP CHECK (f1 + CURRENT_DATE() > '2011-11-21')); + +--echo # CURRENT_DATE +--error ER_CHECK_CONSTRAINT_NAMED_FUNCTION_IS_NOT_ALLOWED +CREATE TABLE t1 (f1 TIMESTAMP CHECK (f1 + CURRENT_DATE > '2011-11-21')); + +--echo # CURRENT_TIME() +--error ER_CHECK_CONSTRAINT_NAMED_FUNCTION_IS_NOT_ALLOWED +CREATE TABLE t1 (f1 TIMESTAMP CHECK (f1 + CURRENT_TIME() > '01:02:03')); + +--echo # CURRENT_TIME +--error ER_CHECK_CONSTRAINT_NAMED_FUNCTION_IS_NOT_ALLOWED +CREATE TABLE t1 (f1 TIMESTAMP CHECK (f1 + CURRENT_TIME > '01:02:03')); + +--echo # LOCALTIME() +--error ER_CHECK_CONSTRAINT_NAMED_FUNCTION_IS_NOT_ALLOWED +CREATE TABLE t1 (f1 DATETIME CHECK (f1 + LOCALTIME() > '23:11:21')); + +--echo # LOCALTIME +--error ER_CHECK_CONSTRAINT_NAMED_FUNCTION_IS_NOT_ALLOWED +CREATE TABLE t1 (f1 DATETIME CHECK (f1 + LOCALTIME > '23:11:21')); + +--echo # LOCALTIMESTAMP() +--error ER_CHECK_CONSTRAINT_NAMED_FUNCTION_IS_NOT_ALLOWED +CREATE TABLE t1 (f1 TIMESTAMP CHECK (f1 + LOCALTIMESTAMP() > '2011-11-21 01:02:03')); + +--echo # LOCALTIMESTAMP +--error ER_CHECK_CONSTRAINT_NAMED_FUNCTION_IS_NOT_ALLOWED +CREATE TABLE t1 (f1 TIMESTAMP CHECK (f1 + LOCALTIMESTAMP > '2011-11-21 01:02:03')); + +--echo # UNIX_TIMESTAMP() +--error ER_CHECK_CONSTRAINT_NAMED_FUNCTION_IS_NOT_ALLOWED +CREATE TABLE t1 (f1 TIMESTAMP CHECK (f1 + UNIX_TIMESTAMP() > '2011-11-21 01:02:03')); + +--echo # UNIX_DATE() +--error ER_CHECK_CONSTRAINT_NAMED_FUNCTION_IS_NOT_ALLOWED +CREATE TABLE t1 (f1 DATETIME CHECK (f1 + UTC_DATE() > '2011-11-21')); + +--echo # UNIX_TIMESTAMP() +--error ER_CHECK_CONSTRAINT_NAMED_FUNCTION_IS_NOT_ALLOWED +CREATE TABLE t1 (f1 TIMESTAMP CHECK (f1 + UTC_TIMESTAMP() > '2011-11-21 01:02:03')); + +--echo # UNIX_TIME() +--error ER_CHECK_CONSTRAINT_NAMED_FUNCTION_IS_NOT_ALLOWED +CREATE TABLE t1 (f1 DATETIME CHECK (f1 + UTC_TIME() > '23:11:21')); + +--echo # CONNECTION_ID +--error ER_CHECK_CONSTRAINT_NAMED_FUNCTION_IS_NOT_ALLOWED +CREATE TABLE t1 (f1 INT CHECK (f1 + CONNECTION_ID() < 929)); + +--echo # CURRENT_USER() +--error ER_CHECK_CONSTRAINT_NAMED_FUNCTION_IS_NOT_ALLOWED +CREATE TABLE t1 (a VARCHAR(32) CHECK (CURRENT_USER() != a)); + +--echo # CURRENT_USER +--error ER_CHECK_CONSTRAINT_NAMED_FUNCTION_IS_NOT_ALLOWED +CREATE TABLE t1 (a VARCHAR(32) CHECK (CURRENT_USER != a)); + +--echo # SESSION_USER() +--error ER_CHECK_CONSTRAINT_NAMED_FUNCTION_IS_NOT_ALLOWED +CREATE TABLE t1 (a VARCHAR(32) CHECK (SESSION_USER() != a)); + +--echo # VERSION() +--error ER_CHECK_CONSTRAINT_NAMED_FUNCTION_IS_NOT_ALLOWED +CREATE TABLE t1 (a VARCHAR(32) CHECK (VERSION() != a)); + +--echo # FOUND_ROWS +--error ER_CHECK_CONSTRAINT_NAMED_FUNCTION_IS_NOT_ALLOWED +CREATE TABLE t1 (a VARCHAR(1024), b INT CHECK (b + FOUND_ROWS() > 2000)); + +--echo # LAST_INSERT_ID +--error ER_CHECK_CONSTRAINT_NAMED_FUNCTION_IS_NOT_ALLOWED +CREATE TABLE t1 (a INT CHECK ((a + LAST_INSERT_ID()) < 929)); + +--echo # SYSTEM_USER +--error ER_CHECK_CONSTRAINT_NAMED_FUNCTION_IS_NOT_ALLOWED +CREATE TABLE t1 (a VARCHAR(32) CHECK (SYSTEM_USER() != a)); + +--echo # USER +--error ER_CHECK_CONSTRAINT_NAMED_FUNCTION_IS_NOT_ALLOWED +CREATE TABLE t1 (a VARCHAR(32) CHECK (USER() != a)); + +--echo # RAND() +--error ER_CHECK_CONSTRAINT_NAMED_FUNCTION_IS_NOT_ALLOWED +CREATE TABLE t1 (f1 FLOAT CHECK (f1 + RAND() < 929.929)); + +--echo # ROW_COUNT() +--error ER_CHECK_CONSTRAINT_NAMED_FUNCTION_IS_NOT_ALLOWED +CREATE TABLE t1 (a INT CHECK (a + ROW_COUNT() > 1000)); + +--echo # GET_LOCK() +--error ER_CHECK_CONSTRAINT_NAMED_FUNCTION_IS_NOT_ALLOWED +CREATE TABLE t1 (a VARCHAR(1024), b VARCHAR(1024) CHECK (GET_LOCK(b,10) != 0)); + +--echo # IS_FREE_LOCK() +--error ER_CHECK_CONSTRAINT_NAMED_FUNCTION_IS_NOT_ALLOWED +CREATE TABLE t1 (a VARCHAR(1024), b VARCHAR(1024) CHECK (IS_FREE_LOCK(b) != 0)); + +--echo # IS_USED_LOCK() +--error ER_CHECK_CONSTRAINT_NAMED_FUNCTION_IS_NOT_ALLOWED +CREATE TABLE t1 (a VARCHAR(1024), b VARCHAR(1024) CHECK (IS_USED_LOCK(b) != 0)); + +--echo # RELEASE_LOCK() +--error ER_CHECK_CONSTRAINT_NAMED_FUNCTION_IS_NOT_ALLOWED +CREATE TABLE t1 (a VARCHAR(1024), b VARCHAR(1024) CHECK (RELEASE_LOCK(b) != 0)); + +--echo # RELEASE_ALL_LOCK() +--error ER_CHECK_CONSTRAINT_NAMED_FUNCTION_IS_NOT_ALLOWED +CREATE TABLE t1 (a VARCHAR(1024), b VARCHAR(1024), CHECK (RELEASE_ALL_LOCKS() != 0)); + +--echo # LOAD_FILE +--error ER_CHECK_CONSTRAINT_NAMED_FUNCTION_IS_NOT_ALLOWED +CREATE TABLE t1 (f1 VARCHAR(1024), f2 VARCHAR(1024) CHECK (LOAD_FILE(f2) != NULL)); + +--echo # UUID() +--error ER_CHECK_CONSTRAINT_NAMED_FUNCTION_IS_NOT_ALLOWED +CREATE TABLE t1 (id CHAR(40) CHECK(UUID() != id)); + +--echo # UUID_SHORT +--error ER_CHECK_CONSTRAINT_NAMED_FUNCTION_IS_NOT_ALLOWED +CREATE TABLE t1 (id INT CHECK(UUID_SHORT() != id)); + +--echo # SLEEP +--error ER_CHECK_CONSTRAINT_NAMED_FUNCTION_IS_NOT_ALLOWED +CREATE TABLE t1 (id INT CHECK(SLEEP(id) != 0)); + +--echo # Stored function +CREATE FUNCTION func() RETURNS INT DETERMINISTIC return 1; +--error ER_CHECK_CONSTRAINT_NAMED_FUNCTION_IS_NOT_ALLOWED +CREATE TABLE t1 (id INT CHECK(id = func())); +DROP FUNCTION func; + +--echo # Stored procedure +CREATE PROCEDURE proc() SELECT 1; +--error ER_CHECK_CONSTRAINT_NAMED_FUNCTION_IS_NOT_ALLOWED +CREATE TABLE t1 (id INT CHECK(id = proc())); +DROP PROCEDURE proc; + +--echo # User variable +SET @v = 10; +--error ER_CHECK_CONSTRAINT_VARIABLES +CREATE TABLE t1 (id INT CHECK (id != @v)); + +--echo # System variables. +--error ER_CHECK_CONSTRAINT_VARIABLES +CREATE TABLE t1 (id INT CHECK (id != @@global.max_execution_time)); +--error ER_CHECK_CONSTRAINT_VARIABLES +CREATE TABLE t1 (id INt CHECK (id != @@session.max_execution_time)); + +--echo # Subquery +--error ER_CHECK_CONSTRAINT_FUNCTION_IS_NOT_ALLOWED +CREATE TABLE t1 (id INT CHECK (id != (SELECT 1))); + +--echo # Parameter +PREPARE stmt FROM 'CREATE TABLE t1 (id INT CHECK(id != ?))'; +--error ER_CHECK_CONSTRAINT_FUNCTION_IS_NOT_ALLOWED +EXECUTE stmt using @v; +DEALLOCATE PREPARE stmt; + + +--echo #------------------------------------------------------------------------ +--echo # Test case to verify check constraints with numeric data types. +--echo #------------------------------------------------------------------------ +CREATE TABLE t1 ( + c1 BIT(7) CHECK(c1 < B'1111100'), + c2 BOOLEAN CHECK(c2 > 0), + c3 TINYINT CHECK(c3 > 10), + c4 SMALLINT CHECK(c4 > 10), + c5 MEDIUMINT CHECK(c5 > 10), + c6 INT CHECK(c6 > 10), + c7 BIGINT CHECK(c7 > 10), + c8 DECIMAL(6,2) CHECK(c8 > 10.1), + c9 FLOAT(6,2) CHECK(c9 > 10.1), + c10 DOUBLE(6,2) CHECK(c10 > 10.1)); +SHOW CREATE TABLE t1; + +--error ER_CHECK_CONSTRAINT_VIOLATED +INSERT INTO t1(c1) VALUES(B'1111110'); +--error ER_CHECK_CONSTRAINT_VIOLATED +INSERT INTO t1(c2) VALUES(0); +--error ER_CHECK_CONSTRAINT_VIOLATED +INSERT INTO t1(c3) VALUES(1); +--error ER_CHECK_CONSTRAINT_VIOLATED +INSERT INTO t1(c4) VALUES(1); +--error ER_CHECK_CONSTRAINT_VIOLATED +INSERT INTO t1(c5) VALUES(1); +--error ER_CHECK_CONSTRAINT_VIOLATED +INSERT INTO t1(c6) VALUES(1); +--error ER_CHECK_CONSTRAINT_VIOLATED +INSERT INTO t1(c7) VALUES(1); +--error ER_CHECK_CONSTRAINT_VIOLATED +INSERT INTO t1(c8) VALUES(10.0); +--error ER_CHECK_CONSTRAINT_VIOLATED +INSERT INTO t1(c9) VALUES(10.0); +--error ER_CHECK_CONSTRAINT_VIOLATED +INSERT INTO t1(c10) VALUES(10.0); + +INSERT INTO t1(c1,c2,c3,c4,c5,c6,c7,c8,c9,c10) + VALUES(B'1111000',1,11,11,11,11,11,10.2,10.2,10.2); + +DROP TABLE t1; + + +--echo #------------------------------------------------------------------------ +--echo # Test case to verify check constraints with string data types. +--echo #------------------------------------------------------------------------ +CREATE TABLE t1(c1 CHAR(1) CHECK(c1 > 'a'), + c2 VARCHAR(1) CHECK(c2 > 'a'), + c3 BINARY(1) CHECK(c3 > 'a'), + c4 VARBINARY(1) CHECK(c4 > 'a'), + c5 TINYBLOB CHECK(c5 > 'a'), + c6 TINYTEXT CHECK(c6 > 'a'), + c7 BLOB CHECK(c7 > 'a'), + c8 TEXT CHECK(c8 > 'a'), + c9 MEDIUMBLOB CHECK(c9 > 'a'), + c10 MEDIUMTEXT CHECK(c10 > 'a'), + c11 LONGBLOB CHECK(c11 > 'a'), + c12 LONGTEXT CHECK(c12 > 'a')); +SHOW CREATE TABLE t1; + +--error ER_CHECK_CONSTRAINT_VIOLATED +INSERT INTO t1(c1) VALUES('a'); +--error ER_CHECK_CONSTRAINT_VIOLATED +INSERT INTO t1(c2) VALUES('a'); +--error ER_CHECK_CONSTRAINT_VIOLATED +INSERT INTO t1(c3) VALUES('a'); +--error ER_CHECK_CONSTRAINT_VIOLATED +INSERT INTO t1(c4) VALUES('a'); +--error ER_CHECK_CONSTRAINT_VIOLATED +INSERT INTO t1(c5) VALUES('a'); +--error ER_CHECK_CONSTRAINT_VIOLATED +INSERT INTO t1(c6) VALUES('a'); +--error ER_CHECK_CONSTRAINT_VIOLATED +INSERT INTO t1(c7) VALUES('a'); +--error ER_CHECK_CONSTRAINT_VIOLATED +INSERT INTO t1(c8) VALUES('a'); +--error ER_CHECK_CONSTRAINT_VIOLATED +INSERT INTO t1(c9) VALUES('a'); +--error ER_CHECK_CONSTRAINT_VIOLATED +INSERT INTO t1(c10) VALUES('a'); +--error ER_CHECK_CONSTRAINT_VIOLATED +INSERT INTO t1(c11) VALUES('a'); +--error ER_CHECK_CONSTRAINT_VIOLATED +INSERT INTO t1(c12) VALUES('a'); + +INSERT INTO t1(c1,c2,c3,c4,c5,c6,c7,c8,c9,c10,c11,c12) + VALUES('b',"b","b","b","b","b","b","b","b","b","b","b"); + +DROP TABLE t1; + + +--echo #------------------------------------------------------------------------ +--echo # Test case to verify check constraints with date and time data types. +--echo #------------------------------------------------------------------------ +CREATE TABLE t1 (c1 DATE CHECK(c1 > '2007-01-01'), + c2 DATETIME CHECK(c2 > '2007-01-01 12:00:01'), + c3 TIMESTAMP CHECK(c3 > '2007-01-01 00:00:01.000000'), + c4 TIME CHECK(c4 > '12:00:01.000000'), + c5 YEAR CHECK(c5 > '2007')); + +--error ER_CHECK_CONSTRAINT_VIOLATED +INSERT INTO t1(c1) VALUES('2006-01-01'); +--error ER_CHECK_CONSTRAINT_VIOLATED +INSERT INTO t1(c2) VALUES('2007-01-01 11:00:01'); +--error ER_CHECK_CONSTRAINT_VIOLATED +INSERT INTO t1(c3) VALUES('2007-01-01 00:00:00.000000'); +--error ER_CHECK_CONSTRAINT_VIOLATED +INSERT INTO t1(c4) VALUES('12:00:00.000000'); +--error ER_CHECK_CONSTRAINT_VIOLATED +INSERT INTO t1(c5) VALUES('2006'); + +INSERT INTO t1(c1,c2,c3,c4,c5) + VALUES('2008-01-01','2007-01-01 12:00:02','2007-01-01 00:00:02.000000', + '12:00:02.000000','2008'); +DROP TABLE t1; + + +--echo #------------------------------------------------------------------------ +--echo # Test case to verify check constraints with JSON data type. +--echo #------------------------------------------------------------------------ +CREATE TABLE t1( + id INT AUTO_INCREMENT PRIMARY KEY, + name VARCHAR(255), + browser JSON CHECK( browser->'$.name' = "Chrome" )); + +--error ER_CHECK_CONSTRAINT_VIOLATED +INSERT INTO t1(name,browser) + VALUES('pageview','{ "name": "Safari", "os": "Mac" }'); + +INSERT INTO t1(name,browser) + VALUES('pageview','{ "name": "Chrome", "os": "Mac" }'); + +SELECT * FROM t1; +DROP TABLE t1; + + +--echo #----------------------------------------------------------------------- +--echo # check constraint with ENUM data type +--echo #----------------------------------------------------------------------- +CREATE TABLE t1 (c1 ENUM ('a','b') CHECK (c1 IN ('c', 'd')) ); +SHOW CREATE TABLE t1; +--error ER_CHECK_CONSTRAINT_VIOLATED +INSERT INTO t1 VALUES('a'); +--error ER_CHECK_CONSTRAINT_VIOLATED +INSERT INTO t1 VALUES('b'); +--error 1265 #WARN_DATA_TRUNCATED +INSERT INTO t1 VALUES('c'); +--error 1265 #WARN_DATA_TRUNCATED +INSERT INTO t1 VALUES('d'); +DROP TABLE t1; + + +--echo #----------------------------------------------------------------------- +--echo # check constraint with SET data type +--echo #----------------------------------------------------------------------- +CREATE TABLE t1 (c1 SET ('a','b') CHECK (c1 IN ('c', 'd')) ); +SHOW CREATE TABLE t1; +--error ER_CHECK_CONSTRAINT_VIOLATED +INSERT INTO t1 VALUES('a'); +--error ER_CHECK_CONSTRAINT_VIOLATED +INSERT INTO t1 VALUES('b'); +--error 1265 #WARN_DATA_TRUNCATED +INSERT INTO t1 VALUES('c'); +--error 1265 #WARN_DATA_TRUNCATED +INSERT INTO t1 VALUES('d'); +DROP TABLE t1; + + +--echo #------------------------------------------------------------------------ +--echo # Test case to verify check constraints with spatial data type. +--echo #------------------------------------------------------------------------ +CREATE TABLE t1( + pt POINT CHECK(ST_Equals(pt, ST_GEOMFROMTEXT('POINT(10 20)')) = TRUE), + lnstr LINESTRING CHECK(ST_Equals(lnstr, ST_GEOMFROMTEXT('LINESTRING(0 0,5 5,6 6)'))), + mlnstr MULTILINESTRING CHECK(ST_Equals(mlnstr, ST_GEOMFROMTEXT('MULTILINESTRING((0 0,2 3,4 5), + (6 6,8 8,9 9,10 10))'))), + poly POLYGON CHECK(ST_Equals(poly, ST_GEOMFROMTEXT('POLYGON((0 0,6 7,8 8,3 9,0 0), + (3 6,4 6,4 7,3 6))'))), + mpoly MULTIPOLYGON CHECK(ST_Equals(mpoly, ST_GEOMFROMTEXT('MULTIPOLYGON(((0 0,0 5,5 5,5 0,0 0)), + ((2 2,4 5,6 2,2 2)))')))); +SHOW CREATE TABLE t1; + +--error ER_CHECK_CONSTRAINT_VIOLATED +INSERT INTO t1(pt) VALUES (ST_GEOMFROMTEXT('POINT(10 21)')); +--error ER_CHECK_CONSTRAINT_VIOLATED +INSERT INTO t1(lnstr) VALUES (ST_GEOMFROMTEXT('LINESTRING(0 0,5 5,6 7)')); +--error ER_CHECK_CONSTRAINT_VIOLATED +INSERT INTO t1(mlnstr) VALUES (ST_GEOMFROMTEXT('MULTILINESTRING((0 0,2 3,4 5),(6 6,8 8,9 9,10 11))')); +--error ER_CHECK_CONSTRAINT_VIOLATED +INSERT INTO t1(poly) VALUES (ST_GEOMFROMTEXT('POLYGON((0 0,6 7,8 8,3 9,0 0),(3 6,4 6,4 8,3 6))')); +--error ER_CHECK_CONSTRAINT_VIOLATED +INSERT INTO t1(mpoly) VALUES (ST_GEOMFROMTEXT('MULTIPOLYGON(((0 0,0 5,5 5,5 0,0 0)),((2 2,4 5,6 3,2 2)))')); + +INSERT INTO t1(pt) VALUES (ST_GEOMFROMTEXT('POINT(10 20)')); +INSERT INTO t1(lnstr) VALUES (ST_GEOMFROMTEXT('LINESTRING(0 0,5 5,6 6)')); +INSERT INTO t1(mlnstr) VALUES (ST_GEOMFROMTEXT('MULTILINESTRING((0 0,2 3,4 5),(6 6,8 8,9 9,10 10))')); +INSERT INTO t1(poly) VALUES (ST_GEOMFROMTEXT('POLYGON((0 0,6 7,8 8,3 9,0 0),(3 6,4 6,4 7,3 6))')); +INSERT INTO t1(mpoly) VALUES (ST_GEOMFROMTEXT('MULTIPOLYGON(((0 0,0 5,5 5,5 0,0 0)),((2 2,4 5,6 2,2 2)))')); + +DROP TABLE t1; + + +--echo #----------------------------------------------------------------------- +--echo # Test case to verify check constraint with REGEX +--echo #----------------------------------------------------------------------- +CREATE TABLE student +( + id INT, + stu_code VARCHAR(10), + name VARCHAR(14), + email VARCHAR(20), + scholarship INT, + country VARCHAR(20), + CONSTRAINT ck1 CHECK (id != 0), + CONSTRAINT ck2 CHECK (stu_code like 'j%'), + CONSTRAINT ck3 CHECK (lower(name) != "noname"), + CONSTRAINT ck4 CHECK (REGEXP_LIKE(email,'@')), + CONSTRAINT ck5 CHECK (scholarship BETWEEN 5000 AND 20000), + CONSTRAINT ck6 CHECK (country IN ('usa','uk')) +); +SHOW CREATE TABLE student; + +--error ER_CHECK_CONSTRAINT_VIOLATED +INSERT INTO student VALUES(0,"j001","name1","name1@oracle.com",6000,'usa'); +--error ER_CHECK_CONSTRAINT_VIOLATED +INSERT INTO student VALUES(1,"s001","name1","name1@oracle.com",6000,'usa'); +--error ER_CHECK_CONSTRAINT_VIOLATED +INSERT INTO student VALUES(1,"j001","NONAME","name1@oracle.com",6000,'usa'); +--error ER_CHECK_CONSTRAINT_VIOLATED +INSERT INTO student VALUES(1,"j001","name1","name1oracle.com",6000,'usa'); +--error ER_CHECK_CONSTRAINT_VIOLATED +INSERT INTO student VALUES(1,"j001","name1","name1@oracle.com",4000,'usa'); +--error ER_CHECK_CONSTRAINT_VIOLATED +INSERT INTO student VALUES(1,"j001","name1","name1@oracle.com",6000,'nocountry'); + +INSERT INTO student VALUES(1,"j001","name1","name1@oracle.com",6000,'usa'); +SELECT * FROM student; +DROP TABLE student; + + +--echo #----------------------------------------------------------------------- +--echo # Test case to verify check constraint with numeric comparator +--echo # operators with varchar columns. +--echo #----------------------------------------------------------------------- +CREATE TABLE t1(c1 INT, c2 VARCHAR(20)); +ALTER TABLE t1 ADD CONSTRAINT ck1 CHECK ( c1 > c2 ); +SHOW CREATE TABLE t1; +DROP TABLE t1; + + +--echo #----------------------------------------------------------------------- +--echo # Test case to verify check constraint with Comparison Functions +--echo # and Operators +--echo #----------------------------------------------------------------------- +--error ER_NON_BOOLEAN_EXPR_FOR_CHECK_CONSTRAINT +CREATE TABLE t1(c1 INT, CHECK ( c1 IN ( SELECT COALESCE(NULL, 1, 1)))); +--error ER_CHECK_CONSTRAINT_FUNCTION_IS_NOT_ALLOWED +CREATE TABLE t1(c1 INT, CHECK ( c1 < ( SELECT COALESCE(NULL, 1, 1)))); +CREATE TABLE t1(c1 INT , CHECK ( c1 <=> NULL )); +--error ER_CHECK_CONSTRAINT_VIOLATED +INSERT INTO t1 VALUES(1); +INSERT INTO t1 VALUES(NULL); +SELECT * FROM t1; + +ALTER TABLE t1 ADD COLUMN c2 INT, ADD CONSTRAINT CHECK( c2 > 10 ); +--error ER_CHECK_CONSTRAINT_VIOLATED +INSERT INTO t1(c2) VALUES(10); +INSERT INTO t1(c2) VALUES(11); + +ALTER TABLE t1 ADD COLUMN c3 INT, ADD CONSTRAINT CHECK( c3 >= 10 ); +--error ER_CHECK_CONSTRAINT_VIOLATED +INSERT INTO t1(c3) VALUES(9); +INSERT INTO t1(c3) VALUES(10); + +ALTER TABLE t1 ADD COLUMN c4 INT, ADD CONSTRAINT CHECK( c4 < 10 ); +--error ER_CHECK_CONSTRAINT_VIOLATED +INSERT INTO t1(c4) VALUES(10); +INSERT INTO t1(c4) VALUES(9); + +ALTER TABLE t1 ADD COLUMN c5 INT, ADD CONSTRAINT CHECK( c5 <= 10 ); +--error ER_CHECK_CONSTRAINT_VIOLATED +INSERT INTO t1(c5) VALUES(11); +INSERT INTO t1(c5) VALUES(10); + +ALTER TABLE t1 ADD COLUMN c6 INT, ADD CONSTRAINT CHECK( c6 != 10 ); +--error ER_CHECK_CONSTRAINT_VIOLATED +INSERT INTO t1(c6) VALUES(10); +INSERT INTO t1(c6) VALUES(20); + +ALTER TABLE t1 ADD COLUMN c7 INT, ADD CONSTRAINT CHECK( c7 <> 10 ); +--error ER_CHECK_CONSTRAINT_VIOLATED +INSERT INTO t1(c7) VALUES(10); +INSERT INTO t1(c7) VALUES(20); + +ALTER TABLE t1 ADD COLUMN c8 INT, ADD CONSTRAINT CHECK( c8 = GREATEST(1,2,3) ); +--error ER_CHECK_CONSTRAINT_VIOLATED +INSERT INTO t1(c8) VALUES(1); +INSERT INTO t1(c8) VALUES(3); + +ALTER TABLE t1 ADD COLUMN c9 INT, ADD CONSTRAINT CHECK( c9 = LEAST(1,2,3) ); +--error ER_CHECK_CONSTRAINT_VIOLATED +INSERT INTO t1(c9) VALUES(3); +INSERT INTO t1(c9) VALUES(1); + +ALTER TABLE t1 ADD COLUMN c10 INT, ADD CONSTRAINT CHECK( c10 NOT IN (1,2,3) ); +--error ER_CHECK_CONSTRAINT_VIOLATED +INSERT INTO t1(c10) VALUES(1); +--error ER_CHECK_CONSTRAINT_VIOLATED +INSERT INTO t1(c10) VALUES(3); +INSERT INTO t1(c10) VALUES(10); + +ALTER TABLE t1 ADD COLUMN c11 YEAR, ADD CONSTRAINT CHECK ( c11 > '2007-01-01' + INTERVAL +1 YEAR); +--error ER_CHECK_CONSTRAINT_VIOLATED +INSERT INTO t1(c11) VALUES(2007); +--error ER_CHECK_CONSTRAINT_VIOLATED +INSERT INTO t1(c11) VALUES(2008); +INSERT INTO t1(c11) VALUES(2009); + +ALTER TABLE t1 ADD COLUMN c12 INT, ADD CONSTRAINT CHECK ( c12 NOT BETWEEN 10 AND 20); +--error ER_CHECK_CONSTRAINT_VIOLATED +INSERT INTO t1(c12) VALUES(15); +INSERT INTO t1(c12) VALUES(25); + +ALTER TABLE t1 ADD COLUMN c13 INT, ADD CONSTRAINT CHECK ( c13 NOT IN (1, 2, 3)); +--error ER_CHECK_CONSTRAINT_VIOLATED +INSERT INTO t1(c13) VALUES(1); +INSERT INTO t1(c13) VALUES(15); + +ALTER TABLE t1 ADD COLUMN c14 CHAR(10), ADD CONSTRAINT CHECK ( c14 LIKE 'A%'); +--error ER_CHECK_CONSTRAINT_VIOLATED +INSERT INTO t1(c14) VALUES('Good'); +INSERT INTO t1(c14) VALUES('All'); + +ALTER TABLE t1 ADD COLUMN c15 INT, ADD CONSTRAINT CHECK ( c15 = STRCMP('A','A')); +--error ER_CHECK_CONSTRAINT_VIOLATED +INSERT INTO t1(c15) VALUES(1); +INSERT INTO t1(c15) VALUES(0); + +SHOW CREATE TABLE t1; +DROP TABLE t1; + + +--echo #----------------------------------------------------------------------- +--echo # Test case to verify check constraint with Logical Operators +--echo #----------------------------------------------------------------------- +CREATE TABLE t1(c1 INT, c2 INT); +ALTER TABLE t1 ADD CONSTRAINT CHECK( (c1 > 10) AND (c2 < 20) ); +--error ER_CHECK_CONSTRAINT_VIOLATED +INSERT INTO t1 VALUES(1,10); +ALTER TABLE t1 ADD CONSTRAINT CHECK( (c1 > 10) && (c2 < 20) ); +--error ER_CHECK_CONSTRAINT_VIOLATED +INSERT INTO t1 VALUES(15,25); +ALTER TABLE t1 DROP CHECK `t1_chk_1`; +ALTER TABLE t1 DROP CHECK `t1_chk_2`; + +ALTER TABLE t1 ADD CONSTRAINT CHECK( (c1 > 10) || (c2 < 20) ); +ALTER TABLE t1 ADD CONSTRAINT CHECK( (c1 > 10) OR (c2 < 20) ); +INSERT INTO t1 VALUES(15,25); +INSERT INTO t1 VALUES(5,10); +--error ER_CHECK_CONSTRAINT_VIOLATED +INSERT INTO t1 VALUES(5,25); +ALTER TABLE t1 DROP CHECK `t1_chk_1`; +ALTER TABLE t1 DROP CHECK `t1_chk_2`; +DELETE FROM t1; + +ALTER TABLE t1 ADD CONSTRAINT CHECK( (c1 > 10) XOR (c2 < 20) ); +--error ER_CHECK_CONSTRAINT_VIOLATED +INSERT INTO t1 VALUES(15,10); + +SHOW CREATE TABLE t1; +DROP TABLE t1; + + +--echo #----------------------------------------------------------------------- +--echo # Test case to verify check constraint behaviour with DEFAULT, NULL +--echo # and with LOGICAL operators. +--echo #----------------------------------------------------------------------- +CREATE TABLE t1(c1 INT DEFAULT 2 PRIMARY KEY CHECK(c1 > 1 OR c1 IS NOT NULL)); +SHOW CREATE TABLE t1; +--error ER_BAD_NULL_ERROR +INSERT INTO t1 VALUES(NULL); +INSERT INTO t1 VALUES(1); +SELECT * FROM t1; +DROP TABLE t1; +CREATE TABLE t1(c1 INT DEFAULT 2 PRIMARY KEY CHECK(c1 > 1 OR c1 > 2)); +--error ER_CHECK_CONSTRAINT_VIOLATED +INSERT INTO t1 VALUES(1); +INSERT INTO t1 VALUES(2); +SELECT * FROM t1; +DROP TABLE t1; +CREATE TABLE t1(c1 INT DEFAULT 2 PRIMARY KEY CHECK(c1 > 1 AND c1 IS NOT NULL)); +--error ER_CHECK_CONSTRAINT_VIOLATED +INSERT INTO t1 VALUES(1); +DROP TABLE t1; + + +--echo #----------------------------------------------------------------------- +--echo # Test case to verify check constraint when table is moved to another DB +--echo #----------------------------------------------------------------------- +CREATE DATABASE test1; +CREATE DATABASE test2; +USE test1; +CREATE TABLE t1(c1 INT, c2 INT CHECK (c2 < 10)); +INSERT INTO t1 VALUES(1,1); +SELECT * FROM INFORMATION_SCHEMA.CHECK_CONSTRAINTS; +SELECT * FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE TABLE_NAME='t1'; +ALTER TABLE test1.t1 rename test2.t1; +USE test2; +SELECT * FROM t1; +SELECT * FROM INFORMATION_SCHEMA.CHECK_CONSTRAINTS; +SELECT * FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE TABLE_NAME='t1'; +DROP DATABASE test2; +DROP DATABASE test1; + + +--echo #----------------------------------------------------------------------- +--echo # Test case to verify check constraint when table is moved to another DB +--echo # with different name. +--echo #----------------------------------------------------------------------- +CREATE DATABASE test1; +CREATE DATABASE test2; +USE test1; +CREATE TABLE t1(c1 INT, c2 INT CHECK (c2 < 10)); +INSERT INTO t1 VALUES(1,1); +SELECT * FROM INFORMATION_SCHEMA.CHECK_CONSTRAINTS; +SELECT * FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE TABLE_NAME='t1'; +ALTER TABLE test1.t1 rename test2.t2; +USE test2; +SELECT * FROM t2; +SELECT * FROM INFORMATION_SCHEMA.CHECK_CONSTRAINTS; +SELECT * FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE TABLE_NAME='t2'; +DROP DATABASE test2; +DROP DATABASE test1; +use test; + + +--echo #----------------------------------------------------------------------- +--echo # Test case to verify check constraints with foreign key constraint +--echo #----------------------------------------------------------------------- +CREATE TABLE parent(pid INT NOT NULL PRIMARY KEY CHECK(pid > 1)); +CREATE TABLE child(cid INT CHECK(cid > 1), + FOREIGN KEY fk(cid) REFERENCES parent(pid)); +SHOW CREATE TABLE parent; +SHOW CREATE TABLE child; +INSERT INTO parent VALUES(2); +--error ER_CHECK_CONSTRAINT_VIOLATED +INSERT INTO child VALUES(1); +--error ER_NO_REFERENCED_ROW_2 +INSERT INTO child VALUES(3); +INSERT INTO child VALUES(2); +SELECT * FROM parent; +SELECT * FROM child; +DROP TABLE child; +DROP TABLE parent; + + +--echo #----------------------------------------------------------------------- +--echo # Test case to verify check constraint with FK referential actions. +--echo #----------------------------------------------------------------------- +CREATE TABLE parent (a INT PRIMARY KEY); +# With ON DELETE SET NULL referential action. +--error ER_CHECK_CONSTRAINT_CLAUSE_USING_FK_REFER_ACTION_COLUMN +CREATE TABLE child ( + b INT, + c INT CHECK (c < 10), + INDEX(b), + FOREIGN KEY (b) REFERENCES parent(a) ON DELETE SET NULL, + CHECK (b IS NOT NULL) + ); +CREATE TABLE child ( + b INT, + c INT CHECK (c < 10), + INDEX(b), + FOREIGN KEY (b) REFERENCES parent(a) ON DELETE SET NULL + ); +--error ER_CHECK_CONSTRAINT_CLAUSE_USING_FK_REFER_ACTION_COLUMN +ALTER TABLE child ADD CONSTRAINT CHECK (b IS NOT NULL); +ALTER TABLE child DROP FOREIGN KEY child_ibfk_1; +--error ER_CHECK_CONSTRAINT_CLAUSE_USING_FK_REFER_ACTION_COLUMN +ALTER TABLE child ADD CONSTRAINT FOREIGN KEY (b) REFERENCES parent(a) ON DELETE SET NULL, + ADD CONSTRAINT CHECK (b IS NOT NULL); +DROP TABLE child; + +# With ON UPDATE SET NULL referential action. +--error ER_CHECK_CONSTRAINT_CLAUSE_USING_FK_REFER_ACTION_COLUMN +CREATE TABLE child ( + b INT, + c INT CHECK (c < 10), + INDEX(b), + FOREIGN KEY (b) REFERENCES parent(a) ON UPDATE SET NULL, + CHECK (b IS NOT NULL) + ); +CREATE TABLE child ( + b INT, + c INT CHECK (c < 10), + INDEX(b), + FOREIGN KEY (b) REFERENCES parent(a) ON UPDATE SET NULL + ); +--error ER_CHECK_CONSTRAINT_CLAUSE_USING_FK_REFER_ACTION_COLUMN +ALTER TABLE child ADD CONSTRAINT CHECK (b IS NOT NULL); +ALTER TABLE child DROP FOREIGN KEY child_ibfk_1; +--error ER_CHECK_CONSTRAINT_CLAUSE_USING_FK_REFER_ACTION_COLUMN +ALTER TABLE child ADD CONSTRAINT FOREIGN KEY (b) REFERENCES parent(a) ON UPDATE SET NULL, + ADD CONSTRAINT CHECK (b IS NOT NULL); +DROP TABLE child; + +# With ON UPDATE CASCADE referential action. +--error ER_CHECK_CONSTRAINT_CLAUSE_USING_FK_REFER_ACTION_COLUMN +CREATE TABLE child ( + b INT, + c INT CHECK (c < 10), + INDEX(b), + FOREIGN KEY (b) REFERENCES parent(a) ON UPDATE CASCADE, + CHECK (b IS NOT NULL) + ); +CREATE TABLE child ( + b INT, + c INT CHECK (c < 10), + INDEX(b), + FOREIGN KEY (b) REFERENCES parent(a) ON UPDATE CASCADE + ); +--error ER_CHECK_CONSTRAINT_CLAUSE_USING_FK_REFER_ACTION_COLUMN +ALTER TABLE child ADD CONSTRAINT CHECK (b IS NOT NULL); +ALTER TABLE child DROP FOREIGN KEY child_ibfk_1; +--error ER_CHECK_CONSTRAINT_CLAUSE_USING_FK_REFER_ACTION_COLUMN +ALTER TABLE child ADD CONSTRAINT FOREIGN KEY (b) REFERENCES parent(a) ON UPDATE CASCADE, + ADD CONSTRAINT CHECK (b IS NOT NULL); +DROP TABLE child; +DROP TABLE parent; + + +--echo #----------------------------------------------------------------------- +--echo # Test case to verify check constraint with triggers +--echo #----------------------------------------------------------------------- +CREATE TABLE t1(c1 INT, c2 INT CHECK (c2 < 10)); +CREATE TABLE t2(c1 INT, c2 INT); + +# before insert +DELIMITER //; +CREATE TRIGGER before_t2_insert + BEFORE INSERT ON t2 + FOR EACH ROW + BEGIN + INSERT INTO t1 VALUES(NEW.c1,NEW.c2); + END +// +DELIMITER ;// + +--error ER_CHECK_CONSTRAINT_VIOLATED +INSERT INTO t2 VALUES(1,20); +SELECT * FROM t1; +SELECT * FROM t2; +DROP TRIGGER before_t2_insert; + +# after insert +DELIMITER //; +CREATE TRIGGER after_t2_insert + AFTER INSERT ON t2 + FOR EACH ROW + BEGIN + INSERT INTO t1 VALUES(NEW.c1,NEW.c2); + END +// +DELIMITER ;// + +--error ER_CHECK_CONSTRAINT_VIOLATED +INSERT INTO t2 VALUES(1,30); +SELECT * FROM t1; +SELECT * FROM t2; +DROP TRIGGER after_t2_insert; + +# before update +INSERT INTO t2 VALUES(1,5); +INSERT INTO t1 VALUES(1,5); +DELIMITER //; +CREATE TRIGGER before_t2_update + BEFORE UPDATE ON t2 + FOR EACH ROW + BEGIN + UPDATE t1 SET c2=NEW.c2 WHERE c1=NEW.c1; + END +// +DELIMITER ;// + +--error ER_CHECK_CONSTRAINT_VIOLATED +UPDATE t2 SET c2=20 WHERE c1=1; +SELECT * FROM t1; +SELECT * FROM t2; +DROP TRIGGER before_t2_update; + +# after update +DELIMITER //; +CREATE TRIGGER after_t2_update + AFTER UPDATE ON t2 + FOR EACH ROW + BEGIN + UPDATE t1 SET c2=NEW.c2 WHERE c1=NEW.c1; + END +// +DELIMITER ;// + +--error ER_CHECK_CONSTRAINT_VIOLATED +UPDATE t2 SET c2=20 WHERE c1=1; +SELECT * FROM t1; +SELECT * FROM t2; +DROP TRIGGER after_t2_update; +DROP TABLE t1,t2; + + +--echo #----------------------------------------------------------------------- +--echo # Test case to verify check constraint with triggers old style. +--echo #----------------------------------------------------------------------- +CREATE TABLE t1(c1 int CONSTRAINT ck1 CHECK(c1 < 5)); + +DELIMITER //; +CREATE PROCEDURE proc1 (IN val1 INT) +BEGIN + IF val1 < 10 THEN + SIGNAL SQLSTATE '45000' + SET MESSAGE_TEXT = 'check constraint on c1 failed'; + END IF; +END +// + +CREATE TRIGGER before_t1_insert + BEFORE INSERT ON t1 + FOR EACH ROW + BEGIN + CALL proc1(new.c1); + END +// + +DELIMITER ;// + +--error ER_CHECK_CONSTRAINT_VIOLATED +INSERT INTO t1 VALUES(20); +--error ER_SIGNAL_EXCEPTION +INSERT INTO t1 VALUES(9); +--error ER_SIGNAL_EXCEPTION +INSERT INTO t1 VALUES(4); +DROP PROCEDURE proc1; +DROP TRIGGER before_t1_insert; +DROP TABLE t1; + + +--echo #----------------------------------------------------------------------- +--echo # Test case to verify check constraint with mysqldump +--echo #----------------------------------------------------------------------- +CREATE DATABASE test1; +USE test1; +CREATE TABLE t1 ( + c1 BIT(7) CHECK(c1 < B'1111100') NOT ENFORCED, + c2 BOOLEAN CHECK(c2 > 0) NOT ENFORCED, + c3 TINYINT CHECK(c3 > 10) NOT ENFORCED, + c4 SMALLINT CHECK(c4 > 10) NOT ENFORCED, + c5 MEDIUMINT CHECK(c5 > 10) NOT ENFORCED, + c6 INT CHECK(c6 > 10), + c7 BIGINT CHECK(c7 > 10), + c8 DECIMAL(6,2) CHECK(c8 > 10.1), + c9 FLOAT(6,2) CHECK(c9 > 10.1), + c10 DOUBLE(6,2) CHECK(c10 > 10.1), + c11 CHAR(6) CHECK (c11 IS NULL)); +SHOW CREATE TABLE t1; +--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +--exec $MYSQL_DUMP --databases test1 > $MYSQLTEST_VARDIR/tmp/test1_db.sql 2>&1 +DROP DATABASE test1; +--exec $MYSQL < $MYSQLTEST_VARDIR/tmp/test1_db.sql +USE test1; +SHOW CREATE TABLE t1; +--error ER_CHECK_CONSTRAINT_VIOLATED +INSERT INTO t1(c1,c2,c3,c4,c5,c6,c7,c8,c9,c10) + VALUES(B'1111111',0,5,5,5,1,1,1.2,1.2,1.2); +INSERT INTO t1(c1,c2,c3,c4,c5,c6,c7,c8,c9,c10) + VALUES(B'1111111',0,5,5,5,11,11,10.2,10.2,10.2); +SELECT * FROM t1; +DROP TABLE t1; +DROP DATABASE test1; +--remove_file $MYSQLTEST_VARDIR/tmp/test1_db.sql + + +--echo #----------------------------------------------------------------------- +--echo # Test case to verify check constraint with mysqlpump +--echo #----------------------------------------------------------------------- +CREATE DATABASE test2; +USE test2; +CREATE TABLE t2 ( + c1 BIT(7) CHECK(c1 < B'1111100'), + c2 BOOLEAN CHECK(c2 > 0), + c3 TINYINT CHECK(c3 > 10), + c4 SMALLINT CHECK(c4 > 10), + c5 MEDIUMINT CHECK(c5 > 10), + c6 INT CHECK(c6 > 10) NOT ENFORCED, + c7 BIGINT CHECK(c7 > 10) NOT ENFORCED, + c8 DECIMAL(6,2) CHECK(c8 > 10.1) NOT ENFORCED, + c9 FLOAT(6,2) CHECK(c9 > 10.1) NOT ENFORCED, + c10 DOUBLE(6,2) CHECK(c10 > 10.1) NOT ENFORCED); +SHOW CREATE TABLE t2; +--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +--exec $MYSQL_PUMP --databases test2 > $MYSQLTEST_VARDIR/tmp/test2_db.sql +DROP DATABASE test2; +--exec $MYSQL < $MYSQLTEST_VARDIR/tmp/test2_db.sql +USE test2; +SHOW CREATE TABLE t2; +--error ER_CHECK_CONSTRAINT_VIOLATED +INSERT INTO t2(c1,c2,c3,c4,c5,c6,c7,c8,c9,c10) + VALUES(B'1111000',0,10,10,10,5,5,9.1,9.1,9.1); +INSERT INTO t2(c1,c2,c3,c4,c5,c6,c7,c8,c9,c10) + VALUES(B'1111000',1,11,11,11,5,5,9.1,9.1,9.1); +SELECT * FROM t2; +DROP TABLE t2; +DROP DATABASE test2; +--remove_file $MYSQLTEST_VARDIR/tmp/test2_db.sql +USE test; + + +--echo #----------------------------------------------------------------------- +--echo # Test case to verify check constraint with PREPARE statement +--echo #----------------------------------------------------------------------- +CREATE TABLE t1(c1 INT CHECK(c1 > 10)); +PREPARE stmt1 FROM 'INSERT INTO t1 VALUES(1)'; +--error ER_CHECK_CONSTRAINT_VIOLATED +EXECUTE stmt1; +DEALLOCATE PREPARE stmt1; +PREPARE stmt2 FROM 'INSERT INTO t1 VALUES(20)'; +EXECUTE stmt2; +DEALLOCATE PREPARE stmt2; +SELECT * FROM t1; +DROP TABLE t1; + + +--echo #----------------------------------------------------------------------- +--echo # Test case to verify check constraint behaviour inside transaction +--echo #----------------------------------------------------------------------- +CREATE TABLE t1(c1 INT); +CREATE TABLE t2(c1 INT CHECK(c1 > 10)); +SET AUTOCOMMIT = OFF; +# Transaction 1 +START TRANSACTION; +INSERT INTO t1 VALUES(1); +--error ER_CHECK_CONSTRAINT_VIOLATED +INSERT INTO t2 VALUES(1); +ROLLBACK; +SELECT * FROM t1; +SELECT * FROM t2; + +# Transaction 2 +START TRANSACTION; +ALTER TABLE t1 ADD CONSTRAINT CHECK (C1 > 10); +COMMIT; +SHOW CREATE TABLE t1; +SET AUTOCOMMIT = ON; +DROP TABLE t1,t2; + + +--echo #------------------------------------------------------------------------ +--echo # Test case to verify check constraints with Partition table. +--echo #------------------------------------------------------------------------ +--echo # check constraint with range partition +CREATE TABLE t1( + d DATE NOT NULL CHECK(YEAR(d) > '1950') +) +PARTITION BY RANGE( YEAR(d) ) ( +PARTITION p0 VALUES LESS THAN (1960), +PARTITION p1 VALUES LESS THAN (1970), +PARTITION p2 VALUES LESS THAN (1980), +PARTITION p3 VALUES LESS THAN (1990) +); +SHOW CREATE TABLE t1; + +--error ER_CHECK_CONSTRAINT_VIOLATED +INSERT INTO t1 VALUES('1940-01-01'); + +INSERT INTO t1 VALUES('1960-01-01'); +SELECT * FROM t1; +DROP TABLE t1; + +--echo # check constraint with list partition +CREATE TABLE t1( + id INT NOT NULL CHECK(id BETWEEN 10 AND 50), + name VARCHAR(10) +) +PARTITION BY LIST(id) ( +PARTITION p0 VALUES IN (10,19), +PARTITION p1 VALUES IN (20,29), +PARTITION p2 VALUES IN (30,39), +PARTITION p3 VALUES IN (40,49) +); +SHOW CREATE TABLE t1; + +--error ER_CHECK_CONSTRAINT_VIOLATED +INSERT INTO t1 VALUES(60,'aaa'); +INSERT INTO t1 VALUES(30,'aaa'); +SELECT * FROM t1; +DROP TABLE t1; + +--echo # check constraint with hash partition +CREATE TABLE t1(id INT NOT NULL CHECK(id > 10), + name VARCHAR(40) +) +PARTITION BY HASH(id) +PARTITIONS 4; +SHOW CREATE TABLE t1; + +--error ER_CHECK_CONSTRAINT_VIOLATED +INSERT INTO t1 VALUES(1,'aaa'); +INSERT INTO t1 VALUES(60,'aaa'); +SELECT * FROM t1; + +DROP TABLE t1; + +--echo # check constraint with key partition +CREATE TABLE t1(id INT PRIMARY KEY NOT NULL CHECK(id > 10), + name VARCHAR(40) +) +PARTITION BY KEY() +PARTITIONS 4; +SHOW CREATE TABLE t1; + +--error ER_CHECK_CONSTRAINT_VIOLATED +INSERT INTO t1 VALUES(1,'aaa'); +INSERT INTO t1 VALUES(60,'aaa'); +SELECT * FROM t1; +DROP TABLE t1; + + +--echo #----------------------------------------------------------------------- +--echo # Test case to verify alter operations on non-transactional SE table +--echo # with check constraints. +--echo #----------------------------------------------------------------------- +CREATE TABLE t1(f1 INT CHECK (f1 < 10)) ENGINE = myisam; +SHOW CREATE TABLE t1; +ALTER TABLE t1 ADD f2 INT, ALGORITHM=copy; +SHOW CREATE TABLE t1; +ALTER TABLE t1 ALTER f1 SET DEFAULT 10, ALGORITHM=INPLACE; +SHOW CREATE TABLE t1; +DROP TABLE t1; + + +--echo #----------------------------------------------------------------------- +--echo # Test case to verify check constraint with Updatable view +--echo #----------------------------------------------------------------------- +CREATE TABLE t1(c1 INT, c2 INT CHECK (c2 < 10)); +CREATE VIEW v1 AS SELECT * FROM t1; +--error ER_CHECK_CONSTRAINT_VIOLATED +INSERT INTO v1 VALUES(1,20); +INSERT INTO v1 VALUES(1,5); +SELECT * FROM t1; +SELECT * FROM v1; +DROP VIEW v1; +DROP TABLE t1; diff --git a/mysql-test/t/check_constraints_debug.test b/mysql-test/t/check_constraints_debug.test new file mode 100644 index 000000000000..29b69791face --- /dev/null +++ b/mysql-test/t/check_constraints_debug.test @@ -0,0 +1,172 @@ +--source include/have_debug.inc + +################################################################################ +# WL929 - CHECK CONSTRAINTS. # +# Test cases to verify MDL on check constraints. # +################################################################################ + +--enable_connect_log + +--echo #------------------------------------------------------------------------ +--echo # Test case to verify MDL locking on check constraints with same names +--echo # in the concurrent CREATE TABLE statements. +--echo #------------------------------------------------------------------------ +SET DEBUG_SYNC="after_acquiring_lock_on_check_constraints SIGNAL cc_locked WAIT_FOR continue"; +--SEND CREATE TABLE t1 (f1 INT CHECK (f1 < 10), f2 INT, CONSTRAINT t1_ck CHECK(f2 < 10)); + +CONNECT (con1, localhost, root); +SET DEBUG_SYNC="now WAIT_FOR cc_locked"; +--send CREATE TABLE t2 (f1 INT, f2 INT, CONSTRAINT t1_ck CHECK(f2 < 10)); + +CONNECT (con2, localhost, root); +--echo # default connection acquires MDL lock on the check constraint name 'test.t1_ck'. +--echo # con1 waits for the MDL lock on 'test.t1_ck' at this point. +let $wait_condition= + SELECT count(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST + WHERE state = "Waiting for check constraint metadata lock" AND + info = "CREATE TABLE t2 (f1 INT, f2 INT, CONSTRAINT t1_ck CHECK(f2 < 10))"; +--source include/wait_condition.inc +SET DEBUG_SYNC="now SIGNAL continue"; + +CONNECTION con1; +--error ER_CHECK_CONSTRAINT_DUP_NAME +--reap + +CONNECTION default; +--reap + + +--echo #------------------------------------------------------------------------ +--echo # Test case to verify MDL locking on check constraints names in the +--echo # RENAME TABLE and CREATE TABLE statements. +--echo #------------------------------------------------------------------------ +SET DEBUG_SYNC="after_acquiring_lock_on_check_constraints_for_rename SIGNAL cc_locked WAIT_FOR continue"; +--SEND RENAME TABLE t1 to t2; + +CONNECTION con1; +SET DEBUG_SYNC="now WAIT_FOR cc_locked"; +--send CREATE TABLE t3 (f1 INT, CONSTRAINT t1_chk_1 CHECK (f1 < 10)); + +CONNECTION con2; +--echo # default connection acquires lock on check constraint 'test.t1_chk_1'. +--echo # Concurrent create operation with same name for check constraint in con1 +--echo # waits for the lock. +let $wait_condition= + SELECT count(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST + WHERE state = "Waiting for check constraint metadata lock" AND + info = "CREATE TABLE t3 (f1 INT, CONSTRAINT t1_chk_1 CHECK (f1 < 10))"; +--source include/wait_condition.inc +SET DEBUG_SYNC="now SIGNAL continue"; + +CONNECTION con1; +--reap + +CONNECTION default; +--reap +SHOW CREATE TABLE t2; +SHOW CREATE TABLE t3; +DROP TABLE t3; + + +--echo #------------------------------------------------------------------------ +--echo # Test case to verify MDL locking on generated check constraints names +--echo # in the RENAME TABLE using the target table name and CREATE TABLE +--echo # statements. +--echo #------------------------------------------------------------------------ +SET DEBUG_SYNC="after_acquiring_lock_on_check_constraints_for_rename SIGNAL cc_locked WAIT_FOR continue"; +--SEND RENAME TABLE t2 to t1; + +CONNECTION con1; +SET DEBUG_SYNC="now WAIT_FOR cc_locked"; +--send CREATE TABLE t3 (f1 INT, CONSTRAINT t1_chk_1 CHECK (f1 < 10)); + +CONNECTION con2; +--echo # default connection acquires lock on check constraint name('test.t1_chk_1') +--echo # generated using target table t1. +--echo # concurrent con1 waits for the MDL on test.t1_chk_1 in CREATE TABLE +--echo # statement. +let $wait_condition= + SELECT count(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST + WHERE state = "Waiting for check constraint metadata lock" AND + info = "CREATE TABLE t3 (f1 INT, CONSTRAINT t1_chk_1 CHECK (f1 < 10))"; +--source include/wait_condition.inc +SET DEBUG_SYNC="now SIGNAL continue"; + +CONNECTION con1; +--error ER_CHECK_CONSTRAINT_DUP_NAME +--reap +SHOW CREATE TABLE t1; + +CONNECTION default; +--reap + + +--echo #------------------------------------------------------------------------ +--echo # Test case to verify MDL locking on check constraint name in ALTER +--echo # TABLE statement to RENAME table and CREATE TABLE statements. +--echo #------------------------------------------------------------------------ +SET DEBUG_SYNC="after_acquiring_lock_on_check_constraints_for_rename SIGNAL cc_locked WAIT_FOR continue"; +--SEND ALTER TABLE t1 RENAME TO t3; + +CONNECTION con1; +SET DEBUG_SYNC="now WAIT_FOR cc_locked"; +--send CREATE TABLE t2 (f1 INT, CONSTRAINT t1_chk_1 CHECK (f1 < 10)); + +CONNECTION con2; +--echo # default connection acquires lock on check constraint 'test.t1_chk_1'. +--echo # Concurrent con1 waits for lock on test.t1_chk_1. +let $wait_condition= + SELECT count(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST + WHERE state = "Waiting for check constraint metadata lock" AND + info = "CREATE TABLE t2 (f1 INT, CONSTRAINT t1_chk_1 CHECK (f1 < 10))"; +--source include/wait_condition.inc +SET DEBUG_SYNC="now SIGNAL continue"; + +CONNECTION con1; +--reap + +CONNECTION default; +--reap +SHOW CREATE TABLE t2; +SHOW CREATE TABLE t3; +DROP TABLE t2; + + +--echo #------------------------------------------------------------------------ +--echo # Test case to verify MDL locking on generated check constraint name +--echo # using target table name in ALTER TABLE statement to RENAME table and +--echo # CREATE TABLE statements. +--echo #------------------------------------------------------------------------ +SET DEBUG_SYNC="after_acquiring_lock_on_check_constraints_for_rename SIGNAL cc_locked WAIT_FOR continue"; +--SEND ALTER TABLE t3 RENAME TO t1; + +CONNECTION con1; +SET DEBUG_SYNC="now WAIT_FOR cc_locked"; +--send CREATE TABLE t2 (f1 INT, CONSTRAINT t1_chk_1 CHECK (f1 < 10)); + +CONNECTION con2; +--echo # default connection acquires lock on the generated check constraint +--echo # name('test.t1_chk_1') using target table name t1. con1 waits for +--echo # the lock on same name for check constraint. +let $wait_condition= + SELECT count(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST + WHERE state = "Waiting for check constraint metadata lock" AND + info = "CREATE TABLE t2 (f1 INT, CONSTRAINT t1_chk_1 CHECK (f1 < 10))"; +--source include/wait_condition.inc +SET DEBUG_SYNC="now SIGNAL continue"; + +CONNECTION con1; +--error ER_CHECK_CONSTRAINT_DUP_NAME +--reap + +CONNECTION default; +--reap +SHOW CREATE TABLE t1; + +#Cleanup +CONNECTION default; +DISCONNECT con1; +DISCONNECT con2; +DROP TABLE t1; +SET DEBUG_SYNC='RESET'; +--disable_connect_log diff --git a/mysql-test/t/constraints.test b/mysql-test/t/constraints.test index 731e2f3a9bc0..45bcafa80c3e 100644 --- a/mysql-test/t/constraints.test +++ b/mysql-test/t/constraints.test @@ -11,14 +11,17 @@ drop table if exists t1; create table t1 (a int check (a>0)); insert into t1 values (1); +--error ER_CHECK_CONSTRAINT_VIOLATED insert into t1 values (0); drop table t1; create table t1 (a int, b int, check (a>b)); insert into t1 values (1,0); +--error ER_CHECK_CONSTRAINT_VIOLATED insert into t1 values (0,1); drop table t1; create table t1 (a int ,b int, constraint abc check (a>b)); insert into t1 values (1,0); +--error ER_CHECK_CONSTRAINT_VIOLATED insert into t1 values (0,1); drop table t1; create table t1 (a int null); diff --git a/mysql-test/t/dd_schema_definition_debug.test b/mysql-test/t/dd_schema_definition_debug.test index ac915d0a8f2f..ddc8ee914028 100644 --- a/mysql-test/t/dd_schema_definition_debug.test +++ b/mysql-test/t/dd_schema_definition_debug.test @@ -330,6 +330,12 @@ INSERT INTO dd_published_schema INSERT INTO dd_published_schema VALUES ('80014', 1, 'cc5651651505fe0a4ebccb74d82e6fcd9555a4bd29478e21637c95da98f4537c'); +INSERT INTO dd_published_schema + VALUES('80015', 0, + 'd744ea5852332319804c577901ca4fb0c0b823cc4d583bab9630659cbb11951e'); +INSERT INTO dd_published_schema + VALUES('80015', 1, + '403cb6e600b964c120e0a7eb92fefa15bd02f4cee745182191275df2c1cb30d7'); SELECT IFNULL(CONCAT('The schema checksum corresponds to DD version ', version, '.'), diff --git a/mysql-test/t/dd_upgrade_test.test b/mysql-test/t/dd_upgrade_test.test index 51998a73b33e..ec9e7da9f83b 100644 --- a/mysql-test/t/dd_upgrade_test.test +++ b/mysql-test/t/dd_upgrade_test.test @@ -767,4 +767,56 @@ call mtr.add_suppression("You need to use --log-bin to make --binlog-format work --echo # Restart the server with default options. --source include/start_mysqld.inc +--echo #----------------------------------------------------------------------- +--echo # WL#929: CHECK Constraint +--echo # Test case to verify upgrade from version before check +--echo # constraint suppport. +--echo #----------------------------------------------------------------------- + +let $MYSQLD_LOG= $MYSQLTEST_VARDIR/log/save_dd_upgrade_4.log; + +--echo # Copy the remote tablespace & DB zip files from suite location to working location. +--copy_file $MYSQLTEST_VARDIR/std_data/upgrade/data_80014.zip $MYSQL_TMP_DIR/data_80014.zip + +--echo # Check that the file exists in the working folder. +--file_exists $MYSQL_TMP_DIR/data_80014.zip +--exec unzip -qo $MYSQL_TMP_DIR/data_80014.zip -d $MYSQL_TMP_DIR/data_80014 + +--echo # Set different paths for --datadir +let $MYSQLD_DATADIR3 = $MYSQL_TMP_DIR/data_80014/ + +--echo # Check that the file exits after unzip +--file_exists $MYSQL_TMP_DIR/data_80014 + +--echo # Stop DB server which was created by MTR default +--exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +--shutdown_server +--source include/wait_until_disconnected.inc + +--echo # Start the DB server +--exec echo "restart: --datadir=$MYSQLD_DATADIR3 --log-error=$MYSQLD_LOG" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +--enable_reconnect +--let $wait_counter= 3000 +--source include/wait_until_connected_again.inc + +USE test; +CREATE TABLE t1 (f1 INT CHECK (f1 < 10)); +--echo # After upgrade CHECK_CONSTRAINTS table should be present and should list +--echo # check constraints. +SELECT * FROM INFORMATION_SCHEMA.CHECK_CONSTRAINTS; +--echo # After upgrade TABLE_CONSTRAINTS should list check constraints. +SELECT * FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE TABLE_NAME='t1'; +SHOW CREATE TABLE t1; +--error ER_CHECK_CONSTRAINT_VIOLATED +INSERT INTO t1 VALUES (100); +DROP TABLE t1; + +--echo # Stop the server +--source include/shutdown_mysqld.inc +--echo # Remove copied files +--remove_file $MYSQL_TMP_DIR/data_80014.zip +--force-rmdir $MYSQL_TMP_DIR/data_80014 +--echo # Restart the server with default options. +--source include/start_mysqld.inc + --echo # end of test diff --git a/mysql-test/t/import.test b/mysql-test/t/import.test index 6a73da0e62c6..e86a24926204 100644 --- a/mysql-test/t/import.test +++ b/mysql-test/t/import.test @@ -647,6 +647,20 @@ SET SESSION sql_require_primary_key= OFF; --echo # Clean SDI files in \$EXPORT_DIR --remove_files_wildcard $EXPORT_DIR t* +--echo #----------------------------------------------------------------------- +--echo # WL#929 - Check constraint. +--echo # Test case to verify check constraint import from SDI. +--echo #----------------------------------------------------------------------- +CREATE TABLE t1 (f1 INT CHECK (f1 < 10)) ENGINE=MyISAM; +let $MYSQLD_DATADIR=`SELECT @@datadir`; +--copy_files_wildcard $MYSQLD_DATADIR/test/ $MYSQL_TMP_DIR/ t* +DROP TABLE t1; +--copy_files_wildcard $MYSQL_TMP_DIR/ $MYSQLD_DATADIR/test/ t* +IMPORT TABLE FROM 'test/t1*.sdi'; +SHOW CREATE TABLE t1; +DROP TABLE t1; +--remove_files_wildcard $MYSQL_TMP_DIR/ t* + --echo # Remove 'export' folder created at the beginning of test file. --force-rmdir $EXPORT_DIR diff --git a/scripts/fill_help_tables.sql b/scripts/fill_help_tables.sql index 36ae2f935070..76707135d4d4 100644 --- a/scripts/fill_help_tables.sql +++ b/scripts/fill_help_tables.sql @@ -1,4 +1,4 @@ --- Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved. +-- Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved. -- -- This program is free software; you can redistribute it and/or modify -- it under the terms of the GNU General Public License, version 2.0, @@ -118,7 +118,7 @@ INSERT INTO help_topic (help_topic_id,help_category_id,name,description,example, INSERT INTO help_topic (help_topic_id,help_category_id,name,description,example,url) VALUES (29,9,'ALTER PROCEDURE','Syntax:\nALTER PROCEDURE proc_name [characteristic ...]\n\ncharacteristic:\n COMMENT \'string\'\n | LANGUAGE SQL\n | { CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA }\n | SQL SECURITY { DEFINER | INVOKER }\n\nThis statement can be used to change the characteristics of a stored\nprocedure. More than one change may be specified in an ALTER PROCEDURE\nstatement. However, you cannot change the parameters or body of a\nstored procedure using this statement; to make such changes, you must\ndrop and re-create the procedure using DROP PROCEDURE and CREATE\nPROCEDURE.\n\nYou must have the ALTER ROUTINE privilege for the procedure. By\ndefault, that privilege is granted automatically to the procedure\ncreator. This behavior can be changed by disabling the\nautomatic_sp_privileges system variable. See\nhttp://dev.mysql.com/doc/refman/8.0/en/stored-routines-privileges.html.\n\nURL: http://dev.mysql.com/doc/refman/8.0/en/alter-procedure.html\n\n','','http://dev.mysql.com/doc/refman/8.0/en/alter-procedure.html'); INSERT INTO help_topic (help_topic_id,help_category_id,name,description,example,url) VALUES (30,1,'ALTER RESOURCE GROUP','Syntax:\nALTER RESOURCE GROUP group_name\n [VCPU [=] vcpu_spec [, vcpu_spec] ...]\n [THREAD_PRIORITY [=] N]\n [ENABLE|DISABLE [FORCE]]\n\nvcpu_spec: {N | M - N}\n\nALTER RESOURCE GROUP is used for resource group management (see\nhttp://dev.mysql.com/doc/refman/8.0/en/resource-groups.html). This\nstatement alters modifiable attributes of an existing resource group.\nIt requires the RESOURCE_GROUP_ADMIN privilege.\n\ngroup_name identifies which resource group to alter. If the group does\nnot exist, an error occurs.\n\nThe attributes for CPU affinity, priority, and whether the group is\nenabled can be modified with ALTER RESOURCE GROUP. These attributes are\nspecified the same way as described for CREATE RESOURCE GROUP (see\n[HELP CREATE RESOURCE GROUP]). Only the attributes specified are\naltered. Unspecified attributes retain their current values.\n\nThe FORCE modifier is used with DISABLE. It determines statement\nbehavior if the resource group has any threads assigned to it:\n\no If FORCE is not given, existing threads in the group continue to run\n until they terminate, but new threads cannot be assigned to the\n group.\n\no If FORCE is given, existing threads in the group are moved to their\n respective default group (system threads to SYS_default, user threads\n to USR_default).\n\nThe name and type attributes are set at group creation time and cannot\nbe modified thereafter with ALTER RESOURCE GROUP.\n\nURL: http://dev.mysql.com/doc/refman/8.0/en/alter-resource-group.html\n\n','','http://dev.mysql.com/doc/refman/8.0/en/alter-resource-group.html'); INSERT INTO help_topic (help_topic_id,help_category_id,name,description,example,url) VALUES (31,9,'ALTER SERVER','Syntax:\nALTER SERVER server_name\n OPTIONS (option [, option] ...)\n\nAlters the server information for server_name, adjusting any of the\noptions permitted in the CREATE SERVER statement. The corresponding\nfields in the mysql.servers table are updated accordingly. This\nstatement requires the SUPER privilege.\n\nURL: http://dev.mysql.com/doc/refman/8.0/en/alter-server.html\n\n','ALTER SERVER s OPTIONS (USER \'sally\');\n','http://dev.mysql.com/doc/refman/8.0/en/alter-server.html'); -INSERT INTO help_topic (help_topic_id,help_category_id,name,description,example,url) VALUES (32,9,'ALTER TABLE','Syntax:\nALTER TABLE tbl_name\n [alter_specification [, alter_specification] ...]\n [partition_options]\n\nalter_specification:\n table_options\n | ADD [COLUMN] col_name column_definition\n [FIRST | AFTER col_name]\n | ADD [COLUMN] (col_name column_definition,...)\n | ADD {INDEX|KEY} [index_name]\n [index_type] (key_part,...) [index_option] ...\n | ADD [CONSTRAINT [symbol]] PRIMARY KEY\n [index_type] (key_part,...) [index_option] ...\n | ADD [CONSTRAINT [symbol]]\n UNIQUE [INDEX|KEY] [index_name]\n [index_type] (key_part,...) [index_option] ...\n | ADD FULLTEXT [INDEX|KEY] [index_name]\n (key_part,...) [index_option] ...\n | ADD SPATIAL [INDEX|KEY] [index_name]\n (key_part,...) [index_option] ...\n | ADD [CONSTRAINT [symbol]]\n FOREIGN KEY [index_name] (col_name,...)\n reference_definition\n | ALGORITHM [=] {DEFAULT|INSTANT|INPLACE|COPY}\n | ALTER [COLUMN] col_name {SET DEFAULT literal | DROP DEFAULT}\n | ALTER INDEX index_name {VISIBLE | INVISIBLE}\n | CHANGE [COLUMN] old_col_name new_col_name column_definition\n [FIRST|AFTER col_name]\n | [DEFAULT] CHARACTER SET [=] charset_name [COLLATE [=] collation_name]\n | CONVERT TO CHARACTER SET charset_name [COLLATE collation_name]\n | {DISABLE|ENABLE} KEYS\n | {DISCARD|IMPORT} TABLESPACE\n | DROP [COLUMN] col_name\n | DROP {INDEX|KEY} index_name\n | DROP PRIMARY KEY\n | DROP FOREIGN KEY fk_symbol\n | FORCE\n | LOCK [=] {DEFAULT|NONE|SHARED|EXCLUSIVE}\n | MODIFY [COLUMN] col_name column_definition\n [FIRST | AFTER col_name]\n | ORDER BY col_name [, col_name] ...\n | RENAME COLUMN old_col_name TO new_col_name\n | RENAME {INDEX|KEY} old_index_name TO new_index_name\n | RENAME [TO|AS] new_tbl_name\n | {WITHOUT|WITH} VALIDATION\n | ADD PARTITION (partition_definition)\n | DROP PARTITION partition_names\n | DISCARD PARTITION {partition_names | ALL} TABLESPACE\n | IMPORT PARTITION {partition_names | ALL} TABLESPACE\n | TRUNCATE PARTITION {partition_names | ALL}\n | COALESCE PARTITION number\n | REORGANIZE PARTITION partition_names INTO (partition_definitions)\n | EXCHANGE PARTITION partition_name WITH TABLE tbl_name [{WITH|WITHOUT} VALIDATION]\n | ANALYZE PARTITION {partition_names | ALL}\n | CHECK PARTITION {partition_names | ALL}\n | OPTIMIZE PARTITION {partition_names | ALL}\n | REBUILD PARTITION {partition_names | ALL}\n | REPAIR PARTITION {partition_names | ALL}\n | REMOVE PARTITIONING\n | UPGRADE PARTITIONING\n\nkey_part: {col_name [(length)] | (expr)} [ASC | DESC]\n\nindex_type:\n USING {BTREE | HASH}\n\nindex_option:\n KEY_BLOCK_SIZE [=] value\n | index_type\n | WITH PARSER parser_name\n | COMMENT \'string\'\n | {VISIBLE | INVISIBLE}\n\ntable_options:\n table_option [[,] table_option] ...\n\ntable_option:\n AUTO_INCREMENT [=] value\n | AVG_ROW_LENGTH [=] value\n | [DEFAULT] CHARACTER SET [=] charset_name\n | CHECKSUM [=] {0 | 1}\n | [DEFAULT] COLLATE [=] collation_name\n | COMMENT [=] \'string\'\n | COMPRESSION [=] {\'ZLIB\'|\'LZ4\'|\'NONE\'}\n | CONNECTION [=] \'connect_string\'\n | {DATA|INDEX} DIRECTORY [=] \'absolute path to directory\'\n | DELAY_KEY_WRITE [=] {0 | 1}\n | ENCRYPTION [=] {\'Y\' | \'N\'}\n | ENGINE [=] engine_name\n | INSERT_METHOD [=] { NO | FIRST | LAST }\n | KEY_BLOCK_SIZE [=] value\n | MAX_ROWS [=] value\n | MIN_ROWS [=] value\n | PACK_KEYS [=] {0 | 1 | DEFAULT}\n | PASSWORD [=] \'string\'\n | ROW_FORMAT [=] {DEFAULT|DYNAMIC|FIXED|COMPRESSED|REDUNDANT|COMPACT}\n | STATS_AUTO_RECALC [=] {DEFAULT|0|1}\n | STATS_PERSISTENT [=] {DEFAULT|0|1}\n | STATS_SAMPLE_PAGES [=] value\n | TABLESPACE tablespace_name\n | UNION [=] (tbl_name[,tbl_name]...)\n\npartition_options:\n (see CREATE TABLE options)\n\nALTER TABLE changes the structure of a table. For example, you can add\nor delete columns, create or destroy indexes, change the type of\nexisting columns, or rename columns or the table itself. You can also\nchange characteristics such as the storage engine used for the table or\nthe table comment.\n\no To use ALTER TABLE, you need ALTER, CREATE, and INSERT privileges for\n the table. Renaming a table requires ALTER and DROP on the old table,\n ALTER, CREATE, and INSERT on the new table.\n\no Following the table name, specify the alterations to be made. If none\n are given, ALTER TABLE does nothing.\n\no The syntax for many of the permissible alterations is similar to\n clauses of the CREATE TABLE statement. column_definition clauses use\n the same syntax for ADD and CHANGE as for CREATE TABLE. For more\n information, see [HELP CREATE TABLE].\n\no The word COLUMN is optional and can be omitted, except for RENAME\n COLUMN (to distinguish a column-renaming operation from the RENAME\n table-renaming operation).\n\no Multiple ADD, ALTER, DROP, and CHANGE clauses are permitted in a\n single ALTER TABLE statement, separated by commas. This is a MySQL\n extension to standard SQL, which permits only one of each clause per\n ALTER TABLE statement. For example, to drop multiple columns in a\n single statement, do this:\n\nALTER TABLE t2 DROP COLUMN c, DROP COLUMN d;\n\no If a storage engine does not support an attempted ALTER TABLE\n operation, a warning may result. Such warnings can be displayed with\n SHOW WARNINGS. See [HELP SHOW WARNINGS]. For information on\n troubleshooting ALTER TABLE, see\n http://dev.mysql.com/doc/refman/8.0/en/alter-table-problems.html.\n\no For information about generated columns, see\n http://dev.mysql.com/doc/refman/8.0/en/alter-table-generated-columns.\n html.\n\no For usage examples, see\n http://dev.mysql.com/doc/refman/8.0/en/alter-table-examples.html.\n\no With the mysql_info() C API function, you can find out how many rows\n were copied by ALTER TABLE. See\n http://dev.mysql.com/doc/refman/8.0/en/mysql-info.html.\n\nURL: http://dev.mysql.com/doc/refman/8.0/en/alter-table.html\n\n','','http://dev.mysql.com/doc/refman/8.0/en/alter-table.html'); +INSERT INTO help_topic (help_topic_id,help_category_id,name,description,example,url) VALUES (32,9,'ALTER TABLE','Syntax:\nALTER TABLE tbl_name\n [alter_specification [, alter_specification] ...]\n [partition_options]\n\nalter_specification:\n table_options\n | ADD [COLUMN] col_name column_definition\n [FIRST | AFTER col_name]\n | ADD [COLUMN] (col_name column_definition,...)\n | ADD {INDEX|KEY} [index_name]\n [index_type] (key_part,...) [index_option] ...\n | ADD [CONSTRAINT [symbol]] PRIMARY KEY\n [index_type] (key_part,...) [index_option] ...\n | ADD [CONSTRAINT [symbol]]\n UNIQUE [INDEX|KEY] [index_name]\n [index_type] (key_part,...) [index_option] ...\n | ADD FULLTEXT [INDEX|KEY] [index_name]\n (key_part,...) [index_option] ...\n | ADD SPATIAL [INDEX|KEY] [index_name]\n (key_part,...) [index_option] ...\n | ADD [CONSTRAINT [symbol]]\n FOREIGN KEY [index_name] (col_name,...)\n reference_definition\n | ALGORITHM [=] {DEFAULT|INSTANT|INPLACE|COPY}\n | ALTER [COLUMN] col_name {SET DEFAULT literal | DROP DEFAULT}\n | ALTER INDEX index_name {VISIBLE | INVISIBLE}\n | ALTER CHECK symbol [NOT] ENFORCED\n | CHANGE [COLUMN] old_col_name new_col_name column_definition\n [FIRST|AFTER col_name]\n | [DEFAULT] CHARACTER SET [=] charset_name [COLLATE [=] collation_name]\n | CONVERT TO CHARACTER SET charset_name [COLLATE collation_name]\n | {DISABLE|ENABLE} KEYS\n | {DISCARD|IMPORT} TABLESPACE\n | DROP [COLUMN] col_name\n | DROP {INDEX|KEY} index_name\n | DROP PRIMARY KEY\n | DROP FOREIGN KEY fk_symbol\n | DROP CHECK symbol\n | FORCE\n | LOCK [=] {DEFAULT|NONE|SHARED|EXCLUSIVE}\n | MODIFY [COLUMN] col_name column_definition\n [FIRST | AFTER col_name]\n | ORDER BY col_name [, col_name] ...\n | RENAME COLUMN old_col_name TO new_col_name\n | RENAME {INDEX|KEY} old_index_name TO new_index_name\n | RENAME [TO|AS] new_tbl_name\n | {WITHOUT|WITH} VALIDATION\n | ADD PARTITION (partition_definition)\n | DROP PARTITION partition_names\n | DISCARD PARTITION {partition_names | ALL} TABLESPACE\n | IMPORT PARTITION {partition_names | ALL} TABLESPACE\n | TRUNCATE PARTITION {partition_names | ALL}\n | COALESCE PARTITION number\n | REORGANIZE PARTITION partition_names INTO (partition_definitions)\n | EXCHANGE PARTITION partition_name WITH TABLE tbl_name [{WITH|WITHOUT} VALIDATION]\n | ANALYZE PARTITION {partition_names | ALL}\n | CHECK PARTITION {partition_names | ALL}\n | OPTIMIZE PARTITION {partition_names | ALL}\n | REBUILD PARTITION {partition_names | ALL}\n | REPAIR PARTITION {partition_names | ALL}\n | REMOVE PARTITIONING\n | UPGRADE PARTITIONING\n\nkey_part: {col_name [(length)] | (expr)} [ASC | DESC]\n\nindex_type:\n USING {BTREE | HASH}\n\nindex_option:\n KEY_BLOCK_SIZE [=] value\n | index_type\n | WITH PARSER parser_name\n | COMMENT \'string\'\n | {VISIBLE | INVISIBLE}\n\ntable_options:\n table_option [[,] table_option] ...\n\ntable_option:\n AUTO_INCREMENT [=] value\n | AVG_ROW_LENGTH [=] value\n | [DEFAULT] CHARACTER SET [=] charset_name\n | CHECKSUM [=] {0 | 1}\n | [DEFAULT] COLLATE [=] collation_name\n | COMMENT [=] \'string\'\n | COMPRESSION [=] {\'ZLIB\'|\'LZ4\'|\'NONE\'}\n | CONNECTION [=] \'connect_string\'\n | {DATA|INDEX} DIRECTORY [=] \'absolute path to directory\'\n | DELAY_KEY_WRITE [=] {0 | 1}\n | ENCRYPTION [=] {\'Y\' | \'N\'}\n | ENGINE [=] engine_name\n | INSERT_METHOD [=] { NO | FIRST | LAST }\n | KEY_BLOCK_SIZE [=] value\n | MAX_ROWS [=] value\n | MIN_ROWS [=] value\n | PACK_KEYS [=] {0 | 1 | DEFAULT}\n | PASSWORD [=] \'string\'\n | ROW_FORMAT [=] {DEFAULT|DYNAMIC|FIXED|COMPRESSED|REDUNDANT|COMPACT}\n | STATS_AUTO_RECALC [=] {DEFAULT|0|1}\n | STATS_PERSISTENT [=] {DEFAULT|0|1}\n | STATS_SAMPLE_PAGES [=] value\n | TABLESPACE tablespace_name\n | UNION [=] (tbl_name[,tbl_name]...)\n\npartition_options:\n (see CREATE TABLE options)\n\nALTER TABLE changes the structure of a table. For example, you can add\nor delete columns, create or destroy indexes, change the type of\nexisting columns, or rename columns or the table itself. You can also\nchange characteristics such as the storage engine used for the table or\nthe table comment.\n\no To use ALTER TABLE, you need ALTER, CREATE, and INSERT privileges for\n the table. Renaming a table requires ALTER and DROP on the old table,\n ALTER, CREATE, and INSERT on the new table.\n\no Following the table name, specify the alterations to be made. If none\n are given, ALTER TABLE does nothing.\n\no The syntax for many of the permissible alterations is similar to\n clauses of the CREATE TABLE statement. column_definition clauses use\n the same syntax for ADD and CHANGE as for CREATE TABLE. For more\n information, see [HELP CREATE TABLE].\n\no The word COLUMN is optional and can be omitted, except for RENAME\n COLUMN (to distinguish a column-renaming operation from the RENAME\n table-renaming operation).\n\no Multiple ADD, ALTER, DROP, and CHANGE clauses are permitted in a\n single ALTER TABLE statement, separated by commas. This is a MySQL\n extension to standard SQL, which permits only one of each clause per\n ALTER TABLE statement. For example, to drop multiple columns in a\n single statement, do this:\n\nALTER TABLE t2 DROP COLUMN c, DROP COLUMN d;\n\no If a storage engine does not support an attempted ALTER TABLE\n operation, a warning may result. Such warnings can be displayed with\n SHOW WARNINGS. See [HELP SHOW WARNINGS]. For information on\n troubleshooting ALTER TABLE, see\n http://dev.mysql.com/doc/refman/8.0/en/alter-table-problems.html.\n\no For information about generated columns, see\n http://dev.mysql.com/doc/refman/8.0/en/alter-table-generated-columns.\n html.\n\no For usage examples, see\n http://dev.mysql.com/doc/refman/8.0/en/alter-table-examples.html.\n\no With the mysql_info() C API function, you can find out how many rows\n were copied by ALTER TABLE. See\n http://dev.mysql.com/doc/refman/8.0/en/mysql-info.html.\n\nURL: http://dev.mysql.com/doc/refman/8.0/en/alter-table.html\n\n','','http://dev.mysql.com/doc/refman/8.0/en/alter-table.html'); INSERT INTO help_topic (help_topic_id,help_category_id,name,description,example,url) VALUES (33,9,'ALTER TABLESPACE','Syntax:\nALTER TABLESPACE tablespace_name\n [RENAME TO tablespace_name] \n [ENCRYPTION [=] {\'Y\' | \'N\'}]\n [ENGINE [=] engine_name]\n\nThis statement can be used to rename an InnoDB general tablespace.\n\nThe CREATE TABLESPACE privilege is required to rename a general\ntablespace.\n\nThe ENGINE clause, which specifies the storage engine used by the\ntablespace, is deprecated and will be removed in a future release. The\ntablespace storage engine is known by the data dictionary, making the\nENGINE clause obsolete. If the storage engine is specified, it must\nmatch the tablespace storage engine defined in the data dictionary.\n\nRENAME TO operations are implicitly performed in autocommit mode,\nregardless of the autocommit setting.\n\nA RENAME TO operation cannot be performed while LOCK TABLES or FLUSH\nTABLES WITH READ LOCK is in effect for tables that reside in the\ntablespace.\n\nExclusive metadata locks are taken on tables that reside in a general\ntablespace while the tablespace is renamed, which prevents concurrent\nDDL. Concurrent DML is supported.\n\nThe ENCRYPTION option is used to enable or disable page-level data\nencryption for an InnoDB general tablespace. Option values are not\ncase-sensitive. The Encryption support for general tablespaces was\nintroduced in MySQL 8.0.13. A keyring plugin must be installed and\nconfigured to encrypt a tablespace using the ENCRYPTION option.\n\nWhen a general tablespace is encrypted, all tables residing in the\ntablespace are encrypted. Likewise, a table created in an encrypted\ngeneral tablespace is encrypted.\n\nThe INPLACE algorithm is used when altering the ENCRYPTION attribute of\na general tablespace. The INPLACE algorithm permits concurrent DML on\ntables that reside in the general tablespace. Concurrent DDL is\nblocked.\n\nFor more information, see\nhttp://dev.mysql.com/doc/refman/8.0/en/innodb-tablespace-encryption.htm\nl.\n\nURL: http://dev.mysql.com/doc/refman/8.0/en/alter-tablespace.html\n\n','','http://dev.mysql.com/doc/refman/8.0/en/alter-tablespace.html'); INSERT INTO help_topic (help_topic_id,help_category_id,name,description,example,url) VALUES (34,1,'ALTER USER','Syntax:\nALTER USER [IF EXISTS]\n user [auth_option] [, user [auth_option]] ...\n [REQUIRE {NONE | tls_option [[AND] tls_option] ...}]\n [WITH resource_option [resource_option] ...]\n [password_option | lock_option] ...\n\nALTER USER [IF EXISTS]\n USER() IDENTIFIED BY \'auth_string\' [REPLACE \'current_auth_string\']\n\nALTER USER [IF EXISTS]\n user DEFAULT ROLE\n {NONE | ALL | role [, role ] ...}\n\nuser:\n (see )\n\nauth_option: {\n IDENTIFIED BY \'auth_string\' [REPLACE \'current_auth_string\']\n | IDENTIFIED WITH auth_plugin\n | IDENTIFIED WITH auth_plugin BY \'auth_string\' [REPLACE \'current_auth_string\']\n | IDENTIFIED WITH auth_plugin AS \'hash_string\'\n}\n\ntls_option: {\n SSL\n | X509\n | CIPHER \'cipher\'\n | ISSUER \'issuer\'\n | SUBJECT \'subject\'\n}\n\nresource_option: {\n MAX_QUERIES_PER_HOUR count\n | MAX_UPDATES_PER_HOUR count\n | MAX_CONNECTIONS_PER_HOUR count\n | MAX_USER_CONNECTIONS count\n}\n\npassword_option: {\n PASSWORD EXPIRE [DEFAULT | NEVER | INTERVAL N DAY]\n | PASSWORD HISTORY {DEFAULT | N}\n | PASSWORD REUSE INTERVAL {DEFAULT | N DAY}\n | PASSWORD REQUIRE CURRENT [DEFAULT | OPTIONAL]\n}\n\nlock_option: {\n ACCOUNT LOCK\n | ACCOUNT UNLOCK\n}\n\nThe ALTER USER statement modifies MySQL accounts. It enables\nauthentication, role, SSL/TLS, resource-limit, and password-management\nproperties to be modified for existing accounts, and enables account\nlocking and unlocking.\n\nIn most cases, ALTER USER requires the global CREATE USER privilege, or\nthe UPDATE privilege for the mysql system database. The exceptions are:\n\no Any client who connects to the server using a nonanonymous account\n can change the password for that account. (In particular, you can\n change your own password.) To see which account the server\n authenticated you as, invoke the CURRENT_USER() function:\n\nSELECT CURRENT_USER();\n\no For DEFAULT ROLE syntax, ALTER USER requires these privileges:\n\n o Setting the default roles for another user requires the global\n CREATE USER privilege, or the UPDATE privilege for the\n mysql.default_roles system table.\n\n o Setting the default roles for yourself requires no special\n privileges, as long as the roles you want as the default have been\n granted to you.\n\nWhen the read_only system variable is enabled, ALTER USER additionally\nrequires the CONNECTION_ADMIN or SUPER privilege.\n\nBy default, an error occurs if you try to modify a user that does not\nexist. If the IF EXISTS clause is given, the statement produces a\nwarning for each named user that does not exist, rather than an error.\n\nURL: http://dev.mysql.com/doc/refman/8.0/en/alter-user.html\n\n','','http://dev.mysql.com/doc/refman/8.0/en/alter-user.html'); INSERT INTO help_topic (help_topic_id,help_category_id,name,description,example,url) VALUES (35,9,'ALTER VIEW','Syntax:\nALTER\n [ALGORITHM = {UNDEFINED | MERGE | TEMPTABLE}]\n [DEFINER = { user | CURRENT_USER }]\n [SQL SECURITY { DEFINER | INVOKER }]\n VIEW view_name [(column_list)]\n AS select_statement\n [WITH [CASCADED | LOCAL] CHECK OPTION]\n\nThis statement changes the definition of a view, which must exist. The\nsyntax is similar to that for CREATE VIEW see [HELP CREATE VIEW]). This\nstatement requires the CREATE VIEW and DROP privileges for the view,\nand some privilege for each column referred to in the SELECT statement.\nALTER VIEW is permitted only to the definer or users with the\nSET_USER_ID or SUPER privilege.\n\nURL: http://dev.mysql.com/doc/refman/8.0/en/alter-view.html\n\n','','http://dev.mysql.com/doc/refman/8.0/en/alter-view.html'); @@ -204,7 +204,7 @@ INSERT INTO help_topic (help_topic_id,help_category_id,name,description,example, INSERT INTO help_topic (help_topic_id,help_category_id,name,description,example,url) VALUES (115,1,'CREATE ROLE','Syntax:\nCREATE ROLE [IF NOT EXISTS] role [, role ] ...\n\nCREATE ROLE creates one or more roles, which are named collections of\nprivileges. To use this statement, you must have the global CREATE ROLE\nor CREATE USER privilege. When the read_only system variable is\nenabled, CREATE ROLE additionally requires the CONNECTION_ADMIN or\nSUPER privilege.\n\nA role when created is locked, has no password, and is assigned the\ndefault authentication plugin.\n\nCREATE ROLE either succeeds for all named roles or rolls back and has\nno effect if any error occurs. By default, an error occurs if you try\nto create a role that already exists. If the IF NOT EXISTS clause is\ngiven, the statement produces a warning for each named role that\nalready exists, rather than an error.\n\nThe statement is written to the binary log if it succeeds, but not if\nit fails; in that case, rollback occurs and no changes are made. A\nstatement written to the binary log includes all named roles. If the IF\nNOT EXISTS clause is given, this includes even roles that already exist\nand were not created.\n\nEach role name uses the format described in\nhttp://dev.mysql.com/doc/refman/8.0/en/role-names.html. For example:\n\nCREATE ROLE \'administrator\', \'developer\';\nCREATE ROLE \'webapp\'@\'localhost\';\n\nThe host name part of the role name, if omitted, defaults to \'%\'.\n\nFor role usage examples, see\nhttp://dev.mysql.com/doc/refman/8.0/en/roles.html.\n\nURL: http://dev.mysql.com/doc/refman/8.0/en/create-role.html\n\n','','http://dev.mysql.com/doc/refman/8.0/en/create-role.html'); INSERT INTO help_topic (help_topic_id,help_category_id,name,description,example,url) VALUES (116,9,'CREATE SERVER','Syntax:\nCREATE SERVER server_name\n FOREIGN DATA WRAPPER wrapper_name\n OPTIONS (option [, option] ...)\n\noption:\n { HOST character-literal\n | DATABASE character-literal\n | USER character-literal\n | PASSWORD character-literal\n | SOCKET character-literal\n | OWNER character-literal\n | PORT numeric-literal }\n\nThis statement creates the definition of a server for use with the\nFEDERATED storage engine. The CREATE SERVER statement creates a new row\nin the servers table in the mysql database. This statement requires the\nSUPER privilege.\n\nThe server_name should be a unique reference to the server. Server\ndefinitions are global within the scope of the server, it is not\npossible to qualify the server definition to a specific database.\nserver_name has a maximum length of 64 characters (names longer than 64\ncharacters are silently truncated), and is case insensitive. You may\nspecify the name as a quoted string.\n\nThe wrapper_name is an identifier and may be quoted with single\nquotation marks.\n\nFor each option you must specify either a character literal or numeric\nliteral. Character literals are UTF-8, support a maximum length of 64\ncharacters and default to a blank (empty) string. String literals are\nsilently truncated to 64 characters. Numeric literals must be a number\nbetween 0 and 9999, default value is 0.\n\n*Note*:\n\nThe OWNER option is currently not applied, and has no effect on the\nownership or operation of the server connection that is created.\n\nThe CREATE SERVER statement creates an entry in the mysql.servers table\nthat can later be used with the CREATE TABLE statement when creating a\nFEDERATED table. The options that you specify will be used to populate\nthe columns in the mysql.servers table. The table columns are\nServer_name, Host, Db, Username, Password, Port and Socket.\n\nURL: http://dev.mysql.com/doc/refman/8.0/en/create-server.html\n\n','CREATE SERVER s\nFOREIGN DATA WRAPPER mysql\nOPTIONS (USER \'Remote\', HOST \'198.51.100.106\', DATABASE \'test\');\n','http://dev.mysql.com/doc/refman/8.0/en/create-server.html'); INSERT INTO help_topic (help_topic_id,help_category_id,name,description,example,url) VALUES (117,9,'CREATE SPATIAL REFERENCE SYSTEM','Syntax:\nCREATE OR REPLACE SPATIAL REFERENCE SYSTEM\n srid srs_attribute ...\n\nCREATE SPATIAL REFERENCE SYSTEM\n [IF NOT EXISTS]\n srid srs_attribute ...\n\nsrs_attribute: {\n NAME \'srs_name\'\n | DEFINITION \'definition\'\n | ORGANIZATION \'org_name\' IDENTIFIED BY org_id\n | DESCRIPTION \'description\'\n}\n\nsrid, org_id: 32-bit unsigned integer\n\nThis statement creates a spatial reference system (SRS) definition and\nstores it in the data dictionary. The definition can be inspected using\nthe INFORMATION_SCHEMA ST_SPATIAL_REFERENCE_SYSTEMS table. This\nstatement requires the SUPER privilege.\n\nIf neither OR REPLACE nor IF NOT EXISTS is specified, an error occurs\nif an SRS definition with the SRID value already exists.\n\nWith CREATE OR REPLACE syntax, any existing SRS definition with the\nsame SRID value is replaced, unless the SRID value is used by some\ncolumn in an existing table. In that case, an error occurs. For\nexample:\n\nmysql> CREATE OR REPLACE SPATIAL REFERENCE SYSTEM 4326 ...;\nERROR 3716 (SR005): Can\'t modify SRID 4326. There is at\nleast one column depending on it.\n\nTo identify which column or columns use the SRID, use this query:\n\nSELECT * FROM INFORMATION_SCHEMA.ST_GEOMETRY_COLUMNS WHERE SRS_ID=4326;\n\nWith CREATE ... IF NOT EXISTS syntax, any existing SRS definition with\nthe same SRID value causes the new definition to be ignored and a\nwarning occurs.\n\nURL: http://dev.mysql.com/doc/refman/8.0/en/create-spatial-reference-system.html\n\n','CREATE SPATIAL REFERENCE SYSTEM 4120\nNAME \'Greek\'\nORGANIZATION \'EPSG\' IDENTIFIED BY 4120\nDEFINITION\n \'GEOGCS["Greek",DATUM["Greek",SPHEROID["Bessel 1841",\n 6377397.155,299.1528128,AUTHORITY["EPSG","7004"]],\n AUTHORITY["EPSG","6120"]],PRIMEM["Greenwich",0,\n AUTHORITY["EPSG","8901"]],UNIT["degree",0.017453292519943278,\n AUTHORITY["EPSG","9122"]],AXIS["Lat",NORTH],AXIS["Lon",EAST],\n AUTHORITY["EPSG","4120"]]\';\n','http://dev.mysql.com/doc/refman/8.0/en/create-spatial-reference-system.html'); -INSERT INTO help_topic (help_topic_id,help_category_id,name,description,example,url) VALUES (118,9,'CREATE TABLE','Syntax:\nCREATE [TEMPORARY] TABLE [IF NOT EXISTS] tbl_name\n (create_definition,...)\n [table_options]\n [partition_options]\n\nCREATE [TEMPORARY] TABLE [IF NOT EXISTS] tbl_name\n [(create_definition,...)]\n [table_options]\n [partition_options]\n [IGNORE | REPLACE]\n [AS] query_expression\n\nCREATE [TEMPORARY] TABLE [IF NOT EXISTS] tbl_name\n { LIKE old_tbl_name | (LIKE old_tbl_name) }\n\ncreate_definition:\n col_name column_definition\n | [CONSTRAINT [symbol]] PRIMARY KEY [index_type] (key_part,...)\n [index_option] ...\n | {INDEX|KEY} [index_name] [index_type] (key_part,...)\n [index_option] ...\n | [CONSTRAINT [symbol]] UNIQUE [INDEX|KEY]\n [index_name] [index_type] (key_part,...)\n [index_option] ...\n | {FULLTEXT|SPATIAL} [INDEX|KEY] [index_name] (key_part,...)\n [index_option] ...\n | [CONSTRAINT [symbol]] FOREIGN KEY\n [index_name] (col_name,...) reference_definition\n | CHECK (expr)\n\ncolumn_definition:\n data_type [NOT NULL | NULL] [DEFAULT {literal | (expr)} ]\n [AUTO_INCREMENT] [UNIQUE [KEY]] [[PRIMARY] KEY]\n [COMMENT \'string\']\n [COLUMN_FORMAT {FIXED|DYNAMIC|DEFAULT}]\n [reference_definition]\n | data_type [GENERATED ALWAYS] AS (expression)\n [VIRTUAL | STORED] [NOT NULL | NULL]\n [UNIQUE [KEY]] [[PRIMARY] KEY]\n [COMMENT \'string\']\n\ndata_type:\n (see http://dev.mysql.com/doc/refman/8.0/en/data-types.html)\n\nkey_part: {col_name [(length)] | (expr)} [ASC | DESC]\n\nindex_type:\n USING {BTREE | HASH}\n\nindex_option:\n KEY_BLOCK_SIZE [=] value\n | index_type\n | WITH PARSER parser_name\n | COMMENT \'string\'\n | {VISIBLE | INVISIBLE}\n\nreference_definition:\n REFERENCES tbl_name (key_part,...)\n [MATCH FULL | MATCH PARTIAL | MATCH SIMPLE]\n [ON DELETE reference_option]\n [ON UPDATE reference_option]\n\nreference_option:\n RESTRICT | CASCADE | SET NULL | NO ACTION | SET DEFAULT\n\ntable_options:\n table_option [[,] table_option] ...\n\ntable_option:\n AUTO_INCREMENT [=] value\n | AVG_ROW_LENGTH [=] value\n | [DEFAULT] CHARACTER SET [=] charset_name\n | CHECKSUM [=] {0 | 1}\n | [DEFAULT] COLLATE [=] collation_name\n | COMMENT [=] \'string\'\n | COMPRESSION [=] {\'ZLIB\'|\'LZ4\'|\'NONE\'}\n | CONNECTION [=] \'connect_string\'\n | {DATA|INDEX} DIRECTORY [=] \'absolute path to directory\'\n | DELAY_KEY_WRITE [=] {0 | 1}\n | ENCRYPTION [=] {\'Y\' | \'N\'}\n | ENGINE [=] engine_name\n | INSERT_METHOD [=] { NO | FIRST | LAST }\n | KEY_BLOCK_SIZE [=] value\n | MAX_ROWS [=] value\n | MIN_ROWS [=] value\n | PACK_KEYS [=] {0 | 1 | DEFAULT}\n | PASSWORD [=] \'string\'\n | ROW_FORMAT [=] {DEFAULT|DYNAMIC|FIXED|COMPRESSED|REDUNDANT|COMPACT}\n | STATS_AUTO_RECALC [=] {DEFAULT|0|1}\n | STATS_PERSISTENT [=] {DEFAULT|0|1}\n | STATS_SAMPLE_PAGES [=] value\n | TABLESPACE tablespace_name\n | UNION [=] (tbl_name[,tbl_name]...)\n\npartition_options:\n PARTITION BY\n { [LINEAR] HASH(expr)\n | [LINEAR] KEY [ALGORITHM={1|2}] (column_list)\n | RANGE{(expr) | COLUMNS(column_list)}\n | LIST{(expr) | COLUMNS(column_list)} }\n [PARTITIONS num]\n [SUBPARTITION BY\n { [LINEAR] HASH(expr)\n | [LINEAR] KEY [ALGORITHM={1|2}] (column_list) }\n [SUBPARTITIONS num]\n ]\n [(partition_definition [, partition_definition] ...)]\n\npartition_definition:\n PARTITION partition_name\n [VALUES\n {LESS THAN {(expr | value_list) | MAXVALUE}\n |\n IN (value_list)}]\n [[STORAGE] ENGINE [=] engine_name]\n [COMMENT [=] \'string\' ]\n [DATA DIRECTORY [=] \'data_dir\']\n [INDEX DIRECTORY [=] \'index_dir\']\n [MAX_ROWS [=] max_number_of_rows]\n [MIN_ROWS [=] min_number_of_rows]\n [TABLESPACE [=] tablespace_name]\n [(subpartition_definition [, subpartition_definition] ...)]\n\nsubpartition_definition:\n SUBPARTITION logical_name\n [[STORAGE] ENGINE [=] engine_name]\n [COMMENT [=] \'string\' ]\n [DATA DIRECTORY [=] \'data_dir\']\n [INDEX DIRECTORY [=] \'index_dir\']\n [MAX_ROWS [=] max_number_of_rows]\n [MIN_ROWS [=] min_number_of_rows]\n [TABLESPACE [=] tablespace_name]\n\nquery_expression:\n SELECT ... (Some valid select or union statement)\n\nCREATE TABLE creates a table with the given name. You must have the\nCREATE privilege for the table.\n\nBy default, tables are created in the default database, using the\nInnoDB storage engine. An error occurs if the table exists, if there is\nno default database, or if the database does not exist.\n\nFor information about the physical representation of a table, see\nhttp://dev.mysql.com/doc/refman/8.0/en/create-table-files.html.\n\nURL: http://dev.mysql.com/doc/refman/8.0/en/create-table.html\n\n','','http://dev.mysql.com/doc/refman/8.0/en/create-table.html'); +INSERT INTO help_topic (help_topic_id,help_category_id,name,description,example,url) VALUES (118,9,'CREATE TABLE','Syntax:\nCREATE [TEMPORARY] TABLE [IF NOT EXISTS] tbl_name\n (create_definition,...)\n [table_options]\n [partition_options]\n\nCREATE [TEMPORARY] TABLE [IF NOT EXISTS] tbl_name\n [(create_definition,...)]\n [table_options]\n [partition_options]\n [IGNORE | REPLACE]\n [AS] query_expression\n\nCREATE [TEMPORARY] TABLE [IF NOT EXISTS] tbl_name\n { LIKE old_tbl_name | (LIKE old_tbl_name) }\n\ncreate_definition:\n col_name column_definition\n | [CONSTRAINT [symbol]] PRIMARY KEY [index_type] (key_part,...)\n [index_option] ...\n | {INDEX|KEY} [index_name] [index_type] (key_part,...)\n [index_option] ...\n | [CONSTRAINT [symbol]] UNIQUE [INDEX|KEY]\n [index_name] [index_type] (key_part,...)\n [index_option] ...\n | {FULLTEXT|SPATIAL} [INDEX|KEY] [index_name] (key_part,...)\n [index_option] ...\n | [CONSTRAINT [symbol]] FOREIGN KEY\n [index_name] (col_name,...) reference_definition\n | check_constraint_definition\n\ncolumn_definition:\n data_type [NOT NULL | NULL] [DEFAULT {literal | (expr)} ]\n [AUTO_INCREMENT] [UNIQUE [KEY]] [[PRIMARY] KEY]\n [COMMENT \'string\']\n [COLUMN_FORMAT {FIXED|DYNAMIC|DEFAULT}]\n [reference_definition]\n [check_constraint_definition]\n | data_type [GENERATED ALWAYS] AS (expression)\n [VIRTUAL | STORED] [NOT NULL | NULL]\n [UNIQUE [KEY]] [[PRIMARY] KEY]\n [COMMENT \'string\']\n [check_constraint_definition]\n\n\ndata_type:\n (see http://dev.mysql.com/doc/refman/8.0/en/data-types.html)\n\nkey_part: {col_name [(length)] | (expr)} [ASC | DESC]\n\nindex_type:\n USING {BTREE | HASH}\n\nindex_option:\n KEY_BLOCK_SIZE [=] value\n | index_type\n | WITH PARSER parser_name\n | COMMENT \'string\'\n | {VISIBLE | INVISIBLE}\n\nreference_definition:\n REFERENCES tbl_name (key_part,...)\n [MATCH FULL | MATCH PARTIAL | MATCH SIMPLE]\n [ON DELETE reference_option]\n [ON UPDATE reference_option]\n\nreference_option:\n RESTRICT | CASCADE | SET NULL | NO ACTION | SET DEFAULT\n\ncheck_constraint_definition:\n [CONSTRAINT [symbol]] CHECK (expr) [[NOT] ENFORCED]\n\ntable_options:\n table_option [[,] table_option] ...\n\ntable_option:\n AUTO_INCREMENT [=] value\n | AVG_ROW_LENGTH [=] value\n | [DEFAULT] CHARACTER SET [=] charset_name\n | CHECKSUM [=] {0 | 1}\n | [DEFAULT] COLLATE [=] collation_name\n | COMMENT [=] \'string\'\n | COMPRESSION [=] {\'ZLIB\'|\'LZ4\'|\'NONE\'}\n | CONNECTION [=] \'connect_string\'\n | {DATA|INDEX} DIRECTORY [=] \'absolute path to directory\'\n | DELAY_KEY_WRITE [=] {0 | 1}\n | ENCRYPTION [=] {\'Y\' | \'N\'}\n | ENGINE [=] engine_name\n | INSERT_METHOD [=] { NO | FIRST | LAST }\n | KEY_BLOCK_SIZE [=] value\n | MAX_ROWS [=] value\n | MIN_ROWS [=] value\n | PACK_KEYS [=] {0 | 1 | DEFAULT}\n | PASSWORD [=] \'string\'\n | ROW_FORMAT [=] {DEFAULT|DYNAMIC|FIXED|COMPRESSED|REDUNDANT|COMPACT}\n | STATS_AUTO_RECALC [=] {DEFAULT|0|1}\n | STATS_PERSISTENT [=] {DEFAULT|0|1}\n | STATS_SAMPLE_PAGES [=] value\n | TABLESPACE tablespace_name\n | UNION [=] (tbl_name[,tbl_name]...)\n\npartition_options:\n PARTITION BY\n { [LINEAR] HASH(expr)\n | [LINEAR] KEY [ALGORITHM={1|2}] (column_list)\n | RANGE{(expr) | COLUMNS(column_list)}\n | LIST{(expr) | COLUMNS(column_list)} }\n [PARTITIONS num]\n [SUBPARTITION BY\n { [LINEAR] HASH(expr)\n | [LINEAR] KEY [ALGORITHM={1|2}] (column_list) }\n [SUBPARTITIONS num]\n ]\n [(partition_definition [, partition_definition] ...)]\n\npartition_definition:\n PARTITION partition_name\n [VALUES\n {LESS THAN {(expr | value_list) | MAXVALUE}\n |\n IN (value_list)}]\n [[STORAGE] ENGINE [=] engine_name]\n [COMMENT [=] \'string\' ]\n [DATA DIRECTORY [=] \'data_dir\']\n [INDEX DIRECTORY [=] \'index_dir\']\n [MAX_ROWS [=] max_number_of_rows]\n [MIN_ROWS [=] min_number_of_rows]\n [TABLESPACE [=] tablespace_name]\n [(subpartition_definition [, subpartition_definition] ...)]\n\nsubpartition_definition:\n SUBPARTITION logical_name\n [[STORAGE] ENGINE [=] engine_name]\n [COMMENT [=] \'string\' ]\n [DATA DIRECTORY [=] \'data_dir\']\n [INDEX DIRECTORY [=] \'index_dir\']\n [MAX_ROWS [=] max_number_of_rows]\n [MIN_ROWS [=] min_number_of_rows]\n [TABLESPACE [=] tablespace_name]\n\nquery_expression:\n SELECT ... (Some valid select or union statement)\n\nCREATE TABLE creates a table with the given name. You must have the\nCREATE privilege for the table.\n\nBy default, tables are created in the default database, using the\nInnoDB storage engine. An error occurs if the table exists, if there is\nno default database, or if the database does not exist.\n\nFor information about the physical representation of a table, see\nhttp://dev.mysql.com/doc/refman/8.0/en/create-table-files.html.\n\nURL: http://dev.mysql.com/doc/refman/8.0/en/create-table.html\n\n','','http://dev.mysql.com/doc/refman/8.0/en/create-table.html'); INSERT INTO help_topic (help_topic_id,help_category_id,name,description,example,url) VALUES (119,9,'CREATE TABLESPACE','Syntax:\nCREATE TABLESPACE tablespace_name\n ADD DATAFILE \'file_name\'\n [FILE_BLOCK_SIZE = value]\n [ENCRYPTION [=] {\'Y\' | \'N\'}]\n [ENGINE [=] engine_name]\n\nThis statement is used to create an InnoDB tablespace. An InnoDB\ntablespace created using CREATE TABLESPACE is referred to as general\ntablespace.\n\nA general tablespace is a shared tablespace, similar to the system\ntablespace. It can hold multiple tables, and supports all table row\nformats. General tablespaces can also be created in a location relative\nto or independent of the MySQL data directory.\n\nAfter creating an InnoDB general tablespace, you can use CREATE TABLE\ntbl_name ... TABLESPACE [=] tablespace_name or ALTER TABLE tbl_name\nTABLESPACE [=] tablespace_name to add tables to the tablespace.\n\nFor more information, see\nhttp://dev.mysql.com/doc/refman/8.0/en/general-tablespaces.html.\n\n*Note*:\n\nCREATE TABLESPACE is supported with InnoDB. In earlier releases, CREATE\nTABLESPACE only supported NDB\n(http://dev.mysql.com/doc/refman/5.7/en/mysql-cluster.html), which is\nthe MySQL NDB Cluster storage engine.\n\nOptions\n\no ADD DATAFILE: Defines the name of the tablespace data file. A data\n file must be specified with the CREATE TABLESPACE statement, and the\n data file name must have a .ibd extension. An InnoDB general\n tablespace only supports a single data file.\n\n To place the data file in a location outside of the MySQL data\n directory (DATADIR), include an absolute directory path or a path\n relative to the MySQL data directory. If you do not specify a path,\n the general tablespace is created in the MySQL data directory.\n\n To avoid conflicts with implicitly created file-per-table\n tablespaces, creating a general tablespace in a subdirectory under\n the MySQL data directory is not supported. Also, when creating a\n general tablespace outside of the MySQL data directory, the directory\n must exist and must be known to InnoDB prior to creating the\n tablespace. To make an unknown directory known to InnoDB, add the\n directory to the innodb_directories argument value.\n innodb_directories is a read-only startup option. Configuring it\n requires restarting the server.\n\n The file_name, including the path (optional), must be quoted with\n single or double quotations marks. File names (not counting the\n ".ibd" extension) and directory names must be at least one byte in\n length. Zero length file names and directory names are not supported.\n\no FILE_BLOCK_SIZE: Defines the block size for the tablespace data file.\n Values can be specified in bytes or kilobytes. For example, an 8\n kilobyte file block size can be specified as 8192 or 8K. If you do\n not specify this option, FILE_BLOCK_SIZE defaults to\n innodb_page_size. FILE_BLOCK_SIZE is required when you intend to use\n the tablespace for storing compressed InnoDB tables\n (ROW_FORMAT=COMPRESSED). In this case, you must define the tablespace\n FILE_BLOCK_SIZE when creating the tablespace.\n\n If FILE_BLOCK_SIZE is equal innodb_page_size, the tablespace can\n contain only tables having an uncompressed row format (COMPACT,\n REDUNDANT, and DYNAMIC row formats). Tables with a COMPRESSED row\n format have a different physical page size than uncompressed tables.\n Therefore, compressed tables cannot coexist in the same tablespace as\n uncompressed tables.\n\n For a general tablespace to contain compressed tables,\n FILE_BLOCK_SIZE must be specified, and the FILE_BLOCK_SIZE value must\n be a valid compressed page size in relation to the innodb_page_size\n value. Also, the physical page size of the compressed table\n (KEY_BLOCK_SIZE) must be equal to FILE_BLOCK_SIZE/1024. For example,\n if innodb_page_size=16K, and FILE_BLOCK_SIZE=8K, the KEY_BLOCK_SIZE\n of the table must be 8. For more information, see\n http://dev.mysql.com/doc/refman/8.0/en/general-tablespaces.html.\n\no The ENCRYPTION option is used to enable or disable page-level data\n encryption for an InnoDB general tablespace. Option values are not\n case-sensitive. Encryption support for general tablespaces was\n introduced in MySQL 8.0.13. A keyring plugin must be installed and\n configured to use the ENCRYPTION option.\n\n When a general tablespace is encrypted, all tables residing in the\n tablespace are encrypted. Likewise, a table created in an encrypted\n general tablespace is encrypted.\n\n For more information, see\n http://dev.mysql.com/doc/refman/8.0/en/innodb-tablespace-encryption.h\n tml\n\no ENGINE: Defines the storage engine which uses the tablespace, where\n engine_name is the name of the storage engine. Currently, only the\n InnoDB storage engine is supported. ENGINE = InnoDB must be defined\n as part of the CREATE TABLESPACE statement or InnoDB must be defined\n as the default storage engine (default_storage_engine=InnoDB).\n\nNotes\n\no tablespace_name is a case-sensitive identifier for the tablespace. It\n may be quoted or unquoted. The forward slash character ("/") is not\n permitted. Names beginning with innodb_ are either not permitted or\n are reserved for special use.\n\no Creation of temporary general tablespaces is not supported.\n\no General tablespaces do not support temporary tables.\n\no General tablespaces support the addition of tables of any row format\n using CREATE TABLE ... TABLESPACE. innodb_file_per_table does not\n need to be enabled.\n\no innodb_strict_mode is not applicable to general tablespaces.\n Tablespace management rules are strictly enforced independently of\n innodb_strict_mode. If CREATE TABLESPACE parameters are incorrect or\n incompatible, the operation fails regardless of the\n innodb_strict_mode setting. When a table is added to a general\n tablespace using CREATE TABLE ... TABLESPACE or ALTER TABLE ...\n TABLESPACE, innodb_strict_mode is ignored but the statement is\n evaluated as if innodb_strict_mode is enabled.\n\no Use DROP TABLESPACE to remove a general tablespace. All tables must\n be dropped from a general tablespace using DROP TABLE prior to\n dropping the tablespace.\n\no All parts of a table added to a general tablespace reside in the\n general tablespace, including indexes and BLOB pages.\n\no Similar to the system tablespace, truncating or dropping tables\n stored in a general tablespace creates free space internally in the\n general tablespace .ibd data file which can only be used for new\n InnoDB data. Space is not released back to the operating system as it\n is for file-per-table tablespaces.\n\no A general tablespace is not associated with any database or schema.\n\no ALTER TABLE ... DISCARD TABLESPACE and ALTER TABLE ...IMPORT\n TABLESPACE are not supported for tables that belong to a general\n tablespace.\n\no The server uses tablespace-level metadata locking for DDL that\n references general tablespaces. By comparison, the server uses\n table-level metadata locking for DDL that references file-per-table\n tablespaces.\n\no A generated or existing tablespace cannot be changed to a general\n tablespace.\n\no There is no conflict between general tablespace names and\n file-per-table tablespace names. The "/" character, which is present\n in file-per-table tablespace names, is not permitted in general\n tablespace names.\n\no mysqldump and mysqlpump do not dump InnoDB CREATE TABLESPACE\n statements.\n\nExamples\n\nThis example demonstrates creating a general tablespace and adding\nthree uncompressed tables of different row formats.\n\nmysql> CREATE TABLESPACE `ts1` ADD DATAFILE \'ts1.ibd\' Engine=InnoDB;\nQuery OK, 0 rows affected (0.01 sec)\n\nmysql> CREATE TABLE t1 (c1 INT PRIMARY KEY) TABLESPACE ts1 ROW_FORMAT=REDUNDANT;\nQuery OK, 0 rows affected (0.00 sec)\n\nmysql> CREATE TABLE t2 (c1 INT PRIMARY KEY) TABLESPACE ts1 ROW_FORMAT=COMPACT;\nQuery OK, 0 rows affected (0.00 sec)\n\nmysql> CREATE TABLE t3 (c1 INT PRIMARY KEY) TABLESPACE ts1 ROW_FORMAT=DYNAMIC;\nQuery OK, 0 rows affected (0.00 sec)\n\nThis example demonstrates creating a general tablespace and adding a\ncompressed table. The example assumes a default innodb_page_size of\n16K. The FILE_BLOCK_SIZE of 8192 requires that the compressed table\nhave a KEY_BLOCK_SIZE of 8.\n\nmysql> CREATE TABLESPACE `ts2` ADD DATAFILE \'ts2.ibd\' FILE_BLOCK_SIZE = 8192 Engine=InnoDB;\nQuery OK, 0 rows affected (0.01 sec)\n\nmysql> CREATE TABLE t4 (c1 INT PRIMARY KEY) TABLESPACE ts2 ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=8;\nQuery OK, 0 rows affected (0.00 sec)\n\nURL: http://dev.mysql.com/doc/refman/8.0/en/create-tablespace.html\n\n','','http://dev.mysql.com/doc/refman/8.0/en/create-tablespace.html'); INSERT INTO help_topic (help_topic_id,help_category_id,name,description,example,url) VALUES (120,9,'CREATE TRIGGER','Syntax:\nCREATE\n [DEFINER = { user | CURRENT_USER }]\n TRIGGER trigger_name\n trigger_time trigger_event\n ON tbl_name FOR EACH ROW\n [trigger_order]\n trigger_body\n\ntrigger_time: { BEFORE | AFTER }\n\ntrigger_event: { INSERT | UPDATE | DELETE }\n\ntrigger_order: { FOLLOWS | PRECEDES } other_trigger_name\n\nThis statement creates a new trigger. A trigger is a named database\nobject that is associated with a table, and that activates when a\nparticular event occurs for the table. The trigger becomes associated\nwith the table named tbl_name, which must refer to a permanent table.\nYou cannot associate a trigger with a TEMPORARY table or a view.\n\nTrigger names exist in the schema namespace, meaning that all triggers\nmust have unique names within a schema. Triggers in different schemas\ncan have the same name.\n\nThis section describes CREATE TRIGGER syntax. For additional\ndiscussion, see\nhttp://dev.mysql.com/doc/refman/8.0/en/trigger-syntax.html.\n\nCREATE TRIGGER requires the TRIGGER privilege for the table associated\nwith the trigger. The statement might also require the SET_USER_ID or\nSUPER privilege, depending on the DEFINER value, as described later in\nthis section. If binary logging is enabled, CREATE TRIGGER might\nrequire the SUPER privilege, as described in\nhttp://dev.mysql.com/doc/refman/8.0/en/stored-programs-logging.html.\n\nThe DEFINER clause determines the security context to be used when\nchecking access privileges at trigger activation time, as described\nlater in this section.\n\ntrigger_time is the trigger action time. It can be BEFORE or AFTER to\nindicate that the trigger activates before or after each row to be\nmodified.\n\nBasic column value checks occur prior to trigger activation, so you\ncannot use BEFORE triggers to convert values inappropriate for the\ncolumn type to valid values.\n\ntrigger_event indicates the kind of operation that activates the\ntrigger. These trigger_event values are permitted:\n\no INSERT: The trigger activates whenever a new row is inserted into the\n table; for example, through INSERT, LOAD DATA, and REPLACE\n statements.\n\no UPDATE: The trigger activates whenever a row is modified; for\n example, through UPDATE statements.\n\no DELETE: The trigger activates whenever a row is deleted from the\n table; for example, through DELETE and REPLACE statements. DROP TABLE\n and TRUNCATE TABLE statements on the table do not activate this\n trigger, because they do not use DELETE. Dropping a partition does\n not activate DELETE triggers, either.\n\nURL: http://dev.mysql.com/doc/refman/8.0/en/create-trigger.html\n\n','','http://dev.mysql.com/doc/refman/8.0/en/create-trigger.html'); INSERT INTO help_topic (help_topic_id,help_category_id,name,description,example,url) VALUES (121,1,'CREATE USER','Syntax:\nCREATE USER [IF NOT EXISTS]\n user [auth_option] [, user [auth_option]] ...\n DEFAULT ROLE role [, role ] ...\n [REQUIRE {NONE | tls_option [[AND] tls_option] ...}]\n [WITH resource_option [resource_option] ...]\n [password_option | lock_option] ...\n\nuser:\n (see )\n\nauth_option: {\n IDENTIFIED BY \'auth_string\'\n | IDENTIFIED WITH auth_plugin\n | IDENTIFIED WITH auth_plugin BY \'auth_string\'\n | IDENTIFIED WITH auth_plugin AS \'hash_string\'\n}\n\ntls_option: {\n SSL\n | X509\n | CIPHER \'cipher\'\n | ISSUER \'issuer\'\n | SUBJECT \'subject\'\n}\n\nresource_option: {\n MAX_QUERIES_PER_HOUR count\n | MAX_UPDATES_PER_HOUR count\n | MAX_CONNECTIONS_PER_HOUR count\n | MAX_USER_CONNECTIONS count\n}\n\npassword_option: {\n PASSWORD EXPIRE [DEFAULT | NEVER | INTERVAL N DAY]\n | PASSWORD HISTORY {DEFAULT | N}\n | PASSWORD REUSE INTERVAL {DEFAULT | N DAY}\n | PASSWORD REQUIRE CURRENT [DEFAULT | OPTIONAL]\n}\n\nlock_option: {\n ACCOUNT LOCK\n | ACCOUNT UNLOCK\n}\n\nThe CREATE USER statement creates new MySQL accounts. It enables\nauthentication, role, SSL/TLS, resource-limit, and password-management\nproperties to be established for new accounts, and controls whether\naccounts are initially locked or unlocked.\n\nTo use CREATE USER, you must have the global CREATE USER privilege, or\nthe INSERT privilege for the mysql system database. When the read_only\nsystem variable is enabled, CREATE USER additionally requires the\nCONNECTION_ADMIN or SUPER privilege.\n\nCREATE USER either succeeds for all named users or rolls back and has\nno effect if any error occurs. By default, an error occurs if you try\nto create a user that already exists. If the IF NOT EXISTS clause is\ngiven, the statement produces a warning for each named user that\nalready exists, rather than an error.\n\nURL: http://dev.mysql.com/doc/refman/8.0/en/create-user.html\n\n','','http://dev.mysql.com/doc/refman/8.0/en/create-user.html'); diff --git a/share/errmsg-utf8.txt b/share/errmsg-utf8.txt index b4ee156a73eb..c8a0c31cda36 100644 --- a/share/errmsg-utf8.txt +++ b/share/errmsg-utf8.txt @@ -8772,6 +8772,42 @@ ER_BINLOG_MASTER_KEY_ROTATION_FAIL_TO_CLEANUP_AUX_KEY ER_CLIENT_WARN_PARTIAL_REVOKE_MYSQLBINLOG_INCOMPATIBILITY eng "mysqlbinlog tool may not be able to process GRANT/REVOKE correctly if --partial_revokes is set to ON. This may have implications on point in time recovery using mysqlbinlog." +ER_NON_BOOLEAN_EXPR_FOR_CHECK_CONSTRAINT + eng "An expression of non-boolean type specified to a check constraint '%-.192s'." + +ER_COLUMN_CHECK_CONSTRAINT_REFERENCES_OTHER_COLUMN + eng "Column check constraint '%-.192s' references other column." + +ER_CHECK_CONSTRAINT_NAMED_FUNCTION_IS_NOT_ALLOWED + eng "An expression of a check constraint '%-.192s' contains disallowed function: %s." + +ER_CHECK_CONSTRAINT_FUNCTION_IS_NOT_ALLOWED + eng "An expression of a check constraint '%-.192s' contains disallowed function." + +ER_CHECK_CONSTRAINT_VARIABLES + eng "An expression of a check constraint '%-.192s' cannot refer to a user or system variables." + +ER_CHECK_CONSTRAINT_ROW_VALUE + eng "Check constraint '%-.192s' cannot refer to a row value." + +ER_CHECK_CONSTRAINT_REFERS_AUTO_INCREMENT_COLUMN + eng "Check constraint '%-.192s' cannot refer to an auto-increment column." + +ER_CHECK_CONSTRAINT_VIOLATED + eng "Check constraint '%-.192s' is violated." + +ER_CHECK_CONSTRAINT_REFERS_UNKNOWN_COLUMN + eng "Check constraint '%-.192s' refers to non-existing column '%-.192s'." + +ER_CHECK_CONSTRAINT_NOT_FOUND + eng "Check constraint '%-.192s' is not found in the table." + +ER_CHECK_CONSTRAINT_DUP_NAME + eng "Duplicate check constraint name '%-.192s'." + +ER_CHECK_CONSTRAINT_CLAUSE_USING_FK_REFER_ACTION_COLUMN + eng "Column '%-.192s' cannot be used in a check constraint '%-.192s': needed in a foreign key constraint '%-.192s' referential action." + # # End of 8.0 error messages. # diff --git a/sql/CMakeLists.txt b/sql/CMakeLists.txt index 184602edd5db..f05d3d836022 100644 --- a/sql/CMakeLists.txt +++ b/sql/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2006, 2018, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2006, 2019, Oracle and/or its affiliates. All rights reserved. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License, version 2.0, @@ -120,6 +120,7 @@ SET(DD_SOURCES dd/impl/raw/raw_table.cc dd/impl/system_views/character_sets.cc + dd/impl/system_views/check_constraints.cc dd/impl/system_views/collations.cc dd/impl/system_views/collation_charset_applicability.cc dd/impl/system_views/columns.cc @@ -151,6 +152,7 @@ SET(DD_SOURCES dd/impl/system_views/views.cc dd/impl/tables/character_sets.cc + dd/impl/tables/check_constraints.cc dd/impl/tables/collations.cc dd/impl/tables/columns.cc dd/impl/tables/column_statistics.cc @@ -183,6 +185,7 @@ SET(DD_SOURCES dd/impl/types/table_stat_impl.cc dd/impl/types/abstract_table_impl.cc dd/impl/types/charset_impl.cc + dd/impl/types/check_constraint_impl.cc dd/impl/types/collation_impl.cc dd/impl/types/column_impl.cc dd/impl/types/column_statistics_impl.cc @@ -440,6 +443,7 @@ SET(SQL_SHARED_SOURCES sql_bootstrap.cc sql_initialize.cc sql_call.cc + sql_check_constraint.cc sql_class.cc sql_component.cc sql_const_folding.cc diff --git a/sql/create_field.cc b/sql/create_field.cc index f43fcfbb99d3..fb9daa3b8b03 100644 --- a/sql/create_field.cc +++ b/sql/create_field.cc @@ -1,4 +1,4 @@ -/* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License, version 2.0, @@ -279,11 +279,11 @@ bool Create_field::init( */ sql_type = fld_type = gcol_info->get_real_type(); if (pre_validate_value_generator_expr(gcol_info->expr_item, field_name, - true)) + VGS_GENERATED_COLUMN)) DBUG_RETURN(true); } else { if (pre_validate_value_generator_expr(m_default_val_expr->expr_item, - field_name, false)) + field_name, VGS_DEFAULT_EXPRESSION)) DBUG_RETURN(true); } } diff --git a/sql/dd/cache/dictionary_client.h b/sql/dd/cache/dictionary_client.h index 9a84acfeb990..d757c8d1c827 100644 --- a/sql/dd/cache/dictionary_client.h +++ b/sql/dd/cache/dictionary_client.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License, version 2.0, @@ -835,6 +835,23 @@ class Dictionary_client { bool *exists) MY_ATTRIBUTE((warn_unused_result)); + /** + Check if schema contains check constraint with specified name. + + @param schema Schema containing the check constraint. + @param check_cons_name Name of the check constraint. + @param [out] exists Set to true if check constraint with + the name provided exists in the + schema, false otherwise. + + @retval false No error. + @retval true Error. + */ + + bool check_constraint_exists(const Schema &schema, + const String_type &check_cons_name, + bool *exists); + /** Fetch the names of the components in the schema. Hidden components are ignored. E.g., Object with dd::Table::hidden() == true will be ignored. diff --git a/sql/dd/collection.cc b/sql/dd/collection.cc index 37ddbfa69e5f..b7d105ed5855 100644 --- a/sql/dd/collection.cc +++ b/sql/dd/collection.cc @@ -1,4 +1,4 @@ -/* Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License, version 2.0, @@ -31,6 +31,7 @@ #include "sql/dd/impl/raw/raw_record_set.h" // dd::Raw_record_set #include "sql/dd/impl/raw/raw_table.h" // dd::Raw_table #include "sql/dd/impl/types/abstract_table_impl.h" // IWYU pragma: keep +#include "sql/dd/impl/types/check_constraint_impl.h" // IWYU pragma: keep #include "sql/dd/impl/types/column_impl.h" // IWYU pragma: keep #include "sql/dd/impl/types/column_type_element_impl.h" // IWYU pragma: keep #include "sql/dd/impl/types/foreign_key_element_impl.h" // IWYU pragma: keep @@ -299,6 +300,8 @@ template dd::Partition_index * template Tablespace_file * &Collection::Collection_iterator::operator*(); template Trigger *&Collection::Collection_iterator::operator*(); +template Check_constraint * + &Collection::Collection_iterator::operator*(); template const Column * &Collection::Collection_const_iterator::operator*(); @@ -330,6 +333,8 @@ template const View_table * &Collection::Collection_const_iterator::operator*(); template const Trigger * &Collection::Collection_const_iterator::operator*(); +template const Check_constraint * + &Collection::Collection_const_iterator::operator*(); template bool Collection::restore_items( Abstract_table_impl *, Open_dictionary_tables_ctx *, Raw_table *, @@ -390,6 +395,9 @@ template bool Collection::restore_items( Table_impl *, Open_dictionary_tables_ctx *, Raw_table *, Object_key *, Trigger_order_comparator); +template bool Collection::restore_items( + Table_impl *, Open_dictionary_tables_ctx *, Raw_table *, Object_key *, + Check_constraint_order_comparator); template bool Collection::store_items(Open_dictionary_tables_ctx *); template bool Collection::store_items( @@ -418,6 +426,8 @@ template bool Collection::store_items( template bool Collection::store_items( Open_dictionary_tables_ctx *); template bool Collection::store_items(Open_dictionary_tables_ctx *); +template bool Collection::store_items( + Open_dictionary_tables_ctx *); template bool Collection::drop_items(Open_dictionary_tables_ctx *, Raw_table *, Object_key *) const; @@ -453,6 +463,8 @@ template bool Collection::drop_items(Open_dictionary_tables_ctx *, template bool Collection::drop_items(Open_dictionary_tables_ctx *, Raw_table *, Object_key *) const; +template bool Collection::drop_items( + Open_dictionary_tables_ctx *, Raw_table *, Object_key *) const; template void Collection::clear_all_items(); template void Collection::clear_all_items(); @@ -469,6 +481,7 @@ template void Collection::clear_all_items(); template void Collection::clear_all_items(); template void Collection::clear_all_items(); template void Collection::clear_all_items(); +template void Collection::clear_all_items(); template void Collection::clear_removed_items(); template void Collection::clear_removed_items(); @@ -484,6 +497,7 @@ template void Collection::clear_removed_items(); template void Collection::clear_removed_items(); template void Collection::clear_removed_items(); template void Collection::clear_removed_items(); +template void Collection::clear_removed_items(); template void Collection::remove(Column_impl *); template void Collection::remove( @@ -503,6 +517,7 @@ template void Collection::remove(Tablespace_file_impl *); template void Collection::remove(View_routine_impl *); template void Collection::remove(View_table_impl *); template void Collection::remove(Trigger_impl *); +template void Collection::remove(Check_constraint_impl *); template Collection::iterator Collection::find( const Column_impl *); @@ -534,6 +549,8 @@ template Collection::iterator Collection::find( const View_table_impl *); template Collection::iterator Collection::find( const Trigger_impl *); +template Collection::iterator +Collection::find(const Check_constraint_impl *); template const Collection::abstract_type *Collection::at( size_t n) const; @@ -582,6 +599,8 @@ template void Collection::deep_copy( Collection const &, View_impl *); template void Collection::deep_copy( Collection const &, Table_impl *); +template void Collection::deep_copy( + Collection const &, Table_impl *); /** @endcond diff --git a/sql/dd/dd_table.cc b/sql/dd/dd_table.cc index 302c59f69f55..07fbd5c055fa 100644 --- a/sql/dd/dd_table.cc +++ b/sql/dd/dd_table.cc @@ -1,4 +1,4 @@ -/* Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License, version 2.0, @@ -56,6 +56,7 @@ #include "sql/dd/properties.h" // dd::Properties #include "sql/dd/string_type.h" #include "sql/dd/types/abstract_table.h" +#include "sql/dd/types/check_constraint.h" // dd::Check_constraint #include "sql/dd/types/column.h" // dd::Column #include "sql/dd/types/column_type_element.h" // dd::Column_type_element #include "sql/dd/types/foreign_key.h" // dd::Foreign_key @@ -79,12 +80,14 @@ #include "sql/key_spec.h" #include "sql/log.h" #include "sql/mdl.h" +#include "sql/mem_root_array.h" #include "sql/my_decimal.h" #include "sql/mysqld.h" // lower_case_table_names #include "sql/partition_element.h" -#include "sql/partition_info.h" // partition_info -#include "sql/psi_memory_key.h" // key_memory_frm -#include "sql/sql_class.h" // THD +#include "sql/partition_info.h" // partition_info +#include "sql/psi_memory_key.h" // key_memory_frm +#include "sql/sql_check_constraint.h" // Sql_check_constraint_spec_list +#include "sql/sql_class.h" // THD #include "sql/sql_const.h" #include "sql/sql_lex.h" #include "sql/sql_list.h" @@ -1744,6 +1747,46 @@ static bool fill_dd_partition_from_create_info( return false; } +/** + Fill in check constraints metadata to the Table object from the list of + check constraint specifications. + + @param[in] thd Thread handle. + @param[in,out] tab_obj Table object where to store the info. + @param[in] check_cons_spec Check constraints specification list. + + @return false on success, else true. +*/ +bool fill_dd_check_constraints( + THD *thd, dd::Table *tab_obj, + const Sql_check_constraint_spec_list *check_cons_spec) { + if (check_cons_spec == nullptr) return false; + + for (auto &cc_spec : *check_cons_spec) { + Check_constraint *cc = tab_obj->add_check_constraint(); + + // Constraint name. + cc->set_name(cc_spec->name.str); + + // Constraint clause. + char buffer[256]; + String expr(buffer, sizeof(buffer), &my_charset_bin); + cc_spec->print_expr(thd, expr); + cc->set_check_clause(String_type(expr.c_ptr_safe())); + + // Prepare UTF8 expressions for INFORMATION_SCHEMA tables. + String expr_for_IS; + convert_and_print(&expr, &expr_for_IS, system_charset_info); + cc->set_check_clause_utf8( + String_type(expr_for_IS.ptr(), expr_for_IS.length())); + + // State. (enforced / not enforced) + cc->set_constraint_state(cc_spec->is_enforced); + } + + return false; +} + /** Convert old row type value to corresponding value in new row format enum used by DD framework. @@ -1890,7 +1933,8 @@ static bool fill_dd_table_from_create_info( const dd::String_type &schema_name, const HA_CREATE_INFO *create_info, const List &create_fields, const KEY *keyinfo, uint keys, Alter_info::enum_enable_or_disable keys_onoff, - const FOREIGN_KEY *fk_keyinfo, uint fk_keys, handler *file) { + const FOREIGN_KEY *fk_keyinfo, uint fk_keys, + const Sql_check_constraint_spec_list *check_cons_spec, handler *file) { // Table name must be set with the correct case depending on l_c_t_n tab_obj->set_name(table_case_name(create_info, table_name.c_str())); @@ -2089,6 +2133,9 @@ static bool fill_dd_table_from_create_info( fill_dd_indexes_from_keyinfo(thd, tab_obj, keys, keyinfo, create_fields, file); + // Add check constraints. + if (fill_dd_check_constraints(thd, tab_obj, check_cons_spec)) return true; + // Only add foreign key definitions for engines that support it. if (ha_check_storage_engine_flag(create_info->db_type, HTON_SUPPORTS_FOREIGN_KEYS)) { @@ -2202,7 +2249,8 @@ static std::unique_ptr create_dd_system_table( THD *thd, const dd::Schema &system_schema, const dd::String_type &table_name, HA_CREATE_INFO *create_info, const List &create_fields, const KEY *keyinfo, uint keys, - const FOREIGN_KEY *fk_keyinfo, uint fk_keys, handler *file, + const FOREIGN_KEY *fk_keyinfo, uint fk_keys, + const Sql_check_constraint_spec_list *check_cons_spec, handler *file, const dd::Object_table &dd_table) { // Create dd::Table object. std::unique_ptr tab_obj(system_schema.create_table(thd)); @@ -2215,7 +2263,7 @@ static std::unique_ptr create_dd_system_table( if (fill_dd_table_from_create_info( thd, tab_obj.get(), table_name, system_schema.name(), create_info, create_fields, keyinfo, keys, Alter_info::ENABLE, fk_keyinfo, fk_keys, - file)) + check_cons_spec, file)) return nullptr; /* @@ -2255,7 +2303,8 @@ std::unique_ptr create_dd_user_table( HA_CREATE_INFO *create_info, const List &create_fields, const KEY *keyinfo, uint keys, Alter_info::enum_enable_or_disable keys_onoff, - const FOREIGN_KEY *fk_keyinfo, uint fk_keys, handler *file) { + const FOREIGN_KEY *fk_keyinfo, uint fk_keys, + const Sql_check_constraint_spec_list *check_cons_spec, handler *file) { // Verify that this is not a dd table. DBUG_ASSERT( !dd::get_dictionary()->is_dd_table_name(sch_obj.name(), table_name)); @@ -2270,9 +2319,10 @@ std::unique_ptr create_dd_user_table( if (is_server_ps_table_name(sch_obj.name(), table_name)) performance_schema::set_PS_version_for_table(&tab_obj->options()); - if (fill_dd_table_from_create_info( - thd, tab_obj.get(), table_name, sch_obj.name(), create_info, - create_fields, keyinfo, keys, keys_onoff, fk_keyinfo, fk_keys, file)) + if (fill_dd_table_from_create_info(thd, tab_obj.get(), table_name, + sch_obj.name(), create_info, create_fields, + keyinfo, keys, keys_onoff, fk_keyinfo, + fk_keys, check_cons_spec, file)) return nullptr; return tab_obj; @@ -2283,24 +2333,27 @@ std::unique_ptr create_table( HA_CREATE_INFO *create_info, const List &create_fields, const KEY *keyinfo, uint keys, Alter_info::enum_enable_or_disable keys_onoff, - const FOREIGN_KEY *fk_keyinfo, uint fk_keys, handler *file) { + const FOREIGN_KEY *fk_keyinfo, uint fk_keys, + const Sql_check_constraint_spec_list *check_cons_spec, handler *file) { dd::Dictionary *dict = dd::get_dictionary(); const dd::Object_table *dd_table = dict->get_dd_table(sch_obj.name(), table_name); - return dd_table ? create_dd_system_table( - thd, sch_obj, table_name, create_info, create_fields, - keyinfo, keys, fk_keyinfo, fk_keys, file, *dd_table) - : create_dd_user_table(thd, sch_obj, table_name, create_info, - create_fields, keyinfo, keys, - keys_onoff, fk_keyinfo, fk_keys, file); + return dd_table + ? create_dd_system_table(thd, sch_obj, table_name, create_info, + create_fields, keyinfo, keys, fk_keyinfo, + fk_keys, check_cons_spec, file, *dd_table) + : create_dd_user_table(thd, sch_obj, table_name, create_info, + create_fields, keyinfo, keys, keys_onoff, + fk_keyinfo, fk_keys, check_cons_spec, file); } std::unique_ptr create_tmp_table( THD *thd, const dd::Schema &sch_obj, const dd::String_type &table_name, HA_CREATE_INFO *create_info, const List &create_fields, const KEY *keyinfo, uint keys, - Alter_info::enum_enable_or_disable keys_onoff, handler *file) { + Alter_info::enum_enable_or_disable keys_onoff, + const Sql_check_constraint_spec_list *check_cons_spec, handler *file) { // Create dd::Table object. std::unique_ptr tab_obj(sch_obj.create_table(thd)); @@ -2308,7 +2361,8 @@ std::unique_ptr create_tmp_table( if (fill_dd_table_from_create_info(thd, tab_obj.get(), table_name, sch_obj.name(), create_info, create_fields, - keyinfo, keys, keys_onoff, NULL, 0, file)) + keyinfo, keys, keys_onoff, NULL, 0, + check_cons_spec, file)) return nullptr; return tab_obj; @@ -2648,4 +2702,39 @@ bool has_primary_key(const Table &t) { return ix->type() == Index::IT_PRIMARY && !ix->is_hidden(); }); } + +bool is_generated_check_constraint_name(const char *table_name, + size_t table_name_length, + const char *cc_name, + size_t cc_name_length) { + // We assume that the name is generated if it starts with _chk_ + return ((cc_name_length > + table_name_length + sizeof(dd::CHECK_CONSTRAINT_NAME_SUBSTR) - 1) && + (memcmp(cc_name, table_name, table_name_length) == 0) && + (memcmp(cc_name + table_name_length, dd::CHECK_CONSTRAINT_NAME_SUBSTR, + sizeof(dd::CHECK_CONSTRAINT_NAME_SUBSTR) - 1) == 0)); +} + +bool rename_check_constraints(const char *old_table_name, dd::Table *new_tab) { + size_t old_table_name_length = strlen(old_table_name); + for (auto &cc : *new_tab->check_constraints()) { + if (is_generated_check_constraint_name( + old_table_name, old_table_name_length, cc->name().c_str(), + cc->name().length())) { + // Generate new name. + dd::String_type new_name(new_tab->name()); + new_name.append(cc->name().substr(old_table_name_length)); + if (check_string_char_length(to_lex_cstring(new_name.c_str()), "", + NAME_CHAR_LEN, system_charset_info, true)) { + my_error(ER_TOO_LONG_IDENT, MYF(0), new_name.c_str()); + return true; + } + // Set new name. + cc->set_name(new_name); + } + } + + return false; +} + } // namespace dd diff --git a/sql/dd/dd_table.h b/sql/dd/dd_table.h index cba03ca01912..5f0ee83c8420 100644 --- a/sql/dd/dd_table.h +++ b/sql/dd/dd_table.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License, version 2.0, @@ -44,6 +44,10 @@ class Schema; } // namespace dd struct TABLE; +class Sql_check_constraint_spec; +using Sql_check_constraint_spec_list = + Mem_root_array; + struct HA_CREATE_INFO; template class List; @@ -59,23 +63,26 @@ class Dictionary_client; static const char FIELD_NAME_SEPARATOR_CHAR = ';'; static const char FOREIGN_KEY_NAME_SUBSTR[] = "_ibfk_"; +static const char CHECK_CONSTRAINT_NAME_SUBSTR[] = "_chk_"; /** Prepares a dd::Table object from mysql_prepare_create_table() output and return it to the caller. This function creates a user table, as opposed to create_table() which can handle system tables as well. - @param thd Thread handle - @param sch_obj Schema. - @param table_name Table name. - @param create_info HA_CREATE_INFO describing the table to be created. - @param create_fields List of fields for the table. - @param keyinfo Array with descriptions of keys for the table. - @param keys Number of keys. - @param keys_onoff keys ON or OFF - @param fk_keyinfo Array with descriptions of foreign keys for the table. - @param fk_keys Number of foreign keys. - @param file handler instance for the table. + @param thd Thread handle + @param sch_obj Schema. + @param table_name Table name. + @param create_info HA_CREATE_INFO describing the table to be created. + @param create_fields List of fields for the table. + @param keyinfo Array with descriptions of keys for the table. + @param keys Number of keys. + @param keys_onoff keys ON or OFF + @param fk_keyinfo Array with descriptions of foreign keys for the + table. + @param fk_keys Number of foreign keys. + @param check_cons_spec Specification of check constraints for the table. + @param file handler instance for the table. @returns Constructed dd::Table object, or nullptr in case of an error. */ @@ -84,7 +91,8 @@ std::unique_ptr create_dd_user_table( HA_CREATE_INFO *create_info, const List &create_fields, const KEY *keyinfo, uint keys, Alter_info::enum_enable_or_disable keys_onoff, - const FOREIGN_KEY *fk_keyinfo, uint fk_keys, handler *file); + const FOREIGN_KEY *fk_keyinfo, uint fk_keys, + const Sql_check_constraint_spec_list *check_cons_spec, handler *file); /** Prepares a dd::Table object from mysql_prepare_create_table() output @@ -101,6 +109,7 @@ std::unique_ptr create_dd_user_table( @param fk_keyinfo Array with descriptions of foreign keys for the table. @param fk_keys Number of foreign keys. + @param check_cons_spec Specification of check constraints for the table. @param file handler instance for the table. @returns Constructed dd::Table object, or nullptr in case of an error. @@ -110,22 +119,24 @@ std::unique_ptr create_table( HA_CREATE_INFO *create_info, const List &create_fields, const KEY *keyinfo, uint keys, Alter_info::enum_enable_or_disable keys_onoff, - const FOREIGN_KEY *fk_keyinfo, uint fk_keys, handler *file); + const FOREIGN_KEY *fk_keyinfo, uint fk_keys, + const Sql_check_constraint_spec_list *check_cons_spec, handler *file); /** Prepares a dd::Table object for a temporary table from mysql_prepare_create_table() output. Doesn't update DD tables, instead returns dd::Table object to caller. - @param thd Thread handle. - @param sch_obj Schema. - @param table_name Table name. - @param create_info HA_CREATE_INFO describing the table to be created. - @param create_fields List of fields for the table. - @param keyinfo Array with descriptions of keys for the table. - @param keys Number of keys. - @param keys_onoff Enable or disable keys. - @param file handler instance for the table. + @param thd Thread handle. + @param sch_obj Schema. + @param table_name Table name. + @param create_info HA_CREATE_INFO describing the table to be created. + @param create_fields List of fields for the table. + @param keyinfo Array with descriptions of keys for the table. + @param keys Number of keys. + @param keys_onoff Enable or disable keys. + @param check_cons_spec Specification of check constraints for the table. + @param file handler instance for the table. @returns Constructed dd::Table object, or nullptr in case of an error. */ @@ -133,7 +144,8 @@ std::unique_ptr create_tmp_table( THD *thd, const dd::Schema &sch_obj, const dd::String_type &table_name, HA_CREATE_INFO *create_info, const List &create_fields, const KEY *keyinfo, uint keys, - Alter_info::enum_enable_or_disable keys_onoff, handler *file); + Alter_info::enum_enable_or_disable keys_onoff, + const Sql_check_constraint_spec_list *check_cons_spec, handler *file); ////////////////////////////////////////////////////////////////////////// // Function common to 'table' and 'view' objects @@ -404,5 +416,31 @@ Encrypt_result is_tablespace_encrypted(THD *thd, const dd::Table &t); */ bool has_primary_key(const Table &t); +/** + Check if name of check constraint is generated one. + + @param table_name Table name. + @param table_name_length Table name length. + @param cc_name Check constraint name. + @param cc_name_length Check constraint name length. + + @retval true If check constraint name is generated one. + @retval false Otherwise. +*/ +bool is_generated_check_constraint_name(const char *table_name, + size_t table_name_length, + const char *cc_name, + size_t cc_name_length); + +/** + Rename generated check constraint names to match the new name of the table. + + @param old_table_name Table name before rename. + @param new_tab New version of the table with new name set. + + @returns true if error, false otherwise. +*/ +bool rename_check_constraints(const char *old_table_name, dd::Table *new_tab); + } // namespace dd #endif // DD_TABLE_INCLUDED diff --git a/sql/dd/dd_version.h b/sql/dd/dd_version.h index 688df9a37b4b..c02c25a396a8 100644 --- a/sql/dd/dd_version.h +++ b/sql/dd/dd_version.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License, version 2.0, @@ -137,18 +137,25 @@ - Bug#24741307: add last_checked_for_upgrade column to msyql.tables table - 80014: Current + 80014: Published in 8.0.14 ---------------------------------------------------------------------------- Changes from version 80013: - Bug#28492272: Synchronize sql_mode in server with that in DD. - 80015: Next DD version number after the previous is public. + 80015: Current ---------------------------------------------------------------------------- Changes from version 80014: - - No changes, this version number is not active yet. + - WL#929 - CHECK CONSTRAINTS + New DD table check_constraints is introduced for the check + constraints metadata. + + + 80016: Next DD version number after the previous is public. + ---------------------------------------------------------------------------- + Changes from version 80015: If a new DD version is published in a MRU, that version may or may not @@ -160,9 +167,9 @@ */ namespace dd { -static const uint DD_VERSION = 80014; +static const uint DD_VERSION = 80015; -static const uint DD_VERSION_MINOR_DOWNGRADE_THRESHOLD = 80014; +static const uint DD_VERSION_MINOR_DOWNGRADE_THRESHOLD = 80015; } // namespace dd diff --git a/sql/dd/impl/bootstrap_ctx.h b/sql/dd/impl/bootstrap_ctx.h index c877d6ad22d3..d6b41bbf9348 100644 --- a/sql/dd/impl/bootstrap_ctx.h +++ b/sql/dd/impl/bootstrap_ctx.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License, version 2.0, @@ -55,6 +55,7 @@ static constexpr uint DD_VERSION_80011 = 80011; static constexpr uint DD_VERSION_80012 = 80012; static constexpr uint DD_VERSION_80013 = 80013; static constexpr uint DD_VERSION_80014 = 80014; +static constexpr uint DD_VERSION_80015 = 80015; /* Set of supported DD version labels. A supported DD version is a version @@ -65,7 +66,8 @@ static constexpr uint DD_VERSION_80014 = 80014; stored in the 'dd_properties' table by the server from which we downgrade. */ static std::set supported_dd_versions = { - DD_VERSION_80011, DD_VERSION_80012, DD_VERSION_80013, DD_VERSION_80014}; + DD_VERSION_80011, DD_VERSION_80012, DD_VERSION_80013, DD_VERSION_80014, + DD_VERSION_80015}; // Individual server version labels that we can refer to. static constexpr uint SERVER_VERSION_80011 = 80011; diff --git a/sql/dd/impl/bootstrapper.cc b/sql/dd/impl/bootstrapper.cc index 74e68671dca7..e9ca97bc5423 100644 --- a/sql/dd/impl/bootstrapper.cc +++ b/sql/dd/impl/bootstrapper.cc @@ -1,4 +1,4 @@ -/* Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License, version 2.0, @@ -1103,8 +1103,14 @@ bool sync_meta_data(THD *thd) { it != System_tables::instance()->end() && persisted_it != persisted_dd_tables.end(); ++it, ++persisted_it) { + /* + If we are in the process of upgrading, there may not be an entry + in the persisted_dd_tables for new tables that have been added after + the version we are upgrading from. + */ + if ((*persisted_it) == nullptr) continue; + if ((*it)->property() == System_tables::Types::CORE) { - DBUG_ASSERT((*it)->entity()->name() == (*persisted_it)->name()); dd::cache::Storage_adapter::instance()->core_store( thd, static_cast
((*persisted_it).get())); } diff --git a/sql/dd/impl/cache/dictionary_client.cc b/sql/dd/impl/cache/dictionary_client.cc index 2b6bed150935..202b46bbcfbb 100644 --- a/sql/dd/impl/cache/dictionary_client.cc +++ b/sql/dd/impl/cache/dictionary_client.cc @@ -1,4 +1,4 @@ -/* Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License, version 2.0, @@ -48,6 +48,7 @@ #include "sql/dd/impl/raw/raw_table.h" // Raw_table #include "sql/dd/impl/sdi.h" // dd::sdi::drop_after_update #include "sql/dd/impl/tables/character_sets.h" // create_name_key() +#include "sql/dd/impl/tables/check_constraints.h" // check_constraint_exists #include "sql/dd/impl/tables/collations.h" // create_name_key() #include "sql/dd/impl/tables/column_statistics.h" // create_name_key() #include "sql/dd/impl/tables/events.h" // create_name_key() @@ -1868,6 +1869,31 @@ bool Dictionary_client::check_foreign_key_exists( return false; } +bool Dictionary_client::check_constraint_exists( + const Schema &schema, const String_type &check_cons_name, bool *exists) { +#ifndef DBUG_OFF + char schema_name_buf[NAME_LEN + 1]; + char check_cons_name_buff[NAME_LEN + 1]; + my_stpcpy(check_cons_name_buff, check_cons_name.c_str()); + my_casedn_str(system_charset_info, check_cons_name_buff); + + DBUG_ASSERT(m_thd->mdl_context.owns_equal_or_stronger_lock( + MDL_key::CHECK_CONSTRAINT, + dd::Object_table_definition_impl::fs_name_case(schema.name(), + schema_name_buf), + check_cons_name_buff, MDL_EXCLUSIVE)); +#endif + + // Get info directly from the tables. + if (tables::Check_constraints::check_constraint_exists( + m_thd, schema.id(), check_cons_name, exists)) { + DBUG_ASSERT(m_thd->is_error() || m_thd->killed); + return true; + } + + return false; +} + template bool fetch_raw_record(THD *thd, std::function const &processor) { diff --git a/sql/dd/impl/system_registry.cc b/sql/dd/impl/system_registry.cc index 51be063b0365..16ee9aa635bf 100644 --- a/sql/dd/impl/system_registry.cc +++ b/sql/dd/impl/system_registry.cc @@ -1,4 +1,4 @@ -/* Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License, version 2.0, @@ -22,7 +22,8 @@ #include "sql/dd/impl/system_registry.h" -#include "sql/dd/impl/system_views/character_sets.h" // Character_sets +#include "sql/dd/impl/system_views/character_sets.h" // Character_sets +#include "sql/dd/impl/system_views/check_constraints.h" // Check_constraints #include "sql/dd/impl/system_views/collation_charset_applicability.h" // Collati... #include "sql/dd/impl/system_views/collations.h" // Collations #include "sql/dd/impl/system_views/column_statistics.h" // Column_statistics @@ -55,6 +56,7 @@ #include "sql/dd/impl/tables/catalogs.h" // Catalog #include "sql/dd/impl/tables/character_sets.h" // Character_sets +#include "sql/dd/impl/tables/check_constraints.h" // Check_constraints #include "sql/dd/impl/tables/collations.h" // Collations #include "sql/dd/impl/tables/column_statistics.h" // Column_statistics #include "sql/dd/impl/tables/column_type_elements.h" // Column_type_elements @@ -154,6 +156,7 @@ void System_tables::add_remaining_dd_tables() { register_table(core); register_table(core); + register_table(core); register_table(core); register_table(core); register_table(core); @@ -233,6 +236,7 @@ void System_views::init() { dd::System_views::Types is = dd::System_views::Types::INFORMATION_SCHEMA; register_view(is); + register_view(is); register_view(is); register_view(is); register_view(is); diff --git a/sql/dd/impl/system_views/check_constraints.cc b/sql/dd/impl/system_views/check_constraints.cc new file mode 100644 index 000000000000..0076ad7b273f --- /dev/null +++ b/sql/dd/impl/system_views/check_constraints.cc @@ -0,0 +1,54 @@ +/* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License, version 2.0, + as published by the Free Software Foundation. + + This program is also distributed with certain software (including + but not limited to OpenSSL) that is licensed under separate terms, + as designated in a particular file or component or in included license + documentation. The authors of MySQL hereby grant you an additional + permission to link the program and your derivative works with the + separately licensed software that they have included with MySQL. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License, version 2.0, for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ + +#include "sql/dd/impl/system_views/check_constraints.h" + +namespace dd { +namespace system_views { + +const Check_constraints &Check_constraints::instance() { + static Check_constraints *s_instance = new Check_constraints(); + return *s_instance; +} + +Check_constraints::Check_constraints() { + m_target_def.set_view_name(view_name()); + + m_target_def.add_field(FIELD_CONSTRAINT_CATALOG, "CONSTRAINT_CATALOG", + "cat.name" + m_target_def.fs_name_collation()); + m_target_def.add_field(FIELD_CONSTRAINT_SCHEMA, "CONSTRAINT_SCHEMA", + "sch.name" + m_target_def.fs_name_collation()); + m_target_def.add_field(FIELD_CONSTRAINT_NAME, "CONSTRAINT_NAME", "cc.name"); + m_target_def.add_field(FIELD_CHECK_CLAUSE, "CHECK_CLAUSE", + "cc.check_clause_utf8"); + + m_target_def.add_from("mysql.check_constraints cc"); + m_target_def.add_from("JOIN mysql.tables tbl ON cc.table_id=tbl.id"); + m_target_def.add_from("JOIN mysql.schemata sch ON tbl.schema_id=sch.id"); + m_target_def.add_from("JOIN mysql.catalogs cat ON cat.id=sch.catalog_id"); + + m_target_def.add_where("CAN_ACCESS_TABLE(sch.name, tbl.name)"); + m_target_def.add_where("AND IS_VISIBLE_DD_OBJECT(tbl.hidden)"); +} + +} // namespace system_views +} // namespace dd diff --git a/sql/dd/impl/system_views/check_constraints.h b/sql/dd/impl/system_views/check_constraints.h new file mode 100644 index 000000000000..fab6a3f479f9 --- /dev/null +++ b/sql/dd/impl/system_views/check_constraints.h @@ -0,0 +1,65 @@ +/* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License, version 2.0, + as published by the Free Software Foundation. + + This program is also distributed with certain software (including + but not limited to OpenSSL) that is licensed under separate terms, + as designated in a particular file or component or in included license + documentation. The authors of MySQL hereby grant you an additional + permission to link the program and your derivative works with the + separately licensed software that they have included with MySQL. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License, version 2.0, for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ + +#ifndef DD_SYSTEM_VIEWS__CHECK_CONSTRAINTS_INCLUDED +#define DD_SYSTEM_VIEWS__CHECK_CONSTRAINTS_INCLUDED + +#include "sql/dd/impl/system_views/system_view_definition_impl.h" +#include "sql/dd/impl/system_views/system_view_impl.h" +#include "sql/dd/string_type.h" + +namespace dd { +namespace system_views { + +/* + The class representing INFORMATION_SCHEMA.CHECK_CONSTRAINTS system view + definition. +*/ + +class Check_constraints + : public System_view_impl { + public: + enum enum_fields { + FIELD_CONSTRAINT_CATALOG, + FIELD_CONSTRAINT_SCHEMA, + FIELD_CONSTRAINT_NAME, + FIELD_CHECK_CLAUSE + }; + + Check_constraints(); + + static const Check_constraints &instance(); + + static const String_type &view_name() { + static String_type s_view_name("CHECK_CONSTRAINTS"); + return s_view_name; + } + + virtual const String_type &name() const { + return Check_constraints::view_name(); + } +}; + +} // namespace system_views +} // namespace dd + +#endif // DD_SYSTEM_VIEWS__CHECK_CONSTRAINTS_INCLUDED diff --git a/sql/dd/impl/system_views/key_column_usage.cc b/sql/dd/impl/system_views/key_column_usage.cc index 46a64a813474..f4cc86af238e 100644 --- a/sql/dd/impl/system_views/key_column_usage.cc +++ b/sql/dd/impl/system_views/key_column_usage.cc @@ -1,4 +1,4 @@ -/* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License, version 2.0, @@ -37,93 +37,91 @@ const Key_column_usage &Key_column_usage::instance() { Key_column_usage::Key_column_usage() { m_target_def.set_view_name(view_name()); - System_view_select_definition_impl *first_select, *second_select; - first_select = m_target_def.get_first_select(); - second_select = m_target_def.get_second_select(); - // First SELECT for UNION - - first_select->add_field(FIELD_CONSTRAINT_CATALOG, "CONSTRAINT_CATALOG", - "cat.name" + m_target_def.fs_name_collation()); - first_select->add_field(FIELD_CONSTRAINT_SCHEMA, "CONSTRAINT_SCHEMA", - "sch.name" + m_target_def.fs_name_collation()); - first_select->add_field(FIELD_CONSTRAINT_NAME, "CONSTRAINT_NAME", "idx.name"); - first_select->add_field(FIELD_TABLE_CATALOG, "TABLE_CATALOG", - "cat.name" + m_target_def.fs_name_collation()); - first_select->add_field(FIELD_TABLE_SCHEMA, "TABLE_SCHEMA", - "sch.name" + m_target_def.fs_name_collation()); - first_select->add_field(FIELD_TABLE_NAME, "TABLE_NAME", - "tbl.name" + m_target_def.fs_name_collation()); - first_select->add_field(FIELD_COLUMN_NAME, "COLUMN_NAME", - "col.name COLLATE utf8_tolower_ci"); - first_select->add_field(FIELD_ORDINAL_POSITION, "ORDINAL_POSITION", - "icu.ordinal_position"); - first_select->add_field(FIELD_POSITION_IN_UNIQUE_CONSTRAINT, - "POSITION_IN_UNIQUE_CONSTRAINT", "NULL"); - first_select->add_field(FIELD_REFERENCED_TABLE_SCHEMA, - "REFERENCED_TABLE_SCHEMA", "NULL"); - first_select->add_field(FIELD_REFERENCED_TABLE_NAME, "REFERENCED_TABLE_NAME", - "NULL"); - first_select->add_field(FIELD_REFERENCED_COLUMN_NAME, - "REFERENCED_COLUMN_NAME", "NULL"); - - first_select->add_from("mysql.indexes idx"); - first_select->add_from("JOIN mysql.tables tbl ON idx.table_id=tbl.id"); - first_select->add_from("JOIN mysql.schemata sch ON tbl.schema_id=sch.id"); - first_select->add_from("JOIN mysql.catalogs cat ON cat.id=sch.catalog_id"); - first_select->add_from( + System_view_select_definition_impl &first_select = m_target_def.get_select(); + + first_select.add_field(FIELD_CONSTRAINT_CATALOG, "CONSTRAINT_CATALOG", + "cat.name" + m_target_def.fs_name_collation()); + first_select.add_field(FIELD_CONSTRAINT_SCHEMA, "CONSTRAINT_SCHEMA", + "sch.name" + m_target_def.fs_name_collation()); + first_select.add_field(FIELD_CONSTRAINT_NAME, "CONSTRAINT_NAME", "idx.name"); + first_select.add_field(FIELD_TABLE_CATALOG, "TABLE_CATALOG", + "cat.name" + m_target_def.fs_name_collation()); + first_select.add_field(FIELD_TABLE_SCHEMA, "TABLE_SCHEMA", + "sch.name" + m_target_def.fs_name_collation()); + first_select.add_field(FIELD_TABLE_NAME, "TABLE_NAME", + "tbl.name" + m_target_def.fs_name_collation()); + first_select.add_field(FIELD_COLUMN_NAME, "COLUMN_NAME", + "col.name COLLATE utf8_tolower_ci"); + first_select.add_field(FIELD_ORDINAL_POSITION, "ORDINAL_POSITION", + "icu.ordinal_position"); + first_select.add_field(FIELD_POSITION_IN_UNIQUE_CONSTRAINT, + "POSITION_IN_UNIQUE_CONSTRAINT", "NULL"); + first_select.add_field(FIELD_REFERENCED_TABLE_SCHEMA, + "REFERENCED_TABLE_SCHEMA", "NULL"); + first_select.add_field(FIELD_REFERENCED_TABLE_NAME, "REFERENCED_TABLE_NAME", + "NULL"); + first_select.add_field(FIELD_REFERENCED_COLUMN_NAME, "REFERENCED_COLUMN_NAME", + "NULL"); + + first_select.add_from("mysql.indexes idx"); + first_select.add_from("JOIN mysql.tables tbl ON idx.table_id=tbl.id"); + first_select.add_from("JOIN mysql.schemata sch ON tbl.schema_id=sch.id"); + first_select.add_from("JOIN mysql.catalogs cat ON cat.id=sch.catalog_id"); + first_select.add_from( "JOIN mysql.index_column_usage icu" " ON icu.index_id=idx.id"); - first_select->add_from( + first_select.add_from( "JOIN mysql.columns col ON icu.column_id=col.id" " AND idx.type IN ('PRIMARY', 'UNIQUE')"); - first_select->add_where("CAN_ACCESS_COLUMN(sch.name, tbl.name, col.name)"); - first_select->add_where( + first_select.add_where("CAN_ACCESS_COLUMN(sch.name, tbl.name, col.name)"); + first_select.add_where( "AND IS_VISIBLE_DD_OBJECT(tbl.hidden, " "col.hidden <> 'Visible' OR idx.hidden OR icu.hidden)"); // Second SELECT for UNION + System_view_select_definition_impl &second_select = m_target_def.get_select(); - second_select->add_field(FIELD_CONSTRAINT_CATALOG, "CONSTRAINT_CATALOG", - "cat.name" + m_target_def.fs_name_collation()); - second_select->add_field(FIELD_CONSTRAINT_SCHEMA, "CONSTRAINT_SCHEMA", - "sch.name" + m_target_def.fs_name_collation()); - second_select->add_field(FIELD_CONSTRAINT_NAME, "CONSTRAINT_NAME", - "fk.name COLLATE utf8_tolower_ci"); - second_select->add_field(FIELD_TABLE_CATALOG, "TABLE_CATALOG", - "cat.name" + m_target_def.fs_name_collation()); - second_select->add_field(FIELD_TABLE_SCHEMA, "TABLE_SCHEMA", - "sch.name" + m_target_def.fs_name_collation()); - second_select->add_field(FIELD_TABLE_NAME, "TABLE_NAME", - "tbl.name" + m_target_def.fs_name_collation()); - second_select->add_field(FIELD_COLUMN_NAME, "COLUMN_NAME", - "col.name COLLATE utf8_tolower_ci"); - second_select->add_field(FIELD_ORDINAL_POSITION, "ORDINAL_POSITION", - "fkcu.ordinal_position"); - second_select->add_field(FIELD_POSITION_IN_UNIQUE_CONSTRAINT, - "POSITION_IN_UNIQUE_CONSTRAINT", - "fkcu.ordinal_position"); - second_select->add_field(FIELD_REFERENCED_TABLE_SCHEMA, - "REFERENCED_TABLE_SCHEMA", - "fk.referenced_table_schema"); - second_select->add_field(FIELD_REFERENCED_TABLE_NAME, "REFERENCED_TABLE_NAME", - "fk.referenced_table_name"); - second_select->add_field(FIELD_REFERENCED_COLUMN_NAME, - "REFERENCED_COLUMN_NAME", - "fkcu.referenced_column_name"); - - second_select->add_from("mysql.foreign_keys fk"); - second_select->add_from("JOIN mysql.tables tbl ON fk.table_id=tbl.id"); - second_select->add_from( + second_select.add_field(FIELD_CONSTRAINT_CATALOG, "CONSTRAINT_CATALOG", + "cat.name" + m_target_def.fs_name_collation()); + second_select.add_field(FIELD_CONSTRAINT_SCHEMA, "CONSTRAINT_SCHEMA", + "sch.name" + m_target_def.fs_name_collation()); + second_select.add_field(FIELD_CONSTRAINT_NAME, "CONSTRAINT_NAME", + "fk.name COLLATE utf8_tolower_ci"); + second_select.add_field(FIELD_TABLE_CATALOG, "TABLE_CATALOG", + "cat.name" + m_target_def.fs_name_collation()); + second_select.add_field(FIELD_TABLE_SCHEMA, "TABLE_SCHEMA", + "sch.name" + m_target_def.fs_name_collation()); + second_select.add_field(FIELD_TABLE_NAME, "TABLE_NAME", + "tbl.name" + m_target_def.fs_name_collation()); + second_select.add_field(FIELD_COLUMN_NAME, "COLUMN_NAME", + "col.name COLLATE utf8_tolower_ci"); + second_select.add_field(FIELD_ORDINAL_POSITION, "ORDINAL_POSITION", + "fkcu.ordinal_position"); + second_select.add_field(FIELD_POSITION_IN_UNIQUE_CONSTRAINT, + "POSITION_IN_UNIQUE_CONSTRAINT", + "fkcu.ordinal_position"); + second_select.add_field(FIELD_REFERENCED_TABLE_SCHEMA, + "REFERENCED_TABLE_SCHEMA", + "fk.referenced_table_schema"); + second_select.add_field(FIELD_REFERENCED_TABLE_NAME, "REFERENCED_TABLE_NAME", + "fk.referenced_table_name"); + second_select.add_field(FIELD_REFERENCED_COLUMN_NAME, + "REFERENCED_COLUMN_NAME", + "fkcu.referenced_column_name"); + + second_select.add_from("mysql.foreign_keys fk"); + second_select.add_from("JOIN mysql.tables tbl ON fk.table_id=tbl.id"); + second_select.add_from( "JOIN mysql.foreign_key_column_usage fkcu" " ON fkcu.foreign_key_id=fk.id"); - second_select->add_from("JOIN mysql.schemata sch ON fk.schema_id=sch.id"); - second_select->add_from("JOIN mysql.catalogs cat ON cat.id=sch.catalog_id"); - second_select->add_from("JOIN mysql.columns col ON fkcu.column_id=col.id"); + second_select.add_from("JOIN mysql.schemata sch ON fk.schema_id=sch.id"); + second_select.add_from("JOIN mysql.catalogs cat ON cat.id=sch.catalog_id"); + second_select.add_from("JOIN mysql.columns col ON fkcu.column_id=col.id"); - second_select->add_where("CAN_ACCESS_COLUMN(sch.name, tbl.name, col.name)"); - second_select->add_where( + second_select.add_where("CAN_ACCESS_COLUMN(sch.name, tbl.name, col.name)"); + second_select.add_where( "AND IS_VISIBLE_DD_OBJECT(tbl.hidden, col.hidden <> 'Visible')"); } diff --git a/sql/dd/impl/system_views/system_view_definition_impl.h b/sql/dd/impl/system_views/system_view_definition_impl.h index 65e489613861..f931736f8b71 100644 --- a/sql/dd/impl/system_views/system_view_definition_impl.h +++ b/sql/dd/impl/system_views/system_view_definition_impl.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License, version 2.0, @@ -24,6 +24,7 @@ #define DD_SYSTEM_VIEWS__SYSTEM_VIEW_DEFINITION_IMPL_INCLUDED #include +#include #include #include "sql/dd/string_type.h" // dd::String_type @@ -210,37 +211,42 @@ class System_view_select_definition_impl : public System_view_definition_impl { class System_view_union_definition_impl : public System_view_definition_impl { public: /** - Get the object for first SELECT view definition to be used in UNION. + Get the object for a SELECT definition to be used in the UNION. - @return The System_view_select_definition_impl*. + @return The System_view_select_definition_impl&. */ - System_view_select_definition_impl *get_first_select() { - return &m_first_select; - } - - /** - Get the object for second SELECT view definition to be used in UNION. - - @return The System_view_select_definition_impl*. - */ - System_view_select_definition_impl *get_second_select() { - return &m_second_select; + System_view_select_definition_impl &get_select() { + m_selects.push_back( + Select_definition(new System_view_select_definition_impl)); + return *(m_selects.back().get()); } virtual String_type build_ddl_create_view() const { Stringstream_type ss; - ss << "CREATE OR REPLACE DEFINER=`mysql.infoschema`@`localhost` VIEW " - << "information_schema." << view_name() << " AS " - << "(" << m_first_select.build_select_query() << ")" - << " UNION " - << "(" << m_second_select.build_select_query() << ")"; + bool first_select = true; + // Union definition must have minimum two SELECTs. + DBUG_ASSERT(m_selects.size() >= 2); + + for (auto &select : m_selects) { + if (first_select) { + ss << "CREATE OR REPLACE DEFINER=`mysql.infoschema`@`localhost` VIEW " + << "information_schema." << view_name() << " AS " + << "(" << select->build_select_query() << ")"; + first_select = false; + } else { + ss << " UNION " + << "(" << select->build_select_query() << ")"; + } + } return ss.str(); } private: - // Member that holds two SELECT's used for UNION - System_view_select_definition_impl m_first_select, m_second_select; + using Select_definition = std::unique_ptr; + + // Member holds SELECT's used for the UNION + std::vector m_selects; }; } // namespace system_views diff --git a/sql/dd/impl/system_views/table_constraints.cc b/sql/dd/impl/system_views/table_constraints.cc index efb7a7eacfe9..4c8f76755be2 100644 --- a/sql/dd/impl/system_views/table_constraints.cc +++ b/sql/dd/impl/system_views/table_constraints.cc @@ -1,4 +1,4 @@ -/* Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License, version 2.0, @@ -37,56 +37,79 @@ const Table_constraints &Table_constraints::instance() { Table_constraints::Table_constraints() { m_target_def.set_view_name(view_name()); - System_view_select_definition_impl *first_select, *second_select; - first_select = m_target_def.get_first_select(); - second_select = m_target_def.get_second_select(); - // First SELECT for UNION - - first_select->add_field(FIELD_CONSTRAINT_CATALOG, "CONSTRAINT_CATALOG", - "cat.name" + m_target_def.fs_name_collation()); - first_select->add_field(FIELD_CONSTRAINT_SCHEMA, "CONSTRAINT_SCHEMA", - "sch.name" + m_target_def.fs_name_collation()); - first_select->add_field(FIELD_CONSTRAINT_NAME, "CONSTRAINT_NAME", "idx.name"); - first_select->add_field(FIELD_TABLE_SCHEMA, "TABLE_SCHEMA", - "sch.name" + m_target_def.fs_name_collation()); - first_select->add_field(FIELD_TABLE_NAME, "TABLE_NAME", - "tbl.name" + m_target_def.fs_name_collation()); - first_select->add_field(FIELD_CONSTRAINT_TYPE, "CONSTRAINT_TYPE", - "IF (idx.type='PRIMARY', 'PRIMARY KEY', idx.type)"); - - first_select->add_from("mysql.indexes idx"); - first_select->add_from("JOIN mysql.tables tbl ON idx.table_id=tbl.id"); - first_select->add_from("JOIN mysql.schemata sch ON tbl.schema_id=sch.id"); - first_select->add_from( + System_view_select_definition_impl &first_select = m_target_def.get_select(); + + first_select.add_field(FIELD_CONSTRAINT_CATALOG, "CONSTRAINT_CATALOG", + "cat.name" + m_target_def.fs_name_collation()); + first_select.add_field(FIELD_CONSTRAINT_SCHEMA, "CONSTRAINT_SCHEMA", + "sch.name" + m_target_def.fs_name_collation()); + first_select.add_field(FIELD_CONSTRAINT_NAME, "CONSTRAINT_NAME", "idx.name"); + first_select.add_field(FIELD_TABLE_SCHEMA, "TABLE_SCHEMA", + "sch.name" + m_target_def.fs_name_collation()); + first_select.add_field(FIELD_TABLE_NAME, "TABLE_NAME", + "tbl.name" + m_target_def.fs_name_collation()); + first_select.add_field(FIELD_CONSTRAINT_TYPE, "CONSTRAINT_TYPE", + "IF (idx.type='PRIMARY', 'PRIMARY KEY', idx.type)"); + first_select.add_field(FIELD_ENFORCED, "ENFORCED", "'YES'"); + + first_select.add_from("mysql.indexes idx"); + first_select.add_from("JOIN mysql.tables tbl ON idx.table_id=tbl.id"); + first_select.add_from("JOIN mysql.schemata sch ON tbl.schema_id=sch.id"); + first_select.add_from( "JOIN mysql.catalogs cat ON cat.id=sch.catalog_id" " AND idx.type IN ('PRIMARY', 'UNIQUE')"); - first_select->add_where("CAN_ACCESS_TABLE(sch.name, tbl.name)"); - first_select->add_where("AND IS_VISIBLE_DD_OBJECT(tbl.hidden, idx.hidden)"); + first_select.add_where("CAN_ACCESS_TABLE(sch.name, tbl.name)"); + first_select.add_where("AND IS_VISIBLE_DD_OBJECT(tbl.hidden, idx.hidden)"); // Second SELECT for UNION + System_view_select_definition_impl &second_select = m_target_def.get_select(); - second_select->add_field(FIELD_CONSTRAINT_CATALOG, "CONSTRAINT_CATALOG", - "cat.name" + m_target_def.fs_name_collation()); - second_select->add_field(FIELD_CONSTRAINT_SCHEMA, "CONSTRAINT_SCHEMA", - "sch.name" + m_target_def.fs_name_collation()); - second_select->add_field(FIELD_CONSTRAINT_NAME, "CONSTRAINT_NAME", - "fk.name COLLATE utf8_tolower_ci"); - second_select->add_field(FIELD_TABLE_SCHEMA, "TABLE_SCHEMA", - "sch.name" + m_target_def.fs_name_collation()); - second_select->add_field(FIELD_TABLE_NAME, "TABLE_NAME", - "tbl.name" + m_target_def.fs_name_collation()); - second_select->add_field(FIELD_CONSTRAINT_TYPE, "CONSTRAINT_TYPE", - "'FOREIGN KEY'"); - - second_select->add_from("mysql.foreign_keys fk"); - second_select->add_from("JOIN mysql.tables tbl ON fk.table_id=tbl.id"); - second_select->add_from("JOIN mysql.schemata sch ON tbl.schema_id=sch.id"); - second_select->add_from("JOIN mysql.catalogs cat ON cat.id=sch.catalog_id"); - - second_select->add_where("CAN_ACCESS_TABLE(sch.name, tbl.name)"); - second_select->add_where("AND IS_VISIBLE_DD_OBJECT(tbl.hidden)"); + second_select.add_field(FIELD_CONSTRAINT_CATALOG, "CONSTRAINT_CATALOG", + "cat.name" + m_target_def.fs_name_collation()); + second_select.add_field(FIELD_CONSTRAINT_SCHEMA, "CONSTRAINT_SCHEMA", + "sch.name" + m_target_def.fs_name_collation()); + second_select.add_field(FIELD_CONSTRAINT_NAME, "CONSTRAINT_NAME", + "fk.name COLLATE utf8_tolower_ci"); + second_select.add_field(FIELD_TABLE_SCHEMA, "TABLE_SCHEMA", + "sch.name" + m_target_def.fs_name_collation()); + second_select.add_field(FIELD_TABLE_NAME, "TABLE_NAME", + "tbl.name" + m_target_def.fs_name_collation()); + second_select.add_field(FIELD_CONSTRAINT_TYPE, "CONSTRAINT_TYPE", + "'FOREIGN KEY'"); + second_select.add_field(FIELD_ENFORCED, "ENFORCED", "'YES'"); + + second_select.add_from("mysql.foreign_keys fk"); + second_select.add_from("JOIN mysql.tables tbl ON fk.table_id=tbl.id"); + second_select.add_from("JOIN mysql.schemata sch ON tbl.schema_id=sch.id"); + second_select.add_from("JOIN mysql.catalogs cat ON cat.id=sch.catalog_id"); + + second_select.add_where("CAN_ACCESS_TABLE(sch.name, tbl.name)"); + second_select.add_where("AND IS_VISIBLE_DD_OBJECT(tbl.hidden)"); + + // Third SELECT for UNION + System_view_select_definition_impl &third_select = m_target_def.get_select(); + + third_select.add_field(FIELD_CONSTRAINT_CATALOG, "CONSTRAINT_CATALOG", + "cat.name" + m_target_def.fs_name_collation()); + third_select.add_field(FIELD_CONSTRAINT_SCHEMA, "CONSTRAINT_SCHEMA", + "sch.name" + m_target_def.fs_name_collation()); + third_select.add_field(FIELD_CONSTRAINT_NAME, "CONSTRAINT_NAME", "cc.name"); + third_select.add_field(FIELD_TABLE_SCHEMA, "TABLE_SCHEMA", + "sch.name" + m_target_def.fs_name_collation()); + third_select.add_field(FIELD_TABLE_NAME, "TABLE_NAME", + "tbl.name" + m_target_def.fs_name_collation()); + third_select.add_field(FIELD_CONSTRAINT_TYPE, "CONSTRAINT_TYPE", "'CHECK'"); + third_select.add_field(FIELD_ENFORCED, "ENFORCED", "cc.enforced"); + + third_select.add_from("mysql.check_constraints cc"); + third_select.add_from("JOIN mysql.tables tbl ON cc.table_id=tbl.id"); + third_select.add_from("JOIN mysql.schemata sch ON tbl.schema_id=sch.id"); + third_select.add_from("JOIN mysql.catalogs cat ON cat.id=sch.catalog_id"); + + third_select.add_where("CAN_ACCESS_TABLE(sch.name, tbl.name)"); + third_select.add_where("AND IS_VISIBLE_DD_OBJECT(tbl.hidden)"); } } // namespace system_views diff --git a/sql/dd/impl/system_views/table_constraints.h b/sql/dd/impl/system_views/table_constraints.h index e46ea6c0005f..a287ce4a8476 100644 --- a/sql/dd/impl/system_views/table_constraints.h +++ b/sql/dd/impl/system_views/table_constraints.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License, version 2.0, @@ -43,7 +43,8 @@ class Table_constraints FIELD_CONSTRAINT_NAME, FIELD_TABLE_SCHEMA, FIELD_TABLE_NAME, - FIELD_CONSTRAINT_TYPE + FIELD_CONSTRAINT_TYPE, + FIELD_ENFORCED }; Table_constraints(); diff --git a/sql/dd/impl/tables/check_constraints.cc b/sql/dd/impl/tables/check_constraints.cc new file mode 100644 index 000000000000..7041e04f7a7c --- /dev/null +++ b/sql/dd/impl/tables/check_constraints.cc @@ -0,0 +1,132 @@ +/* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License, version 2.0, + as published by the Free Software Foundation. + + This program is also distributed with certain software (including + but not limited to OpenSSL) that is licensed under separate terms, + as designated in a particular file or component or in included license + documentation. The authors of MySQL hereby grant you an additional + permission to link the program and your derivative works with the + separately licensed software that they have included with MySQL. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License, version 2.0, for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ + +#include "sql/dd/impl/tables/check_constraints.h" + +#include + +#include "sql/dd/impl/raw/object_keys.h" // dd::Parent_id_range_key +#include "sql/dd/impl/raw/raw_record.h" // dd::Raw_record +#include "sql/dd/impl/raw/raw_table.h" // dd::Raw_table +#include "sql/dd/impl/transaction_impl.h" // Transaction_ro +#include "sql/dd/impl/types/object_table_definition_impl.h" + +namespace dd { +namespace tables { + +/////////////////////////////////////////////////////////////////////////// + +const Check_constraints &Check_constraints::instance() { + static Check_constraints *s_instance = new (std::nothrow) Check_constraints(); + return *s_instance; +} + +/////////////////////////////////////////////////////////////////////////// + +const CHARSET_INFO *Check_constraints::name_collation() { + return &my_charset_utf8_tolower_ci; +} + +/////////////////////////////////////////////////////////////////////////// + +Check_constraints::Check_constraints() { + m_target_def.set_table_name("check_constraints"); + + m_target_def.add_field(FIELD_ID, "FIELD_ID", + "id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT"); + m_target_def.add_field(FIELD_SCHEMA_ID, "FIELD_SCHEMA_ID", + "schema_id BIGINT UNSIGNED NOT NULL"); + m_target_def.add_field(FIELD_TABLE_ID, "FIELD_TABLE_ID", + "table_id BIGINT UNSIGNED NOT NULL"); + m_target_def.add_field(FIELD_NAME, "FIELD_NAME", + "name VARCHAR(64) NOT NULL COLLATE " + + String_type(name_collation()->name)); + m_target_def.add_field(FIELD_ENFORCED, "FIELD_ENFORCED", + "enforced ENUM('NO', 'YES') NOT NULL"); + m_target_def.add_field(FIELD_CHECK_CLAUSE, "FIELD_CHECK_CLAUSE", + "check_clause LONGBLOB NOT NULL"); + m_target_def.add_field(FIELD_CHECK_CLAUSE_UTF8, "FIELD_CHECK_CLAUSE_UTF8", + "check_clause_utf8 LONGTEXT NOT NULL"); + + m_target_def.add_index(INDEX_PK_ID, "INDEX_PK_ID", "PRIMARY KEY (id)"); + m_target_def.add_index(INDEX_UK_SCHEMA_ID_NAME, "INDEX_UK_SCHEMA_ID_NAME", + "UNIQUE KEY (schema_id, name)"); + m_target_def.add_index(INDEX_UK_TABLE_ID_NAME, "INDEX_UK_TABLE_ID_NAME", + "UNIQUE KEY (table_id, name)"); + + m_target_def.add_foreign_key(FK_SCHEMA_ID, "FK_SCHEMA_ID", + "FOREIGN KEY (schema_id) REFERENCES " + "schemata(id)"); + m_target_def.add_foreign_key(FK_TABLE_ID, "FK_TABLE_ID", + "FOREIGN KEY (table_id) REFERENCES " + "tables(id)"); +} + +/////////////////////////////////////////////////////////////////////////// + +Object_key *Check_constraints::create_key_by_table_id(Object_id table_id) { + return new (std::nothrow) + Parent_id_range_key(INDEX_UK_TABLE_ID_NAME, FIELD_TABLE_ID, table_id); +} + +/////////////////////////////////////////////////////////////////////////// + +Object_key *Check_constraints::create_key_by_check_constraint_name( + Object_id schema_id, const String_type &check_cons_name) { + return new (std::nothrow) + Item_name_key(FIELD_SCHEMA_ID, schema_id, FIELD_NAME, check_cons_name, + name_collation()); +} + +/////////////////////////////////////////////////////////////////////////// + +bool Check_constraints::check_constraint_exists( + THD *thd, Object_id schema_id, const String_type &check_cons_name, + bool *exists) { + DBUG_ENTER("Check_constraints::check_constraint_exists"); + + Transaction_ro trx(thd, ISO_READ_COMMITTED); + trx.otx.register_tables(); + if (trx.otx.open_tables()) DBUG_RETURN(true); + + const std::unique_ptr key( + create_key_by_check_constraint_name(schema_id, check_cons_name.c_str())); + + Raw_table *table = trx.otx.get_table(instance().name()); + DBUG_ASSERT(table != nullptr); + + // Find record by the object-key. + std::unique_ptr record; + if (table->find_record(*key, record)) DBUG_RETURN(true); + + if (record.get()) + *exists = true; + else + *exists = false; + + DBUG_RETURN(false); +} + +/////////////////////////////////////////////////////////////////////////// + +} // namespace tables +} // namespace dd diff --git a/sql/dd/impl/tables/check_constraints.h b/sql/dd/impl/tables/check_constraints.h new file mode 100644 index 000000000000..4350875e5c38 --- /dev/null +++ b/sql/dd/impl/tables/check_constraints.h @@ -0,0 +1,92 @@ +/* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License, version 2.0, + as published by the Free Software Foundation. + + This program is also distributed with certain software (including + but not limited to OpenSSL) that is licensed under separate terms, + as designated in a particular file or component or in included license + documentation. The authors of MySQL hereby grant you an additional + permission to link the program and your derivative works with the + separately licensed software that they have included with MySQL. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License, version 2.0, for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ + +#ifndef DD_TABLES__CHECK_CONSTRAINTS_INCLUDED +#define DD_TABLES__CHECK_CONSTRAINTS_INCLUDED + +#include "sql/dd/impl/types/object_table_impl.h" // dd::Object_table_impl +#include "sql/dd/object_id.h" // dd::Object_id + +namespace dd { +class Object_key; + +namespace tables { + +/////////////////////////////////////////////////////////////////////////// + +// The Check_constraints table has one row for each check constraint. +class Check_constraints : virtual public Object_table_impl { + public: + static const Check_constraints &instance(); + + static const CHARSET_INFO *name_collation(); + + enum enum_fields { + FIELD_ID, + FIELD_SCHEMA_ID, + FIELD_TABLE_ID, + FIELD_NAME, + FIELD_ENFORCED, + FIELD_CHECK_CLAUSE, + FIELD_CHECK_CLAUSE_UTF8 + }; + + enum enum_indexes { + INDEX_PK_ID = static_cast(Common_index::PK_ID), + INDEX_UK_SCHEMA_ID_NAME = static_cast(Common_index::UK_NAME), + INDEX_UK_TABLE_ID_NAME + }; + + enum enum_foreign_keys { FK_SCHEMA_ID, FK_TABLE_ID }; + + Check_constraints(); + + static Object_key *create_key_by_table_id(Object_id table_id); + + static Object_key *create_key_by_check_constraint_name( + Object_id schema_id, const String_type &check_cons_name); + + /** + Check if schema contains check constraints with specified name. + + @param thd Thread context. + @param schema_id Id of schema to be inspected. + @param check_cons_name Name of the check constraint. + @param[out] exists Set to true if check constraint + the the name provided exists in + the schema, false otherwise. + + @retval false No error. + @retval true Error. + */ + + static bool check_constraint_exists(THD *thd, Object_id schema_id, + const String_type &check_cons_name, + bool *exists); +}; + +/////////////////////////////////////////////////////////////////////////// + +} // namespace tables +} // namespace dd + +#endif // DD_TABLES__CHECK_CONSTRAINTS_INCLUDED diff --git a/sql/dd/impl/transaction_impl.h b/sql/dd/impl/transaction_impl.h index 8207c04af9cc..3b6df2ef4dc1 100644 --- a/sql/dd/impl/transaction_impl.h +++ b/sql/dd/impl/transaction_impl.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License, version 2.0, @@ -31,6 +31,7 @@ #include "sql/dd/dd_kill_immunizer.h" // dd::DD_kill_immunizer #include "sql/dd/impl/types/abstract_table_impl.h" #include "sql/dd/impl/types/charset_impl.h" +#include "sql/dd/impl/types/check_constraint_impl.h" #include "sql/dd/impl/types/collation_impl.h" #include "sql/dd/impl/types/column_impl.h" #include "sql/dd/impl/types/column_statistics_impl.h" diff --git a/sql/dd/impl/types/check_constraint_impl.cc b/sql/dd/impl/types/check_constraint_impl.cc new file mode 100644 index 000000000000..21ee9226f922 --- /dev/null +++ b/sql/dd/impl/types/check_constraint_impl.cc @@ -0,0 +1,205 @@ +/* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License, version 2.0, + as published by the Free Software Foundation. + + This program is also distributed with certain software (including + but not limited to OpenSSL) that is licensed under separate terms, + as designated in a particular file or component or in included license + documentation. The authors of MySQL hereby grant you an additional + permission to link the program and your derivative works with the + separately licensed software that they have included with MySQL. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License, version 2.0, for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ + +#include "sql/dd/impl/types/check_constraint_impl.h" + +#include "mysqld_error.h" // ER_* +#include "sql/dd/impl/raw/raw_record.h" // Raw_record +#include "sql/dd/impl/sdi_impl.h" // sdi read/write functions +#include "sql/dd/impl/tables/check_constraints.h" // Check_constraints +#include "sql/dd/impl/transaction_impl.h" // Open_dictionary_tables_ctx +#include "sql/dd/impl/types/table_impl.h" // Table_impl +#include "sql/error_handler.h" // Internal_error_handler + +namespace dd { +class Object_key; +} // namespace dd + +using dd::tables::Check_constraints; + +namespace dd { + +/////////////////////////////////////////////////////////////////////////// +// Check_constraint_impl implementation. +/////////////////////////////////////////////////////////////////////////// + +Check_constraint_impl::Check_constraint_impl() {} + +Check_constraint_impl::Check_constraint_impl(Table_impl *table) + : m_table(table) {} + +/////////////////////////////////////////////////////////////////////////// + +const Table &Check_constraint_impl::table() const { return *m_table; } + +Table &Check_constraint_impl::table() { return *m_table; } + +/////////////////////////////////////////////////////////////////////////// + +bool Check_constraint_impl::validate() const { + if (!m_table) { + my_error(ER_INVALID_DD_OBJECT, MYF(0), DD_table::instance().name().c_str(), + "No table is associated with this check constraint object."); + return true; + } + + return false; +} + +/////////////////////////////////////////////////////////////////////////// + +/** + Error handler to convert ER_DUP_ENTRY error to more user friendly error + ER_CHECK_CONSTRAINT_DUP_NAME. +*/ +class Check_constraint_name_error_handler : public Internal_error_handler { + public: + Check_constraint_name_error_handler(const char *name) : m_name(name) {} + + virtual bool handle_condition(THD *, uint sql_errno, const char *, + Sql_condition::enum_severity_level *, + const char *) { + if (sql_errno == ER_DUP_ENTRY) { + my_error(ER_CHECK_CONSTRAINT_DUP_NAME, MYF(0), m_name); + return true; + } + return false; + } + + private: + const char *m_name; +}; + +bool Check_constraint_impl::store(Open_dictionary_tables_ctx *otx) { + /* + Translate ER_DUP_ENTRY errors to the more user-friendly + ER_CHECK_CONSTRAINT_DUP_NAME error. + */ + Check_constraint_name_error_handler error_handler(name().c_str()); + otx->get_thd()->push_internal_handler(&error_handler); + bool error = Weak_object_impl::store(otx); + otx->get_thd()->pop_internal_handler(); + return error; +} + +/////////////////////////////////////////////////////////////////////////// + +bool Check_constraint_impl::restore_attributes(const Raw_record &r) { + if (check_parent_consistency( + m_table, r.read_ref_id(Check_constraints::FIELD_TABLE_ID))) + return true; + + restore_id(r, Check_constraints::FIELD_ID); + restore_name(r, Check_constraints::FIELD_NAME); + m_schema_id = r.read_int(Check_constraints::FIELD_SCHEMA_ID); + m_constraint_state = static_cast( + r.read_int(Check_constraints::FIELD_ENFORCED)); + m_check_clause = r.read_str(Check_constraints::FIELD_CHECK_CLAUSE); + m_check_clause_utf8 = r.read_str(Check_constraints::FIELD_CHECK_CLAUSE_UTF8); + + return false; +} + +/////////////////////////////////////////////////////////////////////////// + +bool Check_constraint_impl::store_attributes(dd::Raw_record *r) { + return store_id(r, Check_constraints::FIELD_ID) || + store_name(r, Check_constraints::FIELD_NAME) || + r->store(Check_constraints::FIELD_SCHEMA_ID, m_table->schema_id()) || + r->store(Check_constraints::FIELD_TABLE_ID, m_table->id()) || + r->store(Check_constraints::FIELD_ENFORCED, m_constraint_state) || + r->store(Check_constraints::FIELD_CHECK_CLAUSE, m_check_clause) || + r->store(Check_constraints::FIELD_CHECK_CLAUSE_UTF8, + m_check_clause_utf8); +} + +/////////////////////////////////////////////////////////////////////////// + +static_assert(Check_constraints::FIELD_CHECK_CLAUSE_UTF8 == 6, + "Check_constraints definition has changed, review (de)serialize " + "member functions!"); +void Check_constraint_impl::serialize(Sdi_wcontext *wctx, Sdi_writer *w) const { + w->StartObject(); + Entity_object_impl::serialize(wctx, w); + + write_enum(w, m_constraint_state, STRING_WITH_LEN("state")); + write_binary(wctx, w, m_check_clause, STRING_WITH_LEN("check_clause")); + write(w, m_check_clause_utf8, STRING_WITH_LEN("check_clause_utf8")); + + w->EndObject(); +} + +/////////////////////////////////////////////////////////////////////////// + +bool Check_constraint_impl::deserialize(Sdi_rcontext *rctx, + const RJ_Value &val) { + Entity_object_impl::deserialize(rctx, val); + + read_enum(&m_constraint_state, val, "state"); + read_binary(rctx, &m_check_clause, val, "check_clause"); + read(&m_check_clause_utf8, val, "check_clause_utf8"); + return false; +} + +/////////////////////////////////////////////////////////////////////////// + +void Check_constraint_impl::debug_print(String_type &outb) const { + dd::Stringstream_type ss; + ss << "VIEW TABLE OBJECT: { " + << "m_id: {OID: " << id() << "}; " + << "m_schema_id: {OID: " << m_table->schema_id() << "}; " + << "m_table: {OID: " << m_table->id() << "}; " + << "m_name: " << name() << ";" + << "m_constraint_state: " << m_constraint_state << "; " + << "m_check_clause: ; " + << "m_check_clause_utf8: " << m_check_clause_utf8 << "; "; + + outb = ss.str(); +} + +/////////////////////////////////////////////////////////////////////////// + +Check_constraint_impl::Check_constraint_impl(const Check_constraint_impl &src, + Table_impl *parent) + : Weak_object(src), + Entity_object_impl(src), + m_constraint_state(src.m_constraint_state), + m_check_clause(src.m_check_clause), + m_check_clause_utf8(src.m_check_clause_utf8), + m_schema_id(src.m_schema_id), + m_table(parent) {} + +/////////////////////////////////////////////////////////////////////////// + +const Object_table &Check_constraint_impl::object_table() const { + return DD_table::instance(); +} + +/////////////////////////////////////////////////////////////////////////// + +void Check_constraint_impl::register_tables(Open_dictionary_tables_ctx *otx) { + otx->add_table(); +} + +/////////////////////////////////////////////////////////////////////////// + +} // namespace dd diff --git a/sql/dd/impl/types/check_constraint_impl.h b/sql/dd/impl/types/check_constraint_impl.h new file mode 100644 index 000000000000..34c9a7db31ee --- /dev/null +++ b/sql/dd/impl/types/check_constraint_impl.h @@ -0,0 +1,155 @@ +/* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License, version 2.0, + as published by the Free Software Foundation. + + This program is also distributed with certain software (including + but not limited to OpenSSL) that is licensed under separate terms, + as designated in a particular file or component or in included license + documentation. The authors of MySQL hereby grant you an additional + permission to link the program and your derivative works with the + separately licensed software that they have included with MySQL. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License, version 2.0, for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ + +#ifndef DD__CHECK_CONSTRAINT_IMPL_INCLUDED +#define DD__CHECK_CONSTRAINT_IMPL_INCLUDED + +#include + +#include "m_ctype.h" // my_strcasecmp +#include "sql/dd/impl/types/entity_object_impl.h" // dd::Entity_object_impl +#include "sql/dd/sdi_fwd.h" +#include "sql/dd/string_type.h" +#include "sql/dd/types/check_constraint.h" // dd::Check_constraint + +namespace dd { + +/////////////////////////////////////////////////////////////////////////// + +class Object_table; +class Open_dictionary_tables_ctx; +class Raw_record; +class Sdi_rcontext; +class Sdi_wcontext; +class Table; +class Table_impl; + +/////////////////////////////////////////////////////////////////////////// + +class Check_constraint_impl : public Entity_object_impl, + public Check_constraint { + public: + Check_constraint_impl(); + + Check_constraint_impl(Table_impl *table); + + Check_constraint_impl(const Check_constraint_impl &src, Table_impl *parent); + + virtual ~Check_constraint_impl() {} + + public: + static void register_tables(Open_dictionary_tables_ctx *otx); + + virtual const Object_table &object_table() const; + + virtual bool validate() const; + + virtual bool store(Open_dictionary_tables_ctx *otx); + + virtual bool store_attributes(Raw_record *r); + + virtual bool restore_attributes(const Raw_record &r); + + void serialize(Sdi_wcontext *wctx, Sdi_writer *w) const; + + bool deserialize(Sdi_rcontext *rctx, const RJ_Value &val); + + virtual void debug_print(String_type &outb) const; + + void set_ordinal_position(uint) {} + + virtual uint ordinal_position() const { return -1; } + + public: + ///////////////////////////////////////////////////////////////////////// + // State. + ///////////////////////////////////////////////////////////////////////// + + virtual enum_constraint_state constraint_state() const { + return m_constraint_state; + } + + virtual void set_constraint_state(bool is_enabled) { + m_constraint_state = is_enabled ? CS_ENFORCED : CS_NOT_ENFORCED; + } + + ///////////////////////////////////////////////////////////////////////// + // Check clause/utf8. + ///////////////////////////////////////////////////////////////////////// + + virtual const String_type &check_clause() const { return m_check_clause; } + + virtual void set_check_clause(const String_type &check_clause) { + m_check_clause = check_clause; + } + + virtual const String_type &check_clause_utf8() const { + return m_check_clause_utf8; + } + + virtual void set_check_clause_utf8(const String_type &check_clause_utf8) { + m_check_clause_utf8 = check_clause_utf8; + } + + ///////////////////////////////////////////////////////////////////////// + // Table. + ///////////////////////////////////////////////////////////////////////// + + virtual const Table &table() const; + + virtual Table &table(); + + public: + static Check_constraint_impl *restore_item(Table_impl *table) { + return new (std::nothrow) Check_constraint_impl(table); + } + + static Check_constraint_impl *clone(const Check_constraint_impl &other, + Table_impl *table) { + return new (std::nothrow) Check_constraint_impl(other, table); + } + + private: + enum_constraint_state m_constraint_state{CS_ENFORCED}; + String_type m_check_clause; + String_type m_check_clause_utf8; + Object_id m_schema_id; + + // References to the Table object. + Table_impl *m_table; +}; + +/////////////////////////////////////////////////////////////////////////// + +/** Class used to sort check constraints by name for the same table. */ +struct Check_constraint_order_comparator { + bool operator()(const dd::Check_constraint *cc1, + const dd::Check_constraint *cc2) const { + return (my_strcasecmp(system_charset_info, cc1->name().c_str(), + cc2->name().c_str()) < 0); + } +}; + +/////////////////////////////////////////////////////////////////////////// +} // namespace dd + +#endif // DD__CHECK_CONSTRAINT_IMPL_INCLUDED diff --git a/sql/dd/impl/types/table_impl.cc b/sql/dd/impl/types/table_impl.cc index f0c297414286..fe05a15800a4 100644 --- a/sql/dd/impl/types/table_impl.cc +++ b/sql/dd/impl/types/table_impl.cc @@ -1,4 +1,4 @@ -/* Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License, version 2.0, @@ -35,27 +35,29 @@ #include "m_string.h" #include "my_dbug.h" #include "my_sys.h" -#include "mysqld_error.h" // ER_* -#include "sql/current_thd.h" // current_thd -#include "sql/dd/impl/bootstrap_ctx.h" // dd::bootstrap::DD_bootstrap_ctx -#include "sql/dd/impl/dictionary_impl.h" // Dictionary_impl -#include "sql/dd/impl/properties_impl.h" // Properties_impl -#include "sql/dd/impl/raw/raw_record.h" // Raw_record -#include "sql/dd/impl/raw/raw_record_set.h" // Raw_record_set -#include "sql/dd/impl/raw/raw_table.h" // Raw_table -#include "sql/dd/impl/sdi_impl.h" // sdi read/write functions -#include "sql/dd/impl/tables/columns.h" // Columns -#include "sql/dd/impl/tables/foreign_keys.h" // Foreign_keys -#include "sql/dd/impl/tables/indexes.h" // Indexes -#include "sql/dd/impl/tables/schemata.h" // Schemata -#include "sql/dd/impl/tables/table_partitions.h" // Table_partitions -#include "sql/dd/impl/tables/tables.h" // Tables -#include "sql/dd/impl/tables/triggers.h" // Triggers -#include "sql/dd/impl/transaction_impl.h" // Open_dictionary_tables_ctx -#include "sql/dd/impl/types/foreign_key_impl.h" // Foreign_key_impl -#include "sql/dd/impl/types/index_impl.h" // Index_impl -#include "sql/dd/impl/types/partition_impl.h" // Partition_impl -#include "sql/dd/impl/types/trigger_impl.h" // Trigger_impl +#include "mysqld_error.h" // ER_* +#include "sql/current_thd.h" // current_thd +#include "sql/dd/impl/bootstrap_ctx.h" // dd::bootstrap::DD_bootstrap_ctx +#include "sql/dd/impl/dictionary_impl.h" // Dictionary_impl +#include "sql/dd/impl/properties_impl.h" // Properties_impl +#include "sql/dd/impl/raw/raw_record.h" // Raw_record +#include "sql/dd/impl/raw/raw_record_set.h" // Raw_record_set +#include "sql/dd/impl/raw/raw_table.h" // Raw_table +#include "sql/dd/impl/sdi_impl.h" // sdi read/write functions +#include "sql/dd/impl/tables/check_constraints.h" // Check_constraints +#include "sql/dd/impl/tables/columns.h" // Columns +#include "sql/dd/impl/tables/foreign_keys.h" // Foreign_keys +#include "sql/dd/impl/tables/indexes.h" // Indexes +#include "sql/dd/impl/tables/schemata.h" // Schemata +#include "sql/dd/impl/tables/table_partitions.h" // Table_partitions +#include "sql/dd/impl/tables/tables.h" // Tables +#include "sql/dd/impl/tables/triggers.h" // Triggers +#include "sql/dd/impl/transaction_impl.h" // Open_dictionary_tables_ctx +#include "sql/dd/impl/types/check_constraint_impl.h" // Check_constraint_impl +#include "sql/dd/impl/types/foreign_key_impl.h" // Foreign_key_impl +#include "sql/dd/impl/types/index_impl.h" // Index_impl +#include "sql/dd/impl/types/partition_impl.h" // Partition_impl +#include "sql/dd/impl/types/trigger_impl.h" // Trigger_impl #include "sql/dd/properties.h" #include "sql/dd/string_type.h" // dd::String_type #include "sql/dd/types/column.h" // Column @@ -65,6 +67,7 @@ #include "sql/dd/types/weak_object.h" #include "sql/sql_class.h" +using dd::tables::Check_constraints; using dd::tables::Foreign_keys; using dd::tables::Indexes; using dd::tables::Table_partitions; @@ -99,6 +102,7 @@ Table_impl::Table_impl() m_foreign_keys(), m_partitions(), m_triggers(), + m_check_constraints(), m_collation_id(INVALID_OBJECT_ID), m_tablespace_id(INVALID_OBJECT_ID) {} @@ -257,6 +261,14 @@ bool Table_impl::restore_children(Open_dictionary_tables_ctx *otx) { // - Partitions should be loaded at the end, as it refers to // indexes. + /* + Do not load check constraints if upgrade is from the DD version before + check constraints support. Check constraint support is introduced in 80015. + */ + bool skip_check_constraints = + (bootstrap::DD_bootstrap_ctx::instance().is_dd_upgrade_from_before( + bootstrap::DD_VERSION_80015)); + return ( Abstract_table_impl::restore_children(otx) || m_indexes.restore_items(this, otx, otx->get_table(), @@ -274,7 +286,12 @@ bool Table_impl::restore_children(Open_dictionary_tables_ctx *otx) { m_triggers.restore_items(this, otx, otx->get_table(), Triggers::create_key_by_table_id(this->id()), Trigger_order_comparator()) || - load_foreign_key_parents(otx)); + load_foreign_key_parents(otx) || + (!skip_check_constraints && + m_check_constraints.restore_items( + this, otx, otx->get_table(), + Check_constraints::create_key_by_table_id(this->id()), + Check_constraint_order_comparator()))); } /////////////////////////////////////////////////////////////////////////// @@ -342,11 +359,20 @@ bool Table_impl::store_triggers(Open_dictionary_tables_ctx *otx) { /////////////////////////////////////////////////////////////////////////// bool Table_impl::store_children(Open_dictionary_tables_ctx *otx) { + /* + Do not store check constraints if upgrade is from the DD version before + check constraints support. Check constraint support is introduced in 80015. + */ + bool skip_check_constraints = + (bootstrap::DD_bootstrap_ctx::instance().is_dd_upgrade_from_before( + bootstrap::DD_VERSION_80015)); + return Abstract_table_impl::store_children(otx) || // Note that indexes has to be stored first, as // partitions refer indexes. m_indexes.store_items(otx) || m_foreign_keys.store_items(otx) || - m_partitions.store_items(otx) || store_triggers(otx); + m_partitions.store_items(otx) || store_triggers(otx) || + (!skip_check_constraints && m_check_constraints.store_items(otx)); } /////////////////////////////////////////////////////////////////////////// @@ -355,7 +381,10 @@ bool Table_impl::drop_children(Open_dictionary_tables_ctx *otx) const { // Note that partition collection has to be dropped first // as it has foreign key to indexes. - return m_triggers.drop_items(otx, otx->get_table(), + return m_check_constraints.drop_items( + otx, otx->get_table(), + Check_constraints::create_key_by_table_id(this->id())) || + m_triggers.drop_items(otx, otx->get_table(), Triggers::create_key_by_table_id(this->id())) || m_partitions.drop_items( otx, otx->get_table(), @@ -523,6 +552,8 @@ void Table_impl::serialize(Sdi_wcontext *wctx, Sdi_writer *w) const { STRING_WITH_LEN("default_subpartitioning")); serialize_each(wctx, w, m_indexes, STRING_WITH_LEN("indexes")); serialize_each(wctx, w, m_foreign_keys, STRING_WITH_LEN("foreign_keys")); + serialize_each(wctx, w, m_check_constraints, + STRING_WITH_LEN("check_constraints")); serialize_each(wctx, w, m_partitions, STRING_WITH_LEN("partitions")); write(w, m_collation_id, STRING_WITH_LEN("collation_id")); serialize_tablespace_ref(wctx, w, m_tablespace_id, @@ -565,6 +596,8 @@ bool Table_impl::deserialize(Sdi_rcontext *rctx, const RJ_Value &val) { deserialize_each(rctx, [this]() { return add_foreign_key(); }, val, "foreign_keys"); + deserialize_each(rctx, [this]() { return add_check_constraint(); }, val, + "check_constraints"); deserialize_each(rctx, [this]() { return add_partition(); }, val, "partitions"); read(&m_collation_id, val, "collation_id"); @@ -628,6 +661,16 @@ void Table_impl::debug_print(String_type &outb) const { } } + ss << "] m_check_constraints: " << m_check_constraints.size() << " [ "; + + { + for (const Check_constraint *cc : check_constraints()) { + String_type s; + cc->debug_print(s); + ss << s << " | "; + } + } + ss << "] m_triggers: " << m_triggers.size() << " [ "; { @@ -898,6 +941,16 @@ void Table_impl::drop_trigger(const Trigger *trigger) { reorder_action_order(at, et); } +/////////////////////////////////////////////////////////////////////////// +// Check constraint collection. +/////////////////////////////////////////////////////////////////////////// + +Check_constraint *Table_impl::add_check_constraint() { + Check_constraint_impl *cc = new (std::nothrow) Check_constraint_impl(this); + m_check_constraints.push_back(cc); + return cc; +} + /////////////////////////////////////////////////////////////////////////// Partition *Table_impl::get_partition(const String_type &name) { @@ -929,6 +982,13 @@ void Table_impl::register_tables(Open_dictionary_tables_ctx *otx) { otx->register_tables(); otx->register_tables(); otx->register_tables(); + /* + Do not register check constraint table if upgrade is from the DD version + before check constraints support. Check constraint is introduced in 8.0.15. + */ + if (!bootstrap::DD_bootstrap_ctx::instance().is_dd_upgrade_from_before( + bootstrap::DD_VERSION_80015)) + otx->register_tables(); } /////////////////////////////////////////////////////////////////////////// @@ -956,6 +1016,7 @@ Table_impl::Table_impl(const Table_impl &src) m_foreign_keys(), m_partitions(), m_triggers(), + m_check_constraints(), m_collation_id(src.m_collation_id), m_tablespace_id(src.m_tablespace_id) { m_indexes.deep_copy(src.m_indexes, this); @@ -965,5 +1026,6 @@ Table_impl::Table_impl(const Table_impl &src) Foreign_key_parent(*fk_parent)); m_partitions.deep_copy(src.m_partitions, this); m_triggers.deep_copy(src.m_triggers, this); + m_check_constraints.deep_copy(src.m_check_constraints, this); } } // namespace dd diff --git a/sql/dd/impl/types/table_impl.h b/sql/dd/impl/types/table_impl.h index eeadf689118c..a8306978924a 100644 --- a/sql/dd/impl/types/table_impl.h +++ b/sql/dd/impl/types/table_impl.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License, version 2.0, @@ -39,11 +39,12 @@ #include "sql/dd/sdi_fwd.h" #include "sql/dd/string_type.h" #include "sql/dd/types/abstract_table.h" -#include "sql/dd/types/foreign_key.h" // dd::Foreign_key -#include "sql/dd/types/index.h" // dd::Index -#include "sql/dd/types/partition.h" // dd::Partition -#include "sql/dd/types/table.h" // dd:Table -#include "sql/dd/types/trigger.h" // dd::Trigger +#include "sql/dd/types/check_constraint.h" // dd::Check_constraint +#include "sql/dd/types/foreign_key.h" // dd::Foreign_key +#include "sql/dd/types/index.h" // dd::Index +#include "sql/dd/types/partition.h" // dd::Partition +#include "sql/dd/types/table.h" // dd:Table +#include "sql/dd/types/trigger.h" // dd::Trigger namespace dd { @@ -501,6 +502,21 @@ class Table_impl : public Abstract_table_impl, virtual public Table { Trigger_impl *create_trigger(); + public: + ///////////////////////////////////////////////////////////////////////// + // Check constraints. + ///////////////////////////////////////////////////////////////////////// + + virtual Check_constraint *add_check_constraint(); + + virtual const Check_constraint_collection &check_constraints() const { + return m_check_constraints; + } + + virtual Check_constraint_collection *check_constraints() { + return &m_check_constraints; + } + private: // Fields. @@ -538,6 +554,7 @@ class Table_impl : public Abstract_table_impl, virtual public Table { Partition_collection m_partitions; Partition_leaf_vector m_leaf_partitions; Trigger_collection m_triggers; + Check_constraint_collection m_check_constraints; // References to other objects. diff --git a/sql/dd/info_schema/metadata.h b/sql/dd/info_schema/metadata.h index 3e83d16fc8a5..af49955e2c8f 100644 --- a/sql/dd/info_schema/metadata.h +++ b/sql/dd/info_schema/metadata.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License, version 2.0, @@ -77,7 +77,7 @@ namespace info_schema { if it is a regular key part. For functional key parts, COLUMN_NAME is set to SQL NULL. - 80013: Current + 80013: Published in 8.0.13 ------------------------------------ Changes from version 80012 @@ -85,9 +85,23 @@ namespace info_schema { Adds a new view `information_schema`.`st_units_of_measure` with columns `UNIT_NAME`, `CONVERSION_FACTOR`, `DESCRIPTION`, and `UNIT_TYPE`. This view contains the supported spatial units. + + 80014: + ------------------------------------ + There are no changes from version 80013. Hence server version 80014 used + I_S version 80013. + + 80015: Current + ------------------------------------ + Changes from version 80014. + + - WL#929 - CHECK CONSTRAINTS + New INFORMATION_SCHMEA table CHECK_CONSTRAINTS is introduced and + INFORMATION_SCHMEA.TABLE_CONSTRAINTS is modified to include check + constraints defined on the table. */ -static const uint IS_DD_VERSION = 80013; +static const uint IS_DD_VERSION = 80015; /** Initialize INFORMATION_SCHEMA system views. diff --git a/sql/dd/types/check_constraint.h b/sql/dd/types/check_constraint.h new file mode 100644 index 000000000000..ddb02d2cfbf1 --- /dev/null +++ b/sql/dd/types/check_constraint.h @@ -0,0 +1,115 @@ +/* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License, version 2.0, + as published by the Free Software Foundation. + + This program is also distributed with certain software (including + but not limited to OpenSSL) that is licensed under separate terms, + as designated in a particular file or component or in included license + documentation. The authors of MySQL hereby grant you an additional + permission to link the program and your derivative works with the + separately licensed software that they have included with MySQL. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License, version 2.0, for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ + +#ifndef DD__CHECK_CONSTRAINTS_INCLUDED +#define DD__CHECK_CONSTRAINTS_INCLUDED + +#include "sql/dd/types/entity_object.h" // dd::Entity_object + +namespace dd { + +/////////////////////////////////////////////////////////////////////////// + +class Table; +class Check_constraint_impl; + +namespace tables { +class Check_constraints; +} + +/////////////////////////////////////////////////////////////////////////// + +class Check_constraint : virtual public Entity_object { + public: + typedef Check_constraint_impl Impl; + typedef tables::Check_constraints DD_table; + + public: + enum enum_constraint_state { CS_NOT_ENFORCED = 1, CS_ENFORCED }; + + public: + virtual ~Check_constraint() {} + + ///////////////////////////////////////////////////////////////////////// + // State. (enforced / not enforced) + ///////////////////////////////////////////////////////////////////////// + + virtual enum_constraint_state constraint_state() const = 0; + virtual void set_constraint_state(bool is_enforced) = 0; + + ///////////////////////////////////////////////////////////////////////// + // Check clause/utf8. + ///////////////////////////////////////////////////////////////////////// + + virtual const String_type &check_clause() const = 0; + virtual void set_check_clause(const String_type &check_clause) = 0; + + virtual const String_type &check_clause_utf8() const = 0; + virtual void set_check_clause_utf8(const String_type &check_clause_utf8) = 0; + + ///////////////////////////////////////////////////////////////////////// + // Parent table. + ///////////////////////////////////////////////////////////////////////// + + virtual const Table &table() const = 0; + + virtual Table &table() = 0; + + /** + Converts *this into json. + + Converts all member variables that are to be included in the sdi + into json by transforming them appropriately and passing them to + the rapidjson writer provided. + + @param wctx opaque context for data needed by serialization + @param w rapidjson writer which will perform conversion to json + + */ + + virtual void serialize(Sdi_wcontext *wctx, Sdi_writer *w) const = 0; + + /** + Re-establishes the state of *this by reading sdi information from + the rapidjson DOM subobject provided. + + Cross-references encountered within this object are tracked in + sdictx, so that they can be updated when the entire object graph + has been established. + + @param rctx stores book-keeping information for the + deserialization process + @param val subobject of rapidjson DOM containing json + representation of this object + @return + @retval false success + @retval true failure + */ + + virtual bool deserialize(Sdi_rcontext *rctx, const RJ_Value &val) = 0; +}; + +/////////////////////////////////////////////////////////////////////////// + +} // namespace dd + +#endif // DD__CHECK_CONSTRAINTS_INCLUDED diff --git a/sql/dd/types/table.h b/sql/dd/types/table.h index dcd276efe59f..ed60b81d637c 100644 --- a/sql/dd/types/table.h +++ b/sql/dd/types/table.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License, version 2.0, @@ -33,6 +33,7 @@ namespace dd { /////////////////////////////////////////////////////////////////////////// +class Check_constraint; class Partition; class Table_impl; class Trigger; @@ -47,6 +48,7 @@ class Table : virtual public Abstract_table { typedef std::vector Foreign_key_parent_collection; typedef Collection Partition_collection; typedef Collection Trigger_collection; + typedef Collection Check_constraint_collection; /* The type Partition_collection object 'own' the Partition* object. That @@ -385,6 +387,16 @@ class Table : virtual public Abstract_table { virtual void drop_all_triggers() = 0; + ///////////////////////////////////////////////////////////////////////// + // Check constraint collection. + ///////////////////////////////////////////////////////////////////////// + + virtual Check_constraint *add_check_constraint() = 0; + + virtual const Check_constraint_collection &check_constraints() const = 0; + + virtual Check_constraint_collection *check_constraints() = 0; + public: /** Allocate a new object graph and invoke the copy contructor for diff --git a/sql/dd/upgrade/table.cc b/sql/dd/upgrade/table.cc index dc8fb77e0d42..f5bb1d6defae 100644 --- a/sql/dd/upgrade/table.cc +++ b/sql/dd/upgrade/table.cc @@ -1,4 +1,4 @@ -/* Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License, version 2.0, @@ -1256,9 +1256,9 @@ static bool fix_generated_columns_for_upgrade( for (field_ptr = table->s->field; (sql_field = itc++); field_ptr++) { // Field has generated col information. if (sql_field->gcol_info && (*field_ptr)->gcol_info) { - if (unpack_value_generator(thd, table, *field_ptr, - &(*field_ptr)->gcol_info, false, true, - &error_reported)) { + if (unpack_value_generator( + thd, table, &(*field_ptr)->gcol_info, VGS_GENERATED_COLUMN, + (*field_ptr)->field_name, *field_ptr, false, &error_reported)) { error = true; break; } @@ -1693,6 +1693,7 @@ static bool migrate_table_to_dd(THD *thd, const String_type &schema_name, FOREIGN_KEY *fk_key_info_buffer = NULL; uint fk_number = 0; + Sql_check_constraint_spec_list cc_spec_list_unused(thd->mem_root); // Set sql_mode=0 for handling default values, it will be restored vai RAII. thd->variables.sql_mode = 0; @@ -1725,7 +1726,7 @@ static bool migrate_table_to_dd(THD *thd, const String_type &schema_name, std::unique_ptr table_def = dd::create_dd_user_table( thd, *sch_obj, to_table_name, &create_info, alter_info.create_list, key_info_buffer, key_count, Alter_info::ENABLE, fk_key_info_buffer, - fk_number, table.file); + fk_number, &cc_spec_list_unused, table.file); if (!table_def || thd->dd_client()->store(table_def.get())) { LogErr(ERROR_LEVEL, ER_DD_ERROR_CREATING_ENTRY, schema_name.c_str(), diff --git a/sql/dd_table_share.cc b/sql/dd_table_share.cc index 7af767025a05..efe125b32858 100644 --- a/sql/dd_table_share.cc +++ b/sql/dd_table_share.cc @@ -1,4 +1,4 @@ -/* Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License, version 2.0, @@ -55,6 +55,7 @@ #include "sql/dd/impl/utils.h" // dd::eat_str #include "sql/dd/properties.h" // dd::Properties #include "sql/dd/string_type.h" +#include "sql/dd/types/check_constraint.h" // dd::Check_constraint #include "sql/dd/types/column.h" // dd::enum_column_types #include "sql/dd/types/column_type_element.h" // dd::Column_type_element #include "sql/dd/types/foreign_key.h" @@ -74,7 +75,8 @@ #include "sql/partition_element.h" // partition_element #include "sql/partition_info.h" // partition_info #include "sql/sql_bitmap.h" -#include "sql/sql_class.h" // THD +#include "sql/sql_check_constraint.h" // Sql_check_constraint_share_list +#include "sql/sql_class.h" // THD #include "sql/sql_const.h" #include "sql/sql_error.h" #include "sql/sql_list.h" @@ -2233,6 +2235,54 @@ static bool fill_foreign_keys_from_dd(TABLE_SHARE *share, return false; } +/** + Fill check constraints from dd::Table object to the TABLE_SHARE. + + @param[in,out] share TABLE_SHARE instance. + @param[in] tab_obj Table instance. + + @retval false On Success. + @retval true On failure. +*/ +static bool fill_check_constraints_from_dd(TABLE_SHARE *share, + const dd::Table *tab_obj) { + DBUG_ASSERT(share->check_constraint_share_list == nullptr); + + if (tab_obj->check_constraints().size() > 0) { + share->check_constraint_share_list = new (&share->mem_root) + Sql_check_constraint_share_list(&share->mem_root); + if (share->check_constraint_share_list == nullptr) return true; // OOM + + for (auto &cc : tab_obj->check_constraints()) { + // Check constraint name. + LEX_CSTRING name; + if (lex_string_strmake(&share->mem_root, &name, cc->name().c_str(), + cc->name().length())) + return true; // OOM + + // Check constraint expression (clause). + LEX_CSTRING check_clause; + if (lex_string_strmake(&share->mem_root, &check_clause, + cc->check_clause().c_str(), + cc->check_clause().length())) + return true; // OOM + + // Check constraint state. + bool is_cc_enforced = + (cc->constraint_state() == dd::Check_constraint::CS_ENFORCED); + + Sql_check_constraint_share *cc_share = new (&share->mem_root) + Sql_check_constraint_share(name, check_clause, is_cc_enforced); + if (cc_share == nullptr) return true; // OOM + + if (share->check_constraint_share_list->push_back(cc_share)) + return true; // OOM + } + } + + return false; +} + bool open_table_def(THD *thd, TABLE_SHARE *share, const dd::Table &table_def) { DBUG_ENTER("open_table_def"); @@ -2245,7 +2295,8 @@ bool open_table_def(THD *thd, TABLE_SHARE *share, const dd::Table &table_def) { fill_columns_from_dd(thd, share, &table_def) || fill_indexes_from_dd(thd, share, &table_def) || fill_partitioning_from_dd(thd, share, &table_def) || - fill_foreign_keys_from_dd(share, &table_def)); + fill_foreign_keys_from_dd(share, &table_def) || + fill_check_constraints_from_dd(share, &table_def)); thd->mem_root = old_root; diff --git a/sql/error_handler.cc b/sql/error_handler.cc index e859c620e018..99b667c31900 100644 --- a/sql/error_handler.cc +++ b/sql/error_handler.cc @@ -1,4 +1,4 @@ -/* Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License, version 2.0, @@ -104,6 +104,7 @@ bool Ignore_error_handler::handle_condition( case ER_NO_PARTITION_FOR_GIVEN_VALUE: case ER_NO_PARTITION_FOR_GIVEN_VALUE_SILENT: case ER_ROW_DOES_NOT_MATCH_GIVEN_PARTITION_SET: + case ER_CHECK_CONSTRAINT_VIOLATED: (*level) = Sql_condition::SL_WARNING; break; default: diff --git a/sql/field.cc b/sql/field.cc index 5785ecc0d740..ae11fa753a3e 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -1103,27 +1103,33 @@ static enum_field_types field_types_merge_rules[FIELDTYPE_NUM][FIELDTYPE_NUM] = // MYSQL_TYPE_STRING MYSQL_TYPE_GEOMETRY MYSQL_TYPE_STRING, MYSQL_TYPE_GEOMETRY}}; -bool pre_validate_value_generator_expr(Item *expression, - const char *column_name, - bool is_gen_col) { +bool pre_validate_value_generator_expr(Item *expression, const char *name, + Value_generator_source source) { + enum error_type { ER_GENERATED_ROW, ER_NAMED_FUNCTION, MAX_ERROR }; + int error_code_map[][MAX_ERROR] = { + // Generated column + {ER_GENERATED_COLUMN_ROW_VALUE, + ER_GENERATED_COLUMN_NAMED_FUNCTION_IS_NOT_ALLOWED}, + // Default expression + {ER_DEFAULT_VAL_GENERATED_ROW_VALUE, + ER_DEFAULT_VAL_GENERATED_NAMED_FUNCTION_IS_NOT_ALLOWED}, + // Check constraint + {ER_CHECK_CONSTRAINT_ROW_VALUE, + ER_CHECK_CONSTRAINT_NAMED_FUNCTION_IS_NOT_ALLOWED}}; + // ROW values are not allowed if (expression->cols() != 1) { - const int err_code = is_gen_col ? ER_GENERATED_COLUMN_ROW_VALUE - : ER_DEFAULT_VAL_GENERATED_ROW_VALUE; - my_error(err_code, MYF(0), column_name); + my_error(error_code_map[source][ER_GENERATED_ROW], MYF(0), name); return true; } - const int error_code = - is_gen_col ? ER_GENERATED_COLUMN_NAMED_FUNCTION_IS_NOT_ALLOWED - : ER_DEFAULT_VAL_GENERATED_NAMED_FUNCTION_IS_NOT_ALLOWED; - Check_function_as_value_generator_parameters checker_args(error_code, - is_gen_col); + Check_function_as_value_generator_parameters checker_args( + error_code_map[source][ER_NAMED_FUNCTION], source); if (expression->walk(&Item::check_function_as_value_generator, Item::WALK_SUBQUERY_POSTFIX, pointer_cast(&checker_args))) { - my_error(checker_args.err_code, MYF(0), column_name, + my_error(checker_args.err_code, MYF(0), name, checker_args.banned_function_name); return true; } diff --git a/sql/field.h b/sql/field.h index a667466ad89a..f833c4b6baac 100644 --- a/sql/field.h +++ b/sql/field.h @@ -1,7 +1,7 @@ #ifndef FIELD_INCLUDED #define FIELD_INCLUDED -/* Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License, version 2.0, @@ -572,8 +572,19 @@ void copy_integer(uchar *to, size_t to_length, const uchar *from, } /** - Used for storing information associated with generated column or default - values generated from expression. + Enum to indicate source for which value generator is used. This is needed + while unpacking value generator expression and pre-validating the + expression for generated column, default expression or check constraint. +*/ +enum Value_generator_source : short { + VGS_GENERATED_COLUMN = 0, // Value generator for GENERATED_COLUMN. + VGS_DEFAULT_EXPRESSION, // Value generator for Default expression. + VGS_CHECK_CONSTRAINT // Value generator for check constraints. +}; + +/** + Used for storing information associated with generated column, default + values generated from expression or check constraint expression. */ class Value_generator { public: @@ -4633,18 +4644,18 @@ inline bool is_blob(enum_field_types sql_type) { const char *get_field_name_or_expression(THD *thd, const Field *field); /* - Perform per item-type checks to determine if the expression is - allowed for a generated column, default value expression or a functional - index. Note that validation of the specific function is done later in - procedures open_table_from_share and fix_value_generators_fields - - @param expr the expression to check for validity - @param column_name used for error reporting - @param is_gen_col weather it is a GCOL or a default value expression + Perform per item-type checks to determine if the expression is allowed for + a generated column, default value expression, a functional index or a check + constraint. Note that validation of the specific function is done later in + procedures open_table_from_share and fix_value_generators_fields. + + @param expr the expression to check for validity + @param name used for error reporting + @param source Source of value generator(a generated column, a + regular column with generated default value or + a check constraint). @return false if ok, true otherwise */ -bool pre_validate_value_generator_expr(Item *expression, - const char *column_name, - bool is_gen_col); - +bool pre_validate_value_generator_expr(Item *expression, const char *name, + Value_generator_source source); #endif /* FIELD_INCLUDED */ diff --git a/sql/handler.h b/sql/handler.h index 01d5902aaee0..95e6610a5d7c 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -2766,6 +2766,15 @@ class Alter_inplace_info { */ static const HA_ALTER_FLAGS STORED_GCOL_REEVAL = 1ULL << 45; + // Add check constraint. + static const HA_ALTER_FLAGS ADD_CHECK_CONSTRAINT = 1ULL << 46; + + // Drop check constraint. + static const HA_ALTER_FLAGS DROP_CHECK_CONSTRAINT = 1ULL << 47; + + // Suspend check constraint. + static const HA_ALTER_FLAGS SUSPEND_CHECK_CONSTRAINT = 1ULL << 48; + /** Create options (like MAX_ROWS) for the new version of table. diff --git a/sql/item.cc b/sql/item.cc index c17eb4dd993d..f6bf5a17041a 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -859,30 +859,36 @@ bool Item_field::check_function_as_value_generator(uchar *checker_args) { } int fld_idx = func_args->col_index; - bool is_gen_col = func_args->is_gen_col; DBUG_ASSERT(fld_idx > -1); + /* Don't allow the GC (or default expression) to refer itself or another GC (or default expressions) that is defined after it. */ - if ((field->is_gcol() || + if ((func_args->source != VGS_CHECK_CONSTRAINT) && + (field->is_gcol() || field->has_insert_default_general_value_expression()) && field->field_index >= fld_idx) { - func_args->err_code = is_gen_col ? ER_GENERATED_COLUMN_NON_PRIOR - : ER_DEFAULT_VAL_GENERATED_NON_PRIOR; + func_args->err_code = (func_args->source == VGS_GENERATED_COLUMN) + ? ER_GENERATED_COLUMN_NON_PRIOR + : ER_DEFAULT_VAL_GENERATED_NON_PRIOR; return true; } /* - If a generated column or default expression depends on an auto_increment - column: + If a generated column, default expression or check constraint depends + on an auto_increment column: - calculation of the generated value is done before write_row(), - but the auto_increment value is determined in write_row() by the engine. So this case is forbidden. */ if (field->flags & AUTO_INCREMENT_FLAG) { - func_args->err_code = is_gen_col ? ER_GENERATED_COLUMN_REF_AUTO_INC - : ER_DEFAULT_VAL_GENERATED_REF_AUTO_INC; + func_args->err_code = + (func_args->source == VGS_GENERATED_COLUMN) + ? ER_GENERATED_COLUMN_REF_AUTO_INC + : (func_args->source == VGS_DEFAULT_EXPRESSION) + ? ER_DEFAULT_VAL_GENERATED_REF_AUTO_INC + : ER_CHECK_CONSTRAINT_REFERS_AUTO_INCREMENT_COLUMN; return true; } diff --git a/sql/item.h b/sql/item.h index 7e78987a89f4..ebe71bdfe266 100644 --- a/sql/item.h +++ b/sql/item.h @@ -478,24 +478,30 @@ struct Name_resolution_context { check_function_as_value_generator */ struct Check_function_as_value_generator_parameters { - Check_function_as_value_generator_parameters(int default_error_code, - bool is_generated_column) - : err_code(default_error_code), is_gen_col(is_generated_column) {} + Check_function_as_value_generator_parameters( + int default_error_code, Value_generator_source val_gen_src) + : err_code(default_error_code), source(val_gen_src) {} /// the order of the column in table int col_index{-1}; /// the error code found during check(if any) int err_code; - /// if it is a generated column - bool is_gen_col; + /* + If it is a generated column, default expression or check constraint + expresion value generator. + */ + Value_generator_source source; /// the name of the function which is not allowed const char *banned_function_name{nullptr}; /// Return the correct error code, based on whether or not if we are checking - /// for disallowed functions in generated column expressions or in default - /// value expressions. + /// for disallowed functions in generated column expressions, in default + /// value expressions or in check constraint expression. int get_unnamed_function_error_code() const { - return is_gen_col ? ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED - : ER_DEFAULT_VAL_GENERATED_FUNCTION_IS_NOT_ALLOWED; + return ((source == VGS_GENERATED_COLUMN) + ? ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED + : (source == VGS_DEFAULT_EXPRESSION) + ? ER_DEFAULT_VAL_GENERATED_FUNCTION_IS_NOT_ALLOWED + : ER_CHECK_CONSTRAINT_FUNCTION_IS_NOT_ALLOWED); } }; /* diff --git a/sql/item_func.h b/sql/item_func.h index 276c3ad72209..d01864403e6f 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -892,7 +892,8 @@ class Item_func_connection_id final : public Item_int_func { pointer_cast( checker_args); func_arg->banned_function_name = func_name(); - return func_arg->is_gen_col; + return ((func_arg->source == VGS_GENERATED_COLUMN) || + (func_arg->source == VGS_CHECK_CONSTRAINT)); } }; @@ -1296,7 +1297,8 @@ class Item_func_rand final : public Item_real_func { pointer_cast( checker_args); func_arg->banned_function_name = func_name(); - return func_arg->is_gen_col; + return ((func_arg->source == VGS_GENERATED_COLUMN) || + (func_arg->source == VGS_CHECK_CONSTRAINT)); } private: @@ -2764,7 +2766,9 @@ class Item_var_func : public Item_func { Check_function_as_value_generator_parameters *func_arg = pointer_cast( checker_args); - func_arg->err_code = ER_DEFAULT_VAL_GENERATED_VARIABLES; + func_arg->err_code = (func_arg->source == VGS_CHECK_CONSTRAINT) + ? ER_CHECK_CONSTRAINT_VARIABLES + : ER_DEFAULT_VAL_GENERATED_VARIABLES; return true; } }; @@ -3734,7 +3738,8 @@ class Item_func_uuid_short final : public Item_int_func { pointer_cast( checker_args); func_arg->banned_function_name = func_name(); - return func_arg->is_gen_col; + return ((func_arg->source == VGS_GENERATED_COLUMN) || + (func_arg->source == VGS_CHECK_CONSTRAINT)); } }; diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h index 240f971bb4da..6d3cbe24ec92 100644 --- a/sql/item_strfunc.h +++ b/sql/item_strfunc.h @@ -231,7 +231,7 @@ class Item_func_statement_digest final : public Item_str_ascii_func { pointer_cast( checker_args); func_arg->banned_function_name = func_name(); - return func_arg->is_gen_col; + return (func_arg->source == VGS_GENERATED_COLUMN); } bool resolve_type(THD *) override { @@ -263,7 +263,7 @@ class Item_func_statement_digest_text final : public Item_str_func { pointer_cast( checker_args); func_arg->banned_function_name = func_name(); - return func_arg->is_gen_col; + return (func_arg->source == VGS_GENERATED_COLUMN); } String *val_str(String *) override; }; @@ -584,7 +584,8 @@ class Item_func_sysconst : public Item_str_func { pointer_cast( checker_args); func_arg->banned_function_name = func_name(); - return func_arg->is_gen_col; + return ((func_arg->source == VGS_GENERATED_COLUMN) || + (func_arg->source == VGS_CHECK_CONSTRAINT)); } }; @@ -1222,7 +1223,8 @@ class Item_func_uuid final : public Item_str_func { pointer_cast( checker_args); func_arg->banned_function_name = func_name(); - return func_arg->is_gen_col; + return ((func_arg->source == VGS_GENERATED_COLUMN) || + (func_arg->source == VGS_CHECK_CONSTRAINT)); } }; diff --git a/sql/item_timefunc.h b/sql/item_timefunc.h index 9ebc21dcd9e6..8fcde97a00cb 100644 --- a/sql/item_timefunc.h +++ b/sql/item_timefunc.h @@ -480,7 +480,8 @@ class Item_func_unix_timestamp final : public Item_timeval_func { Check_function_as_value_generator_parameters *func_arg = pointer_cast(p_arg); func_arg->banned_function_name = func_name(); - return func_arg->is_gen_col; + return ((func_arg->source == VGS_GENERATED_COLUMN) || + (func_arg->source == VGS_CHECK_CONSTRAINT)); } }; @@ -1032,7 +1033,8 @@ class Item_func_curtime : public Item_time_func { pointer_cast( checker_args); func_arg->banned_function_name = func_name(); - return func_arg->is_gen_col; + return ((func_arg->source == VGS_GENERATED_COLUMN) || + (func_arg->source == VGS_CHECK_CONSTRAINT)); } }; @@ -1091,7 +1093,8 @@ class Item_func_curdate : public Item_date_func { pointer_cast( checker_args); func_arg->banned_function_name = func_name(); - return func_arg->is_gen_col; + return ((func_arg->source == VGS_GENERATED_COLUMN) || + (func_arg->source == VGS_CHECK_CONSTRAINT)); } }; @@ -1154,7 +1157,8 @@ class Item_func_now : public Item_datetime_func { pointer_cast( checker_args); func_arg->banned_function_name = func_name(); - return func_arg->is_gen_col; + return ((func_arg->source == VGS_GENERATED_COLUMN) || + (func_arg->source == VGS_CHECK_CONSTRAINT)); } }; diff --git a/sql/lex.h b/sql/lex.h index 4a8166283470..83d504da31c8 100644 --- a/sql/lex.h +++ b/sql/lex.h @@ -1,7 +1,7 @@ #ifndef LEX_INCLUDED #define LEX_INCLUDED -/* Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License, version 2.0, @@ -224,6 +224,7 @@ static const SYMBOL symbols[] = { {SYM("ENCLOSED", ENCLOSED)}, {SYM("END", END)}, {SYM("ENDS", ENDS_SYM)}, + {SYM("ENFORCED", ENFORCED_SYM)}, {SYM("ENGINE", ENGINE_SYM)}, {SYM("ENGINES", ENGINES_SYM)}, {SYM("ENUM", ENUM_SYM)}, diff --git a/sql/log_event.cc b/sql/log_event.cc index fcf74433c2a6..c4af87c4abcb 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -11552,6 +11552,10 @@ int Write_rows_log_event::write_row(const Relay_log_info *const rli, DBUG_RETURN(ER_SLAVE_CORRUPT_EVENT); } + // Invoke check constraints on the unpacked row. + if (invoke_table_check_constraints(thd, table)) + DBUG_RETURN(ER_CHECK_CONSTRAINT_VIOLATED); + if (m_curr_row == m_rows_buf) { /* this is the first row to be inserted, we estimate the rows with the size of the first row and use that value to initialize @@ -12009,6 +12013,10 @@ int Update_rows_log_event::do_exec_row(const Relay_log_info *const rli) { if ((error = unpack_current_row(rli, &m_cols_ai, true /*is AI*/))) return error; + // Invoke check constraints on the unpacked row. + if (invoke_table_check_constraints(thd, m_table)) + return ER_CHECK_CONSTRAINT_VIOLATED; + /* Now we have the right row to update. The old row (the one we're looking for) is in record[1] and the new row is in record[0]. diff --git a/sql/mdl.cc b/sql/mdl.cc index 7d0ec85815d6..755b816b29c8 100644 --- a/sql/mdl.cc +++ b/sql/mdl.cc @@ -1,4 +1,4 @@ -/* Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2007, 2019, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License, version 2.0, @@ -127,7 +127,8 @@ PSI_stage_info MDL_key::m_namespace_to_wait_state_name[NAMESPACE_END] = { {0, "Waiting for column statistics lock", 0, PSI_DOCUMENT_ME}, {0, "Waiting for backup lock", 0, PSI_DOCUMENT_ME}, {0, "Waiting for resource groups metadata lock", 0, PSI_DOCUMENT_ME}, - {0, "Waiting for foreign key metadata lock", 0, PSI_DOCUMENT_ME}}; + {0, "Waiting for foreign key metadata lock", 0, PSI_DOCUMENT_ME}, + {0, "Waiting for check constraint metadata lock", 0, PSI_DOCUMENT_ME}}; #ifdef HAVE_PSI_INTERFACE void MDL_key::init_psi_keys() { @@ -814,6 +815,7 @@ class MDL_lock { case MDL_key::BACKUP_LOCK: case MDL_key::RESOURCE_GROUPS: case MDL_key::FOREIGN_KEY: + case MDL_key::CHECK_CONSTRAINT: return &m_scoped_lock_strategy; default: return &m_object_lock_strategy; diff --git a/sql/mdl.h b/sql/mdl.h index b58620c0754a..116e83211c26 100644 --- a/sql/mdl.h +++ b/sql/mdl.h @@ -1,6 +1,6 @@ #ifndef MDL_H #define MDL_H -/* Copyright (c) 2009, 2018, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2009, 2019, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License, version 2.0, @@ -374,6 +374,7 @@ struct MDL_key { and some administrative statements. - RESOURCE_GROUPS is for resource groups. - FOREIGN_KEY is for foreign key names. + - CHECK_CONSTRAINT is for check constraint names. Note that requests waiting for user-level locks get special treatment - waiting is aborted if connection to client is lost. */ @@ -395,6 +396,7 @@ struct MDL_key { BACKUP_LOCK, RESOURCE_GROUPS, FOREIGN_KEY, + CHECK_CONSTRAINT, /* This should be the last ! */ NAMESPACE_END }; diff --git a/sql/ndb_dd_upgrade_table.cc b/sql/ndb_dd_upgrade_table.cc index d1481343ad77..93bd4831f9d0 100644 --- a/sql/ndb_dd_upgrade_table.cc +++ b/sql/ndb_dd_upgrade_table.cc @@ -1,4 +1,4 @@ -/* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License, version 2.0, @@ -414,8 +414,8 @@ static bool fix_generated_columns_for_upgrade(THD *thd, if (sql_field->gcol_info && (*field_ptr)->gcol_info) { if (unpack_value_generator( - thd, table, *field_ptr, &(*field_ptr)->gcol_info, false, false, - &error_reported)) { + thd, table, &(*field_ptr)->gcol_info, VGS_GENERATED_COLUMN, + (*field_ptr)->field_name, *field_ptr, false, &error_reported)) { error= false; break; } @@ -964,7 +964,7 @@ bool migrate_table_to_dd(THD *thd, std::unique_ptr table_def = dd::create_dd_user_table( thd, *sch_obj, to_table_name, &create_info, alter_info.create_list, key_info_buffer, key_count, Alter_info::ENABLE, fk_key_info_buffer, - fk_number, table.file); + fk_number, nullptr, table.file); if (!table_def || thd->dd_client()->store(table_def.get())) { ndb_log_error("Error in Creating DD entry for %s.%s", diff --git a/sql/parse_tree_column_attrs.h b/sql/parse_tree_column_attrs.h index a44d039153f4..9b656792501e 100644 --- a/sql/parse_tree_column_attrs.h +++ b/sql/parse_tree_column_attrs.h @@ -66,7 +66,7 @@ class PT_column_attr_base : public Parse_tree_node_tmpl { typedef decltype(Alter_info::flags) alter_info_flags_t; virtual void apply_type_flags(ulong *) const {} - virtual void apply_alter_info_flags(uint *) const {} + virtual void apply_alter_info_flags(ulonglong *) const {} virtual void apply_comment(LEX_STRING *) const {} virtual void apply_default_value(Item **) const {} virtual void apply_gen_default_value(Value_generator **) {} @@ -126,7 +126,7 @@ class PT_unique_key_column_attr : public PT_column_attr_base { *type_flags |= UNIQUE_FLAG; } - virtual void apply_alter_info_flags(uint *flags) const { + virtual void apply_alter_info_flags(ulonglong *flags) const { *flags |= Alter_info::ALTER_ADD_INDEX; } }; @@ -142,7 +142,7 @@ class PT_primary_key_column_attr : public PT_column_attr_base { *type_flags |= PRI_KEY_FLAG | NOT_NULL_FLAG; } - virtual void apply_alter_info_flags(uint *flags) const { + virtual void apply_alter_info_flags(ulonglong *flags) const { *flags |= Alter_info::ALTER_ADD_INDEX; } }; @@ -271,7 +271,7 @@ class PT_serial_default_value_column_attr : public PT_column_attr_base { virtual void apply_type_flags(ulong *type_flags) const { *type_flags |= AUTO_INCREMENT_FLAG | NOT_NULL_FLAG | UNIQUE_FLAG; } - virtual void apply_alter_info_flags(uint *flags) const { + virtual void apply_alter_info_flags(ulonglong *flags) const { *flags |= Alter_info::ALTER_ADD_INDEX; } virtual bool contextualize(Column_parse_context *pc) { diff --git a/sql/parse_tree_nodes.h b/sql/parse_tree_nodes.h index 7274eff3e085..1bf8a1c7176c 100644 --- a/sql/parse_tree_nodes.h +++ b/sql/parse_tree_nodes.h @@ -29,6 +29,7 @@ #include #include "binary_log_types.h" +#include "binlog_event.h" // UNDEFINED_SERVER_VERSION #include "lex_string.h" #include "m_ctype.h" #include "my_base.h" @@ -63,7 +64,8 @@ #include "sql/sp_head.h" // sp_head #include "sql/sql_admin.h" // Sql_cmd_shutdown etc. #include "sql/sql_alter.h" -#include "sql/sql_class.h" // THD +#include "sql/sql_check_constraint.h" // Sql_check_constraint_spec +#include "sql/sql_class.h" // THD #include "sql/sql_cmd_srs.h" #include "sql/sql_exchange.h" #include "sql/sql_lex.h" // LEX @@ -3254,16 +3256,40 @@ class PT_create_table_default_collation : public PT_create_table_option { bool contextualize(Table_ddl_parse_context *pc) override; }; -class PT_check_constraint : public PT_table_constraint_def { +class PT_check_constraint final : public PT_table_constraint_def { typedef PT_table_constraint_def super; - - Item *expr; + Sql_check_constraint_spec cc_spec; public: - explicit PT_check_constraint(Item *expr) : expr(expr) {} + explicit PT_check_constraint(LEX_STRING &name, Item *expr, bool is_enforced) { + cc_spec.name = name; + cc_spec.check_expr = expr; + cc_spec.is_enforced = is_enforced; + } + void set_column_name(const LEX_STRING &name) { cc_spec.column_name = name; } bool contextualize(Table_ddl_parse_context *pc) override { - return super::contextualize(pc) && expr->itemize(pc, &expr); + /* + On slave, add check constraint only if master server is on version + supporting check constraints. Check constraint support is introduced + in 80015. + */ + THD *thd = pc->thd; + if ((thd->system_thread & + (SYSTEM_THREAD_SLAVE_SQL | SYSTEM_THREAD_SLAVE_WORKER)) && + (thd->variables.original_server_version == UNDEFINED_SERVER_VERSION || + thd->variables.original_server_version < 80015)) + return false; + + if (super::contextualize(pc) || + cc_spec.check_expr->itemize(pc, &cc_spec.check_expr)) + return true; + + if (pc->alter_info->check_constraint_spec_list.push_back(&cc_spec)) + return true; + + pc->alter_info->flags |= Alter_info::ADD_CHECK_CONSTRAINT; + return false; } }; @@ -3272,20 +3298,22 @@ class PT_column_def : public PT_table_element { const LEX_STRING field_ident; PT_field_def_base *field_def; - - /// Currently we ignore that constraint in the executor. - PT_table_constraint_def *opt_column_constraint; + // For column check constraint. + PT_check_constraint *opt_column_constraint{nullptr}; const char *opt_place; public: PT_column_def(const LEX_STRING &field_ident, PT_field_def_base *field_def, - PT_table_constraint_def *opt_column_constraint, + PT_table_constraint_def *column_constraint, const char *opt_place = NULL) - : field_ident(field_ident), - field_def(field_def), - opt_column_constraint(opt_column_constraint), - opt_place(opt_place) {} + : field_ident(field_ident), field_def(field_def), opt_place(opt_place) { + if (column_constraint) { + opt_column_constraint = + down_cast(column_constraint); + opt_column_constraint->set_column_name(field_ident); + } + } bool contextualize(Table_ddl_parse_context *pc) override; }; @@ -3829,6 +3857,31 @@ class PT_alter_table_drop_key final : public PT_alter_table_drop { name) {} }; +class PT_alter_table_drop_check_constraint final : public PT_alter_table_drop { + public: + explicit PT_alter_table_drop_check_constraint(const char *name) + : PT_alter_table_drop(Alter_drop::CHECK_CONSTRAINT, + Alter_info::DROP_CHECK_CONSTRAINT, name) {} +}; + +class PT_alter_table_check_constraint final : public PT_alter_table_action { + typedef PT_alter_table_action super; + + public: + explicit PT_alter_table_check_constraint(const char *name, bool state) + : super(state ? Alter_info::ENFORCE_CHECK_CONSTRAINT + : Alter_info::SUSPEND_CHECK_CONSTRAINT), + cc_state(Alter_state::Type::CHECK_CONSTRAINT, name, state) {} + + bool contextualize(Table_ddl_parse_context *pc) override { + return (super::contextualize(pc) || + pc->alter_info->alter_state_list.push_back(&cc_state)); + } + + private: + Alter_state cc_state; +}; + class PT_alter_table_enable_keys final : public PT_alter_table_action { typedef PT_alter_table_action super; diff --git a/sql/sql_alter.cc b/sql/sql_alter.cc index 52ec81787cd6..6a5c6695b963 100644 --- a/sql/sql_alter.cc +++ b/sql/sql_alter.cc @@ -1,4 +1,4 @@ -/* Copyright (c) 2010, 2018, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2010, 2019, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License, version 2.0, @@ -63,6 +63,11 @@ Alter_info::Alter_info(const Alter_info &rhs, MEM_ROOT *mem_root) alter_index_visibility_list(mem_root, rhs.alter_index_visibility_list.begin(), rhs.alter_index_visibility_list.end()), + alter_state_list(mem_root, rhs.alter_state_list.begin(), + rhs.alter_state_list.end()), + check_constraint_spec_list(mem_root, + rhs.check_constraint_spec_list.begin(), + rhs.check_constraint_spec_list.end()), create_list(rhs.create_list, mem_root), flags(rhs.flags), keys_onoff(rhs.keys_onoff), diff --git a/sql/sql_alter.h b/sql/sql_alter.h index 375e6fadd567..804068541bf1 100644 --- a/sql/sql_alter.h +++ b/sql/sql_alter.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2010, 2018, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2010, 2019, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License, version 2.0, @@ -36,11 +36,12 @@ #include "nullable.h" #include "sql/dd/types/column.h" #include "sql/gis/srid.h" -#include "sql/mdl.h" // MDL_request -#include "sql/mem_root_array.h" // Mem_root_array -#include "sql/sql_cmd.h" // Sql_cmd -#include "sql/sql_cmd_ddl_table.h" // Sql_cmd_ddl_table -#include "sql/sql_list.h" // List +#include "sql/mdl.h" // MDL_request +#include "sql/mem_root_array.h" // Mem_root_array +#include "sql/sql_check_constraint.h" // Sql_check_constraint_spec_list +#include "sql/sql_cmd.h" // Sql_cmd +#include "sql/sql_cmd_ddl_table.h" // Sql_cmd_ddl_table +#include "sql/sql_list.h" // List #include "sql/thr_malloc.h" class Create_field; @@ -55,13 +56,13 @@ struct TABLE_LIST; using Mysql::Nullable; /** - Class representing DROP COLUMN, DROP KEY and DROP FOREIGN KEY - clauses in ALTER TABLE statement. + Class representing DROP COLUMN, DROP KEY, DROP FOREIGN KEY and DROP CHECK + CONSTRAINT clauses in ALTER TABLE statement. */ class Alter_drop { public: - enum drop_type { KEY, COLUMN, FOREIGN_KEY }; + enum drop_type { KEY, COLUMN, FOREIGN_KEY, CHECK_CONSTRAINT }; const char *name; drop_type type; @@ -160,6 +161,24 @@ class Alter_rename_key { : old_name(old_name_arg), new_name(new_name_arg) {} }; +/** + Class which instances represents state(i.e ENFORCED | NOT ENFORCED) of + CHECK CONSTRAINT in ALTER TABLE statement. +*/ + +class Alter_state { + public: + enum class Type { CHECK_CONSTRAINT }; + const char *name; + Type type; + bool state; + + Alter_state(Type par_type, const char *par_name, bool par_state) + : name(par_name), type(par_type), state(par_state) { + DBUG_ASSERT(par_name != nullptr); + } +}; + /** Data describing the table being created by CREATE TABLE or altered by ALTER TABLE. @@ -176,107 +195,119 @@ class Alter_info { type of index to be added/dropped. */ - enum Alter_info_flag : uint { + enum Alter_info_flag : ulonglong { /// Set for ADD [COLUMN] - ALTER_ADD_COLUMN = 1UL << 0, + ALTER_ADD_COLUMN = 1ULL << 0, /// Set for DROP [COLUMN] - ALTER_DROP_COLUMN = 1UL << 1, + ALTER_DROP_COLUMN = 1ULL << 1, /// Set for CHANGE [COLUMN] | MODIFY [CHANGE] /// Set by mysql_recreate_table() - ALTER_CHANGE_COLUMN = 1UL << 2, + ALTER_CHANGE_COLUMN = 1ULL << 2, /// Set for ADD INDEX | ADD KEY | ADD PRIMARY KEY | ADD UNIQUE KEY | /// ADD UNIQUE INDEX | ALTER ADD [COLUMN] - ALTER_ADD_INDEX = 1UL << 3, + ALTER_ADD_INDEX = 1ULL << 3, /// Set for DROP PRIMARY KEY | DROP FOREIGN KEY | DROP KEY | DROP INDEX - ALTER_DROP_INDEX = 1UL << 4, + ALTER_DROP_INDEX = 1ULL << 4, /// Set for RENAME [TO] - ALTER_RENAME = 1UL << 5, + ALTER_RENAME = 1ULL << 5, /// Set for ORDER BY - ALTER_ORDER = 1UL << 6, + ALTER_ORDER = 1ULL << 6, /// Set for table_options - ALTER_OPTIONS = 1UL << 7, + ALTER_OPTIONS = 1ULL << 7, /// Set for ALTER [COLUMN] ... SET DEFAULT ... | DROP DEFAULT - ALTER_CHANGE_COLUMN_DEFAULT = 1UL << 8, + ALTER_CHANGE_COLUMN_DEFAULT = 1ULL << 8, /// Set for DISABLE KEYS | ENABLE KEYS - ALTER_KEYS_ONOFF = 1UL << 9, + ALTER_KEYS_ONOFF = 1ULL << 9, /// Set for FORCE /// Set for ENGINE(same engine) /// Set by mysql_recreate_table() - ALTER_RECREATE = 1UL << 10, + ALTER_RECREATE = 1ULL << 10, /// Set for ADD PARTITION - ALTER_ADD_PARTITION = 1UL << 11, + ALTER_ADD_PARTITION = 1ULL << 11, /// Set for DROP PARTITION - ALTER_DROP_PARTITION = 1UL << 12, + ALTER_DROP_PARTITION = 1ULL << 12, /// Set for COALESCE PARTITION - ALTER_COALESCE_PARTITION = 1UL << 13, + ALTER_COALESCE_PARTITION = 1ULL << 13, /// Set for REORGANIZE PARTITION ... INTO - ALTER_REORGANIZE_PARTITION = 1UL << 14, + ALTER_REORGANIZE_PARTITION = 1ULL << 14, /// Set for partition_options - ALTER_PARTITION = 1UL << 15, + ALTER_PARTITION = 1ULL << 15, /// Set for LOAD INDEX INTO CACHE ... PARTITION /// Set for CACHE INDEX ... PARTITION - ALTER_ADMIN_PARTITION = 1UL << 16, + ALTER_ADMIN_PARTITION = 1ULL << 16, /// Set for REORGANIZE PARTITION - ALTER_TABLE_REORG = 1UL << 17, + ALTER_TABLE_REORG = 1ULL << 17, /// Set for REBUILD PARTITION - ALTER_REBUILD_PARTITION = 1UL << 18, + ALTER_REBUILD_PARTITION = 1ULL << 18, /// Set for partitioning operations specifying ALL keyword - ALTER_ALL_PARTITION = 1UL << 19, + ALTER_ALL_PARTITION = 1ULL << 19, /// Set for REMOVE PARTITIONING - ALTER_REMOVE_PARTITIONING = 1UL << 20, + ALTER_REMOVE_PARTITIONING = 1ULL << 20, /// Set for ADD FOREIGN KEY - ADD_FOREIGN_KEY = 1UL << 21, + ADD_FOREIGN_KEY = 1ULL << 21, /// Set for DROP FOREIGN KEY - DROP_FOREIGN_KEY = 1UL << 22, + DROP_FOREIGN_KEY = 1ULL << 22, /// Set for EXCHANGE PARITION - ALTER_EXCHANGE_PARTITION = 1UL << 23, + ALTER_EXCHANGE_PARTITION = 1ULL << 23, /// Set by Sql_cmd_alter_table_truncate_partition::execute() - ALTER_TRUNCATE_PARTITION = 1UL << 24, + ALTER_TRUNCATE_PARTITION = 1ULL << 24, /// Set for ADD [COLUMN] FIRST | AFTER - ALTER_COLUMN_ORDER = 1UL << 25, + ALTER_COLUMN_ORDER = 1ULL << 25, /// Set for RENAME INDEX - ALTER_RENAME_INDEX = 1UL << 26, + ALTER_RENAME_INDEX = 1ULL << 26, /// Set for discarding the tablespace - ALTER_DISCARD_TABLESPACE = 1UL << 27, + ALTER_DISCARD_TABLESPACE = 1ULL << 27, /// Set for importing the tablespace - ALTER_IMPORT_TABLESPACE = 1UL << 28, + ALTER_IMPORT_TABLESPACE = 1ULL << 28, /// Means that the visibility of an index is changed. - ALTER_INDEX_VISIBILITY = 1UL << 29, + ALTER_INDEX_VISIBILITY = 1ULL << 29, + + /// Set for SECONDARY LOAD + ALTER_SECONDARY_LOAD = 1ULL << 30, + + /// Set for SECONDARY UNLOAD + ALTER_SECONDARY_UNLOAD = 1ULL << 31, + + /// Set for add check constraint. + ADD_CHECK_CONSTRAINT = 1ULL << 32, - /// Set for SECONDARY_LOAD - ALTER_SECONDARY_LOAD = 1UL << 30, + /// Set for drop check constraint. + DROP_CHECK_CONSTRAINT = 1ULL << 33, - /// Set for SECONDARY_UNLOAD - ALTER_SECONDARY_UNLOAD = 1UL << 31, + /// Set for check constraint enforce. + ENFORCE_CHECK_CONSTRAINT = 1ULL << 34, + + /// Set for check constraint suspend. + SUSPEND_CHECK_CONSTRAINT = 1ULL << 35, }; enum enum_enable_or_disable { LEAVE_AS_IS, ENABLE, DISABLE }; @@ -350,10 +381,16 @@ class Alter_info { /// Indexes whose visibilities are to be changed. Mem_root_array alter_index_visibility_list; + /// List of check constraints whose state is changed. + Mem_root_array alter_state_list; + + /// Check constraints specification for CREATE and ALTER TABLE operations. + Sql_check_constraint_spec_list check_constraint_spec_list; + // List of columns, used by both CREATE and ALTER TABLE. List create_list; // Type of ALTER TABLE operation. - uint flags; + ulonglong flags; // Enable or disable keys. enum_enable_or_disable keys_onoff; // List of partitions. @@ -383,6 +420,8 @@ class Alter_info { key_list(mem_root), alter_rename_key_list(mem_root), alter_index_visibility_list(mem_root), + alter_state_list(mem_root), + check_constraint_spec_list(mem_root), flags(0), keys_onoff(LEAVE_AS_IS), num_parts(0), diff --git a/sql/sql_base.cc b/sql/sql_base.cc index cb11dab1003b..ef0791c0fced 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -1,4 +1,4 @@ -/* Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License, version 2.0, @@ -9138,6 +9138,57 @@ static bool check_inserting_record(THD *thd, Field **ptr) { return thd->is_error(); } +/** + Invoke check constraints defined on the table. + + @param thd Thread handle. + @param table Instance of TABLE. + + @retval false If all enforced check constraints are satisfied. + @retval true Otherwise. +*/ + +bool invoke_table_check_constraints(THD *thd, const TABLE *table) { + if (table->table_check_constraint_list != nullptr) { + for (auto &table_cc : *table->table_check_constraint_list) { + if (table_cc->is_enforced()) { + /* + Set the columns used by the enforced check constraint expression in + the TABLE read_set. + */ + bitmap_union(const_cast
(table)->read_set, + &table_cc->value_generator()->base_columns_map); + + // Validate check constraint. + bool is_constraint_violated = + (!table_cc->value_generator()->expr_item->val_bool() && + !table_cc->value_generator()->expr_item->null_value); + + /* + If check constraint is violated then report an error. If expression + operand types are incompatible and reported error in conversion even + then report a more user friendly error. Sql_conditions of DA still has + a conversion error in the error stack. + */ + if (is_constraint_violated || thd->is_error()) { + if (thd->is_error()) thd->clear_error(); + const char *cc_name = table_cc->name().str; + /* + Use actual check constraint name to report error if constraint + names ares adjusted for the operation. + */ + if (thd->m_cc_adjusted_names_map != nullptr) + cc_name = thd->m_cc_adjusted_names_map->actual_name(cc_name); + my_error(ER_CHECK_CONSTRAINT_VIOLATED, MYF(0), cc_name); + return true; + } + } + } + } + + return false; +} + /** Check if SQL-statement is INSERT/INSERT SELECT/REPLACE/REPLACE SELECT and trigger event is ON INSERT. When this condition is true that means diff --git a/sql/sql_base.h b/sql/sql_base.h index 3774e63195fd..04cc22dc6e9e 100644 --- a/sql/sql_base.h +++ b/sql/sql_base.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2010, 2018, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2010, 2019, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License, version 2.0, @@ -219,6 +219,17 @@ bool fill_record(THD *thd, TABLE *table, Field **field, List &values, bool check_record(THD *thd, Field **ptr); +/** + Invoke check constraints defined on the table. + + @param thd Thread handle. + @param table Instance of TABLE. + + @retval false If all enforced check constraints are satisfied. + @retval true Otherwise. +*/ +bool invoke_table_check_constraints(THD *thd, const TABLE *table); + Field *find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *first_table, TABLE_LIST *last_table, Item **ref, find_item_error_report_type report_error, diff --git a/sql/sql_check_constraint.cc b/sql/sql_check_constraint.cc new file mode 100644 index 000000000000..931c96a4cfca --- /dev/null +++ b/sql/sql_check_constraint.cc @@ -0,0 +1,116 @@ +/* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License, version 2.0, + as published by the Free Software Foundation. + + This program is also distributed with certain software (including + but not limited to OpenSSL) that is licensed under separate terms, + as designated in a particular file or component or in included license + documentation. The authors of MySQL hereby grant you an additional + permission to link the program and your derivative works with the + separately licensed software that they have included with MySQL. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License, version 2.0, for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ + +#include "sql_check_constraint.h" + +#include "item_func.h" // print +#include "mysqld_error.h" // ER_* +#include "sql_parse.h" // check_string_char_length +#include "sql_string.h" // String +#include "strfunc.h" // make_lex_string_root +#include "thd_raii.h" // Sql_mode_parse_guard + +bool Sql_check_constraint_spec::pre_validate() { + /* + Validate check constraint expression name. If name is not specified for the + check constraint then name is generated before calling this method. + */ + if (check_string_char_length(to_lex_cstring(name), "", NAME_CHAR_LEN, + system_charset_info, 1)) { + my_error(ER_TOO_LONG_IDENT, MYF(0), name.str); + return true; + } + + /* + If this is a column check constraint then expression should refer only its + column. + */ + if (column_name.length != 0) { + if (!expr_refers_to_only_column(column_name.str)) { + my_error(ER_COLUMN_CHECK_CONSTRAINT_REFERENCES_OTHER_COLUMN, MYF(0), + name.str); + return true; + } + } + + // Check constraint expression must be a boolean expression. + if (!check_expr->is_bool_func()) { + my_error(ER_NON_BOOLEAN_EXPR_FOR_CHECK_CONSTRAINT, MYF(0), name.str); + return true; + } + + /* + Pre-validate expression to determine if it is allowed for the check + constraint. + */ + if (pre_validate_value_generator_expr(check_expr, name.str, + VGS_CHECK_CONSTRAINT)) + return true; + + return false; +} + +void Sql_check_constraint_spec::print_expr(THD *thd, String &out) { + out.length(0); + Sql_mode_parse_guard parse_guard(thd); + auto flags = enum_query_type(QT_NO_DB | QT_NO_TABLE | QT_FORCE_INTRODUCERS); + check_expr->print(thd, &out, flags); +} + +bool Sql_check_constraint_spec::expr_refers_column(const char *column_name) { + List fields; + check_expr->walk(&Item::collect_item_field_processor, Item::WALK_POSTFIX, + (uchar *)&fields); + + Item_field *cur_item; + List_iterator fields_it(fields); + while ((cur_item = fields_it++)) { + if (cur_item->type() == Item::FIELD_ITEM && + !my_strcasecmp(system_charset_info, cur_item->field_name, column_name)) + return true; + } + return false; +} + +bool Sql_check_constraint_spec::expr_refers_to_only_column( + const char *column_name) { + List fields; + check_expr->walk(&Item::collect_item_field_processor, Item::WALK_POSTFIX, + (uchar *)&fields); + + // Expression does not refer to any columns. + if (fields.elements == 0) return false; + + Item_field *cur_item; + List_iterator fields_it(fields); + while ((cur_item = fields_it++)) { + // Expression refers to some other column. + if (cur_item->type() == Item::FIELD_ITEM && + my_strcasecmp(system_charset_info, cur_item->field_name, column_name)) + return false; + } + return true; +} + +Sql_table_check_constraint::~Sql_table_check_constraint() { + if (m_val_gen != nullptr) delete m_val_gen; +} diff --git a/sql/sql_check_constraint.h b/sql/sql_check_constraint.h new file mode 100644 index 000000000000..3c74ffe009c0 --- /dev/null +++ b/sql/sql_check_constraint.h @@ -0,0 +1,254 @@ +/* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License, version 2.0, + as published by the Free Software Foundation. + + This program is also distributed with certain software (including + but not limited to OpenSSL) that is licensed under separate terms, + as designated in a particular file or component or in included license + documentation. The authors of MySQL hereby grant you an additional + permission to link the program and your derivative works with the + separately licensed software that they have included with MySQL. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License, version 2.0, for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ + +#ifndef SQL_CHECK_CONSTRAINT_INCLUDED +#define SQL_CHECK_CONSTRAINT_INCLUDED + +#include + +#include "lex_string.h" // LEX_STRING +#include "mem_root_array.h" // Mem_root_array +#include "sql/dd/string_type.h" // dd::String_type + +class Item; +class String; +struct TABLE; +class THD; +class Value_generator; + +/** + Class to represent the check constraint specifications obtained from the SQL + statement parse. +*/ +class Sql_check_constraint_spec { + public: + /* + Validate check constraint name, perform per item-type to check if the + expression is allowed for the check constraint. Check expression is + pre-validated at this stage. Validation of specific functions in expression + is done later in the method open_table_from_share. + + @retval false Success. + @retval true Failure. + */ + bool pre_validate(); + + /* + Write check constraint expression into a String with proper syntax. + + @param[in] THD Thread handle. + @param[out] out Check constraint expression. + */ + void print_expr(THD *thd, String &out); + + /* + Method to check if column "column_name" referred in the check constraint + expression. + + @param[in] column_name Column name. + + @retval true If column name is referenced in the check expression. + @retval false Otherwise. + */ + bool expr_refers_column(const char *column_name); + + /* + Method to check if constraint expresssion refers to only "column_name" + column of the table. + + @param[in] column_name Column name. + + @retval true If expression refers to only "column_name". + @retval false If expression refers to more than one column + or if expression does not refers to "column_name". + */ + bool expr_refers_to_only_column(const char *column_name); + + public: + /// Name of the check constraint. + LEX_STRING name{nullptr, 0}; + + /// Check constraint expression. + Item *check_expr{nullptr}; + + /// Name of the column if check clause is defined at the column level. + LEX_STRING column_name{nullptr, 0}; + + /// Check constraint state (enforced/not enforced) + bool is_enforced{true}; +}; + +/** + Class to represent check constraint in the TABLE_SHARE. + + The instance of Sql_check_constraint_share contains information as name, + state and expression in string form. These informations are filled from + the data-dictionary. The check expression is not in itemized (materialized) + form here. +*/ +class Sql_check_constraint_share { + public: + // Default check constraint. + Sql_check_constraint_share() = default; + + Sql_check_constraint_share(const LEX_CSTRING &name, + const LEX_CSTRING &expr_str, bool is_enforced) + : m_name(name), m_expr_str(expr_str), m_is_enforced(is_enforced) {} + + ~Sql_check_constraint_share() { + if (m_name.str != nullptr) delete m_name.str; + if (m_expr_str.str != nullptr) delete m_expr_str.str; + } + + // Constraint name. + LEX_CSTRING &name() { return m_name; } + // Check expression in string form. + LEX_CSTRING &expr_str() { return m_expr_str; } + // Check constraint state (enforced / not enforced) + bool is_enforced() { return m_is_enforced; } + + private: + // Check constraint name. + LEX_CSTRING m_name{nullptr, 0}; + + // Check constraint expression. + LEX_CSTRING m_expr_str{nullptr, 0}; + + // Check constraint state. + bool m_is_enforced{true}; + + private: + // Delete default copy and assignment operator to avoid accidental destruction + // of shallow copied Sql_table_check_constraint_share objects. + Sql_check_constraint_share(const Sql_check_constraint_share &) = delete; + Sql_check_constraint_share &operator=(const Sql_check_constraint_share &) = + delete; +}; + +/** + Class to represent check constraint in the TABLE instance. + + The Sql_table_check_constraint is a Sql_check_constraint_share with reference + to the parent TABLE instance and itemized (materialized) form of check + constraint expression. + Sql_table_check_constraint is prepared from the Sql_check_constraint_share of + TABLE_SHARE instance. +*/ +class Sql_table_check_constraint : public Sql_check_constraint_share { + public: + Sql_table_check_constraint() = default; + + Sql_table_check_constraint(const LEX_CSTRING &name, + const LEX_CSTRING &expr_str, bool is_enforced, + Value_generator *val_gen, TABLE *table) + : Sql_check_constraint_share(name, expr_str, is_enforced), + m_val_gen(val_gen), + m_table(table) {} + + ~Sql_table_check_constraint(); + + // Value generator. + Value_generator *value_generator() { return m_val_gen; } + void set_value_generator(Value_generator *val_gen) { m_val_gen = val_gen; } + + // Reference to owner table. + TABLE *table() const { return m_table; } + + private: + // Value generator for the check constraint expression. + Value_generator *m_val_gen{nullptr}; + + // Parent table reference. + TABLE *m_table{nullptr}; + + private: + // Delete default copy and assignment operator to avoid accidental destruction + // of shallow copied Sql_table_check_constraint objects. + Sql_table_check_constraint(const Sql_table_check_constraint &) = delete; + Sql_table_check_constraint &operator=(const Sql_table_check_constraint &) = + delete; +}; + +// Type for the list of Sql_check_constraint_spec elements. +using Sql_check_constraint_spec_list = + Mem_root_array; + +// Type for the list of Sql_check_constraint_share elements. +using Sql_check_constraint_share_list = + Mem_root_array; + +// Type for the list of Sql_table_check_constraint elements. +using Sql_table_check_constraint_list = + Mem_root_array; + +/** + Class to represent the adjusted check constraint names to actual check + constraint names during ALTER TABLE operation. + + During ALTER TABLE operation the check constraint names of a table is + adjusted to avoid check constraint name conflicts and restored after older + table version is either dropped or when new version is renamed to table + name. Instance of this class holds the mapping between adjusted name to + actual check constraint names. Actual names are required to restore and also + to report errors with correct check constraint name. Class is a wrapper over + a std::map class. +*/ +class Check_constraints_adjusted_names_map final { + public: + Check_constraints_adjusted_names_map() = default; + /** + Method to insert adjusted name and actual name to map. + + @param adjusted_name Adjusted name of check constraint. + @param actual_name Actual name of check constraint. + */ + void insert(const char *adjusted_name, const char *actual_name) { + m_names_map.insert({adjusted_name, actual_name}); + } + /** + Method to get actual check constraint name from the adjusted name. + + @param adjusted_name Adjusted name of check constraint. + + @retval Actual name of check constraint. + */ + const char *actual_name(const char *adjusted_name) { + auto name = m_names_map.find(adjusted_name); + DBUG_ASSERT(name != m_names_map.end()); + return name->second; + } + /** + Method to check if map is empty. + + @retval true If map is empty. + @retval false Otherwise. + */ + bool empty() { return m_names_map.empty(); } + /** + Method to clear map. + */ + void clear() { m_names_map.clear(); } + + private: + std::map m_names_map; +}; +#endif // SQL_CHECK_CONSTRAINT_INCLUDED diff --git a/sql/sql_class.h b/sql/sql_class.h index ccfd6778ecc2..b8c77bfe2255 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License, version 2.0, @@ -149,6 +149,7 @@ class Time_zone; class sp_cache; struct Binlog_user_var_event; struct LOG_INFO; +class Check_constraints_adjusted_names_map; typedef struct user_conn USER_CONN; struct MYSQL_LOCK; @@ -2428,6 +2429,12 @@ class THD : public MDL_context_owner, // We don't want to load/unload plugins for unit tests. bool m_enable_plugins; + /* + Map of check constraints adjusted names to actual names. Needed for error + reporting during ALTER TABLE. + */ + Check_constraints_adjusted_names_map *m_cc_adjusted_names_map{nullptr}; + THD(bool enable_plugins = true); /* diff --git a/sql/sql_db.cc b/sql/sql_db.cc index a2b95e3c3aed..949ee2f38f4c 100644 --- a/sql/sql_db.cc +++ b/sql/sql_db.cc @@ -1,5 +1,5 @@ /* - Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. + Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License, version 2.0, @@ -585,6 +585,7 @@ bool mysql_rm_db(THD *thd, const LEX_CSTRING &db, bool if_exists) { if (lock_table_names(thd, tables, NULL, thd->variables.lock_wait_timeout, 0) || rm_table_do_discovery_and_lock_fk_tables(thd, tables) || + lock_check_constraint_names(thd, tables) || Events::lock_schema_events(thd, *schema) || lock_db_routines(thd, *schema) || lock_trigger_names(thd, tables)) DBUG_RETURN(true); diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 9580685e0c8b..5d1b24a5b814 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -1,5 +1,5 @@ /* - Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. + Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License, version 2.0, @@ -612,6 +612,15 @@ bool Sql_cmd_insert_values::execute_inner(THD *thd) { } } + if (invoke_table_check_constraints(thd, insert_table)) { + if (thd->is_error()) { + has_error = true; + break; + } + // continue when IGNORE clause is used. + continue; + } + const int check_result = table_list->view_check_option(thd); if (check_result == VIEW_CHECK_SKIP) continue; @@ -1753,6 +1762,11 @@ bool write_record(THD *thd, TABLE *table, COPY_INFO *info, COPY_INFO *update) { if (!insert_id_consumed) table->file->restore_auto_increment(prev_insert_id); + if (invoke_table_check_constraints(thd, table)) { + if (thd->is_error()) goto before_trg_err; + goto ok_or_after_trg_err; // return false when IGNORE clause is used + } + /* CHECK OPTION for VIEW ... ON DUPLICATE KEY UPDATE ... */ { const TABLE_LIST *inserted_view = @@ -2095,6 +2109,12 @@ bool Query_result_insert::send_data(THD *thd, List &values) { table->auto_increment_field_not_null = false; DBUG_RETURN(true); } + + if (invoke_table_check_constraints(thd, table)) { + // return false when IGNORE clause is used. + DBUG_RETURN(thd->is_error()); + } + if (table_list) // Not CREATE ... SELECT { switch (table_list->view_check_option(thd)) { diff --git a/sql/sql_load.cc b/sql/sql_load.cc index fca14b595e1b..787dfb8b09d5 100644 --- a/sql/sql_load.cc +++ b/sql/sql_load.cc @@ -1,5 +1,5 @@ /* - Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. + Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License, version 2.0, @@ -778,6 +778,12 @@ bool Sql_cmd_load_table::read_fixed_length(THD *thd, COPY_INFO &info, TRG_EVENT_INSERT, table->s->fields)) DBUG_RETURN(true); + if (invoke_table_check_constraints(thd, table)) { + if (thd->is_error()) DBUG_RETURN(true); + // continue when IGNORE clause is used. + goto continue_loop; + } + switch (table_list->view_check_option(thd)) { case VIEW_CHECK_SKIP: read_info.next_line(); @@ -997,6 +1003,12 @@ bool Sql_cmd_load_table::read_sep_field(THD *thd, COPY_INFO &info, if (thd->is_error()) DBUG_RETURN(true); + if (invoke_table_check_constraints(thd, table)) { + if (thd->is_error()) DBUG_RETURN(true); + // continue when IGNORE clause is used. + goto continue_loop; + } + switch (table_list->view_check_option(thd)) { case VIEW_CHECK_SKIP: read_info.next_line(); @@ -1159,6 +1171,12 @@ bool Sql_cmd_load_table::read_xml_field(THD *thd, COPY_INFO &info, TRG_EVENT_INSERT, table->s->fields)) DBUG_RETURN(true); + if (invoke_table_check_constraints(thd, table)) { + if (thd->is_error()) DBUG_RETURN(true); + // continue when IGNORE clause is used. + goto continue_loop; + } + switch (table_list->view_check_option(thd)) { case VIEW_CHECK_SKIP: read_info.next_line(); diff --git a/sql/sql_rename.cc b/sql/sql_rename.cc index 3128c0ebcf58..54eaac66dc71 100644 --- a/sql/sql_rename.cc +++ b/sql/sql_rename.cc @@ -1,4 +1,4 @@ -/* Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License, version 2.0, @@ -699,6 +699,10 @@ static bool do_rename(THD *thd, TABLE_LIST *ren_table, const char *new_db, } } + if (lock_check_constraint_names_for_rename(thd, ren_table->db, old_alias, + from_table, new_db, new_alias)) + DBUG_RETURN(true); + /* We commit changes to data-dictionary immediately after renaming table in storage engine if SE doesn't support atomic DDL or diff --git a/sql/sql_show.cc b/sql/sql_show.cc index cf1d8118a425..bad58f1886cd 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -1,4 +1,4 @@ -/* Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License, version 2.0, @@ -1344,6 +1344,31 @@ bool store_create_info(THD *thd, TABLE_LIST *table_list, String *packet, file->free_foreign_key_create_info(for_str); } + /* + Append check constraints to the CREATE TABLE statement. All check + constraints are listed in table check constraint form. + */ + if (table->table_check_constraint_list != nullptr) { + for (auto &cc : *table->table_check_constraint_list) { + packet->append(STRING_WITH_LEN(",\n ")); + packet->append(STRING_WITH_LEN("CONSTRAINT ")); + append_identifier(thd, packet, cc->name().str, cc->name().length); + + packet->append(STRING_WITH_LEN(" CHECK (")); + packet->append(cc->expr_str().str, cc->expr_str().length, + system_charset_info); + packet->append(STRING_WITH_LEN(")")); + + /* + If check constraint is not-enforced then it is listed with the comment + "NOT ENFORCED". + */ + if (!cc->is_enforced()) { + packet->append(STRING_WITH_LEN(" /*!80015 NOT ENFORCED */")); + } + } + } + packet->append(STRING_WITH_LEN("\n)")); if (!foreign_db_mode) { show_table_options = true; diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 6113e1f4fd05..6fad9ed7d98a 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -1,5 +1,5 @@ /* - Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. + Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License, version 2.0, @@ -83,6 +83,7 @@ #include "sql/dd/properties.h" // dd::Properties #include "sql/dd/string_type.h" #include "sql/dd/types/abstract_table.h" +#include "sql/dd/types/check_constraint.h" // dd::Check_constraint #include "sql/dd/types/column.h" #include "sql/dd/types/foreign_key.h" // dd::Foreign_key #include "sql/dd/types/foreign_key_element.h" // dd::Foreign_key_element @@ -127,7 +128,8 @@ #include "sql/sql_backup_lock.h" // acquire_shared_backup_lock #include "sql/sql_base.h" // lock_table_names #include "sql/sql_bitmap.h" -#include "sql/sql_class.h" // THD +#include "sql/sql_check_constraint.h" // Sql_check_constraint_spec* +#include "sql/sql_class.h" // THD #include "sql/sql_const.h" #include "sql/sql_db.h" // get_default_db_collation #include "sql/sql_error.h" @@ -199,6 +201,28 @@ static bool prepare_enum_field(THD *thd, Create_field *sql_field); static uint blob_length_by_type(enum_field_types type); static const Create_field *get_field_by_index(Alter_info *alter_info, uint idx); +static bool generate_check_constraint_name(THD *thd, const char *table_name, + uint ordinal_number, + LEX_STRING &name, + bool skip_validation); +static bool push_check_constraint_mdl_request_to_list( + THD *thd, const char *db, const char *cc_name, + MDL_request_list &cc_mdl_request_list); +static bool prepare_check_constraints_for_create(THD *thd, const char *db_name, + const char *table_name, + Alter_info *alter_info); +static bool prepare_check_constraints_for_create_like_table( + THD *thd, TABLE_LIST *src_table, TABLE_LIST *table, Alter_info *alter_info); +static bool prepare_check_constraints_for_alter( + THD *thd, const TABLE *table, Alter_info *alter_info, + Alter_table_ctx *alter_tbl_ctx, + Check_constraints_adjusted_names_map &cc_adjusted_names_map); +static bool adjust_check_constraint_names(THD *thd, const char *old_table_db, + dd::Table *old_table, + dd::Table *new_table); +static bool is_any_check_constraints_evaluation_required( + const Alter_info *alter_info); + /** RAII class to control the atomic DDL commit on slave. A slave context flag responsible to mark the DDL as committed is @@ -771,24 +795,25 @@ size_t build_tmptable_filename(THD *thd, char *buff, size_t bufflen) { The temporary table is also created in the storage engine, depending on the 'no_ha_table' argument. - @param thd Thread handler - @param path Name of file (including database) - @param sch_obj Schema. - @param db Schema name. - Cannot use dd::Schema::name() directly due to LCTN. - @param table_name Table name - @param create_info create info parameters - @param create_fields Fields to create - @param keys number of keys to create - @param key_info Keys to create - @param keys_onoff Enable or disable keys. - @param file Handler to use - @param no_ha_table Indicates that only definitions needs to be created - and not a table in the storage engine. + @param thd Thread handler + @param path Name of file (including database) + @param sch_obj Schema. + @param db Schema name. + Cannot use dd::Schema::name() directly due to LCTN. + @param table_name Table name + @param create_info create info parameters + @param create_fields Fields to create + @param keys number of keys to create + @param key_info Keys to create + @param keys_onoff Enable or disable keys. + @param check_cons_spec List of check constraint specification. + @param file Handler to use + @param no_ha_table Indicates that only definitions needs to be created + and not a table in the storage engine. @param[out] binlog_to_trx_cache - Which binlog cache should be used? - If true => trx cache - If false => stmt cache + Which binlog cache should be used? + If true => trx cache + If false => stmt cache @param[out] tmp_table_def Data-dictionary object for temporary table which was created. Is not set if no_ha_table was false. @@ -801,14 +826,15 @@ static bool rea_create_tmp_table( THD *thd, const char *path, const dd::Schema &sch_obj, const char *db, const char *table_name, HA_CREATE_INFO *create_info, List &create_fields, uint keys, KEY *key_info, - Alter_info::enum_enable_or_disable keys_onoff, handler *file, + Alter_info::enum_enable_or_disable keys_onoff, + const Sql_check_constraint_spec_list *check_cons_spec, handler *file, bool no_ha_table, bool *binlog_to_trx_cache, std::unique_ptr *tmp_table_def) { DBUG_ENTER("rea_create_tmp_table"); std::unique_ptr tmp_table_ptr = dd::create_tmp_table(thd, sch_obj, table_name, create_info, create_fields, - key_info, keys, keys_onoff, file); + key_info, keys, keys_onoff, check_cons_spec, file); if (!tmp_table_ptr) DBUG_RETURN(true); if (no_ha_table) { @@ -849,30 +875,32 @@ static bool rea_create_tmp_table( Create table definition in the Data Dictionary. The table is also created in the storage engine, depending on the 'no_ha_table' argument. - @param thd Thread handler - @param path Name of file (including database) - @param sch_obj Schema. - @param db Schema name. - Cannot use dd::Schema::name() directly due to LCTN. - @param table_name Table name - @param create_info create info parameters - @param create_fields Fields to create - @param keys number of keys to create - @param key_info Keys to create - @param keys_onoff Enable or disable keys. - @param fk_keys Number of foreign keys to create - @param fk_key_info Foreign keys to create - @param file Handler to use - @param no_ha_table Indicates that only definitions needs to be created - and not a table in the storage engine. - @param do_not_store_in_dd Indicates that we should postpone storing table - object in the data-dictionary. Requires SE - supporting atomic DDL and no_ha_table flag set. - @param part_info Reference to partitioning data structure. + @param thd Thread handler + @param path Name of file (including database) + @param sch_obj Schema. + @param db Schema name. + Cannot use dd::Schema::name() directly due to + LCTN. + @param table_name Table name + @param create_info create info parameters + @param create_fields Fields to create + @param keys number of keys to create + @param key_info Keys to create + @param keys_onoff Enable or disable keys. + @param fk_keys Number of foreign keys to create + @param fk_key_info Foreign keys to create + @param check_cons_spec List of check constraint specifications. + @param file Handler to use + @param no_ha_table Indicates that only definitions needs to be + created and not a table in the storage engine. + @param do_not_store_in_dd Indicates that we should postpone storing table + object in the data-dictionary. Requires SE + supporting atomic DDL and no_ha_table flag set. + @param part_info Reference to partitioning data structure. @param[out] binlog_to_trx_cache - Which binlog cache should be used? - If true => trx cache - If false => stmt cache + Which binlog cache should be used? + If true => trx cache + If false => stmt cache @param[out] table_def_ptr dd::Table object describing the table created if do_not_store_in_dd option was used. Not set otherwise. @@ -893,15 +921,16 @@ static bool rea_create_base_table( const char *table_name, HA_CREATE_INFO *create_info, List &create_fields, uint keys, KEY *key_info, Alter_info::enum_enable_or_disable keys_onoff, uint fk_keys, - FOREIGN_KEY *fk_key_info, handler *file, bool no_ha_table, - bool do_not_store_in_dd, partition_info *part_info, + FOREIGN_KEY *fk_key_info, + const Sql_check_constraint_spec_list *check_cons_spec, handler *file, + bool no_ha_table, bool do_not_store_in_dd, partition_info *part_info, bool *binlog_to_trx_cache, std::unique_ptr *table_def_ptr, handlerton **post_ddl_ht) { DBUG_ENTER("rea_create_base_table"); - std::unique_ptr table_def_res = - dd::create_table(thd, sch_obj, table_name, create_info, create_fields, - key_info, keys, keys_onoff, fk_key_info, fk_keys, file); + std::unique_ptr table_def_res = dd::create_table( + thd, sch_obj, table_name, create_info, create_fields, key_info, keys, + keys_onoff, fk_key_info, fk_keys, check_cons_spec, file); if (!table_def_res) DBUG_RETURN(true); @@ -1448,6 +1477,8 @@ bool mysql_rm_table(THD *thd, TABLE_LIST *tables, bool if_exists, if (rm_table_do_discovery_and_lock_fk_tables(thd, tables)) DBUG_RETURN(true); + + if (lock_check_constraint_names(thd, tables)) DBUG_RETURN(true); } std::vector safe_to_release_mdl; @@ -6111,6 +6142,34 @@ static bool prepare_foreign_key(THD *thd, HA_CREATE_INFO *create_info, DBUG_RETURN(true); } + /* + Check constraints evaluation is done before writing row to the storage + engine but foreign key referential actions SET NULL, UPDATE CASCADE and + SET DEFAULT are executed by the engine. Check constraints can not be + evaluated for the these foreign key referential actions, so prohibit + them. + */ + if (fk_info->delete_opt == FK_OPTION_SET_NULL || + fk_info->delete_opt == FK_OPTION_DEFAULT || + fk_info->update_opt == FK_OPTION_SET_NULL || + fk_info->update_opt == FK_OPTION_DEFAULT || + fk_info->update_opt == FK_OPTION_CASCADE) { + for (auto &cc_spec : alter_info->check_constraint_spec_list) { + if (cc_spec->expr_refers_column(find->field_name)) { + const char *cc_name = cc_spec->name.str; + /* + Use actual name for error reporting if check constraint name is + adjusted for the operation. + */ + if (thd->m_cc_adjusted_names_map != nullptr) + cc_name = thd->m_cc_adjusted_names_map->actual_name(cc_name); + my_error(ER_CHECK_CONSTRAINT_CLAUSE_USING_FK_REFER_ACTION_COLUMN, + MYF(0), find->field_name, cc_name, fk_info->name); + DBUG_RETURN(true); + } + } + } + referencing_fields.push_back(find); /* @@ -6341,9 +6400,10 @@ static bool prepare_foreign_key(THD *thd, HA_CREATE_INFO *create_info, @param table_name Table name. @param key_info Array of indexes. @param key_count Number of indexes. - @param existing_fks_table dd::Table object for table version from - which pre-existing foreign keys come - from. Needed for error reporting. + @param existing_fks_table dd::Table object for table version + from which pre-existing foreign keys + come from. Needed for error + reporting. @param[in,out] fk FOREIGN_KEY object describing pre-existing foreign key. @@ -6383,6 +6443,34 @@ static bool prepare_preexisting_foreign_key( my_error(ER_FK_COLUMN_NOT_NULL, MYF(0), fk->key_part[j].str, fk->name); return true; } + + /* + Check constraints evaluation is done before writing row to the storage + engine but foreign key referential actions SET NULL, UPDATE CASCADE and + SET DEFAULT are executed by the engine. Check constraints can not be + evaluated for the these foreign key referential actions, so we prohibit + them. + */ + if (fk->delete_opt == FK_OPTION_SET_NULL || + fk->delete_opt == FK_OPTION_DEFAULT || + fk->update_opt == FK_OPTION_SET_NULL || + fk->update_opt == FK_OPTION_DEFAULT || + fk->update_opt == FK_OPTION_CASCADE) { + for (auto &cc_spec : alter_info->check_constraint_spec_list) { + if (cc_spec->expr_refers_column(sql_field->field_name)) { + const char *cc_name = cc_spec->name.str; + /* + Use actual name for error reporting if check constraint name is + adjusted for the operation. + */ + if (thd->m_cc_adjusted_names_map != nullptr) + cc_name = thd->m_cc_adjusted_names_map->actual_name(cc_name); + my_error(ER_CHECK_CONSTRAINT_CLAUSE_USING_FK_REFER_ACTION_COLUMN, + MYF(0), sql_field->field_name, cc_name, fk->name); + return true; + } + } + } } // Check that we still have supporting index on child table. @@ -7095,8 +7183,8 @@ static bool add_functional_index_to_create_list(THD *thd, Key_spec *key_spec, return true; } - if (pre_validate_value_generator_expr(kp->get_expression(), - key_spec->name.str, true)) { + if (pre_validate_value_generator_expr( + kp->get_expression(), key_spec->name.str, VGS_GENERATED_COLUMN)) { return true; } @@ -8149,13 +8237,15 @@ static bool create_table_impl( if (create_info->options & HA_LEX_CREATE_TMP_TABLE) { if (rea_create_tmp_table(thd, path, schema, db, table_name, create_info, alter_info->create_list, *key_count, *key_info, - keys_onoff, file.get(), no_ha_table, is_trans, - table_def)) + keys_onoff, + &alter_info->check_constraint_spec_list, + file.get(), no_ha_table, is_trans, table_def)) DBUG_RETURN(true); } else { if (rea_create_base_table(thd, path, schema, db, table_name, create_info, alter_info->create_list, *key_count, *key_info, keys_onoff, *fk_key_count, *fk_key_info, + &alter_info->check_constraint_spec_list, file.get(), no_ha_table, do_not_store_in_dd, part_info, is_trans, table_def, post_ddl_ht)) DBUG_RETURN(true); @@ -9049,6 +9139,13 @@ bool mysql_create_table(THD *thd, TABLE_LIST *create_table, } } + // Prepare check constraints. + if (prepare_check_constraints_for_create( + thd, create_table->db, create_table->table_name, alter_info)) { + result = true; + goto end; + } + /* Promote first timestamp column, when explicit_defaults_for_timestamp is not set @@ -9385,6 +9482,8 @@ static bool alter_table_drop_histograms(THD *thd, TABLE_LIST *table, data-dictionary. NO_FK_RENAME Don't change generated foreign key names during rename. + NO_CC_RENAME Don't change generated check constraint + names during rename. @note Use of NO_DD_COMMIT flag only allowed for SEs supporting atomic DDL. @@ -9479,6 +9578,10 @@ bool mysql_rename_table(THD *thd, handlerton *base, const char *old_db, dd::rename_foreign_keys(thd, old_db, old_fk_name, new_db, to_table_def)) DBUG_RETURN(true); + if (!(flags & NO_CC_RENAME) && + dd::rename_check_constraints(old_name, to_table_def)) + DBUG_RETURN(true); + // Get the handler for the table, and issue an error if we cannot load it. handler *file = (base == NULL ? 0 @@ -9671,6 +9774,10 @@ bool mysql_create_like_table(THD *thd, TABLE_LIST *table, TABLE_LIST *src_table, &local_alter_ctx)) DBUG_RETURN(true); + if (prepare_check_constraints_for_create_like_table(thd, src_table, table, + &local_alter_info)) + DBUG_RETURN(true); + /* During open_tables(), the target tablespace name(s) for a table being created or altered should be locked. However, for 'CREATE TABLE ... LIKE', @@ -10595,6 +10702,13 @@ static bool fill_alter_inplace_info(THD *thd, TABLE *table, ha_alter_info->handler_flags |= Alter_inplace_info::RECREATE_TABLE; if (alter_info->with_validation == Alter_info::ALTER_WITH_VALIDATION) ha_alter_info->handler_flags |= Alter_inplace_info::VALIDATE_VIRTUAL_COLUMN; + if (alter_info->flags & Alter_info::ADD_CHECK_CONSTRAINT) + ha_alter_info->handler_flags |= Alter_inplace_info::ADD_CHECK_CONSTRAINT; + if (alter_info->flags & Alter_info::DROP_CHECK_CONSTRAINT) + ha_alter_info->handler_flags |= Alter_inplace_info::DROP_CHECK_CONSTRAINT; + if (alter_info->flags & Alter_info::SUSPEND_CHECK_CONSTRAINT) + ha_alter_info->handler_flags |= + Alter_inplace_info::SUSPEND_CHECK_CONSTRAINT; /* Go through fields in old version of table and detect changes to them. @@ -11345,6 +11459,13 @@ static bool is_inplace_alter_impossible(TABLE *table, (Alter_info::ALTER_ORDER | Alter_info::ALTER_KEYS_ONOFF)) DBUG_RETURN(true); + /* + Check constraints are evaluated in the server, if any check constraint + (re-)evalutation is required then it can't be added/enforced inplace. + */ + if (is_any_check_constraints_evaluation_required(alter_info)) + DBUG_RETURN(true); + /* If the table engine is changed explicitly (using ENGINE clause) or implicitly (e.g. when non-partitioned table becomes @@ -12175,6 +12296,9 @@ static bool mysql_inplace_alter_table( DEBUG_SYNC_C("alter_table_after_dd_client_drop"); + if (adjust_check_constraint_names(thd, nullptr, nullptr, altered_table_def)) + goto cleanup2; + if ((db_type->flags & HTON_SUPPORTS_ATOMIC_DDL)) { /* For engines supporting atomic DDL we have delayed storing new @@ -12840,7 +12964,8 @@ static bool alter_column_name_or_default( if (alter->m_default_val_expr != nullptr && pre_validate_value_generator_expr( - alter->m_default_val_expr->expr_item, alter->name, false)) + alter->m_default_val_expr->expr_item, alter->name, + VGS_DEFAULT_EXPRESSION)) DBUG_RETURN(true); // Default value is not permitted for generated columns @@ -13427,7 +13552,7 @@ bool prepare_fields_and_keys(THD *thd, const dd::Table *src_table, TABLE *table, } if (alter_info->drop_list.size() > 0) { - // Now this contains only DROP for foreign keys and not-found objects + // Now this contains only DROP for foreign keys and not-found objects. for (const Alter_drop *drop : alter_info->drop_list) { switch (drop->type) { case Alter_drop::KEY: @@ -13435,6 +13560,13 @@ bool prepare_fields_and_keys(THD *thd, const dd::Table *src_table, TABLE *table, my_error(ER_CANT_DROP_FIELD_OR_KEY, MYF(0), alter_info->drop_list[0]->name); DBUG_RETURN(true); + case Alter_drop::CHECK_CONSTRAINT: + /* + Check constraints to be dropped are already handled by the + prepare_check_constraints_for_alter(). + */ + DBUG_ASSERT(false); + break; case Alter_drop::FOREIGN_KEY: break; default: @@ -13442,7 +13574,7 @@ bool prepare_fields_and_keys(THD *thd, const dd::Table *src_table, TABLE *table, break; } } - // new_drop_list has DROP for virtual generated columns; add foreign keys: + // new_drop_list has DROP for virtual generated columns; add foreign keys. new_drop_list.reserve(new_drop_list.size() + alter_info->drop_list.size()); for (const Alter_drop *drop : alter_info->drop_list) new_drop_list.push_back(drop); @@ -13998,15 +14130,13 @@ static bool simple_rename_or_index_change( if (wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN)) DBUG_RETURN(true); - if (old_db_type->flags & HTON_SUPPORTS_FOREIGN_KEYS) { - const dd::Table *table_def = nullptr; - - if (thd->dd_client()->acquire(table_list->db, table_list->table_name, - &table_def)) - DBUG_RETURN(true); - - DBUG_ASSERT(table_def != nullptr); + const dd::Table *table_def = nullptr; + if (thd->dd_client()->acquire(table_list->db, table_list->table_name, + &table_def)) + DBUG_RETURN(true); + DBUG_ASSERT(table_def != nullptr); + if (old_db_type->flags & HTON_SUPPORTS_FOREIGN_KEYS) { if (collect_and_lock_fk_tables_for_rename_table( thd, table_list->db, table_list->table_name, table_def, alter_ctx->new_db, alter_ctx->new_alias, old_db_type, @@ -14014,6 +14144,11 @@ static bool simple_rename_or_index_change( DBUG_RETURN(true); } + if (lock_check_constraint_names_for_rename( + thd, table_list->db, table_list->table_name, table_def, + alter_ctx->new_db, alter_ctx->new_alias)) + DBUG_RETURN(true); + close_all_tables_for_name(thd, table->s, false, NULL); if (mysql_rename_table( @@ -15012,6 +15147,18 @@ bool mysql_alter_table(THD *thd, const char *new_db, const char *new_name, if (create_field->change != nullptr) columns.emplace(create_field->change); } + // Map to store adjusted names to actual check constraint names. + Check_constraints_adjusted_names_map cc_adjusted_names_map; + // Prepare check constraints for alter table operation. + if (prepare_check_constraints_for_alter(thd, table, alter_info, &alter_ctx, + cc_adjusted_names_map)) + DBUG_RETURN(true); + // For non-temorary table, set thd->m_cc_adjusted_names_map. + if (!cc_adjusted_names_map.empty()) + thd->m_cc_adjusted_names_map = &cc_adjusted_names_map; + auto guard_thd_cc_adjusted_names_map = + create_scope_guard([&thd] { thd->m_cc_adjusted_names_map = nullptr; }); + if (mysql_prepare_alter_table(thd, old_table_def, table, create_info, alter_info, &alter_ctx)) { DBUG_RETURN(true); @@ -15415,6 +15562,9 @@ bool mysql_alter_table(THD *thd, const char *new_db, const char *new_name, *table_def); (void)trans_intermediate_ddl_commit(thd, result); } + // Reset THD::m_cc_adjusted_names_map. + thd->m_cc_adjusted_names_map = nullptr; + is_noop = true; goto end_inplace_noop; } @@ -15907,10 +16057,11 @@ bool mysql_alter_table(THD *thd, const char *new_db, const char *new_name, } } - if (mysql_rename_table( - thd, old_db_type, alter_ctx.db, alter_ctx.table_name, alter_ctx.db, - alter_ctx.table_name, *schema, alter_ctx.db, backup_name, - FN_TO_IS_TMP | (atomic_replace ? NO_DD_COMMIT : 0) | NO_FK_RENAME)) { + if (mysql_rename_table(thd, old_db_type, alter_ctx.db, alter_ctx.table_name, + alter_ctx.db, alter_ctx.table_name, *schema, + alter_ctx.db, backup_name, + FN_TO_IS_TMP | (atomic_replace ? NO_DD_COMMIT : 0) | + NO_FK_RENAME | NO_CC_RENAME)) { // Rename to temporary name failed, delete the new table, abort ALTER. if (!atomic_replace) { /* @@ -15971,7 +16122,7 @@ bool mysql_alter_table(THD *thd, const char *new_db, const char *new_name, (FN_FROM_IS_TMP | ((new_db_type->flags & HTON_SUPPORTS_ATOMIC_DDL) ? NO_DD_COMMIT : 0) | - (alter_ctx.is_table_renamed() ? 0 : NO_FK_RENAME))) || + (alter_ctx.is_table_renamed() ? 0 : NO_FK_RENAME | NO_CC_RENAME))) || ((new_db_type->flags & HTON_SUPPORTS_FOREIGN_KEYS) && adjust_fks_for_complex_alter_table(thd, table_list, &alter_ctx, alter_info, new_db_type, @@ -16010,10 +16161,10 @@ bool mysql_alter_table(THD *thd, const char *new_db, const char *new_name, // gap locks on DD tables (which might cause deadlocks). uint retries = 20; while (retries-- && - mysql_rename_table(thd, old_db_type, alter_ctx.db, backup_name, - alter_ctx.db, backup_name, *schema, - alter_ctx.db, alter_ctx.alias, - FN_FROM_IS_TMP | NO_FK_CHECKS | NO_FK_RENAME)) + mysql_rename_table( + thd, old_db_type, alter_ctx.db, backup_name, alter_ctx.db, + backup_name, *schema, alter_ctx.db, alter_ctx.alias, + FN_FROM_IS_TMP | NO_FK_CHECKS | NO_FK_RENAME | NO_CC_RENAME)) ; } goto err_with_mdl; @@ -16026,11 +16177,7 @@ bool mysql_alter_table(THD *thd, const char *new_db, const char *new_name, */ if (!atomic_replace) invalidate_fk_parents_on_error = true; - /* - Since trigger names have to be unique per schema, we cannot - create them while both the old and the tmp version of the - table exist. - */ + // Handle trigger name, check constraint names and histograms statistics. { dd::Table *backup_table = nullptr; dd::Table *new_table = nullptr; @@ -16053,7 +16200,22 @@ bool mysql_alter_table(THD *thd, const char *new_db, const char *new_name, columns, backup_table, new_table)) goto err_with_mdl; /* purecov: deadcode */ - bool update = false; + bool update = !cc_adjusted_names_map.empty(); + /* + Check constraint names are unique per schema, we cannot create them while + both table version exists. Adjust check constraint names in old table + version and restore check constraint name in new version from + cc_adjusted_names_map. + */ + if (adjust_check_constraint_names(thd, alter_ctx.db, backup_table, + new_table)) + goto err_with_mdl; + + /* + Since trigger names have to be unique per schema, we cannot + create them while both the old and the tmp version of the + table exist. + */ if (backup_table->has_trigger()) { new_table->copy_triggers(backup_table); backup_table->drop_all_triggers(); @@ -16592,6 +16754,9 @@ static int copy_data_between_tables( } } + error = invoke_table_check_constraints(thd, to); + if (error) break; + error = to->file->ha_write_row(to->record[0]); to->auto_increment_field_not_null = false; if (error) { @@ -16910,3 +17075,817 @@ static bool check_engine(THD *thd, const char *db_name, const char *table_name, DBUG_RETURN(false); } + +/** + Helper method to generate check constraint name. + + @param thd Thread handle. + @param table_name Table name. + @param ordinal_number Ordinal number of the generated name. + @param[out] name LEX_STRING instance to hold the + generated check constraint name. + @param skip_validation Skip generated name validation. +*/ +static bool generate_check_constraint_name(THD *thd, const char *table_name, + uint ordinal_number, + LEX_STRING &name, + bool skip_validation) { + // Allocate memory for name. + size_t generated_name_len = + strlen(table_name) + sizeof(dd::CHECK_CONSTRAINT_NAME_SUBSTR) + 11 + 1; + name.str = (char *)alloc_root(thd->mem_root, generated_name_len); + if (name.str == nullptr) return true; // OOM + + // Prepare name for check constraint. + sprintf(name.str, "%s%s%u", table_name, dd::CHECK_CONSTRAINT_NAME_SUBSTR, + ordinal_number); + name.length = strlen(name.str); + + // Validate check constraint name. + if (!skip_validation && + check_string_char_length(to_lex_cstring(name), "", NAME_CHAR_LEN, + system_charset_info, 1)) { + my_error(ER_TOO_LONG_IDENT, MYF(0), name.str); + return true; + } + + return false; +} + +/** + Helper method to create MDL_request for check constraint names. Check + constraint names are case insensitive. Hence names are lowercased + in MDL_request and pushed to MDL_request_list. + + @param thd Thread handle. + @param db Database name. + @param cc_name Check constraint name. + @param[out] cc_mdl_request_list MDL request list. + + @retval false Success. + @retval true Failure. +*/ +static bool push_check_constraint_mdl_request_to_list( + THD *thd, const char *db, const char *cc_name, + MDL_request_list &cc_mdl_request_list) { + DBUG_ASSERT(thd != nullptr && db != nullptr && cc_name != nullptr); + + /* + Check constraint names are case insensitive. Hence lowercasing names for + MDL locking. + */ + char lc_cc_name[NAME_LEN + 1]; + strmake(lc_cc_name, cc_name, NAME_LEN); + my_casedn_str(system_charset_info, lc_cc_name); + + MDL_request *mdl_request = new (thd->mem_root) MDL_request; + if (mdl_request == nullptr) return true; // OOM + MDL_REQUEST_INIT(mdl_request, MDL_key::CHECK_CONSTRAINT, db, lc_cc_name, + MDL_EXCLUSIVE, MDL_STATEMENT); + cc_mdl_request_list.push_front(mdl_request); + + return false; +} + +/** + Method to prepare check constraints for the CREATE operation. If name of the + check constraint is not specified then name is generated, check constraint + is pre-validated and MDL on check constraint is acquired here. + + @param thd Thread handle. + @param db_name Database name. + @param table_name Table name. + @param alter_info Alter_info object with list of + check constraints to be created. + + @retval false Success. + @retval true Failure. +*/ +static bool prepare_check_constraints_for_create(THD *thd, const char *db_name, + const char *table_name, + Alter_info *alter_info) { + DBUG_ENTER("prepare_check_constraints_for_create"); + MDL_request_list cc_mdl_request_list; + uint cc_max_generated_number = 0; + + for (auto &cc_spec : alter_info->check_constraint_spec_list) { + // If check constraint name is omitted then generate name. + if (cc_spec->name.length == 0) { + if (generate_check_constraint_name( + thd, table_name, ++cc_max_generated_number, cc_spec->name, false)) + DBUG_RETURN(true); + } + + // Pre-validate check constraint. + if (cc_spec->pre_validate()) DBUG_RETURN(true); + + // Create MDL request for the check constraint. + if (push_check_constraint_mdl_request_to_list( + thd, db_name, cc_spec->name.str, cc_mdl_request_list)) + DBUG_RETURN(true); + } + + // Make sure fields used by the check constraint exists in the create list. + List fields; + for (auto &cc_spec : alter_info->check_constraint_spec_list) { + cc_spec->check_expr->walk(&Item::collect_item_field_processor, + Item::WALK_POSTFIX, (uchar *)&fields); + + Item_field *cur_item_fld; + List_iterator fields_it(fields); + Create_field *cur_fld; + List_iterator create_fields_it(alter_info->create_list); + while ((cur_item_fld = fields_it++)) { + if (cur_item_fld->type() != Item::FIELD_ITEM) continue; + + while ((cur_fld = create_fields_it++)) { + if (!my_strcasecmp(system_charset_info, cur_item_fld->field_name, + cur_fld->field_name)) + break; + } + create_fields_it.rewind(); + + if (cur_fld == nullptr) { + my_error(ER_CHECK_CONSTRAINT_REFERS_UNKNOWN_COLUMN, MYF(0), + cc_spec->name.str, cur_item_fld->field_name); + DBUG_RETURN(true); + } + } + fields.empty(); + } + + DEBUG_SYNC(thd, "before_acquiring_lock_on_check_constraints"); + if (thd->mdl_context.acquire_locks(&cc_mdl_request_list, + thd->variables.lock_wait_timeout)) + DBUG_RETURN(true); + DEBUG_SYNC(thd, "after_acquiring_lock_on_check_constraints"); + + DBUG_RETURN(false); +} + +/** + Method to prepare check constraints for the CREATE TABLE LIKE operation. + If check constraints are defined on the source table then check constraints + specifications are prepared for the table being created from it. To + avoid name conflicts, names are generated for all the check constraints + prepared for the table being created. + + + @param thd Thread handle. + @param src_table TABLE_LIST instance for source table. + @param target_table TABLE_LIST instance for target table. + @param alter_info Alter_info instance to prepare + list of check constraint spec + for table being created. + + @retval false Success. + @retval true Failure. +*/ +static bool prepare_check_constraints_for_create_like_table( + THD *thd, TABLE_LIST *src_table, TABLE_LIST *target_table, + Alter_info *alter_info) { + DBUG_ENTER("prepare_check_constraints_for_create_like_table"); + MDL_request_list cc_mdl_request_list; + uint number = 0; + + if (src_table->table->table_check_constraint_list != nullptr) { + for (auto &table_cc : *src_table->table->table_check_constraint_list) { + Sql_check_constraint_spec *cc_spec = + new (thd->mem_root) Sql_check_constraint_spec; + if (cc_spec == nullptr) DBUG_RETURN(true); // OOM + + // For create like table, all the check constraint names are generated to + // avoid name conflicts. + if (generate_check_constraint_name(thd, target_table->table_name, + ++number, cc_spec->name, true)) + DBUG_RETURN(true); + + // check constraint expression. + cc_spec->check_expr = table_cc->value_generator()->expr_item; + + // Copy check constraint status. + cc_spec->is_enforced = table_cc->is_enforced(); + + alter_info->check_constraint_spec_list.push_back(cc_spec); + + /* + Create MDL request for check constraint in source table and the + generated check constraint name for target table. + */ + if (push_check_constraint_mdl_request_to_list( + thd, src_table->db, table_cc->name().str, cc_mdl_request_list) || + push_check_constraint_mdl_request_to_list( + thd, target_table->db, cc_spec->name.str, cc_mdl_request_list)) + DBUG_RETURN(true); + } + } + + DEBUG_SYNC(thd, "before_acquiring_lock_on_check_constraints"); + if (thd->mdl_context.acquire_locks(&cc_mdl_request_list, + thd->variables.lock_wait_timeout)) + DBUG_RETURN(true); + DEBUG_SYNC(thd, "after_acquiring_lock_on_check_constraints"); + + DBUG_RETURN(false); +} + +/** + Method to prepare check constraints for the ALTER TABLE operation. + Method prepares check constraints specifications from the existing + list of check constraints on the table, appends new check constraints + to list, updates state (enforced/not enforced) and drop any existing + check constraint from the list. + + @param thd Thread handle. + @param table TABLE instance of source table. + @param alter_info Alter_info object to prepare + list of check constraint spec + for table being altered. + @param alter_tbl_ctx Runtime context for + ALTER TABLE. + @param[out] cc_adjusted_names_map Adjusted name of check constraint + to actual name map. + + @retval false Success. + @retval true Failure. +*/ +static bool prepare_check_constraints_for_alter( + THD *thd, const TABLE *table, Alter_info *alter_info, + Alter_table_ctx *alter_tbl_ctx, + Check_constraints_adjusted_names_map &cc_adjusted_names_map) { + DBUG_ENTER("prepare_check_constraints_for_alter"); + MDL_request_list cc_mdl_request_list; + Sql_check_constraint_spec_list new_check_cons_list(thd->mem_root); + Mem_root_array new_drop_list(thd->mem_root); + Mem_root_array new_state_list(thd->mem_root); + uint cc_max_generated_number = 0; + uint table_name_len = strlen(alter_tbl_ctx->table_name); + + /* + List of new or adjusted check constraint names. Used at STEP 9 to verify + check constraint names conflict with existing check constraint names. + */ + std::vector new_cc_names; + auto erase_cc_name = [](std::vector &names, const char *s) { + auto name = find_if(names.begin(), names.end(), [s](const char *cc_name) { + return !my_strcasecmp(system_charset_info, s, cc_name); + }); + if (name != names.end()) names.erase(name); + }; + + /* + Step 1: Prepare check constraint specification for the existing check + constraints on the table. + + * Get max sequence number for generated names. This is required + in Step 2. + + * If table is renamed, adjust generated check constraint names + to use new table name. + + * Create MDL request on all check constraints. + - Also on adjusted check constraint names if table is renamed. + - If database changed then on all check constraints with the + new database. + */ + if (table->table_check_constraint_list != nullptr) { + for (auto &table_cc : *table->table_check_constraint_list) { + Sql_check_constraint_spec *cc_spec = + new (thd->mem_root) Sql_check_constraint_spec; + if (cc_spec == nullptr) DBUG_RETURN(true); // OOM + + bool is_generated_name = dd::is_generated_check_constraint_name( + alter_tbl_ctx->table_name, table_name_len, table_cc->name().str, + table_cc->name().length); + /* + Get number from generated name and update max generated number if + needed. + */ + if (is_generated_name) { + char *end; + uint number = + my_strtoull(table_cc->name().str + table_name_len + + sizeof(dd::CHECK_CONSTRAINT_NAME_SUBSTR) - 1, + &end, 10); + if (number > cc_max_generated_number) cc_max_generated_number = number; + } + + // If generated name and table is renamed then update generated name. + if (is_generated_name && alter_tbl_ctx->is_table_name_changed()) { + char *end; + uint number = + my_strtoull(table_cc->name().str + table_name_len + + sizeof(dd::CHECK_CONSTRAINT_NAME_SUBSTR) - 1, + &end, 10); + if (number > cc_max_generated_number) cc_max_generated_number = number; + + // Generate new check constraint name. + if (generate_check_constraint_name(thd, alter_tbl_ctx->new_name, number, + cc_spec->name, true)) + DBUG_RETURN(true); + } else { + lex_string_strmake(thd->mem_root, &cc_spec->name, table_cc->name().str, + table_cc->name().length); + if (cc_spec->name.str == nullptr) DBUG_RETURN(true); // OOM + } + + // check constraint expression. + cc_spec->check_expr = table_cc->value_generator()->expr_item; + + // Copy check constraint status. + cc_spec->is_enforced = table_cc->is_enforced(); + + // Push check constraint to new list. + new_check_cons_list.push_back(cc_spec); + + // Push MDL_request for the existing check constraint name. + if (push_check_constraint_mdl_request_to_list(thd, alter_tbl_ctx->db, + table_cc->name().str, + cc_mdl_request_list)) + DBUG_RETURN(true); + + /* + If db is changed then push MDL_request on check constraint with new db + name or if table name is changed then push MDL_request on generated + check constraint name. + */ + if ((alter_tbl_ctx->is_database_changed() || + (alter_tbl_ctx->is_table_name_changed() && is_generated_name))) { + if (push_check_constraint_mdl_request_to_list( + thd, alter_tbl_ctx->new_db, cc_spec->name.str, + cc_mdl_request_list)) + DBUG_RETURN(true); + + new_cc_names.push_back(cc_spec->name.str); + } + } + } + + /* + Step 2: Handle new check constraints added to the table. + + * Generate name if name is not specified. + If table already has check constraints with generated name + then use sequence number from Step 1. + + * pre-validate check constraint. + + * Prepare MDL request for new check constraints. + */ + for (auto &cc_spec : alter_info->check_constraint_spec_list) { + // If check constraint name is omitted then generate name. + if (cc_spec->name.length == 0) { + if (generate_check_constraint_name(thd, alter_tbl_ctx->new_name, + ++cc_max_generated_number, + cc_spec->name, false)) + DBUG_RETURN(true); + } + + if (cc_spec->pre_validate()) DBUG_RETURN(true); + + // Push check constraint to new list. + new_check_cons_list.push_back(cc_spec); + + // Create MDL request for the check constraint. + if (push_check_constraint_mdl_request_to_list( + thd, alter_tbl_ctx->new_db, cc_spec->name.str, cc_mdl_request_list)) + DBUG_RETURN(true); + + new_cc_names.push_back(cc_spec->name.str); + } + + // Step 3: Remove specifications of check constraints marked for drop. + for (auto *cc_drop : alter_info->drop_list) { + if (cc_drop->type != Alter_drop::CHECK_CONSTRAINT) { + new_drop_list.push_back(cc_drop); + continue; + } + + bool cc_found = false; + size_t cc_pos = 0; + for (auto &cc_spec : new_check_cons_list) { + if (!my_strcasecmp(system_charset_info, cc_spec->name.str, + cc_drop->name)) { + cc_found = true; + // Remove check constraint from the check constraints list. + new_check_cons_list.erase(cc_pos); + // Remove check constraint names from new_cc_names. + erase_cc_name(new_cc_names, cc_spec->name.str); + break; + } + cc_pos++; + } + if (!cc_found) { + my_error(ER_CHECK_CONSTRAINT_NOT_FOUND, MYF(0), cc_drop->name); + DBUG_RETURN(true); + } + } + + /* + Step 4: If check constraint refers to only one column and that column + is marked for drop then drop check constraint too. + */ + for (auto *cc_drop : alter_info->drop_list) { + if (cc_drop->type == Alter_drop::COLUMN) { + for (auto it = new_check_cons_list.begin(); + it < new_check_cons_list.end();) { + if ((*it)->expr_refers_to_only_column(cc_drop->name)) { + // Remove check constraint from the check constraints list. + new_check_cons_list.erase(it); + // Remove check constraint names from new_cc_names. + erase_cc_name(new_cc_names, (*it)->name.str); + } else + it++; + } + } + } + + // Step 5: Update check constraint state (i.e. enforced or not enforced). + for (auto *cc_state : alter_info->alter_state_list) { + if (cc_state->type != Alter_state::Type::CHECK_CONSTRAINT) { + new_state_list.push_back(cc_state); + continue; + } + + bool cc_found = false; + for (auto &cc_spec : new_check_cons_list) { + if (!my_strcasecmp(system_charset_info, cc_spec->name.str, + cc_state->name)) { + cc_found = true; + // Update status. + cc_spec->is_enforced = cc_state->state; + break; + } + } + if (!cc_found) { + my_error(ER_CHECK_CONSTRAINT_NOT_FOUND, MYF(0), cc_state->name); + DBUG_RETURN(true); + } + } + + /* + Step 6: Adjust Alter_info::flags. + + * Check if final list has any check constraint whose state is + changed from NOT ENFORCED to ENFORCED. + + * Check if list has any new check constraints added with ENFORCED + state. + + * Update Alter_info::flags accordingly. + */ + bool final_enforced_state = false; + for (auto &cc : new_check_cons_list) { + // Check if any of existing constraint is enforced. + if (table->table_check_constraint_list != nullptr) { + for (auto &table_cc : *table->table_check_constraint_list) { + if (!my_strcasecmp(system_charset_info, cc->name.str, + table_cc->name().str) && + !table_cc->is_enforced() && cc->is_enforced) { + final_enforced_state = true; + break; + } + } + } + if (final_enforced_state) break; + + // Check if new constraint is added in enforced state. + for (auto &new_cc : alter_info->check_constraint_spec_list) { + if (!my_strcasecmp(system_charset_info, cc->name.str, new_cc->name.str) && + cc->is_enforced) { + final_enforced_state = true; + break; + } + } + if (final_enforced_state) break; + } + if (final_enforced_state) + alter_info->flags |= Alter_info::ENFORCE_CHECK_CONSTRAINT; + else + alter_info->flags &= ~Alter_info::ENFORCE_CHECK_CONSTRAINT; + + /* + Step 7: Adjust check constraint names to avoid name conflicts. + + For non-temporary table prepare temporary check constraint names. + During ALTER TABLE operation, two versions of table exists and to + avoid check constraint name conflicts temporary names assigned to + newer version. Check constraint names are restored later in ALTER + TABLE operation. MDL request to temporary name is also created to + avoid creation of table with same name by concurrent operation. + Map from temporary name to actual name is stored in + cc_adjusted_names_map. + + * Prepare temporary name for each check constraint specification. + + * Prepare MDL request for each temporary name. + + * Store mapping between temporary to actual check constraint name. + */ + if (table->s->tmp_table == NO_TMP_TABLE) { + ulong id = 1; + for (auto &cc : new_check_cons_list) { + char temp_name_buf[3 + 20 + 10 + 20 + 3]; + snprintf(temp_name_buf, sizeof(temp_name_buf), "#cc_%lu_%u_%lu", + current_pid, thd->thread_id(), id++); + + // Create MDL request for the temp check constraint name. + if (push_check_constraint_mdl_request_to_list( + thd, alter_tbl_ctx->new_db, temp_name_buf, cc_mdl_request_list)) + DBUG_RETURN(true); + + // Store map from adjusted name to actual name. + cc_adjusted_names_map.insert(temp_name_buf, cc->name.str); + + cc->name.length = strlen(temp_name_buf); + cc->name.str = + strmake_root(thd->mem_root, temp_name_buf, cc->name.length); + } + } + + // Step 8: Acquire MDL lock on all the MDL_request prepared in this method. + DEBUG_SYNC(thd, "before_acquiring_lock_on_check_constraints"); + if (thd->mdl_context.acquire_locks(&cc_mdl_request_list, + thd->variables.lock_wait_timeout)) + DBUG_RETURN(true); + DEBUG_SYNC(thd, "after_acquiring_lock_on_check_constraints"); + + /* + Step 9: Make sure new check constraint names do not conflict with any + existing check constraint names before starting expensive ALTER + operation. + */ + dd::Schema_MDL_locker mdl_locker(thd); + const dd::Schema *new_schema = nullptr; + dd::cache::Dictionary_client::Auto_releaser releaser(thd->dd_client()); + if (mdl_locker.ensure_locked(alter_tbl_ctx->new_db) || + thd->dd_client()->acquire(alter_tbl_ctx->new_db, &new_schema)) + DBUG_RETURN(true); + bool exists = false; + for (auto cc_name : new_cc_names) { + if (thd->dd_client()->check_constraint_exists(*new_schema, cc_name, + &exists)) + DBUG_RETURN(true); + if (exists) { + my_error(ER_CHECK_CONSTRAINT_DUP_NAME, MYF(0), cc_name); + DBUG_RETURN(true); + } + } + + alter_info->drop_list.clear(); + alter_info->drop_list.resize(new_drop_list.size()); + std::move(new_drop_list.begin(), new_drop_list.end(), + alter_info->drop_list.begin()); + + alter_info->alter_state_list.clear(); + alter_info->alter_state_list.resize(new_state_list.size()); + std::move(new_state_list.begin(), new_state_list.end(), + alter_info->alter_state_list.begin()); + + alter_info->check_constraint_spec_list.clear(); + alter_info->check_constraint_spec_list.resize(new_check_cons_list.size()); + std::move(new_check_cons_list.begin(), new_check_cons_list.end(), + alter_info->check_constraint_spec_list.begin()); + + DBUG_RETURN(false); +} + +/** + Make old table definition's check constraint use temporary names and restore + check constraint names from new table definition. This is needed to avoid + problems with duplicate check constraint names while we have two definitions + of the same table. + Method updates only dd::Table object. It is not stored or updated to + data-dictionary in this method. + + @param thd Thread context. + @param old_table_db Database of old table. + @param old_table Old table definition. + @param new_table New table definition. + + @returns False - Success, True - Failure. +*/ +static bool adjust_check_constraint_names(THD *thd, const char *old_table_db, + dd::Table *old_table, + dd::Table *new_table) { + if (thd->m_cc_adjusted_names_map == nullptr) return false; + DBUG_ASSERT(!thd->m_cc_adjusted_names_map->empty()); + + if (old_table) { + MDL_request_list mdl_requests; + for (auto &cc : *old_table->check_constraints()) { + char temp_cc_name[3 + 20 + 2]; + snprintf(temp_cc_name, sizeof(temp_cc_name), "#cc_%llu", + (ulonglong)cc->id()); + + /* + Acquire lock on temporary names before updating data-dictionary just in + case somebody tries to create check constraints with same name. + */ + if (push_check_constraint_mdl_request_to_list(thd, old_table_db, + temp_cc_name, mdl_requests)) + return true; + + // Set adjusted name. + cc->set_name(temp_cc_name); + } + + if (thd->mdl_context.acquire_locks(&mdl_requests, + thd->variables.lock_wait_timeout)) + return true; + } + + // Restore check constraint names from cc_adjusted_names_map for new table. + for (auto &cc : *new_table->check_constraints()) { + cc->set_name(thd->m_cc_adjusted_names_map->actual_name(cc->name().c_str())); + } + + // After restore map is not needed. + thd->m_cc_adjusted_names_map->clear(); + thd->m_cc_adjusted_names_map = nullptr; + + return false; +} + +/** + Helper method to check if any check constraints (re-)evaluation is required. + If any check constraint re-evaluation is required then in-place alter is not + possible as it is done in the SQL-layer. This method is called by + is_inplace_alter_impossible() to check inplace alter is possible. + + Check constraint (re-)evaluation is required when + 1) New check constraint is added in ENFORCED state. + 2) Any existing check constraint is ENFORCED. + 3) Type of column used by any enforced check constraint is changed. + 4) check constraints expression depends on DEFAULT function on a column and + default is changed as part of alter operation. + + @param alter_info Data related to detected changes. + + @retval true Check constraint (re-)evaluation required. + @retval false Otherwise. +*/ +static bool is_any_check_constraints_evaluation_required( + const Alter_info *alter_info) { + /* + Check if any check constraint is added in enforced state or state of any + check is is changed to ENFORCED. + */ + if (alter_info->flags & Alter_info::ENFORCE_CHECK_CONSTRAINT) return true; + + for (auto &cc_spec : alter_info->check_constraint_spec_list) { + if (!cc_spec->is_enforced) continue; + + /* + if column is modified then check if type is changed or if default value is + changed. Check constraint re-evaluation is required in this case. + */ + if (alter_info->flags & Alter_info::ALTER_CHANGE_COLUMN) { + for (auto &fld : const_cast(alter_info)->create_list) { + // Get fields used by check constraint. + List fields; + cc_spec->check_expr->walk(&Item::collect_item_field_processor, + Item::WALK_POSTFIX, (uchar *)&fields); + for (auto &itm_fld : fields) { + if (itm_fld.type() != Item::FIELD_ITEM || itm_fld.field == nullptr) + continue; + + // Check if data type is changed. + if (!my_strcasecmp(system_charset_info, itm_fld.field_name, + fld.field_name) && + (itm_fld.data_type() != fld.sql_type)) + return true; + } + + /* + If column is modified then default might have changed. Check if + check constraint uses default function. + */ + if (fld.change && + cc_spec->check_expr->walk( + &Item::check_gcol_depend_default_processor, Item::WALK_POSTFIX, + reinterpret_cast(const_cast(fld.change)))) + return true; + } + } + + /* + If column is altered to drop or set default then check any check + constraint using the default function. Re-evaluation of check constraint + is required in this case. + */ + if (alter_info->flags & Alter_info::ALTER_CHANGE_COLUMN_DEFAULT) { + for (auto *alter : alter_info->alter_list) { + if (alter->change_type() == Alter_column::Type::SET_DEFAULT || + alter->change_type() == Alter_column::Type::DROP_DEFAULT) { + if (cc_spec->check_expr->walk( + &Item::check_gcol_depend_default_processor, + Item::WALK_POSTFIX, + reinterpret_cast(const_cast(alter->name)))) + return true; + } + } + } + } + + return false; +} + +bool lock_check_constraint_names_for_rename(THD *thd, const char *db, + const char *table_name, + const dd::Table *table_def, + const char *target_db, + const char *target_table_name) { + DBUG_ENTER("lock_check_constraint_names_for_rename"); + MDL_request_list mdl_requests; + size_t table_name_len = strlen(table_name); + + // Push lock requests for the check constraints defined on db.table_name. + for (auto &cc : table_def->check_constraints()) { + if (push_check_constraint_mdl_request_to_list(thd, db, cc->name().c_str(), + mdl_requests)) + DBUG_RETURN(true); + } + + // Push lock request for the check constraints in target table. + for (auto &cc : table_def->check_constraints()) { + const char *cc_name = cc->name().c_str(); + /* + If check constraint name is a generated name in the source table then + generate name with the target table to create mdl_request with it. + */ + bool is_generated_name = dd::is_generated_check_constraint_name( + table_name, table_name_len, cc->name().c_str(), cc->name().length()); + if (is_generated_name) { + char *end; + uint number = + my_strtoull(cc->name().c_str() + table_name_len + + sizeof(dd::CHECK_CONSTRAINT_NAME_SUBSTR) - 1, + &end, 10); + LEX_STRING name; + if (generate_check_constraint_name(thd, target_table_name, number, name, + true)) + DBUG_RETURN(true); + cc_name = name.str; + } + + /* + If check constraint name is generated or table moved different database + then create mdl_request with target_db.cc_name. + */ + if ((is_generated_name || + my_strcasecmp(table_alias_charset, db, target_db)) && + push_check_constraint_mdl_request_to_list(thd, target_db, cc_name, + mdl_requests)) + DBUG_RETURN(true); + } + + // Acquire locks on all the collected check constraint names. + if (!mdl_requests.is_empty() && + thd->mdl_context.acquire_locks(&mdl_requests, + thd->variables.lock_wait_timeout)) + DBUG_RETURN(true); + + DEBUG_SYNC(thd, "after_acquiring_lock_on_check_constraints_for_rename"); + + DBUG_RETURN(false); +} + +bool lock_check_constraint_names(THD *thd, TABLE_LIST *tables) { + DBUG_ENTER("lock_check_constraint_names"); + MDL_request_list mdl_requests; + + for (TABLE_LIST *table = tables; table != nullptr; + table = table->next_local) { + if (table->open_type != OT_BASE_ONLY && is_temporary_table(table)) continue; + + dd::cache::Dictionary_client::Auto_releaser releaser(thd->dd_client()); + + const dd::Abstract_table *abstract_table_def = nullptr; + if (thd->dd_client()->acquire(table->db, table->table_name, + &abstract_table_def)) + DBUG_RETURN(true); + + if (abstract_table_def == nullptr || + abstract_table_def->type() != dd::enum_table_type::BASE_TABLE) + continue; + + const dd::Table *table_def = + dynamic_cast(abstract_table_def); + DBUG_ASSERT(table_def != nullptr); + + for (auto &cc : table_def->check_constraints()) { + if (push_check_constraint_mdl_request_to_list( + thd, table->db, cc->name().c_str(), mdl_requests)) + DBUG_RETURN(false); + } + } + + // Acquire MDL lock on all the check constraint names. + if (!mdl_requests.is_empty() && + thd->mdl_context.acquire_locks(&mdl_requests, + thd->variables.lock_wait_timeout)) + DBUG_RETURN(true); + + DBUG_RETURN(false); +} diff --git a/sql/sql_table.h b/sql/sql_table.h index 8dc426478189..6503f1811620 100644 --- a/sql/sql_table.h +++ b/sql/sql_table.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2006, 2018, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2006, 2019, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License, version 2.0, @@ -81,6 +81,8 @@ static const uint NO_FK_CHECKS = 1 << 2; static const uint NO_DD_COMMIT = 1 << 3; /** Don't change generated foreign key names while renaming table. */ static const uint NO_FK_RENAME = 1 << 4; +/** Don't change generated check constraint names while renaming table. */ +static const uint NO_CC_RENAME = 1 << 5; size_t filename_to_tablename(const char *from, char *to, size_t to_length, bool stay_quiet = false); @@ -513,4 +515,37 @@ bool lock_trigger_names(THD *thd, TABLE_LIST *tables); struct TYPELIB; TYPELIB *create_typelib(MEM_ROOT *mem_root, Create_field *field_def); +/** + Method to collect check constraint names for the all the tables and acquire + MDL lock on them. + + @param[in] thd Thread handle. + @param[in] tables Check constraints of tables to be locked. + + @retval false Success. + @retval true Failure. +*/ +bool lock_check_constraint_names(THD *thd, TABLE_LIST *tables); + +/** + Method to lock check constraint names for rename table operation. + Method acquire locks on the constraint names of source table and + also on the name of check constraint in the target table. + + @param[in] thd Thread handle. + @param[in] db Database name. + @param[in] table_name Table name. + @param[in] table_def DD table object of source table. + @param[in] target_db Target database name. + @param[in] target_table_name Target table name. + + @retval false Success. + @retval true Failure. +*/ +bool lock_check_constraint_names_for_rename(THD *thd, const char *db, + const char *table_name, + const dd::Table *table_def, + const char *target_db, + const char *target_table_name); + #endif /* SQL_TABLE_INCLUDED */ diff --git a/sql/sql_update.cc b/sql/sql_update.cc index f5426a41513f..27d5195b76a1 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -796,6 +796,14 @@ bool Sql_cmd_update::update_single_table(THD *thd) { error = 1; break; } + if (invoke_table_check_constraints(thd, table)) { + if (thd->is_error()) { + error = 1; + break; + } + // continue when IGNORE clause is used. + continue; + } found_rows++; if (!records_are_comparable(table) || compare_records(table)) { @@ -2067,6 +2075,12 @@ bool Query_result_update::send_data(THD *thd, List &) { *values_for_table[offset], table, TRG_EVENT_UPDATE, 0)) DBUG_RETURN(true); + if (invoke_table_check_constraints(thd, table)) { + if (thd->is_error()) DBUG_RETURN(true); + // continue when IGNORE clause is used. + continue; + } + /* Reset the table->auto_increment_field_not_null as it is valid for only one row. @@ -2375,6 +2389,12 @@ bool Query_result_update::do_updates(THD *thd) { if (rc || check_record(thd, table->field)) goto err; } + if (invoke_table_check_constraints(thd, table)) { + if (thd->is_error()) goto err; + // continue when IGNORE clause is used. + continue; + } + if (!records_are_comparable(table) || compare_records(table)) { update_operations[offset]->set_function_defaults(table); int error; diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index d75859ff0ef3..98fbc8ac323e 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -1,5 +1,5 @@ /* - Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. + Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License, version 2.0, @@ -461,6 +461,7 @@ void warn_about_deprecated_national(THD *thd) For each token, please include in the same line a comment that contains one or more of the following tags: + SQL-2015-N : Non Reserved keyword as per SQL-2015 draft SQL-2015-R : Reserved keyword as per SQL-2015 draft SQL-2003-R : Reserved keyword as per SQL-2003 SQL-2003-N : Non Reserved keyword as per SQL-2003 @@ -1235,6 +1236,7 @@ void warn_about_deprecated_national(THD *thd) %token SECONDARY_UNLOAD_SYM /* MYSQL */ %token RETAIN_SYM /* MYSQL */ %token OLD_SYM /* SQL-2003-R */ +%token ENFORCED_SYM /* SQL-2015-N */ /* Resolve column attribute ambiguity -- force precedence of "UNIQUE KEY" against @@ -1494,6 +1496,8 @@ void warn_about_deprecated_national(THD *thd) opt_local opt_retain_current_password opt_discard_old_password + opt_constraint_enforcement + opt_not %type opt_show_cmd_type @@ -6149,16 +6153,8 @@ column_def: ; opt_check_or_references: - /* empty */ { $$= NULL; } - | check_constraint - { - /* - Currently we ignore the CHECK clause. - - Return expression for syntax validation purposes only: - */ - $$= $1; - } + /* empty */ { $$= NULL; } + | check_constraint { $$= $1; } | references { /* Currently we ignore FK references here: */ @@ -6202,21 +6198,14 @@ table_constraint_def: $8.fk_update_opt, $8.fk_delete_opt); } - | opt_constraint check_constraint - { - $$= $2; - } + | check_constraint { $$= $1; } ; check_constraint: - CHECK_SYM '(' expr ')' + opt_constraint CHECK_SYM '(' expr ')' opt_constraint_enforcement { - /* - Currently we ignore CHECK clauses in the query executor. - - Return expression for syntax validation purposes only: - */ - $$= NEW_PTN PT_check_constraint($3); + $$= NEW_PTN PT_check_constraint($1, $4, $6); + if ($$ == nullptr) MYSQL_YYABORT; // OOM } ; @@ -6225,6 +6214,16 @@ opt_constraint: | CONSTRAINT opt_ident { $$= $2; } ; +opt_not: + /* empty */ { $$= false; } + | NOT_SYM { $$= true; } + ; + +opt_constraint_enforcement: + /* empty */ { $$= true; } + | opt_not ENFORCED_SYM { $$ = !($1); } + ; + field_def: type opt_column_attribute_list { @@ -8025,6 +8024,10 @@ alter_list_item: { $$= NEW_PTN PT_alter_table_drop_key($3.str); } + | DROP CHECK_SYM ident + { + $$= NEW_PTN PT_alter_table_drop_check_constraint($3.str); + } | DISABLE_SYM KEYS { $$= NEW_PTN PT_alter_table_enable_keys(false); @@ -8049,6 +8052,10 @@ alter_list_item: { $$= NEW_PTN PT_alter_table_index_visible($3.str, $4); } + | ALTER CHECK_SYM ident opt_not ENFORCED_SYM + { + $$ = NEW_PTN PT_alter_table_check_constraint($3.str, !($4)); + } | RENAME opt_to table_ident { $$= NEW_PTN PT_alter_table_rename($3); @@ -14047,6 +14054,7 @@ role_or_label_keyword: | ENABLE_SYM | ENCRYPTION_SYM | ENDS_SYM + | ENFORCED_SYM | ENGINES_SYM | ENGINE_SYM | ENUM_SYM diff --git a/sql/table.cc b/sql/table.cc index e9fbfec26b1a..0046901316b0 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -1,5 +1,5 @@ /* - Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. + Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License, version 2.0, @@ -96,7 +96,8 @@ #include "sql/query_options.h" #include "sql/query_result.h" // Query_result #include "sql/sql_base.h" -#include "sql/sql_class.h" // THD +#include "sql/sql_check_constraint.h" // Sql_table_check_constraint +#include "sql/sql_class.h" // THD #include "sql/sql_error.h" #include "sql/sql_lex.h" #include "sql/sql_opt_exec_shared.h" @@ -2243,46 +2244,60 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, Validate the expression to see whether there are invalid Item objects. Needs to be done after fix_fields to allow checking references - to other generated columns or default value expressions. + to other generated columns, default value expressions or check constraints. @param expr Pointer to the expression - @param column_name The name of the column, to be used for error reporting. - @param column_index The column order - @param is_gen_col Wheather it is a generated column or a regular column - with generated default value. + @param source Source of value generator(a generated column, a regular + column with generated default value or + a check constraint). + @param source_name Name of the source (generated column, a reguler column + with generated default value or a check constraint). + @param column_index The column order. @retval true The generated expression has some invalid objects @retval false No illegal objects in the generated expression */ -static bool validate_value_generator_expr(Item *expr, const char *column_name, - int column_index, bool is_gen_col) { +static bool validate_value_generator_expr(Item *expr, + Value_generator_source source, + const char *source_name, + int column_index) { DBUG_ENTER("validate_value_generator_expr"); DBUG_ASSERT(expr); - int err_code = is_gen_col - ? ER_GENERATED_COLUMN_NAMED_FUNCTION_IS_NOT_ALLOWED - : ER_DEFAULT_VAL_GENERATED_NAMED_FUNCTION_IS_NOT_ALLOWED; + // Map to get actual error code from error_type for the source. + enum error_type { ER_NAME_FUNCTION, ER_FUNCTION, ER_VARIABLES, MAX_ERROR }; + uint error_code_map[][MAX_ERROR] = { + // Generated column errors. + {ER_GENERATED_COLUMN_NAMED_FUNCTION_IS_NOT_ALLOWED, + ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED, + ER_GENERATED_COLUMN_VARIABLES}, + // Default expressions errors. + {ER_DEFAULT_VAL_GENERATED_NAMED_FUNCTION_IS_NOT_ALLOWED, + ER_DEFAULT_VAL_GENERATED_FUNCTION_IS_NOT_ALLOWED, + ER_DEFAULT_VAL_GENERATED_VARIABLES}, + // Check constraint errors. + {ER_CHECK_CONSTRAINT_NAMED_FUNCTION_IS_NOT_ALLOWED, + ER_CHECK_CONSTRAINT_FUNCTION_IS_NOT_ALLOWED, + ER_CHECK_CONSTRAINT_VARIABLES}}; + uint err_code = error_code_map[source][ER_NAME_FUNCTION]; + // No non-deterministic functions are allowed as GC but most of them are // allowed as default value expressions - if ((expr->used_tables() & RAND_TABLE_BIT && is_gen_col)) { + if ((expr->used_tables() & RAND_TABLE_BIT && + (source == VGS_GENERATED_COLUMN))) { Item_func *func_item; if (expr->type() == Item::FUNC_ITEM && ((func_item = down_cast(expr)))) { - my_error(err_code, MYF(0), column_name, func_item->func_name()); + my_error(err_code, MYF(0), source_name, func_item->func_name()); DBUG_RETURN(true); } else { - // Error codes without specifying the function name - err_code = is_gen_col ? ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED - : ER_DEFAULT_VAL_GENERATED_FUNCTION_IS_NOT_ALLOWED; - my_error(err_code, MYF(0), column_name); + my_error(error_code_map[source][ER_FUNCTION], MYF(0), source_name); DBUG_RETURN(true); } } // System variables or parameters are not allowed else if (expr->used_tables() & INNER_TABLE_BIT) { - err_code = is_gen_col ? ER_GENERATED_COLUMN_VARIABLES - : ER_DEFAULT_VAL_GENERATED_VARIABLES; - my_error(err_code, MYF(0), column_name); + my_error(error_code_map[source][ER_VARIABLES], MYF(0), source_name); DBUG_RETURN(true); } @@ -2296,13 +2311,11 @@ static bool validate_value_generator_expr(Item *expr, const char *column_name, Walk through the Item tree, checking the validity of items belonging to the expression. */ - Check_function_as_value_generator_parameters checker_args(err_code, - is_gen_col); + Check_function_as_value_generator_parameters checker_args(err_code, source); checker_args.col_index = column_index; - if (expr->walk(&Item::check_function_as_value_generator, Item::WALK_POSTFIX, pointer_cast(&checker_args))) { - my_error(checker_args.err_code, MYF(0), column_name, + my_error(checker_args.err_code, MYF(0), source_name, checker_args.banned_function_name); DBUG_RETURN(true); } @@ -2312,7 +2325,7 @@ static bool validate_value_generator_expr(Item *expr, const char *column_name, if (expr->has_stored_program()) { /* purecov: begin deadcode */ DBUG_ASSERT(false); - my_error(err_code, MYF(0), column_name, "stored progam"); + my_error(err_code, MYF(0), source_name, "stored progam"); DBUG_RETURN(true); /* purecov: end */ } @@ -2321,21 +2334,27 @@ static bool validate_value_generator_expr(Item *expr, const char *column_name, } /** - Process the generated expression or generated default value of the column. - - @param thd The thread object - @param table The table to which the column belongs - @param field Field to which the val_generator is attached to - @param val_generator The expression to unpack - @param is_gen_col Whether is a column or just the expression for a - default value + Process the generated expression, generated default value of the column or + check constraint expression. + + @param thd The thread object + @param table The table to which the column belongs + @param val_generator The expression to unpack + @param source Source of value generator(a generated column, a regular + column with generated default value or + a check constraint). + @param source_name Name of the source (generated column, a reguler column + with generated default value or a check constraint). + @param field Field to which the val_generator is attached to for + generated columns and default expression. @retval true An error occurred, something was wrong with the function. @retval false Ok, generated expression is fixed sucessfully */ -static bool fix_value_generators_fields(THD *thd, TABLE *table, Field *field, +static bool fix_value_generators_fields(THD *thd, TABLE *table, Value_generator *val_generator, - bool is_gen_col) { + Value_generator_source source, + const char *source_name, Field *field) { uint dir_length, home_dir_length; bool result = true; Item *func_expr = val_generator->expr_item; @@ -2347,6 +2366,8 @@ static bool fix_value_generators_fields(THD *thd, TABLE *table, Field *field, char *db_name; char db_name_string[FN_REFLEN]; bool save_use_only_table_context; + std::unique_ptr + functional_index_error_handler; enum_mark_columns save_mark_used_columns = thd->mark_used_columns; DBUG_ASSERT(func_expr); DBUG_ENTER("fix_value_generators_fields"); @@ -2355,7 +2376,10 @@ static bool fix_value_generators_fields(THD *thd, TABLE *table, Field *field, // functional index names. Since functional indexes is implemented as // indexed hidden generated columns, we may end up printing out the // auto-generated column name if we don't have an extra error handler. - Functional_index_error_handler functional_index_error_handler(field, thd); + if (source == VGS_GENERATED_COLUMN || source == VGS_DEFAULT_EXPRESSION) + functional_index_error_handler = + std::unique_ptr( + new Functional_index_error_handler(field, thd)); /* Set-up the TABLE_LIST object to be a list with a single table @@ -2387,11 +2411,18 @@ static bool fix_value_generators_fields(THD *thd, TABLE *table, Field *field, (uchar *)context); save_where = thd->where; - if (field->is_field_for_functional_index()) { - thd->where = "functional index"; + dd::String_type where_str; + if (source == VGS_GENERATED_COLUMN || source == VGS_DEFAULT_EXPRESSION) { + thd->where = field->is_field_for_functional_index() + ? "functional index" + : (source == VGS_GENERATED_COLUMN) + ? "generated column function" + : "default value expression"; } else { - thd->where = - is_gen_col ? "generated column function" : "default value expression"; + DBUG_ASSERT(source == VGS_CHECK_CONSTRAINT); + where_str = + "check constraint " + dd::String_type(source_name) + " expression"; + thd->where = where_str.c_str(); } /* Save the context before fixing the fields*/ @@ -2438,8 +2469,8 @@ static bool fix_value_generators_fields(THD *thd, TABLE *table, Field *field, /* Checking if all items are valid to be part of the expression. */ - if (validate_value_generator_expr(func_expr, field->field_name, - field->field_index, is_gen_col)) + if (validate_value_generator_expr(func_expr, source, source_name, + field ? field->field_index : 0)) goto end; // Virtual columns expressions that substitute themselves are invalid @@ -2499,12 +2530,14 @@ void Value_generator::print_expr(THD *thd, String *out) { expr_item->print(thd, out, flags); } -bool unpack_value_generator(THD *thd, TABLE *table, Field *field, +bool unpack_value_generator(THD *thd, TABLE *table, Value_generator **val_generator, - bool is_create_table, bool is_gen_col, - bool *error_reported) { + Value_generator_source source, + const char *source_name, Field *field, + bool is_create_table, bool *error_reported) { DBUG_ENTER("unpack_value_generator"); - DBUG_ASSERT(field->table == table); + DBUG_ASSERT(field == nullptr || field->table == table); + LEX_STRING *val_gen_expr = &(*val_generator)->expr_str; DBUG_ASSERT(val_gen_expr); DBUG_ASSERT(!(*val_generator)->expr_item); // No Item in TABLE_SHARE @@ -2573,12 +2606,13 @@ bool unpack_value_generator(THD *thd, TABLE *table, Field *field, thd->lex->expr_allows_subselect = save_allow_subselects; /* - From now on use val_generator generated by the parser. It has an expr_item, - and no expr_str. + From now on use val_generator generated by the parser. It has an + expr_item, and no expr_str. */ *val_generator = parser_state.result; /* Keep attribute of generated column */ - (*val_generator)->set_field_stored(field->stored_in_db); + if (source == VGS_GENERATED_COLUMN || source == VGS_DEFAULT_EXPRESSION) + (*val_generator)->set_field_stored(field->stored_in_db); DBUG_ASSERT((*val_generator)->expr_item && !(*val_generator)->expr_str.str); @@ -2590,8 +2624,8 @@ bool unpack_value_generator(THD *thd, TABLE *table, Field *field, } /* Validate the Item tree. */ - status = fix_value_generators_fields(thd, table, field, (*val_generator), - is_gen_col); + status = fix_value_generators_fields(thd, table, (*val_generator), source, + source_name, field); // Permanent changes to the item_tree are completed. if (!thd->lex->is_ps_or_view_context_analysis()) @@ -2982,9 +3016,10 @@ int open_table_from_share(THD *thd, TABLE_SHARE *share, const char *alias, for (field_ptr = outparam->field; *field_ptr; field_ptr++) { if ((*field_ptr)->gcol_info) { - if (unpack_value_generator(thd, outparam, *field_ptr, - &(*field_ptr)->gcol_info, is_create_table, - true, &error_reported)) { + if (unpack_value_generator(thd, outparam, &(*field_ptr)->gcol_info, + VGS_GENERATED_COLUMN, + (*field_ptr)->field_name, *field_ptr, + is_create_table, &error_reported)) { *vfield_ptr = nullptr; error = 4; // in case no error is reported goto err; @@ -3020,9 +3055,10 @@ int open_table_from_share(THD *thd, TABLE_SHARE *share, const char *alias, outparam->gen_def_fields_ptr = gen_def_field; for (field_ptr = outparam->field; *field_ptr; field_ptr++) { if ((*field_ptr)->has_insert_default_general_value_expression()) { - if (unpack_value_generator(thd, outparam, *field_ptr, - &(*field_ptr)->m_default_val_expr, - is_create_table, false, &error_reported)) { + if (unpack_value_generator( + thd, outparam, &(*field_ptr)->m_default_val_expr, + VGS_DEFAULT_EXPRESSION, (*field_ptr)->field_name, *field_ptr, + is_create_table, &error_reported)) { (*field_ptr)->m_default_val_expr = nullptr; *gen_def_field = nullptr; // In case no error is reported @@ -3035,6 +3071,65 @@ int open_table_from_share(THD *thd, TABLE_SHARE *share, const char *alias, *gen_def_field = nullptr; // End marker } + /* + Set up table check constraints from the table share and unpack check + constraint expression. + */ + if (share->check_constraint_share_list != nullptr) { + DBUG_ASSERT(share->check_constraint_share_list->size() > 0); + + outparam->table_check_constraint_list = + new (root) Sql_table_check_constraint_list(root); + if (outparam->table_check_constraint_list == nullptr) goto err; // OOM + + for (auto &cc_share : *share->check_constraint_share_list) { + // Check constraint name. + LEX_CSTRING name; + if (lex_string_strmake(root, &name, cc_share->name().str, + cc_share->name().length)) + goto err; // OOM + + // Check constraint expression. + LEX_CSTRING expr_str; + if (lex_string_strmake(root, &expr_str, cc_share->expr_str().str, + cc_share->expr_str().length)) + goto err; // OOM + + /* + Value generator instance for the check constraint expression. Memory + for val_gen is allocated in the thd->mem_root here intentionally. + Parser instantiate another value generator object in TABLE's mem_root + in unpack_value_generator(). + */ + Value_generator *val_gen = new (thd->mem_root) Value_generator(); + val_gen->dup_expr_str(thd->mem_root, expr_str.str, expr_str.length); + + Sql_table_check_constraint *table_cc = + new (root) Sql_table_check_constraint( + name, expr_str, cc_share->is_enforced(), val_gen, outparam); + if (table_cc == nullptr) goto err; // OOM + + /* + Use actual name for error reporting if check constraint name is + adjusted for the operation. + */ + const char *cc_name = table_cc->name().str; + if (thd->m_cc_adjusted_names_map != nullptr) + cc_name = thd->m_cc_adjusted_names_map->actual_name(cc_name); + + // Unpack check constraint expression. + if (unpack_value_generator(thd, outparam, &val_gen, VGS_CHECK_CONSTRAINT, + cc_name, nullptr, is_create_table, + &error_reported)) + goto err; + + // Use value generator obtained from the parser. + table_cc->set_value_generator(val_gen); + + if (outparam->table_check_constraint_list->push_back(table_cc)) goto err; + } + } + /* The table struct is now initialized; Open the table */ error = 2; if (db_stat) { @@ -3145,6 +3240,11 @@ int open_table_from_share(THD *thd, TABLE_SHARE *share, const char *alias, for (Field **gen_def = outparam->gen_def_fields_ptr; *gen_def; gen_def++) free_items((*gen_def)->m_default_val_expr->item_list); } + if (outparam->table_check_constraint_list != nullptr) { + for (auto &table_cc : *outparam->table_check_constraint_list) { + free_items(table_cc->value_generator()->item_list); + } + } outparam->file = 0; // For easier error checking outparam->db_stat = 0; if (!internal_tmp) free_root(root, MYF(0)); @@ -3176,6 +3276,11 @@ int closefrm(TABLE *table, bool free_share) { } table->field = 0; } + if (table->table_check_constraint_list != nullptr) { + for (auto &table_cc : *table->table_check_constraint_list) { + free_items(table_cc->value_generator()->item_list); + } + } destroy(table->file); table->file = 0; /* For easier errorchecking */ if (table->part_info) { @@ -4082,7 +4187,8 @@ bool TABLE::refix_value_generator_items(THD *thd) { Field *vfield = *vfield_ptr; DBUG_ASSERT(vfield->gcol_info && vfield->gcol_info->expr_item); refix_inner_value_generator_items(thd, vfield->gcol_info, vfield, - vfield->table, true); + vfield->table, VGS_GENERATED_COLUMN, + vfield->field_name); } } @@ -4091,16 +4197,28 @@ bool TABLE::refix_value_generator_items(THD *thd) { gen_def_col++) { Value_generator *gen_def_expr = (*gen_def_col)->m_default_val_expr; DBUG_ASSERT(gen_def_expr && gen_def_expr->expr_item); - refix_inner_value_generator_items(thd, gen_def_expr, (*gen_def_col), - (*gen_def_col)->table, false); + refix_inner_value_generator_items( + thd, gen_def_expr, (*gen_def_col), (*gen_def_col)->table, + VGS_DEFAULT_EXPRESSION, (*gen_def_col)->field_name); } + if (table_check_constraint_list != nullptr) { + for (auto &table_cc : *table_check_constraint_list) { + Value_generator *cc_expr = table_cc->value_generator(); + DBUG_ASSERT(cc_expr != nullptr && cc_expr->expr_item != nullptr); + refix_inner_value_generator_items(thd, cc_expr, nullptr, + table_cc->table(), VGS_CHECK_CONSTRAINT, + table_cc->name().str); + } + } + return false; } bool TABLE::refix_inner_value_generator_items(THD *thd, Value_generator *g_expr, Field *field, TABLE *table, - bool is_gen_col) { + Value_generator_source source, + const char *source_name) { if (!g_expr->expr_item->fixed) { bool res = false; /* @@ -4131,7 +4249,8 @@ bool TABLE::refix_inner_value_generator_items(THD *thd, Value_generator *g_expr, ulong sav_want_priv = thd->want_privilege; thd->want_privilege = 0; - if (fix_value_generators_fields(thd, table, field, g_expr, is_gen_col)) + if (fix_value_generators_fields(thd, table, g_expr, source, source_name, + field)) res = true; if (!g_expr->permanent_changes_completed && @@ -4164,6 +4283,11 @@ void TABLE::cleanup_value_generator_items() { for (Field **vfield_ptr = gen_def_fields_ptr; *vfield_ptr; vfield_ptr++) cleanup_items((*vfield_ptr)->m_default_val_expr->item_list); + if (table_check_constraint_list != nullptr) { + for (auto &table_cc : *table_check_constraint_list) + cleanup_items(table_cc->value_generator()->item_list); + } + if (!has_gcol()) return; for (Field **vfield_ptr = vfield; *vfield_ptr; vfield_ptr++) diff --git a/sql/table.h b/sql/table.h index ac6adf21d4f5..119a1d11ce7a 100644 --- a/sql/table.h +++ b/sql/table.h @@ -1,7 +1,7 @@ #ifndef TABLE_INCLUDED #define TABLE_INCLUDED -/* Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License, version 2.0, @@ -96,6 +96,7 @@ class Temp_table_param; class handler; class partition_info; enum enum_stats_auto_recalc : int; +enum Value_generator_source : short; enum row_type : int; struct HA_CREATE_INFO; struct LEX; @@ -115,6 +116,14 @@ enum class enum_table_type; } // namespace dd class Common_table_expr; +class Sql_table_check_constraint; +using Sql_table_check_constraint_list = + Mem_root_array; + +class Sql_check_constraint_share; +using Sql_check_constraint_share_list = + Mem_root_array; + typedef Mem_root_array_YY Create_col_name_list; typedef int64 query_id_t; @@ -931,6 +940,9 @@ struct TABLE_SHARE { uint foreign_key_parents{0}; TABLE_SHARE_FOREIGN_KEY_PARENT_INFO *foreign_key_parent{nullptr}; + // List of check constraint share instances. + Sql_check_constraint_share_list *check_constraint_share_list{nullptr}; + /** Set share's table cache key and update its db and table name appropriately. @@ -1462,6 +1474,9 @@ struct TABLE { uint db_stat{0}; /* mode of file as in handler.h */ int current_lock{0}; /* Type of lock on table */ + // List of table check constraints. + Sql_table_check_constraint_list *table_check_constraint_list{nullptr}; + private: /** If true, this table is inner w.r.t. some outer join operation, all columns @@ -1838,19 +1853,26 @@ struct TABLE { /** Helper function for refix_value_generator_items() that fixes one column's - expression (be it GC or default expression). - - @param[in] thd current thread - @param[in,out] g_expr the expression who's items needs to be fixed - @param[in] table the table it blongs to - @param[in] field the column it blongs to - @param[in] is_gen_col if it is a generated column or default expression + expression (be it GC or default expression) and check constraint expression. + + @param[in] thd current thread + @param[in,out] g_expr the expression who's items needs to be fixed + @param[in] table the table it blongs to + @param[in] field the column it blongs to (for GC and Default + expression). + @param[in] source Source of value generator(a generated column, a + regular column with generated default value or + a check constraint). + @param[in] source_name Name of the source (generated column, a reguler + column with generated default value or a check + constraint). @return true if error, else false */ bool refix_inner_value_generator_items(THD *thd, Value_generator *g_expr, Field *field, TABLE *table, - bool is_gen_col); + Value_generator_source source, + const char *source_name); /** Clean any state in items associated with generated columns to be ready for @@ -3648,17 +3670,22 @@ static inline void dbug_tmp_restore_column_maps( void init_mdl_requests(TABLE_LIST *table_list); /** - Unpacks the definition of a generated column or default expression passed as - argument. Parses the text obtained from TABLE_SHARE and produces an Item. + Unpacks the definition of a generated column, default expression or check + constraint expression passed as argument. Parses the text obtained from + TABLE_SHARE and produces an Item. @param thd Thread handler @param table Table with the checked field + @param val_generator The expression to unpack. + @param source Source of value generator(a generated column, + a regular column with generated default value or + a check constraint). + @param source_name Name of the source (generated column, a reguler + column with generated default value or a check + constraint). @param field Pointer to Field object - @param val_generator The virtual column or default expr to be parsed. @param is_create_table Indicates that table is opened as part of CREATE or ALTER and does not yet exist in SE - @param is_gen_col Indicates if the expression is a column or just - an expression for the default value. @param error_reported updated flag for the caller that no other error messages are to be generated. @@ -3666,10 +3693,11 @@ void init_mdl_requests(TABLE_LIST *table_list); @retval false Success. */ -bool unpack_value_generator(THD *thd, TABLE *table, Field *field, +bool unpack_value_generator(THD *thd, TABLE *table, Value_generator **val_generator, - bool is_create_table, bool is_gen_col, - bool *error_reported); + Value_generator_source source, + const char *source_name, Field *field, + bool is_create_table, bool *error_reported); /** Unpack the partition expression. Parse the partition expression diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc index b8c6f06bedcb..7cb8a32b0c55 100644 --- a/storage/innobase/handler/handler0alter.cc +++ b/storage/innobase/handler/handler0alter.cc @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 2005, 2018, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2005, 2019, Oracle and/or its affiliates. All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License, version 2.0, as published by the @@ -149,7 +149,10 @@ static const Alter_inplace_info::HA_ALTER_FLAGS INNOBASE_INPLACE_IGNORE = Alter_inplace_info::ALTER_COLUMN_DEFAULT | Alter_inplace_info::ALTER_COLUMN_COLUMN_FORMAT | Alter_inplace_info::ALTER_COLUMN_STORAGE_TYPE | - Alter_inplace_info::ALTER_RENAME | Alter_inplace_info::CHANGE_INDEX_OPTION; + Alter_inplace_info::ALTER_RENAME | Alter_inplace_info::CHANGE_INDEX_OPTION | + Alter_inplace_info::ADD_CHECK_CONSTRAINT | + Alter_inplace_info::DROP_CHECK_CONSTRAINT | + Alter_inplace_info::SUSPEND_CHECK_CONSTRAINT; /** Operations on foreign key definitions (changing the schema only) */ static const Alter_inplace_info::HA_ALTER_FLAGS INNOBASE_FOREIGN_OPERATIONS = diff --git a/storage/innobase/include/dict0dd.h b/storage/innobase/include/dict0dd.h index b8fe2871983a..c5793ae525df 100644 --- a/storage/innobase/include/dict0dd.h +++ b/storage/innobase/include/dict0dd.h @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 2015, 2018, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2015, 2019, Oracle and/or its affiliates. All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License, version 2.0, as published by the @@ -278,6 +278,7 @@ const innodb_dd_table_t innodb_dd_table[] = { INNODB_DD_TABLE("catalogs", 2), INNODB_DD_TABLE("character_sets", 3), + INNODB_DD_TABLE("check_constraints", 3), INNODB_DD_TABLE("collations", 3), INNODB_DD_TABLE("column_statistics", 3), INNODB_DD_TABLE("column_type_elements", 1), diff --git a/storage/innobase/include/fsp0fsp.ic b/storage/innobase/include/fsp0fsp.ic index ec6f7cc445c6..373e87283025 100644 --- a/storage/innobase/include/fsp0fsp.ic +++ b/storage/innobase/include/fsp0fsp.ic @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1995, 2018, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 1995, 2019, Oracle and/or its affiliates. All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License, version 2.0, as published by the @@ -295,7 +295,7 @@ inline bool fsp_is_inode_page(page_no_t page) { /* Number of all hard-coded DD table indexes. Please sync it with innodb_dd_table array. */ - static const uint indexes = 95; + static const uint indexes = 98; /* Max page number for index root pages of hard-coded DD tables. */ static const uint max_page_no = diff --git a/storage/perfschema/pfs_column_types.cc b/storage/perfschema/pfs_column_types.cc index 3c910c20114f..d7ed1c5a9380 100644 --- a/storage/perfschema/pfs_column_types.cc +++ b/storage/perfschema/pfs_column_types.cc @@ -1,4 +1,4 @@ -/* Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License, version 2.0, @@ -55,6 +55,7 @@ static s_object_type_map object_type_map[] = { {OBJECT_TYPE_BACKUP_LOCK, {C_STRING_WITH_LEN("BACKUP LOCK")}}, {OBJECT_TYPE_RESOURCE_GROUPS, {C_STRING_WITH_LEN("RESOURCE_GROUPS")}}, {OBJECT_TYPE_FOREIGN_KEY, {C_STRING_WITH_LEN("FOREIGN KEY")}}, + {OBJECT_TYPE_CHECK_CONSTRAINT, {C_STRING_WITH_LEN("CHECK CONSTRAINT")}}, {NO_OBJECT_TYPE, {C_STRING_WITH_LEN("")}}}; void object_type_to_string(enum_object_type object_type, const char **string, diff --git a/storage/perfschema/pfs_column_types.h b/storage/perfschema/pfs_column_types.h index 18ad2d180276..fca8af053169 100644 --- a/storage/perfschema/pfs_column_types.h +++ b/storage/perfschema/pfs_column_types.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2008, 2019, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License, version 2.0, @@ -215,12 +215,13 @@ enum enum_object_type { OBJECT_TYPE_COLUMN_STATISTICS = 15, OBJECT_TYPE_BACKUP_LOCK = 16, OBJECT_TYPE_RESOURCE_GROUPS = 17, - OBJECT_TYPE_FOREIGN_KEY = 18 + OBJECT_TYPE_FOREIGN_KEY = 18, + OBJECT_TYPE_CHECK_CONSTRAINT = 19 }; /** Integer, first value of @sa enum_object_type. */ #define FIRST_OBJECT_TYPE (static_cast(OBJECT_TYPE_EVENT)) /** Integer, last value of @sa enum_object_type. */ -#define LAST_OBJECT_TYPE (static_cast(OBJECT_TYPE_FOREIGN_KEY)) +#define LAST_OBJECT_TYPE (static_cast(OBJECT_TYPE_CHECK_CONSTRAINT)) /** Integer, number of values of @sa enum_object_type. */ #define COUNT_OBJECT_TYPE (LAST_OBJECT_TYPE - FIRST_OBJECT_TYPE + 1) diff --git a/storage/perfschema/table_events_waits.cc b/storage/perfschema/table_events_waits.cc index 43379c550be6..f113391bad1b 100644 --- a/storage/perfschema/table_events_waits.cc +++ b/storage/perfschema/table_events_waits.cc @@ -1,4 +1,4 @@ -/* Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2008, 2019, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License, version 2.0, @@ -384,7 +384,7 @@ int table_events_waits_common::make_metadata_lock_object_columns( if (safe_metadata_lock->get_version() == wait->m_weak_version) { // TODO: remove code duplication with PFS_column_row::make_row() - static_assert(MDL_key::NAMESPACE_END == 17, + static_assert(MDL_key::NAMESPACE_END == 18, "Adjust performance schema when changing enum_mdl_namespace"); MDL_key *mdl = &safe_metadata_lock->m_mdl_key; @@ -509,6 +509,12 @@ int table_events_waits_common::make_metadata_lock_object_columns( m_row.m_object_schema_length = mdl->db_name_length(); m_row.m_object_name_length = mdl->name_length(); break; + case MDL_key::CHECK_CONSTRAINT: + m_row.m_object_type = "CHECK CONSTRAINT"; + m_row.m_object_type_length = 16; + m_row.m_object_schema_length = mdl->db_name_length(); + m_row.m_object_name_length = mdl->name_length(); + break; case MDL_key::NAMESPACE_END: default: m_row.m_object_type_length = 0; diff --git a/storage/perfschema/table_helper.cc b/storage/perfschema/table_helper.cc index a6d9453f6783..7eeeb4cfc32e 100644 --- a/storage/perfschema/table_helper.cc +++ b/storage/perfschema/table_helper.cc @@ -693,7 +693,7 @@ int PFS_object_row::make_row(PFS_program *pfs) { } int PFS_column_row::make_row(const MDL_key *mdl) { - static_assert(MDL_key::NAMESPACE_END == 17, + static_assert(MDL_key::NAMESPACE_END == 18, "Adjust performance schema when changing enum_mdl_namespace"); switch (mdl->mdl_namespace()) { @@ -798,6 +798,11 @@ int PFS_column_row::make_row(const MDL_key *mdl) { m_schema_name_length = mdl->db_name_length(); m_object_name_length = mdl->name_length(); break; + case MDL_key::CHECK_CONSTRAINT: + m_object_type = OBJECT_TYPE_CHECK_CONSTRAINT; + m_schema_name_length = mdl->db_name_length(); + m_object_name_length = mdl->name_length(); + break; case MDL_key::NAMESPACE_END: default: DBUG_ASSERT(false);