diff --git a/include/my_base.h b/include/my_base.h index bf760c89483..038045dde2a 100644 --- a/include/my_base.h +++ b/include/my_base.h @@ -270,17 +270,15 @@ enum ha_base_keytype { #define HA_NOSAME 1U /* Set if not dupplicated records */ #define HA_PACK_KEY 2U /* Pack string key to previous key */ -#define HA_AUTO_KEY 16U +#define HA_AUTO_KEY 16U /* MEMORY/MyISAM/Aria internal */ #define HA_BINARY_PACK_KEY 32U /* Packing of all keys to prev key */ #define HA_FULLTEXT 128U /* For full-text search */ -#define HA_UNIQUE_CHECK 256U /* Check the key for uniqueness */ #define HA_SPATIAL 1024U /* For spatial search */ #define HA_NULL_ARE_EQUAL 2048U /* NULL in key are cmp as equal */ #define HA_GENERATED_KEY 8192U /* Automatically generated key */ /* The combination of the above can be used for key type comparison. */ -#define HA_KEYFLAG_MASK (HA_NOSAME | HA_AUTO_KEY | \ - HA_FULLTEXT | HA_UNIQUE_CHECK | \ +#define HA_KEYFLAG_MASK (HA_NOSAME | HA_AUTO_KEY | HA_FULLTEXT | \ HA_SPATIAL | HA_NULL_ARE_EQUAL | HA_GENERATED_KEY) /* diff --git a/mysql-test/main/create.result b/mysql-test/main/create.result index 9ab1db89029..c1ef8b527de 100644 --- a/mysql-test/main/create.result +++ b/mysql-test/main/create.result @@ -1221,7 +1221,7 @@ drop table if exists t1,t2,t3; # Fix modified for MariaDB: we support this syntax create table t1 (a int) transactional=0; Warnings: -Warning 1478 Table storage engine 'MyISAM' does not support the create option 'TRANSACTIONAL=0' +Warning 1911 Unknown option 'transactional' create table t2 (a int) page_checksum=1; create table t3 (a int) row_format=page; drop table t1,t2,t3; @@ -2019,7 +2019,7 @@ drop table t1; # MDEV-18428 Memory: If transactional=0 is specified in CREATE TABLE, it is not possible to ALTER TABLE # create table t1 (c int(10) unsigned) engine=memory transactional=0; -ERROR HY000: Table storage engine 'MEMORY' does not support the create option 'TRANSACTIONAL=0' +ERROR HY000: Unknown option 'transactional' # # End of 10.2 tests # diff --git a/mysql-test/main/create.test b/mysql-test/main/create.test index db8638ebe54..e9470edefab 100644 --- a/mysql-test/main/create.test +++ b/mysql-test/main/create.test @@ -1879,7 +1879,7 @@ drop table t1; --echo # --echo # MDEV-18428 Memory: If transactional=0 is specified in CREATE TABLE, it is not possible to ALTER TABLE --echo # ---error ER_ILLEGAL_HA_CREATE_OPTION +--error ER_UNKNOWN_OPTION create table t1 (c int(10) unsigned) engine=memory transactional=0; --echo # diff --git a/mysql-test/main/myisam.result b/mysql-test/main/myisam.result index d1f3c0ad71f..e0923ee037e 100644 --- a/mysql-test/main/myisam.result +++ b/mysql-test/main/myisam.result @@ -2415,13 +2415,13 @@ DROP TABLE t1; set statement sql_mode='' for create table t1 (n int not null, c char(1)) transactional=1; Warnings: -Warning 1478 Table storage engine 'MyISAM' does not support the create option 'TRANSACTIONAL=1' +Warning 1911 Unknown option 'transactional' show create table t1; Table Create Table t1 CREATE TABLE `t1` ( `n` int(11) NOT NULL, `c` char(1) DEFAULT NULL -) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci TRANSACTIONAL=1 +) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci /* TRANSACTIONAL=1 */ drop table t1; CREATE TABLE t1 (line LINESTRING NOT NULL) engine=myisam; INSERT INTO t1 VALUES (GeomFromText("LINESTRING(0 0)")); diff --git a/mysql-test/main/query_cache_innodb.result b/mysql-test/main/query_cache_innodb.result index 62424ac362b..e5569c53d5f 100644 --- a/mysql-test/main/query_cache_innodb.result +++ b/mysql-test/main/query_cache_innodb.result @@ -85,7 +85,7 @@ t2id id use test; drop database `#mysql50#-`; SET NAMES default; -FOUND 8 /\[ERROR\] Invalid \(old\?\) table or database name/ in mysqld.1.err +FOUND 10 /\[ERROR\] Invalid \(old\?\) table or database name/ in mysqld.1.err set global query_cache_type=DEFAULT; set global query_cache_size=@save_query_cache_size; End of 10.2 tests diff --git a/mysql-test/main/table_options.result b/mysql-test/main/table_options.result index 60f25c96a0d..917c4716610 100644 --- a/mysql-test/main/table_options.result +++ b/mysql-test/main/table_options.result @@ -1,4 +1,3 @@ -drop table if exists t1; SET @OLD_SQL_MODE=@@SQL_MODE; SET SQL_MODE='IGNORE_BAD_TABLE_OPTIONS'; create table t1 (a int fkey=vvv, key akey (a) dff=vvv) tkey1='1v1'; @@ -180,3 +179,103 @@ SET SQL_MODE=''; create table t1 (a int fkey=vvv, key akey (a) dff=vvv) tkey1=1v1; ERROR HY000: Unknown option 'fkey' SET @@SQL_MODE=@OLD_SQL_MODE; +# +# End of 5.5 tests +# +# +# MDEV-31822 ALTER TABLE ENGINE=x started failing instead of producing warning on unsupported TRANSACTIONAL=1 +# +create table t0 (a int) transactional=0 engine=aria; +create table t1 (a int) transactional=1 engine=aria; +create table t2 (a int) transactional=default engine=aria; +show create table t0; +Table Create Table +t0 CREATE TABLE `t0` ( + `a` int(11) DEFAULT NULL +) ENGINE=Aria DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci PAGE_CHECKSUM=1 TRANSACTIONAL=0 +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` int(11) DEFAULT NULL +) ENGINE=Aria DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci PAGE_CHECKSUM=1 TRANSACTIONAL=1 +show create table t2; +Table Create Table +t2 CREATE TABLE `t2` ( + `a` int(11) DEFAULT NULL +) ENGINE=Aria DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci PAGE_CHECKSUM=1 +alter table t0 engine=myisam; +alter table t1 engine=myisam; +alter table t2 engine=myisam; +show create table t0; +Table Create Table +t0 CREATE TABLE `t0` ( + `a` int(11) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci PAGE_CHECKSUM=1 /* TRANSACTIONAL=0 */ +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` int(11) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci PAGE_CHECKSUM=1 /* TRANSACTIONAL=1 */ +show create table t2; +Table Create Table +t2 CREATE TABLE `t2` ( + `a` int(11) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci PAGE_CHECKSUM=1 +alter table t0 engine=myisam transactional=0; +ERROR HY000: Unknown option 'transactional' +alter table t1 engine=myisam transactional=1; +ERROR HY000: Unknown option 'transactional' +alter table t2 engine=myisam transactional=default; +ERROR HY000: Unknown option 'transactional' +set sql_mode=IGNORE_BAD_TABLE_OPTIONS; +alter table t0 engine=myisam transactional=0; +Warnings: +Warning 1911 Unknown option 'transactional' +alter table t1 engine=myisam transactional=1; +Warnings: +Warning 1911 Unknown option 'transactional' +alter table t2 engine=myisam transactional=default; +Warnings: +Warning 1911 Unknown option 'transactional' +show create table t0; +Table Create Table +t0 CREATE TABLE `t0` ( + `a` int(11) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci TRANSACTIONAL=0 +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` int(11) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci TRANSACTIONAL=1 +show create table t2; +Table Create Table +t2 CREATE TABLE `t2` ( + `a` int(11) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci +drop table t0,t1,t2; +create table t1 (a int) foo=bar; +Warnings: +Warning 1911 Unknown option 'foo' +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` int(11) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci `foo`=bar +set sql_mode=default; +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` int(11) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci /* `foo`=bar */ +alter table t1 engine=aria bar=foo; +ERROR HY000: Unknown option 'bar' +alter table t1 engine=aria; +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` int(11) DEFAULT NULL +) ENGINE=Aria DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci PAGE_CHECKSUM=1 /* `foo`=bar */ +drop table t1; +# +# End of 10.5 tests +# diff --git a/mysql-test/main/table_options.test b/mysql-test/main/table_options.test index 533e6829c00..0605ce9ee0d 100644 --- a/mysql-test/main/table_options.test +++ b/mysql-test/main/table_options.test @@ -1,7 +1,3 @@ ---disable_warnings -drop table if exists t1; ---enable_warnings - SET @OLD_SQL_MODE=@@SQL_MODE; SET SQL_MODE='IGNORE_BAD_TABLE_OPTIONS'; @@ -66,3 +62,52 @@ SET SQL_MODE=''; create table t1 (a int fkey=vvv, key akey (a) dff=vvv) tkey1=1v1; SET @@SQL_MODE=@OLD_SQL_MODE; + +--echo # +--echo # End of 5.5 tests +--echo # + +--echo # +--echo # MDEV-31822 ALTER TABLE ENGINE=x started failing instead of producing warning on unsupported TRANSACTIONAL=1 +--echo # +create table t0 (a int) transactional=0 engine=aria; +create table t1 (a int) transactional=1 engine=aria; +create table t2 (a int) transactional=default engine=aria; +show create table t0; +show create table t1; +show create table t2; +alter table t0 engine=myisam; +alter table t1 engine=myisam; +alter table t2 engine=myisam; +show create table t0; +show create table t1; +show create table t2; +--error ER_UNKNOWN_OPTION +alter table t0 engine=myisam transactional=0; +--error ER_UNKNOWN_OPTION +alter table t1 engine=myisam transactional=1; +--error ER_UNKNOWN_OPTION +alter table t2 engine=myisam transactional=default; +set sql_mode=IGNORE_BAD_TABLE_OPTIONS; +alter table t0 engine=myisam transactional=0; +alter table t1 engine=myisam transactional=1; +alter table t2 engine=myisam transactional=default; +show create table t0; +show create table t1; +show create table t2; +drop table t0,t1,t2; + +# same behavior for other unknown options: +create table t1 (a int) foo=bar; +show create table t1; +set sql_mode=default; +show create table t1; +--error ER_UNKNOWN_OPTION +alter table t1 engine=aria bar=foo; +alter table t1 engine=aria; +show create table t1; +drop table t1; + +--echo # +--echo # End of 10.5 tests +--echo # diff --git a/mysql-test/suite/galera/r/mariadb_tzinfo_to_sql.result b/mysql-test/suite/galera/r/mariadb_tzinfo_to_sql.result old mode 100644 new mode 100755 index 340840d59d7..9750c97a481 --- a/mysql-test/suite/galera/r/mariadb_tzinfo_to_sql.result +++ b/mysql-test/suite/galera/r/mariadb_tzinfo_to_sql.result @@ -11,8 +11,8 @@ CREATE TABLE time_zone_name LIKE mysql.time_zone_name; CREATE TABLE time_zone_transition LIKE mysql.time_zone_transition; CREATE TABLE time_zone_transition_type LIKE mysql.time_zone_transition_type; CREATE TABLE time_zone_leap_second LIKE mysql.time_zone_leap_second; -ALTER TABLE time_zone_name ENGINE=MyISAM TRANSACTIONAL=default; -ALTER TABLE time_zone_transition_type ENGINE=MyISAM TRANSACTIONAL=default; +ALTER TABLE time_zone_name ENGINE=MyISAM; +ALTER TABLE time_zone_transition_type ENGINE=MyISAM; SET @save_wsrep_mode=@@WSREP_MODE; # # Run on zoneinfo directory --skip-write-binlog diff --git a/mysql-test/suite/galera/t/mariadb_tzinfo_to_sql.test b/mysql-test/suite/galera/t/mariadb_tzinfo_to_sql.test old mode 100644 new mode 100755 index 4c163bc8d79..192a7cb228d --- a/mysql-test/suite/galera/t/mariadb_tzinfo_to_sql.test +++ b/mysql-test/suite/galera/t/mariadb_tzinfo_to_sql.test @@ -20,8 +20,8 @@ CREATE TABLE time_zone_name LIKE mysql.time_zone_name; CREATE TABLE time_zone_transition LIKE mysql.time_zone_transition; CREATE TABLE time_zone_transition_type LIKE mysql.time_zone_transition_type; CREATE TABLE time_zone_leap_second LIKE mysql.time_zone_leap_second; -ALTER TABLE time_zone_name ENGINE=MyISAM TRANSACTIONAL=default; -ALTER TABLE time_zone_transition_type ENGINE=MyISAM TRANSACTIONAL=default; +ALTER TABLE time_zone_name ENGINE=MyISAM; +ALTER TABLE time_zone_transition_type ENGINE=MyISAM; SET @save_wsrep_mode=@@WSREP_MODE; diff --git a/mysql-test/suite/galera/t/mysql_tzinfo_to_sql.test b/mysql-test/suite/galera/t/mysql_tzinfo_to_sql.test old mode 100644 new mode 100755 diff --git a/mysql-test/suite/gcol/r/innodb_virtual_basic.result b/mysql-test/suite/gcol/r/innodb_virtual_basic.result index 5b599dc3520..3823887186b 100644 --- a/mysql-test/suite/gcol/r/innodb_virtual_basic.result +++ b/mysql-test/suite/gcol/r/innodb_virtual_basic.result @@ -1077,7 +1077,7 @@ KEY `a_2` (`a`,`vbidxcol`), KEY `vbidxcol_2` (`vbidxcol`,`d`), CONSTRAINT `fk_16` FOREIGN KEY (`a`) REFERENCES `ibstd_16` (`a`) ON DELETE SET NULL ) ENGINE=InnoDB; -DROP TABLE ibstd_16_fk; +ERROR HY000: Function or expression 'a' cannot be used in the GENERATED ALWAYS AS clause of `vadcol` CREATE TABLE `ibstd_16_fk` ( `a` int(11) DEFAULT NULL, `d` int(11) DEFAULT NULL, diff --git a/mysql-test/suite/gcol/t/innodb_virtual_basic.test b/mysql-test/suite/gcol/t/innodb_virtual_basic.test index 87251ad7d52..3259875823f 100644 --- a/mysql-test/suite/gcol/t/innodb_virtual_basic.test +++ b/mysql-test/suite/gcol/t/innodb_virtual_basic.test @@ -1021,7 +1021,7 @@ CREATE TABLE `ibstd_16` ( ) ENGINE=INNODB; # Block when FK constraint on base column of stored column. -#--error ER_CANNOT_ADD_FOREIGN +--error ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED CREATE TABLE `ibstd_16_fk` ( `a` int(11) DEFAULT NULL, `d` int(11) DEFAULT NULL, @@ -1040,7 +1040,6 @@ CREATE TABLE `ibstd_16_fk` ( KEY `vbidxcol_2` (`vbidxcol`,`d`), CONSTRAINT `fk_16` FOREIGN KEY (`a`) REFERENCES `ibstd_16` (`a`) ON DELETE SET NULL ) ENGINE=InnoDB; -DROP TABLE ibstd_16_fk; # Take out "KEY `a_2` (`a`,`vbidxcol`)", this should then be successful CREATE TABLE `ibstd_16_fk` ( diff --git a/mysql-test/suite/innodb/r/stored_fk.result b/mysql-test/suite/innodb/r/stored_fk.result index fc48f346656..542d362f3cf 100644 --- a/mysql-test/suite/innodb/r/stored_fk.result +++ b/mysql-test/suite/innodb/r/stored_fk.result @@ -1,19 +1,21 @@ -# Create statement with FK on base column of stored column -create table t1(f1 int, f2 int as(f1) stored, -foreign key(f1) references t2(f1) on delete cascade)engine=innodb; -ERROR HY000: Can't create table `test`.`t1` (errno: 150 "Foreign key constraint is incorrectly formed") -# adding new stored column during alter table copy operation. create table t1(f1 int primary key) engine=innodb; +# Create statement with FK on base column of stored column +create table t2(f1 int not null, f2 int as (f1) stored, +foreign key(f1) references t1(f1) on update cascade)engine=innodb; +ERROR HY000: Function or expression 'f1' cannot be used in the GENERATED ALWAYS AS clause of `f2` +create table t2(f1 int not null, f2 int as (f1) virtual, f3 int as (f2) stored, +foreign key(f1) references t1(f1) on update cascade)engine=innodb; +ERROR HY000: Function or expression 'f2' cannot be used in the GENERATED ALWAYS AS clause of `f3` +# adding new stored column during alter table copy operation. create table t2(f1 int not null, f2 int as (f1) virtual, foreign key(f1) references t1(f1) on update cascade)engine=innodb; alter table t2 add column f3 int as (f1) stored, add column f4 int as (f1) virtual; +ERROR HY000: Function or expression 'f1' cannot be used in the GENERATED ALWAYS AS clause of `f3` show create table t2; Table Create Table t2 CREATE TABLE `t2` ( `f1` int(11) NOT NULL, `f2` int(11) GENERATED ALWAYS AS (`f1`) VIRTUAL, - `f3` int(11) GENERATED ALWAYS AS (`f1`) STORED, - `f4` int(11) GENERATED ALWAYS AS (`f1`) VIRTUAL, KEY `f1` (`f1`), CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`f1`) REFERENCES `t1` (`f1`) ON UPDATE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci @@ -21,26 +23,25 @@ drop table t2; # adding foreign key constraint for base columns during alter copy. create table t2(f1 int not null, f2 int as (f1) stored) engine=innodb; alter table t2 add foreign key(f1) references t1(f1) on update cascade, algorithm=copy; +ERROR HY000: Function or expression 'f1' cannot be used in the GENERATED ALWAYS AS clause of `f2` show create table t2; Table Create Table t2 CREATE TABLE `t2` ( `f1` int(11) NOT NULL, - `f2` int(11) GENERATED ALWAYS AS (`f1`) STORED, - KEY `f1` (`f1`), - CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`f1`) REFERENCES `t1` (`f1`) ON UPDATE CASCADE + `f2` int(11) GENERATED ALWAYS AS (`f1`) STORED ) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci drop table t2; # adding foreign key constraint for base columns during online alter. create table t2(f1 int not null, f2 int as (f1) stored) engine=innodb; set foreign_key_checks = 0; alter table t2 add foreign key(f1) references t1(f1) on update cascade, algorithm=inplace; -ERROR 0A000: Cannot add foreign key on the base column of stored column +ERROR HY000: Function or expression 'f1' cannot be used in the GENERATED ALWAYS AS clause of `f2` drop table t2; # adding stored column via online alter. create table t2(f1 int not null, foreign key(f1) references t1(f1) on update cascade)engine=innodb; alter table t2 add column f2 int as (f1) stored, algorithm=inplace; -ERROR 0A000: ALGORITHM=INPLACE is not supported for this operation. Try ALGORITHM=COPY +ERROR HY000: Function or expression 'f1' cannot be used in the GENERATED ALWAYS AS clause of `f2` drop table t2, t1; # # BUG#26731689 FK ON TABLE WITH GENERATED COLS: ASSERTION POS < N_DEF diff --git a/mysql-test/suite/innodb/t/stored_fk.test b/mysql-test/suite/innodb/t/stored_fk.test index b9c7c934555..571ca030d65 100644 --- a/mysql-test/suite/innodb/t/stored_fk.test +++ b/mysql-test/suite/innodb/t/stored_fk.test @@ -1,24 +1,28 @@ --source include/have_innodb.inc +create table t1(f1 int primary key) engine=innodb; + --echo # Create statement with FK on base column of stored column ---error ER_CANT_CREATE_TABLE -create table t1(f1 int, f2 int as(f1) stored, - foreign key(f1) references t2(f1) on delete cascade)engine=innodb; +--error ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED +create table t2(f1 int not null, f2 int as (f1) stored, + foreign key(f1) references t1(f1) on update cascade)engine=innodb; + +--error ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED +create table t2(f1 int not null, f2 int as (f1) virtual, f3 int as (f2) stored, + foreign key(f1) references t1(f1) on update cascade)engine=innodb; --echo # adding new stored column during alter table copy operation. -create table t1(f1 int primary key) engine=innodb; create table t2(f1 int not null, f2 int as (f1) virtual, foreign key(f1) references t1(f1) on update cascade)engine=innodb; -# MySQL 5.7 would refuse this -#--error ER_ERROR_ON_RENAME +--error ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED alter table t2 add column f3 int as (f1) stored, add column f4 int as (f1) virtual; show create table t2; drop table t2; --echo # adding foreign key constraint for base columns during alter copy. create table t2(f1 int not null, f2 int as (f1) stored) engine=innodb; -# MySQL 5.7 would refuse this +--error ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED alter table t2 add foreign key(f1) references t1(f1) on update cascade, algorithm=copy; show create table t2; drop table t2; @@ -26,14 +30,14 @@ drop table t2; --echo # adding foreign key constraint for base columns during online alter. create table t2(f1 int not null, f2 int as (f1) stored) engine=innodb; set foreign_key_checks = 0; ---error 138 +--error ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED alter table t2 add foreign key(f1) references t1(f1) on update cascade, algorithm=inplace; drop table t2; --echo # adding stored column via online alter. create table t2(f1 int not null, foreign key(f1) references t1(f1) on update cascade)engine=innodb; ---error ER_ALTER_OPERATION_NOT_SUPPORTED +--error ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED alter table t2 add column f2 int as (f1) stored, algorithm=inplace; drop table t2, t1; diff --git a/mysql-test/suite/maria/maria3.result b/mysql-test/suite/maria/maria3.result index fcdd08382a0..221f2155a54 100644 --- a/mysql-test/suite/maria/maria3.result +++ b/mysql-test/suite/maria/maria3.result @@ -521,8 +521,6 @@ t1 CREATE TABLE `t1` ( drop table t1; create table t1 (n int not null, c char(1)) engine=aria transactional=1; alter table t1 engine=myisam; -Warnings: -Warning 1478 Table storage engine 'MyISAM' does not support the create option 'TRANSACTIONAL=1' alter table t1 engine=aria; show create table t1; Table Create Table @@ -533,7 +531,7 @@ t1 CREATE TABLE `t1` ( drop table t1; create table t1 (n int not null, c char(1)) engine=myisam transactional=1; Warnings: -Warning 1478 Table storage engine 'MyISAM' does not support the create option 'TRANSACTIONAL=1' +Warning 1911 Unknown option 'transactional' alter table t1 engine=aria; show create table t1; Table Create Table diff --git a/mysql-test/suite/plugins/r/audit_null_debug.result b/mysql-test/suite/plugins/r/audit_null_debug.result index 69a1fa5a866..c916b27f95e 100644 --- a/mysql-test/suite/plugins/r/audit_null_debug.result +++ b/mysql-test/suite/plugins/r/audit_null_debug.result @@ -1,9 +1,4 @@ -set @old_sql_mode= @@sql_mode; -set @@sql_mode= ''; alter table mysql.plugin engine=myisam; -Warnings: -Warning 1478 Table storage engine 'MyISAM' does not support the create option 'TRANSACTIONAL=1' -set @@sql_mode= @old_sql_mode; set @old_dbug=@@debug_dbug; call mtr.add_suppression("Index for table.*mysql.plugin.MYI"); call mtr.add_suppression("Index for table 'plugin' is corrupt; try to repair it"); diff --git a/mysql-test/suite/plugins/t/audit_null_debug.test b/mysql-test/suite/plugins/t/audit_null_debug.test index ed1a59be033..52c50f13b74 100644 --- a/mysql-test/suite/plugins/t/audit_null_debug.test +++ b/mysql-test/suite/plugins/t/audit_null_debug.test @@ -5,10 +5,7 @@ if (!$ADT_NULL_SO) { skip No NULL_AUDIT plugin; } -set @old_sql_mode= @@sql_mode; -set @@sql_mode= ''; alter table mysql.plugin engine=myisam; -set @@sql_mode= @old_sql_mode; set @old_dbug=@@debug_dbug; call mtr.add_suppression("Index for table.*mysql.plugin.MYI"); diff --git a/mysql-test/suite/vcol/r/innodb_virtual_fk.result b/mysql-test/suite/vcol/r/innodb_virtual_fk.result index 58db12583e2..5c0f717642f 100644 --- a/mysql-test/suite/vcol/r/innodb_virtual_fk.result +++ b/mysql-test/suite/vcol/r/innodb_virtual_fk.result @@ -10,3 +10,73 @@ select * from t2; id drop table t2; drop table t1; +# +# End of 10.2 tests +# +# +# MDEV-18114 Foreign Key Constraint actions don't affect Virtual Column +# +create table t1 (id int primary key); +create or replace table t2 (id int, id2 int as (id) virtual, key(id2), foreign key (id) references t1 (id) on update restrict); +create or replace table t2 (id int, id2 int as (id) virtual, key(id2), foreign key (id) references t1 (id) on update no action); +create or replace table t2 (id int, id2 int as (id) virtual, key(id2), foreign key (id) references t1 (id) on delete cascade); +create or replace table t2 (id int, id2 int as (id) virtual, key(id2), foreign key (id) references t1 (id) on update cascade); +create or replace table t2 (id int, id2 int as (id) virtual, key(id2), foreign key (id) references t1 (id) on delete set null); +create or replace table t2 (id int, id2 int as (id) virtual, key(id2), foreign key (id) references t1 (id) on update set null); +create or replace table t2 (id int, id2 int as (id) stored, foreign key (id) references t1 (id) on update restrict); +create or replace table t2 (id int, id2 int as (id) stored, foreign key (id) references t1 (id) on update no action); +create or replace table t2 (id int, id2 int as (id) stored, foreign key (id) references t1 (id) on delete cascade); +create or replace table t2 (id int, id2 int as (id) stored, foreign key (id) references t1 (id) on update cascade); +ERROR HY000: Function or expression 'id' cannot be used in the GENERATED ALWAYS AS clause of `id2` +create or replace table t2 (id int, id2 int as (id) stored, foreign key (id) references t1 (id) on delete set null); +ERROR HY000: Function or expression 'id' cannot be used in the GENERATED ALWAYS AS clause of `id2` +create or replace table t2 (id int, id2 int as (id) stored, foreign key (id) references t1 (id) on update set null); +ERROR HY000: Function or expression 'id' cannot be used in the GENERATED ALWAYS AS clause of `id2` +create or replace table t2 (id int, id2 int as (id) virtual, id3 int as (id2) stored, foreign key (id) references t1 (id) on update restrict); +create or replace table t2 (id int, id2 int as (id) virtual, id3 int as (id2) stored, foreign key (id) references t1 (id) on update no action); +create or replace table t2 (id int, id2 int as (id) virtual, id3 int as (id2) stored, foreign key (id) references t1 (id) on delete cascade); +create or replace table t2 (id int, id2 int as (id) virtual, id3 int as (id2) stored, foreign key (id) references t1 (id) on update cascade); +ERROR HY000: Function or expression 'id2' cannot be used in the GENERATED ALWAYS AS clause of `id3` +create or replace table t2 (id int, id2 int as (id) virtual, id3 int as (id2) stored, foreign key (id) references t1 (id) on delete set null); +ERROR HY000: Function or expression 'id2' cannot be used in the GENERATED ALWAYS AS clause of `id3` +create or replace table t2 (id int, id2 int as (id) virtual, id3 int as (id2) stored, foreign key (id) references t1 (id) on update set null); +ERROR HY000: Function or expression 'id2' cannot be used in the GENERATED ALWAYS AS clause of `id3` +create or replace table t2 (id int, id2 int default (id), foreign key (id) references t1 (id) on update restrict); +create or replace table t2 (id int, id2 int default (id), foreign key (id) references t1 (id) on update no action); +create or replace table t2 (id int, id2 int default (id), foreign key (id) references t1 (id) on delete cascade); +create or replace table t2 (id int, id2 int default (id), foreign key (id) references t1 (id) on update cascade); +create or replace table t2 (id int, id2 int default (id), foreign key (id) references t1 (id) on delete set null); +create or replace table t2 (id int, id2 int default (id), foreign key (id) references t1 (id) on update set null); +create or replace table t2 (id int, id2 int check (id), foreign key (id) references t1 (id) on update restrict); +create or replace table t2 (id int, id2 int check (id), foreign key (id) references t1 (id) on update no action); +create or replace table t2 (id int, id2 int check (id), foreign key (id) references t1 (id) on delete cascade); +create or replace table t2 (id int, id2 int check (id), foreign key (id) references t1 (id) on update cascade); +ERROR HY000: Function or expression 'id' cannot be used in the CHECK clause of `id2` +create or replace table t2 (id int, id2 int check (id), foreign key (id) references t1 (id) on delete set null); +ERROR HY000: Function or expression 'id' cannot be used in the CHECK clause of `id2` +create or replace table t2 (id int, id2 int check (id), foreign key (id) references t1 (id) on update set null); +ERROR HY000: Function or expression 'id' cannot be used in the CHECK clause of `id2` +create or replace table t2 (id int, id2 int, check (id), foreign key (id) references t1 (id) on update restrict); +create or replace table t2 (id int, id2 int, check (id), foreign key (id) references t1 (id) on update no action); +create or replace table t2 (id int, id2 int, check (id), foreign key (id) references t1 (id) on delete cascade); +create or replace table t2 (id int, id2 int, check (id), foreign key (id) references t1 (id) on update cascade); +ERROR HY000: Function or expression 'id' cannot be used in the CHECK clause of `CONSTRAINT_1` +create or replace table t2 (id int, id2 int, check (id), foreign key (id) references t1 (id) on delete set null); +ERROR HY000: Function or expression 'id' cannot be used in the CHECK clause of `CONSTRAINT_1` +create or replace table t2 (id int, id2 int, check (id), foreign key (id) references t1 (id) on update set null); +ERROR HY000: Function or expression 'id' cannot be used in the CHECK clause of `CONSTRAINT_1` +create or replace table t2 (id int, id2 int as (id) virtual, check (id2), foreign key (id) references t1 (id) on update restrict); +create or replace table t2 (id int, id2 int as (id) virtual, check (id2), foreign key (id) references t1 (id) on update no action); +create or replace table t2 (id int, id2 int as (id) virtual, check (id2), foreign key (id) references t1 (id) on delete cascade); +create or replace table t2 (id int, id2 int as (id) virtual, check (id2), foreign key (id) references t1 (id) on update cascade); +ERROR HY000: Function or expression 'id2' cannot be used in the CHECK clause of `CONSTRAINT_1` +create or replace table t2 (id int, id2 int as (id) virtual, check (id2), foreign key (id) references t1 (id) on delete set null); +ERROR HY000: Function or expression 'id2' cannot be used in the CHECK clause of `CONSTRAINT_1` +create or replace table t2 (id int, id2 int as (id) virtual, check (id2), foreign key (id) references t1 (id) on update set null); +ERROR HY000: Function or expression 'id2' cannot be used in the CHECK clause of `CONSTRAINT_1` +drop table if exists t2, t1; +Warnings: +Note 1051 Unknown table 'test.t2' +# +# End of 10.5 tests +# diff --git a/mysql-test/suite/vcol/r/vcol_syntax.result b/mysql-test/suite/vcol/r/vcol_syntax.result index f1a850e8f7c..144d4ab335d 100644 --- a/mysql-test/suite/vcol/r/vcol_syntax.result +++ b/mysql-test/suite/vcol/r/vcol_syntax.result @@ -54,22 +54,22 @@ set session sql_mode=@OLD_SQL_MODE; # create table t2 (x int); create table t1 (x int, y int generated always as (t2.x)); -ERROR 42S22: Unknown column '`t2`.`x`' in 'GENERATED ALWAYS' +ERROR HY000: Function or expression 't2.x' cannot be used in the GENERATED ALWAYS AS clause of `y` create table t1 (x int, y int check (y > t2.x)); -ERROR 42S22: Unknown column '`t2`.`x`' in 'CHECK' +ERROR HY000: Function or expression 't2.x' cannot be used in the CHECK clause of `y` create table t1 (x int, y int default t2.x); -ERROR 42S22: Unknown column '`t2`.`x`' in 'DEFAULT' +ERROR HY000: Function or expression 't2.x' cannot be used in the DEFAULT clause of `y` create table t1 (x int, check (t2.x > 0)); -ERROR 42S22: Unknown column '`t2`.`x`' in 'CHECK' +ERROR HY000: Function or expression 't2.x' cannot be used in the CHECK clause of `CONSTRAINT_1` create table t1 (x int); alter table t1 add column y int generated always as (t2.x); -ERROR 42S22: Unknown column '`t2`.`x`' in 'GENERATED ALWAYS' +ERROR HY000: Function or expression 't2.x' cannot be used in the GENERATED ALWAYS AS clause of `y` alter table t1 add column y int check (z > t2.x); -ERROR 42S22: Unknown column '`t2`.`x`' in 'CHECK' +ERROR HY000: Function or expression 't2.x' cannot be used in the CHECK clause of `y` alter table t1 add column y int default t2.x; -ERROR 42S22: Unknown column '`t2`.`x`' in 'DEFAULT' +ERROR HY000: Function or expression 't2.x' cannot be used in the DEFAULT clause of `y` alter table t1 add constraint check (t2.x > 0); -ERROR 42S22: Unknown column '`t2`.`x`' in 'CHECK' +ERROR HY000: Function or expression 't2.x' cannot be used in the CHECK clause of `CONSTRAINT_1` create or replace table t1 (x int, y int generated always as (t1.x)); create or replace table t1 (x int, y int check (y > t1.x)); create or replace table t1 (x int, y int default t1.x); @@ -80,13 +80,13 @@ create or replace table t1 (x int, y int default test.t1.x); create or replace table t1 (x int, check (test.t1.x > 0)); drop tables t1, t2; create table t1 (x int, y int generated always as (test2.t1.x)); -ERROR 42S22: Unknown column '`test2`.`t1`.`x`' in 'GENERATED ALWAYS' +ERROR HY000: Function or expression 'test2.t1.x' cannot be used in the GENERATED ALWAYS AS clause of `y` create table t1 (x int, y int check (y > test2.t1.x)); -ERROR 42S22: Unknown column '`test2`.`t1`.`x`' in 'CHECK' +ERROR HY000: Function or expression 'test2.t1.x' cannot be used in the CHECK clause of `y` create table t1 (x int, y int default test2.t1.x); -ERROR 42S22: Unknown column '`test2`.`t1`.`x`' in 'DEFAULT' +ERROR HY000: Function or expression 'test2.t1.x' cannot be used in the DEFAULT clause of `y` create table t1 (x int, check (test2.t1.x > 0)); -ERROR 42S22: Unknown column '`test2`.`t1`.`x`' in 'CHECK' +ERROR HY000: Function or expression 'test2.t1.x' cannot be used in the CHECK clause of `CONSTRAINT_1` # # MDEV-25672 table alias from previous statement interferes later commands # diff --git a/mysql-test/suite/vcol/t/innodb_virtual_fk.test b/mysql-test/suite/vcol/t/innodb_virtual_fk.test index c364adaa613..ed1d9c6c0cf 100644 --- a/mysql-test/suite/vcol/t/innodb_virtual_fk.test +++ b/mysql-test/suite/vcol/t/innodb_virtual_fk.test @@ -14,3 +14,92 @@ select * from t1; select * from t2; drop table t2; drop table t1; + +--echo # +--echo # End of 10.2 tests +--echo # + +--echo # +--echo # MDEV-18114 Foreign Key Constraint actions don't affect Virtual Column +--echo # +create table t1 (id int primary key); + +# note that RESTRICT, NO ACTION, and DELETE CASCADE are fine +# because they don't change values of referenced columns + +# virtual indexed +create or replace table t2 (id int, id2 int as (id) virtual, key(id2), foreign key (id) references t1 (id) on update restrict); +create or replace table t2 (id int, id2 int as (id) virtual, key(id2), foreign key (id) references t1 (id) on update no action); +create or replace table t2 (id int, id2 int as (id) virtual, key(id2), foreign key (id) references t1 (id) on delete cascade); +create or replace table t2 (id int, id2 int as (id) virtual, key(id2), foreign key (id) references t1 (id) on update cascade); +create or replace table t2 (id int, id2 int as (id) virtual, key(id2), foreign key (id) references t1 (id) on delete set null); +create or replace table t2 (id int, id2 int as (id) virtual, key(id2), foreign key (id) references t1 (id) on update set null); + +# stored +create or replace table t2 (id int, id2 int as (id) stored, foreign key (id) references t1 (id) on update restrict); +create or replace table t2 (id int, id2 int as (id) stored, foreign key (id) references t1 (id) on update no action); +create or replace table t2 (id int, id2 int as (id) stored, foreign key (id) references t1 (id) on delete cascade); +--error ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED +create or replace table t2 (id int, id2 int as (id) stored, foreign key (id) references t1 (id) on update cascade); +--error ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED +create or replace table t2 (id int, id2 int as (id) stored, foreign key (id) references t1 (id) on delete set null); +--error ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED +create or replace table t2 (id int, id2 int as (id) stored, foreign key (id) references t1 (id) on update set null); + +# stored indirect +create or replace table t2 (id int, id2 int as (id) virtual, id3 int as (id2) stored, foreign key (id) references t1 (id) on update restrict); +create or replace table t2 (id int, id2 int as (id) virtual, id3 int as (id2) stored, foreign key (id) references t1 (id) on update no action); +create or replace table t2 (id int, id2 int as (id) virtual, id3 int as (id2) stored, foreign key (id) references t1 (id) on delete cascade); +--error ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED +create or replace table t2 (id int, id2 int as (id) virtual, id3 int as (id2) stored, foreign key (id) references t1 (id) on update cascade); +--error ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED +create or replace table t2 (id int, id2 int as (id) virtual, id3 int as (id2) stored, foreign key (id) references t1 (id) on delete set null); +--error ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED +create or replace table t2 (id int, id2 int as (id) virtual, id3 int as (id2) stored, foreign key (id) references t1 (id) on update set null); + +# default +create or replace table t2 (id int, id2 int default (id), foreign key (id) references t1 (id) on update restrict); +create or replace table t2 (id int, id2 int default (id), foreign key (id) references t1 (id) on update no action); +create or replace table t2 (id int, id2 int default (id), foreign key (id) references t1 (id) on delete cascade); +create or replace table t2 (id int, id2 int default (id), foreign key (id) references t1 (id) on update cascade); +create or replace table t2 (id int, id2 int default (id), foreign key (id) references t1 (id) on delete set null); +create or replace table t2 (id int, id2 int default (id), foreign key (id) references t1 (id) on update set null); + +# field check +create or replace table t2 (id int, id2 int check (id), foreign key (id) references t1 (id) on update restrict); +create or replace table t2 (id int, id2 int check (id), foreign key (id) references t1 (id) on update no action); +create or replace table t2 (id int, id2 int check (id), foreign key (id) references t1 (id) on delete cascade); +--error ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED +create or replace table t2 (id int, id2 int check (id), foreign key (id) references t1 (id) on update cascade); +--error ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED +create or replace table t2 (id int, id2 int check (id), foreign key (id) references t1 (id) on delete set null); +--error ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED +create or replace table t2 (id int, id2 int check (id), foreign key (id) references t1 (id) on update set null); + +# table check +create or replace table t2 (id int, id2 int, check (id), foreign key (id) references t1 (id) on update restrict); +create or replace table t2 (id int, id2 int, check (id), foreign key (id) references t1 (id) on update no action); +create or replace table t2 (id int, id2 int, check (id), foreign key (id) references t1 (id) on delete cascade); +--error ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED +create or replace table t2 (id int, id2 int, check (id), foreign key (id) references t1 (id) on update cascade); +--error ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED +create or replace table t2 (id int, id2 int, check (id), foreign key (id) references t1 (id) on delete set null); +--error ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED +create or replace table t2 (id int, id2 int, check (id), foreign key (id) references t1 (id) on update set null); + +# table check indirect +create or replace table t2 (id int, id2 int as (id) virtual, check (id2), foreign key (id) references t1 (id) on update restrict); +create or replace table t2 (id int, id2 int as (id) virtual, check (id2), foreign key (id) references t1 (id) on update no action); +create or replace table t2 (id int, id2 int as (id) virtual, check (id2), foreign key (id) references t1 (id) on delete cascade); +--error ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED +create or replace table t2 (id int, id2 int as (id) virtual, check (id2), foreign key (id) references t1 (id) on update cascade); +--error ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED +create or replace table t2 (id int, id2 int as (id) virtual, check (id2), foreign key (id) references t1 (id) on delete set null); +--error ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED +create or replace table t2 (id int, id2 int as (id) virtual, check (id2), foreign key (id) references t1 (id) on update set null); + +drop table if exists t2, t1; + +--echo # +--echo # End of 10.5 tests +--echo # diff --git a/mysql-test/suite/vcol/t/vcol_syntax.test b/mysql-test/suite/vcol/t/vcol_syntax.test index cb741bc6def..da2ad27d37d 100644 --- a/mysql-test/suite/vcol/t/vcol_syntax.test +++ b/mysql-test/suite/vcol/t/vcol_syntax.test @@ -29,23 +29,23 @@ set session sql_mode=@OLD_SQL_MODE; --echo # create table t2 (x int); ---error ER_BAD_FIELD_ERROR +--error ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED create table t1 (x int, y int generated always as (t2.x)); ---error ER_BAD_FIELD_ERROR +--error ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED create table t1 (x int, y int check (y > t2.x)); ---error ER_BAD_FIELD_ERROR +--error ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED create table t1 (x int, y int default t2.x); ---error ER_BAD_FIELD_ERROR +--error ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED create table t1 (x int, check (t2.x > 0)); create table t1 (x int); ---error ER_BAD_FIELD_ERROR +--error ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED alter table t1 add column y int generated always as (t2.x); ---error ER_BAD_FIELD_ERROR +--error ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED alter table t1 add column y int check (z > t2.x); ---error ER_BAD_FIELD_ERROR +--error ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED alter table t1 add column y int default t2.x; ---error ER_BAD_FIELD_ERROR +--error ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED alter table t1 add constraint check (t2.x > 0); create or replace table t1 (x int, y int generated always as (t1.x)); @@ -60,13 +60,13 @@ create or replace table t1 (x int, check (test.t1.x > 0)); drop tables t1, t2; ---error ER_BAD_FIELD_ERROR +--error ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED create table t1 (x int, y int generated always as (test2.t1.x)); ---error ER_BAD_FIELD_ERROR +--error ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED create table t1 (x int, y int check (y > test2.t1.x)); ---error ER_BAD_FIELD_ERROR +--error ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED create table t1 (x int, y int default test2.t1.x); ---error ER_BAD_FIELD_ERROR +--error ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED create table t1 (x int, check (test2.t1.x > 0)); --echo # diff --git a/sql/field.h b/sql/field.h index fd7336afd2c..9534cfabeed 100644 --- a/sql/field.h +++ b/sql/field.h @@ -5235,7 +5235,7 @@ class Column_definition: public Sql_alloc, const Type_handler *field_type() const; // Prevent using this Compression_method *compression_method_ptr; public: - LEX_CSTRING field_name; + Lex_ident field_name; LEX_CSTRING comment; // Comment for field enum enum_column_versioning { diff --git a/sql/handler.cc b/sql/handler.cc index 17e0144d827..bae38a670b0 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -110,7 +110,7 @@ static handlerton *installed_htons[128]; #define BITMAP_STACKBUF_SIZE (128/8) KEY_CREATE_INFO default_key_create_info= -{ HA_KEY_ALG_UNDEF, 0, 0, {NullS, 0}, {NullS, 0}, true, false }; +{ HA_KEY_ALG_UNDEF, 0, 0, {NullS, 0}, {NullS, 0}, false }; /* number of entries in handlertons[] */ ulong total_ha= 0; diff --git a/sql/handler.h b/sql/handler.h index b25f38212d1..0296d30213f 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -2702,12 +2702,6 @@ typedef struct st_key_create_information uint flags; /* HA_USE.. flags */ LEX_CSTRING parser_name; LEX_CSTRING comment; - /** - A flag to determine if we will check for duplicate indexes. - This typically means that the key information was specified - directly by the user (set by the parser). - */ - bool check_for_duplicate_indexes; bool is_ignored; } KEY_CREATE_INFO; @@ -3717,7 +3711,7 @@ public: - How things are tracked in trx and in add_changed_table(). - If we can combine several statements under one commit in the binary log. */ - bool has_transactions() + bool has_transactions() const { return ((ha_table_flags() & (HA_NO_TRANSACTIONS | HA_PERSISTENT_TABLE)) == 0); @@ -3728,24 +3722,33 @@ public: we don't have to write failed statements to the log as they can be rolled back. */ - bool has_transactions_and_rollback() + bool has_transactions_and_rollback() const { return has_transactions() && has_rollback(); } /* True if the underlaying table support transactions and rollback */ - bool has_transaction_manager() + bool has_transaction_manager() const { return ((ha_table_flags() & HA_NO_TRANSACTIONS) == 0 && has_rollback()); } + /* + True if the underlaying table support TRANSACTIONAL table option + */ + bool has_transactional_option() const + { + extern handlerton *maria_hton; + return partition_ht() == maria_hton || has_transaction_manager(); + } + /* True if table has rollback. Used to check if an update on the table can be killed fast. */ - bool has_rollback() + bool has_rollback() const { return ((ht->flags & HTON_NO_ROLLBACK) == 0); } diff --git a/sql/item.cc b/sql/item.cc index c10eb877179..ce1ba00bd5b 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -1521,7 +1521,7 @@ int Item::save_in_field_no_warnings(Field *field, bool no_conversions) #ifndef DBUG_OFF static inline -void mark_unsupported_func(const char *where, const char *processor_name) +void dbug_mark_unsupported_func(const char *where, const char *processor_name) { char buff[64]; my_snprintf(buff, sizeof(buff), "%s::%s", where ? where: "", processor_name); @@ -1531,7 +1531,7 @@ void mark_unsupported_func(const char *where, const char *processor_name) DBUG_VOID_RETURN; } #else -#define mark_unsupported_func(X,Y) {} +#define dbug_mark_unsupported_func(X,Y) {} #endif bool mark_unsupported_function(const char *where, void *store, uint result) @@ -1539,7 +1539,7 @@ bool mark_unsupported_function(const char *where, void *store, uint result) Item::vcol_func_processor_result *res= (Item::vcol_func_processor_result*) store; uint old_errors= res->errors; - mark_unsupported_func(where, "check_vcol_func_processor"); + dbug_mark_unsupported_func(where, "check_vcol_func_processor"); res->errors|= result; /* Store type of expression */ /* Store the name to the highest violation (normally VCOL_IMPOSSIBLE) */ if (result > old_errors) @@ -1560,33 +1560,19 @@ bool mark_unsupported_function(const char *w1, const char *w2, bool Item_field::check_vcol_func_processor(void *arg) { + uint r= VCOL_FIELD_REF; context= 0; vcol_func_processor_result *res= (vcol_func_processor_result *) arg; if (res && res->alter_info) + r|= res->alter_info->check_vcol_field(this); + else if (field) { - for (Key &k: res->alter_info->key_list) - { - if (k.type != Key::FOREIGN_KEY) - continue; - Foreign_key *fk= (Foreign_key*) &k; - if (fk->update_opt != FK_OPTION_CASCADE) - continue; - for (Key_part_spec& kp: fk->columns) - { - if (!lex_string_cmp(system_charset_info, &kp.field_name, &field_name)) - { - return mark_unsupported_function(field_name.str, arg, VCOL_IMPOSSIBLE); - } - } - } + if (field->unireg_check == Field::NEXT_NUMBER) + r|= VCOL_AUTO_INC; + if (field->vcol_info && + field->vcol_info->flags & (VCOL_NOT_STRICTLY_DETERMINISTIC | VCOL_AUTO_INC)) + r|= VCOL_NON_DETERMINISTIC; } - - uint r= VCOL_FIELD_REF; - if (field && field->unireg_check == Field::NEXT_NUMBER) - r|= VCOL_AUTO_INC; - if (field && field->vcol_info && - field->vcol_info->flags & (VCOL_NOT_STRICTLY_DETERMINISTIC | VCOL_AUTO_INC)) - r|= VCOL_NON_DETERMINISTIC; return mark_unsupported_function(field_name.str, arg, r); } diff --git a/sql/item.h b/sql/item.h index 486ca098dda..0f59b38cd38 100644 --- a/sql/item.h +++ b/sql/item.h @@ -2207,15 +2207,6 @@ public: return 0; } - /** - Check db/table_name if they defined in item and match arg values - - @param arg Pointer to Check_table_name_prm structure - - @retval true Match failed - @retval false Match succeeded - */ - virtual bool check_table_name_processor(void *arg) { return false; } /* TRUE if the expression depends only on the table indicated by tab_map or can be converted to such an exression using equalities. @@ -2416,15 +2407,6 @@ public: bool collect; }; - struct Check_table_name_prm - { - LEX_CSTRING db; - LEX_CSTRING table_name; - String field; - Check_table_name_prm(LEX_CSTRING _db, LEX_CSTRING _table_name) : - db(_db), table_name(_table_name) {} - }; - /* For SP local variable returns pointer to Item representing its current value and pointer to current Item otherwise. @@ -3480,17 +3462,17 @@ protected: updated during fix_fields() to values from Field object and life-time of those is shorter than life-time of Item_field. */ - LEX_CSTRING orig_db_name; - LEX_CSTRING orig_table_name; - LEX_CSTRING orig_field_name; + Lex_table_name orig_db_name; + Lex_table_name orig_table_name; + Lex_ident orig_field_name; void undeclared_spvar_error() const; public: Name_resolution_context *context; - LEX_CSTRING db_name; - LEX_CSTRING table_name; - LEX_CSTRING field_name; + Lex_table_name db_name; + Lex_table_name table_name; + Lex_ident field_name; /* Cached pointer to table which contains this field, used for the same reason by prep. stmt. too in case then we have not-fully qualified field. @@ -3741,24 +3723,6 @@ public: } return 0; } - bool check_table_name_processor(void *arg) override - { - Check_table_name_prm &p= *static_cast(arg); - if (!field && p.table_name.length && table_name.length) - { - DBUG_ASSERT(p.db.length); - if ((db_name.length && - my_strcasecmp(table_alias_charset, p.db.str, db_name.str)) || - my_strcasecmp(table_alias_charset, p.table_name.str, table_name.str)) - { - print(&p.field, (enum_query_type) (QT_ITEM_ORIGINAL_FUNC_NULLIF | - QT_NO_DATA_EXPANSION | - QT_TO_SYSTEM_CHARSET)); - return true; - } - } - return false; - } void cleanup() override; Item_equal *get_item_equal() override { return item_equal; } void set_item_equal(Item_equal *item_eq) override { item_equal= item_eq; } diff --git a/sql/sql_alter.cc b/sql/sql_alter.cc index bcbf86f1e8f..1ad41f444fd 100644 --- a/sql/sql_alter.cc +++ b/sql/sql_alter.cc @@ -253,6 +253,43 @@ Alter_info::algorithm(const THD *thd) const } +uint Alter_info::check_vcol_field(Item_field *item) const +{ + if (!item->field && + ((item->db_name.length && !db.streq(item->db_name)) || + (item->table_name.length && !table_name.streq(item->table_name)))) + { + char *ptr= (char*)current_thd->alloc(item->db_name.length + + item->table_name.length + + item->field_name.length + 3); + strxmov(ptr, safe_str(item->db_name.str), item->db_name.length ? "." : "", + item->table_name.str, ".", item->field_name.str, NullS); + item->field_name.str= ptr; + return VCOL_IMPOSSIBLE; + } + for (Key &k: key_list) + { + if (k.type != Key::FOREIGN_KEY) + continue; + Foreign_key *fk= (Foreign_key*) &k; + if (fk->update_opt < FK_OPTION_CASCADE && + fk->delete_opt < FK_OPTION_SET_NULL) + continue; + for (Key_part_spec& kp: fk->columns) + { + if (item->field_name.streq(kp.field_name)) + return VCOL_NON_DETERMINISTIC; + } + } + for (Create_field &cf: create_list) + { + if (item->field_name.streq(cf.field_name)) + return cf.vcol_info ? cf.vcol_info->flags : 0; + } + return 0; +} + + Alter_table_ctx::Alter_table_ctx() : db(null_clex_str), table_name(null_clex_str), alias(null_clex_str), new_db(null_clex_str), new_name(null_clex_str), new_alias(null_clex_str) diff --git a/sql/sql_alter.h b/sql/sql_alter.h index d0ac4ab27f5..4605a6d415a 100644 --- a/sql/sql_alter.h +++ b/sql/sql_alter.h @@ -85,6 +85,7 @@ public: ALTER_TABLE_LOCK_EXCLUSIVE }; + Lex_table_name db, table_name; // Columns and keys to be dropped. List drop_list; @@ -234,6 +235,8 @@ public: */ enum_alter_table_algorithm algorithm(const THD *thd) const; + uint check_vcol_field(Item_field *f) const; + private: Alter_info &operator=(const Alter_info &rhs); // not implemented Alter_info(const Alter_info &rhs); // not implemented diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 63b8ee86152..8e2f34ac53d 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -177,7 +177,7 @@ Key::Key(const Key &rhs, MEM_ROOT *mem_root) name(rhs.name), option_list(rhs.option_list), generated(rhs.generated), invisible(false), - without_overlaps(rhs.without_overlaps), period(rhs.period) + without_overlaps(rhs.without_overlaps), old(rhs.old), period(rhs.period) { list_copy_and_replace_each_value(columns, mem_root); } @@ -213,11 +213,11 @@ Foreign_key::Foreign_key(const Foreign_key &rhs, MEM_ROOT *mem_root) We only compare field names RETURN - 0 Generated key is a prefix of other key - 1 Not equal + true Generated key is a prefix of other key + false Not a prefix */ -bool foreign_key_prefix(Key *a, Key *b) +bool is_foreign_key_prefix(Key *a, Key *b) { /* Ensure that 'a' is the generated key */ if (a->generated) @@ -228,13 +228,13 @@ bool foreign_key_prefix(Key *a, Key *b) else { if (!b->generated) - return TRUE; // No foreign key + return false; // No foreign key swap_variables(Key*, a, b); // Put generated key in 'a' } /* Test if 'a' is a prefix of 'b' */ if (a->columns.elements > b->columns.elements) - return TRUE; // Can't be prefix + return false; // Can't be prefix List_iterator col_it1(a->columns); List_iterator col_it2(b->columns); @@ -254,17 +254,17 @@ bool foreign_key_prefix(Key *a, Key *b) } } if (!found) - return TRUE; // Error + return false; // Error } - return FALSE; // Is prefix + return true; // Is prefix #else while ((col1= col_it1++)) { col2= col_it2++; if (!(*col1 == *col2)) - return TRUE; + return false; } - return FALSE; // Is prefix + return true; // Is prefix #endif } @@ -285,6 +285,8 @@ bool Foreign_key::validate(List &table_fields) List_iterator cols(columns); List_iterator it(table_fields); DBUG_ENTER("Foreign_key::validate"); + if (old) + DBUG_RETURN(FALSE); // must be good while ((column= cols++)) { it.rewind(); diff --git a/sql/sql_class.h b/sql/sql_class.h index 4e1c924d7e1..4da74a95a9b 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -318,7 +318,7 @@ typedef struct st_copy_info { class Key_part_spec :public Sql_alloc { public: - LEX_CSTRING field_name; + Lex_ident field_name; uint length; bool generated; Key_part_spec(const LEX_CSTRING *name, uint len, bool gen= false) @@ -453,6 +453,7 @@ public: bool generated; bool invisible; bool without_overlaps; + bool old; Lex_ident period; Key(enum Keytype type_par, const LEX_CSTRING *name_arg, @@ -460,7 +461,7 @@ public: :DDL_options(ddl_options), type(type_par), key_create_info(default_key_create_info), name(*name_arg), option_list(NULL), generated(generated_arg), - invisible(false), without_overlaps(false) + invisible(false), without_overlaps(false), old(false) { key_create_info.algorithm= algorithm_arg; } @@ -471,12 +472,12 @@ public: :DDL_options(ddl_options), type(type_par), key_create_info(*key_info_arg), columns(*cols), name(*name_arg), option_list(create_opt), generated(generated_arg), - invisible(false), without_overlaps(false) + invisible(false), without_overlaps(false), old(false) {} Key(const Key &rhs, MEM_ROOT *mem_root); virtual ~Key() = default; /* Equality comparison of keys (ignoring name) */ - friend bool foreign_key_prefix(Key *a, Key *b); + friend bool is_foreign_key_prefix(Key *a, Key *b); /** Used to make a clone of this object for ALTER/CREATE TABLE @sa comment for Key_part_spec::clone @@ -509,9 +510,7 @@ public: ref_db(*ref_db_arg), ref_table(*ref_table_arg), ref_columns(*ref_cols), delete_opt(delete_opt_arg), update_opt(update_opt_arg), match_opt(match_opt_arg) - { - // We don't check for duplicate FKs. - key_create_info.check_for_duplicate_indexes= false; + { } Foreign_key(const Foreign_key &rhs, MEM_ROOT *mem_root); /** diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index de1d8b45701..3ca8fc3303b 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -4537,8 +4537,6 @@ TABLE *select_create::create_table_from_items(THD *thd, List *items, */ if (!mysql_create_table_no_lock(thd, &ddl_log_state_create, &ddl_log_state_rm, - &create_table->db, - &create_table->table_name, create_info, alter_info, NULL, select_field_count, create_table)) { diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc index adb1ad391cf..313142df472 100644 --- a/sql/sql_partition.cc +++ b/sql/sql_partition.cc @@ -6033,7 +6033,8 @@ static bool mysql_change_partitions(ALTER_PARTITION_PARAM_TYPE *lpt) THD *thd= lpt->thd; DBUG_ENTER("mysql_change_partitions"); - build_table_filename(path, sizeof(path) - 1, lpt->db.str, lpt->table_name.str, "", 0); + build_table_filename(path, sizeof(path) - 1, lpt->alter_info->db.str, + lpt->alter_info->table_name.str, "", 0); if(mysql_trans_prepare_alter_copy_data(thd)) DBUG_RETURN(TRUE); @@ -6081,7 +6082,8 @@ static bool mysql_rename_partitions(ALTER_PARTITION_PARAM_TYPE *lpt) int error; DBUG_ENTER("mysql_rename_partitions"); - build_table_filename(path, sizeof(path) - 1, lpt->db.str, lpt->table_name.str, "", 0); + build_table_filename(path, sizeof(path) - 1, lpt->alter_info->db.str, + lpt->alter_info->table_name.str, "", 0); if (unlikely((error= lpt->table->file->ha_rename_partitions(path)))) { if (error != 1) @@ -6125,7 +6127,8 @@ static bool mysql_drop_partitions(ALTER_PARTITION_PARAM_TYPE *lpt) lpt->table->s->table_name.str, MDL_EXCLUSIVE)); - build_table_filename(path, sizeof(path) - 1, lpt->db.str, lpt->table_name.str, "", 0); + build_table_filename(path, sizeof(path) - 1, lpt->alter_info->db.str, + lpt->alter_info->table_name.str, "", 0); if ((error= lpt->table->file->ha_drop_partitions(path))) { lpt->table->file->print_error(error, MYF(0)); @@ -6518,7 +6521,8 @@ static bool write_log_rename_frm(ALTER_PARTITION_PARAM_TYPE *lpt) DBUG_ENTER("write_log_rename_frm"); part_info->first_log_entry= NULL; - build_table_filename(path, sizeof(path) - 1, lpt->db.str, lpt->table_name.str, "", 0); + build_table_filename(path, sizeof(path) - 1, lpt->alter_info->db.str, + lpt->alter_info->table_name.str, "", 0); build_table_shadow_filename(shadow_path, sizeof(shadow_path) - 1, lpt); mysql_mutex_lock(&LOCK_gdl); if (write_log_replace_delete_frm(lpt, 0UL, shadow_path, path, TRUE)) @@ -6569,7 +6573,8 @@ static bool write_log_drop_partition(ALTER_PARTITION_PARAM_TYPE *lpt) DBUG_ENTER("write_log_drop_partition"); part_info->first_log_entry= NULL; - build_table_filename(path, sizeof(path) - 1, lpt->db.str, lpt->table_name.str, "", 0); + build_table_filename(path, sizeof(path) - 1, lpt->alter_info->db.str, + lpt->alter_info->table_name.str, "", 0); build_table_shadow_filename(tmp_path, sizeof(tmp_path) - 1, lpt); mysql_mutex_lock(&LOCK_gdl); if (write_log_dropped_partitions(lpt, &next_entry, (const char*)path, @@ -6627,7 +6632,8 @@ static bool write_log_add_change_partition(ALTER_PARTITION_PARAM_TYPE *lpt) DBUG_ASSERT(old_first_log_entry); DBUG_ENTER("write_log_add_change_partition"); - build_table_filename(path, sizeof(path) - 1, lpt->db.str, lpt->table_name.str, "", 0); + build_table_filename(path, sizeof(path) - 1, lpt->alter_info->db.str, + lpt->alter_info->table_name.str, "", 0); build_table_shadow_filename(tmp_path, sizeof(tmp_path) - 1, lpt); mysql_mutex_lock(&LOCK_gdl); @@ -6694,7 +6700,8 @@ static bool write_log_final_change_partition(ALTER_PARTITION_PARAM_TYPE *lpt) Replace the revert operations with forced retry operations. */ part_info->first_log_entry= NULL; - build_table_filename(path, sizeof(path) - 1, lpt->db.str, lpt->table_name.str, "", 0); + build_table_filename(path, sizeof(path) - 1, lpt->alter_info->db.str, + lpt->alter_info->table_name.str, "", 0); build_table_shadow_filename(shadow_path, sizeof(shadow_path) - 1, lpt); mysql_mutex_lock(&LOCK_gdl); if (write_log_changed_partitions(lpt, &next_entry, (const char*)path)) @@ -6880,8 +6887,8 @@ static void handle_alter_part_error(ALTER_PARTITION_PARAM_TYPE *lpt, Better to do that here, than leave the cleaning up to others. Acquire EXCLUSIVE mdl lock if not already acquired. */ - if (!thd->mdl_context.is_lock_owner(MDL_key::TABLE, lpt->db.str, - lpt->table_name.str, + if (!thd->mdl_context.is_lock_owner(MDL_key::TABLE, lpt->alter_info->db.str, + lpt->alter_info->table_name.str, MDL_EXCLUSIVE) && wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN)) { @@ -7061,13 +7068,13 @@ bool log_partition_alter_to_ddl_log(ALTER_PARTITION_PARAM_TYPE *lpt) ddl_log.query= { C_STRING_WITH_LEN("ALTER") }; ddl_log.org_storage_engine_name= old_engine_lex; ddl_log.org_partitioned= true; - ddl_log.org_database= lpt->db; - ddl_log.org_table= lpt->table_name; + ddl_log.org_database= lpt->alter_info->db; + ddl_log.org_table= lpt->alter_info->table_name; ddl_log.org_table_id= lpt->org_tabledef_version; ddl_log.new_storage_engine_name= old_engine_lex; ddl_log.new_partitioned= true; - ddl_log.new_database= lpt->db; - ddl_log.new_table= lpt->table_name; + ddl_log.new_database= lpt->alter_info->db; + ddl_log.new_table= lpt->alter_info->table_name; ddl_log.new_table_id= lpt->create_info->tabledef_version; backup_log_ddl(&ddl_log); // This sets backup_log_error on failure return 0; @@ -7099,14 +7106,11 @@ bool log_partition_alter_to_ddl_log(ALTER_PARTITION_PARAM_TYPE *lpt) uint fast_alter_partition_table(THD *thd, TABLE *table, Alter_info *alter_info, HA_CREATE_INFO *create_info, - TABLE_LIST *table_list, - const LEX_CSTRING *db, - const LEX_CSTRING *table_name) + TABLE_LIST *table_list) { /* Set-up struct used to write frm files */ partition_info *part_info; - ALTER_PARTITION_PARAM_TYPE lpt_obj; - ALTER_PARTITION_PARAM_TYPE *lpt= &lpt_obj; + ALTER_PARTITION_PARAM_TYPE lpt_obj, *lpt= &lpt_obj; bool action_completed= FALSE; bool frm_install= FALSE; MDL_ticket *mdl_ticket= table->mdl_ticket; @@ -7125,8 +7129,6 @@ uint fast_alter_partition_table(THD *thd, TABLE *table, lpt->table= table; lpt->key_info_buffer= 0; lpt->key_count= 0; - lpt->db= *db; - lpt->table_name= *table_name; lpt->org_tabledef_version= table->s->tabledef_version; lpt->copied= 0; lpt->deleted= 0; diff --git a/sql/sql_partition.h b/sql/sql_partition.h index 57e6d0600ed..a8d52b2b85b 100644 --- a/sql/sql_partition.h +++ b/sql/sql_partition.h @@ -57,8 +57,6 @@ typedef struct st_lock_param_type Alter_info *alter_info; TABLE *table; KEY *key_info_buffer; - LEX_CSTRING db; - LEX_CSTRING table_name; LEX_CUSTRING org_tabledef_version; uchar *pack_frm_data; uint key_count; @@ -256,9 +254,7 @@ typedef int (*get_partitions_in_range_iter)(partition_info *part_info, uint fast_alter_partition_table(THD *thd, TABLE *table, Alter_info *alter_info, HA_CREATE_INFO *create_info, - TABLE_LIST *table_list, - const LEX_CSTRING *db, - const LEX_CSTRING *table_name); + TABLE_LIST *table_list); bool set_part_state(Alter_info *alter_info, partition_info *tab_part_info, enum partition_state part_state); uint prep_alter_part_table(THD *thd, TABLE *table, Alter_info *alter_info, diff --git a/sql/sql_show.cc b/sql/sql_show.cc index d10cea97f2e..e90c52ceabd 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -1977,8 +1977,13 @@ static void add_table_options(THD *thd, TABLE *table, } if (share->transactional != HA_CHOICE_UNDEF) { + bool do_comment= !table->file->has_transactional_option() && check_options; + if (do_comment) + packet->append(STRING_WITH_LEN(" /*")); packet->append(STRING_WITH_LEN(" TRANSACTIONAL=")); packet->append(ha_choice_values[(uint) share->transactional]); + if (do_comment) + packet->append(STRING_WITH_LEN(" */")); } if (share->table_type == TABLE_TYPE_SEQUENCE) packet->append(STRING_WITH_LEN(" SEQUENCE=1")); diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 3924f72fb2a..f7588890a4d 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -82,12 +82,9 @@ static int copy_data_between_tables(THD *, TABLE *,TABLE *, ha_rows *, ha_rows *, Alter_info::enum_enable_or_disable, Alter_table_ctx *); -static int append_system_key_parts(THD *thd, HA_CREATE_INFO *create_info, - Key *key); +static int append_system_key_parts(THD *, HA_CREATE_INFO *, Key *); static int mysql_prepare_create_table(THD *, HA_CREATE_INFO *, Alter_info *, - uint *, handler *, KEY **, uint *, int, - const LEX_CSTRING db, - const LEX_CSTRING table_name); + uint *, handler *, KEY **, uint *, int); static uint blob_length_by_type(enum_field_types type); static bool fix_constraints_names(THD *, List *, const HA_CREATE_INFO *); @@ -401,8 +398,7 @@ uint filename_to_tablename(const char *from, char *to, size_t to_length, system_charset_info, to, to_length, &errors); if (unlikely(errors)) // Old 5.0 name { - res= (strxnmov(to, to_length, MYSQL50_TABLE_NAME_PREFIX, from, NullS) - - to); + res= strxnmov(to, to_length, MYSQL50_TABLE_NAME_PREFIX, from, NullS) - to; if (!stay_quiet) sql_print_error("Invalid (old?) table or database name '%s'", from); } @@ -673,9 +669,9 @@ uint build_table_shadow_filename(char *buff, size_t bufflen, { char tmp_name[FN_REFLEN]; my_snprintf(tmp_name, sizeof (tmp_name), "%s-shadow-%lx-%s", tmp_file_prefix, - (ulong) current_thd->thread_id, lpt->table_name.str); - return build_table_filename(buff, bufflen, lpt->db.str, tmp_name, "", - FN_IS_TMP); + (ulong) current_thd->thread_id, lpt->alter_info->table_name.str); + return build_table_filename(buff, bufflen, lpt->alter_info->db.str, tmp_name, + "", FN_IS_TMP); } @@ -734,7 +730,7 @@ bool mysql_write_frm(ALTER_PARTITION_PARAM_TYPE *lpt, uint flags) if (mysql_prepare_create_table(lpt->thd, lpt->create_info, lpt->alter_info, &lpt->db_options, lpt->table->file, &lpt->key_info_buffer, &lpt->key_count, - C_ALTER_TABLE, lpt->db, lpt->table_name)) + C_ALTER_TABLE)) { DBUG_RETURN(TRUE); } @@ -754,7 +750,7 @@ bool mysql_write_frm(ALTER_PARTITION_PARAM_TYPE *lpt, uint flags) #endif /* Write shadow frm file */ lpt->create_info->table_options= lpt->db_options; - LEX_CUSTRING frm= build_frm_image(lpt->thd, lpt->table_name, + LEX_CUSTRING frm= build_frm_image(lpt->thd, lpt->alter_info->table_name, lpt->create_info, lpt->alter_info->create_list, lpt->key_count, lpt->key_info_buffer, @@ -765,7 +761,8 @@ bool mysql_write_frm(ALTER_PARTITION_PARAM_TYPE *lpt, uint flags) goto end; } - int error= writefile(shadow_frm_name, lpt->db.str, lpt->table_name.str, + int error= writefile(shadow_frm_name, lpt->alter_info->db.str, + lpt->alter_info->table_name.str, lpt->create_info->tmp_table(), frm.str, frm.length); my_free(const_cast(frm.str)); @@ -787,8 +784,8 @@ bool mysql_write_frm(ALTER_PARTITION_PARAM_TYPE *lpt, uint flags) /* Build frm file name */ - build_table_filename(path, sizeof(path) - 1, lpt->db.str, - lpt->table_name.str, "", 0); + build_table_filename(path, sizeof(path) - 1, lpt->alter_info->db.str, + lpt->alter_info->table_name.str, "", 0); strxnmov(frm_name, sizeof(frm_name), path, reg_ext, NullS); /* When we are changing to use new frm file we need to ensure that we @@ -2207,7 +2204,7 @@ static void check_duplicate_key(THD *thd, const Key *key, const KEY *key_info, Check is requested if the key was explicitly created or altered by the user (unless it's a foreign key). */ - if (!key->key_create_info.check_for_duplicate_indexes || key->generated) + if (key->old || key->type == Key::FOREIGN_KEY || key->generated) return; for (const Key &k : *key_list) @@ -2575,8 +2572,7 @@ static int mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info, Alter_info *alter_info, uint *db_options, handler *file, KEY **key_info_buffer, - uint *key_count, int create_table_mode, - const LEX_CSTRING db, const LEX_CSTRING table_name) + uint *key_count, int create_table_mode) { const char *key_name; Create_field *sql_field,*dup_field; @@ -2595,6 +2591,7 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info, const Column_derived_attributes dattr(create_info->default_table_charset); const Column_bulk_alter_attributes battr(create_info->alter_table_convert_to_charset); + const CHARSET_INFO *scs= system_charset_info; DBUG_ENTER("mysql_prepare_create_table"); DBUG_EXECUTE_IF("test_pseudo_invisible",{ @@ -2608,23 +2605,17 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info, new (thd->mem_root)Item_int(thd, 9)); }); DBUG_EXECUTE_IF("test_invisible_index",{ - LEX_CSTRING temp; - temp.str= "invisible"; - temp.length= strlen("invisible"); - mysql_add_invisible_index(thd, &alter_info->key_list - , &temp, Key::MULTIPLE); + LEX_CSTRING temp= { STRING_WITH_LEN("invisible") }; + mysql_add_invisible_index(thd, &alter_info->key_list, &temp, + Key::MULTIPLE); }); - LEX_CSTRING* connect_string = &create_info->connect_string; - if (connect_string->length != 0 && - connect_string->length > CONNECT_STRING_MAXLEN && - (system_charset_info->charpos(connect_string->str, - (connect_string->str + - connect_string->length), - CONNECT_STRING_MAXLEN) - < connect_string->length)) + LEX_CSTRING* connstr = &create_info->connect_string; + if (connstr->length > CONNECT_STRING_MAXLEN && + scs->charpos(connstr->str, connstr->str + connstr->length, + CONNECT_STRING_MAXLEN) < connstr->length) { - my_error(ER_WRONG_STRING_LENGTH, MYF(0), - connect_string->str, "CONNECTION", CONNECT_STRING_MAXLEN); + my_error(ER_WRONG_STRING_LENGTH, MYF(0), connstr->str, "CONNECTION", + CONNECT_STRING_MAXLEN); DBUG_RETURN(TRUE); } @@ -2687,9 +2678,7 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info, /* Check if we have used the same field name before */ for (dup_no=0; (dup_field=it2++) != sql_field; dup_no++) { - if (lex_string_cmp(system_charset_info, - &sql_field->field_name, - &dup_field->field_name) == 0) + if (lex_string_cmp(scs, &sql_field->field_name, &dup_field->field_name) == 0) { /* If this was a CREATE ... SELECT statement, accept a field @@ -2861,15 +2850,13 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info, while ((key2 = key_iterator2++) != key) { /* - foreign_key_prefix(key, key2) returns 0 if key or key2, or both, is - 'generated', and a generated key is a prefix of the other key. - Then we do not need the generated shorter key. + is_foreign_key_prefix(key, key2) returns true if key or key2, or + both, is 'generated', and a generated key is a prefix of the other + key. Then we do not need the generated shorter key. */ - if ((key2->type != Key::FOREIGN_KEY && - key2->name.str != ignore_key && - !foreign_key_prefix(key, key2))) + if (key2->type != Key::FOREIGN_KEY && key2->name.str != ignore_key && + is_foreign_key_prefix(key, key2)) { - /* TODO: issue warning message */ /* mark that the generated key should be ignored */ if (!key2->generated || (key->generated && key->columns.elements < @@ -2890,14 +2877,13 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info, else (*key_count)--; if (key->name.str && !tmp_table && (key->type != Key::PRIMARY) && - !my_strcasecmp(system_charset_info, key->name.str, - primary_key_name.str)) + !my_strcasecmp(scs, key->name.str, primary_key_name.str)) { my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0), key->name.str); DBUG_RETURN(TRUE); } if (key->type == Key::PRIMARY && key->name.str && - my_strcasecmp(system_charset_info, key->name.str, primary_key_name.str) != 0) + my_strcasecmp(scs, key->name.str, primary_key_name.str) != 0) { bool sav_abort_on_warning= thd->abort_on_warning; thd->abort_on_warning= FALSE; /* Don't make an error out of this. */ @@ -2935,9 +2921,7 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info, auto field_name= key->columns.elem(0)->field_name; it.rewind(); while ((sql_field=it++) && - lex_string_cmp(system_charset_info, - &field_name, - &sql_field->field_name)); + lex_string_cmp(scs, &field_name, &sql_field->field_name)); if (sql_field) field_name= sql_field->field_name; key_name=make_unique_key_name(thd, field_name.str, @@ -3110,9 +3094,7 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info, it.rewind(); field=0; while ((sql_field=it++) && - lex_string_cmp(system_charset_info, - &column->field_name, - &sql_field->field_name)) + lex_string_cmp(scs, &column->field_name, &sql_field->field_name)) field++; /* Either field is not present or field visibility is > INVISIBLE_USER @@ -3132,8 +3114,7 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info, } while ((dup_column= cols2++) != column) { - if (!lex_string_cmp(system_charset_info, - &column->field_name, &dup_column->field_name)) + if (!lex_string_cmp(scs, &column->field_name, &dup_column->field_name)) { my_error(ER_DUP_FIELDNAME, MYF(0), column->field_name.str); DBUG_RETURN(TRUE); @@ -3436,8 +3417,7 @@ without_overlaps_err: { for (Key_part_spec& kp2: fk->columns) { - if (!lex_string_cmp(system_charset_info, &kp.field_name, - &kp2.field_name)) + if (!lex_string_cmp(scs, &kp.field_name, &kp2.field_name)) { goto without_overlaps_err; } @@ -3489,7 +3469,6 @@ without_overlaps_err: create_info->null_bits= null_fields; /* Check fields. */ - Item::Check_table_name_prm walk_prm(db, table_name); it.rewind(); while ((sql_field=it++)) { @@ -3547,33 +3526,22 @@ without_overlaps_err: if (create_simple) { - /* - NOTE: we cannot do this in check_vcol_func_processor() as there is already - no table name qualifier in expression. - */ if (sql_field->vcol_info && sql_field->vcol_info->expr && - sql_field->vcol_info->expr->walk(&Item::check_table_name_processor, - false, (void *) &walk_prm)) - { - my_error(ER_BAD_FIELD_ERROR, MYF(0), walk_prm.field.c_ptr(), "GENERATED ALWAYS"); + check_expression(sql_field->vcol_info, &sql_field->field_name, + sql_field->vcol_info->stored_in_db + ? VCOL_GENERATED_STORED : VCOL_GENERATED_VIRTUAL, + alter_info)) DBUG_RETURN(TRUE); - } if (sql_field->default_value && - sql_field->default_value->expr->walk(&Item::check_table_name_processor, - false, (void *) &walk_prm)) - { - my_error(ER_BAD_FIELD_ERROR, MYF(0), walk_prm.field.c_ptr(), "DEFAULT"); + check_expression(sql_field->default_value, &sql_field->field_name, + VCOL_DEFAULT, alter_info)) DBUG_RETURN(TRUE); - } if (sql_field->check_constraint && - sql_field->check_constraint->expr->walk(&Item::check_table_name_processor, - false, (void *) &walk_prm)) - { - my_error(ER_BAD_FIELD_ERROR, MYF(0), walk_prm.field.c_ptr(), "CHECK"); + check_expression(sql_field->check_constraint, &sql_field->field_name, + VCOL_CHECK_FIELD, alter_info)) DBUG_RETURN(TRUE); - } } } @@ -3581,22 +3549,9 @@ without_overlaps_err: create_info->check_constraint_list= &alter_info->check_constraint_list; { List_iterator_fast c_it(alter_info->check_constraint_list); - Virtual_column_info *check; - while ((check= c_it++)) + while (Virtual_column_info *check= c_it++) { - if (create_simple && check->expr->walk(&Item::check_table_name_processor, false, - (void *) &walk_prm)) - { - my_error(ER_BAD_FIELD_ERROR, MYF(0), walk_prm.field.c_ptr(), "CHECK"); - DBUG_RETURN(TRUE); - } - if (!check->name.length || check->automatic_name) - { - if (check_expression(check, &check->name, VCOL_CHECK_TABLE, alter_info)) - DBUG_RETURN(TRUE); - continue; - } - + if (check->name.length && !check->automatic_name) { /* Check that there's no repeating table CHECK constraint names. */ List_iterator_fast @@ -3604,57 +3559,45 @@ without_overlaps_err: const Virtual_column_info *dup_check; while ((dup_check= dup_it++) && dup_check != check) { - if (!lex_string_cmp(system_charset_info, - &check->name, &dup_check->name)) + if (check->name.streq(dup_check->name)) { my_error(ER_DUP_CONSTRAINT_NAME, MYF(0), "CHECK", check->name.str); DBUG_RETURN(TRUE); } } - } - /* Check that there's no repeating key constraint names. */ - List_iterator_fast key_it(alter_info->key_list); - while (const Key *key= key_it++) - { - /* - Not all keys considered to be the CONSTRAINT - Noly Primary Key UNIQUE and Foreign keys. - */ - if (key->type != Key::PRIMARY && key->type != Key::UNIQUE && - key->type != Key::FOREIGN_KEY) - continue; - - if (check->name.length == key->name.length && - my_strcasecmp(system_charset_info, - check->name.str, key->name.str) == 0) + /* Check that there's no repeating key constraint names. */ + List_iterator_fast key_it(alter_info->key_list); + while (const Key *key= key_it++) { - my_error(ER_DUP_CONSTRAINT_NAME, MYF(0), "CHECK", check->name.str); + if (key->type != Key::PRIMARY && key->type != Key::UNIQUE && + key->type != Key::FOREIGN_KEY) + continue; + + if (check->name.length == key->name.length && + my_strcasecmp(scs, check->name.str, key->name.str) == 0) + { + my_error(ER_DUP_CONSTRAINT_NAME, MYF(0), "CHECK", check->name.str); + DBUG_RETURN(TRUE); + } + } + + if (check_string_char_length(&check->name, 0, NAME_CHAR_LEN, scs, 1)) + { + my_error(ER_TOO_LONG_IDENT, MYF(0), check->name.str); DBUG_RETURN(TRUE); } } - - if (check_string_char_length(&check->name, 0, NAME_CHAR_LEN, - system_charset_info, 1)) - { - my_error(ER_TOO_LONG_IDENT, MYF(0), check->name.str); - DBUG_RETURN(TRUE); - } if (check_expression(check, &check->name, VCOL_CHECK_TABLE, alter_info)) DBUG_RETURN(TRUE); } } /* Give warnings for not supported table options */ - extern handlerton *maria_hton; - if (file->partition_ht() != maria_hton && create_info->transactional && - !file->has_transaction_manager()) - push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, - ER_ILLEGAL_HA_CREATE_OPTION, - ER_THD(thd, ER_ILLEGAL_HA_CREATE_OPTION), - file->engine_name()->str, - create_info->transactional == HA_CHOICE_YES - ? "TRANSACTIONAL=1" : "TRANSACTIONAL=0"); + if (create_info->used_fields & HA_CREATE_USED_TRANSACTIONAL && + !file->has_transactional_option()) + push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, ER_UNKNOWN_OPTION, + ER_THD(thd, ER_UNKNOWN_OPTION), "transactional"); if (parse_option_list(thd, file->partition_ht(), &create_info->option_struct, &create_info->option_list, @@ -3662,12 +3605,10 @@ without_overlaps_err: thd->mem_root)) DBUG_RETURN(TRUE); -#ifndef DBUG_OFF DBUG_EXECUTE_IF("key", Debug_key::print_keys(thd, "prep_create_table: ", *key_info_buffer, *key_count); ); -#endif DBUG_RETURN(FALSE); } @@ -3909,9 +3850,7 @@ static int append_system_key_parts(THD *thd, HA_CREATE_INFO *create_info, return result; } -handler *mysql_create_frm_image(THD *thd, const LEX_CSTRING &db, - const LEX_CSTRING &table_name, - HA_CREATE_INFO *create_info, +handler *mysql_create_frm_image(THD *thd, HA_CREATE_INFO *create_info, Alter_info *alter_info, int create_table_mode, KEY **key_info, uint *key_count, LEX_CUSTRING *frm) @@ -3926,7 +3865,7 @@ handler *mysql_create_frm_image(THD *thd, const LEX_CSTRING &db, DBUG_RETURN(NULL); } - set_table_default_charset(thd, create_info, db); + set_table_default_charset(thd, create_info, alter_info->db); db_options= create_info->table_options_with_row_type(); @@ -4047,7 +3986,7 @@ handler *mysql_create_frm_image(THD *thd, const LEX_CSTRING &db, if (part_info->vers_info && !create_info->versioned()) { - my_error(ER_VERS_NOT_VERSIONED, MYF(0), table_name.str); + my_error(ER_VERS_NOT_VERSIONED, MYF(0), alter_info->table_name.str); goto err; } @@ -4145,14 +4084,12 @@ handler *mysql_create_frm_image(THD *thd, const LEX_CSTRING &db, #endif if (mysql_prepare_create_table(thd, create_info, alter_info, &db_options, - file, key_info, key_count, - create_table_mode, db, table_name)) + file, key_info, key_count, create_table_mode)) goto err; create_info->table_options=db_options; - *frm= build_frm_image(thd, table_name, create_info, - alter_info->create_list, *key_count, - *key_info, file); + *frm= build_frm_image(thd, alter_info->table_name, create_info, + alter_info->create_list, *key_count, *key_info, file); if (frm->str) DBUG_RETURN(file); @@ -4457,9 +4394,10 @@ int create_table_impl(THD *thd, &path, &db, &table_name, frm_only); debug_crash_here("ddl_log_create_before_create_frm"); - file= mysql_create_frm_image(thd, orig_db, orig_table_name, create_info, - alter_info, create_table_mode, key_info, - key_count, frm); + alter_info->db= orig_db; + alter_info->table_name= orig_table_name; + file= mysql_create_frm_image(thd, create_info, alter_info, + create_table_mode, key_info, key_count, frm); /* TODO: remove this check of thd->is_error() (now it intercept errors in some val_*() methods and bring some single place to @@ -4548,8 +4486,6 @@ warn: int mysql_create_table_no_lock(THD *thd, DDL_LOG_STATE *ddl_log_state_create, DDL_LOG_STATE *ddl_log_state_rm, - const LEX_CSTRING *db, - const LEX_CSTRING *table_name, Table_specification_st *create_info, Alter_info *alter_info, bool *is_trans, int create_table_mode, TABLE_LIST *table_list) @@ -4560,6 +4496,8 @@ int mysql_create_table_no_lock(THD *thd, uint path_length; char path[FN_REFLEN + 1]; LEX_CSTRING cpath; + const LEX_CSTRING *db= &table_list->db; + const LEX_CSTRING *table_name= &table_list->table_name; LEX_CUSTRING frm= {0,0}; if (create_info->tmp_table()) @@ -4747,8 +4685,7 @@ bool mysql_create_table(THD *thd, TABLE_LIST *create_table, thd->abort_on_warning= thd->is_strict_mode(); if (mysql_create_table_no_lock(thd, &ddl_log_state_create, &ddl_log_state_rm, - &create_table->db, - &create_table->table_name, create_info, + create_info, alter_info, &is_trans, create_table_mode, create_table) > 0) @@ -5260,7 +5197,6 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table, res= ((create_res= mysql_create_table_no_lock(thd, &ddl_log_state_create, &ddl_log_state_rm, - &table->db, &table->table_name, &local_create_info, &local_alter_info, &is_trans, C_ORDINARY_CREATE, table)) > 0); @@ -6948,10 +6884,8 @@ static void update_altered_table(const Alter_inplace_info &ha_alter_info, @retval false success */ -bool mysql_compare_tables(TABLE *table, - Alter_info *alter_info, - HA_CREATE_INFO *create_info, - bool *metadata_equal) +bool mysql_compare_tables(TABLE *table, Alter_info *alter_info, + HA_CREATE_INFO *create_info, bool *metadata_equal) { DBUG_ENTER("mysql_compare_tables"); @@ -6976,15 +6910,16 @@ bool mysql_compare_tables(TABLE *table, Alter_info tmp_alter_info(*alter_info, thd->mem_root); uint db_options= 0; /* not used */ KEY *key_info_buffer= NULL; - LEX_CSTRING db= { table->s->db.str, table->s->db.length }; - LEX_CSTRING table_name= { table->s->db.str, table->s->table_name.length }; + + tmp_alter_info.db= table->s->db; + tmp_alter_info.table_name= table->s->table_name; /* Create the prepared information. */ int create_table_mode= table->s->tmp_table == NO_TMP_TABLE ? C_ORDINARY_CREATE : C_ALTER_TABLE; if (mysql_prepare_create_table(thd, create_info, &tmp_alter_info, &db_options, table->file, &key_info_buffer, - &key_count, create_table_mode, db, table_name)) + &key_count, create_table_mode)) DBUG_RETURN(1); /* Some very basic checks. */ @@ -7760,6 +7695,7 @@ mysql_prepare_alter_table(THD *thd, TABLE *table, List new_create_tail; /* New key definitions are added here */ List new_key_list; + List fk_list; List rename_key_list(alter_info->alter_rename_key_list); /* @@ -7793,12 +7729,13 @@ mysql_prepare_alter_table(THD *thd, TABLE *table, bool drop_period= false; LEX_CSTRING period_start_name= {nullptr, 0}; LEX_CSTRING period_end_name= {nullptr, 0}; + DBUG_ENTER("mysql_prepare_alter_table"); + if (table->s->period.name) { period_start_name= table->s->period_start_field()->field_name; period_end_name= table->s->period_end_field()->field_name; } - DBUG_ENTER("mysql_prepare_alter_table"); /* Merge incompatible changes flag in case of upgrade of a table from an @@ -7859,6 +7796,8 @@ mysql_prepare_alter_table(THD *thd, TABLE *table, create_info->option_list= merge_engine_table_options(table->s->option_list, create_info->option_list, thd->mem_root); + table->file->get_foreign_key_list(thd, &fk_list); + /* First collect all fields from table which isn't in drop_list */ @@ -8473,12 +8412,6 @@ mysql_prepare_alter_table(THD *thd, TABLE *table, key_create_info.comment= key_info->comment; key_create_info.is_ignored= key_info->is_ignored; - /* - We're refreshing an already existing index. Since the index is not - modified, there is no need to check for duplicate indexes again. - */ - key_create_info.check_for_duplicate_indexes= false; - if (key_info->flags & HA_SPATIAL) key_type= Key::SPATIAL; else if (key_info->flags & HA_NOSAME) @@ -8525,10 +8458,11 @@ mysql_prepare_alter_table(THD *thd, TABLE *table, tmp_name.length= strlen(key_name); /* We dont need LONG_UNIQUE_HASH_FIELD flag because it will be autogenerated */ key= new (thd->mem_root) Key(key_type, &tmp_name, &key_create_info, - MY_TEST(key_info->flags & HA_GENERATED_KEY), + key_info->flags & HA_GENERATED_KEY, &key_parts, key_info->option_list, DDL_options()); key->without_overlaps= key_info->without_overlaps; key->period= table->s->period.name; + key->old= true; new_key_list.push_back(key, thd->mem_root); } if (long_hash_key) @@ -8537,6 +8471,30 @@ mysql_prepare_alter_table(THD *thd, TABLE *table, re_setup_keyinfo_hash(key_info); } } + { + // add existing foreign keys + for (auto &fk : fk_list) + { + Alter_drop *drop; + for(drop_it.rewind(); (drop=drop_it++); ) + if (drop->type == Alter_drop::FOREIGN_KEY && + !my_strcasecmp(system_charset_info, fk.foreign_id->str, drop->name)) + break; + if (drop) + continue; + List cols, ref_cols; + for (LEX_CSTRING &c : fk.foreign_fields) + cols.push_back(new (thd->mem_root) Key_part_spec(&c, 0)); + for (LEX_CSTRING &c : fk.referenced_fields) + ref_cols.push_back(new (thd->mem_root) Key_part_spec(&c, 0)); + auto key= new (thd->mem_root) + Foreign_key(fk.foreign_id, &cols, fk.foreign_id, fk.referenced_db, + fk.referenced_table, &ref_cols, fk.delete_method, fk.update_method, + Foreign_key::FK_MATCH_UNDEF, DDL_options()); + key->old= true; + new_key_list.push_back(key, thd->mem_root); + } + } { Key *key; while ((key=key_it++)) // Add new keys @@ -8661,10 +8619,8 @@ mysql_prepare_alter_table(THD *thd, TABLE *table, if (!alter_info->check_constraint_list.is_empty()) { /* Check the table FOREIGN KEYs for name duplications. */ - List fk_child_key_list; FOREIGN_KEY_INFO *f_key; - table->file->get_foreign_key_list(thd, &fk_child_key_list); - List_iterator fk_key_it(fk_child_key_list); + List_iterator fk_key_it(fk_list); while ((f_key= fk_key_it++)) { List_iterator_fast @@ -9089,7 +9045,7 @@ static bool fk_prepare_copy_alter_table(THD *thd, TABLE *table, while (Key *key= fk_list_it++) { - if (key->type != Key::FOREIGN_KEY) + if (key->type != Key::FOREIGN_KEY || key->old) continue; Foreign_key *fk= static_cast(key); @@ -10099,10 +10055,10 @@ do_continue:; } // In-place execution of ALTER TABLE for partitioning. + alter_info->db= alter_ctx.db; + alter_info->table_name= alter_ctx.table_name; DBUG_RETURN(fast_alter_partition_table(thd, table, alter_info, - create_info, table_list, - &alter_ctx.db, - &alter_ctx.table_name)); + create_info, table_list)); } #endif @@ -10255,9 +10211,9 @@ do_continue:; alter_ctx.db, alter_ctx.table_name, alter_ctx.new_db, alter_ctx.tmp_name, alter_ctx.get_tmp_cstring_path(), - thd->lex->create_info, create_info, alter_info, - C_ALTER_TABLE_FRM_ONLY, NULL, - &key_info, &key_count, &frm); + thd->lex->create_info, + create_info, alter_info, C_ALTER_TABLE_FRM_ONLY, + NULL, &key_info, &key_count, &frm); thd->abort_on_warning= false; reenable_binlog(thd); diff --git a/sql/sql_table.h b/sql/sql_table.h index 7fa37bd3e46..3cbdbebeaa3 100644 --- a/sql/sql_table.h +++ b/sql/sql_table.h @@ -128,24 +128,16 @@ bool add_keyword_to_query(THD *thd, String *result, const LEX_CSTRING *keyword, int mysql_create_table_no_lock(THD *thd, DDL_LOG_STATE *ddl_log_state, DDL_LOG_STATE *ddl_log_state_rm, - const LEX_CSTRING *db, - const LEX_CSTRING *table_name, Table_specification_st *create_info, Alter_info *alter_info, bool *is_trans, int create_table_mode, TABLE_LIST *table); -handler *mysql_create_frm_image(THD *thd, - const LEX_CSTRING &db, - const LEX_CSTRING &table_name, - HA_CREATE_INFO *create_info, - Alter_info *alter_info, - int create_table_mode, - KEY **key_info, - uint *key_count, +handler *mysql_create_frm_image(THD *thd, HA_CREATE_INFO *create_info, + Alter_info *alter_info, int create_table_mode, + KEY **key_info, uint *key_count, LEX_CUSTRING *frm); -int mysql_discard_or_import_tablespace(THD *thd, - TABLE_LIST *table_list, +int mysql_discard_or_import_tablespace(THD *thd, TABLE_LIST *table_list, bool discard); bool mysql_prepare_alter_table(THD *thd, TABLE *table, diff --git a/sql/table.cc b/sql/table.cc index 85cf0da7d9b..2a6b758a027 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -3532,17 +3532,18 @@ int TABLE_SHARE::init_from_sql_statement_string(THD *thd, bool write, sql_unusable_for_discovery(thd, hton, sql_copy)))) goto ret; - thd->lex->create_info.db_type= hton; + tmp_lex.create_info.db_type= hton; #ifdef WITH_PARTITION_STORAGE_ENGINE thd->work_part_info= 0; // For partitioning #endif if (tabledef_version.str) - thd->lex->create_info.tabledef_version= tabledef_version; + tmp_lex.create_info.tabledef_version= tabledef_version; - promote_first_timestamp_column(&thd->lex->alter_info.create_list); - file= mysql_create_frm_image(thd, db, table_name, - &thd->lex->create_info, &thd->lex->alter_info, + tmp_lex.alter_info.db= db; + tmp_lex.alter_info.table_name= table_name; + promote_first_timestamp_column(&tmp_lex.alter_info.create_list); + file= mysql_create_frm_image(thd, &tmp_lex.create_info, &tmp_lex.alter_info, C_ORDINARY_CREATE, &unused1, &unused2, &frm); error|= file == 0; delete file; @@ -3556,7 +3557,7 @@ int TABLE_SHARE::init_from_sql_statement_string(THD *thd, bool write, ret: my_free(const_cast(frm.str)); - lex_end(thd->lex); + lex_end(&tmp_lex); thd->reset_db(&db_backup); thd->lex= old_lex; reenable_binlog(thd); @@ -9927,20 +9928,14 @@ LEX_CSTRING *fk_option_name(enum_fk_option opt) { { STRING_WITH_LEN("???") }, { STRING_WITH_LEN("RESTRICT") }, + { STRING_WITH_LEN("NO ACTION") }, { STRING_WITH_LEN("CASCADE") }, { STRING_WITH_LEN("SET NULL") }, - { STRING_WITH_LEN("NO ACTION") }, { STRING_WITH_LEN("SET DEFAULT") } }; return names + opt; } -bool fk_modifies_child(enum_fk_option opt) -{ - static bool can_write[]= { false, false, true, true, false, true }; - return can_write[opt]; -} - enum TR_table::enabled TR_table::use_transaction_registry= TR_table::MAYBE; TR_table::TR_table(THD* _thd, bool rw) : diff --git a/sql/table.h b/sql/table.h index 2a388b22ea4..af09b03c9e0 100644 --- a/sql/table.h +++ b/sql/table.h @@ -1871,8 +1871,8 @@ enum enum_schema_table_state PROCESSED_BY_JOIN_EXEC }; -enum enum_fk_option { FK_OPTION_UNDEF, FK_OPTION_RESTRICT, FK_OPTION_CASCADE, - FK_OPTION_SET_NULL, FK_OPTION_NO_ACTION, FK_OPTION_SET_DEFAULT}; +enum enum_fk_option { FK_OPTION_UNDEF, FK_OPTION_RESTRICT, FK_OPTION_NO_ACTION, + FK_OPTION_CASCADE, FK_OPTION_SET_NULL, FK_OPTION_SET_DEFAULT }; typedef struct st_foreign_key_info { @@ -1889,7 +1889,11 @@ typedef struct st_foreign_key_info } FOREIGN_KEY_INFO; LEX_CSTRING *fk_option_name(enum_fk_option opt); -bool fk_modifies_child(enum_fk_option opt); +static inline bool fk_modifies_child(enum_fk_option opt) +{ + return opt >= FK_OPTION_CASCADE; +} + class IS_table_read_plan; diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 3d8a8bcd4e1..f2b0013411d 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -12427,7 +12427,7 @@ create_table_info_t::create_foreign_keys() } while (Key* key = key_it++) { - if (key->type != Key::FOREIGN_KEY) + if (key->type != Key::FOREIGN_KEY || key->old) continue; if (tmp_table) { diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc index 6cabf9cc590..455b6c451de 100644 --- a/storage/innobase/handler/handler0alter.cc +++ b/storage/innobase/handler/handler0alter.cc @@ -3208,7 +3208,7 @@ innobase_get_foreign_key_info( *n_add_fk = 0; for (Key& key : alter_info->key_list) { - if (key.type != Key::FOREIGN_KEY) { + if (key.type != Key::FOREIGN_KEY || key.old) { continue; } diff --git a/storage/maria/ma_create.c b/storage/maria/ma_create.c index 45ccb49b466..7fd739d13a8 100644 --- a/storage/maria/ma_create.c +++ b/storage/maria/ma_create.c @@ -978,7 +978,6 @@ int maria_create(const char *name, enum data_file_type datafile_type, for (i=0; i < uniques ; i++) { tmp_keydef.keysegs=1; - tmp_keydef.flag= HA_UNIQUE_CHECK; tmp_keydef.block_length= (uint16) maria_block_size; tmp_keydef.keylength= MARIA_UNIQUE_HASH_LENGTH + pointer; tmp_keydef.minlength=tmp_keydef.maxlength=tmp_keydef.keylength; diff --git a/storage/myisam/mi_create.c b/storage/myisam/mi_create.c index 63950a3fc1d..8ad6446f620 100644 --- a/storage/myisam/mi_create.c +++ b/storage/myisam/mi_create.c @@ -754,7 +754,6 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs, for (i=0; i < uniques ; i++) { tmp_keydef.keysegs=1; - tmp_keydef.flag= HA_UNIQUE_CHECK; tmp_keydef.block_length= (uint16)myisam_block_size; tmp_keydef.keylength= MI_UNIQUE_HASH_LENGTH + pointer; tmp_keydef.minlength=tmp_keydef.maxlength=tmp_keydef.keylength;