summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAleksey Midenkov <midenok@gmail.com>2020-06-30 15:02:51 +0300
committerAleksey Midenkov <midenok@gmail.com>2021-03-09 01:31:56 +0300
commitf21f85579773da6008cda60a2bdfb517710d60cc (patch)
tree4787b62b4a236de6763e308b649ffb5b9eab606d
parent45ccb9f784819abacdcf518a24a879d35e7a1f59 (diff)
downloadmariadb-git-f21f85579773da6008cda60a2bdfb517710d60cc.tar.gz
MDEV-20865 Store foreign key info in TABLE_SHARE
1. Access foreign keys via TABLE_SHARE::foreign_keys and TABLE_SHARE::referenced_keys; foreign_keys and referenced_keys are objects in TABLE_SHARE. 2. Remove handler FK interface: - get_foreign_key_list() - get_parent_foreign_key_list() - referenced_by_foreign_key() 3. Invalidate referenced shares on: - RENAME TABLE - DROP TABLE - RENAME COLUMN - ADD FOREIGN KEY When foreign table is created or altered by the above operations all referenced shares are closed. This blocks the operation while any referenced shares are used (when at least one its TABLE instance is locked). 4. Update referenced shares on: - CREATE TABLE On CREATE TABLE add items to referenced_keys of referenced shares. 5. Invalidate foreign shares on: - RENAME TABLE - RENAME COLUMN The above-mentioned blocking takes effect. 6. Check foreign/referenced shares consistency on: - CHECK TABLE 7. Temporary change until MDEV-21051: InnoDB fill foreign key info at handler open(). On first TABLE open FK info is loaded from storage engine into TABLE_SHARE. All referenced shares (if any exist) are closed. This leads to blocking of first time foreign table open while referenced tables are used. Restore states of referenced shares in case of errors. FOREIGN_KEY_INFO refactored to FK_info holding Lex_cstring (MDEV-21311) Converge Foreign_key and supplemental generated Key together mysql_prepare_create_table() does data validation and such utilities as automatic name generation. But it does that only for indexes and ignores Foreign_key objects. Now as Foreign_key data needs to be stored in FRM files as well this processing must be done for them like for any other Key objects. Replace Key::FOREIGN_KEY type with Key::foreign flag of type Key::MULTIPLE and Key::generated set to true. Construct one object with Key::foreign == true instead of two objects of type Key::FOREIGN_KEY and Key::MULTIPLE. (MDEV-21051) datadict refactorings - Move read_extra2() to datadict.cc - Refactored extra2_fields to Extra2_info - build_frm_image() readability (MDEV-21051) build_table_shadow_filename() refactoring mysql_prepare_alter_table() leaks fixes (MDEV-21051) amend system tables locking restriction Table mysql.help_relation has foreign key to mysql.help_keyword. On bootstrap when help_relation is opened, it preopens help_keyword for READ and fails in lock_tables_check(). If system table is opened for write then fk references are opened for write. Related to: Bug#25422, WL#3984 Tests: main.lock (MDEV-21051) Store and read foreign key info into/from FRM files 1. Introduce Foreign_key_io class which creates/parses binary stream containing foreign key structures. Referenced tables store there only hints about foreign tables (their db and name), they restore full info from the corresponding tables. Foreign_key_io is stored under new EXTRA2_FOREIGN_KEY_INFO field in extra2 section of FRM file. 2. Modify mysql_prepare_create_table() to generate names for foreign keys. Until InnoDB storage of foreign keys is removed, FK names must be unique across the database: the FK name must be based on table name. 3. Keep stored data in sync on DDL changes. Referenced tables update their foreign hints after following operations on foreign tables: - RENAME TABLE - DROP TABLE - CREATE TABLE - ADD FOREIGN KEY - DROP FOREIGN KEY Foreign tables update their foreign info after following operations on referenced tables: - RENAME TABLE - RENAME COLUMN 4. To achieve 3. there must be ability to rewrite extra2 section of FRM file without full reparse. FRM binary is built from primary structures like HA_CREATE_INFO and cannot be built from TABLE_SHARE. Use shadow write and rename like fast_alter_partition_table() does. Create table workflow: 1. Foreign_key is constructed in parser, placed into alter_info->key_list; 2. mysql_prepare_create_table() translates them to FK_info, assigns foreign_id if needed; 3. build_frm_image() writes two FK_info lists into FRM's extra2 section, for referenced keys it stores only table names (hints); 4. init_from_binary_frm_image() parses extra2 section and fills foreign_keys and referenced_keys of TABLE_SHARE. It restores referenced_keys by reading hint list of table names, opening corresponding shares and restoring FK_info from their foreign_keys. Hints resolution is done only when initializing non-temporary shares. Usually temporary share has different (temporary) name and it is impossible to resolve foreign keys by that name (as we identify them by both foreign and referenced table names). Another not unimportant reason is performance: this saves spare share acquisitions. Alter table workflow: 1. Foreign_key is constructed in parser, placed into alter_info->key_list; 2. mysql_prepare_alter_table() prepares action lists and share list of foreigns/references; 3. mysql_prepare_alter_table() locks list of foreigns/references by MDL_INTENTION_EXCLUSIVE, acquires shares; 4. prepare_create_table() converts key_list into FK_list, assigns foreign_id; 5. shadow FRM of altered table is created; 6. data is copied; 7. altered table is locked by MDL_EXCLUSIVE; 8. fk_handle_alter() processes action lists, creates FK backups, modifies shares, writes shadow FRMs; 9. altered table is closed; 10. shadow FRMs are installed; 11. altered table is renamed, FRM backup deleted; 12. (TBD in MDEV-21053) shadow FRMs installation log closed, backups deleted; On FK backup system: In case of failed DDL operation all shares that was modified must be restored into original state. This is done by FK_ddl_backup (CREATE, DROP), FK_rename_backup (RENAME), FK_alter_backup (ALTER). On STL usage: STL is used for utility not performance-critical algorithms, core structures hold native List. A wrapper was made to convert STL exception into bool error status or NULL value. MDEV-20865 fk_check_consistency() in CHECK TABLE Self-refs fix
-rw-r--r--include/my_global.h4
-rw-r--r--mysql-test/main/alter_table.result16
-rw-r--r--mysql-test/main/alter_table.test6
-rw-r--r--mysql-test/main/derived_view.result2
-rw-r--r--mysql-test/main/derived_view.test2
-rw-r--r--mysql-test/main/drop_table_force.result12
-rw-r--r--mysql-test/main/features.result2
-rw-r--r--mysql-test/main/foreign_key.result582
-rw-r--r--mysql-test/main/foreign_key.test296
-rw-r--r--mysql-test/main/func_rollback.result2
-rw-r--r--mysql-test/main/information_schema_inno.result24
-rw-r--r--mysql-test/main/insert_innodb.result12
-rw-r--r--mysql-test/main/insert_notembedded.result6
-rw-r--r--mysql-test/main/insert_notembedded.test8
-rw-r--r--mysql-test/main/invisible_field.result2
-rw-r--r--mysql-test/main/join_outer_innodb.result4
-rw-r--r--mysql-test/main/multi_update.result2
-rw-r--r--mysql-test/main/multi_update.test2
-rw-r--r--mysql-test/main/mysqlcheck.result15
-rw-r--r--mysql-test/main/mysqld--help-aria.test2
-rw-r--r--mysql-test/main/profiling.result2
-rw-r--r--mysql-test/main/profiling.test2
-rw-r--r--mysql-test/main/ps.result2
-rw-r--r--mysql-test/main/ps.test2
-rw-r--r--mysql-test/main/query_cache_innodb.result2
-rw-r--r--mysql-test/main/subselect.result2
-rw-r--r--mysql-test/main/subselect.test2
-rw-r--r--mysql-test/main/subselect_no_exists_to_in.result2
-rw-r--r--mysql-test/main/subselect_no_mat.result2
-rw-r--r--mysql-test/main/subselect_no_opts.result2
-rw-r--r--mysql-test/main/subselect_no_scache.result2
-rw-r--r--mysql-test/main/subselect_no_semijoin.result2
-rw-r--r--mysql-test/main/system_mysql_db_fix40123.result4
-rw-r--r--mysql-test/main/system_mysql_db_fix40123.test4
-rw-r--r--mysql-test/main/system_mysql_db_fix50030.result4
-rw-r--r--mysql-test/main/system_mysql_db_fix50030.test4
-rw-r--r--mysql-test/main/system_mysql_db_fix50117.result4
-rw-r--r--mysql-test/main/system_mysql_db_fix50117.test4
-rw-r--r--mysql-test/main/trigger-trans.result2
-rw-r--r--mysql-test/main/type_ranges.result2
-rw-r--r--mysql-test/main/type_ranges.test2
-rw-r--r--mysql-test/main/union.result6
-rw-r--r--mysql-test/main/union.test6
-rw-r--r--mysql-test/suite/archive/discover.result2
-rw-r--r--mysql-test/suite/binlog/r/binlog_database.result6
-rw-r--r--mysql-test/suite/binlog/r/binlog_drop_if_exists.result6
-rw-r--r--mysql-test/suite/funcs_1/r/innodb_trig_frkey.result2
-rw-r--r--mysql-test/suite/funcs_1/r/is_key_column_usage.result2
-rw-r--r--mysql-test/suite/funcs_1/r/is_key_column_usage_embedded.result2
-rw-r--r--mysql-test/suite/funcs_1/r/is_statistics.result2
-rw-r--r--mysql-test/suite/funcs_1/r/is_statistics_mysql.result2
-rw-r--r--mysql-test/suite/funcs_1/r/is_statistics_mysql_embedded.result4
-rw-r--r--mysql-test/suite/funcs_1/r/is_table_constraints.result2
-rw-r--r--mysql-test/suite/funcs_1/r/is_table_constraints_mysql.result2
-rw-r--r--mysql-test/suite/funcs_1/r/is_table_constraints_mysql_embedded.result4
-rw-r--r--mysql-test/suite/gcol/inc/gcol_ins_upd.inc6
-rw-r--r--mysql-test/suite/gcol/inc/gcol_keys.inc4
-rw-r--r--mysql-test/suite/gcol/r/gcol_ins_upd_innodb.result12
-rw-r--r--mysql-test/suite/gcol/r/gcol_keys_innodb.result4
-rw-r--r--mysql-test/suite/gcol/r/innodb_virtual_fk.result6
-rw-r--r--mysql-test/suite/gcol/r/innodb_virtual_fk_restart.result1
-rw-r--r--mysql-test/suite/gcol/t/innodb_virtual_fk.test4
-rw-r--r--mysql-test/suite/innodb/r/alter_foreign_crash.result1
-rw-r--r--mysql-test/suite/innodb/r/alter_table.result4
-rw-r--r--mysql-test/suite/innodb/r/foreign-keys.result16
-rw-r--r--mysql-test/suite/innodb/r/foreign_key.result80
-rw-r--r--mysql-test/suite/innodb/r/foreign_key_debug.result2
-rw-r--r--mysql-test/suite/innodb/r/innodb-alter-table.result4
-rw-r--r--mysql-test/suite/innodb/r/innodb-alter.result59
-rw-r--r--mysql-test/suite/innodb/r/innodb-fk-virtual.result12
-rw-r--r--mysql-test/suite/innodb/r/innodb-fk-warnings.result21
-rw-r--r--mysql-test/suite/innodb/r/innodb-fk.result35
-rw-r--r--mysql-test/suite/innodb/r/innodb-index,debug.rdiff10
-rw-r--r--mysql-test/suite/innodb/r/innodb-index-online-fk.result2
-rw-r--r--mysql-test/suite/innodb/r/innodb-index.result26
-rw-r--r--mysql-test/suite/innodb/r/innodb-truncate.result12
-rw-r--r--mysql-test/suite/innodb/r/innodb-wl5522-1.result2
-rw-r--r--mysql-test/suite/innodb/r/innodb.result42
-rw-r--r--mysql-test/suite/innodb/r/innodb_bug57904.result12
-rw-r--r--mysql-test/suite/innodb/r/innodb_mysql.result22
-rw-r--r--mysql-test/suite/innodb/r/instant_alter.result12
-rw-r--r--mysql-test/suite/innodb/r/instant_alter_bugs.result2
-rw-r--r--mysql-test/suite/innodb/r/instant_alter_index_rename.result9
-rw-r--r--mysql-test/suite/innodb/r/stored_fk.result10
-rw-r--r--mysql-test/suite/innodb/r/table_flags,debug.rdiff98
-rw-r--r--mysql-test/suite/innodb/r/truncate_foreign.result6
-rw-r--r--mysql-test/suite/innodb/r/update-cascade.result20
-rw-r--r--mysql-test/suite/innodb/t/alter_table.test4
-rw-r--r--mysql-test/suite/innodb/t/foreign-keys.test2
-rw-r--r--mysql-test/suite/innodb/t/foreign_key.test14
-rw-r--r--mysql-test/suite/innodb/t/innodb-fk-warnings.test6
-rw-r--r--mysql-test/suite/innodb/t/innodb-fk.test13
-rw-r--r--mysql-test/suite/innodb/t/innodb-index.test10
-rw-r--r--mysql-test/suite/innodb/t/innodb-truncate.test4
-rw-r--r--mysql-test/suite/innodb/t/innodb.test2
-rw-r--r--mysql-test/suite/innodb/t/instant_alter.test4
-rw-r--r--mysql-test/suite/innodb/t/instant_alter_index_rename.test9
-rw-r--r--mysql-test/suite/innodb/t/stored_fk.test2
-rw-r--r--mysql-test/suite/innodb/t/table_flags.test2
-rw-r--r--mysql-test/suite/innodb_fts/r/innodb_fts_misc_1.result18
-rw-r--r--mysql-test/suite/innodb_fts/r/misc_debug.result2
-rw-r--r--mysql-test/suite/innodb_gis/r/point_basic.result6
-rw-r--r--mysql-test/suite/rpl/r/rpl_drop_db_fail.result2
-rw-r--r--mysql-test/suite/vcol/inc/vcol_ins_upd.inc6
-rw-r--r--mysql-test/suite/vcol/inc/vcol_keys.inc4
-rw-r--r--mysql-test/suite/vcol/r/vcol_ins_upd_innodb.result12
-rw-r--r--mysql-test/suite/vcol/r/vcol_keys_innodb.result4
-rw-r--r--mysql-test/suite/versioning/r/foreign.result22
-rw-r--r--mysql-test/suite/versioning/t/foreign.test5
-rw-r--r--scripts/mysql_system_tables.sql4
-rw-r--r--sql/datadict.cc322
-rw-r--r--sql/datadict.h109
-rw-r--r--sql/ddl_log.cc4
-rw-r--r--sql/discover.cc1
-rw-r--r--sql/ha_partition.h21
-rw-r--r--sql/handler.cc35
-rw-r--r--sql/handler.h42
-rw-r--r--sql/item.cc22
-rw-r--r--sql/lex_string.h131
-rw-r--r--sql/lock.cc2
-rw-r--r--sql/log_event_old.cc4
-rw-r--r--sql/log_event_server.cc2
-rw-r--r--sql/sql_admin.cc9
-rw-r--r--sql/sql_alter.cc3
-rw-r--r--sql/sql_alter.h126
-rw-r--r--sql/sql_base.cc33
-rw-r--r--sql/sql_class.cc25
-rw-r--r--sql/sql_class.h350
-rw-r--r--sql/sql_db.cc2
-rw-r--r--sql/sql_insert.cc2
-rw-r--r--sql/sql_lex.cc58
-rw-r--r--sql/sql_lex.h11
-rw-r--r--sql/sql_list.h16
-rw-r--r--sql/sql_parse.cc2
-rw-r--r--sql/sql_partition.cc54
-rw-r--r--sql/sql_rename.cc43
-rw-r--r--sql/sql_rename.h37
-rw-r--r--sql/sql_show.cc171
-rw-r--r--sql/sql_string.h27
-rw-r--r--sql/sql_table.cc2050
-rw-r--r--sql/sql_table.h19
-rw-r--r--sql/sql_truncate.cc36
-rw-r--r--sql/sql_yacc.yy18
-rw-r--r--sql/table.cc517
-rw-r--r--sql/table.h118
-rw-r--r--sql/table_cache.cc34
-rw-r--r--sql/table_cache.h55
-rw-r--r--sql/unireg.cc511
-rw-r--r--sql/unireg.h108
-rw-r--r--sql/wsrep_mysqld.cc17
-rw-r--r--storage/innobase/handler/ha_innodb.cc396
-rw-r--r--storage/innobase/handler/ha_innodb.h9
-rw-r--r--storage/innobase/handler/handler0alter.cc53
-rw-r--r--storage/mroonga/ha_mroonga.cpp134
-rw-r--r--storage/mroonga/ha_mroonga.hpp8
-rw-r--r--storage/mroonga/mrn_table.cpp2
-rw-r--r--storage/mroonga/mysql-test/mroonga/storage/r/foreign_key_alter_add.result8
-rw-r--r--storage/mroonga/mysql-test/mroonga/storage/r/foreign_key_alter_drop.result4
-rw-r--r--storage/mroonga/mysql-test/mroonga/storage/r/foreign_key_rename.result8
-rw-r--r--storage/mroonga/mysql-test/mroonga/storage/t/foreign_key_alter_drop.test2
-rw-r--r--storage/perfschema/unittest/CMakeLists.txt4
-rw-r--r--storage/rocksdb/mysql-test/rocksdb/r/index_file_map.result4
-rw-r--r--storage/rocksdb/mysql-test/rocksdb/r/misc.result2
-rw-r--r--storage/rocksdb/mysql-test/rocksdb/t/index_file_map.test4
-rw-r--r--storage/spider/spd_sys_table.cc2
165 files changed, 5734 insertions, 1869 deletions
diff --git a/include/my_global.h b/include/my_global.h
index 346c453bf86..33eeaaaf524 100644
--- a/include/my_global.h
+++ b/include/my_global.h
@@ -92,9 +92,9 @@
#endif
#ifdef WITH_PARTITION_STORAGE_ENGINE
-#define IF_PARTITIONING(A,B) A
+#define IF_PARTITIONING(A,B) (A)
#else
-#define IF_PARTITIONING(A,B) B
+#define IF_PARTITIONING(A,B) (B)
#endif
#if defined (_WIN32)
diff --git a/mysql-test/main/alter_table.result b/mysql-test/main/alter_table.result
index a27b54d4b48..62e8b73a16c 100644
--- a/mysql-test/main/alter_table.result
+++ b/mysql-test/main/alter_table.result
@@ -1561,18 +1561,18 @@ t2 CREATE TABLE `t2` (
KEY `fk` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
ALTER TABLE t2 ADD FOREIGN KEY (id) REFERENCES t1(id);
-ALTER TABLE t2 ADD FOREIGN KEY IF NOT EXISTS t2_ibfk_1(id) REFERENCES t1(id);
+ALTER TABLE t2 ADD FOREIGN KEY IF NOT EXISTS fk_t2(id) REFERENCES t1(id);
Warnings:
-Note 1061 Duplicate key name 't2_ibfk_1'
-ALTER TABLE t2 DROP FOREIGN KEY IF EXISTS t2_ibfk_1;
-ALTER TABLE t2 DROP FOREIGN KEY IF EXISTS t2_ibfk_1;
+Note 1061 Duplicate key name 'fk_t2'
+ALTER TABLE t2 DROP FOREIGN KEY IF EXISTS fk_t2;
+ALTER TABLE t2 DROP FOREIGN KEY IF EXISTS fk_t2;
Warnings:
-Note 1091 Can't DROP FOREIGN KEY `t2_ibfk_1`; check that it exists
+Note 1091 Can't DROP FOREIGN KEY `fk_t2`; check that it exists
SHOW CREATE TABLE t2;
Table Create Table
t2 CREATE TABLE `t2` (
`id` int(11) NOT NULL,
- KEY `id` (`id`)
+ KEY `fk_t2` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
DROP TABLE t2;
CREATE TABLE t2 (
@@ -2775,7 +2775,7 @@ t3 CREATE TABLE `t3` (
`a` int(11) DEFAULT NULL,
`b` int(11) DEFAULT NULL,
KEY `b` (`b`),
- CONSTRAINT `t3_ibfk_1` FOREIGN KEY (`b`) REFERENCES `t1` (`bb`)
+ CONSTRAINT `fk_t3` FOREIGN KEY (`b`) REFERENCES `t1` (`bb`)
) ENGINE=DEFAULT_ENGINE DEFAULT CHARSET=latin1
ALTER TABLE t1 RENAME COLUMN bb TO b;
SHOW CREATE TABLE t1;
@@ -2792,7 +2792,7 @@ t3 CREATE TABLE `t3` (
`a` int(11) DEFAULT NULL,
`c` int(11) DEFAULT NULL,
KEY `b` (`c`),
- CONSTRAINT `t3_ibfk_1` FOREIGN KEY (`c`) REFERENCES `t1` (`b`)
+ CONSTRAINT `fk_t3` FOREIGN KEY (`c`) REFERENCES `t1` (`b`)
) ENGINE=DEFAULT_ENGINE DEFAULT CHARSET=latin1
CREATE TABLE t4(a int);
ALTER TABLE t4 RENAME COLUMN a TO aa, ALGORITHM = INPLACE;
diff --git a/mysql-test/main/alter_table.test b/mysql-test/main/alter_table.test
index 5fd1358e9a9..6f581a264ac 100644
--- a/mysql-test/main/alter_table.test
+++ b/mysql-test/main/alter_table.test
@@ -1401,9 +1401,9 @@ ALTER TABLE t2 DROP FOREIGN KEY IF EXISTS fk;
ALTER TABLE t2 DROP FOREIGN KEY IF EXISTS fk;
SHOW CREATE TABLE t2;
ALTER TABLE t2 ADD FOREIGN KEY (id) REFERENCES t1(id);
-ALTER TABLE t2 ADD FOREIGN KEY IF NOT EXISTS t2_ibfk_1(id) REFERENCES t1(id);
-ALTER TABLE t2 DROP FOREIGN KEY IF EXISTS t2_ibfk_1;
-ALTER TABLE t2 DROP FOREIGN KEY IF EXISTS t2_ibfk_1;
+ALTER TABLE t2 ADD FOREIGN KEY IF NOT EXISTS fk_t2(id) REFERENCES t1(id);
+ALTER TABLE t2 DROP FOREIGN KEY IF EXISTS fk_t2;
+ALTER TABLE t2 DROP FOREIGN KEY IF EXISTS fk_t2;
SHOW CREATE TABLE t2;
DROP TABLE t2;
diff --git a/mysql-test/main/derived_view.result b/mysql-test/main/derived_view.result
index 6da132848d1..2a04fdb3225 100644
--- a/mysql-test/main/derived_view.result
+++ b/mysql-test/main/derived_view.result
@@ -2702,7 +2702,7 @@ id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY p eq_ref PRIMARY PRIMARY 4 g.p_random 1 Using where
2 DERIVED gal ALL NULL NULL NULL NULL 10
3 DEPENDENT SUBQUERY pi ref gallery_id gallery_id 4 test.gal.id 4 Using temporary; Using filesort
-drop table galleries, pictures;
+drop table pictures, galleries;
#
# MDEV-5740: Assertion
#`!derived->first_select()->exclude_from_table_unique_test ||
diff --git a/mysql-test/main/derived_view.test b/mysql-test/main/derived_view.test
index 76b15fa8787..9b6446bd50e 100644
--- a/mysql-test/main/derived_view.test
+++ b/mysql-test/main/derived_view.test
@@ -1722,7 +1722,7 @@ LEFT JOIN pictures p
ORDER BY gallery_name ASC
;
-drop table galleries, pictures;
+drop table pictures, galleries;
--echo #
--echo # MDEV-5740: Assertion
diff --git a/mysql-test/main/drop_table_force.result b/mysql-test/main/drop_table_force.result
index 622589eb3b9..7677b700c10 100644
--- a/mysql-test/main/drop_table_force.result
+++ b/mysql-test/main/drop_table_force.result
@@ -45,17 +45,17 @@ db.opt
CREATE TABLE parent (id INT NOT NULL, PRIMARY KEY (id)) ENGINE=INNODB;
CREATE TABLE child (id INT, parent_id INT, INDEX par_ind (parent_id), FOREIGN KEY (parent_id) REFERENCES parent(id) ON DELETE CASCADE) ENGINE=INNODB;
drop table parent;
-ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails
+ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (fk_child)
drop table parent restrict;
-ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails
+ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (fk_child)
drop table parent cascade;
-ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails
+ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (fk_child)
drop table parent;
-ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails
+ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (fk_child)
drop table parent restrict;
-ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails
+ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (fk_child)
drop table parent cascade;
-ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails
+ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (fk_child)
drop table child;
drop table parent;
#Test10: drop non-innodb engine table returns ok
diff --git a/mysql-test/main/features.result b/mysql-test/main/features.result
index 0da2e5fe986..db36a25fd0c 100644
--- a/mysql-test/main/features.result
+++ b/mysql-test/main/features.result
@@ -174,7 +174,7 @@ create table t2 (b int, constraint foo check (b < 10));
drop table t1, t2;
show status like "feature_check_constraint";
Variable_name Value
-Feature_check_constraint 2
+Feature_check_constraint 4
#
# Feature insert...returning
#
diff --git a/mysql-test/main/foreign_key.result b/mysql-test/main/foreign_key.result
index 46c8d3b7fee..6ebacf1656a 100644
--- a/mysql-test/main/foreign_key.result
+++ b/mysql-test/main/foreign_key.result
@@ -1,4 +1,9 @@
drop table if exists t1,t2;
+create table t2 (
+a int unique, c int unique);
+create table t3 (
+a int unique, c int unique, d int unique,
+r int references t3(d));
create table t1 (
a int not null references t2,
b int not null constraint t2_c references t2 (c),
@@ -12,13 +17,17 @@ foreign key (a,b) references t3 (c,d) on delete set default,
foreign key (a,b) references t3 (c,d) on update set null);
create index a on t1 (a);
create unique index b on t1 (a,b);
-drop table t1;
+drop tables t2;
+ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (fk_t1)
+drop tables t3;
+ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (fk_t1_2)
+drop tables t1, t2, t3;
create table t1 (id int primary key) engine = innodb;
create table t2 (id int PRIMARY KEY, FOREIGN KEY (id) REFERENCES t1(id)) engine=innodb;
insert into t1 values (1), (2), (3), (4), (5), (6);
insert into t2 values (3), (5);
delete from t1;
-ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`id`) REFERENCES `t1` (`id`))
+ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `fk_t2` FOREIGN KEY (`id`) REFERENCES `t1` (`id`))
select * from t1;
id
1
@@ -29,8 +38,8 @@ id
6
delete ignore from t1;
Warnings:
-Warning 1451 Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`id`) REFERENCES `t1` (`id`))
-Warning 1451 Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`id`) REFERENCES `t1` (`id`))
+Warning 1451 Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `fk_t2` FOREIGN KEY (`id`) REFERENCES `t1` (`id`))
+Warning 1451 Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `fk_t2` FOREIGN KEY (`id`) REFERENCES `t1` (`id`))
select row_count();
row_count()
-1
@@ -108,3 +117,568 @@ ALTER TABLE tfk ADD CONSTRAINT sid UNIQUE(c2);
ERROR 42000: Duplicate key name 'sid'
DROP TABLE tfk;
DROP TABLE tpk;
+#
+# MDEV-16417 Store Foreign Key metadata outside of InnoDB
+#
+set default_storage_engine= innodb;
+# Check create table
+create or replace table t1 (id int primary key);
+create or replace table t2 (id int primary key, foreign key (id) references t1(id));
+select * from t1, t2;
+id id
+check tables t1, t2;
+Table Op Msg_type Msg_text
+test.t1 check Note Found 1 referenced keys
+test.t1 check status OK
+test.t2 check Note Found 1 foreign keys
+test.t2 check status OK
+flush tables t1, t2;
+check tables t1, t2;
+Table Op Msg_type Msg_text
+test.t1 check Note Found 1 referenced keys
+test.t1 check status OK
+test.t2 check Note Found 1 foreign keys
+test.t2 check status OK
+drop table t2, t1;
+create table t1 (id int primary key);
+create table t2 (id int references t1(id)) select id from t1;
+check tables t1, t2;
+Table Op Msg_type Msg_text
+test.t1 check Note Found 1 referenced keys
+test.t1 check status OK
+test.t2 check Note Found 1 foreign keys
+test.t2 check status OK
+flush tables;
+check tables t1, t2;
+Table Op Msg_type Msg_text
+test.t1 check Note Found 1 referenced keys
+test.t1 check status OK
+test.t2 check Note Found 1 foreign keys
+test.t2 check status OK
+drop table t2, t1;
+create database D;
+create table D.T1(id int primary key);
+create table t2(id int primary key, f1 int references D.T1(id));
+select * from D.T1;
+id
+check table D.T1;
+Table Op Msg_type Msg_text
+D.T1 check Note Found 1 referenced keys
+D.T1 check status OK
+drop table t2;
+check table D.T1;
+Table Op Msg_type Msg_text
+D.T1 check status OK
+flush tables;
+check table D.T1;
+Table Op Msg_type Msg_text
+D.T1 check status OK
+drop table D.T1;
+drop database D;
+# Check rename column, lock tables
+create or replace table t1 (id int primary key);
+create or replace table t2 (id int primary key);
+create or replace table t3 (id int primary key);
+create or replace table ch1 (
+id int, id2 int,
+foreign key (id) references t1 (id),
+foreign key (id2) references t2 (id),
+foreign key (id) references t3 (id));
+select * from t1, t2, t3;
+id id id
+connect con1, localhost, root;
+lock tables t3 read;
+connection default;
+set @saved_lock_wait_timeout= @@lock_wait_timeout;
+set lock_wait_timeout= 1;
+alter table ch1 change id2 xid2 int;
+alter table ch1 change id xid int;
+ERROR HY000: Lock wait timeout exceeded; try restarting transaction
+set lock_wait_timeout= @saved_lock_wait_timeout;
+connection con1;
+unlock tables;
+disconnect con1;
+connection default;
+alter table ch1 change id xid int;
+select * from ch1;
+xid xid2
+check tables t1, t2, t3;
+Table Op Msg_type Msg_text
+test.t1 check Note Found 1 referenced keys
+test.t1 check status OK
+test.t2 check Note Found 1 referenced keys
+test.t2 check status OK
+test.t3 check Note Found 1 referenced keys
+test.t3 check status OK
+flush tables t1, t2, t3;
+check tables t1, t2, t3;
+Table Op Msg_type Msg_text
+test.t1 check Note Found 1 referenced keys
+test.t1 check status OK
+test.t2 check Note Found 1 referenced keys
+test.t2 check status OK
+test.t3 check Note Found 1 referenced keys
+test.t3 check status OK
+drop tables ch1, t2, t1, t3;
+# Rename column on referenced table
+create or replace table t1 (id int primary key);
+create or replace table t2 (id int references t1, id2 int references t1(id));
+select * from t2;
+id id2
+alter table t1 change id xid int;
+show create table t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `id` int(11) DEFAULT NULL,
+ `id2` int(11) DEFAULT NULL,
+ KEY `fk_t2` (`id`),
+ KEY `fk_t2_2` (`id2`),
+ CONSTRAINT `fk_t2` FOREIGN KEY (`id`) REFERENCES `t1` (`xid`),
+ CONSTRAINT `fk_t2_2` FOREIGN KEY (`id2`) REFERENCES `t1` (`xid`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+select * from t1;
+xid
+check table t2;
+Table Op Msg_type Msg_text
+test.t2 check Note Found 2 foreign keys
+test.t2 check status OK
+flush table t2;
+check table t2;
+Table Op Msg_type Msg_text
+test.t2 check Note Found 2 foreign keys
+test.t2 check status OK
+alter table t1 rename column xid to yid;
+show create table t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `id` int(11) DEFAULT NULL,
+ `id2` int(11) DEFAULT NULL,
+ KEY `fk_t2` (`id`),
+ KEY `fk_t2_2` (`id2`),
+ CONSTRAINT `fk_t2` FOREIGN KEY (`id`) REFERENCES `t1` (`yid`),
+ CONSTRAINT `fk_t2_2` FOREIGN KEY (`id2`) REFERENCES `t1` (`yid`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+select * from t1;
+yid
+check table t2;
+Table Op Msg_type Msg_text
+test.t2 check Note Found 2 foreign keys
+test.t2 check status OK
+flush table t2;
+check table t2;
+Table Op Msg_type Msg_text
+test.t2 check Note Found 2 foreign keys
+test.t2 check status OK
+drop tables t2, t1;
+# Check rename table
+create or replace table t1 (id int primary key);
+create or replace table t2 (id int references t1);
+select * from t2, t1;
+id id
+rename table t2 to t3;
+create table t2 (x int);
+check table t1;
+Table Op Msg_type Msg_text
+test.t1 check Note Found 1 referenced keys
+test.t1 check status OK
+flush tables t1;
+check table t1;
+Table Op Msg_type Msg_text
+test.t1 check Note Found 1 referenced keys
+test.t1 check status OK
+drop tables t3, t1, t2;
+create or replace table t1 (id int primary key);
+create or replace table t2 (id int primary key);
+create or replace table t3 (id int primary key);
+select * from t1, t2, t3;
+id id id
+create or replace table t4 (
+id int primary key, id2 int references t4(id),
+foreign key (id) references t1 (id),
+foreign key (id2) references t2 (id),
+foreign key (id) references t3 (id));
+select * from t4;
+id id2
+rename table t4 to xt4;
+check tables t1, t2, t3;
+Table Op Msg_type Msg_text
+test.t1 check Note Found 1 referenced keys
+test.t1 check status OK
+test.t2 check Note Found 1 referenced keys
+test.t2 check status OK
+test.t3 check Note Found 1 referenced keys
+test.t3 check status OK
+flush tables t1, t2, t3;
+check tables t1, t2, t3;
+Table Op Msg_type Msg_text
+test.t1 check Note Found 1 referenced keys
+test.t1 check status OK
+test.t2 check Note Found 1 referenced keys
+test.t2 check status OK
+test.t3 check Note Found 1 referenced keys
+test.t3 check status OK
+alter table xt4 rename to yt4, algorithm=inplace;
+select * from t1, t2, t3;
+id id id
+check tables t1, t2, t3;
+Table Op Msg_type Msg_text
+test.t1 check Note Found 1 referenced keys
+test.t1 check status OK
+test.t2 check Note Found 1 referenced keys
+test.t2 check status OK
+test.t3 check Note Found 1 referenced keys
+test.t3 check status OK
+flush tables t1, t2, t3;
+check tables t1, t2, t3;
+Table Op Msg_type Msg_text
+test.t1 check Note Found 1 referenced keys
+test.t1 check status OK
+test.t2 check Note Found 1 referenced keys
+test.t2 check status OK
+test.t3 check Note Found 1 referenced keys
+test.t3 check status OK
+alter table yt4 rename to zt4, algorithm=copy;
+select * from t1, t2, t3;
+id id id
+check tables t1, t2, t3;
+Table Op Msg_type Msg_text
+test.t1 check Note Found 1 referenced keys
+test.t1 check status OK
+test.t2 check Note Found 1 referenced keys
+test.t2 check status OK
+test.t3 check Note Found 1 referenced keys
+test.t3 check status OK
+flush tables t1, t2, t3;
+check tables t1, t2, t3;
+Table Op Msg_type Msg_text
+test.t1 check Note Found 1 referenced keys
+test.t1 check status OK
+test.t2 check Note Found 1 referenced keys
+test.t2 check status OK
+test.t3 check Note Found 1 referenced keys
+test.t3 check status OK
+drop tables zt4, t2, t1, t3;
+# Rename of referenced table
+create or replace table t1 (id int primary key);
+create or replace table t2 (id int references t1);
+select * from t2;
+id
+rename table t1 to xt1;
+show create table t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `id` int(11) DEFAULT NULL,
+ KEY `fk_t2` (`id`),
+ CONSTRAINT `fk_t2` FOREIGN KEY (`id`) REFERENCES `xt1` (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+select * from xt1;
+id
+check tables t2, xt1;
+Table Op Msg_type Msg_text
+test.t2 check Note Found 1 foreign keys
+test.t2 check status OK
+test.xt1 check Note Found 1 referenced keys
+test.xt1 check status OK
+flush tables t2, xt1;
+check tables t2, xt1;
+Table Op Msg_type Msg_text
+test.t2 check Note Found 1 foreign keys
+test.t2 check status OK
+test.xt1 check Note Found 1 referenced keys
+test.xt1 check status OK
+alter table xt1 rename to yt1, algorithm=inplace;
+show create table t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `id` int(11) DEFAULT NULL,
+ KEY `fk_t2` (`id`),
+ CONSTRAINT `fk_t2` FOREIGN KEY (`id`) REFERENCES `yt1` (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+select * from yt1;
+id
+check tables t2, yt1;
+Table Op Msg_type Msg_text
+test.t2 check Note Found 1 foreign keys
+test.t2 check status OK
+test.yt1 check Note Found 1 referenced keys
+test.yt1 check status OK
+flush tables t2, yt1;
+check tables t2, yt1;
+Table Op Msg_type Msg_text
+test.t2 check Note Found 1 foreign keys
+test.t2 check status OK
+test.yt1 check Note Found 1 referenced keys
+test.yt1 check status OK
+alter table yt1 rename to t1, algorithm=copy;
+show create table t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `id` int(11) DEFAULT NULL,
+ KEY `fk_t2` (`id`),
+ CONSTRAINT `fk_t2` FOREIGN KEY (`id`) REFERENCES `t1` (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+select * from t1;
+id
+check tables t2, t1;
+Table Op Msg_type Msg_text
+test.t2 check Note Found 1 foreign keys
+test.t2 check status OK
+test.t1 check Note Found 1 referenced keys
+test.t1 check status OK
+flush tables t2, t1;
+check tables t2, t1;
+Table Op Msg_type Msg_text
+test.t2 check Note Found 1 foreign keys
+test.t2 check status OK
+test.t1 check Note Found 1 referenced keys
+test.t1 check status OK
+drop tables t2, t1;
+# Check drop table
+create or replace table t1 (id int primary key);
+create or replace table ch1 (id int, foreign key (id) references t1 (id));
+select * from t1;
+id
+select * from ch1;
+id
+drop table t1;
+ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (fk_ch1)
+drop tables ch1, t1;
+# Check drop database
+create or replace table t1 (id int primary key);
+select * from t1;
+id
+create or replace database test2;
+use test2;
+create or replace table ch1 (
+id int, id2 int,
+foreign key (id) references test.t1 (id));
+select * from ch1;
+id id2
+use test;
+drop database test2;
+check tables t1;
+Table Op Msg_type Msg_text
+test.t1 check status OK
+flush tables t1;
+check tables t1;
+Table Op Msg_type Msg_text
+test.t1 check status OK
+drop tables t1;
+# Check add foreign key
+create or replace table t1(fld1 int not null primary key);
+create or replace table t2(fld1 int not null, fld2 int as (fld1) virtual);
+insert into t1 values(1);
+insert into t2 values(1, default);
+set foreign_key_checks= 0;
+alter table t2 add index(fld2), add foreign key (fld1) references t1(fld1)
+on update cascade, algorithm=inplace;
+set foreign_key_checks= 1;
+update t1 set fld1= 2;
+select fld2 from t2;
+fld2
+2
+select * from t2;
+fld1 fld2
+2 2
+drop table t2, t1;
+# Check drop column, drop foreign key
+create or replace table t1 (id int primary key, a int);
+create or replace table t2 (id int, a int, foreign key fk (id) references t1 (id));
+alter table t1 drop id;
+ERROR HY000: Cannot drop column 'id': needed in a foreign key constraint 'fk' of table `test`.`t2`
+alter table t2 drop id;
+ERROR 42000: Incorrect foreign key definition for 'id': foreign field not found
+alter table t2 drop foreign key fk;
+drop tables t1, t2;
+# Check self-references
+create or replace table t1 (id int primary key, id2 int references t1 (id));
+check tables t1;
+Table Op Msg_type Msg_text
+test.t1 check Note Found 1 self-references
+test.t1 check status OK
+flush tables t1;
+check tables t1;
+Table Op Msg_type Msg_text
+test.t1 check Note Found 1 self-references
+test.t1 check status OK
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `id` int(11) NOT NULL,
+ `id2` int(11) DEFAULT NULL,
+ PRIMARY KEY (`id`),
+ KEY `fk_t1` (`id2`),
+ CONSTRAINT `fk_t1` FOREIGN KEY (`id2`) REFERENCES `t1` (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (1, 2);
+ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test`.`t1`, CONSTRAINT `fk_t1` FOREIGN KEY (`id2`) REFERENCES `t1` (`id`))
+insert into t1 values (1, 1);
+alter table t1 change id2 id3 int;
+check tables t1;
+Table Op Msg_type Msg_text
+test.t1 check Note Found 1 self-references
+test.t1 check status OK
+flush tables t1;
+check tables t1;
+Table Op Msg_type Msg_text
+test.t1 check Note Found 1 self-references
+test.t1 check status OK
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `id` int(11) NOT NULL,
+ `id3` int(11) DEFAULT NULL,
+ PRIMARY KEY (`id`),
+ KEY `fk_t1` (`id3`),
+ CONSTRAINT `fk_t1` FOREIGN KEY (`id3`) REFERENCES `t1` (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+alter table t1 add foreign key (id3) references t1 (id);
+check tables t1;
+Table Op Msg_type Msg_text
+test.t1 check Note Found 2 self-references
+test.t1 check status OK
+flush tables t1;
+check tables t1;
+Table Op Msg_type Msg_text
+test.t1 check Note Found 2 self-references
+test.t1 check status OK
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `id` int(11) NOT NULL,
+ `id3` int(11) DEFAULT NULL,
+ PRIMARY KEY (`id`),
+ KEY `fk_t1_2` (`id3`),
+ CONSTRAINT `fk_t1` FOREIGN KEY (`id3`) REFERENCES `t1` (`id`),
+ CONSTRAINT `fk_t1_2` FOREIGN KEY (`id3`) REFERENCES `t1` (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+alter table t1 change id id4 int;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `id4` int(11) NOT NULL,
+ `id3` int(11) DEFAULT NULL,
+ PRIMARY KEY (`id4`),
+ KEY `fk_t1_2` (`id3`),
+ CONSTRAINT `fk_t1` FOREIGN KEY (`id3`) REFERENCES `t1` (`id4`),
+ CONSTRAINT `fk_t1_2` FOREIGN KEY (`id3`) REFERENCES `t1` (`id4`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+check tables t1;
+Table Op Msg_type Msg_text
+test.t1 check Note Found 2 self-references
+test.t1 check status OK
+flush tables t1;
+check tables t1;
+Table Op Msg_type Msg_text
+test.t1 check Note Found 2 self-references
+test.t1 check status OK
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `id4` int(11) NOT NULL,
+ `id3` int(11) DEFAULT NULL,
+ PRIMARY KEY (`id4`),
+ KEY `fk_t1_2` (`id3`),
+ CONSTRAINT `fk_t1` FOREIGN KEY (`id3`) REFERENCES `t1` (`id4`),
+ CONSTRAINT `fk_t1_2` FOREIGN KEY (`id3`) REFERENCES `t1` (`id4`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+alter table t1 drop foreign key fk_t1;
+check tables t1;
+Table Op Msg_type Msg_text
+test.t1 check Note Found 1 self-references
+test.t1 check status OK
+flush tables t1;
+check tables t1;
+Table Op Msg_type Msg_text
+test.t1 check Note Found 1 self-references
+test.t1 check status OK
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `id4` int(11) NOT NULL,
+ `id3` int(11) DEFAULT NULL,
+ PRIMARY KEY (`id4`),
+ KEY `fk_t1_2` (`id3`),
+ CONSTRAINT `fk_t1_2` FOREIGN KEY (`id3`) REFERENCES `t1` (`id4`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+rename table t1 to t2;
+check tables t2;
+Table Op Msg_type Msg_text
+test.t2 check Note Found 1 self-references
+test.t2 check status OK
+flush tables t2;
+check tables t2;
+Table Op Msg_type Msg_text
+test.t2 check Note Found 1 self-references
+test.t2 check status OK
+show create table t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `id4` int(11) NOT NULL,
+ `id3` int(11) DEFAULT NULL,
+ PRIMARY KEY (`id4`),
+ KEY `fk_t1_2` (`id3`),
+ CONSTRAINT `fk_t1_2` FOREIGN KEY (`id3`) REFERENCES `t2` (`id4`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+delete from t2;
+ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `fk_t1_2` FOREIGN KEY (`id3`) REFERENCES `t2` (`id4`))
+drop table t2;
+set default_storage_engine= default;
+# Prohibit wrong references and fix field name case
+create table t1 (A int unique key, x timestamp references t1(a));
+ERROR 42000: Incorrect foreign key definition for 'x': foreign-referenced fields type mismatch
+create table t1 (A int unique key, x int references t1(b));
+ERROR 42000: Incorrect foreign key definition for 'b': referenced field not found
+create table t1 (A int unique key, x int references t1(a));
+alter table t1 add foreign key(x) references t1(b);
+ERROR 42000: Incorrect foreign key definition for 'b': referenced field not found
+alter table t1 add foreign key(x) references t1(a);
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `A` int(11) DEFAULT NULL,
+ `x` int(11) DEFAULT NULL,
+ UNIQUE KEY `A` (`A`),
+ KEY `fk_t1_2` (`x`),
+ CONSTRAINT `fk_t1` FOREIGN KEY (`x`) REFERENCES `t1` (`A`),
+ CONSTRAINT `fk_t1_2` FOREIGN KEY (`x`) REFERENCES `t1` (`A`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+create table t2 (AA int, x int references t1(ax));
+ERROR 42000: Incorrect foreign key definition for 'ax': referenced field not found
+create table t2 (AA int, x timestamp references t1(a));
+ERROR 42000: Incorrect foreign key definition for 'x': foreign-referenced fields type mismatch
+create table t2 (AA int, x int references t1(a));
+alter table t2 add foreign key(aa) references t1(b);
+ERROR 42000: Incorrect foreign key definition for 'b': referenced field not found
+alter table t2 add foreign key(aa) references t1(a);
+show create table t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `AA` int(11) DEFAULT NULL,
+ `x` int(11) DEFAULT NULL,
+ KEY `fk_t2` (`x`),
+ KEY `fk_t2_2` (`AA`),
+ CONSTRAINT `fk_t2` FOREIGN KEY (`x`) REFERENCES `t1` (`A`),
+ CONSTRAINT `fk_t2_2` FOREIGN KEY (`AA`) REFERENCES `t1` (`A`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop tables t2, t1;
+# Foreign keys and partitioning
+create table t1 (x int primary key) partition by hash(x) partitions 3;
+create table t2 (y int references t1(x));
+ERROR HY000: Partitioned tables do not support FOREIGN KEY
+create table t2 (y int);
+alter table t2 add foreign key (y) references t1 (x);
+ERROR HY000: Partitioned tables do not support FOREIGN KEY
+drop tables t2, t1;
+create table t1 (x int primary key);
+create table t2 (y int references t1(x)) partition by hash(x) partitions 3;
+ERROR HY000: Partitioned tables do not support FOREIGN KEY
+create table t2 (y int) partition by hash(y) partitions 3;
+alter table t2 add foreign key (y) references t1 (x);
+ERROR HY000: Partitioned tables do not support FOREIGN KEY
+create or replace table t2 (y int references t1(x));
+alter table t1 partition by hash(x) partitions 3;
+ERROR HY000: Partitioned tables do not support FOREIGN KEY
+alter table t2 partition by hash(y) partitions 3;
+ERROR HY000: Partitioned tables do not support FOREIGN KEY
+drop tables t2, t1;
diff --git a/mysql-test/main/foreign_key.test b/mysql-test/main/foreign_key.test
index 8f42d43718e..5547101cbd3 100644
--- a/mysql-test/main/foreign_key.test
+++ b/mysql-test/main/foreign_key.test
@@ -2,12 +2,20 @@
# Test syntax of foreign keys
#
--- source include/have_innodb.inc
+--source include/have_innodb.inc
+--source include/have_partition.inc
--disable_warnings
drop table if exists t1,t2;
--enable_warnings
+create table t2 (
+ a int unique, c int unique);
+
+create table t3 (
+ a int unique, c int unique, d int unique,
+ r int references t3(d));
+
create table t1 (
a int not null references t2,
b int not null constraint t2_c references t2 (c),
@@ -22,7 +30,11 @@ create table t1 (
create index a on t1 (a);
create unique index b on t1 (a,b);
-drop table t1;
+--error ER_ROW_IS_REFERENCED_2
+drop tables t2;
+--error ER_ROW_IS_REFERENCED_2
+drop tables t3;
+drop tables t1, t2, t3;
# End of 4.1 tests
@@ -141,4 +153,284 @@ DROP TABLE tfk;
DROP TABLE tpk;
+--echo #
+--echo # MDEV-16417 Store Foreign Key metadata outside of InnoDB
+--echo #
+set default_storage_engine= innodb;
+
+--echo # Check create table
+create or replace table t1 (id int primary key);
+create or replace table t2 (id int primary key, foreign key (id) references t1(id));
+select * from t1, t2;
+check tables t1, t2;
+flush tables t1, t2;
+check tables t1, t2;
+drop table t2, t1;
+
+create table t1 (id int primary key);
+create table t2 (id int references t1(id)) select id from t1;
+check tables t1, t2;
+flush tables;
+check tables t1, t2;
+drop table t2, t1;
+
+create database D;
+create table D.T1(id int primary key);
+create table t2(id int primary key, f1 int references D.T1(id));
+select * from D.T1;
+--replace_result d.t1 D.T1
+check table D.T1;
+drop table t2;
+--replace_result d.t1 D.T1
+check table D.T1;
+flush tables;
+--replace_result d.t1 D.T1
+check table D.T1;
+drop table D.T1;
+drop database D;
+
+--echo # Check rename column, lock tables
+create or replace table t1 (id int primary key);
+create or replace table t2 (id int primary key);
+create or replace table t3 (id int primary key);
+create or replace table ch1 (
+ id int, id2 int,
+ foreign key (id) references t1 (id),
+ foreign key (id2) references t2 (id),
+ foreign key (id) references t3 (id));
+select * from t1, t2, t3;
+--connect con1, localhost, root
+lock tables t3 read;
+--connection default
+set @saved_lock_wait_timeout= @@lock_wait_timeout;
+set lock_wait_timeout= 1;
+alter table ch1 change id2 xid2 int;
+--error ER_LOCK_WAIT_TIMEOUT
+alter table ch1 change id xid int;
+set lock_wait_timeout= @saved_lock_wait_timeout;
+--connection con1
+unlock tables;
+--disconnect con1
+--connection default
+alter table ch1 change id xid int;
+select * from ch1;
+check tables t1, t2, t3;
+flush tables t1, t2, t3;
+check tables t1, t2, t3;
+drop tables ch1, t2, t1, t3;
+
+--echo # Rename column on referenced table
+create or replace table t1 (id int primary key);
+create or replace table t2 (id int references t1, id2 int references t1(id));
+select * from t2;
+alter table t1 change id xid int;
+show create table t2;
+select * from t1;
+check table t2;
+flush table t2;
+check table t2;
+alter table t1 rename column xid to yid;
+show create table t2;
+select * from t1;
+check table t2;
+flush table t2;
+check table t2;
+drop tables t2, t1;
+
+--echo # Check rename table
+create or replace table t1 (id int primary key);
+create or replace table t2 (id int references t1);
+select * from t2, t1;
+rename table t2 to t3;
+create table t2 (x int);
+check table t1;
+flush tables t1;
+check table t1;
+drop tables t3, t1, t2;
+
+create or replace table t1 (id int primary key);
+create or replace table t2 (id int primary key);
+create or replace table t3 (id int primary key);
+select * from t1, t2, t3;
+create or replace table t4 (
+ id int primary key, id2 int references t4(id),
+ foreign key (id) references t1 (id),
+ foreign key (id2) references t2 (id),
+ foreign key (id) references t3 (id));
+select * from t4;
+rename table t4 to xt4;
+check tables t1, t2, t3;
+flush tables t1, t2, t3;
+check tables t1, t2, t3;
+alter table xt4 rename to yt4, algorithm=inplace;
+select * from t1, t2, t3;
+check tables t1, t2, t3;
+flush tables t1, t2, t3;
+check tables t1, t2, t3;
+alter table yt4 rename to zt4, algorithm=copy;
+select * from t1, t2, t3;
+check tables t1, t2, t3;
+flush tables t1, t2, t3;
+check tables t1, t2, t3;
+drop tables zt4, t2, t1, t3;
+
+--echo # Rename of referenced table
+create or replace table t1 (id int primary key);
+create or replace table t2 (id int references t1);
+select * from t2;
+rename table t1 to xt1;
+show create table t2;
+select * from xt1;
+check tables t2, xt1;
+flush tables t2, xt1;
+check tables t2, xt1;
+alter table xt1 rename to yt1, algorithm=inplace;
+show create table t2;
+select * from yt1;
+check tables t2, yt1;
+flush tables t2, yt1;
+check tables t2, yt1;
+alter table yt1 rename to t1, algorithm=copy;
+show create table t2;
+select * from t1;
+check tables t2, t1;
+flush tables t2, t1;
+check tables t2, t1;
+drop tables t2, t1;
+
+--echo # Check drop table
+create or replace table t1 (id int primary key);
+create or replace table ch1 (id int, foreign key (id) references t1 (id));
+select * from t1;
+select * from ch1;
+--error ER_ROW_IS_REFERENCED_2
+drop table t1;
+drop tables ch1, t1;
+
+--echo # Check drop database
+create or replace table t1 (id int primary key);
+select * from t1;
+create or replace database test2;
+use test2;
+create or replace table ch1 (
+ id int, id2 int,
+ foreign key (id) references test.t1 (id));
+select * from ch1;
+use test;
+drop database test2;
+check tables t1;
+flush tables t1;
+check tables t1;
+drop tables t1;
+
+--echo # Check add foreign key
+create or replace table t1(fld1 int not null primary key);
+create or replace table t2(fld1 int not null, fld2 int as (fld1) virtual);
+insert into t1 values(1);
+insert into t2 values(1, default);
+set foreign_key_checks= 0;
+alter table t2 add index(fld2), add foreign key (fld1) references t1(fld1)
+ on update cascade, algorithm=inplace;
+set foreign_key_checks= 1;
+update t1 set fld1= 2;
+select fld2 from t2;
+select * from t2;
+drop table t2, t1;
+
+--echo # Check drop column, drop foreign key
+create or replace table t1 (id int primary key, a int);
+create or replace table t2 (id int, a int, foreign key fk (id) references t1 (id));
+--error ER_FK_COLUMN_CANNOT_DROP_CHILD
+alter table t1 drop id;
+--error ER_WRONG_FK_DEF
+alter table t2 drop id;
+alter table t2 drop foreign key fk;
+drop tables t1, t2;
+
+--echo # Check self-references
+create or replace table t1 (id int primary key, id2 int references t1 (id));
+check tables t1;
+flush tables t1;
+check tables t1;
+show create table t1;
+--error ER_NO_REFERENCED_ROW_2
+insert into t1 values (1, 2);
+insert into t1 values (1, 1);
+alter table t1 change id2 id3 int;
+check tables t1;
+flush tables t1;
+check tables t1;
+show create table t1;
+alter table t1 add foreign key (id3) references t1 (id);
+check tables t1;
+flush tables t1;
+check tables t1;
+show create table t1;
+alter table t1 change id id4 int;
+show create table t1;
+check tables t1;
+flush tables t1;
+check tables t1;
+show create table t1;
+alter table t1 drop foreign key fk_t1;
+check tables t1;
+flush tables t1;
+check tables t1;
+show create table t1;
+rename table t1 to t2;
+check tables t2;
+flush tables t2;
+check tables t2;
+show create table t2;
+# TODO: actually this should succeed (it fails in upstream too)
+--error ER_ROW_IS_REFERENCED_2
+delete from t2;
+drop table t2;
+
+set default_storage_engine= default;
+
+--echo # Prohibit wrong references and fix field name case
+--error ER_WRONG_FK_DEF
+create table t1 (A int unique key, x timestamp references t1(a));
+--error ER_WRONG_FK_DEF
+create table t1 (A int unique key, x int references t1(b));
+create table t1 (A int unique key, x int references t1(a));
+--error ER_WRONG_FK_DEF
+alter table t1 add foreign key(x) references t1(b);
+alter table t1 add foreign key(x) references t1(a);
+
+show create table t1;
+--error ER_WRONG_FK_DEF
+create table t2 (AA int, x int references t1(ax));
+--error ER_WRONG_FK_DEF
+create table t2 (AA int, x timestamp references t1(a));
+
+create table t2 (AA int, x int references t1(a));
+
+--error ER_WRONG_FK_DEF
+alter table t2 add foreign key(aa) references t1(b);
+alter table t2 add foreign key(aa) references t1(a);
+
+show create table t2;
+drop tables t2, t1;
+--echo # Foreign keys and partitioning
+create table t1 (x int primary key) partition by hash(x) partitions 3;
+--error ER_FEATURE_NOT_SUPPORTED_WITH_PARTITIONING
+create table t2 (y int references t1(x));
+create table t2 (y int);
+--error ER_FEATURE_NOT_SUPPORTED_WITH_PARTITIONING
+alter table t2 add foreign key (y) references t1 (x);
+drop tables t2, t1;
+create table t1 (x int primary key);
+--error ER_FEATURE_NOT_SUPPORTED_WITH_PARTITIONING
+create table t2 (y int references t1(x)) partition by hash(x) partitions 3;
+create table t2 (y int) partition by hash(y) partitions 3;
+--error ER_FEATURE_NOT_SUPPORTED_WITH_PARTITIONING
+alter table t2 add foreign key (y) references t1 (x);
+create or replace table t2 (y int references t1(x));
+--error ER_FEATURE_NOT_SUPPORTED_WITH_PARTITIONING
+alter table t1 partition by hash(x) partitions 3;
+--error ER_FEATURE_NOT_SUPPORTED_WITH_PARTITIONING
+alter table t2 partition by hash(y) partitions 3;
+drop tables t2, t1;
diff --git a/mysql-test/main/func_rollback.result b/mysql-test/main/func_rollback.result
index 91151302a06..8df7a4898f8 100644
--- a/mysql-test/main/func_rollback.result
+++ b/mysql-test/main/func_rollback.result
@@ -446,7 +446,7 @@ INSERT INTO t1_child SET f1 = 2, f2 = 2;
RETURN 1;
END//
SELECT f1_two_inserts();
-ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test`.`t1_child`, CONSTRAINT `t1_child_ibfk_1` FOREIGN KEY (`f1`) REFERENCES `t1_parent` (`f1`))
+ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test`.`t1_child`, CONSTRAINT `fk_t1_child` FOREIGN KEY (`f1`) REFERENCES `t1_parent` (`f1`))
SELECT * FROM t1_child;
f1 f2
DROP TABLE t1_child;
diff --git a/mysql-test/main/information_schema_inno.result b/mysql-test/main/information_schema_inno.result
index d952e4372ca..c5b5dd5fae6 100644
--- a/mysql-test/main/information_schema_inno.result
+++ b/mysql-test/main/information_schema_inno.result
@@ -11,19 +11,19 @@ CONSTRAINT_CATALOG CONSTRAINT_SCHEMA CONSTRAINT_NAME TABLE_SCHEMA TABLE_NAME CON
def test PRIMARY test t1 PRIMARY KEY
def test PRIMARY test t2 PRIMARY KEY
def test PRIMARY test t3 PRIMARY KEY
-def test t2_ibfk_1 test t2 FOREIGN KEY
-def test t2_ibfk_2 test t2 FOREIGN KEY
-def test t3_ibfk_1 test t3 FOREIGN KEY
+def test fk_t2 test t2 FOREIGN KEY
+def test fk_t2_2 test t2 FOREIGN KEY
+def test fk_t3 test t3 FOREIGN KEY
select * from information_schema.KEY_COLUMN_USAGE where
TABLE_SCHEMA= "test";
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
def test PRIMARY def test t1 id 1 NULL NULL NULL NULL
def test PRIMARY def test t2 id 1 NULL NULL NULL NULL
def test PRIMARY def test t3 id 1 NULL NULL NULL NULL
-def test t2_ibfk_1 def test t2 t1_id 1 1 test t1 id
-def test t2_ibfk_2 def test t2 t1_id 1 1 test t1 id
-def test t3_ibfk_1 def test t3 id 1 1 test t2 t1_id
-def test t3_ibfk_1 def test t3 t2_id 2 2 test t2 id
+def test fk_t2 def test t2 t1_id 1 1 test t1 id
+def test fk_t2_2 def test t2 t1_id 1 1 test t1 id
+def test fk_t3 def test t3 id 1 1 test t2 t1_id
+def test fk_t3 def test t3 t2_id 2 2 test t2 id
drop table t3, t2, t1;
CREATE TABLE t1(a1 INT NOT NULL, a2 INT NOT NULL,
PRIMARY KEY(a1, a2)) ENGINE=INNODB;
@@ -51,10 +51,10 @@ information_schema.REFERENTIAL_CONSTRAINTS b
where a.CONSTRAINT_SCHEMA = 'test' and a.CONSTRAINT_SCHEMA = b.CONSTRAINT_SCHEMA and
a.CONSTRAINT_NAME = b.CONSTRAINT_NAME;
CONSTRAINT_SCHEMA TABLE_NAME CONSTRAINT_TYPE CONSTRAINT_NAME UNIQUE_CONSTRAINT_SCHEMA UNIQUE_CONSTRAINT_NAME MATCH_OPTION UPDATE_RULE DELETE_RULE REFERENCED_TABLE_NAME
-test t2 FOREIGN KEY A1 test PRIMARY NONE CASCADE NO ACTION t1
-test t3 FOREIGN KEY A2 test b1 NONE SET NULL RESTRICT t2
-test t4 FOREIGN KEY A3 test t3_indx NONE NO ACTION SET NULL t3
-test t5 FOREIGN KEY A4 test t4_ukey NONE RESTRICT CASCADE t4
+test t2 FOREIGN KEY A1 test A1 NONE CASCADE NO ACTION t1
+test t3 FOREIGN KEY A2 test A2 NONE SET NULL RESTRICT t2
+test t4 FOREIGN KEY A3 test A3 NONE NO ACTION SET NULL t3
+test t5 FOREIGN KEY A4 test A4 NONE RESTRICT CASCADE t4
drop tables t5, t4, t3, t2, t1;
create database `db-1`;
use `db-1`;
@@ -87,7 +87,7 @@ select UNIQUE_CONSTRAINT_NAME
from information_schema.referential_constraints
where constraint_schema = schema();
UNIQUE_CONSTRAINT_NAME
-NULL
+fk_t2
drop table t2;
set foreign_key_checks = 1;
#
diff --git a/mysql-test/main/insert_innodb.result b/mysql-test/main/insert_innodb.result
index e5e2b4b8623..f82c70998af 100644
--- a/mysql-test/main/insert_innodb.result
+++ b/mysql-test/main/insert_innodb.result
@@ -10,7 +10,7 @@ INSERT INTO t2 VALUES(0);
# Without fix, an error is reported.
INSERT IGNORE INTO t2 VALUES(1);
Warnings:
-Warning 1452 Cannot add or update a child row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`fld2`) REFERENCES `t1` (`fld1`))
+Warning 1452 Cannot add or update a child row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `fk_t2` FOREIGN KEY (`fld2`) REFERENCES `t1` (`fld1`))
UPDATE IGNORE t2 SET fld2=20 WHERE fld2=0;
UPDATE IGNORE t1 SET fld1=20 WHERE fld1=0;
# Test for multi update.
@@ -18,15 +18,15 @@ UPDATE IGNORE t1, t2 SET t2.fld2= t2.fld2 + 3;
UPDATE IGNORE t1, t2 SET t1.fld1= t1.fld1 + 3;
# Reports an error since IGNORE is not used.
INSERT INTO t2 VALUES(1);
-ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`fld2`) REFERENCES `t1` (`fld1`))
+ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `fk_t2` FOREIGN KEY (`fld2`) REFERENCES `t1` (`fld1`))
UPDATE t2 SET fld2=20 WHERE fld2=0;
-ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`fld2`) REFERENCES `t1` (`fld1`))
+ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `fk_t2` FOREIGN KEY (`fld2`) REFERENCES `t1` (`fld1`))
UPDATE t1 SET fld1=20 WHERE fld1=0;
-ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`fld2`) REFERENCES `t1` (`fld1`))
+ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `fk_t2` FOREIGN KEY (`fld2`) REFERENCES `t1` (`fld1`))
UPDATE t1, t2 SET t2.fld2= t2.fld2 + 3;
-ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`fld2`) REFERENCES `t1` (`fld1`))
+ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `fk_t2` FOREIGN KEY (`fld2`) REFERENCES `t1` (`fld1`))
UPDATE t1, t2 SET t1.fld1= t1.fld1 + 3;
-ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`fld2`) REFERENCES `t1` (`fld1`))
+ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `fk_t2` FOREIGN KEY (`fld2`) REFERENCES `t1` (`fld1`))
DROP TABLE t2, t1;
#
# BUG#22037930: INSERT IGNORE FAILS TO IGNORE FOREIGN
diff --git a/mysql-test/main/insert_notembedded.result b/mysql-test/main/insert_notembedded.result
index 8dd4aa7d71e..71749864a48 100644
--- a/mysql-test/main/insert_notembedded.result
+++ b/mysql-test/main/insert_notembedded.result
@@ -15,10 +15,10 @@ CREATE TABLE table_target2 ( mexs_id CHAR(8), messzeit TIMESTAMP, PRIMARY KEY (
CREATE TABLE table_target3 ( mexs_id CHAR(8), messzeit TIMESTAMP, PRIMARY KEY (mexs_id));
CREATE VIEW view_target2 AS SELECT mexs_id,messzeit FROM table_target2;
CREATE SQL SECURITY INVOKER VIEW view_target3 AS SELECT mexs_id,messzeit FROM table_target3;
-CREATE TABLE table_stations ( mexs_id VARCHAR(8), icao VARCHAR(4), country CHAR(2), PRIMARY KEY (mexs_id), UNIQUE KEY icao (icao), KEY country (country), CONSTRAINT stations_ibfk_8 FOREIGN KEY (country) REFERENCES countries (country) ON UPDATE CASCADE);
-INSERT INTO table_stations VALUES ('87654321','XXXX','YY');
CREATE TABLE table_countries ( country CHAR(2), iso_short_en VARCHAR(64), PRIMARY KEY (country));
INSERT INTO table_countries VALUES ('YY','Entenhausen');
+CREATE TABLE table_stations ( mexs_id VARCHAR(8), icao VARCHAR(4), country CHAR(2), PRIMARY KEY (mexs_id), UNIQUE KEY icao (icao), KEY country (country), CONSTRAINT stations_ibfk_8 FOREIGN KEY (country) REFERENCES table_countries (country) ON UPDATE CASCADE);
+INSERT INTO table_stations VALUES ('87654321','XXXX','YY');
CREATE ALGORITHM=MERGE SQL SECURITY INVOKER VIEW view_stations AS select table_stations.mexs_id AS mexs_id, table_stations.icao AS icao, table_stations.country AS landescode from (table_stations join table_countries on((table_stations.country = table_countries.country)));
CREATE TABLE table_source ( id varchar(4), datetime TIMESTAMP, PRIMARY KEY (id));
INSERT INTO table_source VALUES ('XXXX','2006-07-12 07:50:00');
@@ -108,8 +108,8 @@ mexs_id messzeit
87654321 2006-07-12 07:50:00
DROP VIEW view_stations;
DROP TABLE table_source;
-DROP TABLE table_countries;
DROP TABLE table_stations;
+DROP TABLE table_countries;
DROP TABLE table_target;
DROP TABLE table_target2;
DROP TABLE table_target3;
diff --git a/mysql-test/main/insert_notembedded.test b/mysql-test/main/insert_notembedded.test
index 2769aee8d8a..1e8cd43cc36 100644
--- a/mysql-test/main/insert_notembedded.test
+++ b/mysql-test/main/insert_notembedded.test
@@ -38,12 +38,12 @@ CREATE TABLE table_target3 ( mexs_id CHAR(8), messzeit TIMESTAMP, PRIMARY KEY (
CREATE VIEW view_target2 AS SELECT mexs_id,messzeit FROM table_target2;
CREATE SQL SECURITY INVOKER VIEW view_target3 AS SELECT mexs_id,messzeit FROM table_target3;
-CREATE TABLE table_stations ( mexs_id VARCHAR(8), icao VARCHAR(4), country CHAR(2), PRIMARY KEY (mexs_id), UNIQUE KEY icao (icao), KEY country (country), CONSTRAINT stations_ibfk_8 FOREIGN KEY (country) REFERENCES countries (country) ON UPDATE CASCADE);
-INSERT INTO table_stations VALUES ('87654321','XXXX','YY');
-
CREATE TABLE table_countries ( country CHAR(2), iso_short_en VARCHAR(64), PRIMARY KEY (country));
INSERT INTO table_countries VALUES ('YY','Entenhausen');
+CREATE TABLE table_stations ( mexs_id VARCHAR(8), icao VARCHAR(4), country CHAR(2), PRIMARY KEY (mexs_id), UNIQUE KEY icao (icao), KEY country (country), CONSTRAINT stations_ibfk_8 FOREIGN KEY (country) REFERENCES table_countries (country) ON UPDATE CASCADE);
+INSERT INTO table_stations VALUES ('87654321','XXXX','YY');
+
CREATE ALGORITHM=MERGE SQL SECURITY INVOKER VIEW view_stations AS select table_stations.mexs_id AS mexs_id, table_stations.icao AS icao, table_stations.country AS landescode from (table_stations join table_countries on((table_stations.country = table_countries.country)));
CREATE TABLE table_source ( id varchar(4), datetime TIMESTAMP, PRIMARY KEY (id));
@@ -141,8 +141,8 @@ SELECT * FROM view_target3;
DROP VIEW view_stations;
DROP TABLE table_source;
-DROP TABLE table_countries;
DROP TABLE table_stations;
+DROP TABLE table_countries;
DROP TABLE table_target;
DROP TABLE table_target2;
DROP TABLE table_target3;
diff --git a/mysql-test/main/invisible_field.result b/mysql-test/main/invisible_field.result
index 9b42b043ec6..f8c7f2b1ec1 100644
--- a/mysql-test/main/invisible_field.result
+++ b/mysql-test/main/invisible_field.result
@@ -444,7 +444,7 @@ d int(11) YES UNI NULL
drop table t1;
SHOW STATUS LIKE 'Feature_invisible_columns';
Variable_name Value
-Feature_invisible_columns 52
+Feature_invisible_columns 54
#invisible is non reserved
create table t1(a int unique , invisible int invisible, c int );
desc t1;
diff --git a/mysql-test/main/join_outer_innodb.result b/mysql-test/main/join_outer_innodb.result
index 0b34a399d77..575862e886b 100644
--- a/mysql-test/main/join_outer_innodb.result
+++ b/mysql-test/main/join_outer_innodb.result
@@ -9,13 +9,13 @@ SELECT COUNT(*) FROM t2 LEFT JOIN t1 ON t2.fkey = t1.id
WHERE t1.name LIKE 'A%';
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range PRIMARY,name name 23 NULL 2 Using where; Using index
-1 SIMPLE t2 ref fkey fkey 5 test.t1.id 1 Using index
+1 SIMPLE t2 ref fk_t2 fk_t2 5 test.t1.id 1 Using index
EXPLAIN
SELECT COUNT(*) FROM t2 LEFT JOIN t1 ON t2.fkey = t1.id
WHERE t1.name LIKE 'A%' OR FALSE;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range PRIMARY,name name 23 NULL 2 Using where; Using index
-1 SIMPLE t2 ref fkey fkey 5 test.t1.id 1 Using index
+1 SIMPLE t2 ref fk_t2 fk_t2 5 test.t1.id 1 Using index
DROP TABLE t1,t2;
#
# BUG#58456: Assertion 0 in QUICK_INDEX_MERGE_SELECT::need_sorted_output
diff --git a/mysql-test/main/multi_update.result b/mysql-test/main/multi_update.result
index d792b2828b8..1ca1f95c69a 100644
--- a/mysql-test/main/multi_update.result
+++ b/mysql-test/main/multi_update.result
@@ -124,7 +124,7 @@ ID ParId tst tst1
1 1 MySQL MySQL AB
2 2 MSSQL Microsoft
3 3 ORACLE ORACLE
-drop table t1, t2 ;
+drop table t2, t1;
create table t1 (n numeric(10));
create table t2 (n numeric(10));
insert into t2 values (1),(2),(4),(8),(16),(32);
diff --git a/mysql-test/main/multi_update.test b/mysql-test/main/multi_update.test
index 8a32f626818..c6796cf7151 100644
--- a/mysql-test/main/multi_update.test
+++ b/mysql-test/main/multi_update.test
@@ -131,7 +131,7 @@ select * from t2;
UPDATE t2, t1 SET t2.tst = t1.tst, t2.tst1 = t1.tst1 WHERE t2.ParId = t1.Id;
select * from t2;
-drop table t1, t2 ;
+drop table t2, t1;
create table t1 (n numeric(10));
create table t2 (n numeric(10));
diff --git a/mysql-test/main/mysqlcheck.result b/mysql-test/main/mysqlcheck.result
index bace4f0ef3a..34e3d371dc7 100644
--- a/mysql-test/main/mysqlcheck.result
+++ b/mysql-test/main/mysqlcheck.result
@@ -440,9 +440,15 @@ mysql.func Table is already up to date
mysql.global_priv Table is already up to date
mysql.gtid_slave_pos Table is already up to date
mysql.help_category Table is already up to date
-mysql.help_keyword Table is already up to date
-mysql.help_relation Table is already up to date
-mysql.help_topic Table is already up to date
+mysql.help_keyword
+Note : Found 1 referenced keys
+status : Table is already up to date
+mysql.help_relation
+Note : Found 2 foreign keys
+status : Table is already up to date
+mysql.help_topic
+Note : Found 1 referenced keys
+status : Table is already up to date
mysql.index_stats Table is already up to date
mysql.innodb_index_stats OK
mysql.innodb_table_stats OK
@@ -468,6 +474,9 @@ error : Corrupt
test.t2 Table is already up to date
Repairing tables
+mysql.help_keyword OK
+mysql.help_relation OK
+mysql.help_topic OK
mysqltest1.t1 OK
drop table t2;
drop database mysqltest1;
diff --git a/mysql-test/main/mysqld--help-aria.test b/mysql-test/main/mysqld--help-aria.test
index 253a46492f0..9f0288c381d 100644
--- a/mysql-test/main/mysqld--help-aria.test
+++ b/mysql-test/main/mysqld--help-aria.test
@@ -29,7 +29,7 @@
--exec $MYSQLD_CMD $args --datadir=$MYSQL_TMP_DIR/help > $MYSQL_TMP_DIR/mysqld--help2.txt 2> $MYSQL_TMP_DIR/mysqld--help2.err
--replace_regex /\d\d\d\d-\d*-\d* *\d*:\d*:\d* \d* //
--cat_file $MYSQL_TMP_DIR/mysqld--help2.err
---list_files $MYSQL_TMP_DIR/help
+--list_files $MYSQL_TMP_DIR/help !(gmon.out)
#
# Cleanup
diff --git a/mysql-test/main/profiling.result b/mysql-test/main/profiling.result
index f1403c3ec2f..abd49190608 100644
--- a/mysql-test/main/profiling.result
+++ b/mysql-test/main/profiling.result
@@ -411,7 +411,7 @@ commit;
select @@profiling;
@@profiling
1
-drop table if exists t1, t2, t3;
+drop table if exists t2, t1, t3;
drop view if exists v1;
Warnings:
Note 4092 Unknown VIEW: 'test.v1'
diff --git a/mysql-test/main/profiling.test b/mysql-test/main/profiling.test
index 912e4f69798..73846c1d028 100644
--- a/mysql-test/main/profiling.test
+++ b/mysql-test/main/profiling.test
@@ -248,7 +248,7 @@ select @@profiling;
commit;
select @@profiling;
-drop table if exists t1, t2, t3;
+drop table if exists t2, t1, t3;
drop view if exists v1;
drop function if exists f1;
diff --git a/mysql-test/main/ps.result b/mysql-test/main/ps.result
index d97720c2d41..a431447e805 100644
--- a/mysql-test/main/ps.result
+++ b/mysql-test/main/ps.result
@@ -589,7 +589,7 @@ select t2.id from t2, t1 where (t1.id=1 and t2.t1_id=t1.id);
id
3
deallocate prepare stmt;
-drop table t1, t2;
+drop table t2, t1;
create table t1 (id int);
prepare stmt from "insert into t1 (id) select id from t1 union select id from t1";
execute stmt;
diff --git a/mysql-test/main/ps.test b/mysql-test/main/ps.test
index e702cb76bbb..eca44085049 100644
--- a/mysql-test/main/ps.test
+++ b/mysql-test/main/ps.test
@@ -638,7 +638,7 @@ execute stmt using @a;
select t2.id from t2, t1 where (t1.id=1 and t2.t1_id=t1.id);
deallocate prepare stmt;
-drop table t1, t2;
+drop table t2, t1;
#
# Bug#11060 "Server crashes on calling stored procedure with INSERT SELECT
diff --git a/mysql-test/main/query_cache_innodb.result b/mysql-test/main/query_cache_innodb.result
index 62424ac362b..0163e9ed615 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 4 /\[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/subselect.result b/mysql-test/main/subselect.result
index 1ee4718ef10..1e0dce03b02 100644
--- a/mysql-test/main/subselect.result
+++ b/mysql-test/main/subselect.result
@@ -3854,7 +3854,7 @@ FROM (SELECT a, b, (SELECT x FROM t2 WHERE y=b ORDER BY z DESC LIMIT 1) c
FROM t1) t;
COUNT(*)
3000
-DROP TABLE t1,t2,t3;
+DROP TABLE t2, t1, t3;
CREATE TABLE t1 (id char(4) PRIMARY KEY, c int);
CREATE TABLE t2 (c int);
INSERT INTO t1 VALUES ('aa', 1);
diff --git a/mysql-test/main/subselect.test b/mysql-test/main/subselect.test
index f6333c22684..7d5f22af078 100644
--- a/mysql-test/main/subselect.test
+++ b/mysql-test/main/subselect.test
@@ -2703,7 +2703,7 @@ SELECT SQL_NO_CACHE COUNT(*)
FROM (SELECT a, b, (SELECT x FROM t2 WHERE y=b ORDER BY z DESC LIMIT 1) c
FROM t1) t;
-DROP TABLE t1,t2,t3;
+DROP TABLE t2, t1, t3;
#
# Bug#25219 EXIST subquery with UNION over a mix of
diff --git a/mysql-test/main/subselect_no_exists_to_in.result b/mysql-test/main/subselect_no_exists_to_in.result
index 1436f98d9f8..50539dffa95 100644
--- a/mysql-test/main/subselect_no_exists_to_in.result
+++ b/mysql-test/main/subselect_no_exists_to_in.result
@@ -3857,7 +3857,7 @@ FROM (SELECT a, b, (SELECT x FROM t2 WHERE y=b ORDER BY z DESC LIMIT 1) c
FROM t1) t;
COUNT(*)
3000
-DROP TABLE t1,t2,t3;
+DROP TABLE t2, t1, t3;
CREATE TABLE t1 (id char(4) PRIMARY KEY, c int);
CREATE TABLE t2 (c int);
INSERT INTO t1 VALUES ('aa', 1);
diff --git a/mysql-test/main/subselect_no_mat.result b/mysql-test/main/subselect_no_mat.result
index 8100c1da7e5..f1b9c264e54 100644
--- a/mysql-test/main/subselect_no_mat.result
+++ b/mysql-test/main/subselect_no_mat.result
@@ -3857,7 +3857,7 @@ FROM (SELECT a, b, (SELECT x FROM t2 WHERE y=b ORDER BY z DESC LIMIT 1) c
FROM t1) t;
COUNT(*)
3000
-DROP TABLE t1,t2,t3;
+DROP TABLE t2, t1, t3;
CREATE TABLE t1 (id char(4) PRIMARY KEY, c int);
CREATE TABLE t2 (c int);
INSERT INTO t1 VALUES ('aa', 1);
diff --git a/mysql-test/main/subselect_no_opts.result b/mysql-test/main/subselect_no_opts.result
index 86c89f9bd5f..fb5cf97d3f8 100644
--- a/mysql-test/main/subselect_no_opts.result
+++ b/mysql-test/main/subselect_no_opts.result
@@ -3853,7 +3853,7 @@ FROM (SELECT a, b, (SELECT x FROM t2 WHERE y=b ORDER BY z DESC LIMIT 1) c
FROM t1) t;
COUNT(*)
3000
-DROP TABLE t1,t2,t3;
+DROP TABLE t2, t1, t3;
CREATE TABLE t1 (id char(4) PRIMARY KEY, c int);
CREATE TABLE t2 (c int);
INSERT INTO t1 VALUES ('aa', 1);
diff --git a/mysql-test/main/subselect_no_scache.result b/mysql-test/main/subselect_no_scache.result
index 5dc8040698f..173c7db17b7 100644
--- a/mysql-test/main/subselect_no_scache.result
+++ b/mysql-test/main/subselect_no_scache.result
@@ -3860,7 +3860,7 @@ FROM (SELECT a, b, (SELECT x FROM t2 WHERE y=b ORDER BY z DESC LIMIT 1) c
FROM t1) t;
COUNT(*)
3000
-DROP TABLE t1,t2,t3;
+DROP TABLE t2, t1, t3;
CREATE TABLE t1 (id char(4) PRIMARY KEY, c int);
CREATE TABLE t2 (c int);
INSERT INTO t1 VALUES ('aa', 1);
diff --git a/mysql-test/main/subselect_no_semijoin.result b/mysql-test/main/subselect_no_semijoin.result
index f9bbf2e00c4..693d4e50147 100644
--- a/mysql-test/main/subselect_no_semijoin.result
+++ b/mysql-test/main/subselect_no_semijoin.result
@@ -3853,7 +3853,7 @@ FROM (SELECT a, b, (SELECT x FROM t2 WHERE y=b ORDER BY z DESC LIMIT 1) c
FROM t1) t;
COUNT(*)
3000
-DROP TABLE t1,t2,t3;
+DROP TABLE t2, t1, t3;
CREATE TABLE t1 (id char(4) PRIMARY KEY, c int);
CREATE TABLE t2 (c int);
INSERT INTO t1 VALUES ('aa', 1);
diff --git a/mysql-test/main/system_mysql_db_fix40123.result b/mysql-test/main/system_mysql_db_fix40123.result
index a876e71bdff..66994e736b6 100644
--- a/mysql-test/main/system_mysql_db_fix40123.result
+++ b/mysql-test/main/system_mysql_db_fix40123.result
@@ -18,8 +18,8 @@ CREATE TABLE tables_priv ( Host char(60) binary DEFAULT '' NOT NULL, Db char(64)
CREATE TABLE columns_priv ( Host char(60) binary DEFAULT '' NOT NULL, Db char(64) binary DEFAULT '' NOT NULL, User char(16) binary DEFAULT '' NOT NULL, Table_name char(64) binary DEFAULT '' NOT NULL, Column_name char(64) binary DEFAULT '' NOT NULL, Timestamp timestamp, Column_priv set('Select','Insert','Update','References') COLLATE utf8_general_ci DEFAULT '' NOT NULL, PRIMARY KEY (Host,Db,User,Table_name,Column_name) ) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Column privileges';
CREATE TABLE help_topic ( help_topic_id int unsigned not null, name varchar(64) not null, help_category_id smallint unsigned not null, description text not null, example text not null, url varchar(128) not null, primary key (help_topic_id), unique index (name) ) engine=MyISAM CHARACTER SET utf8 comment='help topics';
CREATE TABLE help_category ( help_category_id smallint unsigned not null, name varchar(64) not null, parent_category_id smallint unsigned null, url varchar(128) not null, primary key (help_category_id), unique index (name) ) engine=MyISAM CHARACTER SET utf8 comment='help categories';
-CREATE TABLE help_relation ( help_topic_id int unsigned not null references help_topic, help_keyword_id int unsigned not null references help_keyword, primary key (help_keyword_id, help_topic_id) ) engine=MyISAM CHARACTER SET utf8 comment='keyword-topic relation';
CREATE TABLE help_keyword ( help_keyword_id int unsigned not null, name varchar(64) not null, primary key (help_keyword_id), unique index (name) ) engine=MyISAM CHARACTER SET utf8 comment='help keywords';
+CREATE TABLE help_relation ( help_topic_id int unsigned not null references help_topic, help_keyword_id int unsigned not null references help_keyword, primary key (help_keyword_id, help_topic_id) ) engine=MyISAM CHARACTER SET utf8 comment='keyword-topic relation';
CREATE TABLE time_zone_name ( Name char(64) NOT NULL, Time_zone_id int unsigned NOT NULL, PRIMARY KEY Name (Name) ) engine=MyISAM CHARACTER SET utf8 comment='Time zone names';
Warnings:
Warning 1280 Name 'Name' ignored for PRIMARY key.
@@ -287,6 +287,6 @@ index_stats CREATE TABLE `index_stats` (
PRIMARY KEY (`db_name`,`table_name`,`index_name`,`prefix_arity`)
) ENGINE=Aria DEFAULT CHARSET=utf8 COLLATE=utf8_bin PAGE_CHECKSUM=1 TRANSACTIONAL=0 COMMENT='Statistics on Indexes'
DROP VIEW user;
-DROP TABLE db, host, func, plugin, tables_priv, columns_priv, procs_priv, servers, help_category, help_keyword, help_relation, help_topic, proc, time_zone, time_zone_leap_second, time_zone_name, time_zone_transition, time_zone_transition_type, general_log, slow_log, event, proxies_priv, innodb_index_stats, innodb_table_stats, transaction_registry, table_stats, column_stats, index_stats, roles_mapping, gtid_slave_pos, global_priv;
+DROP TABLE db, host, func, plugin, tables_priv, columns_priv, procs_priv, servers, help_category, help_relation, help_keyword, help_topic, proc, time_zone, time_zone_leap_second, time_zone_name, time_zone_transition, time_zone_transition_type, general_log, slow_log, event, proxies_priv, innodb_index_stats, innodb_table_stats, transaction_registry, table_stats, column_stats, index_stats, roles_mapping, gtid_slave_pos, global_priv;
show tables;
Tables_in_test
diff --git a/mysql-test/main/system_mysql_db_fix40123.test b/mysql-test/main/system_mysql_db_fix40123.test
index 2e7ebd151d2..12288e2f0e1 100644
--- a/mysql-test/main/system_mysql_db_fix40123.test
+++ b/mysql-test/main/system_mysql_db_fix40123.test
@@ -37,8 +37,8 @@ CREATE TABLE tables_priv ( Host char(60) binary DEFAULT '' NOT NULL, Db char(64)
CREATE TABLE columns_priv ( Host char(60) binary DEFAULT '' NOT NULL, Db char(64) binary DEFAULT '' NOT NULL, User char(16) binary DEFAULT '' NOT NULL, Table_name char(64) binary DEFAULT '' NOT NULL, Column_name char(64) binary DEFAULT '' NOT NULL, Timestamp timestamp, Column_priv set('Select','Insert','Update','References') COLLATE utf8_general_ci DEFAULT '' NOT NULL, PRIMARY KEY (Host,Db,User,Table_name,Column_name) ) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Column privileges';
CREATE TABLE help_topic ( help_topic_id int unsigned not null, name varchar(64) not null, help_category_id smallint unsigned not null, description text not null, example text not null, url varchar(128) not null, primary key (help_topic_id), unique index (name) ) engine=MyISAM CHARACTER SET utf8 comment='help topics';
CREATE TABLE help_category ( help_category_id smallint unsigned not null, name varchar(64) not null, parent_category_id smallint unsigned null, url varchar(128) not null, primary key (help_category_id), unique index (name) ) engine=MyISAM CHARACTER SET utf8 comment='help categories';
-CREATE TABLE help_relation ( help_topic_id int unsigned not null references help_topic, help_keyword_id int unsigned not null references help_keyword, primary key (help_keyword_id, help_topic_id) ) engine=MyISAM CHARACTER SET utf8 comment='keyword-topic relation';
CREATE TABLE help_keyword ( help_keyword_id int unsigned not null, name varchar(64) not null, primary key (help_keyword_id), unique index (name) ) engine=MyISAM CHARACTER SET utf8 comment='help keywords';
+CREATE TABLE help_relation ( help_topic_id int unsigned not null references help_topic, help_keyword_id int unsigned not null references help_keyword, primary key (help_keyword_id, help_topic_id) ) engine=MyISAM CHARACTER SET utf8 comment='keyword-topic relation';
CREATE TABLE time_zone_name ( Name char(64) NOT NULL, Time_zone_id int unsigned NOT NULL, PRIMARY KEY Name (Name) ) engine=MyISAM CHARACTER SET utf8 comment='Time zone names';
CREATE TABLE time_zone ( Time_zone_id int unsigned NOT NULL auto_increment, Use_leap_seconds enum('Y','N') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, PRIMARY KEY TzId (Time_zone_id) ) engine=MyISAM CHARACTER SET utf8 comment='Time zones';
CREATE TABLE time_zone_transition ( Time_zone_id int unsigned NOT NULL, Transition_time bigint signed NOT NULL, Transition_type_id int unsigned NOT NULL, PRIMARY KEY TzIdTranTime (Time_zone_id, Transition_time) ) engine=MyISAM CHARACTER SET utf8 comment='Time zone transitions';
@@ -55,7 +55,7 @@ CREATE TABLE time_zone_leap_second ( Transition_time bigint signed NOT NULL, Cor
# Drop all tables created by this test
DROP VIEW user;
-DROP TABLE db, host, func, plugin, tables_priv, columns_priv, procs_priv, servers, help_category, help_keyword, help_relation, help_topic, proc, time_zone, time_zone_leap_second, time_zone_name, time_zone_transition, time_zone_transition_type, general_log, slow_log, event, proxies_priv, innodb_index_stats, innodb_table_stats, transaction_registry, table_stats, column_stats, index_stats, roles_mapping, gtid_slave_pos, global_priv;
+DROP TABLE db, host, func, plugin, tables_priv, columns_priv, procs_priv, servers, help_category, help_relation, help_keyword, help_topic, proc, time_zone, time_zone_leap_second, time_zone_name, time_zone_transition, time_zone_transition_type, general_log, slow_log, event, proxies_priv, innodb_index_stats, innodb_table_stats, transaction_registry, table_stats, column_stats, index_stats, roles_mapping, gtid_slave_pos, global_priv;
# check that we dropped all system tables
show tables;
diff --git a/mysql-test/main/system_mysql_db_fix50030.result b/mysql-test/main/system_mysql_db_fix50030.result
index 9b21a54e86d..3d75e9259cd 100644
--- a/mysql-test/main/system_mysql_db_fix50030.result
+++ b/mysql-test/main/system_mysql_db_fix50030.result
@@ -18,8 +18,8 @@ CREATE TABLE tables_priv ( Host char(60) binary DEFAULT '' NOT NULL, Db char(64)
CREATE TABLE columns_priv ( Host char(60) binary DEFAULT '' NOT NULL, Db char(64) binary DEFAULT '' NOT NULL, User char(16) binary DEFAULT '' NOT NULL, Table_name char(64) binary DEFAULT '' NOT NULL, Column_name char(64) binary DEFAULT '' NOT NULL, Timestamp timestamp, Column_priv set('Select','Insert','Update','References') COLLATE utf8_general_ci DEFAULT '' NOT NULL, PRIMARY KEY (Host,Db,User,Table_name,Column_name) ) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Column privileges';
CREATE TABLE help_topic ( help_topic_id int unsigned not null, name char(64) not null, help_category_id smallint unsigned not null, description text not null, example text not null, url char(128) not null, primary key (help_topic_id), unique index (name) ) engine=MyISAM CHARACTER SET utf8 comment='help topics';
CREATE TABLE help_category ( help_category_id smallint unsigned not null, name char(64) not null, parent_category_id smallint unsigned null, url char(128) not null, primary key (help_category_id), unique index (name) ) engine=MyISAM CHARACTER SET utf8 comment='help categories';
-CREATE TABLE help_relation ( help_topic_id int unsigned not null references help_topic, help_keyword_id int unsigned not null references help_keyword, primary key (help_keyword_id, help_topic_id) ) engine=MyISAM CHARACTER SET utf8 comment='keyword-topic relation';
CREATE TABLE help_keyword ( help_keyword_id int unsigned not null, name char(64) not null, primary key (help_keyword_id), unique index (name) ) engine=MyISAM CHARACTER SET utf8 comment='help keywords';
+CREATE TABLE help_relation ( help_topic_id int unsigned not null references help_topic, help_keyword_id int unsigned not null references help_keyword, primary key (help_keyword_id, help_topic_id) ) engine=MyISAM CHARACTER SET utf8 comment='keyword-topic relation';
CREATE TABLE time_zone_name ( Name char(64) NOT NULL, Time_zone_id int unsigned NOT NULL, PRIMARY KEY Name (Name) ) engine=MyISAM CHARACTER SET utf8 comment='Time zone names';
Warnings:
Warning 1280 Name 'Name' ignored for PRIMARY key.
@@ -291,6 +291,6 @@ index_stats CREATE TABLE `index_stats` (
PRIMARY KEY (`db_name`,`table_name`,`index_name`,`prefix_arity`)
) ENGINE=Aria DEFAULT CHARSET=utf8 COLLATE=utf8_bin PAGE_CHECKSUM=1 TRANSACTIONAL=0 COMMENT='Statistics on Indexes'
DROP VIEW user;
-DROP TABLE db, host, func, plugin, tables_priv, columns_priv, procs_priv, servers, help_category, help_keyword, help_relation, help_topic, proc, time_zone, time_zone_leap_second, time_zone_name, time_zone_transition, time_zone_transition_type, general_log, slow_log, event, proxies_priv, innodb_index_stats, innodb_table_stats, transaction_registry, table_stats, column_stats, index_stats, roles_mapping, gtid_slave_pos, global_priv;
+DROP TABLE db, host, func, plugin, tables_priv, columns_priv, procs_priv, servers, help_category, help_relation, help_keyword, help_topic, proc, time_zone, time_zone_leap_second, time_zone_name, time_zone_transition, time_zone_transition_type, general_log, slow_log, event, proxies_priv, innodb_index_stats, innodb_table_stats, transaction_registry, table_stats, column_stats, index_stats, roles_mapping, gtid_slave_pos, global_priv;
show tables;
Tables_in_test
diff --git a/mysql-test/main/system_mysql_db_fix50030.test b/mysql-test/main/system_mysql_db_fix50030.test
index 77f1a97b1aa..54a8cfb2f14 100644
--- a/mysql-test/main/system_mysql_db_fix50030.test
+++ b/mysql-test/main/system_mysql_db_fix50030.test
@@ -37,8 +37,8 @@ CREATE TABLE tables_priv ( Host char(60) binary DEFAULT '' NOT NULL, Db char(64)
CREATE TABLE columns_priv ( Host char(60) binary DEFAULT '' NOT NULL, Db char(64) binary DEFAULT '' NOT NULL, User char(16) binary DEFAULT '' NOT NULL, Table_name char(64) binary DEFAULT '' NOT NULL, Column_name char(64) binary DEFAULT '' NOT NULL, Timestamp timestamp, Column_priv set('Select','Insert','Update','References') COLLATE utf8_general_ci DEFAULT '' NOT NULL, PRIMARY KEY (Host,Db,User,Table_name,Column_name) ) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Column privileges';
CREATE TABLE help_topic ( help_topic_id int unsigned not null, name char(64) not null, help_category_id smallint unsigned not null, description text not null, example text not null, url char(128) not null, primary key (help_topic_id), unique index (name) ) engine=MyISAM CHARACTER SET utf8 comment='help topics';
CREATE TABLE help_category ( help_category_id smallint unsigned not null, name char(64) not null, parent_category_id smallint unsigned null, url char(128) not null, primary key (help_category_id), unique index (name) ) engine=MyISAM CHARACTER SET utf8 comment='help categories';
-CREATE TABLE help_relation ( help_topic_id int unsigned not null references help_topic, help_keyword_id int unsigned not null references help_keyword, primary key (help_keyword_id, help_topic_id) ) engine=MyISAM CHARACTER SET utf8 comment='keyword-topic relation';
CREATE TABLE help_keyword ( help_keyword_id int unsigned not null, name char(64) not null, primary key (help_keyword_id), unique index (name) ) engine=MyISAM CHARACTER SET utf8 comment='help keywords';
+CREATE TABLE help_relation ( help_topic_id int unsigned not null references help_topic, help_keyword_id int unsigned not null references help_keyword, primary key (help_keyword_id, help_topic_id) ) engine=MyISAM CHARACTER SET utf8 comment='keyword-topic relation';
CREATE TABLE time_zone_name ( Name char(64) NOT NULL, Time_zone_id int unsigned NOT NULL, PRIMARY KEY Name (Name) ) engine=MyISAM CHARACTER SET utf8 comment='Time zone names';
CREATE TABLE time_zone ( Time_zone_id int unsigned NOT NULL auto_increment, Use_leap_seconds enum('Y','N') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, PRIMARY KEY TzId (Time_zone_id) ) engine=MyISAM CHARACTER SET utf8 comment='Time zones';
CREATE TABLE time_zone_transition ( Time_zone_id int unsigned NOT NULL, Transition_time bigint signed NOT NULL, Transition_type_id int unsigned NOT NULL, PRIMARY KEY TzIdTranTime (Time_zone_id, Transition_time) ) engine=MyISAM CHARACTER SET utf8 comment='Time zone transitions';
@@ -59,7 +59,7 @@ INSERT INTO servers VALUES ('test','localhost','test','root','', 0,'','mysql','r
# Drop all tables created by this test
DROP VIEW user;
-DROP TABLE db, host, func, plugin, tables_priv, columns_priv, procs_priv, servers, help_category, help_keyword, help_relation, help_topic, proc, time_zone, time_zone_leap_second, time_zone_name, time_zone_transition, time_zone_transition_type, general_log, slow_log, event, proxies_priv, innodb_index_stats, innodb_table_stats, transaction_registry, table_stats, column_stats, index_stats, roles_mapping, gtid_slave_pos, global_priv;
+DROP TABLE db, host, func, plugin, tables_priv, columns_priv, procs_priv, servers, help_category, help_relation, help_keyword, help_topic, proc, time_zone, time_zone_leap_second, time_zone_name, time_zone_transition, time_zone_transition_type, general_log, slow_log, event, proxies_priv, innodb_index_stats, innodb_table_stats, transaction_registry, table_stats, column_stats, index_stats, roles_mapping, gtid_slave_pos, global_priv;
# check that we dropped all system tables
show tables;
diff --git a/mysql-test/main/system_mysql_db_fix50117.result b/mysql-test/main/system_mysql_db_fix50117.result
index 07119cda6c6..3f496547166 100644
--- a/mysql-test/main/system_mysql_db_fix50117.result
+++ b/mysql-test/main/system_mysql_db_fix50117.result
@@ -9,8 +9,8 @@ CREATE TABLE IF NOT EXISTS tables_priv ( Host char(60) binary DEFAULT '' NOT NUL
CREATE TABLE IF NOT EXISTS columns_priv ( Host char(60) binary DEFAULT '' NOT NULL, Db char(64) binary DEFAULT '' NOT NULL, User char(16) binary DEFAULT '' NOT NULL, Table_name char(64) binary DEFAULT '' NOT NULL, Column_name char(64) binary DEFAULT '' NOT NULL, Timestamp timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, Column_priv set('Select','Insert','Update','References') COLLATE utf8_general_ci DEFAULT '' NOT NULL, PRIMARY KEY (Host,Db,User,Table_name,Column_name) ) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Column privileges';
CREATE TABLE IF NOT EXISTS help_topic ( help_topic_id int unsigned not null, name char(64) not null, help_category_id smallint unsigned not null, description text not null, example text not null, url char(128) not null, primary key (help_topic_id), unique index (name) ) engine=MyISAM CHARACTER SET utf8 comment='help topics';
CREATE TABLE IF NOT EXISTS help_category ( help_category_id smallint unsigned not null, name char(64) not null, parent_category_id smallint unsigned null, url char(128) not null, primary key (help_category_id), unique index (name) ) engine=MyISAM CHARACTER SET utf8 comment='help categories';
-CREATE TABLE IF NOT EXISTS help_relation ( help_topic_id int unsigned not null references help_topic, help_keyword_id int unsigned not null references help_keyword, primary key (help_keyword_id, help_topic_id) ) engine=MyISAM CHARACTER SET utf8 comment='keyword-topic relation';
CREATE TABLE IF NOT EXISTS help_keyword ( help_keyword_id int unsigned not null, name char(64) not null, primary key (help_keyword_id), unique index (name) ) engine=MyISAM CHARACTER SET utf8 comment='help keywords';
+CREATE TABLE IF NOT EXISTS help_relation ( help_topic_id int unsigned not null references help_topic, help_keyword_id int unsigned not null references help_keyword, primary key (help_keyword_id, help_topic_id) ) engine=MyISAM CHARACTER SET utf8 comment='keyword-topic relation';
CREATE TABLE IF NOT EXISTS time_zone_name ( Name char(64) NOT NULL, Time_zone_id int unsigned NOT NULL, PRIMARY KEY (Name) ) engine=MyISAM CHARACTER SET utf8 comment='Time zone names';
CREATE TABLE IF NOT EXISTS time_zone ( Time_zone_id int unsigned NOT NULL auto_increment, Use_leap_seconds enum('Y','N') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, PRIMARY KEY (Time_zone_id) ) engine=MyISAM CHARACTER SET utf8 comment='Time zones';
CREATE TABLE IF NOT EXISTS time_zone_transition ( Time_zone_id int unsigned NOT NULL, Transition_time bigint signed NOT NULL, Transition_type_id int unsigned NOT NULL, PRIMARY KEY (Time_zone_id, Transition_time) ) engine=MyISAM CHARACTER SET utf8 comment='Time zone transitions';
@@ -271,6 +271,6 @@ index_stats CREATE TABLE `index_stats` (
PRIMARY KEY (`db_name`,`table_name`,`index_name`,`prefix_arity`)
) ENGINE=Aria DEFAULT CHARSET=utf8 COLLATE=utf8_bin PAGE_CHECKSUM=1 TRANSACTIONAL=0 COMMENT='Statistics on Indexes'
DROP VIEW user;
-DROP TABLE db, host, func, plugin, tables_priv, columns_priv, procs_priv, servers, help_category, help_keyword, help_relation, help_topic, proc, time_zone, time_zone_leap_second, time_zone_name, time_zone_transition, time_zone_transition_type, general_log, slow_log, event, proxies_priv, innodb_index_stats, innodb_table_stats, transaction_registry, table_stats, column_stats, index_stats, roles_mapping, gtid_slave_pos, global_priv;
+DROP TABLE db, host, func, plugin, tables_priv, columns_priv, procs_priv, servers, help_category, help_relation, help_keyword, help_topic, proc, time_zone, time_zone_leap_second, time_zone_name, time_zone_transition, time_zone_transition_type, general_log, slow_log, event, proxies_priv, innodb_index_stats, innodb_table_stats, transaction_registry, table_stats, column_stats, index_stats, roles_mapping, gtid_slave_pos, global_priv;
show tables;
Tables_in_test
diff --git a/mysql-test/main/system_mysql_db_fix50117.test b/mysql-test/main/system_mysql_db_fix50117.test
index 28b8621a638..056e844dd9f 100644
--- a/mysql-test/main/system_mysql_db_fix50117.test
+++ b/mysql-test/main/system_mysql_db_fix50117.test
@@ -32,8 +32,8 @@ CREATE TABLE IF NOT EXISTS tables_priv ( Host char(60) binary DEFAULT '' NOT NUL
CREATE TABLE IF NOT EXISTS columns_priv ( Host char(60) binary DEFAULT '' NOT NULL, Db char(64) binary DEFAULT '' NOT NULL, User char(16) binary DEFAULT '' NOT NULL, Table_name char(64) binary DEFAULT '' NOT NULL, Column_name char(64) binary DEFAULT '' NOT NULL, Timestamp timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, Column_priv set('Select','Insert','Update','References') COLLATE utf8_general_ci DEFAULT '' NOT NULL, PRIMARY KEY (Host,Db,User,Table_name,Column_name) ) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Column privileges';
CREATE TABLE IF NOT EXISTS help_topic ( help_topic_id int unsigned not null, name char(64) not null, help_category_id smallint unsigned not null, description text not null, example text not null, url char(128) not null, primary key (help_topic_id), unique index (name) ) engine=MyISAM CHARACTER SET utf8 comment='help topics';
CREATE TABLE IF NOT EXISTS help_category ( help_category_id smallint unsigned not null, name char(64) not null, parent_category_id smallint unsigned null, url char(128) not null, primary key (help_category_id), unique index (name) ) engine=MyISAM CHARACTER SET utf8 comment='help categories';
-CREATE TABLE IF NOT EXISTS help_relation ( help_topic_id int unsigned not null references help_topic, help_keyword_id int unsigned not null references help_keyword, primary key (help_keyword_id, help_topic_id) ) engine=MyISAM CHARACTER SET utf8 comment='keyword-topic relation';
CREATE TABLE IF NOT EXISTS help_keyword ( help_keyword_id int unsigned not null, name char(64) not null, primary key (help_keyword_id), unique index (name) ) engine=MyISAM CHARACTER SET utf8 comment='help keywords';
+CREATE TABLE IF NOT EXISTS help_relation ( help_topic_id int unsigned not null references help_topic, help_keyword_id int unsigned not null references help_keyword, primary key (help_keyword_id, help_topic_id) ) engine=MyISAM CHARACTER SET utf8 comment='keyword-topic relation';
CREATE TABLE IF NOT EXISTS time_zone_name ( Name char(64) NOT NULL, Time_zone_id int unsigned NOT NULL, PRIMARY KEY (Name) ) engine=MyISAM CHARACTER SET utf8 comment='Time zone names';
CREATE TABLE IF NOT EXISTS time_zone ( Time_zone_id int unsigned NOT NULL auto_increment, Use_leap_seconds enum('Y','N') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, PRIMARY KEY (Time_zone_id) ) engine=MyISAM CHARACTER SET utf8 comment='Time zones';
CREATE TABLE IF NOT EXISTS time_zone_transition ( Time_zone_id int unsigned NOT NULL, Transition_time bigint signed NOT NULL, Transition_type_id int unsigned NOT NULL, PRIMARY KEY (Time_zone_id, Transition_time) ) engine=MyISAM CHARACTER SET utf8 comment='Time zone transitions';
@@ -53,7 +53,7 @@ CREATE TABLE IF NOT EXISTS event ( db char(64) CHARACTER SET utf8 COLLATE utf8_b
# Drop all tables created by this test
DROP VIEW user;
-DROP TABLE db, host, func, plugin, tables_priv, columns_priv, procs_priv, servers, help_category, help_keyword, help_relation, help_topic, proc, time_zone, time_zone_leap_second, time_zone_name, time_zone_transition, time_zone_transition_type, general_log, slow_log, event, proxies_priv, innodb_index_stats, innodb_table_stats, transaction_registry, table_stats, column_stats, index_stats, roles_mapping, gtid_slave_pos, global_priv;
+DROP TABLE db, host, func, plugin, tables_priv, columns_priv, procs_priv, servers, help_category, help_relation, help_keyword, help_topic, proc, time_zone, time_zone_leap_second, time_zone_name, time_zone_transition, time_zone_transition_type, general_log, slow_log, event, proxies_priv, innodb_index_stats, innodb_table_stats, transaction_registry, table_stats, column_stats, index_stats, roles_mapping, gtid_slave_pos, global_priv;
# check that we dropped all system tables
show tables;
diff --git a/mysql-test/main/trigger-trans.result b/mysql-test/main/trigger-trans.result
index c58c4230a40..1f201874237 100644
--- a/mysql-test/main/trigger-trans.result
+++ b/mysql-test/main/trigger-trans.result
@@ -160,7 +160,7 @@ CREATE TRIGGER t1_ad AFTER DELETE ON t1 FOR EACH ROW SET @b = 1;
SET @a = 0;
SET @b = 0;
TRUNCATE t1;
-ERROR 42000: Cannot truncate a table referenced in a foreign key constraint (`test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`b`) REFERENCES `test`.`t1` (`a`))
+ERROR 42000: Cannot truncate a table referenced in a foreign key constraint (`test`.`t2`, CONSTRAINT `fk_t2` FOREIGN KEY (`b`) REFERENCES `test`.`t1` (`a`))
SELECT @a, @b;
@a @b
0 0
diff --git a/mysql-test/main/type_ranges.result b/mysql-test/main/type_ranges.result
index 784a394d8b5..123e0f54b5b 100644
--- a/mysql-test/main/type_ranges.result
+++ b/mysql-test/main/type_ranges.result
@@ -144,7 +144,7 @@ alter short drop default,
DROP INDEX utiny,
DROP INDEX ushort,
DROP PRIMARY KEY,
-DROP FOREIGN KEY any_name,
+DROP KEY any_name,
ADD INDEX (auto);
LOCK TABLES t1 WRITE;
ALTER TABLE t1
diff --git a/mysql-test/main/type_ranges.test b/mysql-test/main/type_ranges.test
index 7bf29321d06..75755e5392e 100644
--- a/mysql-test/main/type_ranges.test
+++ b/mysql-test/main/type_ranges.test
@@ -76,7 +76,7 @@ alter short drop default,
DROP INDEX utiny,
DROP INDEX ushort,
DROP PRIMARY KEY,
-DROP FOREIGN KEY any_name,
+DROP KEY any_name,
ADD INDEX (auto);
LOCK TABLES t1 WRITE;
diff --git a/mysql-test/main/union.result b/mysql-test/main/union.result
index ef3aed397ba..293c9f54651 100644
--- a/mysql-test/main/union.result
+++ b/mysql-test/main/union.result
@@ -575,6 +575,10 @@ id select_type table type possible_keys key key_len ref rows Extra
2 UNION t1 ref b b 5 const 1
NULL UNION RESULT <union1,2> ALL NULL NULL NULL NULL NULL
drop table t1,t2;
+create table users (id int primary key);
+create table groups (id int primary key);
+insert into users values (1);
+insert into groups values (1);
create table t1 ( id int not null auto_increment, primary key (id) ,user_name text );
create table t2 ( id int not null auto_increment, primary key (id) ,group_name text );
create table t3 ( id int not null auto_increment, primary key (id) ,user_id int ,index user_idx (user_id) ,foreign key (user_id) references users(id) ,group_id int ,index group_idx (group_id) ,foreign key (group_id) references groups(id) );
@@ -587,7 +591,7 @@ is_in_group user_name group_name id
1 Tester Group A 1
0 Tester Group A NULL
0 Tester Group B NULL
-drop table t1, t2, t3;
+drop table t1, t2, t3, groups, users;
create table t1 (mat_id MEDIUMINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, matintnum CHAR(6) NOT NULL, test MEDIUMINT UNSIGNED NULL);
create table t2 (mat_id MEDIUMINT UNSIGNED NOT NULL, pla_id MEDIUMINT UNSIGNED NOT NULL);
insert into t1 values (NULL, 'a', 1), (NULL, 'b', 2), (NULL, 'c', 3), (NULL, 'd', 4), (NULL, 'e', 5), (NULL, 'f', 6), (NULL, 'g', 7), (NULL, 'h', 8), (NULL, 'i', 9);
diff --git a/mysql-test/main/union.test b/mysql-test/main/union.test
index 33adbb4603d..62e5c978602 100644
--- a/mysql-test/main/union.test
+++ b/mysql-test/main/union.test
@@ -347,6 +347,10 @@ set @@optimizer_use_condition_selectivity=@save_optimizer_use_condition_selectiv
explain (select * from t1 where a=1) union (select * from t1 where b=1);
drop table t1,t2;
+create table users (id int primary key);
+create table groups (id int primary key);
+insert into users values (1);
+insert into groups values (1);
create table t1 ( id int not null auto_increment, primary key (id) ,user_name text );
create table t2 ( id int not null auto_increment, primary key (id) ,group_name text );
create table t3 ( id int not null auto_increment, primary key (id) ,user_id int ,index user_idx (user_id) ,foreign key (user_id) references users(id) ,group_id int ,index group_idx (group_id) ,foreign key (group_id) references groups(id) );
@@ -355,7 +359,7 @@ insert into t2 (group_name) values ('Group A');
insert into t2 (group_name) values ('Group B');
insert into t3 (user_id, group_id) values (1,1);
select 1 'is_in_group', a.user_name, c.group_name, b.id from t1 a, t3 b, t2 c where a.id = b.user_id and b.group_id = c.id UNION select 0 'is_in_group', a.user_name, c.group_name, null from t1 a, t2 c;
-drop table t1, t2, t3;
+drop table t1, t2, t3, groups, users;
#
# fix_fields problem
diff --git a/mysql-test/suite/archive/discover.result b/mysql-test/suite/archive/discover.result
index 99bb955ea24..9dd7884238a 100644
--- a/mysql-test/suite/archive/discover.result
+++ b/mysql-test/suite/archive/discover.result
@@ -65,6 +65,7 @@ flush tables;
rename table t2 to t0;
db.opt
t0.ARZ
+t0.frm
t1.ARZ
t1.frm
#
@@ -83,6 +84,7 @@ flush tables;
drop table t1;
db.opt
t0.ARZ
+t0.frm
#
# discover of table non-existance on drop
#
diff --git a/mysql-test/suite/binlog/r/binlog_database.result b/mysql-test/suite/binlog/r/binlog_database.result
index 2661b344cad..663a540a09b 100644
--- a/mysql-test/suite/binlog/r/binlog_database.result
+++ b/mysql-test/suite/binlog/r/binlog_database.result
@@ -84,7 +84,7 @@ CREATE TABLE t3 (a INT, KEY (a), FOREIGN KEY(a) REFERENCES db1.t2(b))
engine=innodb;
RESET MASTER;
DROP DATABASE db1;
-ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails
+ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (fk_t3)
SHOW TABLES FROM db1;
Tables_in_db1
t2
@@ -180,7 +180,7 @@ CREATE TABLE t3 (a INT, KEY (a), FOREIGN KEY(a) REFERENCES db1.t2(b))
engine=innodb;
RESET MASTER;
DROP DATABASE db1;
-ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails
+ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (fk_t3)
SHOW TABLES FROM db1;
Tables_in_db1
t2
@@ -276,7 +276,7 @@ CREATE TABLE t3 (a INT, KEY (a), FOREIGN KEY(a) REFERENCES db1.t2(b))
engine=innodb;
RESET MASTER;
DROP DATABASE db1;
-ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails
+ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (fk_t3)
SHOW TABLES FROM db1;
Tables_in_db1
t2
diff --git a/mysql-test/suite/binlog/r/binlog_drop_if_exists.result b/mysql-test/suite/binlog/r/binlog_drop_if_exists.result
index c918de9a907..81e4d045d2c 100644
--- a/mysql-test/suite/binlog/r/binlog_drop_if_exists.result
+++ b/mysql-test/suite/binlog/r/binlog_drop_if_exists.result
@@ -171,12 +171,12 @@ master-bin.000001 # Query # # use `test`; DROP TABLE IF EXISTS /* */ `t1` /* gen
create table t1 (a int, key(a)) engine=InnoDB;
create table t2 (b int, foreign key(b) references t1(a)) engine=InnoDB;
drop table if exists t1;
-ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails
+ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (fk_t2)
drop table if exists t1,t0;
-ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails
+ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (fk_t2)
show warnings;
Level Code Message
-Error 1451 Cannot delete or update a parent row: a foreign key constraint fails
+Error 1451 Cannot delete or update a parent row: a foreign key constraint fails (fk_t2)
Note 1051 Unknown table 'test.t0'
drop table t2,t1;
create table t3 (a int) engine=aria;
diff --git a/mysql-test/suite/funcs_1/r/innodb_trig_frkey.result b/mysql-test/suite/funcs_1/r/innodb_trig_frkey.result
index 333e9533608..1fd947e2e8b 100644
--- a/mysql-test/suite/funcs_1/r/innodb_trig_frkey.result
+++ b/mysql-test/suite/funcs_1/r/innodb_trig_frkey.result
@@ -49,7 +49,7 @@ INSERT INTO t1 VALUES (3,'Department C');
INSERT INTO t2 VALUES (1,2,'Emp 1');
INSERT INTO t2 VALUES (2,3,'Emp 2');
insert into t2 VALUES (3,4,'Emp 3');
-ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`f_id`) REFERENCES `t1` (`id`) ON UPDATE CASCADE)
+ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `fk_t2` FOREIGN KEY (`f_id`) REFERENCES `t1` (`id`) ON UPDATE CASCADE)
CREATE TRIGGER tr_t2 BEFORE INSERT ON t2 FOR EACH ROW
INSERT INTO t1 VALUES(new.f_id, CONCAT('New Department ', new.f_id));
LOCK TABLES t1 WRITE, t2 WRITE;
diff --git a/mysql-test/suite/funcs_1/r/is_key_column_usage.result b/mysql-test/suite/funcs_1/r/is_key_column_usage.result
index efb67e32cee..6e56def7d6c 100644
--- a/mysql-test/suite/funcs_1/r/is_key_column_usage.result
+++ b/mysql-test/suite/funcs_1/r/is_key_column_usage.result
@@ -99,7 +99,9 @@ def mysql name def mysql help_category name
def mysql PRIMARY def mysql help_keyword help_keyword_id
def mysql name def mysql help_keyword name
def mysql PRIMARY def mysql help_relation help_keyword_id
+def mysql fk_help_relation_2 def mysql help_relation help_keyword_id
def mysql PRIMARY def mysql help_relation help_topic_id
+def mysql fk_help_relation def mysql help_relation help_topic_id
def mysql PRIMARY def mysql help_topic help_topic_id
def mysql name def mysql help_topic name
def mysql PRIMARY def mysql index_stats db_name
diff --git a/mysql-test/suite/funcs_1/r/is_key_column_usage_embedded.result b/mysql-test/suite/funcs_1/r/is_key_column_usage_embedded.result
index cf67be8f7a0..5a869f7fe82 100644
--- a/mysql-test/suite/funcs_1/r/is_key_column_usage_embedded.result
+++ b/mysql-test/suite/funcs_1/r/is_key_column_usage_embedded.result
@@ -99,7 +99,9 @@ def mysql name def mysql help_category name
def mysql PRIMARY def mysql help_keyword help_keyword_id
def mysql name def mysql help_keyword name
def mysql PRIMARY def mysql help_relation help_keyword_id
+def mysql fk_help_relation_2 def mysql help_relation help_keyword_id
def mysql PRIMARY def mysql help_relation help_topic_id
+def mysql fk_help_relation def mysql help_relation help_topic_id
def mysql PRIMARY def mysql help_topic help_topic_id
def mysql name def mysql help_topic name
def mysql PRIMARY def mysql index_stats db_name
diff --git a/mysql-test/suite/funcs_1/r/is_statistics.result b/mysql-test/suite/funcs_1/r/is_statistics.result
index 858e1b0399e..9e4a3b72fe7 100644
--- a/mysql-test/suite/funcs_1/r/is_statistics.result
+++ b/mysql-test/suite/funcs_1/r/is_statistics.result
@@ -109,7 +109,7 @@ def mysql help_category mysql name
def mysql help_category mysql PRIMARY
def mysql help_keyword mysql name
def mysql help_keyword mysql PRIMARY
-def mysql help_relation mysql help_topic_id
+def mysql help_relation mysql fk_help_relation
def mysql help_relation mysql PRIMARY
def mysql help_relation mysql PRIMARY
def mysql help_topic mysql name
diff --git a/mysql-test/suite/funcs_1/r/is_statistics_mysql.result b/mysql-test/suite/funcs_1/r/is_statistics_mysql.result
index 40d5e125c0d..be967529816 100644
--- a/mysql-test/suite/funcs_1/r/is_statistics_mysql.result
+++ b/mysql-test/suite/funcs_1/r/is_statistics_mysql.result
@@ -30,7 +30,7 @@ def mysql help_category 0 mysql name 1 name A #CARD# NULL NULL BTREE
def mysql help_category 0 mysql PRIMARY 1 help_category_id A #CARD# NULL NULL BTREE
def mysql help_keyword 0 mysql name 1 name A #CARD# NULL NULL BTREE
def mysql help_keyword 0 mysql PRIMARY 1 help_keyword_id A #CARD# NULL NULL BTREE
-def mysql help_relation 1 mysql help_topic_id 1 help_topic_id A #CARD# NULL NULL BTREE
+def mysql help_relation 1 mysql fk_help_relation 1 help_topic_id A #CARD# NULL NULL BTREE
def mysql help_relation 0 mysql PRIMARY 1 help_keyword_id A #CARD# NULL NULL BTREE
def mysql help_relation 0 mysql PRIMARY 2 help_topic_id A #CARD# NULL NULL BTREE
def mysql help_topic 0 mysql name 1 name A #CARD# NULL NULL BTREE
diff --git a/mysql-test/suite/funcs_1/r/is_statistics_mysql_embedded.result b/mysql-test/suite/funcs_1/r/is_statistics_mysql_embedded.result
index 01a98e413da..f4662a3a26d 100644
--- a/mysql-test/suite/funcs_1/r/is_statistics_mysql_embedded.result
+++ b/mysql-test/suite/funcs_1/r/is_statistics_mysql_embedded.result
@@ -30,7 +30,7 @@ def mysql help_category 0 mysql name 1 name A #CARD# NULL NULL BTREE
def mysql help_category 0 mysql PRIMARY 1 help_category_id A #CARD# NULL NULL BTREE
def mysql help_keyword 0 mysql name 1 name A #CARD# NULL NULL BTREE
def mysql help_keyword 0 mysql PRIMARY 1 help_keyword_id A #CARD# NULL NULL BTREE
-def mysql help_relation 1 mysql help_topic_id 1 help_topic_id A #CARD# NULL NULL BTREE
+def mysql help_relation 1 mysql fk_help_relation 1 help_topic_id A #CARD# NULL NULL BTREE
def mysql help_relation 0 mysql PRIMARY 1 help_keyword_id A #CARD# NULL NULL BTREE
def mysql help_relation 0 mysql PRIMARY 2 help_topic_id A #CARD# NULL NULL BTREE
def mysql help_topic 0 mysql name 1 name A #CARD# NULL NULL BTREE
@@ -111,7 +111,7 @@ def mysql help_category 0 mysql name 1 name A #CARD# NULL NULL BTREE
def mysql help_category 0 mysql PRIMARY 1 help_category_id A #CARD# NULL NULL BTREE
def mysql help_keyword 0 mysql name 1 name A #CARD# NULL NULL BTREE
def mysql help_keyword 0 mysql PRIMARY 1 help_keyword_id A #CARD# NULL NULL BTREE
-def mysql help_relation 1 mysql help_topic_id 1 help_topic_id A #CARD# NULL NULL BTREE
+def mysql help_relation 1 mysql fk_help_relation 1 help_topic_id A #CARD# NULL NULL BTREE
def mysql help_relation 0 mysql PRIMARY 1 help_keyword_id A #CARD# NULL NULL BTREE
def mysql help_relation 0 mysql PRIMARY 2 help_topic_id A #CARD# NULL NULL BTREE
def mysql help_topic 0 mysql name 1 name A #CARD# NULL NULL BTREE
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 e0b861c8589..68abef860c4 100644
--- a/mysql-test/suite/funcs_1/r/is_table_constraints.result
+++ b/mysql-test/suite/funcs_1/r/is_table_constraints.result
@@ -70,6 +70,8 @@ def mysql name mysql help_category
def mysql PRIMARY mysql help_category
def mysql name mysql help_keyword
def mysql PRIMARY mysql help_keyword
+def mysql fk_help_relation mysql help_relation
+def mysql fk_help_relation_2 mysql help_relation
def mysql PRIMARY mysql help_relation
def mysql name mysql help_topic
def mysql PRIMARY mysql help_topic
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 d5da807388b..da029cffef5 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
@@ -19,6 +19,8 @@ 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 fk_help_relation mysql help_relation FOREIGN KEY
+def mysql fk_help_relation_2 mysql help_relation FOREIGN KEY
def mysql PRIMARY mysql help_relation PRIMARY KEY
def mysql name mysql help_topic UNIQUE
def mysql PRIMARY mysql help_topic PRIMARY KEY
diff --git a/mysql-test/suite/funcs_1/r/is_table_constraints_mysql_embedded.result b/mysql-test/suite/funcs_1/r/is_table_constraints_mysql_embedded.result
index 0426877bc1c..7e1fc5bcb61 100644
--- a/mysql-test/suite/funcs_1/r/is_table_constraints_mysql_embedded.result
+++ b/mysql-test/suite/funcs_1/r/is_table_constraints_mysql_embedded.result
@@ -19,6 +19,8 @@ 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 fk_help_relation mysql help_relation FOREIGN KEY
+def mysql fk_help_relation_2 mysql help_relation FOREIGN KEY
def mysql PRIMARY mysql help_relation PRIMARY KEY
def mysql name mysql help_topic UNIQUE
def mysql PRIMARY mysql help_topic PRIMARY KEY
@@ -57,6 +59,8 @@ 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 fk_help_relation mysql help_relation FOREIGN KEY
+def mysql fk_help_relation_2 mysql help_relation FOREIGN KEY
def mysql PRIMARY mysql help_relation PRIMARY KEY
def mysql name mysql help_topic UNIQUE
def mysql PRIMARY mysql help_topic PRIMARY KEY
diff --git a/mysql-test/suite/gcol/inc/gcol_ins_upd.inc b/mysql-test/suite/gcol/inc/gcol_ins_upd.inc
index 8c00bde7fca..5959f3dc97b 100644
--- a/mysql-test/suite/gcol/inc/gcol_ins_upd.inc
+++ b/mysql-test/suite/gcol/inc/gcol_ins_upd.inc
@@ -245,7 +245,7 @@ if ($innodb_engine)
--error 1451
update t2 set a=4 where a=3;
select t1.a, t1.b, t2.name from t1,t2 where t1.b=t2.a;
- alter table t1 drop foreign key t1_ibfk_1;
+ alter table t1 drop foreign key fk_t1;
--echo # - ON DELETE RESTRICT
alter table t1 add foreign key (b) references t2(a) on delete restrict;
@@ -253,14 +253,14 @@ if ($innodb_engine)
delete from t2 where a=3;
select t1.a, t1.b, t2.name from t1,t2 where t1.b=t2.a;
select t1.a, t1.b, t2.name from t1 left outer join t2 on (t1.b=t2.a);
- alter table t1 drop foreign key t1_ibfk_1;
+ alter table t1 drop foreign key fk_t1;
--echo # - ON DELETE CASCADE
alter table t1 add foreign key (b) references t2(a) on delete cascade;
delete from t2 where a=3;
select t1.a, t1.b, t2.name from t1,t2 where t1.b=t2.a;
select t1.a, t1.b, t2.name from t1 left outer join t2 on (t1.b=t2.a);
- alter table t1 drop foreign key t1_ibfk_1;
+ alter table t1 drop foreign key fk_t1;
drop table t1;
drop table t2;
diff --git a/mysql-test/suite/gcol/inc/gcol_keys.inc b/mysql-test/suite/gcol/inc/gcol_keys.inc
index 475ab96e56f..e59b368c261 100644
--- a/mysql-test/suite/gcol/inc/gcol_keys.inc
+++ b/mysql-test/suite/gcol/inc/gcol_keys.inc
@@ -151,12 +151,12 @@ drop table t1;
if(!$skip_foreign_key_check)
{
---error ER_CANT_CREATE_TABLE
+--error ER_NO_SUCH_TABLE
create table t1 (a int, b int generated always as (a+1) virtual,
foreign key (b) references t2(a));
create table t1 (a int, b int generated always as (a+1) virtual);
---error ER_CANT_CREATE_TABLE
+--error ER_NO_SUCH_TABLE
alter table t1 add foreign key (b) references t2(a);
drop table t1;
}
diff --git a/mysql-test/suite/gcol/r/gcol_ins_upd_innodb.result b/mysql-test/suite/gcol/r/gcol_ins_upd_innodb.result
index 3024b58da54..dc8e26d446f 100644
--- a/mysql-test/suite/gcol/r/gcol_ins_upd_innodb.result
+++ b/mysql-test/suite/gcol/r/gcol_ins_upd_innodb.result
@@ -357,19 +357,19 @@ a b name
# - ON UPDATE RESTRICT
alter table t1 add foreign key (b) references t2(a) on update restrict;
insert into t1 (a) values (4);
-ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test`.`t1`, CONSTRAINT `t1_ibfk_1` FOREIGN KEY (`b`) REFERENCES `t2` (`a`))
+ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test`.`t1`, CONSTRAINT `fk_t1` FOREIGN KEY (`b`) REFERENCES `t2` (`a`))
update t2 set a=4 where a=3;
-ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t1`, CONSTRAINT `t1_ibfk_1` FOREIGN KEY (`b`) REFERENCES `t2` (`a`))
+ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t1`, CONSTRAINT `fk_t1` FOREIGN KEY (`b`) REFERENCES `t2` (`a`))
select t1.a, t1.b, t2.name from t1,t2 where t1.b=t2.a;
a b name
1 1 value1
2 2 value2
3 3 value3
-alter table t1 drop foreign key t1_ibfk_1;
+alter table t1 drop foreign key fk_t1;
# - ON DELETE RESTRICT
alter table t1 add foreign key (b) references t2(a) on delete restrict;
delete from t2 where a=3;
-ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t1`, CONSTRAINT `t1_ibfk_1` FOREIGN KEY (`b`) REFERENCES `t2` (`a`))
+ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t1`, CONSTRAINT `fk_t1` FOREIGN KEY (`b`) REFERENCES `t2` (`a`))
select t1.a, t1.b, t2.name from t1,t2 where t1.b=t2.a;
a b name
1 1 value1
@@ -380,7 +380,7 @@ a b name
1 1 value1
2 2 value2
3 3 value3
-alter table t1 drop foreign key t1_ibfk_1;
+alter table t1 drop foreign key fk_t1;
# - ON DELETE CASCADE
alter table t1 add foreign key (b) references t2(a) on delete cascade;
delete from t2 where a=3;
@@ -392,7 +392,7 @@ select t1.a, t1.b, t2.name from t1 left outer join t2 on (t1.b=t2.a);
a b name
1 1 value1
2 2 value2
-alter table t1 drop foreign key t1_ibfk_1;
+alter table t1 drop foreign key fk_t1;
drop table t1;
drop table t2;
#
diff --git a/mysql-test/suite/gcol/r/gcol_keys_innodb.result b/mysql-test/suite/gcol/r/gcol_keys_innodb.result
index 4f7d654ac4e..de3d82172dc 100644
--- a/mysql-test/suite/gcol/r/gcol_keys_innodb.result
+++ b/mysql-test/suite/gcol/r/gcol_keys_innodb.result
@@ -150,10 +150,10 @@ ERROR HY000: Cannot define foreign key with ON DELETE SET NULL clause on a gener
drop table t1;
create table t1 (a int, b int generated always as (a+1) virtual,
foreign key (b) references t2(a));
-ERROR HY000: Can't create table `test`.`t1` (errno: 150 "Foreign key constraint is incorrectly formed")
+ERROR 42S02: Table 'test.t2' doesn't exist
create table t1 (a int, b int generated always as (a+1) virtual);
alter table t1 add foreign key (b) references t2(a);
-ERROR HY000: Can't create table `test`.`t1` (errno: 150 "Foreign key constraint is incorrectly formed")
+ERROR 42S02: Table 'test.t2' doesn't exist
drop table t1;
# Allowed FK options.
create table t2 (a int primary key, b char(5));
diff --git a/mysql-test/suite/gcol/r/innodb_virtual_fk.result b/mysql-test/suite/gcol/r/innodb_virtual_fk.result
index 68601823e31..001608e6257 100644
--- a/mysql-test/suite/gcol/r/innodb_virtual_fk.result
+++ b/mysql-test/suite/gcol/r/innodb_virtual_fk.result
@@ -602,7 +602,7 @@ SELECT f1, f2 FROM t2;
f1 f2
1 1
INSERT INTO t2(f1) VALUES(2);
-ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`f1`) REFERENCES `t1` (`f1`))
+ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `fk_t2` FOREIGN KEY (`f1`) REFERENCES `t1` (`f1`))
DROP TABLE t2, t1;
CREATE TABLE t1 (f1 INT NOT NULL PRIMARY KEY)ENGINE=INNODB;
CREATE TABLE t2 (f1 INT NOT NULL, f2 INT AS (f1) VIRTUAL,
@@ -702,7 +702,7 @@ v3 TIME AS (c3) VIRTUAL,
v4 CHAR(10) AS (c4) VIRTUAL
) ENGINE=InnoDB;
ALTER TABLE t1 ADD CONSTRAINT fk FOREIGN KEY (v4) REFERENCES nosuch(col);
-ERROR HY000: Can't create table `test`.`t1` (errno: 150 "Foreign key constraint is incorrectly formed")
+ERROR 42S02: Table 'test.nosuch' doesn't exist
SET foreign_key_checks=0;
ALTER TABLE t1 ADD CONSTRAINT fk FOREIGN KEY (v4) REFERENCES nosuch(col);
ERROR HY000: Failed to add the foreign key constaint. Missing index for constraint 'fk' in the foreign table 't1'
@@ -725,7 +725,7 @@ t1 CREATE TABLE `t1` (
) ENGINE=InnoDB DEFAULT CHARSET=latin1
ALTER TABLE t1 DROP FOREIGN KEY fk;
ALTER TABLE t1 ADD CONSTRAINT fk FOREIGN KEY (v4) REFERENCES nosuch(col);
-ERROR HY000: Can't create table `test`.`t1` (errno: 150 "Foreign key constraint is incorrectly formed")
+ERROR 42S02: Table 'test.nosuch' doesn't exist
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
diff --git a/mysql-test/suite/gcol/r/innodb_virtual_fk_restart.result b/mysql-test/suite/gcol/r/innodb_virtual_fk_restart.result
index c45579aec2b..138d8876adf 100644
--- a/mysql-test/suite/gcol/r/innodb_virtual_fk_restart.result
+++ b/mysql-test/suite/gcol/r/innodb_virtual_fk_restart.result
@@ -48,6 +48,7 @@ fld2
3
CHECK TABLE t2;
Table Op Msg_type Msg_text
+test.t2 check Note Found 1 foreign keys
test.t2 check status OK
connection default;
disconnect con1;
diff --git a/mysql-test/suite/gcol/t/innodb_virtual_fk.test b/mysql-test/suite/gcol/t/innodb_virtual_fk.test
index da20612f0a1..fcf390aeda1 100644
--- a/mysql-test/suite/gcol/t/innodb_virtual_fk.test
+++ b/mysql-test/suite/gcol/t/innodb_virtual_fk.test
@@ -590,7 +590,7 @@ CREATE TABLE t1 (
v3 TIME AS (c3) VIRTUAL,
v4 CHAR(10) AS (c4) VIRTUAL
) ENGINE=InnoDB;
---error ER_CANT_CREATE_TABLE
+--error ER_NO_SUCH_TABLE
ALTER TABLE t1 ADD CONSTRAINT fk FOREIGN KEY (v4) REFERENCES nosuch(col);
SET foreign_key_checks=0;
--error ER_FK_NO_INDEX_CHILD
@@ -600,7 +600,7 @@ ALTER TABLE t1 ADD CONSTRAINT fk FOREIGN KEY (v4) REFERENCES nosuch(col);
SET foreign_key_checks=1;
SHOW CREATE TABLE t1;
ALTER TABLE t1 DROP FOREIGN KEY fk;
---error ER_CANT_CREATE_TABLE
+--error ER_NO_SUCH_TABLE
ALTER TABLE t1 ADD CONSTRAINT fk FOREIGN KEY (v4) REFERENCES nosuch(col);
SHOW CREATE TABLE t1;
# Cleanup
diff --git a/mysql-test/suite/innodb/r/alter_foreign_crash.result b/mysql-test/suite/innodb/r/alter_foreign_crash.result
index 9a7a23a5b72..d4b813900f9 100644
--- a/mysql-test/suite/innodb/r/alter_foreign_crash.result
+++ b/mysql-test/suite/innodb/r/alter_foreign_crash.result
@@ -22,6 +22,7 @@ Tables_in_bug
parent
alter table parent row_format=dynamic;
Warnings:
+Warning 1215 Reference hint to non-existent table `bug.child` skipped
Warning 1088 failed to load FOREIGN KEY constraints
drop table parent;
drop database bug;
diff --git a/mysql-test/suite/innodb/r/alter_table.result b/mysql-test/suite/innodb/r/alter_table.result
index 58e2b22273b..d6ebff600a8 100644
--- a/mysql-test/suite/innodb/r/alter_table.result
+++ b/mysql-test/suite/innodb/r/alter_table.result
@@ -46,11 +46,11 @@ CREATE TABLE tx (pk INT PRIMARY KEY) ENGINE=InnoDB;
CREATE TABLE t1 (pk INT, a INT, PRIMARY KEY (pk), KEY (a), FOREIGN KEY (a) REFERENCES tx (pk)) ENGINE=InnoDB;
SET FOREIGN_KEY_CHECKS=OFF;
ALTER TABLE t1 DROP a;
-ERROR HY000: Cannot drop column 'a': needed in a foreign key constraint 'test/t1_ibfk_1'
+ERROR 42000: Incorrect foreign key definition for 'a'
SET FOREIGN_KEY_CHECKS=ON;
ALTER TABLE t1 ADD b INT;
ALTER TABLE t1 DROP a;
-ERROR HY000: Cannot drop index 'a': needed in a foreign key constraint
+ERROR 42000: Incorrect foreign key definition for 'a'
ALTER TABLE t1 ADD c INT;
DROP TABLE t1, tx;
#
diff --git a/mysql-test/suite/innodb/r/foreign-keys.result b/mysql-test/suite/innodb/r/foreign-keys.result
index 45177a4bddf..df6e31c81eb 100644
--- a/mysql-test/suite/innodb/r/foreign-keys.result
+++ b/mysql-test/suite/innodb/r/foreign-keys.result
@@ -22,7 +22,7 @@ insert t2 values (4,1),(5,2),(6,3);
flush table t2 with read lock;
connect con1,localhost,root;
delete from t1 where a=2;
-ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`d`) REFERENCES `t1` (`a`) ON UPDATE CASCADE)
+ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `fk_t2` FOREIGN KEY (`d`) REFERENCES `t1` (`a`) ON UPDATE CASCADE)
update t1 set a=10 where a=1;
connection default;
unlock tables;
@@ -34,7 +34,7 @@ delete from t1 where a=2;
connection default;
unlock tables;
connection con1;
-ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`d`) REFERENCES `t1` (`a`) ON UPDATE CASCADE)
+ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `fk_t2` FOREIGN KEY (`d`) REFERENCES `t1` (`a`) ON UPDATE CASCADE)
connection default;
unlock tables;
disconnect con1;
@@ -75,7 +75,7 @@ Table Create Table
t2 CREATE TABLE `t2` (
`f2` int(11) NOT NULL,
PRIMARY KEY (`f2`),
- CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`f2`) REFERENCES `t1` (`f1`) ON DELETE CASCADE ON UPDATE CASCADE
+ CONSTRAINT `fk_t2` FOREIGN KEY (`f2`) REFERENCES `t1` (`f1`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=latin1
disconnect con1;
connection default;
@@ -132,7 +132,7 @@ insert t2 values (4,1),(5,2),(6,3);
flush table t2 with read lock;
connect con1,localhost,root;
delete from t1 where a=2;
-ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`d`) REFERENCES `t1` (`a`) ON UPDATE CASCADE)
+ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `fk_t2` FOREIGN KEY (`d`) REFERENCES `t1` (`a`) ON UPDATE CASCADE)
update t1 set a=10 where a=1;
connection default;
unlock tables;
@@ -144,7 +144,7 @@ delete from t1 where a=2;
connection default;
unlock tables;
connection con1;
-ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`d`) REFERENCES `t1` (`a`) ON UPDATE CASCADE)
+ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `fk_t2` FOREIGN KEY (`d`) REFERENCES `t1` (`a`) ON UPDATE CASCADE)
connection default;
unlock tables;
disconnect con1;
@@ -217,8 +217,8 @@ t2 CREATE TABLE `t2` (
CONSTRAINT `fk_fid` FOREIGN KEY (`fid`) REFERENCES `t1` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
drop table t1,t2;
-ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails
-drop table t1,t2;
+ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (fk_fid)
+drop table t2, t1;
ERROR 42S02: Unknown table 'test.t2'
#
# MDEV-23470 InnoDB: Failing assertion: cmp < 0 in
@@ -233,6 +233,6 @@ SET FOREIGN_KEY_CHECKS=0;
DROP INDEX f2 ON t2;
SET FOREIGN_KEY_CHECKS=1;
INSERT INTO t2 VALUES('G', 3);
-ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`f2`) REFERENCES `t1` (`f1`))
+ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `fk_t2` FOREIGN KEY (`f2`) REFERENCES `t1` (`f1`))
DROP TABLE t2, t1;
SET FOREIGN_KEY_CHECKS=DEFAULT;
diff --git a/mysql-test/suite/innodb/r/foreign_key.result b/mysql-test/suite/innodb/r/foreign_key.result
index 399e35b698f..8c7a2871f93 100644
--- a/mysql-test/suite/innodb/r/foreign_key.result
+++ b/mysql-test/suite/innodb/r/foreign_key.result
@@ -10,10 +10,10 @@ ERROR HY000: Can't create table `test`.`t2` (errno: 150 "Foreign key constraint
create table t2 (f1 int primary key,
constraint c1 foreign key (f1) references t1(f1)) engine=innodb;
alter table t2 add constraint c1 foreign key (f1) references t1(f1);
-ERROR HY000: Can't create table `test`.`t2` (errno: 121 "Duplicate key on write or update")
+ERROR HY000: Duplicate FOREIGN KEY constraint name 'c1'
set foreign_key_checks = 0;
alter table t2 add constraint c1 foreign key (f1) references t1(f1);
-ERROR HY000: Duplicate FOREIGN KEY constraint name 'test/c1'
+ERROR HY000: Duplicate FOREIGN KEY constraint name 'c1'
drop table t2, t1;
#
# Bug #20031243 CREATE TABLE FAILS TO CHECK IF FOREIGN KEY COLUMN
@@ -47,7 +47,7 @@ t2 CREATE TABLE `t2` (
`b` int(11) DEFAULT NULL,
PRIMARY KEY (`a`),
KEY `ind` (`b`),
- CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`b`) REFERENCES `t1` (`a`) ON DELETE CASCADE ON UPDATE CASCADE
+ CONSTRAINT `fk_t2` FOREIGN KEY (`b`) REFERENCES `t1` (`a`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=latin1
INSERT INTO t1 VALUES (1, 80);
INSERT INTO t1 VALUES (2, 81);
@@ -74,7 +74,7 @@ a b
54 4
55 5
INSERT INTO t2 VALUES (56, 6);
-ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`b`) REFERENCES `t1` (`a`) ON DELETE CASCADE ON UPDATE CASCADE)
+ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `fk_t2` FOREIGN KEY (`b`) REFERENCES `t1` (`a`) ON DELETE CASCADE ON UPDATE CASCADE)
ALTER TABLE t1 CHANGE a id INT;
SELECT id, b FROM t1 ORDER BY id;
id b
@@ -92,9 +92,9 @@ a b
55 5
# Operations on child table
INSERT INTO t2 VALUES (56, 6);
-ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`b`) REFERENCES `t1` (`id`) ON DELETE CASCADE ON UPDATE CASCADE)
+ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `fk_t2` FOREIGN KEY (`b`) REFERENCES `t1` (`id`) ON DELETE CASCADE ON UPDATE CASCADE)
UPDATE t2 SET b = 99 WHERE a = 51;
-ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`b`) REFERENCES `t1` (`id`) ON DELETE CASCADE ON UPDATE CASCADE)
+ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `fk_t2` FOREIGN KEY (`b`) REFERENCES `t1` (`id`) ON DELETE CASCADE ON UPDATE CASCADE)
DELETE FROM t2 WHERE a = 53;
SELECT id, b FROM t1 ORDER BY id;
id b
@@ -136,21 +136,21 @@ INSERT INTO t2 VALUES (1);
SELECT unique_constraint_name FROM information_schema.referential_constraints
WHERE table_name = 't2';
unique_constraint_name
-PRIMARY
+fk_t2
# restart
SET @saved_frequency = @@GLOBAL.innodb_purge_rseg_truncate_frequency;
SET GLOBAL innodb_purge_rseg_truncate_frequency = 1;
SELECT unique_constraint_name FROM information_schema.referential_constraints
WHERE table_name = 't2';
unique_constraint_name
-PRIMARY
+fk_t2
SELECT * FROM t1;
c1
1
SELECT unique_constraint_name FROM information_schema.referential_constraints
WHERE table_name = 't2';
unique_constraint_name
-PRIMARY
+fk_t2
DROP TABLE t2;
DROP TABLE t1;
SET FOREIGN_KEY_CHECKS=0;
@@ -180,7 +180,7 @@ CREATE DATABASE best default character set latin1;
CREATE TABLE t3 (a INT PRIMARY KEY,
CONSTRAINT t2_ibfk_1 FOREIGN KEY (a) REFERENCES t1(a)) ENGINE=InnoDB;
CREATE TABLE best.t2 (a INT PRIMARY KEY, b TEXT, FULLTEXT INDEX(b),
-FOREIGN KEY (a) REFERENCES test.t1(a)) ENGINE=InnoDB;
+FOREIGN KEY t2_ibfk_1 (a) REFERENCES test.t1(a)) ENGINE=InnoDB;
RENAME TABLE best.t2 TO test.t2;
ERROR 42S01: Table 't2' already exists
SHOW CREATE TABLE best.t2;
@@ -235,19 +235,17 @@ DROP TABLE t2, t1;
CREATE TABLE t1 (f VARCHAR(256)) ENGINE=InnoDB;
SET SESSION FOREIGN_KEY_CHECKS = OFF;
ALTER TABLE t1 ADD FOREIGN KEY (f) REFERENCES non_existing_table (x);
-SET SESSION FOREIGN_KEY_CHECKS = ON;
ALTER TABLE t1 ADD FULLTEXT INDEX ft1 (f);
ALTER TABLE t1 ADD FULLTEXT INDEX ft2 (f);
+SET SESSION FOREIGN_KEY_CHECKS = ON;
DROP TABLE t1;
CREATE TABLE t1 (f VARCHAR(256), FTS_DOC_ID BIGINT UNSIGNED PRIMARY KEY)
ENGINE=InnoDB;
SET SESSION FOREIGN_KEY_CHECKS = OFF;
ALTER TABLE t1 ADD FOREIGN KEY (f) REFERENCES non_existing_table (x);
-SET SESSION FOREIGN_KEY_CHECKS = ON;
ALTER TABLE t1 ADD FULLTEXT INDEX ft1 (f);
-Warnings:
-Warning 1088 failed to load FOREIGN KEY constraints
ALTER TABLE t1 ADD FULLTEXT INDEX ft2 (f);
+SET SESSION FOREIGN_KEY_CHECKS = ON;
DROP TABLE t1;
#
# MDEV-18630 Conditional jump or move depends on uninitialised value
@@ -255,12 +253,9 @@ DROP TABLE t1;
#
CREATE TABLE t1 (a INT) ENGINE=InnoDB;
ALTER IGNORE TABLE t1 ADD FOREIGN KEY (a) REFERENCES t2 (b);
-ERROR HY000: Can't create table `test`.`t1` (errno: 150 "Foreign key constraint is incorrectly formed")
+ERROR 42S02: Table 'test.t2' doesn't exist
SHOW WARNINGS;
Level Code Message
-Warning 150 Alter table `test`.`t1` with foreign key (a) constraint failed. Referenced table `test`.`t2` not found in the data dictionary.
-Error 1005 Can't create table `test`.`t1` (errno: 150 "Foreign key constraint is incorrectly formed")
-Warning 1215 Cannot add foreign key constraint for `t1`
DROP TABLE t1;
#
# MDEV-18139 ALTER IGNORE ... ADD FOREIGN KEY causes bogus error
@@ -311,7 +306,7 @@ insert t2 values (4,1),(5,2),(6,3);
flush table t2 with read lock;
connect con1,localhost,root;
delete from t1 where a=2;
-ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`d`) REFERENCES `t1` (`a`) ON UPDATE CASCADE)
+ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `fk_t2` FOREIGN KEY (`d`) REFERENCES `t1` (`a`) ON UPDATE CASCADE)
update t1 set a=10 where a=1;
connection default;
unlock tables;
@@ -323,7 +318,7 @@ delete from t1 where a=2;
connection default;
unlock tables;
connection con1;
-ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`d`) REFERENCES `t1` (`a`) ON UPDATE CASCADE)
+ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `fk_t2` FOREIGN KEY (`d`) REFERENCES `t1` (`a`) ON UPDATE CASCADE)
connection default;
unlock tables;
disconnect con1;
@@ -358,13 +353,13 @@ insert t1 values (1,1),(2,2),(3,3);
create table t2 (t1_pk int, foreign key (t1_pk) references t1 (pk)) engine=innodb;
insert t2 values (1),(2);
insert t2 values (10);
-ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`t1_pk`) REFERENCES `t1` (`pk`))
+ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `fk_t2` FOREIGN KEY (`t1_pk`) REFERENCES `t1` (`pk`))
flush tables;
flush status;
update t1 set data=10 where pk+1>10;
show status like '%opened_tab%';
Variable_name Value
-Opened_table_definitions 4
+Opened_table_definitions 5
Opened_tables 4
flush tables;
flush status;
@@ -398,7 +393,7 @@ foo()
5
show status like '%opened_tab%';
Variable_name Value
-Opened_table_definitions 5
+Opened_table_definitions 6
Opened_tables 5
drop function foo;
drop table t2, t1;
@@ -447,10 +442,10 @@ pk f1 f2 f3 f4 f5 f6 f7 f8
ROLLBACK;
ALTER TABLE t1 ADD FOREIGN KEY (f5) REFERENCES t1 (f6) ON UPDATE SET NULL;
UPDATE t1 SET f6='update';
-ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t1`, CONSTRAINT `t1_ibfk_3` FOREIGN KEY (`f5`) REFERENCES `t1` (`f6`) ON UPDATE SET NULL)
+ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t1`, CONSTRAINT `fk_t1_3` FOREIGN KEY (`f5`) REFERENCES `t1` (`f6`) ON UPDATE SET NULL)
ALTER TABLE t1 ADD FOREIGN KEY (f7) REFERENCES t1 (f8) ON UPDATE CASCADE;
UPDATE t1 SET f6='cascade';
-ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t1`, CONSTRAINT `t1_ibfk_3` FOREIGN KEY (`f5`) REFERENCES `t1` (`f6`) ON UPDATE SET NULL)
+ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t1`, CONSTRAINT `fk_t1_3` FOREIGN KEY (`f5`) REFERENCES `t1` (`f6`) ON UPDATE SET NULL)
DROP TABLE t1;
# Start of 10.2 tests
#
@@ -524,8 +519,8 @@ t2 CREATE TABLE `t2` (
`ref_id` int(11) NOT NULL DEFAULT 0,
`f` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
- KEY `ref_id` (`ref_id`),
- CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`ref_id`) REFERENCES `t1` (`id`) ON DELETE CASCADE
+ KEY `fk_t2` (`ref_id`),
+ CONSTRAINT `fk_t2` FOREIGN KEY (`ref_id`) REFERENCES `t1` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=latin1
connection con1;
BEGIN;
@@ -656,10 +651,10 @@ connection default;
DELETE IGNORE FROM t1 WHERE b = 1;
Warnings:
Warning 152 InnoDB: Cannot delete/update rows with cascading foreign key constraints that exceed max depth of 20. Please drop extra constraints and try again
-Warning 1296 Got error 193 '`test`.`t1`, CONSTRAINT `t1_ibfk_1` FOREIGN KEY (`a`) REFERENCES `t1` (`b`) ON DELETE CASCADE' from InnoDB
+Warning 1296 Got error 193 '`test`.`t1`, CONSTRAINT `fk_t1` FOREIGN KEY (`a`) REFERENCES `t1` (`b`) ON DELETE CASCADE' from InnoDB
Warning 152 InnoDB: Cannot delete/update rows with cascading foreign key constraints that exceed max depth of 20. Please drop extra constraints and try again
-Warning 1296 Got error 193 '`test`.`t1`, CONSTRAINT `t1_ibfk_1` FOREIGN KEY (`a`) REFERENCES `t1` (`b`) ON DELETE CASCADE' from InnoDB
-SELECT a FROM t1 FORCE INDEX(a);
+Warning 1296 Got error 193 '`test`.`t1`, CONSTRAINT `fk_t1` FOREIGN KEY (`a`) REFERENCES `t1` (`b`) ON DELETE CASCADE' from InnoDB
+SELECT a FROM t1 FORCE INDEX(fk_t1);
a
0
0
@@ -697,6 +692,7 @@ disconnect con1;
InnoDB 0 transactions not purged
CHECK TABLE t1;
Table Op Msg_type Msg_text
+test.t1 check Note Found 1 self-references
test.t1 check status OK
DROP TABLE t1;
SET GLOBAL innodb_purge_rseg_truncate_frequency = @saved_frequency;
@@ -757,7 +753,7 @@ t2 CREATE TABLE `t2` (
CONSTRAINT `fk_fid` FOREIGN KEY (`fid`) REFERENCES `t1` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
drop table t1,t2;
-ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails
+ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (fk_fid)
drop table t1,t2;
ERROR 42S02: Unknown table 'test.t2'
#
@@ -781,7 +777,9 @@ t2 CREATE TABLE `t2` (
`f1` int(11) NOT NULL,
`f2` int(11) NOT NULL,
`f3` int(11) NOT NULL,
- PRIMARY KEY (`f3`)
+ PRIMARY KEY (`f3`),
+ CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`f2`) REFERENCES `t1` (`f2`) ON DELETE CASCADE,
+ CONSTRAINT `t2_ibfk_2` FOREIGN KEY (`f1`) REFERENCES `t1` (`f1`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=latin1
CREATE TABLE t2 (f1 INT NOT NULL)ENGINE=InnoDB;
ERROR 42S01: Table 't2' already exists
@@ -826,10 +824,10 @@ Table Create Table
t2 CREATE TABLE `t2` (
`x` int(11) DEFAULT NULL,
`y` int(11) DEFAULT NULL,
- KEY `x` (`x`),
+ KEY `fk_t2` (`x`),
KEY `fk` (`y`),
- CONSTRAINT `fk` FOREIGN KEY (`y`) REFERENCES `t1` (`y`),
- CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`x`) REFERENCES `t1` (`x`)
+ CONSTRAINT `fk_t2` FOREIGN KEY (`x`) REFERENCES `t1` (`x`),
+ CONSTRAINT `fk` FOREIGN KEY (`y`) REFERENCES `t1` (`y`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
create table t3 (z int);
alter table t3 add x int references t1(x), add y int constraint fk2 references t1(y);
@@ -839,22 +837,22 @@ t3 CREATE TABLE `t3` (
`z` int(11) DEFAULT NULL,
`x` int(11) DEFAULT NULL,
`y` int(11) DEFAULT NULL,
- KEY `x` (`x`),
+ KEY `fk_t3` (`x`),
KEY `fk2` (`y`),
- CONSTRAINT `fk2` FOREIGN KEY (`y`) REFERENCES `t1` (`y`),
- CONSTRAINT `t3_ibfk_1` FOREIGN KEY (`x`) REFERENCES `t1` (`x`)
+ CONSTRAINT `fk_t3` FOREIGN KEY (`x`) REFERENCES `t1` (`x`),
+ CONSTRAINT `fk2` FOREIGN KEY (`y`) REFERENCES `t1` (`y`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
drop tables t3, t2, t1;
create table t1 (id int primary key);
create table t2 (id2 int references t1);
-ERROR HY000: Can't create table `test`.`t2` (errno: 150 "Foreign key constraint is incorrectly formed")
+ERROR 42000: Incorrect foreign key definition for 'id2': referenced field not found
create table t2 (id int references t1);
show create table t2;
Table Create Table
t2 CREATE TABLE `t2` (
`id` int(11) DEFAULT NULL,
- KEY `id` (`id`),
- CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`id`) REFERENCES `t1` (`id`)
+ KEY `fk_t2` (`id`),
+ CONSTRAINT `fk_t2` FOREIGN KEY (`id`) REFERENCES `t1` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
drop tables t2, t1;
set default_storage_engine= default;
diff --git a/mysql-test/suite/innodb/r/foreign_key_debug.result b/mysql-test/suite/innodb/r/foreign_key_debug.result
index 10a7e6f36e9..cab5d37d643 100644
--- a/mysql-test/suite/innodb/r/foreign_key_debug.result
+++ b/mysql-test/suite/innodb/r/foreign_key_debug.result
@@ -22,7 +22,7 @@ Table Create Table
t2 CREATE TABLE `t2` (
`f2` int(11) NOT NULL,
PRIMARY KEY (`f2`),
- CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`f2`) REFERENCES `t1` (`f1`) ON DELETE CASCADE ON UPDATE CASCADE
+ CONSTRAINT `fk_t2` FOREIGN KEY (`f2`) REFERENCES `t1` (`f1`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=latin1
disconnect con1;
connection default;
diff --git a/mysql-test/suite/innodb/r/innodb-alter-table.result b/mysql-test/suite/innodb/r/innodb-alter-table.result
index ad3b2cb04af..2462cf9074b 100644
--- a/mysql-test/suite/innodb/r/innodb-alter-table.result
+++ b/mysql-test/suite/innodb/r/innodb-alter-table.result
@@ -131,8 +131,8 @@ child CREATE TABLE `child` (
`a` int(11) NOT NULL,
`c` int(11) NOT NULL,
PRIMARY KEY (`a`),
- KEY `c` (`c`),
- CONSTRAINT `child_ibfk_1` FOREIGN KEY (`c`) REFERENCES `parent` (`a`)
+ KEY `fk_child` (`c`),
+ CONSTRAINT `fk_child` FOREIGN KEY (`c`) REFERENCES `parent` (`a`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
DROP TABLE child, parent;
CREATE TABLE IF NOT EXISTS ticket (
diff --git a/mysql-test/suite/innodb/r/innodb-alter.result b/mysql-test/suite/innodb/r/innodb-alter.result
index 59abdb01d82..b30b32c71c6 100644
--- a/mysql-test/suite/innodb/r/innodb-alter.result
+++ b/mysql-test/suite/innodb/r/innodb-alter.result
@@ -722,8 +722,8 @@ SHOW CREATE TABLE t2;
Table Create Table
t2 CREATE TABLE `t2` (
`c2` int(11) NOT NULL,
- KEY `c2` (`c2`),
- CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`c2`) REFERENCES `t1` (`c1`)
+ KEY `fk_t2` (`c2`),
+ CONSTRAINT `fk_t2` FOREIGN KEY (`c2`) REFERENCES `t1` (`c1`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
ALTER TABLE t1 CHANGE COLUMN c1 C1 INT;
ALTER TABLE t2 CHANGE COLUMN c2 C2 INT;
@@ -737,8 +737,8 @@ SHOW CREATE TABLE t2;
Table Create Table
t2 CREATE TABLE `t2` (
`C2` int(11) DEFAULT NULL,
- KEY `c2` (`C2`),
- CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`C2`) REFERENCES `t1` (`C1`)
+ KEY `fk_t2` (`C2`),
+ CONSTRAINT `fk_t2` FOREIGN KEY (`C2`) REFERENCES `t1` (`C1`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
ALTER TABLE t1 CHANGE COLUMN C1 c5 INT;
ALTER TABLE t2 CHANGE COLUMN C2 c6 INT;
@@ -752,8 +752,8 @@ SHOW CREATE TABLE t2;
Table Create Table
t2 CREATE TABLE `t2` (
`c6` int(11) DEFAULT NULL,
- KEY `c2` (`c6`),
- CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`c6`) REFERENCES `t1` (`c5`)
+ KEY `fk_t2` (`c6`),
+ CONSTRAINT `fk_t2` FOREIGN KEY (`c6`) REFERENCES `t1` (`c5`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
SELECT C.NAME FROM INFORMATION_SCHEMA.INNODB_SYS_COLUMNS C INNER JOIN
INFORMATION_SCHEMA.INNODB_SYS_TABLES T ON C.TABLE_ID=T.TABLE_ID
@@ -838,31 +838,31 @@ t2 CREATE TABLE `t2` (
`BB` int(11) DEFAULT NULL,
`CC` int(11) DEFAULT NULL,
`DD` int(11) DEFAULT NULL,
- KEY `aa` (`AA`),
- KEY `bb` (`BB`),
- KEY `CC` (`CC`),
- KEY `DD` (`DD`),
- CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`AA`) REFERENCES `t1` (`A`),
- CONSTRAINT `t2_ibfk_2` FOREIGN KEY (`BB`) REFERENCES `t1` (`B`),
- CONSTRAINT `t2_ibfk_3` FOREIGN KEY (`CC`) REFERENCES `t1` (`C`),
- CONSTRAINT `t2_ibfk_4` FOREIGN KEY (`DD`) REFERENCES `t1` (`D`)
+ KEY `fk_t2` (`AA`),
+ KEY `fk_t2_2` (`BB`),
+ KEY `fk_t2_3` (`CC`),
+ KEY `fk_t2_4` (`DD`),
+ CONSTRAINT `fk_t2` FOREIGN KEY (`AA`) REFERENCES `t1` (`A`),
+ CONSTRAINT `fk_t2_2` FOREIGN KEY (`BB`) REFERENCES `t1` (`B`),
+ CONSTRAINT `fk_t2_3` FOREIGN KEY (`CC`) REFERENCES `t1` (`C`),
+ CONSTRAINT `fk_t2_4` FOREIGN KEY (`DD`) REFERENCES `t1` (`D`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
DELETE FROM t1 WHERE a=1;
-ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`AA`) REFERENCES `t1` (`A`))
+ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `fk_t2` FOREIGN KEY (`AA`) REFERENCES `t1` (`A`))
DELETE FROM t1 WHERE A=1;
-ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`AA`) REFERENCES `t1` (`A`))
+ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `fk_t2` FOREIGN KEY (`AA`) REFERENCES `t1` (`A`))
DELETE FROM t1 WHERE b=1;
-ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`AA`) REFERENCES `t1` (`A`))
+ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `fk_t2` FOREIGN KEY (`AA`) REFERENCES `t1` (`A`))
DELETE FROM t1 WHERE B=1;
-ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`AA`) REFERENCES `t1` (`A`))
+ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `fk_t2` FOREIGN KEY (`AA`) REFERENCES `t1` (`A`))
DELETE FROM t1 WHERE c=1;
-ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`AA`) REFERENCES `t1` (`A`))
+ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `fk_t2` FOREIGN KEY (`AA`) REFERENCES `t1` (`A`))
DELETE FROM t1 WHERE C=1;
-ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`AA`) REFERENCES `t1` (`A`))
+ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `fk_t2` FOREIGN KEY (`AA`) REFERENCES `t1` (`A`))
DELETE FROM t1 WHERE d=1;
-ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`AA`) REFERENCES `t1` (`A`))
+ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `fk_t2` FOREIGN KEY (`AA`) REFERENCES `t1` (`A`))
DELETE FROM t1 WHERE D=1;
-ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`AA`) REFERENCES `t1` (`A`))
+ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `fk_t2` FOREIGN KEY (`AA`) REFERENCES `t1` (`A`))
DROP TABLE t2, t1;
# virtual columns case too
CREATE TABLE t1 (a INT, b INT GENERATED ALWAYS AS (a) VIRTUAL) ENGINE = InnoDB;
@@ -916,11 +916,12 @@ t1 CREATE TABLE `t1` (
`a1` int(11) DEFAULT NULL,
`a3` int(11) DEFAULT NULL,
KEY `fk_1` (`a1`,`a3`),
- CONSTRAINT `fk_1` FOREIGN KEY (`a1`, `a3`) REFERENCES `parent` (`a`, `b`) ON DELETE SET NULL ON UPDATE CASCADE,
- CONSTRAINT `fk_a` FOREIGN KEY (`a1`, `a3`) REFERENCES `parent` (`a`, `b`) ON DELETE SET NULL ON UPDATE CASCADE
+ CONSTRAINT `fk_a` FOREIGN KEY (`a1`, `a3`) REFERENCES `parent` (`a`, `b`) ON DELETE SET NULL ON UPDATE CASCADE,
+ CONSTRAINT `fk_1` FOREIGN KEY (`a1`, `a3`) REFERENCES `parent` (`a`, `b`) ON DELETE SET NULL ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=latin1
CHECK TABLE t1;
Table Op Msg_type Msg_text
+test.t1 check Note Found 2 foreign keys
test.t1 check status OK
ALTER TABLE t1 CHANGE a3 a4 INT;
SHOW CREATE TABLE t1;
@@ -929,11 +930,12 @@ t1 CREATE TABLE `t1` (
`a1` int(11) DEFAULT NULL,
`a4` int(11) DEFAULT NULL,
KEY `fk_1` (`a1`,`a4`),
- CONSTRAINT `fk_1` FOREIGN KEY (`a1`, `a4`) REFERENCES `parent` (`a`, `b`) ON DELETE SET NULL ON UPDATE CASCADE,
- CONSTRAINT `fk_a` FOREIGN KEY (`a1`, `a4`) REFERENCES `parent` (`a`, `b`) ON DELETE SET NULL ON UPDATE CASCADE
+ CONSTRAINT `fk_a` FOREIGN KEY (`a1`, `a4`) REFERENCES `parent` (`a`, `b`) ON DELETE SET NULL ON UPDATE CASCADE,
+ CONSTRAINT `fk_1` FOREIGN KEY (`a1`, `a4`) REFERENCES `parent` (`a`, `b`) ON DELETE SET NULL ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=latin1
CHECK TABLE t1;
Table Op Msg_type Msg_text
+test.t1 check Note Found 2 foreign keys
test.t1 check status OK
ALTER TABLE parent CHANGE b c INT;
SHOW CREATE TABLE t1;
@@ -942,11 +944,12 @@ t1 CREATE TABLE `t1` (
`a1` int(11) DEFAULT NULL,
`a4` int(11) DEFAULT NULL,
KEY `fk_1` (`a1`,`a4`),
- CONSTRAINT `fk_1` FOREIGN KEY (`a1`, `a4`) REFERENCES `parent` (`a`, `c`) ON DELETE SET NULL ON UPDATE CASCADE,
- CONSTRAINT `fk_a` FOREIGN KEY (`a1`, `a4`) REFERENCES `parent` (`a`, `c`) ON DELETE SET NULL ON UPDATE CASCADE
+ CONSTRAINT `fk_a` FOREIGN KEY (`a1`, `a4`) REFERENCES `parent` (`a`, `c`) ON DELETE SET NULL ON UPDATE CASCADE,
+ CONSTRAINT `fk_1` FOREIGN KEY (`a1`, `a4`) REFERENCES `parent` (`a`, `c`) ON DELETE SET NULL ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=latin1
CHECK TABLE t1;
Table Op Msg_type Msg_text
+test.t1 check Note Found 2 foreign keys
test.t1 check status OK
DROP TABLE t1, parent;
#
diff --git a/mysql-test/suite/innodb/r/innodb-fk-virtual.result b/mysql-test/suite/innodb/r/innodb-fk-virtual.result
index a79cd133aa3..cdc4189e623 100644
--- a/mysql-test/suite/innodb/r/innodb-fk-virtual.result
+++ b/mysql-test/suite/innodb/r/innodb-fk-virtual.result
@@ -25,7 +25,7 @@ b CREATE TABLE `b` (
`p_cola` int(10) DEFAULT NULL,
`c_cola` int(10) GENERATED ALWAYS AS (`cola` + 2) VIRTUAL,
KEY `p_cola_fk` (`p_cola`),
- CONSTRAINT `p_cola_fk` FOREIGN KEY (`p_cola`) REFERENCES `a` (`p_cola`)
+ CONSTRAINT `p_cola_fk` FOREIGN KEY (`p_cola`) REFERENCES `a` (`p_cola`) ON DELETE RESTRICT ON UPDATE RESTRICT
) ENGINE=InnoDB DEFAULT CHARSET=latin1
alter table b add constraint `v_cola_fk`
foreign key (v_cola) references a (v_cola)
@@ -42,8 +42,8 @@ b CREATE TABLE `b` (
`c_cola` int(10) GENERATED ALWAYS AS (`cola` + 2) VIRTUAL,
KEY `p_cola_fk` (`p_cola`),
KEY `v_cola_fk` (`v_cola`),
- CONSTRAINT `p_cola_fk` FOREIGN KEY (`p_cola`) REFERENCES `a` (`p_cola`),
- CONSTRAINT `v_cola_fk` FOREIGN KEY (`v_cola`) REFERENCES `a` (`v_cola`)
+ CONSTRAINT `p_cola_fk` FOREIGN KEY (`p_cola`) REFERENCES `a` (`p_cola`) ON DELETE RESTRICT ON UPDATE RESTRICT,
+ CONSTRAINT `v_cola_fk` FOREIGN KEY (`v_cola`) REFERENCES `a` (`v_cola`) ON DELETE RESTRICT ON UPDATE RESTRICT
) ENGINE=InnoDB DEFAULT CHARSET=latin1
alter table b add constraint `c_cola_fk`
foreign key (c_cola) references a (cola)
@@ -61,9 +61,9 @@ b CREATE TABLE `b` (
KEY `p_cola_fk` (`p_cola`),
KEY `v_cola_fk` (`v_cola`),
KEY `c_cola_fk` (`c_cola`),
- CONSTRAINT `c_cola_fk` FOREIGN KEY (`c_cola`) REFERENCES `a` (`cola`),
- CONSTRAINT `p_cola_fk` FOREIGN KEY (`p_cola`) REFERENCES `a` (`p_cola`),
- CONSTRAINT `v_cola_fk` FOREIGN KEY (`v_cola`) REFERENCES `a` (`v_cola`)
+ CONSTRAINT `p_cola_fk` FOREIGN KEY (`p_cola`) REFERENCES `a` (`p_cola`) ON DELETE RESTRICT ON UPDATE RESTRICT,
+ CONSTRAINT `v_cola_fk` FOREIGN KEY (`v_cola`) REFERENCES `a` (`v_cola`) ON DELETE RESTRICT ON UPDATE RESTRICT,
+ CONSTRAINT `c_cola_fk` FOREIGN KEY (`c_cola`) REFERENCES `a` (`cola`) ON DELETE RESTRICT ON UPDATE RESTRICT
) ENGINE=InnoDB DEFAULT CHARSET=latin1
insert into a(cola) values (12);
select * from a;
diff --git a/mysql-test/suite/innodb/r/innodb-fk-warnings.result b/mysql-test/suite/innodb/r/innodb-fk-warnings.result
index 99b16dc1e9c..90ce03b91f8 100644
--- a/mysql-test/suite/innodb/r/innodb-fk-warnings.result
+++ b/mysql-test/suite/innodb/r/innodb-fk-warnings.result
@@ -34,7 +34,7 @@ create table t2(a int, b int, foreign key (a) references t1(a), foreign key (b)
ERROR HY000: Can't create table `test`.`t2` (errno: 150 "Foreign key constraint is incorrectly formed")
show warnings;
Level Code Message
-Warning 150 Create table `test`.`t2` with foreign key (b) constraint failed. There is no index in the referenced table where the referenced columns appear as the first columns.
+Warning 150 Create table `test`.`t2` with foreign key `fk_t2_2` constraint failed. There is no index in the referenced table where the referenced columns appear as the first columns.
Error 1005 Can't create table `test`.`t2` (errno: 150 "Foreign key constraint is incorrectly formed")
Warning 1215 Cannot add foreign key constraint for `t2`
drop table t1;
@@ -57,12 +57,9 @@ Warning 1215 Cannot add foreign key constraint for `t2`
drop table t2, t1;
create table t1 (f1 integer primary key) engine=innodb;
alter table t1 add constraint c1 foreign key (f1) references t11(f1);
-ERROR HY000: Can't create table `test`.`t1` (errno: 150 "Foreign key constraint is incorrectly formed")
+ERROR 42S02: Table 'test.t11' doesn't exist
show warnings;
Level Code Message
-Warning 150 Alter table `test`.`t1` with foreign key `c1` constraint failed. Referenced table `test`.`t11` not found in the data dictionary.
-Error 1005 Can't create table `test`.`t1` (errno: 150 "Foreign key constraint is incorrectly formed")
-Warning 1215 Cannot add foreign key constraint for `t1`
drop table t1;
create temporary table t1(a int not null primary key, b int, key(b)) engine=innodb;
create temporary table t2(a int, foreign key(a) references t1(a)) engine=innodb;
@@ -80,12 +77,10 @@ Warning 150 Alter table `mysqld.1`.`t1` with foreign key constraint failed. Ref
Error 1005 Can't create table `test`.`#sql-temporary` (errno: 150 "Foreign key constraint is incorrectly formed")
Warning 1215 Cannot add foreign key constraint
create temporary table t2(a int, foreign key(a) references t1(a)) engine=innodb;
-ERROR HY000: Can't create table `test`.`t2` (errno: 150 "Foreign key constraint is incorrectly formed")
+ERROR 42S02: Table 'test.t1' doesn't exist
show warnings;
Level Code Message
-Warning 150 Create table `test`.`t2` with foreign key constraint failed. Temporary tables can't have foreign key constraints.
-Error 1005 Can't create table `test`.`t2` (errno: 150 "Foreign key constraint is incorrectly formed")
-Warning 1215 Cannot add foreign key constraint for `t2`
+Error 1239 Incorrect foreign key definition for 't1': referenced table not found
alter table t1 add foreign key(b) references t1(a);
ERROR HY000: Can't create table `test`.`t1` (errno: 150 "Foreign key constraint is incorrectly formed")
show warnings;
@@ -120,16 +115,14 @@ create table t2(a int not null, foreign key(a) references t1(f1) on delete set n
ERROR HY000: Can't create table `test`.`t2` (errno: 150 "Foreign key constraint is incorrectly formed")
show warnings;
Level Code Message
-Warning 150 Create table `test`.`t2` with foreign key (a) constraint failed. You have defined a SET NULL condition but column 'a' is defined as NOT NULL.
+Warning 150 Create table `test`.`t2` with foreign key `fk_t2` constraint failed. You have defined a SET NULL condition but column 'a' is defined as NOT NULL.
Error 1005 Can't create table `test`.`t2` (errno: 150 "Foreign key constraint is incorrectly formed")
Warning 1215 Cannot add foreign key constraint for `t2`
drop table t1;
create table t1 (id int not null primary key, f1 int, f2 int, key(f1)) engine=innodb;
create table t2(a char(20), key(a), foreign key(a) references t1(f1)) engine=innodb;
-ERROR HY000: Can't create table `test`.`t2` (errno: 150 "Foreign key constraint is incorrectly formed")
+ERROR 42000: Incorrect foreign key definition for 'a': foreign-referenced fields type mismatch
show warnings;
Level Code Message
-Warning 150 Create table `test`.`t2` with foreign key (a) constraint failed. Field type or character set for column 'a' does not mach referenced column 'f1'.
-Error 1005 Can't create table `test`.`t2` (errno: 150 "Foreign key constraint is incorrectly formed")
-Warning 1215 Cannot add foreign key constraint for `t2`
+Error 1239 Incorrect foreign key definition for 'a': foreign-referenced fields type mismatch
drop table t1;
diff --git a/mysql-test/suite/innodb/r/innodb-fk.result b/mysql-test/suite/innodb/r/innodb-fk.result
index d3c1aa77eaf..d3828e6a942 100644
--- a/mysql-test/suite/innodb/r/innodb-fk.result
+++ b/mysql-test/suite/innodb/r/innodb-fk.result
@@ -49,12 +49,10 @@ PRIMARY KEY (`id`),
CONSTRAINT fk2 FOREIGN KEY (f2) REFERENCES t1 (`id`) ON DELETE CASCADE,
CONSTRAINT fk3 FOREIGN KEY (f3) REFERENCES t3 (id) ON DELETE CASCADE
) ENGINE=InnoDB;
-ERROR HY000: Can't create table `test`.`t2` (errno: 150 "Foreign key constraint is incorrectly formed")
+ERROR 42S02: Table 'test.t3' doesn't exist
show warnings;
Level Code Message
-Warning 150 Create table `test`.`t2` with foreign key `fk3` constraint failed. Referenced table `test`.`t3` not found in the data dictionary.
-Error 1005 Can't create table `test`.`t2` (errno: 150 "Foreign key constraint is incorrectly formed")
-Warning 1215 Cannot add foreign key constraint for `t2`
+Error 1239 Incorrect foreign key definition for 't3': referenced table not found
CREATE TABLE t2 (
id int(11) NOT NULL AUTO_INCREMENT,
f2 int(11) NOT NULL,
@@ -63,12 +61,9 @@ PRIMARY KEY (`id`),
CONSTRAINT fk2 FOREIGN KEY (f2) REFERENCES t1 (`id`) ON DELETE CASCADE
) ENGINE=InnoDB;
ALTER TABLE t2 ADD CONSTRAINT fk3 FOREIGN KEY (f3) REFERENCES t3 (id) ON DELETE CASCADE;
-ERROR HY000: Can't create table `test`.`t2` (errno: 150 "Foreign key constraint is incorrectly formed")
+ERROR 42S02: Table 'test.t3' doesn't exist
show warnings;
Level Code Message
-Warning 150 Alter table `test`.`t2` with foreign key `fk3` constraint failed. Referenced table `test`.`t3` not found in the data dictionary.
-Error 1005 Can't create table `test`.`t2` (errno: 150 "Foreign key constraint is incorrectly formed")
-Warning 1215 Cannot add foreign key constraint for `t2`
drop table t2;
drop table t1;
CREATE DATABASE kg_test1;
@@ -96,7 +91,7 @@ CREATE TABLE `kg_test2`.`person2` (
PRIMARY KEY (`Id`),
CONSTRAINT `fk_person_group` FOREIGN KEY (`Id`) REFERENCES `group` (`Id`)
) ENGINE=INNODB DEFAULT CHARSET=utf8;
-ERROR HY000: Can't create table `kg_test2`.`person2` (errno: 150 "Foreign key constraint is incorrectly formed")
+ERROR 42S02: Table 'kg_test2.group' doesn't exist
CREATE TABLE `kg_test2`.`person2` (
`Id` INT(11) NOT NULL AUTO_INCREMENT,
`Name` VARCHAR(50) NOT NULL,
@@ -133,9 +128,9 @@ Table Create Table
`id_depart` int(10) unsigned NOT NULL,
`id_depart_in` int(10) unsigned NOT NULL,
PRIMARY KEY (`id_depart`,`id_depart_in`),
- KEY `id_depart_in` (`id_depart_in`),
+ KEY `fk_#departaments_tree` (`id_depart_in`),
CONSTRAINT `#departaments_tree_ibfk_1` FOREIGN KEY (`id_depart`) REFERENCES `#departaments` (`id_depart`),
- CONSTRAINT `#departaments_tree_ibfk_2` FOREIGN KEY (`id_depart_in`) REFERENCES `#departaments` (`id_depart`)
+ CONSTRAINT `fk_#departaments_tree` FOREIGN KEY (`id_depart_in`) REFERENCES `#departaments` (`id_depart`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
DROP TABLE `#departaments_tree`;
DROP TABLE `#departaments`;
@@ -148,7 +143,7 @@ KEY `a` (`a`),
CONSTRAINT `boroda_ibfk_1` FOREIGN KEY (`a`) REFERENCES `boroda` (`id`)
) ENGINE=INNODB DEFAULT CHARSET=utf8;
ALTER TABLE `boroda`
- ADD FOREIGN KEY (`b`) REFERENCES `boroda`(`id`);
+ ADD FOREIGN KEY `boroda_ibfk_2` (`b`) REFERENCES `boroda`(`id`);
ALTER TABLE `boroda` DROP FOREIGN KEY `boroda_ibfk_2`;
RENAME TABLE `boroda` TO `#boroda`;
ALTER TABLE `#boroda`
@@ -161,9 +156,9 @@ Table Create Table
`b` int(11) unsigned DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `a` (`a`),
- KEY `b` (`b`),
- CONSTRAINT `#boroda_ibfk_1` FOREIGN KEY (`a`) REFERENCES `#boroda` (`id`),
- CONSTRAINT `#boroda_ibfk_2` FOREIGN KEY (`b`) REFERENCES `#boroda` (`id`)
+ KEY `fk_#boroda` (`b`),
+ CONSTRAINT `boroda_ibfk_1` FOREIGN KEY (`a`) REFERENCES `#boroda` (`id`),
+ CONSTRAINT `fk_#boroda` FOREIGN KEY (`b`) REFERENCES `#boroda` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
DROP TABLE `#boroda`;
CREATE TABLE `boroda` (
@@ -185,14 +180,15 @@ bor#oda CREATE TABLE `bor#oda` (
`b` int(11) unsigned DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `a` (`a`),
- KEY `b` (`b`),
- CONSTRAINT `bor#oda_ibfk_1` FOREIGN KEY (`a`) REFERENCES `bor#oda` (`id`),
- CONSTRAINT `bor#oda_ibfk_2` FOREIGN KEY (`b`) REFERENCES `bor#oda` (`id`)
+ KEY `fk_bor#oda` (`b`),
+ CONSTRAINT `boroda_ibfk_1` FOREIGN KEY (`a`) REFERENCES `bor#oda` (`id`),
+ CONSTRAINT `fk_bor#oda` FOREIGN KEY (`b`) REFERENCES `bor#oda` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
DROP TABLE `bor#oda`;
#
# MDEV-21127 Assertion `(size_t)(ptr - buf) < MAX_TEXT - 4' failed in key_text::key_text
#
+create table tx (ax char(255) unique, bx char(255) unique) engine innodb;
CREATE TABLE t1 (
a012345678901234567890123456789012345678901 char(255),
b char(255),
@@ -205,4 +201,5 @@ b int,
c0123456789012345678 int,
FOREIGN KEY (a012345678901234567,c0123456789012345678,b) REFERENCES tx (x1,x2,x3)
) ENGINE=InnoDB;
-ERROR HY000: Can't create table `test`.`t1` (errno: 150 "Foreign key constraint is incorrectly formed")
+ERROR 42000: Incorrect foreign key definition for 'x1': referenced field not found
+drop table tx;
diff --git a/mysql-test/suite/innodb/r/innodb-index,debug.rdiff b/mysql-test/suite/innodb/r/innodb-index,debug.rdiff
deleted file mode 100644
index 2740e440cd5..00000000000
--- a/mysql-test/suite/innodb/r/innodb-index,debug.rdiff
+++ /dev/null
@@ -1,10 +0,0 @@
---- innodb-index.result
-+++ innodb-index.reject
-@@ -1851,6 +1851,7 @@
- #
- # MDEV-15325 Incomplete validation of missing tablespace during recovery
- #
-+SET GLOBAL DEBUG_DBUG='+d,fil_names_write_bogus';
- CREATE TABLE t1(f1 INT PRIMARY KEY)ENGINE=InnoDB;
- CREATE TABLE t2(f1 INT PRIMARY KEY)ENGINE=InnoDB;
- # Kill the server
diff --git a/mysql-test/suite/innodb/r/innodb-index-online-fk.result b/mysql-test/suite/innodb/r/innodb-index-online-fk.result
index a3041985519..6fc8273637e 100644
--- a/mysql-test/suite/innodb/r/innodb-index-online-fk.result
+++ b/mysql-test/suite/innodb/r/innodb-index-online-fk.result
@@ -21,7 +21,7 @@ test/fk_1 a2 b 0
ALTER TABLE child ADD CONSTRAINT fk_1 FOREIGN KEY (a2)
REFERENCES parent(b) ON DELETE SET NULL ON UPDATE CASCADE,
ALGORITHM = INPLACE;
-ERROR HY000: Duplicate FOREIGN KEY constraint name 'test/fk_1'
+ERROR HY000: Duplicate FOREIGN KEY constraint name 'fk_1'
SET foreign_key_checks = 1;
INSERT INTO child VALUES(1,2),(2,3);
INSERT INTO child VALUES(4,4);
diff --git a/mysql-test/suite/innodb/r/innodb-index.result b/mysql-test/suite/innodb/r/innodb-index.result
index 7e58bfe38e5..908090f542a 100644
--- a/mysql-test/suite/innodb/r/innodb-index.result
+++ b/mysql-test/suite/innodb/r/innodb-index.result
@@ -441,8 +441,8 @@ create table t1(a int not null, b int not null, c int, primary key (a), key (b))
create table t3(a int not null, c int not null, d int, primary key (a), key (c)) engine = innodb;
create table t4(a int not null, d int not null, e int, primary key (a), key (d)) engine = innodb;
create table t2(a int not null, b int, c int, d int, e int,
-foreign key (b) references t1(b) on delete set null,
-foreign key (c) references t3(c), foreign key (d) references t4(d) on update set null)
+foreign key b (b) references t1(b) on delete set null,
+foreign key c (c) references t3(c), foreign key d (d) references t4(d) on update set null)
engine = innodb;
alter table t1 drop index b;
ERROR HY000: Cannot drop index 'b': needed in a foreign key constraint
@@ -455,21 +455,21 @@ ERROR HY000: Cannot drop index 'b': needed in a foreign key constraint
alter table t2 drop index b, drop index c, drop index d;
ERROR HY000: Cannot drop index 'b': needed in a foreign key constraint
alter table t2 MODIFY b INT NOT NULL, ALGORITHM=COPY;
-ERROR HY000: Cannot change column 'b': used in a foreign key constraint 't2_ibfk_1'
+ERROR HY000: Cannot change column 'b': used in a foreign key constraint 'b'
set @old_sql_mode = @@sql_mode;
set @@sql_mode = 'STRICT_TRANS_TABLES';
alter table t2 MODIFY b INT NOT NULL, ALGORITHM=INPLACE;
-ERROR HY000: Column 'b' cannot be NOT NULL: needed in a foreign key constraint 'test/t2_ibfk_1' SET NULL
+ERROR HY000: Column 'b' cannot be NOT NULL: needed in a foreign key constraint 'test/b' SET NULL
set @@sql_mode = @old_sql_mode;
SET FOREIGN_KEY_CHECKS=0;
alter table t2 DROP COLUMN b, ALGORITHM=COPY;
-ERROR HY000: Cannot drop column 'b': needed in a foreign key constraint 't2_ibfk_1'
+ERROR 42000: Incorrect foreign key definition for 'b': foreign field not found
alter table t2 DROP COLUMN b;
-ERROR HY000: Cannot drop column 'b': needed in a foreign key constraint 'test/t2_ibfk_1'
+ERROR 42000: Incorrect foreign key definition for 'b': foreign field not found
alter table t1 DROP COLUMN b, ALGORITHM=COPY;
-ERROR HY000: Cannot drop column 'b': needed in a foreign key constraint 't2_ibfk_1' of table `test`.`t2`
+ERROR HY000: Cannot drop column 'b': needed in a foreign key constraint 'b' of table `test`.`t2`
alter table t1 DROP COLUMN b;
-ERROR HY000: Cannot drop column 'b': needed in a foreign key constraint 'test/t2_ibfk_1' of table `test`.`t2`
+ERROR HY000: Cannot drop column 'b': needed in a foreign key constraint 'test/b' of table `test`.`t2`
SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS;
create unique index dc on t2 (d,c);
affected rows: 0
@@ -480,10 +480,10 @@ info: Records: 0 Duplicates: 0 Warnings: 0
set @@sql_mode = 'STRICT_TRANS_TABLES';
alter table t2 add primary key (alpha), change a alpha int,
change b beta int not null, change c charlie int not null;
-ERROR HY000: Column 'b' cannot be NOT NULL: needed in a foreign key constraint 'test/t2_ibfk_1' SET NULL
+ERROR HY000: Column 'b' cannot be NOT NULL: needed in a foreign key constraint 'test/b' SET NULL
alter table t2 add primary key (alpha), change a alpha int,
change c charlie int not null, change d delta int not null;
-ERROR HY000: Column 'd' cannot be NOT NULL: needed in a foreign key constraint 'test/t2_ibfk_3' SET NULL
+ERROR HY000: Column 'd' cannot be NOT NULL: needed in a foreign key constraint 'test/d' SET NULL
alter table t2 add primary key (alpha), change a alpha int,
change b beta int, modify c int not null;
affected rows: 0
@@ -537,9 +537,9 @@ t2 CREATE TABLE `t2` (
UNIQUE KEY `dc` (`d`,`c`),
KEY `c` (`c`),
KEY `beta` (`beta`),
- CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`beta`) REFERENCES `t1` (`b`) ON DELETE SET NULL,
- CONSTRAINT `t2_ibfk_2` FOREIGN KEY (`c`) REFERENCES `t3` (`c`),
- CONSTRAINT `t2_ibfk_3` FOREIGN KEY (`d`) REFERENCES `t4` (`d`) ON UPDATE SET NULL
+ CONSTRAINT `b` FOREIGN KEY (`beta`) REFERENCES `t1` (`b`) ON DELETE SET NULL,
+ CONSTRAINT `c` FOREIGN KEY (`c`) REFERENCES `t3` (`c`),
+ CONSTRAINT `d` FOREIGN KEY (`d`) REFERENCES `t4` (`d`) ON UPDATE SET NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1
delete from t1;
ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t4`, CONSTRAINT `dc` FOREIGN KEY (`a`) REFERENCES `t1` (`a`))
diff --git a/mysql-test/suite/innodb/r/innodb-truncate.result b/mysql-test/suite/innodb/r/innodb-truncate.result
index 8610a892cc6..cc0e982b152 100644
--- a/mysql-test/suite/innodb/r/innodb-truncate.result
+++ b/mysql-test/suite/innodb/r/innodb-truncate.result
@@ -7,7 +7,7 @@
CREATE TABLE t1 (pk INT PRIMARY KEY) ENGINE=INNODB;
CREATE TABLE t2 (fk INT NOT NULL, FOREIGN KEY (fk) REFERENCES t1 (pk)) ENGINE=INNODB;
TRUNCATE TABLE t1;
-ERROR 42000: Cannot truncate a table referenced in a foreign key constraint (`test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`fk`) REFERENCES `test`.`t1` (`pk`))
+ERROR 42000: Cannot truncate a table referenced in a foreign key constraint (`test`.`t2`, CONSTRAINT `fk_t2` FOREIGN KEY (`fk`) REFERENCES `test`.`t1` (`pk`))
# Truncation of child should succeed.
TRUNCATE TABLE t2;
DROP TABLE t2;
@@ -32,7 +32,7 @@ TRUNCATE TABLE t2;
TRUNCATE TABLE t3;
SET @@SESSION.foreign_key_checks = 1;
TRUNCATE TABLE t1;
-ERROR 42000: Cannot truncate a table referenced in a foreign key constraint (`test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`fk`) REFERENCES `test`.`t1` (`pk`))
+ERROR 42000: Cannot truncate a table referenced in a foreign key constraint (`test`.`t2`, CONSTRAINT `fk_t2` FOREIGN KEY (`fk`) REFERENCES `test`.`t1` (`pk`))
TRUNCATE TABLE t2;
TRUNCATE TABLE t3;
LOCK TABLES t1 WRITE;
@@ -40,7 +40,7 @@ SET @@SESSION.foreign_key_checks = 0;
TRUNCATE TABLE t1;
SET @@SESSION.foreign_key_checks = 1;
TRUNCATE TABLE t1;
-ERROR 42000: Cannot truncate a table referenced in a foreign key constraint (`test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`fk`) REFERENCES `test`.`t1` (`pk`))
+ERROR 42000: Cannot truncate a table referenced in a foreign key constraint (`test`.`t2`, CONSTRAINT `fk_t2` FOREIGN KEY (`fk`) REFERENCES `test`.`t1` (`pk`))
UNLOCK TABLES;
DROP TABLE t3,t2,t1;
SET @@SESSION.foreign_key_checks = @old_foreign_key_checks;
@@ -86,8 +86,10 @@ CREATE TABLE t2 (f2 INT, FOREIGN KEY(f2) REFERENCES t1 (f2)) ENGINE=InnoDB;
CREATE TABLE t3 (a INT) ENGINE=InnoDB;
ERROR HY000: Can't create table `test`.`t3` (errno: 150 "Foreign key constraint is incorrectly formed")
ALTER TABLE t1 RENAME TO t3;
-ERROR HY000: Error on rename of './test/t1' to './test/t3' (errno: 150 "Foreign key constraint is incorrectly formed")
+ERROR 42S02: Table 'test.t3' doesn't exist
+SET FOREIGN_KEY_CHECKS= OFF;
ALTER TABLE t1 FORCE;
+SET FOREIGN_KEY_CHECKS= ON;
TRUNCATE TABLE t1;
-ERROR 42000: Cannot truncate a table referenced in a foreign key constraint (`test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`f2`) REFERENCES `test`.`t3` (`f2`))
+ERROR 42000: Cannot truncate a table referenced in a foreign key constraint (`test`.`t2`, CONSTRAINT `fk_t2` FOREIGN KEY (`f2`) REFERENCES `test`.`t1` (`f2`))
DROP TABLE t2, t1;
diff --git a/mysql-test/suite/innodb/r/innodb-wl5522-1.result b/mysql-test/suite/innodb/r/innodb-wl5522-1.result
index 55557a8fb99..9a742df6705 100644
--- a/mysql-test/suite/innodb/r/innodb-wl5522-1.result
+++ b/mysql-test/suite/innodb/r/innodb-wl5522-1.result
@@ -279,7 +279,7 @@ col_1_int col_2_varchar
2 a2
3 a3
INSERT INTO testdb_wl5522.t1_fk VALUES (100,'a100');
-ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`testdb_wl5522`.`t1_fk`, CONSTRAINT `t1_fk_ibfk_1` FOREIGN KEY (`col_2_varchar`) REFERENCES `t1` (`col_2_varchar`))
+ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`testdb_wl5522`.`t1_fk`, CONSTRAINT `fk_t1_fk` FOREIGN KEY (`col_2_varchar`) REFERENCES `t1` (`col_2_varchar`))
SET AUTOCOMMIT = 0;
INSERT INTO testdb_wl5522.t1_fk VALUES (4,'a4'),(5,'a5');
ROLLBACK;
diff --git a/mysql-test/suite/innodb/r/innodb.result b/mysql-test/suite/innodb/r/innodb.result
index 2313c415496..e77e82d57de 100644
--- a/mysql-test/suite/innodb/r/innodb.result
+++ b/mysql-test/suite/innodb/r/innodb.result
@@ -1565,7 +1565,7 @@ t2 CREATE TABLE `t2` (
PRIMARY KEY (`a`),
UNIQUE KEY `b_2` (`b`),
KEY `b` (`b`),
- CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`b`) REFERENCES `t1` (`id`)
+ CONSTRAINT `fk_t2` FOREIGN KEY (`b`) REFERENCES `t1` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
drop table t2;
create table t2 (a int auto_increment primary key, b int, foreign key (b) references t1(id), foreign key (b) references t1(id), unique(b)) engine=innodb;
@@ -1576,8 +1576,8 @@ t2 CREATE TABLE `t2` (
`b` int(11) DEFAULT NULL,
PRIMARY KEY (`a`),
UNIQUE KEY `b` (`b`),
- CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`b`) REFERENCES `t1` (`id`),
- CONSTRAINT `t2_ibfk_2` FOREIGN KEY (`b`) REFERENCES `t1` (`id`)
+ CONSTRAINT `fk_t2` FOREIGN KEY (`b`) REFERENCES `t1` (`id`),
+ CONSTRAINT `fk_t2_2` FOREIGN KEY (`b`) REFERENCES `t1` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
drop table t2, t1;
create table t1 (c char(10), index (c,c)) engine=innodb;
@@ -2407,7 +2407,7 @@ SELECT * FROM t1;
id
1
TRUNCATE t1;
-ERROR 42000: Cannot truncate a table referenced in a foreign key constraint (`test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`id`) REFERENCES `test`.`t1` (`id`))
+ERROR 42000: Cannot truncate a table referenced in a foreign key constraint (`test`.`t2`, CONSTRAINT `fk_t2` FOREIGN KEY (`id`) REFERENCES `test`.`t1` (`id`))
INSERT INTO t1 (id) VALUES (NULL);
SELECT * FROM t1;
id
@@ -2415,7 +2415,7 @@ id
2
DELETE FROM t1;
TRUNCATE t1;
-ERROR 42000: Cannot truncate a table referenced in a foreign key constraint (`test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`id`) REFERENCES `test`.`t1` (`id`))
+ERROR 42000: Cannot truncate a table referenced in a foreign key constraint (`test`.`t2`, CONSTRAINT `fk_t2` FOREIGN KEY (`id`) REFERENCES `test`.`t1` (`id`))
INSERT INTO t1 (id) VALUES (NULL);
SELECT * FROM t1;
id
@@ -2481,7 +2481,7 @@ INSERT INTO t2 VALUES(1);
DELETE FROM t1 WHERE id = 1;
ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `c1` FOREIGN KEY (`v`) REFERENCES `t1` (`id`))
DROP TABLE t1;
-ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `c1` FOREIGN KEY (`v`) REFERENCES `t1` (`id`))
+ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (c1)
SET FOREIGN_KEY_CHECKS=0;
DROP TABLE t1;
SET FOREIGN_KEY_CHECKS=1;
@@ -2567,29 +2567,29 @@ create table t4(a int primary key,constraint foreign key(a)references t3(a)) row
insert into t1 values(1);
insert into t3 values(1);
insert into t2 values(2);
-ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`a`) REFERENCES `t1` (`a`))
+ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `fk_t2` FOREIGN KEY (`a`) REFERENCES `t1` (`a`))
insert into t4 values(2);
-ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test`.`t4`, CONSTRAINT `t4_ibfk_1` FOREIGN KEY (`a`) REFERENCES `t3` (`a`))
+ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test`.`t4`, CONSTRAINT `fk_t4` FOREIGN KEY (`a`) REFERENCES `t3` (`a`))
insert into t2 values(1);
insert into t4 values(1);
update t1 set a=2;
-ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`a`) REFERENCES `t1` (`a`))
+ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `fk_t2` FOREIGN KEY (`a`) REFERENCES `t1` (`a`))
update t2 set a=2;
-ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`a`) REFERENCES `t1` (`a`))
+ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `fk_t2` FOREIGN KEY (`a`) REFERENCES `t1` (`a`))
update t3 set a=2;
-ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t4`, CONSTRAINT `t4_ibfk_1` FOREIGN KEY (`a`) REFERENCES `t3` (`a`))
+ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t4`, CONSTRAINT `fk_t4` FOREIGN KEY (`a`) REFERENCES `t3` (`a`))
update t4 set a=2;
-ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test`.`t4`, CONSTRAINT `t4_ibfk_1` FOREIGN KEY (`a`) REFERENCES `t3` (`a`))
+ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test`.`t4`, CONSTRAINT `fk_t4` FOREIGN KEY (`a`) REFERENCES `t3` (`a`))
truncate t1;
-ERROR 42000: Cannot truncate a table referenced in a foreign key constraint (`test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`a`) REFERENCES `test`.`t1` (`a`))
+ERROR 42000: Cannot truncate a table referenced in a foreign key constraint (`test`.`t2`, CONSTRAINT `fk_t2` FOREIGN KEY (`a`) REFERENCES `test`.`t1` (`a`))
truncate t3;
-ERROR 42000: Cannot truncate a table referenced in a foreign key constraint (`test`.`t4`, CONSTRAINT `t4_ibfk_1` FOREIGN KEY (`a`) REFERENCES `test`.`t3` (`a`))
+ERROR 42000: Cannot truncate a table referenced in a foreign key constraint (`test`.`t4`, CONSTRAINT `fk_t4` FOREIGN KEY (`a`) REFERENCES `test`.`t3` (`a`))
truncate t2;
truncate t4;
truncate t1;
-ERROR 42000: Cannot truncate a table referenced in a foreign key constraint (`test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`a`) REFERENCES `test`.`t1` (`a`))
+ERROR 42000: Cannot truncate a table referenced in a foreign key constraint (`test`.`t2`, CONSTRAINT `fk_t2` FOREIGN KEY (`a`) REFERENCES `test`.`t1` (`a`))
truncate t3;
-ERROR 42000: Cannot truncate a table referenced in a foreign key constraint (`test`.`t4`, CONSTRAINT `t4_ibfk_1` FOREIGN KEY (`a`) REFERENCES `test`.`t3` (`a`))
+ERROR 42000: Cannot truncate a table referenced in a foreign key constraint (`test`.`t4`, CONSTRAINT `fk_t4` FOREIGN KEY (`a`) REFERENCES `test`.`t3` (`a`))
drop table t4,t3,t2,t1;
create table t1 (a varchar(255) character set utf8,
b varchar(255) character set utf8,
@@ -2710,7 +2710,7 @@ drop table t2,t1;
CREATE TABLE t1(a INT, PRIMARY KEY(a)) ENGINE=InnoDB;
CREATE TABLE t2(a INT) ENGINE=InnoDB;
ALTER TABLE t2 ADD FOREIGN KEY (a) REFERENCES t1(a);
-ALTER TABLE t2 DROP FOREIGN KEY t2_ibfk_1;
+ALTER TABLE t2 DROP FOREIGN KEY fk_t2;
ALTER TABLE t2 ADD CONSTRAINT t2_ibfk_0 FOREIGN KEY (a) REFERENCES t1(a);
ALTER TABLE t2 DROP FOREIGN KEY t2_ibfk_0;
SHOW CREATE TABLE t2;
@@ -3042,9 +3042,9 @@ t2 CREATE TABLE `t2` (
`id` int(11) NOT NULL,
`f` int(11) NOT NULL,
PRIMARY KEY (`id`),
- KEY `f` (`f`),
- CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`f`) REFERENCES `t1` (`f`) ON DELETE CASCADE ON UPDATE CASCADE,
- CONSTRAINT `t2_t1` FOREIGN KEY (`id`) REFERENCES `t1` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
+ KEY `fk_t2` (`f`),
+ CONSTRAINT `t2_t1` FOREIGN KEY (`id`) REFERENCES `t1` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
+ CONSTRAINT `fk_t2` FOREIGN KEY (`f`) REFERENCES `t1` (`f`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=latin1
DROP TABLE t2, t1;
CREATE TABLE t1 (a INT, INDEX(a)) ENGINE=InnoDB;
@@ -3055,7 +3055,7 @@ ALTER TABLE t2 ADD FOREIGN KEY (a) REFERENCES t1 (a) ON DELETE SET NULL;
set @old_sql_mode = @@sql_mode;
set @@sql_mode = 'STRICT_TRANS_TABLES';
ALTER TABLE t2 MODIFY a INT NOT NULL;
-ERROR HY000: Column 'a' cannot be NOT NULL: needed in a foreign key constraint 'test/t2_ibfk_1' SET NULL
+ERROR HY000: Column 'a' cannot be NOT NULL: needed in a foreign key constraint 'test/fk_t2' SET NULL
set @@sql_mode = @old_sql_mode;
DELETE FROM t1;
DROP TABLE t2,t1;
diff --git a/mysql-test/suite/innodb/r/innodb_bug57904.result b/mysql-test/suite/innodb/r/innodb_bug57904.result
index 909f77b25d4..cbbb77ea722 100644
--- a/mysql-test/suite/innodb/r/innodb_bug57904.result
+++ b/mysql-test/suite/innodb/r/innodb_bug57904.result
@@ -17,10 +17,10 @@ SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS
WHERE table_name = 'product_order';
CONSTRAINT_CATALOG def
CONSTRAINT_SCHEMA test
-CONSTRAINT_NAME product_order_ibfk_1
+CONSTRAINT_NAME fk_product_order
UNIQUE_CONSTRAINT_CATALOG def
UNIQUE_CONSTRAINT_SCHEMA test
-UNIQUE_CONSTRAINT_NAME PRIMARY
+UNIQUE_CONSTRAINT_NAME fk_product_order
MATCH_OPTION NONE
UPDATE_RULE CASCADE
DELETE_RULE RESTRICT
@@ -28,13 +28,13 @@ TABLE_NAME product_order
REFERENCED_TABLE_NAME product
CONSTRAINT_CATALOG def
CONSTRAINT_SCHEMA test
-CONSTRAINT_NAME product_order_ibfk_2
+CONSTRAINT_NAME fk_product_order_2
UNIQUE_CONSTRAINT_CATALOG def
UNIQUE_CONSTRAINT_SCHEMA test
-UNIQUE_CONSTRAINT_NAME PRIMARY
+UNIQUE_CONSTRAINT_NAME fk_product_order_2
MATCH_OPTION NONE
-UPDATE_RULE RESTRICT
-DELETE_RULE RESTRICT
+UPDATE_RULE ???
+DELETE_RULE ???
TABLE_NAME product_order
REFERENCED_TABLE_NAME customer
DROP TABLE product_order;
diff --git a/mysql-test/suite/innodb/r/innodb_mysql.result b/mysql-test/suite/innodb/r/innodb_mysql.result
index 595a56a8bef..aa9ab6c176f 100644
--- a/mysql-test/suite/innodb/r/innodb_mysql.result
+++ b/mysql-test/suite/innodb/r/innodb_mysql.result
@@ -322,7 +322,7 @@ INSERT INTO t1 VALUES (1);
INSERT INTO t2 VALUES (1);
DELETE IGNORE FROM t1 WHERE i = 1;
Warnings:
-Warning 1451 Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`i`) REFERENCES `t1` (`i`) ON DELETE NO ACTION)
+Warning 1451 Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `fk_t2` FOREIGN KEY (`i`) REFERENCES `t1` (`i`) ON DELETE NO ACTION)
SELECT * FROM t1, t2;
i i
1 1
@@ -362,13 +362,13 @@ SELECT COUNT(*) FROM t2 LEFT JOIN t1 ON t2.fkey = t1.id
WHERE t1.name LIKE 'A%';
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range PRIMARY,name name 23 NULL 2 Using where; Using index
-1 SIMPLE t2 ref fkey fkey 5 test.t1.id 1 Using index
+1 SIMPLE t2 ref fk_t2 fk_t2 5 test.t1.id 1 Using index
EXPLAIN
SELECT COUNT(*) FROM t2 LEFT JOIN t1 ON t2.fkey = t1.id
WHERE t1.name LIKE 'A%' OR FALSE;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range PRIMARY,name name 23 NULL 2 Using where; Using index
-1 SIMPLE t2 ref fkey fkey 5 test.t1.id 1 Using index
+1 SIMPLE t2 ref fk_t2 fk_t2 5 test.t1.id 1 Using index
DROP TABLE t1,t2;
CREATE TABLE t1 (
id int NOT NULL,
@@ -2138,7 +2138,7 @@ t2 CREATE TABLE `t2` (
CONSTRAINT `c1` FOREIGN KEY (`c`) REFERENCES `t1` (`a`) ON DELETE NO ACTION,
CONSTRAINT `c2` FOREIGN KEY (`c`) REFERENCES `t1` (`a`) ON UPDATE NO ACTION,
CONSTRAINT `f3` FOREIGN KEY (`c`) REFERENCES `t1` (`a`) ON UPDATE NO ACTION,
- CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`c`) REFERENCES `t1` (`a`) ON UPDATE NO ACTION
+ CONSTRAINT `fk_t2` FOREIGN KEY (`c`) REFERENCES `t1` (`a`) ON UPDATE NO ACTION
) ENGINE=InnoDB DEFAULT CHARSET=latin1
DROP TABLE t2;
DROP TABLE t1;
@@ -2442,7 +2442,7 @@ INSERT INTO t2 VALUES (3,2);
SET AUTOCOMMIT = 0;
START TRANSACTION;
TRUNCATE TABLE t1;
-ERROR 42000: Cannot truncate a table referenced in a foreign key constraint (`test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`t1_id`) REFERENCES `test`.`t1` (`id`))
+ERROR 42000: Cannot truncate a table referenced in a foreign key constraint (`test`.`t2`, CONSTRAINT `fk_t2` FOREIGN KEY (`t1_id`) REFERENCES `test`.`t1` (`id`))
SELECT * FROM t1;
id
1
@@ -2454,7 +2454,7 @@ id
2
START TRANSACTION;
TRUNCATE TABLE t1;
-ERROR 42000: Cannot truncate a table referenced in a foreign key constraint (`test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`t1_id`) REFERENCES `test`.`t1` (`id`))
+ERROR 42000: Cannot truncate a table referenced in a foreign key constraint (`test`.`t2`, CONSTRAINT `fk_t2` FOREIGN KEY (`t1_id`) REFERENCES `test`.`t1` (`id`))
SELECT * FROM t1;
id
1
@@ -2472,7 +2472,7 @@ id
2
COMMIT;
TRUNCATE TABLE t1;
-ERROR 42000: Cannot truncate a table referenced in a foreign key constraint (`test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`t1_id`) REFERENCES `test`.`t1` (`id`))
+ERROR 42000: Cannot truncate a table referenced in a foreign key constraint (`test`.`t2`, CONSTRAINT `fk_t2` FOREIGN KEY (`t1_id`) REFERENCES `test`.`t1` (`id`))
SELECT * FROM t1;
id
1
@@ -2484,7 +2484,7 @@ id
1
2
TRUNCATE TABLE t1;
-ERROR 42000: Cannot truncate a table referenced in a foreign key constraint (`test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`t1_id`) REFERENCES `test`.`t1` (`id`))
+ERROR 42000: Cannot truncate a table referenced in a foreign key constraint (`test`.`t2`, CONSTRAINT `fk_t2` FOREIGN KEY (`t1_id`) REFERENCES `test`.`t1` (`id`))
ROLLBACK;
SELECT * FROM t1;
id
@@ -2523,9 +2523,9 @@ INSERT INTO t4 VALUES (1),(2),(3),(4),(5);
INSERT INTO t5 VALUES (1);
DELETE t5 FROM t4 LEFT JOIN t5 ON t4.a= t5.a;
DELETE t2, t1 FROM t2 INNER JOIN t1 ON (t2.aid = t1.id) WHERE t2.id = 1;
-ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t3`, CONSTRAINT `t3_ibfk_1` FOREIGN KEY (`bid`) REFERENCES `t2` (`id`))
+ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t3`, CONSTRAINT `fk_t3` FOREIGN KEY (`bid`) REFERENCES `t2` (`id`))
DELETE t2, t1 FROM t2 INNER JOIN t1 ON (t2.aid = t1.id) WHERE t2.id = 1;
-ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t3`, CONSTRAINT `t3_ibfk_1` FOREIGN KEY (`bid`) REFERENCES `t2` (`id`))
+ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t3`, CONSTRAINT `fk_t3` FOREIGN KEY (`bid`) REFERENCES `t2` (`id`))
DELETE IGNORE t2, t1 FROM t2 INNER JOIN t1 ON (t2.aid = t1.id) WHERE t2.id = 1;
DROP TABLE t3;
DROP TABLE t2;
@@ -2624,7 +2624,7 @@ END||
SET @a:=0;
** Errors in the trigger causes the statement to abort.
DELETE IGNORE t1 FROM t3 LEFT JOIN t1 ON t1.i=t3.i;
-ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test`.`t4`, CONSTRAINT `t4_ibfk_1` FOREIGN KEY (`t1i`) REFERENCES `t1` (`i`))
+ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test`.`t4`, CONSTRAINT `fk_t4` FOREIGN KEY (`t1i`) REFERENCES `t1` (`i`))
SELECT * FROM t1 LEFT JOIN t3 ON t1.i=t3.i;
i i
1 1
diff --git a/mysql-test/suite/innodb/r/instant_alter.result b/mysql-test/suite/innodb/r/instant_alter.result
index 3ee879fd925..52307070a8c 100644
--- a/mysql-test/suite/innodb/r/instant_alter.result
+++ b/mysql-test/suite/innodb/r/instant_alter.result
@@ -463,7 +463,7 @@ CREATE TABLE t2 (b INT PRIMARY KEY, FOREIGN KEY(b) REFERENCES t1(a))
ENGINE=InnoDB ROW_FORMAT=REDUNDANT;
INSERT INTO t1 SET a=1;
INSERT INTO t2 SET b=1;
-ALTER TABLE t2 ADD COLUMN a INT, DROP FOREIGN KEY t2_ibfk_1;
+ALTER TABLE t2 ADD COLUMN a INT, DROP FOREIGN KEY fk_t2;
ALTER TABLE t2 ADD INDEX(a);
ALTER TABLE t1 ADD COLUMN b INT, ADD FOREIGN KEY(a) REFERENCES t2(a),
ALGORITHM=INSTANT;
@@ -475,7 +475,7 @@ ALTER TABLE t2 ADD CONSTRAINT fk FOREIGN KEY(b) REFERENCES t1(a),
ALGORITHM=INSTANT;
SET foreign_key_checks=1;
ALTER TABLE t2 COMMENT 'domestic keys only', DROP FOREIGN KEY fk;
-ALTER TABLE t1 DROP FOREIGN KEY t1_ibfk_1;
+ALTER TABLE t1 DROP FOREIGN KEY fk_t1;
ALTER TABLE t1 ADD COLUMN big BLOB NOT NULL
DEFAULT REPEAT('a', @@GLOBAL.innodb_page_size * .75);
CHECK TABLE t2, t1;
@@ -1393,7 +1393,7 @@ CREATE TABLE t2 (b INT PRIMARY KEY, FOREIGN KEY(b) REFERENCES t1(a))
ENGINE=InnoDB ROW_FORMAT=COMPACT;
INSERT INTO t1 SET a=1;
INSERT INTO t2 SET b=1;
-ALTER TABLE t2 ADD COLUMN a INT, DROP FOREIGN KEY t2_ibfk_1;
+ALTER TABLE t2 ADD COLUMN a INT, DROP FOREIGN KEY fk_t2;
ALTER TABLE t2 ADD INDEX(a);
ALTER TABLE t1 ADD COLUMN b INT, ADD FOREIGN KEY(a) REFERENCES t2(a),
ALGORITHM=INSTANT;
@@ -1405,7 +1405,7 @@ ALTER TABLE t2 ADD CONSTRAINT fk FOREIGN KEY(b) REFERENCES t1(a),
ALGORITHM=INSTANT;
SET foreign_key_checks=1;
ALTER TABLE t2 COMMENT 'domestic keys only', DROP FOREIGN KEY fk;
-ALTER TABLE t1 DROP FOREIGN KEY t1_ibfk_1;
+ALTER TABLE t1 DROP FOREIGN KEY fk_t1;
ALTER TABLE t1 ADD COLUMN big BLOB NOT NULL
DEFAULT REPEAT('a', @@GLOBAL.innodb_page_size * .75);
CHECK TABLE t2, t1;
@@ -2323,7 +2323,7 @@ CREATE TABLE t2 (b INT PRIMARY KEY, FOREIGN KEY(b) REFERENCES t1(a))
ENGINE=InnoDB ROW_FORMAT=DYNAMIC;
INSERT INTO t1 SET a=1;
INSERT INTO t2 SET b=1;
-ALTER TABLE t2 ADD COLUMN a INT, DROP FOREIGN KEY t2_ibfk_1;
+ALTER TABLE t2 ADD COLUMN a INT, DROP FOREIGN KEY fk_t2;
ALTER TABLE t2 ADD INDEX(a);
ALTER TABLE t1 ADD COLUMN b INT, ADD FOREIGN KEY(a) REFERENCES t2(a),
ALGORITHM=INSTANT;
@@ -2335,7 +2335,7 @@ ALTER TABLE t2 ADD CONSTRAINT fk FOREIGN KEY(b) REFERENCES t1(a),
ALGORITHM=INSTANT;
SET foreign_key_checks=1;
ALTER TABLE t2 COMMENT 'domestic keys only', DROP FOREIGN KEY fk;
-ALTER TABLE t1 DROP FOREIGN KEY t1_ibfk_1;
+ALTER TABLE t1 DROP FOREIGN KEY fk_t1;
ALTER TABLE t1 ADD COLUMN big BLOB NOT NULL
DEFAULT REPEAT('a', @@GLOBAL.innodb_page_size * .75);
CHECK TABLE t2, t1;
diff --git a/mysql-test/suite/innodb/r/instant_alter_bugs.result b/mysql-test/suite/innodb/r/instant_alter_bugs.result
index 79f1b0eb068..cca1b46d0e7 100644
--- a/mysql-test/suite/innodb/r/instant_alter_bugs.result
+++ b/mysql-test/suite/innodb/r/instant_alter_bugs.result
@@ -156,7 +156,7 @@ t2 CREATE TABLE `t2` (
`status` enum('a','b','c') DEFAULT NULL,
PRIMARY KEY (`f1`),
KEY `idx1` (`f2`),
- CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`f2`) REFERENCES `t1` (`f1`)
+ CONSTRAINT `fk_t2` FOREIGN KEY (`f2`) REFERENCES `t1` (`f1`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
ALTER TABLE t2 CHANGE status status VARCHAR(20) DEFAULT NULL;
DROP TABLE t2, t1;
diff --git a/mysql-test/suite/innodb/r/instant_alter_index_rename.result b/mysql-test/suite/innodb/r/instant_alter_index_rename.result
index 41dec275d90..c23c2f3550e 100644
--- a/mysql-test/suite/innodb/r/instant_alter_index_rename.result
+++ b/mysql-test/suite/innodb/r/instant_alter_index_rename.result
@@ -178,10 +178,11 @@ drop table rename_column_and_index;
#
# MDEV-19189: ASAN memcpy-param-overlap in fill_alter_inplace_info upon adding indexes
#
-CREATE TABLE t1 (f1 INT, f2 INT, f3 INT);
-ALTER TABLE t1 ADD FOREIGN KEY f (f2) REFERENCES xx(f2);
-ALTER TABLE t1 ADD FOREIGN KEY (f2) REFERENCES t1(f2), ADD KEY (f3), ADD KEY (f1);
-DROP TABLE t1;
+create table t1 (f1 int, f2 int, f3 int);
+create table t2 (f2 int primary key);
+alter table t1 add foreign key f (f2) references t2(f2);
+alter table t1 add foreign key (f2) references t1(f2), add key (f3), add key (f1);
+drop tables t1, t2;
#
# MDEV-21669 InnoDB: Table ... contains <n> indexes inside InnoDB, which is different from the number of indexes <n> defined in the MariaDB
#
diff --git a/mysql-test/suite/innodb/r/stored_fk.result b/mysql-test/suite/innodb/r/stored_fk.result
index 35524d5a88f..14f5c69a017 100644
--- a/mysql-test/suite/innodb/r/stored_fk.result
+++ b/mysql-test/suite/innodb/r/stored_fk.result
@@ -1,7 +1,7 @@
# 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")
+ERROR 42S02: Table 'test.t2' doesn't exist
# 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,
@@ -14,8 +14,8 @@ t2 CREATE TABLE `t2` (
`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
+ KEY `fk_t2` (`f1`),
+ CONSTRAINT `fk_t2` FOREIGN KEY (`f1`) REFERENCES `t1` (`f1`) ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=latin1
drop table t2;
# adding foreign key constraint for base columns during alter copy.
@@ -26,8 +26,8 @@ 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
+ KEY `fk_t2` (`f1`),
+ CONSTRAINT `fk_t2` FOREIGN KEY (`f1`) REFERENCES `t1` (`f1`) ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=latin1
drop table t2;
# adding foreign key constraint for base columns during online alter.
diff --git a/mysql-test/suite/innodb/r/table_flags,debug.rdiff b/mysql-test/suite/innodb/r/table_flags,debug.rdiff
index 50592d95ac4..e69de29bb2d 100644
--- a/mysql-test/suite/innodb/r/table_flags,debug.rdiff
+++ b/mysql-test/suite/innodb/r/table_flags,debug.rdiff
@@ -1,98 +0,0 @@
---- suite/innodb/r/table_flags.result
-+++ suite/innodb/r/table_flags,debug.reject
-@@ -11,71 +11,71 @@
- PAGE_COMPRESSED=1 PAGE_COMPRESSION_LEVEL=9;
- SYS_TABLES clustered index root page (8):
- N_RECS=8; LEVEL=0; INDEX_ID=0x0000000000000001
--header=0x01000003008d (NAME=0x696e66696d756d00)
--header=0x0000101500d5 (NAME='SYS_FOREIGN',
-+header=0x0100000300de (NAME=0x696e66696d756d00)
-+header=0x000018150126 (NAME='SYS_FOREIGN',
- DB_TRX_ID=0x000000000000,
- DB_ROLL_PTR=0x80000000000000,
-- ID=0x000000000000000b,
-+ ID=0x000000000000000c,
- N_COLS=0x00000004,
- TYPE=0x00000001,
- MIX_ID=0x0000000000000000,
- MIX_LEN=0x00000040,
- CLUSTER_NAME=NULL(0 bytes),
- SPACE=0x00000000)
--header=0x000018150122 (NAME='SYS_FOREIGN_COLS',
-+header=0x000020150173 (NAME='SYS_FOREIGN_COLS',
- DB_TRX_ID=0x000000000000,
- DB_ROLL_PTR=0x80000000000000,
-- ID=0x000000000000000c,
-+ ID=0x000000000000000d,
- N_COLS=0x00000004,
- TYPE=0x00000001,
- MIX_ID=0x0000000000000000,
- MIX_LEN=0x00000040,
- CLUSTER_NAME=NULL(0 bytes),
- SPACE=0x00000000)
--header=0x0000201501ae (NAME='SYS_VIRTUAL',
-+header=0x0000281501bb (NAME='SYS_VIRTUAL',
- DB_TRX_ID=0x000000000000,
- DB_ROLL_PTR=0x80000000000000,
-- ID=0x000000000000000d,
-+ ID=0x000000000000000e,
- N_COLS=0x00000003,
- TYPE=0x00000001,
- MIX_ID=0x0000000000000000,
- MIX_LEN=0x00000040,
- CLUSTER_NAME=NULL(0 bytes),
- SPACE=0x00000000)
--header=0x0400301501f2 (NAME='test/tc',
-+header=0x0400301501ff (NAME='test/tc',
- DB_TRX_ID=0x000000000000,
- DB_ROLL_PTR=0x80000000000000,
-- ID=0x000000000000000f,
-+ ID=0x0000000000000010,
- N_COLS=0x80000001,
- TYPE=0x00000001,
- MIX_ID=0x0000000000000000,
- MIX_LEN=0x00000050,
- CLUSTER_NAME=NULL(0 bytes),
- SPACE=0x00000002)
--header=0x00003815027a (NAME='test/td',
-+header=0x000038150287 (NAME='test/td',
- DB_TRX_ID=0x000000000000,
- DB_ROLL_PTR=0x80000000000000,
-- ID=0x0000000000000010,
-+ ID=0x0000000000000011,
- N_COLS=0x80000001,
- TYPE=0x00000021,
- MIX_ID=0x0000000000000000,
- MIX_LEN=0x00000050,
- CLUSTER_NAME=NULL(0 bytes),
- SPACE=0x00000003)
--header=0x00004815016a (NAME='test/tp',
-+header=0x00004815008d (NAME='test/tp',
- DB_TRX_ID=0x000000000000,
- DB_ROLL_PTR=0x80000000000000,
-- ID=0x0000000000000012,
-+ ID=0x0000000000000013,
- N_COLS=0x80000001,
- TYPE=0x000009a1,
- MIX_ID=0x0000000000000000,
- MIX_LEN=0x00000050,
- CLUSTER_NAME=NULL(0 bytes),
- SPACE=0x00000005)
--header=0x000028150236 (NAME='test/tr',
-+header=0x000010150243 (NAME='test/tr',
- DB_TRX_ID=0x000000000000,
- DB_ROLL_PTR=0x80000000000000,
-- ID=0x000000000000000e,
-+ ID=0x000000000000000f,
- N_COLS=0x00000001,
- TYPE=0x00000001,
- MIX_ID=0x0000000000000000,
-@@ -85,7 +85,7 @@
- header=0x000040150074 (NAME='test/tz',
- DB_TRX_ID=0x000000000000,
- DB_ROLL_PTR=0x80000000000000,
-- ID=0x0000000000000011,
-+ ID=0x0000000000000012,
- N_COLS=0x80000001,
- TYPE=0x00000023,
- MIX_ID=0x0000000000000000,
diff --git a/mysql-test/suite/innodb/r/truncate_foreign.result b/mysql-test/suite/innodb/r/truncate_foreign.result
index fc09b74d62f..d391436dec1 100644
--- a/mysql-test/suite/innodb/r/truncate_foreign.result
+++ b/mysql-test/suite/innodb/r/truncate_foreign.result
@@ -5,7 +5,7 @@ ON UPDATE CASCADE)
ENGINE=InnoDB;
INSERT INTO child SET a=1;
TRUNCATE TABLE parent;
-ERROR 42000: Cannot truncate a table referenced in a foreign key constraint (`test`.`child`, CONSTRAINT `child_ibfk_1` FOREIGN KEY (`a`) REFERENCES `test`.`parent` (`a`))
+ERROR 42000: Cannot truncate a table referenced in a foreign key constraint (`test`.`child`, CONSTRAINT `fk_child` FOREIGN KEY (`a`) REFERENCES `test`.`parent` (`a`))
TRUNCATE TABLE child;
INSERT INTO child SET a=1;
UPDATE parent SET a=2;
@@ -34,7 +34,7 @@ TRUNCATE TABLE child;
ERROR HY000: Lock wait timeout exceeded; try restarting transaction
SET DEBUG_SYNC='now SIGNAL go';
connection dml;
-ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`child`, CONSTRAINT `child_ibfk_1` FOREIGN KEY (`a`) REFERENCES `parent` (`a`) ON UPDATE CASCADE)
+ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`child`, CONSTRAINT `fk_child` FOREIGN KEY (`a`) REFERENCES `parent` (`a`) ON UPDATE CASCADE)
SELECT * FROM child;
a
3
@@ -47,7 +47,7 @@ SET foreign_key_checks=0;
TRUNCATE TABLE parent;
SET DEBUG_SYNC='now SIGNAL go';
connection dml;
-ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test`.`child`, CONSTRAINT `child_ibfk_1` FOREIGN KEY (`a`) REFERENCES `parent` (`a`) ON UPDATE CASCADE)
+ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test`.`child`, CONSTRAINT `fk_child` FOREIGN KEY (`a`) REFERENCES `parent` (`a`) ON UPDATE CASCADE)
SELECT * FROM parent;
a
SELECT * FROM child;
diff --git a/mysql-test/suite/innodb/r/update-cascade.result b/mysql-test/suite/innodb/r/update-cascade.result
index a3c8fed931e..a15f5905dfe 100644
--- a/mysql-test/suite/innodb/r/update-cascade.result
+++ b/mysql-test/suite/innodb/r/update-cascade.result
@@ -17,8 +17,8 @@ t2 CREATE TABLE `t2` (
`f1` int(11) NOT NULL,
`f2` int(11) DEFAULT NULL,
PRIMARY KEY (`f1`),
- KEY `f2` (`f2`),
- CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`f2`) REFERENCES `t1` (`f1`) ON UPDATE CASCADE
+ KEY `fk_t2` (`f2`),
+ CONSTRAINT `fk_t2` FOREIGN KEY (`f2`) REFERENCES `t1` (`f1`) ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=latin1
insert into t1 values (1, repeat('+', 20000));
insert into t1 values (2, repeat('-', 20000));
@@ -80,8 +80,8 @@ t2 CREATE TABLE `t2` (
`f1` int(11) NOT NULL,
`f2` int(11) DEFAULT NULL,
PRIMARY KEY (`f1`),
- KEY `f2` (`f2`),
- CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`f2`) REFERENCES `t1` (`f2`) ON UPDATE CASCADE
+ KEY `fk_t2` (`f2`),
+ CONSTRAINT `fk_t2` FOREIGN KEY (`f2`) REFERENCES `t1` (`f2`) ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=latin1
insert into t1 values (1, 91);
insert into t2 values (1, 91);
@@ -136,7 +136,7 @@ t2 CREATE TABLE `t2` (
`f1` int(11) NOT NULL,
`f2` blob DEFAULT NULL,
PRIMARY KEY (`f1`),
- CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`f1`) REFERENCES `t1` (`f1`) ON UPDATE CASCADE
+ CONSTRAINT `fk_t2` FOREIGN KEY (`f1`) REFERENCES `t1` (`f1`) ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=latin1
show create table t3;
Table Create Table
@@ -144,7 +144,7 @@ t3 CREATE TABLE `t3` (
`f1` int(11) NOT NULL,
`f2` blob DEFAULT NULL,
PRIMARY KEY (`f1`),
- CONSTRAINT `t3_ibfk_1` FOREIGN KEY (`f1`) REFERENCES `t2` (`f1`) ON UPDATE CASCADE
+ CONSTRAINT `fk_t3` FOREIGN KEY (`f1`) REFERENCES `t2` (`f1`) ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=latin1
insert into t1 values (2, repeat('-', 20000));
insert into t2 values (2, repeat('%', 20000));
@@ -223,8 +223,8 @@ t2 CREATE TABLE `t2` (
`f1` int(11) NOT NULL,
`f2` int(11) DEFAULT NULL,
PRIMARY KEY (`f1`),
- KEY `f2` (`f2`),
- CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`f2`) REFERENCES `t1` (`f2`) ON UPDATE CASCADE
+ KEY `fk_t2` (`f2`),
+ CONSTRAINT `fk_t2` FOREIGN KEY (`f2`) REFERENCES `t1` (`f2`) ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=latin1
show create table t3;
Table Create Table
@@ -232,8 +232,8 @@ t3 CREATE TABLE `t3` (
`f1` int(11) NOT NULL,
`f2` int(11) DEFAULT NULL,
PRIMARY KEY (`f1`),
- KEY `f2` (`f2`),
- CONSTRAINT `t3_ibfk_1` FOREIGN KEY (`f2`) REFERENCES `t2` (`f2`) ON UPDATE CASCADE
+ KEY `fk_t3` (`f2`),
+ CONSTRAINT `fk_t3` FOREIGN KEY (`f2`) REFERENCES `t2` (`f2`) ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=latin1
insert into t1 values (2, 91);
insert into t2 values (2, 91);
diff --git a/mysql-test/suite/innodb/t/alter_table.test b/mysql-test/suite/innodb/t/alter_table.test
index ec01d34fdd8..756dc019bcb 100644
--- a/mysql-test/suite/innodb/t/alter_table.test
+++ b/mysql-test/suite/innodb/t/alter_table.test
@@ -50,13 +50,13 @@ CREATE TABLE t1 (pk INT, a INT, PRIMARY KEY (pk), KEY (a), FOREIGN KEY (a) REFER
SET FOREIGN_KEY_CHECKS=OFF;
---error ER_FK_COLUMN_CANNOT_DROP
+--error ER_WRONG_FK_DEF
ALTER TABLE t1 DROP a;
SET FOREIGN_KEY_CHECKS=ON;
ALTER TABLE t1 ADD b INT;
---error ER_DROP_INDEX_FK
+--error ER_WRONG_FK_DEF
ALTER TABLE t1 DROP a;
ALTER TABLE t1 ADD c INT;
DROP TABLE t1, tx;
diff --git a/mysql-test/suite/innodb/t/foreign-keys.test b/mysql-test/suite/innodb/t/foreign-keys.test
index b93f82c93ef..2a18a452e38 100644
--- a/mysql-test/suite/innodb/t/foreign-keys.test
+++ b/mysql-test/suite/innodb/t/foreign-keys.test
@@ -248,7 +248,7 @@ show create table t2;
--error ER_ROW_IS_REFERENCED_2
drop table t1,t2;
--error ER_BAD_TABLE_ERROR
-drop table t1,t2;
+drop table t2, t1;
--echo #
--echo # MDEV-23470 InnoDB: Failing assertion: cmp < 0 in
diff --git a/mysql-test/suite/innodb/t/foreign_key.test b/mysql-test/suite/innodb/t/foreign_key.test
index 94d736e97d4..b164a715711 100644
--- a/mysql-test/suite/innodb/t/foreign_key.test
+++ b/mysql-test/suite/innodb/t/foreign_key.test
@@ -15,7 +15,7 @@ constraint c1 foreign key (f1) references t1(f1)) engine=InnoDB;
create table t2 (f1 int primary key,
constraint c1 foreign key (f1) references t1(f1)) engine=innodb;
---error ER_CANT_CREATE_TABLE
+--error ER_DUP_CONSTRAINT_NAME
alter table t2 add constraint c1 foreign key (f1) references t1(f1);
set foreign_key_checks = 0;
@@ -159,7 +159,7 @@ CREATE DATABASE best default character set latin1;
CREATE TABLE t3 (a INT PRIMARY KEY,
CONSTRAINT t2_ibfk_1 FOREIGN KEY (a) REFERENCES t1(a)) ENGINE=InnoDB;
CREATE TABLE best.t2 (a INT PRIMARY KEY, b TEXT, FULLTEXT INDEX(b),
-FOREIGN KEY (a) REFERENCES test.t1(a)) ENGINE=InnoDB;
+FOREIGN KEY t2_ibfk_1 (a) REFERENCES test.t1(a)) ENGINE=InnoDB;
--replace_regex /Table '.*t2'/Table 't2'/
--error ER_TABLE_EXISTS_ERROR
RENAME TABLE best.t2 TO test.t2;
@@ -224,18 +224,18 @@ DROP TABLE t2, t1;
CREATE TABLE t1 (f VARCHAR(256)) ENGINE=InnoDB;
SET SESSION FOREIGN_KEY_CHECKS = OFF;
ALTER TABLE t1 ADD FOREIGN KEY (f) REFERENCES non_existing_table (x);
-SET SESSION FOREIGN_KEY_CHECKS = ON;
ALTER TABLE t1 ADD FULLTEXT INDEX ft1 (f);
ALTER TABLE t1 ADD FULLTEXT INDEX ft2 (f);
+SET SESSION FOREIGN_KEY_CHECKS = ON;
DROP TABLE t1;
CREATE TABLE t1 (f VARCHAR(256), FTS_DOC_ID BIGINT UNSIGNED PRIMARY KEY)
ENGINE=InnoDB;
SET SESSION FOREIGN_KEY_CHECKS = OFF;
ALTER TABLE t1 ADD FOREIGN KEY (f) REFERENCES non_existing_table (x);
-SET SESSION FOREIGN_KEY_CHECKS = ON;
ALTER TABLE t1 ADD FULLTEXT INDEX ft1 (f);
ALTER TABLE t1 ADD FULLTEXT INDEX ft2 (f);
+SET SESSION FOREIGN_KEY_CHECKS = ON;
DROP TABLE t1;
--echo #
@@ -243,7 +243,7 @@ DROP TABLE t1;
--echo # in ib_push_warning / dict_create_foreign_constraints_low
--echo #
CREATE TABLE t1 (a INT) ENGINE=InnoDB;
---error ER_CANT_CREATE_TABLE
+--error ER_NO_SUCH_TABLE
ALTER IGNORE TABLE t1 ADD FOREIGN KEY (a) REFERENCES t2 (b);
SHOW WARNINGS;
DROP TABLE t1;
@@ -688,7 +688,7 @@ START TRANSACTION WITH CONSISTENT SNAPSHOT;
connection default;
DELETE IGNORE FROM t1 WHERE b = 1;
-SELECT a FROM t1 FORCE INDEX(a);
+SELECT a FROM t1 FORCE INDEX(fk_t1);
# This would wrongly return the empty result if
# the "goto rollback_to_savept" in row_mysql_handle_errors() is reverted.
SELECT * FROM t1;
@@ -820,7 +820,7 @@ show create table t3;
drop tables t3, t2, t1;
create table t1 (id int primary key);
---error ER_CANT_CREATE_TABLE
+--error ER_WRONG_FK_DEF
create table t2 (id2 int references t1);
create table t2 (id int references t1);
show create table t2;
diff --git a/mysql-test/suite/innodb/t/innodb-fk-warnings.test b/mysql-test/suite/innodb/t/innodb-fk-warnings.test
index 8a0ed5815b8..37488574708 100644
--- a/mysql-test/suite/innodb/t/innodb-fk-warnings.test
+++ b/mysql-test/suite/innodb/t/innodb-fk-warnings.test
@@ -64,7 +64,7 @@ drop table t2, t1;
#
create table t1 (f1 integer primary key) engine=innodb;
---error ER_CANT_CREATE_TABLE
+--error ER_NO_SUCH_TABLE
alter table t1 add constraint c1 foreign key (f1) references t11(f1);
show warnings;
drop table t1;
@@ -89,7 +89,7 @@ create temporary table t1(a int not null primary key, b int, key(b)) engine=inno
--echo Warning 150 Alter table `mysqld.1`.`t1` with foreign key constraint failed. Referenced table `mysqld.1`.`t1` not found in the data dictionary close to foreign key(b) references t1(a).
--echo Error 1005 Can't create table `test`.`#sql-temporary` (errno: 150 "Foreign key constraint is incorrectly formed")
--echo Warning 1215 Cannot add foreign key constraint
---error ER_CANT_CREATE_TABLE
+--error ER_NO_SUCH_TABLE
create temporary table t2(a int, foreign key(a) references t1(a)) engine=innodb;
show warnings;
--error ER_CANT_CREATE_TABLE
@@ -127,7 +127,7 @@ drop table t1;
# Incorrect types
#
create table t1 (id int not null primary key, f1 int, f2 int, key(f1)) engine=innodb;
---error ER_CANT_CREATE_TABLE
+--error ER_WRONG_FK_DEF
create table t2(a char(20), key(a), foreign key(a) references t1(f1)) engine=innodb;
show warnings;
drop table t1;
diff --git a/mysql-test/suite/innodb/t/innodb-fk.test b/mysql-test/suite/innodb/t/innodb-fk.test
index fcab4b22eb1..e74d5b31600 100644
--- a/mysql-test/suite/innodb/t/innodb-fk.test
+++ b/mysql-test/suite/innodb/t/innodb-fk.test
@@ -95,7 +95,7 @@ CREATE TABLE t1 (
CONSTRAINT fk1 FOREIGN KEY (f1) REFERENCES t1 (id) ON DELETE CASCADE
) ENGINE=InnoDB;
---error 1005
+--error ER_NO_SUCH_TABLE
CREATE TABLE t2 (
id int(11) NOT NULL AUTO_INCREMENT,
f2 int(11) NOT NULL,
@@ -115,7 +115,7 @@ CREATE TABLE t2 (
CONSTRAINT fk2 FOREIGN KEY (f2) REFERENCES t1 (`id`) ON DELETE CASCADE
) ENGINE=InnoDB;
---error 1005
+--error ER_NO_SUCH_TABLE
ALTER TABLE t2 ADD CONSTRAINT fk3 FOREIGN KEY (f3) REFERENCES t3 (id) ON DELETE CASCADE;
show warnings;
@@ -143,7 +143,7 @@ CONSTRAINT `fk_person_group` FOREIGN KEY (`Id`) REFERENCES `group` (`Id`)
show create table `kg_test1`.`person`;
---error 1005
+--error ER_NO_SUCH_TABLE
CREATE TABLE `kg_test2`.`person2` (
`Id` INT(11) NOT NULL AUTO_INCREMENT,
`Name` VARCHAR(50) NOT NULL,
@@ -198,7 +198,7 @@ CREATE TABLE `boroda` (
) ENGINE=INNODB DEFAULT CHARSET=utf8;
ALTER TABLE `boroda`
- ADD FOREIGN KEY (`b`) REFERENCES `boroda`(`id`);
+ ADD FOREIGN KEY `boroda_ibfk_2` (`b`) REFERENCES `boroda`(`id`);
ALTER TABLE `boroda` DROP FOREIGN KEY `boroda_ibfk_2`;
@@ -230,6 +230,7 @@ DROP TABLE `bor#oda`;
--echo #
--echo # MDEV-21127 Assertion `(size_t)(ptr - buf) < MAX_TEXT - 4' failed in key_text::key_text
--echo #
+create table tx (ax char(255) unique, bx char(255) unique) engine innodb;
--error ER_CANT_CREATE_TABLE
CREATE TABLE t1 (
a012345678901234567890123456789012345678901 char(255),
@@ -237,10 +238,12 @@ CREATE TABLE t1 (
FOREIGN KEY ( a012345678901234567890123456789012345678901, b ) REFERENCES tx (ax, bx)
) ENGINE=InnoDB;
---error ER_CANT_CREATE_TABLE
+--error ER_WRONG_FK_DEF
CREATE TABLE t1 (
a012345678901234567 int,
b int,
c0123456789012345678 int,
FOREIGN KEY (a012345678901234567,c0123456789012345678,b) REFERENCES tx (x1,x2,x3)
) ENGINE=InnoDB;
+
+drop table tx;
diff --git a/mysql-test/suite/innodb/t/innodb-index.test b/mysql-test/suite/innodb/t/innodb-index.test
index 9350672bee9..d924db39960 100644
--- a/mysql-test/suite/innodb/t/innodb-index.test
+++ b/mysql-test/suite/innodb/t/innodb-index.test
@@ -155,8 +155,8 @@ create table t1(a int not null, b int not null, c int, primary key (a), key (b))
create table t3(a int not null, c int not null, d int, primary key (a), key (c)) engine = innodb;
create table t4(a int not null, d int not null, e int, primary key (a), key (d)) engine = innodb;
create table t2(a int not null, b int, c int, d int, e int,
-foreign key (b) references t1(b) on delete set null,
-foreign key (c) references t3(c), foreign key (d) references t4(d) on update set null)
+foreign key b (b) references t1(b) on delete set null,
+foreign key c (c) references t3(c), foreign key d (d) references t4(d) on update set null)
engine = innodb;
--error ER_DROP_INDEX_FK
alter table t1 drop index b;
@@ -178,9 +178,9 @@ alter table t2 MODIFY b INT NOT NULL, ALGORITHM=INPLACE;
set @@sql_mode = @old_sql_mode;
SET FOREIGN_KEY_CHECKS=0;
---error ER_FK_COLUMN_CANNOT_DROP
+--error ER_WRONG_FK_DEF
alter table t2 DROP COLUMN b, ALGORITHM=COPY;
---error ER_FK_COLUMN_CANNOT_DROP
+--error ER_WRONG_FK_DEF
alter table t2 DROP COLUMN b;
--error ER_FK_COLUMN_CANNOT_DROP_CHILD
alter table t1 DROP COLUMN b, ALGORITHM=COPY;
@@ -1127,7 +1127,9 @@ drop table t1;
--source include/no_checkpoint_start.inc
if ($have_debug) {
+--disable_query_log
SET GLOBAL DEBUG_DBUG='+d,fil_names_write_bogus';
+--enable_query_log
}
CREATE TABLE t1(f1 INT PRIMARY KEY)ENGINE=InnoDB;
diff --git a/mysql-test/suite/innodb/t/innodb-truncate.test b/mysql-test/suite/innodb/t/innodb-truncate.test
index 71c0fcfea8b..9231fe5962b 100644
--- a/mysql-test/suite/innodb/t/innodb-truncate.test
+++ b/mysql-test/suite/innodb/t/innodb-truncate.test
@@ -86,9 +86,11 @@ CREATE TABLE t2 (f2 INT, FOREIGN KEY(f2) REFERENCES t1 (f2)) ENGINE=InnoDB;
--error ER_CANT_CREATE_TABLE
CREATE TABLE t3 (a INT) ENGINE=InnoDB;
--replace_result $datadir ./
---error ER_ERROR_ON_RENAME
+--error ER_NO_SUCH_TABLE
ALTER TABLE t1 RENAME TO t3;
+SET FOREIGN_KEY_CHECKS= OFF;
ALTER TABLE t1 FORCE;
+SET FOREIGN_KEY_CHECKS= ON;
--error ER_TRUNCATE_ILLEGAL_FK
TRUNCATE TABLE t1;
DROP TABLE t2, t1;
diff --git a/mysql-test/suite/innodb/t/innodb.test b/mysql-test/suite/innodb/t/innodb.test
index 5a718265624..95145bd8eeb 100644
--- a/mysql-test/suite/innodb/t/innodb.test
+++ b/mysql-test/suite/innodb/t/innodb.test
@@ -1783,7 +1783,7 @@ drop table t2,t1;
CREATE TABLE t1(a INT, PRIMARY KEY(a)) ENGINE=InnoDB;
CREATE TABLE t2(a INT) ENGINE=InnoDB;
ALTER TABLE t2 ADD FOREIGN KEY (a) REFERENCES t1(a);
-ALTER TABLE t2 DROP FOREIGN KEY t2_ibfk_1;
+ALTER TABLE t2 DROP FOREIGN KEY fk_t2;
ALTER TABLE t2 ADD CONSTRAINT t2_ibfk_0 FOREIGN KEY (a) REFERENCES t1(a);
ALTER TABLE t2 DROP FOREIGN KEY t2_ibfk_0;
SHOW CREATE TABLE t2;
diff --git a/mysql-test/suite/innodb/t/instant_alter.test b/mysql-test/suite/innodb/t/instant_alter.test
index ab2636f7554..932daa037cd 100644
--- a/mysql-test/suite/innodb/t/instant_alter.test
+++ b/mysql-test/suite/innodb/t/instant_alter.test
@@ -349,7 +349,7 @@ eval CREATE TABLE t2 (b INT PRIMARY KEY, FOREIGN KEY(b) REFERENCES t1(a))
$engine;
INSERT INTO t1 SET a=1;
INSERT INTO t2 SET b=1;
-ALTER TABLE t2 ADD COLUMN a INT, DROP FOREIGN KEY t2_ibfk_1;
+ALTER TABLE t2 ADD COLUMN a INT, DROP FOREIGN KEY fk_t2;
ALTER TABLE t2 ADD INDEX(a);
--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON
ALTER TABLE t1 ADD COLUMN b INT, ADD FOREIGN KEY(a) REFERENCES t2(a),
@@ -361,7 +361,7 @@ ALTER TABLE t2 ADD CONSTRAINT fk FOREIGN KEY(b) REFERENCES t1(a),
ALGORITHM=INSTANT;
SET foreign_key_checks=1;
ALTER TABLE t2 COMMENT 'domestic keys only', DROP FOREIGN KEY fk;
-ALTER TABLE t1 DROP FOREIGN KEY t1_ibfk_1;
+ALTER TABLE t1 DROP FOREIGN KEY fk_t1;
ALTER TABLE t1 ADD COLUMN big BLOB NOT NULL
DEFAULT REPEAT('a', @@GLOBAL.innodb_page_size * .75);
CHECK TABLE t2, t1;
diff --git a/mysql-test/suite/innodb/t/instant_alter_index_rename.test b/mysql-test/suite/innodb/t/instant_alter_index_rename.test
index af66c1027cc..2ccfe932018 100644
--- a/mysql-test/suite/innodb/t/instant_alter_index_rename.test
+++ b/mysql-test/suite/innodb/t/instant_alter_index_rename.test
@@ -190,10 +190,11 @@ drop table rename_column_and_index;
--echo # MDEV-19189: ASAN memcpy-param-overlap in fill_alter_inplace_info upon adding indexes
--echo #
-CREATE TABLE t1 (f1 INT, f2 INT, f3 INT);
-ALTER TABLE t1 ADD FOREIGN KEY f (f2) REFERENCES xx(f2);
-ALTER TABLE t1 ADD FOREIGN KEY (f2) REFERENCES t1(f2), ADD KEY (f3), ADD KEY (f1);
-DROP TABLE t1;
+create table t1 (f1 int, f2 int, f3 int);
+create table t2 (f2 int primary key);
+alter table t1 add foreign key f (f2) references t2(f2);
+alter table t1 add foreign key (f2) references t1(f2), add key (f3), add key (f1);
+drop tables t1, t2;
--echo #
--echo # MDEV-21669 InnoDB: Table ... contains <n> indexes inside InnoDB, which is different from the number of indexes <n> defined in the MariaDB
diff --git a/mysql-test/suite/innodb/t/stored_fk.test b/mysql-test/suite/innodb/t/stored_fk.test
index b9c7c934555..2b711ed0efa 100644
--- a/mysql-test/suite/innodb/t/stored_fk.test
+++ b/mysql-test/suite/innodb/t/stored_fk.test
@@ -1,7 +1,7 @@
--source include/have_innodb.inc
--echo # Create statement with FK on base column of stored column
---error ER_CANT_CREATE_TABLE
+--error ER_NO_SUCH_TABLE
create table t1(f1 int, f2 int as(f1) stored,
foreign key(f1) references t2(f1) on delete cascade)engine=innodb;
diff --git a/mysql-test/suite/innodb/t/table_flags.test b/mysql-test/suite/innodb/t/table_flags.test
index 79b2c3dd77a..245a92d7952 100644
--- a/mysql-test/suite/innodb/t/table_flags.test
+++ b/mysql-test/suite/innodb/t/table_flags.test
@@ -234,7 +234,7 @@ DROP TABLE tr,tc,td,tz,tp;
--rmdir $bugdir
call mtr.add_suppression("ERROR HY000: Can't create table `test`.`t1`");
---error ER_CANT_CREATE_TABLE
+--error ER_WRONG_FK_DEF
CREATE TABLE t1(f1 INT, f2 VARCHAR(1), KEY k1(f2),
FULLTEXT KEY(f2),
FOREIGN KEY (f2) REFERENCES t1(f3))ENGINE=InnoDB;
diff --git a/mysql-test/suite/innodb_fts/r/innodb_fts_misc_1.result b/mysql-test/suite/innodb_fts/r/innodb_fts_misc_1.result
index c192fced34e..6d2d3de0477 100644
--- a/mysql-test/suite/innodb_fts/r/innodb_fts_misc_1.result
+++ b/mysql-test/suite/innodb_fts/r/innodb_fts_misc_1.result
@@ -32,9 +32,9 @@ INSERT INTO t2 (a2,b2) VALUES
('MySQL Security','When configured properly, MySQL ...');
INSERT INTO t2 (a2,b2) VALUES
('MySQL Tricks','1. Never run mysqld as root. 2. ...');
-ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`a2`) REFERENCES `t1` (`a1`) ON UPDATE CASCADE)
+ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `fk_t2` FOREIGN KEY (`a2`) REFERENCES `t1` (`a1`) ON UPDATE CASCADE)
DELETE FROM t1;
-ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`a2`) REFERENCES `t1` (`a1`) ON UPDATE CASCADE)
+ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `fk_t2` FOREIGN KEY (`a2`) REFERENCES `t1` (`a1`) ON UPDATE CASCADE)
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
test.t1 analyze status Engine-independent statistics collected
@@ -182,9 +182,9 @@ Table Create Table
t2 CREATE TABLE `t2` (
`FTS_DOC_ID` bigint(20) unsigned NOT NULL,
`s2` varchar(200) DEFAULT NULL,
- KEY `FTS_DOC_ID` (`FTS_DOC_ID`),
+ KEY `fk_t2` (`FTS_DOC_ID`),
FULLTEXT KEY `idx` (`s2`),
- CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`FTS_DOC_ID`) REFERENCES `t1` (`s1`) ON UPDATE CASCADE
+ CONSTRAINT `fk_t2` FOREIGN KEY (`FTS_DOC_ID`) REFERENCES `t1` (`s1`) ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=latin1
insert into t1 values (1,'Sunshine'),(2,'Lollipops');
insert into t2 values (1,'Sunshine'),(2,'Lollipops');
@@ -193,7 +193,7 @@ select * from t2 where match(s2) against ('sunshine');
FTS_DOC_ID s2
3 Sunshine
update t1 set s1 = 1 where s1=3;
-ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`FTS_DOC_ID`) REFERENCES `t1` (`s1`) ON UPDATE CASCADE)
+ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `fk_t2` FOREIGN KEY (`FTS_DOC_ID`) REFERENCES `t1` (`s1`) ON UPDATE CASCADE)
DROP TABLE t2 , t1;
CREATE TABLE t1 (
id1 INT ,
@@ -265,9 +265,9 @@ INSERT INTO t2 (a2,b2) VALUES
('MySQL Security','When configured properly, MySQL ...');
INSERT INTO t2 (a2,b2) VALUES
('MySQL Tricks','1. Never run mysqld as root. 2. ...');
-ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`a2`) REFERENCES `t1` (`a1`) ON UPDATE CASCADE)
+ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `fk_t2` FOREIGN KEY (`a2`) REFERENCES `t1` (`a1`) ON UPDATE CASCADE)
DELETE FROM t1;
-ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`a2`) REFERENCES `t1` (`a1`) ON UPDATE CASCADE)
+ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `fk_t2` FOREIGN KEY (`a2`) REFERENCES `t1` (`a1`) ON UPDATE CASCADE)
SELECT * FROM t1 WHERE MATCH (a1,b1) AGAINST ('tutorial') ORDER BY id1;
id1 a1 b1
1 MySQL Tutorial DBMS stands for DataBase VÐƷWİ...
@@ -956,9 +956,9 @@ pk f1 f2 f3 f4 f5 f6 f7 f8
ROLLBACK;
ALTER TABLE t1 ADD FOREIGN KEY (f5) REFERENCES t1 (f6) ON UPDATE SET NULL;
UPDATE t1 SET f6='update';
-ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t1`, CONSTRAINT `t1_ibfk_3` FOREIGN KEY (`f5`) REFERENCES `t1` (`f6`) ON UPDATE SET NULL)
+ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t1`, CONSTRAINT `fk_t1_3` FOREIGN KEY (`f5`) REFERENCES `t1` (`f6`) ON UPDATE SET NULL)
ALTER TABLE t1 ADD FOREIGN KEY (f7) REFERENCES t1 (f8) ON UPDATE CASCADE;
UPDATE t1 SET f6='cascade';
-ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t1`, CONSTRAINT `t1_ibfk_3` FOREIGN KEY (`f5`) REFERENCES `t1` (`f6`) ON UPDATE SET NULL)
+ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t1`, CONSTRAINT `fk_t1_3` FOREIGN KEY (`f5`) REFERENCES `t1` (`f6`) ON UPDATE SET NULL)
DROP TABLE t1;
SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS;
diff --git a/mysql-test/suite/innodb_fts/r/misc_debug.result b/mysql-test/suite/innodb_fts/r/misc_debug.result
index f1110797f33..bd81ad7c5a7 100644
--- a/mysql-test/suite/innodb_fts/r/misc_debug.result
+++ b/mysql-test/suite/innodb_fts/r/misc_debug.result
@@ -21,7 +21,7 @@ CREATE TABLE t1 (pk INT, a VARCHAR(8), PRIMARY KEY(pk),
FULLTEXT KEY(a)) ENGINE=InnoDB;
CREATE TABLE t2 (b INT, FOREIGN KEY(b) REFERENCES t1(pk)) ENGINE=InnoDB;
DROP TABLE t1;
-ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails
+ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (fk_t2)
SET DEBUG_DBUG="+d,fts_instrument_sync";
INSERT INTO t1 VALUES(1, "mariadb");
ALTER TABLE t1 FORCE;
diff --git a/mysql-test/suite/innodb_gis/r/point_basic.result b/mysql-test/suite/innodb_gis/r/point_basic.result
index 4842c72d99c..dc110d5586a 100644
--- a/mysql-test/suite/innodb_gis/r/point_basic.result
+++ b/mysql-test/suite/innodb_gis/r/point_basic.result
@@ -1562,7 +1562,7 @@ ALTER TABLE child ADD FOREIGN KEY(p) REFERENCES parent(p);
ERROR HY000: Can't create table `test`.`child` (errno: 150 "Foreign key constraint is incorrectly formed")
show warnings;
Level Code Message
-Warning 150 Alter table `test`.`child` with foreign key (p) constraint failed. There is no index in the referenced table where the referenced columns appear as the first columns.
+Warning 150 Alter table `test`.`child` with foreign key `fk_child` constraint failed. There is no index in the referenced table where the referenced columns appear as the first columns.
Error 1005 Can't create table `test`.`child` (errno: 150 "Foreign key constraint is incorrectly formed")
Warning 1215 Cannot add foreign key constraint for `child`
ALTER TABLE parent DROP INDEX idx1;
@@ -1570,7 +1570,7 @@ ALTER TABLE child ADD FOREIGN KEY(p) REFERENCES parent(p);
Got one of the listed errors
show warnings;
Level Code Message
-Warning 150 Alter table `test`.`child` with foreign key (p) constraint failed. There is no index in the referenced table where the referenced columns appear as the first columns.
+Warning 150 Alter table `test`.`child` with foreign key `fk_child` constraint failed. There is no index in the referenced table where the referenced columns appear as the first columns.
Error 1005 Can't create table `test`.`child` (errno: 150 "Foreign key constraint is incorrectly formed")
Warning 1215 Cannot add foreign key constraint for `child`
ALTER TABLE child DROP INDEX idx2;
@@ -1578,7 +1578,7 @@ ALTER TABLE child ADD FOREIGN KEY(p) REFERENCES parent(p);
Got one of the listed errors
show warnings;
Level Code Message
-Warning 150 Alter table `test`.`child` with foreign key (p) constraint failed. There is only prefix index in the referenced table where the referenced columns appear as the first columns.
+Warning 150 Alter table `test`.`child` with foreign key `fk_child` constraint failed. There is only prefix index in the referenced table where the referenced columns appear as the first columns.
Error 1005 Can't create table `test`.`child` (errno: 150 "Foreign key constraint is incorrectly formed")
Warning 1215 Cannot add foreign key constraint for `child`
DROP TABLE child, parent;
diff --git a/mysql-test/suite/rpl/r/rpl_drop_db_fail.result b/mysql-test/suite/rpl/r/rpl_drop_db_fail.result
index 4b4eacff3bb..97fef3694a4 100644
--- a/mysql-test/suite/rpl/r/rpl_drop_db_fail.result
+++ b/mysql-test/suite/rpl/r/rpl_drop_db_fail.result
@@ -13,7 +13,7 @@ use db2;
CREATE TABLE table_child(id INT PRIMARY KEY, info VARCHAR(20), father_id INT) ENGINE=INNODB;
ALTER TABLE table_child ADD CONSTRAINT aaa FOREIGN KEY (father_id) REFERENCES db1.table_father(id);
DROP DATABASE db1;
-ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails
+ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (aaa)
DROP DATABASE db2;
connection slave;
connection master;
diff --git a/mysql-test/suite/vcol/inc/vcol_ins_upd.inc b/mysql-test/suite/vcol/inc/vcol_ins_upd.inc
index 8cf0fb9ed6c..cff4ee10013 100644
--- a/mysql-test/suite/vcol/inc/vcol_ins_upd.inc
+++ b/mysql-test/suite/vcol/inc/vcol_ins_upd.inc
@@ -245,7 +245,7 @@ if ($innodb_engine)
--error ER_ROW_IS_REFERENCED_2
update t2 set a=4 where a=3;
select t1.a, t1.b, t2.name from t1,t2 where t1.b=t2.a;
- alter table t1 drop foreign key t1_ibfk_1;
+ alter table t1 drop foreign key fk_t1;
--echo # - ON DELETE RESTRICT
alter table t1 add foreign key (b) references t2(a) on delete restrict;
@@ -253,14 +253,14 @@ if ($innodb_engine)
delete from t2 where a=3;
select t1.a, t1.b, t2.name from t1,t2 where t1.b=t2.a;
select t1.a, t1.b, t2.name from t1 left outer join t2 on (t1.b=t2.a);
- alter table t1 drop foreign key t1_ibfk_1;
+ alter table t1 drop foreign key fk_t1;
--echo # - ON DELETE CASCADE
alter table t1 add foreign key (b) references t2(a) on delete cascade;
delete from t2 where a=3;
select t1.a, t1.b, t2.name from t1,t2 where t1.b=t2.a;
select t1.a, t1.b, t2.name from t1 left outer join t2 on (t1.b=t2.a);
- alter table t1 drop foreign key t1_ibfk_1;
+ alter table t1 drop foreign key fk_t1;
drop table t1;
drop table t2;
diff --git a/mysql-test/suite/vcol/inc/vcol_keys.inc b/mysql-test/suite/vcol/inc/vcol_keys.inc
index 8ec89daff0b..7031f784506 100644
--- a/mysql-test/suite/vcol/inc/vcol_keys.inc
+++ b/mysql-test/suite/vcol/inc/vcol_keys.inc
@@ -123,11 +123,11 @@ alter table t1 add foreign key (b) references t2(a) on delete set null;
drop table t1;
if ($with_foreign_keys) {
---error ER_CANT_CREATE_TABLE
+--error ER_NO_SUCH_TABLE
create table t1 (a int, b int as (a+1), foreign key (b) references t2(a));
create table t1 (a int, b int as (a+1));
---error ER_CANT_CREATE_TABLE
+--error ER_NO_SUCH_TABLE
alter table t1 add foreign key (b) references t2(a);
drop table t1;
}
diff --git a/mysql-test/suite/vcol/r/vcol_ins_upd_innodb.result b/mysql-test/suite/vcol/r/vcol_ins_upd_innodb.result
index 6807f89fdbe..09f7706ab01 100644
--- a/mysql-test/suite/vcol/r/vcol_ins_upd_innodb.result
+++ b/mysql-test/suite/vcol/r/vcol_ins_upd_innodb.result
@@ -363,19 +363,19 @@ a b name
# - ON UPDATE RESTRICT
alter table t1 add foreign key (b) references t2(a) on update restrict;
insert into t1 (a) values (4);
-ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test`.`t1`, CONSTRAINT `t1_ibfk_1` FOREIGN KEY (`b`) REFERENCES `t2` (`a`))
+ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test`.`t1`, CONSTRAINT `fk_t1` FOREIGN KEY (`b`) REFERENCES `t2` (`a`))
update t2 set a=4 where a=3;
-ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t1`, CONSTRAINT `t1_ibfk_1` FOREIGN KEY (`b`) REFERENCES `t2` (`a`))
+ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t1`, CONSTRAINT `fk_t1` FOREIGN KEY (`b`) REFERENCES `t2` (`a`))
select t1.a, t1.b, t2.name from t1,t2 where t1.b=t2.a;
a b name
1 1 value1
2 2 value2
3 3 value3
-alter table t1 drop foreign key t1_ibfk_1;
+alter table t1 drop foreign key fk_t1;
# - ON DELETE RESTRICT
alter table t1 add foreign key (b) references t2(a) on delete restrict;
delete from t2 where a=3;
-ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t1`, CONSTRAINT `t1_ibfk_1` FOREIGN KEY (`b`) REFERENCES `t2` (`a`))
+ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t1`, CONSTRAINT `fk_t1` FOREIGN KEY (`b`) REFERENCES `t2` (`a`))
select t1.a, t1.b, t2.name from t1,t2 where t1.b=t2.a;
a b name
1 1 value1
@@ -386,7 +386,7 @@ a b name
1 1 value1
2 2 value2
3 3 value3
-alter table t1 drop foreign key t1_ibfk_1;
+alter table t1 drop foreign key fk_t1;
# - ON DELETE CASCADE
alter table t1 add foreign key (b) references t2(a) on delete cascade;
delete from t2 where a=3;
@@ -398,7 +398,7 @@ select t1.a, t1.b, t2.name from t1 left outer join t2 on (t1.b=t2.a);
a b name
1 1 value1
2 2 value2
-alter table t1 drop foreign key t1_ibfk_1;
+alter table t1 drop foreign key fk_t1;
drop table t1;
drop table t2;
#
diff --git a/mysql-test/suite/vcol/r/vcol_keys_innodb.result b/mysql-test/suite/vcol/r/vcol_keys_innodb.result
index 759de6fbb23..25c6ace9d0f 100644
--- a/mysql-test/suite/vcol/r/vcol_keys_innodb.result
+++ b/mysql-test/suite/vcol/r/vcol_keys_innodb.result
@@ -123,10 +123,10 @@ alter table t1 add foreign key (b) references t2(a) on delete set null;
ERROR HY000: Cannot define foreign key with ON DELETE SET NULL clause on a generated column
drop table t1;
create table t1 (a int, b int as (a+1), foreign key (b) references t2(a));
-ERROR HY000: Can't create table `test`.`t1` (errno: 150 "Foreign key constraint is incorrectly formed")
+ERROR 42S02: Table 'test.t2' doesn't exist
create table t1 (a int, b int as (a+1));
alter table t1 add foreign key (b) references t2(a);
-ERROR HY000: Can't create table `test`.`t1` (errno: 150 "Foreign key constraint is incorrectly formed")
+ERROR 42S02: Table 'test.t2' doesn't exist
drop table t1;
# Allowed FK options.
create table t2 (a int primary key, b char(5));
diff --git a/mysql-test/suite/versioning/r/foreign.result b/mysql-test/suite/versioning/r/foreign.result
index 07e133e1eeb..acebbb8e30d 100644
--- a/mysql-test/suite/versioning/r/foreign.result
+++ b/mysql-test/suite/versioning/r/foreign.result
@@ -17,13 +17,13 @@ on update restrict
insert into parent values(1);
insert into child values(1);
delete from parent where id = 1;
-ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`child`, CONSTRAINT `child_ibfk_1` FOREIGN KEY (`parent_id`) REFERENCES `parent` (`id`))
+ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`child`, CONSTRAINT `fk_child` FOREIGN KEY (`parent_id`) REFERENCES `parent` (`id`))
delete from child where parent_id = 1;
delete from parent where id = 1;
insert into parent values(1);
insert into child values(1);
update parent set id=id+1;
-ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`child`, CONSTRAINT `child_ibfk_1` FOREIGN KEY (`parent_id`) REFERENCES `parent` (`id`))
+ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`child`, CONSTRAINT `fk_child` FOREIGN KEY (`parent_id`) REFERENCES `parent` (`id`))
delete from child;
update parent set id=id+1;
select * from child for system_time all;
@@ -49,7 +49,7 @@ foreign key(parent_id) references parent(id)
insert into parent values(1);
insert into child values(1);
delete from parent where id = 1;
-ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`child`, CONSTRAINT `child_ibfk_1` FOREIGN KEY (`parent_id`) REFERENCES `parent` (`id`))
+ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`child`, CONSTRAINT `fk_child` FOREIGN KEY (`parent_id`) REFERENCES `parent` (`id`))
drop table child;
drop table parent;
################
@@ -202,19 +202,19 @@ foreign key(parent_id) references parent(id)
insert into parent values(1);
insert into child values(1);
delete from parent;
-ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`child`, CONSTRAINT `child_ibfk_1` FOREIGN KEY (`parent_id`) REFERENCES `parent` (`id`))
+ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`child`, CONSTRAINT `fk_child` FOREIGN KEY (`parent_id`) REFERENCES `parent` (`id`))
update parent set id=2;
-ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`child`, CONSTRAINT `child_ibfk_1` FOREIGN KEY (`parent_id`) REFERENCES `parent` (`id`))
+ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`child`, CONSTRAINT `fk_child` FOREIGN KEY (`parent_id`) REFERENCES `parent` (`id`))
delete from child;
delete from parent;
insert into child values(1);
-ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test`.`child`, CONSTRAINT `child_ibfk_1` FOREIGN KEY (`parent_id`) REFERENCES `parent` (`id`))
+ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test`.`child`, CONSTRAINT `fk_child` FOREIGN KEY (`parent_id`) REFERENCES `parent` (`id`))
insert into parent values(1);
insert into child values(1);
delete from parent;
-ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`child`, CONSTRAINT `child_ibfk_1` FOREIGN KEY (`parent_id`) REFERENCES `parent` (`id`))
+ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`child`, CONSTRAINT `fk_child` FOREIGN KEY (`parent_id`) REFERENCES `parent` (`id`))
update parent set id=2;
-ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`child`, CONSTRAINT `child_ibfk_1` FOREIGN KEY (`parent_id`) REFERENCES `parent` (`id`))
+ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`child`, CONSTRAINT `fk_child` FOREIGN KEY (`parent_id`) REFERENCES `parent` (`id`))
drop table child;
drop table parent;
###################
@@ -309,7 +309,7 @@ set foreign_key_checks= off;
insert ignore into t2 values (1);
set foreign_key_checks= on;
update t2 set f2= 2;
-ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`f2`) REFERENCES `t1` (`f1`))
+ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `fk_t2` FOREIGN KEY (`f2`) REFERENCES `t1` (`f1`))
delete from t2;
drop table t2, t1;
#
@@ -411,7 +411,7 @@ insert into t1 values (1),(2);
insert into t2 values (1);
# DELETE from referenced table is not allowed
delete from t1 where a = 1;
-ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`b`) REFERENCES `t1` (`a`))
+ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `fk_t2` FOREIGN KEY (`b`) REFERENCES `t1` (`a`))
drop tables t2, t1;
#
# MDEV-20812 Unexpected ER_ROW_IS_REFERENCED_2 or server crash in row_ins_foreign_report_err upon DELETE from versioned table with FK
@@ -449,7 +449,7 @@ drop table t1;
# MDEV-20729 Fix REFERENCES constraint in column definition
#
create or replace table t1(
-id int
+id SYS_DATATYPE
);
# system fields can't be foreign keys:
create or replace table t2(
diff --git a/mysql-test/suite/versioning/t/foreign.test b/mysql-test/suite/versioning/t/foreign.test
index ed2ed4dd122..6741c5fb02c 100644
--- a/mysql-test/suite/versioning/t/foreign.test
+++ b/mysql-test/suite/versioning/t/foreign.test
@@ -479,8 +479,9 @@ drop table t1;
--echo #
--echo # MDEV-20729 Fix REFERENCES constraint in column definition
--echo #
-create or replace table t1(
- id int
+--replace_result $sys_datatype_expl SYS_DATATYPE
+eval create or replace table t1(
+ id $sys_datatype_expl
);
--echo # system fields can't be foreign keys:
--replace_result $sys_datatype_expl SYS_DATATYPE
diff --git a/scripts/mysql_system_tables.sql b/scripts/mysql_system_tables.sql
index e390f36a98b..97f183f71c2 100644
--- a/scripts/mysql_system_tables.sql
+++ b/scripts/mysql_system_tables.sql
@@ -129,10 +129,10 @@ CREATE TABLE IF NOT EXISTS help_topic ( help_topic_id int unsigned not null, nam
CREATE TABLE IF NOT EXISTS help_category ( help_category_id smallint unsigned not null, name char(64) not null, parent_category_id smallint unsigned null, url text not null, primary key (help_category_id), unique index (name) ) engine=Aria transactional=0 CHARACTER SET utf8 comment='help categories';
-CREATE TABLE IF NOT EXISTS help_relation ( help_topic_id int unsigned not null references help_topic, help_keyword_id int unsigned not null references help_keyword, primary key (help_keyword_id, help_topic_id) ) engine=Aria transactional=0 CHARACTER SET utf8 comment='keyword-topic relation';
+CREATE TABLE IF NOT EXISTS help_keyword ( help_keyword_id int unsigned not null, name char(64) not null, primary key (help_keyword_id), unique index (name) ) engine=Aria transactional=0 CHARACTER SET utf8 comment='help keywords';
-CREATE TABLE IF NOT EXISTS help_keyword ( help_keyword_id int unsigned not null, name char(64) not null, primary key (help_keyword_id), unique index (name) ) engine=Aria transactional=0 CHARACTER SET utf8 comment='help keywords';
+CREATE TABLE IF NOT EXISTS help_relation ( help_topic_id int unsigned not null references help_topic, help_keyword_id int unsigned not null references help_keyword, primary key (help_keyword_id, help_topic_id) ) engine=Aria transactional=0 CHARACTER SET utf8 comment='keyword-topic relation';
CREATE TABLE IF NOT EXISTS time_zone_name ( Name char(64) NOT NULL, Time_zone_id int unsigned NOT NULL, PRIMARY KEY /*Name*/ (Name) ) engine=Aria transactional=1 CHARACTER SET utf8 comment='Time zone names';
diff --git a/sql/datadict.cc b/sql/datadict.cc
index e09eee98565..797a9203e4c 100644
--- a/sql/datadict.cc
+++ b/sql/datadict.cc
@@ -19,6 +19,7 @@
#include "sql_class.h"
#include "sql_table.h"
#include "ha_sequence.h"
+#include "discover.h"
static int read_string(File file, uchar**to, size_t length)
{
@@ -194,6 +195,325 @@ bool dd_recreate_table(THD *thd, const char *db, const char *table_name)
build_table_filename(path_buf, sizeof(path_buf) - 1,
db, table_name, "", 0);
/* Attempt to reconstruct the table. */
- DBUG_RETURN(ha_create_table(thd, path_buf, db, table_name, &create_info, 0));
+ DBUG_RETURN(ha_create_table(thd, path_buf, db, table_name, &create_info, NULL, 0));
}
+size_t dd_extra2_len(const uchar **pos, const uchar *end)
+{
+ size_t length= *(*pos)++;
+ if (length)
+ return length;
+
+ if ((*pos) + 2 >= end)
+ return 0;
+ length= uint2korr(*pos);
+ (*pos)+= 2;
+ if (length < 256 || *pos + length > end)
+ return 0;
+ return length;
+}
+
+
+bool Extra2_info::read(const uchar *frm_image, size_t frm_size)
+{
+ read_size= uint2korr(frm_image + 4);
+
+ if (frm_size < FRM_HEADER_SIZE + read_size)
+ return true;
+
+ const uchar *pos= frm_image + 64;
+
+ DBUG_ENTER("read_extra2");
+
+ if (*pos == '/') // old frm had '/' there
+ DBUG_RETURN(false);
+
+ const uchar *e2end= pos + read_size;
+ while (pos + 3 <= e2end)
+ {
+ extra2_frm_value_type type= (extra2_frm_value_type)*pos++;
+ size_t length= dd_extra2_len(&pos, e2end);
+ if (!length)
+ DBUG_RETURN(true);
+ switch (type) {
+ case EXTRA2_TABLEDEF_VERSION:
+ if (version.str) // see init_from_sql_statement_string()
+ {
+ if (length != version.length)
+ DBUG_RETURN(true);
+ }
+ else
+ {
+ version.str= pos;
+ version.length= length;
+ }
+ break;
+ case EXTRA2_ENGINE_TABLEOPTS:
+ if (options.str)
+ DBUG_RETURN(true);
+ options.str= pos;
+ options.length= length;
+ break;
+ case EXTRA2_DEFAULT_PART_ENGINE:
+ engine.set((const char*)pos, length);
+ break;
+ case EXTRA2_GIS:
+ if (gis.str)
+ DBUG_RETURN(true);
+ gis.str= pos;
+ gis.length= length;
+ break;
+ case EXTRA2_PERIOD_FOR_SYSTEM_TIME:
+ if (system_period.str || length != 2 * frm_fieldno_size)
+ DBUG_RETURN(true);
+ system_period.str = pos;
+ system_period.length= length;
+ break;
+ case EXTRA2_FIELD_FLAGS:
+ if (field_flags.str)
+ DBUG_RETURN(true);
+ field_flags.str= pos;
+ field_flags.length= length;
+ break;
+ case EXTRA2_APPLICATION_TIME_PERIOD:
+ if (application_period.str)
+ DBUG_RETURN(true);
+ application_period.str= pos;
+ application_period.length= length;
+ break;
+ case EXTRA2_FIELD_DATA_TYPE_INFO:
+ if (field_data_type_info.str)
+ DBUG_RETURN(true);
+ field_data_type_info.str= pos;
+ field_data_type_info.length= length;
+ break;
+ case EXTRA2_PERIOD_WITHOUT_OVERLAPS:
+ if (without_overlaps.str)
+ DBUG_RETURN(true);
+ without_overlaps.str= pos;
+ without_overlaps.length= length;
+ break;
+ case EXTRA2_FOREIGN_KEY_INFO:
+ if (foreign_key_info.str)
+ DBUG_RETURN(true);
+ foreign_key_info.str= pos;
+ foreign_key_info.length= length;
+ break;
+ default:
+ /* abort frm parsing if it's an unknown but important extra2 value */
+ if (type >= EXTRA2_ENGINE_IMPORTANT)
+ DBUG_RETURN(true);
+ }
+ pos+= length;
+ }
+ if (pos != e2end)
+ DBUG_RETURN(true);
+
+ DBUG_ASSERT(store_size() == read_size);
+ DBUG_RETURN(false);
+}
+
+
+uchar *
+Extra2_info::write(uchar *frm_image, size_t frm_size)
+{
+ // FIXME: what to do with frm_size here (and in read())?
+ uchar *pos;
+ /* write the extra2 segment */
+ pos = frm_image + FRM_HEADER_SIZE;
+ compile_time_assert(EXTRA2_TABLEDEF_VERSION != '/');
+
+ if (version.str)
+ pos= extra2_write(pos, EXTRA2_TABLEDEF_VERSION, version);
+
+ if (engine.str)
+ pos= extra2_write(pos, EXTRA2_DEFAULT_PART_ENGINE, engine);
+
+ if (options.str)
+ pos= extra2_write(pos, EXTRA2_ENGINE_TABLEOPTS, options);
+
+ if (gis.str)
+ pos= extra2_write(pos, EXTRA2_GIS, gis);
+
+ if (field_data_type_info.str)
+ pos= extra2_write(pos, EXTRA2_FIELD_DATA_TYPE_INFO, field_data_type_info);
+
+ if (foreign_key_info.str)
+ pos= extra2_write(pos, EXTRA2_FOREIGN_KEY_INFO, foreign_key_info);
+
+ if (system_period.str)
+ pos= extra2_write(pos, EXTRA2_PERIOD_FOR_SYSTEM_TIME, system_period);
+
+ if (application_period.str)
+ pos= extra2_write(pos, EXTRA2_APPLICATION_TIME_PERIOD, application_period);
+
+ if (without_overlaps.str)
+ pos= extra2_write(pos, EXTRA2_PERIOD_WITHOUT_OVERLAPS, without_overlaps);
+
+ if (field_flags.str)
+ pos= extra2_write(pos, EXTRA2_FIELD_FLAGS, field_flags);
+
+ write_size= pos - frm_image - FRM_HEADER_SIZE;
+ DBUG_ASSERT(write_size == store_size());
+ DBUG_ASSERT(write_size <= 0xffff - FRM_HEADER_SIZE - 4);
+
+#if 0
+ int4store(pos, filepos); // end of the extra2 segment
+#endif
+ return pos;
+}
+
+
+int TABLE_SHARE::fk_write_shadow_frm()
+{
+ const uchar * frm_src;
+ uchar * frm_dst;
+ uchar * pos;
+ size_t frm_size;
+ Extra2_info extra2;
+ Foreign_key_io foreign_key_io;
+
+ int err= read_frm_image(&frm_src, &frm_size);
+ if (err)
+ {
+ char path[FN_REFLEN + 1];
+ strxmov(path, normalized_path.str, reg_ext, NullS);
+ switch (err)
+ {
+ case 1:
+ my_error(ER_CANT_OPEN_FILE, MYF(0), path, my_errno);
+ break;
+ case 2:
+ my_error(ER_FILE_NOT_FOUND, MYF(0), path, my_errno);
+ break;
+ default:
+ my_error(ER_OUT_OF_RESOURCES, MYF(0));
+ break;
+ }
+ return err;
+ }
+
+ Scope_malloc frm_src_freer(frm_src); // read_frm_image() passed ownership to us
+
+ if (frm_size < FRM_HEADER_SIZE + FRM_FORMINFO_SIZE)
+ {
+frm_err:
+ char path[FN_REFLEN + 1];
+ strxmov(path, normalized_path.str, reg_ext, NullS);
+ my_error(ER_NOT_FORM_FILE, MYF(0), path);
+ return 10;
+ }
+
+ if (!is_binary_frm_header(frm_src))
+ goto frm_err;
+
+ if (extra2.read(frm_src, frm_size))
+ {
+ my_printf_error(ER_CANT_CREATE_TABLE,
+ "Cannot create table %`s: "
+ "Read of extra2 section failed.",
+ MYF(0), table_name.str);
+ return 10;
+ }
+
+ const uchar * const rest_src= frm_src + FRM_HEADER_SIZE + extra2.read_size;
+ const size_t rest_size= frm_size - FRM_HEADER_SIZE - extra2.read_size;
+ size_t forminfo_off= uint4korr(rest_src);
+
+ foreign_key_io.store(foreign_keys, referenced_keys);
+ extra2.foreign_key_info= foreign_key_io.lex_custring();
+ if (!extra2.foreign_key_info.length)
+ extra2.foreign_key_info.str= NULL;
+ else if (extra2.foreign_key_info.length > 0xffff - FRM_HEADER_SIZE - 8)
+ {
+ my_printf_error(ER_CANT_CREATE_TABLE,
+ "Cannot create table %`s: "
+ "Building the foreign key info image failed.",
+ MYF(0), table_name.str);
+ return 10;
+ }
+
+ const size_t extra2_increase= extra2.store_size() - extra2.read_size; // FIXME: can be negative
+ frm_size+= extra2_increase;
+
+ if (frm_size > FRM_MAX_SIZE)
+ {
+ my_error(ER_TABLE_DEFINITION_TOO_BIG, MYF(0), table_name.str);
+ return 10;
+ }
+
+ Scope_malloc frm_dst_freer(frm_dst, frm_size, MY_WME);
+ if (!frm_dst)
+ return 10;
+
+ memcpy((void *)frm_dst, (void *)frm_src, FRM_HEADER_SIZE);
+
+ if (!(pos= extra2.write(frm_dst, frm_size)))
+ {
+ my_printf_error(ER_CANT_CREATE_TABLE,
+ "Cannot create table %`s: "
+ "Write of extra2 section failed.",
+ MYF(0), table_name.str);
+ return 10;
+ }
+
+ forminfo_off+= extra2_increase;
+ int4store(pos, forminfo_off);
+ pos+= 4;
+ int2store(frm_dst + 4, extra2.write_size);
+ int2store(frm_dst + 6, FRM_HEADER_SIZE + extra2.write_size + 4); // Position to key information
+ int4store(frm_dst + 10, frm_size);
+ memcpy((void *)pos, rest_src + 4, rest_size - 4);
+
+ char shadow_path[FN_REFLEN + 1];
+ char shadow_frm_name[FN_REFLEN + 1];
+ build_table_shadow_filename(shadow_path, sizeof(shadow_path) - 1,
+ db, table_name);
+ strxnmov(shadow_frm_name, sizeof(shadow_frm_name), shadow_path, reg_ext, NullS);
+ if (writefile(shadow_frm_name, db.str, table_name.str, false, frm_dst, frm_size))
+ return 10;
+
+ return 0;
+}
+
+bool fk_install_shadow_frm(Table_name old_name, Table_name new_name)
+{
+ char shadow_path[FN_REFLEN + 1];
+ char path[FN_REFLEN];
+ char shadow_frm_name[FN_REFLEN + 1];
+ char frm_name[FN_REFLEN + 1];
+ MY_STAT stat_info;
+ build_table_shadow_filename(shadow_path, sizeof(shadow_path) - 1,
+ old_name.db, old_name.name);
+ build_table_filename(path, sizeof(path), new_name.db.str,
+ new_name.name.str, "", 0);
+ strxnmov(shadow_frm_name, sizeof(shadow_frm_name), shadow_path, reg_ext, NullS);
+ strxnmov(frm_name, sizeof(frm_name), path, reg_ext, NullS);
+ if (!mysql_file_stat(key_file_frm, shadow_frm_name, &stat_info, MYF(MY_WME)))
+ return true;
+ if (mysql_file_delete(key_file_frm, frm_name, MYF(MY_WME)))
+ return true;
+ if (mysql_file_rename(key_file_frm, shadow_frm_name, frm_name, MYF(MY_WME)))
+ return true;
+ return false;
+}
+
+bool TABLE_SHARE::fk_install_shadow_frm()
+{
+ return ::fk_install_shadow_frm({db, table_name}, {db, table_name});
+}
+
+void fk_drop_shadow_frm(Table_name table)
+{
+ char shadow_path[FN_REFLEN+1];
+ char shadow_frm_name[FN_REFLEN+1];
+ build_table_shadow_filename(shadow_path, sizeof(shadow_path) - 1,
+ table.db, table.name);
+ strxnmov(shadow_frm_name, sizeof(shadow_frm_name), shadow_path, reg_ext, NullS);
+ mysql_file_delete(key_file_frm, shadow_frm_name, MYF(0));
+}
+
+void TABLE_SHARE::fk_drop_shadow_frm()
+{
+ ::fk_drop_shadow_frm({db, table_name});
+}
diff --git a/sql/datadict.h b/sql/datadict.h
index f4af592247a..f88f8bc217f 100644
--- a/sql/datadict.h
+++ b/sql/datadict.h
@@ -30,6 +30,113 @@ enum Table_type
TABLE_TYPE_VIEW
};
+
+#define INVISIBLE_MAX_BITS 3
+
+/*
+ Types of values in the MariaDB extra2 frm segment.
+ Each value is written as
+ type: 1 byte
+ length: 1 byte (1..255) or \0 and 2 bytes.
+ binary value of the 'length' bytes.
+
+ Older MariaDB servers can ignore values of unknown types if
+ the type code is less than 128 (EXTRA2_ENGINE_IMPORTANT).
+ Otherwise older (but newer than 10.0.1) servers are required
+ to report an error.
+*/
+enum extra2_frm_value_type
+{
+ EXTRA2_TABLEDEF_VERSION=0,
+ EXTRA2_DEFAULT_PART_ENGINE=1,
+ EXTRA2_GIS=2,
+ EXTRA2_APPLICATION_TIME_PERIOD=3,
+ EXTRA2_PERIOD_FOR_SYSTEM_TIME=4,
+ EXTRA2_FOREIGN_KEY_INFO=5,
+
+#define EXTRA2_ENGINE_IMPORTANT 128
+
+ EXTRA2_ENGINE_TABLEOPTS=128,
+ EXTRA2_FIELD_FLAGS=129,
+ EXTRA2_FIELD_DATA_TYPE_INFO=130,
+ EXTRA2_PERIOD_WITHOUT_OVERLAPS=131
+};
+
+enum extra2_field_flags
+{
+ VERS_OPTIMIZED_UPDATE= 1 << INVISIBLE_MAX_BITS
+};
+
+uchar * extra2_write_len(uchar *pos, size_t len);
+uchar * extra2_write_str(uchar *pos, const LEX_CSTRING &str);
+inline
+uchar *
+extra2_write(uchar *pos, enum extra2_frm_value_type type, const LEX_CSTRING &str)
+{
+ *pos++ = type;
+ return extra2_write_str(pos, str);
+}
+inline
+uchar *
+extra2_write(uchar *pos, enum extra2_frm_value_type type, const LEX_CUSTRING &str)
+{
+ return extra2_write(pos, type, *reinterpret_cast<const LEX_CSTRING*>(&str));
+}
+uchar *
+extra2_write_field_properties(uchar *pos, List<Create_field> &create_fields);
+
+
+struct Extra2_info
+{
+ LEX_CUSTRING version;
+ LEX_CUSTRING options;
+ Lex_ident engine;
+ LEX_CUSTRING gis;
+ LEX_CUSTRING field_flags;
+ LEX_CUSTRING system_period;
+ LEX_CUSTRING application_period;
+ LEX_CUSTRING field_data_type_info;
+ LEX_CUSTRING without_overlaps;
+ LEX_CUSTRING foreign_key_info;
+ uint read_size;
+ size_t write_size;
+
+ Extra2_info()
+ {
+ bzero((void*)this, sizeof(*this));
+ }
+
+ template <class S>
+ size_t store_size(const S &f) const
+ {
+ if (f.length == 0)
+ return 0;
+ DBUG_ASSERT(f.length <= 65535);
+ // 1 byte is for type; 1 or 3 bytes for length
+ return f.length + (f.length <= 255 ? 2 : 4);
+ }
+ size_t store_size() const
+ {
+ return
+ store_size(version) +
+ store_size(options) +
+ store_size(engine) +
+ store_size(gis) +
+ store_size(field_flags) +
+ store_size(system_period) +
+ store_size(application_period) +
+ store_size(field_data_type_info) +
+ store_size(without_overlaps) +
+ store_size(foreign_key_info);
+ }
+ bool read(const uchar* frm_image, size_t frm_size);
+ uchar * write(uchar* frm_image, size_t frm_size);
+};
+
+class Table_name;
+bool fk_install_shadow_frm(Table_name old_name, Table_name new_name);
+void fk_drop_shadow_frm(Table_name table);
+
/*
Take extra care when using dd_frm_type() - it only checks the .frm file,
and it won't work for any engine that supports discovery.
@@ -46,5 +153,5 @@ static inline bool dd_frm_is_view(THD *thd, char *path)
}
bool dd_recreate_table(THD *thd, const char *db, const char *table_name);
-
+size_t dd_extra2_len(const uchar** pos, const uchar* end);
#endif // DATADICT_INCLUDED
diff --git a/sql/ddl_log.cc b/sql/ddl_log.cc
index 3190dc464c7..01b44bb9b79 100644
--- a/sql/ddl_log.cc
+++ b/sql/ddl_log.cc
@@ -1905,8 +1905,8 @@ bool ddl_log_write_entry(DDL_LOG_ENTRY *ddl_log_entry,
header for the list.
When called, the previous log entries have already been written but not yet
- synched to disk. We write a couple of log entries that describes
- action to perform. This entries are set-up in a linked list,
+ synched to disk. We write a couple of log entries that describe
+ action to perform. These entries are set-up in a linked list,
however only when an execute entry is put as the first entry these will be
executed during recovery.
diff --git a/sql/discover.cc b/sql/discover.cc
index 4267f97cf59..358040e687d 100644
--- a/sql/discover.cc
+++ b/sql/discover.cc
@@ -61,6 +61,7 @@ int readfrm(const char *name, const uchar **frmdata, size_t *len)
*frmdata= NULL; // In case of errors
*len= 0;
error= 1;
+ // TODO: Why MY_WME not everywhere?
if ((file= mysql_file_open(key_file_frm,
fn_format(index_file, name, "", reg_ext,
MY_UNPACK_FILENAME|MY_APPEND_EXT),
diff --git a/sql/ha_partition.h b/sql/ha_partition.h
index 2669d475ff1..b30dd40e8e2 100644
--- a/sql/ha_partition.h
+++ b/sql/ha_partition.h
@@ -1429,27 +1429,6 @@ public:
by the partition handler
*/
- /*
- -------------------------------------------------------------------------
- MODULE foreign key support
- -------------------------------------------------------------------------
- The following methods are used to implement foreign keys as supported by
- InnoDB. Implement this ??
- get_foreign_key_create_info is used by SHOW CREATE TABLE to get a textual
- description of how the CREATE TABLE part to define FOREIGN KEY's is done.
- free_foreign_key_create_info is used to free the memory area that provided
- this description.
- can_switch_engines checks if it is ok to switch to a new engine based on
- the foreign key info in the table.
- -------------------------------------------------------------------------
-
- virtual char* get_foreign_key_create_info()
- virtual void free_foreign_key_create_info(char* str)
-
- virtual int get_foreign_key_list(THD *thd,
- List<FOREIGN_KEY_INFO> *f_key_list)
- virtual uint referenced_by_foreign_key()
- */
bool can_switch_engines() override;
/*
-------------------------------------------------------------------------
diff --git a/sql/handler.cc b/sql/handler.cc
index 1a8f9d2d96f..dd6e24166df 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -31,6 +31,7 @@
#include "sql_table.h" // build_table_filename
#include "sql_parse.h" // check_stack_overrun
#include "sql_base.h" // TDC_element
+#include "sql_rename.h"
#include "discover.h" // extension_based_table_discovery, etc
#include "log_event.h" // *_rows_log_event
#include "create_options.h"
@@ -4937,11 +4938,13 @@ handler::check_if_supported_inplace_alter(TABLE *altered_table,
Alter_inplace_info::Alter_inplace_info(HA_CREATE_INFO *create_info_arg,
Alter_info *alter_info_arg,
+ Alter_table_ctx *alter_ctx_arg,
KEY *key_info_arg, uint key_count_arg,
partition_info *modified_part_info_arg,
bool ignore_arg, bool error_non_empty)
: create_info(create_info_arg),
alter_info(alter_info_arg),
+ alter_ctx(alter_ctx_arg),
key_info_buffer(key_info_arg),
key_count(key_count_arg),
index_drop_count(0),
@@ -5524,13 +5527,15 @@ int handler::calculate_checksum()
*/
int ha_create_table(THD *thd, const char *path,
const char *db, const char *table_name,
- HA_CREATE_INFO *create_info, LEX_CUSTRING *frm)
+ HA_CREATE_INFO *create_info, Alter_info *alter_info,
+ LEX_CUSTRING *frm, bool fk_update_refs)
{
int error= 1;
TABLE table;
char name_buff[FN_REFLEN];
const char *name;
TABLE_SHARE share;
+ FK_create_vector fk_shares;
bool temp_table __attribute__((unused)) =
create_info->options & (HA_LEX_CREATE_TMP_TABLE | HA_CREATE_TMP_ALTER);
DBUG_ENTER("ha_create_table");
@@ -5558,11 +5563,16 @@ int ha_create_table(THD *thd, const char *path,
goto err;
}
+ if (fk_update_refs && share.fk_handle_create(thd, fk_shares))
+ goto err;
+
share.m_psi= PSI_CALL_get_table_share(temp_table, &share);
if (open_table_from_share(thd, &share, &empty_clex_str, 0, READ_ALL, 0,
&table, true))
+ {
goto err;
+ }
update_create_info_from_table(create_info, &table);
@@ -5580,10 +5590,29 @@ int ha_create_table(THD *thd, const char *path,
}
(void) closefrm(&table);
-
+ if (error)
+ goto err;
+
+ if (fk_update_refs)
+ {
+ for (FK_ddl_backup &bak: fk_shares)
+ {
+ bak.sa.share->fk_install_shadow_frm();
+ /* TODO: (MDEV-21053) Now there is no right for error.
+ Actually it should drop table if install shadow fails. */
+ thd->clear_error();
+ }
+ }
+
+ free_table_share(&share);
+ DBUG_RETURN(0);
+
err:
+ if (fk_update_refs)
+ for (FK_ddl_backup &bak: fk_shares)
+ bak.rollback();
free_table_share(&share);
- DBUG_RETURN(error != 0);
+ DBUG_RETURN(1);
}
void st_ha_check_opt::init()
diff --git a/sql/handler.h b/sql/handler.h
index 12f36b7a4e1..3b3c0966cf4 100644
--- a/sql/handler.h
+++ b/sql/handler.h
@@ -46,6 +46,7 @@
#include "mem_root_array.h"
class Alter_info;
+class Alter_table_ctx;
class Virtual_column_info;
class sequence_definition;
class Rowid_filter;
@@ -1063,7 +1064,12 @@ enum enum_schema_tables
struct TABLE_SHARE;
struct HA_CREATE_INFO;
struct st_foreign_key_info;
-typedef struct st_foreign_key_info FOREIGN_KEY_INFO;
+class FK_info;
+class FK_list : public List<FK_info>
+{
+public:
+ bool assign(const FK_list &src, MEM_ROOT *mem_root);
+};
typedef bool (stat_print_fn)(THD *thd, const char *type, size_t type_len,
const char *file, size_t file_len,
const char *status, size_t status_len);
@@ -2411,6 +2417,7 @@ public:
Field instance for old version of table.
*/
Alter_info *alter_info;
+ Alter_table_ctx *alter_ctx;
/**
Array of KEYs for new version of table - including KEYs to be added.
@@ -2538,6 +2545,7 @@ public:
Alter_inplace_info(HA_CREATE_INFO *create_info_arg,
Alter_info *alter_info_arg,
+ Alter_table_ctx *alter_ctx_arg,
KEY *key_info_arg, uint key_count_arg,
partition_info *modified_part_info_arg,
bool ignore_arg, bool error_non_empty);
@@ -4061,35 +4069,6 @@ public:
*/
virtual bool can_switch_engines() { return true; }
virtual int can_continue_handler_scan() { return 0; }
- /**
- Get the list of foreign keys in this table.
-
- @remark Returns the set of foreign keys where this table is the
- dependent or child table.
-
- @param thd The thread handle.
- @param f_key_list[out] The list of foreign keys.
-
- @return The handler error code or zero for success.
- */
- virtual int
- get_foreign_key_list(THD *thd, List<FOREIGN_KEY_INFO> *f_key_list)
- { return 0; }
- /**
- Get the list of foreign keys referencing this table.
-
- @remark Returns the set of foreign keys where this table is the
- referenced or parent table.
-
- @param thd The thread handle.
- @param f_key_list[out] The list of foreign keys.
-
- @return The handler error code or zero for success.
- */
- virtual int
- get_parent_foreign_key_list(THD *thd, List<FOREIGN_KEY_INFO> *f_key_list)
- { return 0; }
- virtual uint referenced_by_foreign_key() { return 0;}
virtual void init_table_handle_for_HANDLER()
{ return; } /* prepare InnoDB for HANDLER */
virtual void free_foreign_key_create_info(char* str) {}
@@ -5115,7 +5094,8 @@ void ha_checkpoint_state(bool disable);
void ha_commit_checkpoint_request(void *cookie, void (*pre_hook)(void *));
int ha_create_table(THD *thd, const char *path,
const char *db, const char *table_name,
- HA_CREATE_INFO *create_info, LEX_CUSTRING *frm);
+ HA_CREATE_INFO *create_info, Alter_info *alter_info,
+ LEX_CUSTRING *frm, bool fk_update_refs= false);
int ha_delete_table(THD *thd, handlerton *db_type, const char *path,
const LEX_CSTRING *db, const LEX_CSTRING *alias,
bool generate_warning);
diff --git a/sql/item.cc b/sql/item.cc
index 1e2c38f1eba..731de380e07 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -41,6 +41,7 @@
// find_item_in_list,
// RESOLVED_AGAINST_ALIAS, ...
#include "sql_expression_cache.h"
+#include "table.h"
const String my_null_string("NULL", 4, default_charset_info);
const String my_default_string("DEFAULT", 7, default_charset_info);
@@ -1502,7 +1503,7 @@ bool Item_field::check_vcol_func_processor(void *arg)
{
for (Key &k: res->alter_info->key_list)
{
- if (k.type != Key::FOREIGN_KEY)
+ if (!k.foreign)
continue;
Foreign_key *fk= (Foreign_key*) &k;
if (fk->update_opt != FK_OPTION_CASCADE)
@@ -10538,7 +10539,7 @@ table_map Item_ref_null_helper::used_tables() const
#ifndef DBUG_OFF
/* Debugger help function */
-static char dbug_item_print_buf[2048];
+static char dbug_item_print_buf[4096];
const char *dbug_print_item(Item *item)
{
@@ -10606,9 +10607,26 @@ const char *dbug_print_unit(SELECT_LEX_UNIT *un)
return "Couldn't fit into buffer";
}
+const char *dbug_print_fk(FK_info *fk)
+{
+ char *buf= dbug_item_print_buf;
+ String str(buf, sizeof(dbug_item_print_buf), &my_charset_bin);
+ str.length(0);
+ if (!fk)
+ return "(FK_info *) NULL";
+
+ fk->print(str);
+
+ if (str.c_ptr() == buf)
+ return buf;
+ else
+ return "Couldn't fit into buffer";
+}
+
const char *dbug_print(Item *x) { return dbug_print_item(x); }
const char *dbug_print(SELECT_LEX *x) { return dbug_print_select(x); }
const char *dbug_print(SELECT_LEX_UNIT *x) { return dbug_print_unit(x); }
+const char *dbug_print(FK_info *x) { return dbug_print_fk(x); }
#endif /*DBUG_OFF*/
diff --git a/sql/lex_string.h b/sql/lex_string.h
index e7a732346c4..c6863b6c225 100644
--- a/sql/lex_string.h
+++ b/sql/lex_string.h
@@ -18,11 +18,14 @@
#ifndef LEX_STRING_INCLUDED
#define LEX_STRING_INCLUDED
+#include "sql_alloc.h"
+#include "mysqld.h"
+
typedef struct st_mysql_const_lex_string LEX_CSTRING;
-class Lex_cstring : public LEX_CSTRING
+class Lex_cstring : public LEX_CSTRING, public Sql_alloc
{
public:
Lex_cstring()
@@ -39,17 +42,74 @@ class Lex_cstring : public LEX_CSTRING
str= _str;
length= _len;
}
+ Lex_cstring(const char *_str)
+ {
+ str= _str;
+ length= strlen(str);
+ }
Lex_cstring(const char *start, const char *end)
{
DBUG_ASSERT(start <= end);
str= start;
length= end - start;
}
+ bool strdup(MEM_ROOT *mem_root, const char *_str, size_t _len)
+ {
+ if (!_str)
+ {
+ str= NULL;
+ length= 0;
+ return false;
+ }
+ length= _len;
+ str= strmake_root(mem_root, _str, length);
+ return !str;
+ }
+ bool strdup(MEM_ROOT *mem_root, const char *_str)
+ {
+ if (!_str)
+ {
+ str= NULL;
+ length= 0;
+ return false;
+ }
+ return strdup(mem_root, _str, strlen(_str));
+ }
+ bool strdup(MEM_ROOT *mem_root, const Lex_cstring &_str)
+ {
+ if (!_str.str)
+ {
+ str= NULL;
+ length= 0;
+ return false;
+ }
+ return strdup(mem_root, _str.str, _str.length);;
+ }
void set(const char *_str, size_t _len)
{
str= _str;
length= _len;
}
+ Lex_cstring print() const
+ {
+ return str ? *this : "(NULL)";
+ }
+ int cmp(const Lex_cstring& rhs) const
+ {
+ if (length < rhs.length)
+ return -1;
+ if (length > rhs.length)
+ return 1;
+ return memcmp(str, rhs.str, length);
+ }
+ int cmp(const char* rhs) const
+ {
+ if (!str)
+ return -1;
+ if (!rhs)
+ return 1;
+ return strcmp(str, rhs);
+ }
};
@@ -61,6 +121,27 @@ public:
{ }
};
+class Scope_malloc
+{
+ void * addr;
+
+public:
+ template <class PTR>
+ Scope_malloc(PTR alloced) : addr((void *)alloced)
+ {
+ DBUG_ASSERT(addr);
+ }
+ template <class PTR>
+ Scope_malloc(PTR &assign, size_t Size, myf MyFlags= 0)
+ {
+ addr= my_malloc(PSI_NOT_INSTRUMENTED, Size, MyFlags);
+ assign= (PTR) addr;
+ }
+ ~Scope_malloc()
+ {
+ my_free(addr);
+ }
+};
/* Functions to compare if two lex strings are equal */
@@ -83,6 +164,22 @@ static inline bool cmp(const LEX_CSTRING a, const LEX_CSTRING b)
{
return a.length != b.length || (a.length && memcmp(a.str, b.str, a.length));
}
+static inline int cmp_ident(const LEX_CSTRING a, const LEX_CSTRING b)
+{
+ return my_strcasecmp(system_charset_info, a.str, b.str);
+}
+static inline int cmp_table(const LEX_CSTRING a, const LEX_CSTRING b)
+{
+ return my_strcasecmp(table_alias_charset, a.str, b.str);
+}
+struct Lex_ident_lt
+{
+ bool operator() (const Lex_cstring &lhs, const Lex_cstring &rhs) const
+ {
+ return cmp_ident(lhs, rhs) < 0;
+ }
+};
+
/*
Compare if two LEX_CSTRING are equal. Assumption is that
@@ -108,4 +205,36 @@ static inline bool lex_string_eq(const LEX_CSTRING *a, const char *b, size_t b_l
return strcasecmp(a->str, b) == 0;
}
+inline
+LEX_CSTRING *make_clex_string(MEM_ROOT *mem_root, const char* str, size_t length)
+{
+ LEX_CSTRING *lex_str;
+ char *tmp;
+ if (unlikely(!(lex_str= (LEX_CSTRING *)alloc_root(mem_root,
+ sizeof(LEX_CSTRING) +
+ (str ? (length + 1) : 0)))))
+ return 0;
+ if (str)
+ {
+ tmp= (char*) (lex_str+1);
+ lex_str->str= tmp;
+ memcpy(tmp, str, length);
+ tmp[length]= 0;
+ lex_str->length= length;
+ }
+ else
+ {
+ DBUG_ASSERT(!length);
+ lex_str->str= NULL;
+ lex_str->length= 0;
+ }
+ return lex_str;
+}
+
+inline
+LEX_CSTRING *make_clex_string(MEM_ROOT *mem_root, const LEX_CSTRING from)
+{
+ return make_clex_string(mem_root, from.str, from.length);
+}
+
#endif /* LEX_STRING_INCLUDED */
diff --git a/sql/lock.cc b/sql/lock.cc
index ff215795604..ebe6f325e65 100644
--- a/sql/lock.cc
+++ b/sql/lock.cc
@@ -193,7 +193,7 @@ lock_tables_check(THD *thd, TABLE **tables, uint count, uint flags)
locking a mix of system and non-system tables in the same lock
is prohibited, to prevent contention.
*/
- if ((system_count > 0) && (system_count < count))
+ if (!opt_bootstrap && (system_count > 0) && (system_count < count))
{
my_error(ER_WRONG_LOCK_OF_SYSTEM_TABLE, MYF(0));
DBUG_RETURN(1);
diff --git a/sql/log_event_old.cc b/sql/log_event_old.cc
index 4e6b9e3f1c8..66913b63872 100644
--- a/sql/log_event_old.cc
+++ b/sql/log_event_old.cc
@@ -572,7 +572,7 @@ replace_record(THD *thd, TABLE *table,
the correct row.
*/
if (last_uniq_key(table, keynum) &&
- !table->file->referenced_by_foreign_key())
+ !table->s->referenced_by_foreign_key())
{
error=table->file->ha_update_row(table->record[1],
table->record[0]);
@@ -2066,7 +2066,7 @@ Old_rows_log_event::write_row(rpl_group_info *rgi, const bool overwrite)
the correct row.
*/
if (last_uniq_key(table, keynum) &&
- !table->file->referenced_by_foreign_key())
+ !table->s->referenced_by_foreign_key())
{
DBUG_PRINT("info",("Updating row using ha_update_row()"));
error=table->file->ha_update_row(table->record[1],
diff --git a/sql/log_event_server.cc b/sql/log_event_server.cc
index b43defc213b..63cf04a2287 100644
--- a/sql/log_event_server.cc
+++ b/sql/log_event_server.cc
@@ -7410,7 +7410,7 @@ Rows_log_event::write_row(rpl_group_info *rgi,
when triggers are used we want a simple and predictable execution path.
*/
if (last_uniq_key(table, keynum) && !invoke_triggers &&
- !table->file->referenced_by_foreign_key())
+ !table->s->referenced_by_foreign_key())
{
DBUG_PRINT("info",("Updating row using ha_update_row()"));
error= table->file->ha_update_row(table->record[1],
diff --git a/sql/sql_admin.cc b/sql/sql_admin.cc
index abb7939595a..1454e1add55 100644
--- a/sql/sql_admin.cc
+++ b/sql/sql_admin.cc
@@ -856,6 +856,15 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
(check_eits_collection_allowed(thd) ||
lex->with_persistent_for_clause));
}
+ else if (!table->table->s->crashed &&
+ operator_func == &handler::ha_check &&
+ !(check_opt->sql_flags & TT_FOR_UPGRADE))
+ {
+ if (table->table->s->fk_check_consistency(thd))
+ {
+ compl_result_code= result_code= HA_ADMIN_FAILED;
+ }
+ }
if (result_code == HA_ADMIN_OK)
{
diff --git a/sql/sql_alter.cc b/sql/sql_alter.cc
index 0184f6beaf4..b13cc610e10 100644
--- a/sql/sql_alter.cc
+++ b/sql/sql_alter.cc
@@ -23,6 +23,8 @@
Alter_info::Alter_info(const Alter_info &rhs, MEM_ROOT *mem_root)
:drop_list(rhs.drop_list, mem_root),
+ tmp_drop_list(rhs.tmp_drop_list, mem_root),
+ tmp_old_fkeys(rhs.tmp_old_fkeys),
alter_list(rhs.alter_list, mem_root),
key_list(rhs.key_list, mem_root),
alter_rename_key_list(rhs.alter_rename_key_list, mem_root),
@@ -45,6 +47,7 @@ Alter_info::Alter_info(const Alter_info &rhs, MEM_ROOT *mem_root)
constants never change.
*/
list_copy_and_replace_each_value(drop_list, mem_root);
+ list_copy_and_replace_each_value(tmp_drop_list, mem_root);
list_copy_and_replace_each_value(alter_list, mem_root);
list_copy_and_replace_each_value(key_list, mem_root);
list_copy_and_replace_each_value(alter_rename_key_list, mem_root);
diff --git a/sql/sql_alter.h b/sql/sql_alter.h
index 250801838b3..7a6e3aca5bb 100644
--- a/sql/sql_alter.h
+++ b/sql/sql_alter.h
@@ -17,11 +17,70 @@
#ifndef SQL_ALTER_TABLE_H
#define SQL_ALTER_TABLE_H
+#include "sql_class.h"
+#include "table_cache.h"
+
class Alter_drop;
class Alter_column;
class Alter_rename_key;
class Key;
+
+/* Backup for the table we altering */
+class FK_table_backup
+{
+public:
+ TABLE_SHARE *share;
+ FK_list foreign_keys;
+ FK_list referenced_keys;
+
+ FK_table_backup() : share(NULL) {}
+ virtual ~FK_table_backup()
+ {
+ if (share)
+ rollback();
+ }
+ bool init(TABLE_SHARE *);
+ void commit()
+ {
+ share= NULL;
+ }
+ void rollback()
+ {
+ DBUG_ASSERT(share);
+ share->foreign_keys= foreign_keys;
+ share->referenced_keys= referenced_keys;
+ share= NULL;
+ }
+};
+
+
+/* Backup for the table we refering or which referes us */
+class FK_ref_backup : public FK_table_backup
+{
+public:
+ bool install_shadow;
+ FK_ref_backup() : install_shadow(false) {}
+ virtual ~FK_ref_backup()
+ {
+ commit();
+ }
+};
+
+
+/* DROP FK does not fail for non-existent ref (but other commands do) */
+struct FK_table_to_lock
+{
+ Table_name table;
+ bool fail; // fail on non-existent foreign/referenced table
+ FK_table_to_lock(Table_name _table) : table(_table), fail(false) {}
+ bool operator< (const FK_table_to_lock &rhs) const
+ {
+ return table.cmp(rhs.table) < 0;
+ }
+};
+
+
/**
Data describing the table being created by CREATE TABLE or
altered by ALTER TABLE.
@@ -87,6 +146,9 @@ public:
// Columns and keys to be dropped.
List<Alter_drop> drop_list;
+ // FIXME: these two to be removed in MDEV-21052
+ List<Alter_drop> tmp_drop_list;
+ uint tmp_old_fkeys;
// Columns for ALTER_CHANGE_COLUMN_DEFAULT.
List<Alter_column> alter_list;
// List of keys, used by both CREATE and ALTER TABLE.
@@ -115,7 +177,8 @@ public:
Alter_info() :
- flags(0), partition_flags(0),
+ tmp_old_fkeys(0),
+ flags(0), partition_flags(0),
keys_onoff(LEAVE_AS_IS),
num_parts(0),
requested_algorithm(ALTER_TABLE_ALGORITHM_NONE),
@@ -125,6 +188,8 @@ public:
void reset()
{
drop_list.empty();
+ tmp_drop_list.empty();
+ tmp_old_fkeys= 0;
alter_list.empty();
key_list.empty();
alter_rename_key_list.empty();
@@ -303,8 +368,8 @@ public:
void set_fk_error_if_delete_row(FOREIGN_KEY_INFO *fk)
{
fk_error_if_delete_row= true;
- fk_error_id= fk->foreign_id->str;
- fk_error_table= fk->foreign_table->str;
+ fk_error_id= fk->foreign_id.str;
+ fk_error_table= fk->foreign_table.str;
}
void report_implicit_default_value_error(THD *thd, const TABLE_SHARE *) const;
@@ -317,7 +382,7 @@ public:
LEX_CSTRING alias;
LEX_CSTRING new_db;
LEX_CSTRING new_name;
- LEX_CSTRING new_alias;
+ LEX_CSTRING new_alias; // TODO: why new_alias is needed?
LEX_CSTRING tmp_name;
char tmp_buff[80];
/**
@@ -330,6 +395,59 @@ public:
const char *fk_error_id;
/** Name of table for the above error. */
const char *fk_error_table;
+ struct FK_rename_col
+ {
+ Table_name table;
+ Table_name altered_table;
+ Lex_cstring col_name;
+ Lex_cstring new_name;
+ // NB: "operator<" is required for std::set
+ bool operator< (const FK_rename_col &rhs) const
+ {
+ int ref_cmp= table.cmp(rhs.table);
+ if (ref_cmp < 0)
+ return true;
+ if (ref_cmp > 0)
+ return false;
+ return col_name.cmp(rhs.col_name) < 0;
+ }
+ };
+ struct FK_add_new
+ {
+ Table_name ref;
+ Foreign_key *fk;
+ };
+ struct FK_drop_old
+ {
+ Table_name ref;
+ const FK_info *fk;
+ };
+ // NB: multiple foreign keys can utilize same column (see fk_prepare_rename())
+ mbd::set<FK_rename_col> fk_renamed_cols;
+ mbd::set<FK_rename_col> rk_renamed_cols;
+ mbd::vector<FK_add_new> fk_added;
+ mbd::vector<FK_drop_old> fk_dropped;
+ mbd::vector<Table_name> fk_renamed_table;
+ mbd::vector<Table_name> rk_renamed_table;
+ /** FK list prepared by prepare_create_table() */
+ FK_list foreign_keys;
+ /** RK list inherited from old table + self-refs from prepare_create_table() */
+ FK_list referenced_keys;
+ MDL_request_list fk_mdl_reqs;
+ mbd::map<Table_name, Share_acquire, Table_name_lt> fk_shares;
+
+ bool fk_prepare_rename(THD *thd, TABLE *table, Create_field *def,
+ mbd::set<FK_table_to_lock> &fk_tables_to_lock);
+ bool fk_handle_alter(THD *thd);
+ void fk_release_locks(THD *thd);
+
+ FK_table_backup fk_table_backup;
+ // NB: share is owned and released by fk_shares
+ mbd::map<TABLE_SHARE *, FK_ref_backup> fk_ref_backup;
+ // NB: backup is added only if not exists
+ FK_ref_backup* fk_add_backup(TABLE_SHARE *share);
+ void fk_rollback();
+ bool fk_install_frms();
private:
char new_filename[FN_REFLEN + 1];
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index 66176dc55ba..999c88dea59 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -4610,43 +4610,36 @@ prepare_fk_prelocking_list(THD *thd, Query_tables_list *prelocking_ctx,
uint8 op)
{
DBUG_ENTER("prepare_fk_prelocking_list");
- List <FOREIGN_KEY_INFO> fk_list;
- List_iterator<FOREIGN_KEY_INFO> fk_list_it(fk_list);
- FOREIGN_KEY_INFO *fk;
- Query_arena *arena, backup;
TABLE *table= table_list->table;
+ List_iterator<FK_info> fk_list_it(table->s->referenced_keys);
+ FK_info *fk;
+ Query_arena *arena, backup;
arena= thd->activate_stmt_arena_if_needed(&backup);
- table->file->get_parent_foreign_key_list(thd, &fk_list);
- if (unlikely(thd->is_error()))
- {
- if (arena)
- thd->restore_active_arena(arena, &backup);
- return TRUE;
- }
-
- *need_prelocking= TRUE;
-
while ((fk= fk_list_it++))
{
// FK_OPTION_RESTRICT and FK_OPTION_NO_ACTION only need read access
thr_lock_type lock_type;
if ((op & (1 << TRG_EVENT_DELETE) && fk_modifies_child(fk->delete_method))
- || (op & (1 << TRG_EVENT_UPDATE) && fk_modifies_child(fk->update_method)))
+ || (op & (1 << TRG_EVENT_UPDATE) && fk_modifies_child(fk->update_method))
+ || (table->s->table_category == TABLE_CATEGORY_SYSTEM &&
+ table_list->lock_type >= TL_WRITE_ALLOW_WRITE))
lock_type= TL_WRITE_ALLOW_WRITE;
else
lock_type= TL_READ;
if (table_already_fk_prelocked(prelocking_ctx->query_tables,
- fk->foreign_db, fk->foreign_table,
+ &fk->foreign_db, &fk->foreign_table,
lock_type))
continue;
+ *need_prelocking= TRUE;
+
TABLE_LIST *tl= (TABLE_LIST *) thd->alloc(sizeof(TABLE_LIST));
- tl->init_one_table_for_prelocking(fk->foreign_db,
- fk->foreign_table,
+ tl->init_one_table_for_prelocking(&fk->foreign_db,
+ &fk->foreign_table,
NULL, lock_type,
TABLE_LIST::PRELOCK_FK,
table_list->belong_to_view, op,
@@ -4701,7 +4694,7 @@ handle_table(THD *thd, Query_tables_list *prelocking_ctx,
return TRUE;
}
- if (table->file->referenced_by_foreign_key())
+ if (table->s->referenced_by_foreign_key())
{
if (prepare_fk_prelocking_list(thd, prelocking_ctx, table_list,
need_prelocking,
@@ -4710,7 +4703,7 @@ handle_table(THD *thd, Query_tables_list *prelocking_ctx,
}
}
else if (table_list->slave_fk_event_map &&
- table->file->referenced_by_foreign_key())
+ table->s->referenced_by_foreign_key())
{
if (prepare_fk_prelocking_list(thd, prelocking_ctx, table_list,
need_prelocking,
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index 6951045a65e..49116979459 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -171,13 +171,14 @@ bool Key_part_spec::init_multiple_key_for_blob(const handler *file)
*/
Key::Key(const Key &rhs, MEM_ROOT *mem_root)
- :DDL_options(rhs),type(rhs.type),
+ :DDL_options(rhs), type(rhs.type), foreign(rhs.foreign),
key_create_info(rhs.key_create_info),
columns(rhs.columns, mem_root),
name(rhs.name),
option_list(rhs.option_list),
- generated(rhs.generated), invisible(false),
- without_overlaps(rhs.without_overlaps), period(rhs.period)
+ generated(rhs.generated), invisible(rhs.invisible),
+ without_overlaps(rhs.without_overlaps), period(rhs.period),
+ ignore(rhs.ignore)
{
list_copy_and_replace_each_value(columns, mem_root);
}
@@ -202,6 +203,22 @@ Foreign_key::Foreign_key(const Foreign_key &rhs, MEM_ROOT *mem_root)
list_copy_and_replace_each_value(ref_columns, mem_root);
}
+void Foreign_key::init(const LEX_CSTRING& _ref_db, const LEX_CSTRING& _ref_table,
+ const LEX* lex)
+{
+ DBUG_ASSERT(lex);
+ ref_db= _ref_db;
+ ref_table= _ref_table;
+ ref_columns= lex->ref_list;
+ if (ref_columns.is_empty())
+ {
+ ref_columns= columns;
+ }
+ delete_opt= lex->fk_delete_opt;
+ update_opt= lex->fk_update_opt;
+ match_opt= lex->fk_match_option;
+}
+
/*
Test if a foreign key (= generated key) is a prefix of the given key
(ignoring key name, key type and order of columns)
@@ -297,7 +314,7 @@ bool Foreign_key::validate(List<Create_field> &table_fields)
my_error(ER_KEY_COLUMN_DOES_NOT_EXITS, MYF(0), column->field_name.str);
DBUG_RETURN(TRUE);
}
- if (type == Key::FOREIGN_KEY && sql_field->vcol_info)
+ if (sql_field->vcol_info)
{
if (delete_opt == FK_OPTION_SET_NULL)
{
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 2e7772b3c37..77e98c7fbfa 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -51,6 +51,9 @@
#include "backup.h"
#include "xa.h"
#include "ddl_log.h" /* DDL_LOG_STATE */
+#include <vector>
+#include <set>
+#include <map>
extern "C"
void set_thd_stage_info(void *thd,
@@ -281,6 +284,233 @@ typedef struct st_copy_info {
} COPY_INFO;
+namespace mbd
+{
+/* Convert STL exceptions to my_error() */
+template <class Base>
+class exception_wrapper : public Base
+{
+public:
+ /*
+ NB: any methods from different classes can be added here,
+ as templates are instantiated on demand.
+ Both lvalue and rvalue types are covered by perfect forwarding.
+ */
+ template <class T>
+ typename Base::iterator insert(T&& value, bool &inserted) noexcept
+ {
+ try
+ {
+ auto ret= Base::insert(std::forward<T>(value));
+ inserted= ret.second;
+ return ret.first;
+ }
+ catch (std::bad_alloc())
+ {
+ my_error(ER_OUT_OF_RESOURCES, MYF(0));
+ return Base::end();
+ }
+ catch (...)
+ {
+ my_error(ER_INTERNAL_ERROR, MYF(0), "Unexpected exception");
+ return Base::end();
+ }
+ return Base::end();
+ }
+ template <class T>
+ bool push_back(T&& value) noexcept
+ {
+ try
+ {
+ Base::push_back(std::forward<T>(value));
+ }
+ catch (std::bad_alloc())
+ {
+ my_error(ER_OUT_OF_RESOURCES, MYF(0));
+ return true;
+ }
+ catch (...)
+ {
+ my_error(ER_INTERNAL_ERROR, MYF(0), "Unexpected exception");
+ return true;
+ }
+ return false;
+ }
+};
+
+
+/* std::vector adapter for returning true instead of throwing exception */
+
+template <class T, class Allocator = std::allocator<T> >
+class vector :
+ public exception_wrapper<std::vector<T, Allocator> >
+{
+public:
+ bool push_back(const T& value)
+ {
+ return exception_wrapper<std::vector<T, Allocator> >::
+ push_back(value);
+ }
+ bool push_back(T&& value)
+ {
+ return exception_wrapper<std::vector<T, Allocator> >::
+ push_back(std::forward<T>(value));
+ }
+};
+
+
+/* std::set adapter for returning NULL instead of throwing exception */
+
+template <class Key, class Compare = std::less<Key>,
+ class Allocator = std::allocator<Key> >
+class set :
+ public exception_wrapper<std::set<Key, Compare, Allocator> >
+{
+public:
+ const Key* insert(const Key& value, bool *inserted= NULL)
+ {
+ bool ins= false;
+ auto ret= exception_wrapper<std::set<Key, Compare, Allocator> >::
+ insert(value, ins);
+ if (inserted)
+ *inserted= ins;
+ if (ret == std::set<Key, Compare, Allocator>::end())
+ return NULL;
+ return &*ret;
+ }
+ const Key* insert(Key&& value, bool *inserted= NULL)
+ {
+ bool ins= false;
+ auto ret= exception_wrapper<std::set<Key, Compare, Allocator> >::
+ insert(std::forward<Key>(value), ins);
+ if (inserted)
+ *inserted= ins;
+ if (ret == std::set<Key, Compare, Allocator>::end())
+ return NULL;
+ return &*ret;
+ }
+ template <class... Args>
+ const Key* emplace(bool *inserted, Args&&... args)
+ {
+ bool ins= false;
+ auto ret= exception_wrapper<std::set<Key, Compare, Allocator> >::
+ emplace(ins, std::forward<Args>(args)...);
+ if (inserted)
+ *inserted= ins;
+ if (ret == std::set<Key, Compare, Allocator>::end())
+ return NULL;
+ return &*ret;
+ }
+};
+
+
+/* std::map adapter for returning NULL instead of throwing exception */
+
+template<class Key, class T, class Compare = std::less<Key>,
+ class Allocator = std::allocator<std::pair<const Key, T> > >
+class map :
+ public exception_wrapper<std::map<Key, T, Compare, Allocator> >
+{
+public:
+ T* insert(const Key& key, const T& value, bool *inserted= NULL)
+ {
+ bool ins;
+ auto ret= exception_wrapper<std::map<Key, T, Compare, Allocator> >::
+ insert(std::make_pair(key, value), ins);
+ if (inserted)
+ *inserted= ins;
+ return &ret->second;
+ }
+ T* insert(const Key& key, T&& value, bool *inserted= NULL)
+ {
+ bool ins;
+ auto ret= exception_wrapper<std::map<Key, T, Compare, Allocator> >::
+ insert(std::make_pair(key, std::forward<T>(value)), ins);
+ if (inserted)
+ *inserted= ins;
+ return &ret->second;
+ }
+};
+} // namespace mbd
+
+
+/*
+ TODO: Table_ident is parser-oriented class that contains SELECT_LEX_UNIT and
+ depends on sql_lex.h, so it can't be declared in this place and is not declared
+ in many headers. Table_ident should be derived from Table_name.
+ Classes containing (db, table_name) pairs such as TABLE_LIST, TABLE_SHARE, etc.
+ should be reworked to contain Table_name instead.
+*/
+class Table_name
+{
+public:
+ // TODO: use Lex_table_name
+ Lex_cstring db;
+ Lex_cstring name;
+ Table_name() {}
+ Table_name(Lex_cstring _db, Lex_cstring _name)
+ : db(_db), name(_name) {}
+ int cmp(const Table_name &rhs) const
+ {
+ if (db.length < rhs.db.length)
+ return -1;
+ if (db.length > rhs.db.length)
+ return 1;
+ if (db.str != rhs.db.str)
+ {
+ int db_cmp= cmp_table(db, rhs.db);
+ if (db_cmp)
+ return db_cmp;
+ }
+ if (name.length < rhs.name.length)
+ return -1;
+ if (name.length > rhs.name.length)
+ return 1;
+ if (name.str != rhs.name.str)
+ return cmp_table(name, rhs.name);
+ return 0;
+ }
+ bool lowercase(MEM_ROOT *mem_root)
+ {
+ if (db.length)
+ {
+ db.str= (const char *) memdup_root(mem_root, db.str, db.length + 1);
+ if (unlikely(!db.str))
+ return true;
+ my_casedn_str(system_charset_info, (char *)db.str);
+ }
+ if (name.length)
+ {
+ name.str= (const char *) memdup_root(mem_root, name.str, name.length + 1);
+ if (unlikely(!name.str))
+ return true;
+ my_casedn_str(system_charset_info, (char *)name.str);
+ }
+ return false;
+ }
+ // NB: needed for std::set
+ bool operator<(const Table_name &rhs) const
+ {
+ return cmp(rhs) < 0;
+ }
+};
+
+/*
+ NB: needed for std::set when we have recommendation to not have operator
+ overloading in important classes.
+*/
+struct Table_name_lt
+{
+ bool operator() (const Table_name &lhs, const Table_name &rhs) const
+ {
+ return lhs.cmp(rhs) < 0;
+ }
+};
+
+typedef mbd::set<Lex_cstring, Lex_ident_lt> Lex_ident_set;
+
+
+
class Key_part_spec :public Sql_alloc {
public:
LEX_CSTRING field_name;
@@ -309,7 +539,7 @@ public:
}
bool check_foreign_key_for_blob(const class handler *file) const
{
- return check_key_for_blob(file) || check_key_length_for_blob();
+ return check_key_for_blob(file);
}
bool init_multiple_key_for_blob(const class handler *file);
};
@@ -384,8 +614,9 @@ public:
class Key :public Sql_alloc, public DDL_options {
public:
- enum Keytype { PRIMARY, UNIQUE, MULTIPLE, FULLTEXT, SPATIAL, FOREIGN_KEY};
+ enum Keytype { PRIMARY, UNIQUE, MULTIPLE, FULLTEXT, SPATIAL };
enum Keytype type;
+ bool foreign;
KEY_CREATE_INFO key_create_info;
List<Key_part_spec> columns;
LEX_CSTRING name;
@@ -394,13 +625,14 @@ public:
bool invisible;
bool without_overlaps;
Lex_ident period;
+ bool ignore;
Key(enum Keytype type_par, const LEX_CSTRING *name_arg,
ha_key_alg algorithm_arg, bool generated_arg, DDL_options_st ddl_options)
:DDL_options(ddl_options),
- type(type_par), key_create_info(default_key_create_info),
+ type(type_par), foreign(false), 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), ignore(false)
{
key_create_info.algorithm= algorithm_arg;
}
@@ -409,9 +641,9 @@ public:
bool generated_arg, List<Key_part_spec> *cols,
engine_option_value *create_opt, DDL_options_st ddl_options)
:DDL_options(ddl_options),
- type(type_par), key_create_info(*key_info_arg), columns(*cols),
+ type(type_par), foreign(false), 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), ignore(false)
{}
Key(const Key &rhs, MEM_ROOT *mem_root);
virtual ~Key() {}
@@ -436,24 +668,46 @@ public:
List<Key_part_spec> ref_columns;
enum enum_fk_option delete_opt, update_opt;
enum fk_match_opt match_opt;
- Foreign_key(const LEX_CSTRING *name_arg, List<Key_part_spec> *cols,
+ Foreign_key(const LEX_CSTRING *name_arg,
const LEX_CSTRING *constraint_name_arg,
- const LEX_CSTRING *ref_db_arg, const LEX_CSTRING *ref_table_arg,
- List<Key_part_spec> *ref_cols,
- enum_fk_option delete_opt_arg, enum_fk_option update_opt_arg,
- fk_match_opt match_opt_arg,
- DDL_options ddl_options)
- :Key(FOREIGN_KEY, name_arg, &default_key_create_info, 0, cols, NULL,
- ddl_options),
- constraint_name(*constraint_name_arg),
- 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);
+ DDL_options ddl_options)
+ : Key(MULTIPLE, name_arg, default_key_create_info.algorithm, true,
+ ddl_options), constraint_name(*constraint_name_arg)
+ {
+ foreign= true;
+ }
+ Foreign_key(const FK_info &src, MEM_ROOT *mem_root)
+ : Key(MULTIPLE, &src.foreign_id, default_key_create_info.algorithm, true,
+ DDL_options()),
+ constraint_name(src.foreign_id),
+ ref_db(src.referenced_db),
+ ref_table(src.referenced_table),
+ delete_opt(src.delete_method),
+ update_opt(src.update_method)
+ {
+ for (const Lex_cstring &src_f: src.foreign_fields)
+ {
+ Key_part_spec *kp= new (mem_root) Key_part_spec(&src_f, 0);
+ if (!kp || columns.push_back(kp, mem_root))
+ return;
+ }
+
+ for (const Lex_cstring &src_f: src.referenced_fields)
+ {
+ Key_part_spec *kp= new (mem_root) Key_part_spec(&src_f, 0);
+ if (!kp || ref_columns.push_back(kp, mem_root))
+ return;
+ }
+
+ foreign= true; // false means failed initialization
+ }
+ bool failed() const
+ {
+ return !foreign;
+ }
+ void init(const LEX_CSTRING &_ref_db, const LEX_CSTRING &_ref_table,
+ const LEX *lex);
+ Foreign_key(const Foreign_key &rhs, MEM_ROOT *mem_root);
/**
Used to make a clone of this object for ALTER/CREATE TABLE
@sa comment for Key_part_spec::clone
@@ -634,6 +888,10 @@ typedef struct system_variables
sql_mode_t sql_mode; ///< which non-standard SQL behaviour should be enabled
sql_mode_t old_behavior; ///< which old SQL behaviour should be enabled
ulonglong option_bits; ///< OPTION_xxx constants, e.g. OPTION_PROFILING
+ bool check_foreign()
+ {
+ return !((bool)(option_bits & OPTION_NO_FOREIGN_KEY_CHECKS));
+ }
ulonglong join_buff_space_limit;
ulonglong log_slow_filter;
ulonglong log_slow_verbosity;
@@ -1200,6 +1458,22 @@ public:
};
+class Mutex_lock
+{
+ mysql_mutex_t *mutex;
+
+public:
+ Mutex_lock(mysql_mutex_t *_mutex): mutex(_mutex)
+ {
+ mysql_mutex_lock(mutex);
+ }
+ ~Mutex_lock()
+ {
+ mysql_mutex_unlock(mutex);
+ }
+};
+
+
class Server_side_cursor;
/*
@@ -5249,6 +5523,8 @@ public:
Item *sp_prepare_func_item(Item **it_addr, uint cols= 1);
bool sp_eval_expr(Field *result_field, Item **expr_item_ptr);
+ List<TABLE_SHARE> fk_circular_check;
+
};
@@ -6567,13 +6843,14 @@ typedef struct st_sort_buffer {
SORT_FIELD *sortorder;
} SORT_BUFFER;
+
/* Structure for db & table in sql_yacc */
class Table_ident :public Sql_alloc
{
public:
- LEX_CSTRING db;
- LEX_CSTRING table;
+ Lex_cstring db;
+ Lex_cstring table;
SELECT_LEX_UNIT *sel;
inline Table_ident(THD *thd, const LEX_CSTRING *db_arg,
const LEX_CSTRING *table_arg,
@@ -6604,6 +6881,11 @@ public:
table.str= internal_table_name;
table.length=1;
}
+ Table_ident(LEX_CSTRING &db_arg, LEX_CSTRING &table_arg)
+ :db(db_arg), table(table_arg)
+ {}
+ Table_ident()
+ {}
bool is_derived_table() const { return MY_TEST(sel); }
inline void change_db(LEX_CSTRING *db_name)
{
@@ -6611,6 +6893,24 @@ public:
}
bool resolve_table_rowtype_ref(THD *thd, Row_definition_list &defs);
bool append_to(THD *thd, String *to) const;
+ bool lowercase(MEM_ROOT *mem_root)
+ {
+ if (db.length)
+ {
+ db.str= (const char *) memdup_root(mem_root, db.str, db.length + 1);
+ if (unlikely(!db.str))
+ return true;
+ my_casedn_str(system_charset_info, (char *)db.str);
+ }
+ if (table.length)
+ {
+ table.str= (const char *) memdup_root(mem_root, table.str, table.length + 1);
+ if (unlikely(!table.str))
+ return true;
+ my_casedn_str(system_charset_info, (char *)table.str);
+ }
+ return false;
+ }
};
diff --git a/sql/sql_db.cc b/sql/sql_db.cc
index 278ec83fa41..f6b196f7ddc 100644
--- a/sql/sql_db.cc
+++ b/sql/sql_db.cc
@@ -1107,7 +1107,7 @@ mysql_rm_db_internal(THD *thd, const LEX_CSTRING *db, bool if_exists,
if (!thd->killed &&
!(tables &&
mysql_rm_table_no_locks(thd, tables, &rm_db, &ddl_log_state, true, false,
- true, false, true, false)))
+ true, false, true, true, false)))
{
debug_crash_here("ddl_log_drop_after_drop_tables");
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index c1806df2a75..174ac763810 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -2019,7 +2019,7 @@ int write_record(THD *thd, TABLE *table, COPY_INFO *info, select_result *sink)
ON UPDATE triggers.
*/
if (last_uniq_key(table,key_nr) &&
- !table->file->referenced_by_foreign_key() &&
+ !table->s->referenced_by_foreign_key() &&
(!table->triggers || !table->triggers->has_delete_triggers()))
{
if (table->versioned(VERS_TRX_ID))
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index 1e7f3c3ef4d..a787f371b4f 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -11403,29 +11403,16 @@ sp_condition_value *LEX::stmt_signal_value(const Lex_ident_sys_st &ident)
}
-bool LEX::add_table_foreign_key(const LEX_CSTRING *name,
- const LEX_CSTRING *constraint_name,
- Table_ident *ref_table_name,
+bool LEX::add_table_foreign_key(const LEX_CSTRING &name,
+ const LEX_CSTRING &constraint_name,
DDL_options ddl_options)
{
- Key *key= new (thd->mem_root) Foreign_key(name,
- &last_key->columns,
- constraint_name,
- &ref_table_name->db,
- &ref_table_name->table,
- &ref_list,
- fk_delete_opt,
- fk_update_opt,
- fk_match_option,
+ last_key= new (thd->mem_root) Foreign_key(&name,
+ &constraint_name,
ddl_options);
- if (unlikely(key == NULL))
+ if (unlikely(last_key == NULL))
return true;
- /*
- handle_if_exists_options() expects the two keys in this order:
- the Foreign_key, followed by its auto-generated Key.
- */
- alter_info.key_list.push_back(key, thd->mem_root);
alter_info.key_list.push_back(last_key, thd->mem_root);
option_list= NULL;
@@ -11437,9 +11424,9 @@ bool LEX::add_table_foreign_key(const LEX_CSTRING *name,
}
-bool LEX::add_column_foreign_key(const LEX_CSTRING *name,
- const LEX_CSTRING *constraint_name,
- Table_ident *ref_table_name,
+bool LEX::add_column_foreign_key(const LEX_CSTRING &field_name,
+ const LEX_CSTRING &constraint_name,
+ Table_ident &ref_table_name,
DDL_options ddl_options)
{
if (last_field->vcol_info || last_field->vers_sys_field())
@@ -11447,26 +11434,19 @@ bool LEX::add_column_foreign_key(const LEX_CSTRING *name,
thd->parse_error();
return true;
}
- if (unlikely(!(last_key= (new (thd->mem_root)
- Key(Key::MULTIPLE, constraint_name,
- HA_KEY_ALG_UNDEF, true, ddl_options)))))
- return true;
- Key_part_spec *key= new (thd->mem_root) Key_part_spec(name, 0);
- if (unlikely(key == NULL))
- return true;
- last_key->columns.push_back(key, thd->mem_root);
- if (ref_list.is_empty())
- {
- ref_list.push_back(key, thd->mem_root);
- }
+ /* TODO: we are not supplying field_name here like that
+ add_table_foreign_key(constraint_name.str ? constraint_name : field_name,
+ but we will after MDEV-21052 */
if (unlikely(add_table_foreign_key(constraint_name, constraint_name,
- ref_table_name, ddl_options)))
+ ddl_options)))
return true;
- option_list= NULL;
-
- /* Only used for ALTER TABLE. Ignored otherwise. */
- alter_info.flags|= ALTER_ADD_FOREIGN_KEY;
-
+ DBUG_ASSERT(field_name.str);
+ Key_part_spec *key= new (thd->mem_root) Key_part_spec(&field_name, 0);
+ if (unlikely(key == NULL))
+ return true;
+ last_key->columns.push_back(key);
+ Foreign_key &fk= static_cast<Foreign_key &>(*last_key);
+ fk.init(ref_table_name.db, ref_table_name.table, this);
return false;
}
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index 30ad1df9a08..76a81f256c8 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -4703,13 +4703,12 @@ public:
select_stack[0]->is_service_select);
}
- bool add_table_foreign_key(const LEX_CSTRING *name,
- const LEX_CSTRING *constraint_name,
- Table_ident *table_name,
+ bool add_table_foreign_key(const LEX_CSTRING &name,
+ const LEX_CSTRING &constraint_name,
DDL_options ddl_options);
- bool add_column_foreign_key(const LEX_CSTRING *name,
- const LEX_CSTRING *constraint_name,
- Table_ident *ref_table_name,
+ bool add_column_foreign_key(const LEX_CSTRING &name,
+ const LEX_CSTRING &constraint_name,
+ Table_ident &ref_table_name,
DDL_options ddl_options);
};
diff --git a/sql/sql_list.h b/sql/sql_list.h
index 91134bcbeb2..77bdef55c57 100644
--- a/sql/sql_list.h
+++ b/sql/sql_list.h
@@ -299,7 +299,7 @@ public:
inline list_node* first_node() { return first;}
inline void *head() { return first->info; }
inline void **head_ref() { return first != &end_of_list ? &first->info : 0; }
- inline bool is_empty() { return first == &end_of_list ; }
+ inline bool is_empty() const { return first == &end_of_list ; }
inline list_node *last_ref() { return &end_of_list; }
inline bool add_unique(void *info, List_eq *eq)
{
@@ -740,7 +740,7 @@ class base_ilist
public:
inline void empty() { first= &last; last.prev= &first; }
base_ilist() { empty(); }
- inline bool is_empty() { return first == &last; }
+ inline bool is_empty() const { return first == &last; }
// Returns true if p is the last "real" object in the list,
// i.e. p->next points to the sentinel.
inline bool is_last(ilink *p) { return p->next == NULL || p->next == &last; }
@@ -821,7 +821,7 @@ public:
I_List() :base_ilist() {}
inline bool is_last(T *p) { return base_ilist::is_last(p); }
inline void empty() { base_ilist::empty(); }
- inline bool is_empty() { return base_ilist::is_empty(); }
+ inline bool is_empty() const { return base_ilist::is_empty(); }
inline void append(T* a) { base_ilist::append(a); }
inline void push_back(T* a) { base_ilist::push_back(a); }
inline T* get() { return (T*) base_ilist::get(); }
@@ -859,14 +859,20 @@ public:
template <typename T>
inline
-void
+bool
list_copy_and_replace_each_value(List<T> &list, MEM_ROOT *mem_root)
{
/* Make a deep copy of each element */
List_iterator<T> it(list);
T *el;
while ((el= it++))
- it.replace(el->clone(mem_root));
+ {
+ T *el2= el->clone(mem_root);
+ if (!el2)
+ return true;
+ it.replace(el2);
+ }
+ return false;
}
void free_list(I_List <i_string_pair> *list);
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 821949c55ca..60f2ee4ed75 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -7182,7 +7182,7 @@ bool check_fk_parent_table_access(THD *thd,
while ((key= key_iterator++))
{
- if (key->type == Key::FOREIGN_KEY)
+ if (key->foreign)
{
TABLE_LIST parent_table;
bool is_qualified_table_name;
diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc
index 672859405e0..98767f76d78 100644
--- a/sql/sql_partition.cc
+++ b/sql/sql_partition.cc
@@ -6470,7 +6470,8 @@ static bool write_log_drop_shadow_frm(ALTER_PARTITION_PARAM_TYPE *lpt)
char shadow_path[FN_REFLEN + 1];
DBUG_ENTER("write_log_drop_shadow_frm");
- build_table_shadow_filename(shadow_path, sizeof(shadow_path) - 1, lpt);
+ build_table_shadow_filename(shadow_path, sizeof(shadow_path) - 1,
+ lpt->db, lpt->table_name);
mysql_mutex_lock(&LOCK_gdl);
if (write_log_replace_delete_frm(lpt, 0UL, NULL,
(const char*)shadow_path, FALSE))
@@ -6517,7 +6518,8 @@ static bool write_log_rename_frm(ALTER_PARTITION_PARAM_TYPE *lpt)
part_info->first_log_entry= NULL;
build_table_filename(path, sizeof(path) - 1, lpt->db.str, lpt->table_name.str, "", 0);
- build_table_shadow_filename(shadow_path, sizeof(shadow_path) - 1, lpt);
+ build_table_shadow_filename(shadow_path, sizeof(shadow_path) - 1,
+ lpt->db, lpt->table_name);
mysql_mutex_lock(&LOCK_gdl);
if (write_log_replace_delete_frm(lpt, 0UL, shadow_path, path, TRUE))
goto error;
@@ -6568,7 +6570,8 @@ static bool write_log_drop_partition(ALTER_PARTITION_PARAM_TYPE *lpt)
part_info->first_log_entry= NULL;
build_table_filename(path, sizeof(path) - 1, lpt->db.str, lpt->table_name.str, "", 0);
- build_table_shadow_filename(tmp_path, sizeof(tmp_path) - 1, lpt);
+ build_table_shadow_filename(tmp_path, sizeof(tmp_path) - 1,
+ lpt->db, lpt->table_name);
mysql_mutex_lock(&LOCK_gdl);
if (write_log_dropped_partitions(lpt, &next_entry, (const char*)path,
FALSE))
@@ -6626,7 +6629,8 @@ static bool write_log_add_change_partition(ALTER_PARTITION_PARAM_TYPE *lpt)
DBUG_ENTER("write_log_add_change_partition");
build_table_filename(path, sizeof(path) - 1, lpt->db.str, lpt->table_name.str, "", 0);
- build_table_shadow_filename(tmp_path, sizeof(tmp_path) - 1, lpt);
+ build_table_shadow_filename(tmp_path, sizeof(tmp_path) - 1,
+ lpt->db, lpt->table_name);
mysql_mutex_lock(&LOCK_gdl);
/* Relink the previous drop shadow frm entry */
@@ -6693,7 +6697,8 @@ static bool write_log_final_change_partition(ALTER_PARTITION_PARAM_TYPE *lpt)
*/
part_info->first_log_entry= NULL;
build_table_filename(path, sizeof(path) - 1, lpt->db.str, lpt->table_name.str, "", 0);
- build_table_shadow_filename(shadow_path, sizeof(shadow_path) - 1, lpt);
+ build_table_shadow_filename(shadow_path, sizeof(shadow_path) - 1,
+ lpt->db, lpt->table_name);
mysql_mutex_lock(&LOCK_gdl);
if (write_log_changed_partitions(lpt, &next_entry, (const char*)path))
goto error;
@@ -6734,28 +6739,28 @@ error:
FALSE Success
*/
-static void write_log_completed(ALTER_PARTITION_PARAM_TYPE *lpt,
- bool dont_crash)
+static void write_log_completed(ALTER_PARTITION_PARAM_TYPE *lpt)
{
partition_info *part_info= lpt->part_info;
- DDL_LOG_MEMORY_ENTRY *log_entry= part_info->exec_log_entry;
+ DDL_LOG_MEMORY_ENTRY *exec_log_entry= part_info->exec_log_entry;
DBUG_ENTER("write_log_completed");
- DBUG_ASSERT(log_entry);
+ DBUG_ASSERT(exec_log_entry);
mysql_mutex_lock(&LOCK_gdl);
- if (ddl_log_disable_execute_entry(&log_entry))
+ bool error= ddl_log_disable_execute_entry(&exec_log_entry);
+ /*
+ If error == true we failed to write, Bad...
+ We have completed the operation but have log records to REMOVE
+ stuff that shouldn't be removed. What clever things could one do
+ here? An error output was written to the error output by the
+ above method so we don't do anything here.
+ */
+ release_part_info_log_entries(part_info->first_log_entry);
+ if (!error)
{
- /*
- Failed to write, Bad...
- We have completed the operation but have log records to REMOVE
- stuff that shouldn't be removed. What clever things could one do
- here? An error output was written to the error output by the
- above method so we don't do anything here.
- */
- ;
+ DBUG_ASSERT(!exec_log_entry->next_active_log_entry);
+ ddl_log_release_memory_entry(exec_log_entry);
}
- release_part_info_log_entries(part_info->first_log_entry);
- release_part_info_log_entries(part_info->exec_log_entry);
mysql_mutex_unlock(&LOCK_gdl);
part_info->exec_log_entry= NULL;
part_info->first_log_entry= NULL;
@@ -6899,8 +6904,7 @@ static void handle_alter_part_error(ALTER_PARTITION_PARAM_TYPE *lpt,
We couldn't recover from error, most likely manual interaction
is required.
*/
- write_log_completed(lpt, FALSE);
- release_log_entries(part_info);
+ write_log_completed(lpt);
if (!action_completed)
{
if (drop_partition)
@@ -7229,7 +7233,7 @@ uint fast_alter_partition_table(THD *thd, TABLE *table,
mysql_drop_partitions(lpt) ||
ERROR_INJECT_CRASH("crash_drop_partition_8") ||
ERROR_INJECT_ERROR("fail_drop_partition_8") ||
- (write_log_completed(lpt, FALSE), FALSE) ||
+ (write_log_completed(lpt), FALSE) ||
ERROR_INJECT_CRASH("crash_drop_partition_9") ||
ERROR_INJECT_ERROR("fail_drop_partition_9"))
{
@@ -7304,7 +7308,7 @@ uint fast_alter_partition_table(THD *thd, TABLE *table,
(frm_install= FALSE, FALSE) ||
ERROR_INJECT_CRASH("crash_add_partition_9") ||
ERROR_INJECT_ERROR("fail_add_partition_9") ||
- (write_log_completed(lpt, FALSE), FALSE) ||
+ (write_log_completed(lpt), FALSE) ||
ERROR_INJECT_CRASH("crash_add_partition_10") ||
ERROR_INJECT_ERROR("fail_add_partition_10"))
{
@@ -7407,7 +7411,7 @@ uint fast_alter_partition_table(THD *thd, TABLE *table,
mysql_rename_partitions(lpt) ||
ERROR_INJECT_CRASH("crash_change_partition_11") ||
ERROR_INJECT_ERROR("fail_change_partition_11") ||
- (write_log_completed(lpt, FALSE), FALSE) ||
+ (write_log_completed(lpt), FALSE) ||
ERROR_INJECT_CRASH("crash_change_partition_12") ||
ERROR_INJECT_ERROR("fail_change_partition_12"))
{
diff --git a/sql/sql_rename.cc b/sql/sql_rename.cc
index 316cd2c9ca7..07d2bcce1fe 100644
--- a/sql/sql_rename.cc
+++ b/sql/sql_rename.cc
@@ -43,7 +43,8 @@ struct TABLE_PAIR
static bool rename_tables(THD *thd, TABLE_LIST *table_list,
DDL_LOG_STATE *ddl_log_state,
bool skip_error, bool if_exits,
- bool *force_if_exists);
+ bool *force_if_exists,
+ FK_rename_vector &fk_rename_backup);
/*
Every two entries in the table_list form a pair of original name and
@@ -59,6 +60,7 @@ bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list, bool silent,
int to_table;
const char *rename_log_table[2]= {NULL, NULL};
DDL_LOG_STATE ddl_log_state;
+ FK_rename_vector fk_rename_backup;
DBUG_ENTER("mysql_rename_tables");
/*
@@ -162,7 +164,7 @@ bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list, bool silent,
no other thread accesses this table.
*/
error= rename_tables(thd, table_list, &ddl_log_state,
- 0, if_exists, &force_if_exists);
+ 0, if_exists, &force_if_exists, fk_rename_backup);
if (likely(!silent && !error))
{
@@ -193,6 +195,16 @@ bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list, bool silent,
if (likely(!error))
{
+ for (FK_rename_backup &bak: fk_rename_backup)
+ {
+ error= fk_install_shadow_frm(bak.old_name, bak.new_name);
+ if (error)
+ break;
+ }
+ }
+
+ if (likely(!error))
+ {
query_cache_invalidate3(thd, table_list, 0);
ddl_log_complete(&ddl_log_state);
}
@@ -200,6 +212,8 @@ bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list, bool silent,
{
/* Revert the renames of normal tables with the help of the ddl log */
ddl_log_revert(thd, &ddl_log_state);
+ for (FK_rename_backup &bak: fk_rename_backup)
+ bak.rollback();
}
err:
@@ -331,7 +345,8 @@ do_rename(THD *thd, rename_param *param, DDL_LOG_STATE *ddl_log_state,
TABLE_LIST *ren_table, const LEX_CSTRING *new_db,
const LEX_CSTRING *new_table_name,
const LEX_CSTRING *new_table_alias,
- bool skip_error, bool if_exists, bool *force_if_exists)
+ bool skip_error, bool if_exists, bool *force_if_exists,
+ FK_rename_vector &fk_rename_backup)
{
int rc= 1;
handlerton *hton;
@@ -359,6 +374,16 @@ do_rename(THD *thd, rename_param *param, DDL_LOG_STATE *ddl_log_state,
if (hton->flags & HTON_TABLE_MAY_NOT_EXIST_ON_SLAVE)
*force_if_exists= 1;
+ /*
+ NB: we cannot do fk_handle_rename() before rename_tables() because of
+
+ rename table t3 to t4, t2 to t3, t1 to t2, t4 to t1;
+ */
+ if (!skip_error &&
+ fk_handle_rename(thd, ren_table, new_db, new_table_name, fk_rename_backup))
+ DBUG_RETURN(1);
+
+
thd->replication_flags= 0;
if (ddl_log_rename_table(thd, ddl_log_state, hton,
@@ -472,7 +497,8 @@ do_rename(THD *thd, rename_param *param, DDL_LOG_STATE *ddl_log_state,
static bool
rename_tables(THD *thd, TABLE_LIST *table_list, DDL_LOG_STATE *ddl_log_state,
- bool skip_error, bool if_exists, bool *force_if_exists)
+ bool skip_error, bool if_exists, bool *force_if_exists,
+ FK_rename_vector &fk_rename_backup)
{
TABLE_LIST *ren_table, *new_table;
List<TABLE_PAIR> tmp_tables;
@@ -516,7 +542,7 @@ rename_tables(THD *thd, TABLE_LIST *table_list, DDL_LOG_STATE *ddl_log_state,
if (do_rename(thd, &param, ddl_log_state,
ren_table,
&new_table->db, &new_table->table_name, &new_table->alias,
- skip_error, if_exists, force_if_exists))
+ skip_error, if_exists, force_if_exists, fk_rename_backup))
goto revert_rename;
}
}
@@ -530,3 +556,10 @@ revert_rename:
DBUG_RETURN(1);
}
+
+
+FK_rename_backup::FK_rename_backup(Share_acquire&& _sa) :
+ FK_ddl_backup(std::forward<Share_acquire>(_sa)),
+ old_name(sa.share->db, sa.share->table_name),
+ new_name(sa.share->db, sa.share->table_name)
+{}
diff --git a/sql/sql_rename.h b/sql/sql_rename.h
index 1f5f94b0f5c..efae44a4300 100644
--- a/sql/sql_rename.h
+++ b/sql/sql_rename.h
@@ -16,9 +16,46 @@
#ifndef SQL_RENAME_INCLUDED
#define SQL_RENAME_INCLUDED
+#include "sql_class.h"
+#include "table_cache.h"
+
class THD;
struct TABLE_LIST;
+// NB: FK_ddl_backup responds for share release unlike FK_alter_backup
+class FK_ddl_backup
+{
+public:
+ Share_acquire sa;
+ FK_list foreign_keys;
+ FK_list referenced_keys;
+
+ FK_ddl_backup() {}
+ FK_ddl_backup(Share_acquire&& _sa);
+ FK_ddl_backup(const FK_ddl_backup&)= delete;
+ FK_ddl_backup(FK_ddl_backup&& src) :
+ sa(std::move(src.sa)),
+ foreign_keys(src.foreign_keys),
+ referenced_keys(src.referenced_keys)
+ {}
+
+ void rollback();
+};
+
+class FK_rename_backup : public FK_ddl_backup
+{
+public:
+ FK_rename_backup(Share_acquire&& _sa);
+ FK_rename_backup(Table_name _old_name, Table_name _new_name) :
+ old_name(_old_name), new_name(_new_name) {}
+ Table_name old_name;
+ Table_name new_name;
+ void rollback();
+};
+
+class FK_create_vector: public mbd::vector<FK_ddl_backup> {};
+class FK_rename_vector: public mbd::vector<FK_rename_backup> {};
+
bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list, bool silent,
bool if_exists);
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index 2e1f8ea0768..4de99645eca 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -2007,6 +2007,85 @@ static void append_period(THD *thd, String *packet, const LEX_CSTRING &start,
packet->append(STRING_WITH_LEN(")"));
}
+
+static
+void fk_append_info(THD *thd, String *p, TABLE *table)
+{
+ for (const FK_info &fk: table->s->foreign_keys)
+ {
+ p->append(STRING_WITH_LEN(",\n CONSTRAINT "));
+ append_identifier(thd, p, &fk.foreign_id);
+ p->append(STRING_WITH_LEN(" FOREIGN KEY ("));
+ bool comma= false;
+ for (const Lex_cstring &fcol: fk.foreign_fields)
+ {
+ if (comma)
+ p->append(STRING_WITH_LEN(", "));
+ else
+ comma= true;
+ append_identifier(thd, p, &fcol);
+ }
+ p->append(STRING_WITH_LEN(") REFERENCES "));
+ if (fk.referenced_db.str && 0 != cmp_table(table->s->db, fk.referenced_db))
+ {
+ append_identifier(thd, p, &fk.referenced_db);
+ p->append('.');
+ }
+ append_identifier(thd, p, &fk.referenced_table);
+ p->append(STRING_WITH_LEN(" ("));
+ comma= false;
+ for (const Lex_cstring &rcol: fk.referenced_fields)
+ {
+ if (comma)
+ p->append(STRING_WITH_LEN(", "));
+ else
+ comma= true;
+ append_identifier(thd, p, &rcol);
+ }
+ p->append(')');
+
+ switch (fk.delete_method)
+ {
+ case FK_OPTION_CASCADE:
+ p->append(STRING_WITH_LEN(" ON DELETE CASCADE"));
+ break;
+ case FK_OPTION_NO_ACTION:
+ p->append(STRING_WITH_LEN(" ON DELETE NO ACTION"));
+ break;
+ case FK_OPTION_RESTRICT:
+ p->append(STRING_WITH_LEN(" ON DELETE RESTRICT"));
+ break;
+ case FK_OPTION_SET_DEFAULT:
+ p->append(STRING_WITH_LEN(" ON DELETE SET DEFAULT"));
+ break;
+ case FK_OPTION_SET_NULL:
+ p->append(STRING_WITH_LEN(" ON DELETE SET NULL"));
+ break;
+ default:;
+ }
+
+ switch (fk.update_method)
+ {
+ case FK_OPTION_CASCADE:
+ p->append(STRING_WITH_LEN(" ON UPDATE CASCADE"));
+ break;
+ case FK_OPTION_NO_ACTION:
+ p->append(STRING_WITH_LEN(" ON UPDATE NO ACTION"));
+ break;
+ case FK_OPTION_RESTRICT:
+ p->append(STRING_WITH_LEN(" ON UPDATE RESTRICT"));
+ break;
+ case FK_OPTION_SET_DEFAULT:
+ p->append(STRING_WITH_LEN(" ON UPDATE SET DEFAULT"));
+ break;
+ case FK_OPTION_SET_NULL:
+ p->append(STRING_WITH_LEN(" ON UPDATE SET NULL"));
+ break;
+ default:;
+ }
+ }
+}
+
int show_create_table(THD *thd, TABLE_LIST *table_list, String *packet,
Table_specification_st *create_info_arg,
enum_with_db_name with_db_name)
@@ -2051,7 +2130,7 @@ int show_create_table_ex(THD *thd, TABLE_LIST *table_list,
enum_with_db_name with_db_name)
{
List<Item> field_list;
- char tmp[MAX_FIELD_WIDTH], *for_str, def_value_buf[MAX_FIELD_WIDTH];
+ char tmp[MAX_FIELD_WIDTH], def_value_buf[MAX_FIELD_WIDTH];
LEX_CSTRING alias;
String type;
String def_value;
@@ -2392,16 +2471,7 @@ int show_create_table_ex(THD *thd, TABLE_LIST *table_list,
}
}
- /*
- Get possible foreign key definitions stored in InnoDB and append them
- to the CREATE TABLE statement
- */
-
- if ((for_str= table->file->get_foreign_key_create_info()))
- {
- packet->append(for_str, strlen(for_str));
- table->file->free_foreign_key_create_info(for_str);
- }
+ fk_append_info(thd, packet, table);
/* Add table level check constraints */
if (share->table_check_constraints)
@@ -6965,7 +7035,6 @@ static int get_schema_constraints_record(THD *thd, TABLE_LIST *tables,
}
else if (!tables->view)
{
- List<FOREIGN_KEY_INFO> f_key_list;
TABLE *show_table= tables->table;
KEY *key_info=show_table->s->key_info;
uint primary_key= show_table->s->primary_key;
@@ -7006,14 +7075,11 @@ static int get_schema_constraints_record(THD *thd, TABLE_LIST *tables,
}
}
- show_table->file->get_foreign_key_list(thd, &f_key_list);
- FOREIGN_KEY_INFO *f_key_info;
- List_iterator_fast<FOREIGN_KEY_INFO> it(f_key_list);
- while ((f_key_info=it++))
+ for (const FK_info &fk: show_table->s->foreign_keys)
{
if (store_constraints(thd, table, db_name, table_name,
- f_key_info->foreign_id->str,
- strlen(f_key_info->foreign_id->str),
+ fk.foreign_id.str,
+ strlen(fk.foreign_id.str),
"FOREIGN KEY", 11))
DBUG_RETURN(1);
}
@@ -7160,7 +7226,6 @@ static int get_schema_key_column_usage_record(THD *thd,
}
else if (!tables->view)
{
- List<FOREIGN_KEY_INFO> f_key_list;
TABLE *show_table= tables->table;
KEY *key_info=show_table->s->key_info;
uint primary_key= show_table->s->primary_key;
@@ -7190,37 +7255,32 @@ static int get_schema_key_column_usage_record(THD *thd,
}
}
- show_table->file->get_foreign_key_list(thd, &f_key_list);
- FOREIGN_KEY_INFO *f_key_info;
- List_iterator_fast<FOREIGN_KEY_INFO> fkey_it(f_key_list);
- while ((f_key_info= fkey_it++))
+ for (FK_info &fk: show_table->s->foreign_keys)
{
- LEX_CSTRING *f_info;
- LEX_CSTRING *r_info;
- List_iterator_fast<LEX_CSTRING> it(f_key_info->foreign_fields),
- it1(f_key_info->referenced_fields);
+ List_iterator_fast<Lex_cstring> rf_it(fk.referenced_fields);
uint f_idx= 0;
- while ((f_info= it++))
+ DBUG_ASSERT(fk.foreign_fields.elements == fk.referenced_fields.elements);
+ for (const Lex_cstring &ff: fk.foreign_fields)
{
- r_info= it1++;
+ const Lex_cstring &rf= *(rf_it++);
f_idx++;
restore_record(table, s->default_values);
store_key_column_usage(table, db_name, table_name,
- f_key_info->foreign_id->str,
- f_key_info->foreign_id->length,
- f_info->str, f_info->length,
- (longlong) f_idx);
- table->field[8]->store((longlong) f_idx, TRUE);
+ fk.foreign_id.str,
+ fk.foreign_id.length,
+ ff.str, ff.length,
+ (longlong) f_idx);
+ table->field[8]->store((longlong) f_idx, true);
table->field[8]->set_notnull();
- table->field[9]->store(f_key_info->referenced_db->str,
- f_key_info->referenced_db->length,
- system_charset_info);
+ table->field[9]->store(fk.ref_db().str,
+ fk.ref_db().length,
+ system_charset_info);
table->field[9]->set_notnull();
- table->field[10]->store(f_key_info->referenced_table->str,
- f_key_info->referenced_table->length,
+ table->field[10]->store(fk.referenced_table.str,
+ fk.referenced_table.length,
system_charset_info);
table->field[10]->set_notnull();
- table->field[11]->store(r_info->str, r_info->length,
+ table->field[11]->store(rf.str, rf.length,
system_charset_info);
table->field[11]->set_notnull();
if (schema_table_store_record(thd, table))
@@ -7925,38 +7985,31 @@ get_referential_constraints_record(THD *thd, TABLE_LIST *tables,
thd->clear_error();
DBUG_RETURN(0);
}
- if (!tables->view)
+ if (!tables->view && !tables->table->s->foreign_keys.is_empty())
{
- List<FOREIGN_KEY_INFO> f_key_list;
TABLE *show_table= tables->table;
show_table->file->info(HA_STATUS_VARIABLE |
HA_STATUS_NO_LOCK |
HA_STATUS_TIME);
- show_table->file->get_foreign_key_list(thd, &f_key_list);
- FOREIGN_KEY_INFO *f_key_info;
- List_iterator_fast<FOREIGN_KEY_INFO> it(f_key_list);
+ FK_info *f_key_info;
+ List_iterator_fast<FK_info> it(show_table->s->foreign_keys);
while ((f_key_info= it++))
{
restore_record(table, s->default_values);
table->field[0]->store(STRING_WITH_LEN("def"), cs);
table->field[1]->store(db_name->str, db_name->length, cs);
table->field[9]->store(table_name->str, table_name->length, cs);
- table->field[2]->store(f_key_info->foreign_id->str,
- f_key_info->foreign_id->length, cs);
+ table->field[2]->store(f_key_info->foreign_id.str,
+ f_key_info->foreign_id.length, cs);
table->field[3]->store(STRING_WITH_LEN("def"), cs);
- table->field[4]->store(f_key_info->referenced_db->str,
- f_key_info->referenced_db->length, cs);
- table->field[10]->store(f_key_info->referenced_table->str,
- f_key_info->referenced_table->length, cs);
- if (f_key_info->referenced_key_name)
- {
- table->field[5]->store(f_key_info->referenced_key_name->str,
- f_key_info->referenced_key_name->length, cs);
- table->field[5]->set_notnull();
- }
- else
- table->field[5]->set_null();
+ table->field[4]->store(f_key_info->ref_db().str,
+ f_key_info->ref_db().length, cs);
+ table->field[10]->store(f_key_info->referenced_table.str,
+ f_key_info->referenced_table.length, cs);
+ table->field[5]->store(f_key_info->foreign_id.str,
+ f_key_info->foreign_id.length, cs);
+ table->field[5]->set_notnull();
table->field[6]->store(STRING_WITH_LEN("NONE"), cs);
s= fk_option_name(f_key_info->update_method);
table->field[7]->store(s->str, s->length, cs);
diff --git a/sql/sql_string.h b/sql/sql_string.h
index 7c36a61a38a..d9c19898c14 100644
--- a/sql/sql_string.h
+++ b/sql/sql_string.h
@@ -222,6 +222,23 @@ public:
inline bool is_empty() const { return (str_length == 0); }
inline const char *ptr() const { return Ptr; }
inline const char *end() const { return Ptr + str_length; }
+
+ LEX_STRING lex_string() const
+ {
+ LEX_STRING str = { (char*) ptr(), length() };
+ return str;
+ }
+ LEX_CSTRING lex_cstring() const
+ {
+ LEX_CSTRING skr = { ptr(), length() };
+ return skr;
+ }
+ LEX_CUSTRING lex_custring() const
+ {
+ LEX_CUSTRING str = { (const uchar *) ptr(), length() };
+ return str;
+ }
+
bool has_8bit_bytes() const
{
for (const char *c= ptr(), *c_end= end(); c < c_end; c++)
@@ -960,6 +977,16 @@ public:
return append(s.str, s.length, cs);
}
+ bool append(longlong num, bool unsigned_flag)
+ {
+ uint l= 20 * charset()->mbmaxlen + 1;
+ int base= unsigned_flag ? 10 : -10;
+ char buf[256];
+ DBUG_ASSERT(l < 256);
+ size_t len= (uint32) (charset()->cset->longlong10_to_str)(charset(), buf, l, base, num);
+ return append(buf, len);
+ }
+
void strip_sp();
friend int sortcmp(const String *a,const String *b, CHARSET_INFO *cs);
friend int stringcmp(const String *a,const String *b);
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index eb149c2849c..e1e3c6f665c 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -59,6 +59,7 @@
#include "ddl_log.h"
#include "debug_sync.h" // debug_crash_here()
#include <algorithm>
+#include "sql_rename.h"
#ifdef __WIN__
#include <io.h>
@@ -70,8 +71,9 @@ static const LEX_CSTRING generated_by_server=
static const LEX_CSTRING SEQUENCE_clex_str= { STRING_WITH_LEN("SEQUENCE") };
static const LEX_CSTRING TABLE_clex_str= { STRING_WITH_LEN("TABLE") };
-static int check_if_keyname_exists(const char *name,KEY *start, KEY *end);
-static char *make_unique_key_name(THD *, const char *, KEY *, KEY *);
+static Lex_cstring
+make_unique_key_name(THD* thd, LEX_CSTRING prefix,
+ const Lex_ident_set& key_names, bool foreign);
static bool make_unique_constraint_name(THD *, LEX_CSTRING *, const char *,
List<Virtual_column_info> *, uint *);
static const char *make_unique_invisible_field_name(THD *, const char *,
@@ -84,11 +86,21 @@ static int copy_data_between_tables(THD *, TABLE *,TABLE *,
static int append_system_key_parts(THD *thd, HA_CREATE_INFO *create_info,
Key *key);
static int mysql_prepare_create_table(THD *, HA_CREATE_INFO *, Alter_info *,
- uint *, handler *, KEY **, uint *, int);
+ uint *, handler *, KEY **, uint *,
+ FK_list &, FK_list &, int,
+ const LEX_CSTRING &db,
+ const LEX_CSTRING &table_name);
static uint blob_length_by_type(enum_field_types type);
static bool fix_constraints_names(THD *thd, List<Virtual_column_info>
*check_constraint_list,
const HA_CREATE_INFO *create_info);
+static
+bool fk_handle_drop(THD* thd, TABLE_LIST* table, mbd::vector<FK_ddl_backup>& shares,
+ bool drop_db);
+
+static
+bool fk_prepare_create_table(THD *thd, Alter_info &alter_info, FK_list &foreign_keys);
+
/**
@brief Helper function for explain_filename
@@ -659,18 +671,20 @@ void build_lower_case_table_filename(char *buff, size_t bufflen,
@param[out] buff buffer to receive the constructed name
@param bufflen size of buff
- @param lpt alter table data structure
+ @param db
+ @param table_name
@retval path length
*/
-uint build_table_shadow_filename(char *buff, size_t bufflen,
- ALTER_PARTITION_PARAM_TYPE *lpt)
+uint build_table_shadow_filename(char *buff, size_t bufflen,
+ const LEX_CSTRING &db,
+ const LEX_CSTRING &table_name)
{
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, "",
+ (ulong) current_thd->thread_id, table_name.str);
+ return build_table_filename(buff, bufflen, db.str, tmp_name, "",
FN_IS_TMP);
}
@@ -723,14 +737,17 @@ bool mysql_write_frm(ALTER_PARTITION_PARAM_TYPE *lpt, uint flags)
/*
Build shadow frm file name
*/
- build_table_shadow_filename(shadow_path, sizeof(shadow_path) - 1, lpt);
+ build_table_shadow_filename(shadow_path, sizeof(shadow_path) - 1,
+ lpt->db, lpt->table_name);
strxmov(shadow_frm_name, shadow_path, reg_ext, NullS);
if (flags & WFRM_WRITE_SHADOW)
{
+ FK_list foreign_keys, referenced_keys;
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))
+ foreign_keys, referenced_keys, C_ALTER_TABLE,
+ lpt->db, lpt->table_name))
{
DBUG_RETURN(TRUE);
}
@@ -754,6 +771,7 @@ bool mysql_write_frm(ALTER_PARTITION_PARAM_TYPE *lpt, uint flags)
lpt->create_info,
lpt->alter_info->create_list,
lpt->key_count, lpt->key_info_buffer,
+ foreign_keys, referenced_keys,
lpt->table->file);
if (!frm.str)
{
@@ -1042,7 +1060,7 @@ bool mysql_rm_table(THD *thd,TABLE_LIST *tables, bool if_exists,
error= mysql_rm_table_no_locks(thd, tables, &thd->db, (DDL_LOG_STATE*) 0,
if_exists,
drop_temporary,
- false, drop_sequence, dont_log_query,
+ false, drop_sequence, false, dont_log_query,
false);
thd->pop_internal_handler();
@@ -1141,7 +1159,7 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables,
DDL_LOG_STATE *ddl_log_state,
bool if_exists,
bool drop_temporary, bool drop_view,
- bool drop_sequence,
+ bool drop_sequence, bool drop_db,
bool dont_log_query,
bool dont_free_locks)
{
@@ -1424,6 +1442,10 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables,
error= 1;
goto err;
}
+ bool enoent_warning;
+ mbd::vector<FK_ddl_backup> shares;
+ if ((error= fk_handle_drop(thd, table, shares, drop_db)))
+ goto fk_error;
if (thd->locked_tables_mode == LTM_LOCK_TABLES ||
thd->locked_tables_mode == LTM_PRELOCKED_UNDER_LOCK_TABLES)
@@ -1431,6 +1453,9 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables,
if (wait_while_table_is_used(thd, table->table, HA_EXTRA_NOT_USED))
{
error= -1;
+ for (FK_ddl_backup &bak: shares)
+ if (bak.sa.share)
+ bak.rollback();
goto err;
}
close_all_tables_for_name(thd, table->table->s,
@@ -1450,7 +1475,7 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables,
if (hton && hton->flags & HTON_TABLE_MAY_NOT_EXIST_ON_SLAVE)
log_if_exists= 1;
- bool enoent_warning= !dont_log_query && !(hton && hton->discover_table);
+ enoent_warning= !dont_log_query && !(hton && hton->discover_table);
if (was_view)
res= ddl_log_drop_view(thd, ddl_log_state, &cpath, &db,
@@ -1475,9 +1500,13 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables,
error= 0; // Table didn't exists
else if (error)
{
- if (thd->is_killed())
+fk_error:
+ if (drop_db || thd->is_killed())
{
error= -1;
+ for (FK_ddl_backup &bak: shares)
+ if (bak.sa.share)
+ bak.rollback();
goto err;
}
}
@@ -1522,6 +1551,20 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables,
table_dropped= 1;
}
}
+ if (likely(!error))
+ {
+ for (FK_ddl_backup &bak: shares)
+ {
+ if (bak.sa.share)
+ bak.sa.share->fk_install_shadow_frm();
+ }
+ }
+ else
+ {
+ for (FK_ddl_backup &bak: shares)
+ if (bak.sa.share)
+ bak.rollback();
+ }
local_non_tmp_error|= MY_TEST(error);
}
@@ -2567,9 +2610,14 @@ 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)
+ uint *key_count, FK_list &foreign_keys,
+ FK_list &referenced_keys,
+ int create_table_mode, const LEX_CSTRING &db,
+ const LEX_CSTRING &table_name)
{
- const char *key_name;
+ Lex_cstring key_name;
+ Lex_ident_set key_names;
+ Lex_ident_set dup_check;
Create_field *sql_field,*dup_field;
uint field,null_fields,max_key_length;
ulong record_offset= 0;
@@ -2798,25 +2846,22 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
List_iterator<Key> key_iterator(alter_info->key_list);
List_iterator<Key> key_iterator2(alter_info->key_list);
- uint key_parts=0, fk_key_count=0;
+ uint key_parts=0;
bool primary_key=0,unique_key=0;
Key *key, *key2;
uint tmp, key_number;
- /* special marker for keys to be ignored */
- static char ignore_key[1];
- /* Calculate number of key segements */
+ /* Calculate number of key segments */
*key_count= 0;
while ((key=key_iterator++))
{
DBUG_PRINT("info", ("key name: '%s' type: %d", key->name.str ? key->name.str :
"(none)" , key->type));
- if (key->type == Key::FOREIGN_KEY)
+ if (key->foreign)
{
- fk_key_count++;
Foreign_key *fk_key= (Foreign_key*) key;
- if (fk_key->validate(alter_info->create_list))
+ if (!fk_key->ignore && fk_key->validate(alter_info->create_list))
DBUG_RETURN(TRUE);
if (fk_key->ref_columns.elements &&
fk_key->ref_columns.elements != fk_key->columns.elements)
@@ -2827,7 +2872,6 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
ER_THD(thd, ER_KEY_REF_DO_NOT_MATCH_TABLE_REF));
DBUG_RETURN(TRUE);
}
- continue;
}
(*key_count)++;
tmp=file->max_key_parts();
@@ -2839,36 +2883,30 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
if (check_ident_length(&key->name))
DBUG_RETURN(TRUE);
key_iterator2.rewind ();
- if (key->type != Key::FOREIGN_KEY)
+ while ((key2 = key_iterator2++) != key)
{
- 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.
+ */
+ if ((!key2->ignore && !foreign_key_prefix(key, key2)))
{
- /*
- 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.
- */
- if ((key2->type != Key::FOREIGN_KEY &&
- key2->name.str != ignore_key &&
- !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 < key2->columns.elements))
+ key->ignore= true;
+ else
{
- /* TODO: issue warning message */
- /* mark that the generated key should be ignored */
- if (!key2->generated ||
- (key->generated && key->columns.elements <
- key2->columns.elements))
- key->name.str= ignore_key;
- else
- {
- key2->name.str= ignore_key;
- key_parts-= key2->columns.elements;
- (*key_count)--;
- }
- break;
+ key2->ignore= true;
+ key_parts-= key2->columns.elements;
+ (*key_count)--;
}
+ break;
}
}
- if (key->name.str != ignore_key)
+ if (!key->ignore)
key_parts+=key->columns.elements;
else
(*key_count)--;
@@ -2899,8 +2937,33 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
key_iterator.rewind();
while ((key=key_iterator++))
{
- if (key->name.str == ignore_key || key->type == Key::FOREIGN_KEY)
+ if (key->ignore)
+ {
+ if (key->foreign)
+ {
+ FK_info *fk= new (thd->mem_root) FK_info();
+ Foreign_key &fkey= static_cast<Foreign_key &>(*key);
+ fk->assign(fkey, {db, table_name});
+ if (!fk->foreign_id.str)
+ {
+ fk->foreign_id= make_unique_key_name(thd, table_name, key_names, true);
+ fkey.constraint_name= fk->foreign_id;
+ }
+ if (foreign_keys.push_back(fk))
+ {
+ my_error(ER_OUT_OF_RESOURCES, MYF(0));
+ DBUG_RETURN(true);
+ }
+ if (fk->self_ref() && referenced_keys.push_back(fk))
+ {
+ my_error(ER_OUT_OF_RESOURCES, MYF(0));
+ DBUG_RETURN(true);
+ }
+ if (!key_names.insert(fk->foreign_id))
+ DBUG_RETURN(true); // Out of memory
+ }
continue;
+ }
/* Create the key name based on the first column (if not given) */
if (key->type == Key::PRIMARY)
{
@@ -2912,8 +2975,22 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
}
key_name= primary_key_name.str;
primary_key=1;
+ if (!key->name.str)
+ {
+ key->name= key_name;
+ }
}
- else if (!(key_name= key->name.str))
+ else if (key->foreign)
+ {
+ Foreign_key &fkey= static_cast<Foreign_key &>(*key);
+ key_name= fkey.constraint_name.str ? fkey.constraint_name : key->name;
+ if (!key_name.str)
+ {
+ key_name= make_unique_key_name(thd, table_name, key_names, true);
+ fkey.constraint_name= key_name;
+ }
+ }
+ else if (!(key_name= key->name, key_name.str))
{
auto field_name= key->columns.elem(0)->field_name;
it.rewind();
@@ -2923,18 +3000,36 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
&sql_field->field_name));
if (sql_field)
field_name= sql_field->field_name;
- key_name=make_unique_key_name(thd, field_name.str,
- *key_info_buffer, key_info);
+ key_name=make_unique_key_name(thd, field_name,
+ key_names, false);
}
- if (check_if_keyname_exists(key_name, *key_info_buffer, key_info))
+ if (dup_check.find(key_name) != dup_check.end())
{
- my_error(ER_DUP_KEYNAME, MYF(0), key_name);
+ my_error(ER_DUP_KEYNAME, MYF(0), key_name.str);
DBUG_RETURN(true);
}
-
- key_info->name.str= (char*) key_name;
- key_info->name.length= strlen(key_name);
- key->name= key_info->name;
+ if (key->foreign)
+ {
+ FK_info *fk= new (thd->mem_root) FK_info();
+ fk->assign(*(Foreign_key *) key, {db, table_name});
+ fk->foreign_id= key_name;
+ if (foreign_keys.push_back(fk))
+ {
+ my_error(ER_OUT_OF_RESOURCES, MYF(0));
+ DBUG_RETURN(TRUE);
+ }
+ if (fk->self_ref() && referenced_keys.push_back(fk))
+ {
+ my_error(ER_OUT_OF_RESOURCES, MYF(0));
+ DBUG_RETURN(TRUE);
+ }
+ }
+ key_info->name= key_name;
+ if (!key_names.insert(key_name))
+ DBUG_RETURN(TRUE);
+ if (!dup_check.insert(key_name))
+ DBUG_RETURN(TRUE);
+ key->name= key_info->name; // FIXME: need this?
int parts_added= append_system_key_parts(thd, create_info, key);
if (parts_added < 0)
@@ -2963,14 +3058,14 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
Key_part_spec *column;
is_hash_field_needed= false;
- if (key->name.str == ignore_key)
+ if (key->ignore)
{
/* ignore redundant keys */
do
- key=key_iterator++;
- while (key && key->name.str == ignore_key);
+ key=key_iterator++;
+ while (key && key->ignore);
if (!key)
- break;
+ break;
}
switch (key->type) {
@@ -2993,9 +3088,6 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
sym_group_geom.name, sym_group_geom.needed_define);
DBUG_RETURN(TRUE);
#endif
- case Key::FOREIGN_KEY:
- key_number--; // Skip this key
- continue;
default:
key_info->flags = HA_NOSAME;
break;
@@ -3177,15 +3269,16 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
break;
case Key::MULTIPLE:
- if (sql_field->type_handler()->Key_part_spec_init_multiple(column,
- *sql_field,
- file) ||
- sql_field->check_vcol_for_key(thd) ||
- key_add_part_check_null(file, key_info, sql_field, column))
- DBUG_RETURN(TRUE);
- break;
-
- case Key::FOREIGN_KEY:
+ if (!key->foreign)
+ {
+ if (sql_field->type_handler()->Key_part_spec_init_multiple(column,
+ *sql_field,
+ file) ||
+ sql_field->check_vcol_for_key(thd) ||
+ key_add_part_check_null(file, key_info, sql_field, column))
+ DBUG_RETURN(TRUE);
+ break;
+ }
if (sql_field->type_handler()->Key_part_spec_init_foreign(column,
*sql_field,
file) ||
@@ -3411,7 +3504,7 @@ without_overlaps_err:
key_iterator2.rewind();
while ((key2 = key_iterator2++))
{
- if (key2->type != Key::FOREIGN_KEY)
+ if (!key2->foreign)
continue;
DBUG_ASSERT(key != key2);
Foreign_key *fk= (Foreign_key*) key2;
@@ -3550,7 +3643,7 @@ without_overlaps_err:
Noly Primary Key UNIQUE and Foreign keys.
*/
if (key->type != Key::PRIMARY && key->type != Key::UNIQUE &&
- key->type != Key::FOREIGN_KEY)
+ !key->foreign)
continue;
if (check->name.length == key->name.length &&
@@ -3573,6 +3666,9 @@ without_overlaps_err:
}
}
+ /* Check foreign keys */
+ fk_prepare_create_table(thd, *alter_info, foreign_keys);
+
/* Give warnings for not supported table options */
extern handlerton *maria_hton;
if (file->partition_ht() != maria_hton && create_info->transactional &&
@@ -3829,9 +3925,12 @@ static int append_system_key_parts(THD *thd, HA_CREATE_INFO *create_info,
handler *mysql_create_frm_image(THD *thd, const LEX_CSTRING &db,
const LEX_CSTRING &table_name,
+ const LEX_CSTRING &new_db,
+ const LEX_CSTRING &new_table_name,
HA_CREATE_INFO *create_info,
Alter_info *alter_info, int create_table_mode,
KEY **key_info, uint *key_count,
+ FK_list &foreign_keys, FK_list &referenced_keys,
LEX_CUSTRING *frm)
{
uint db_options;
@@ -3888,6 +3987,13 @@ handler *mysql_create_frm_image(THD *thd, const LEX_CSTRING &db,
List_iterator<partition_element> part_it(part_info->partitions);
partition_element *part_elem;
+ DBUG_ASSERT(foreign_keys.elements == 0);
+ if (referenced_keys.elements > 0)
+ {
+ my_error(ER_FEATURE_NOT_SUPPORTED_WITH_PARTITIONING, MYF(0), "FOREIGN KEY");
+ goto err;
+ }
+
while ((part_elem= part_it++))
{
if (part_elem->part_comment)
@@ -4052,9 +4158,9 @@ handler *mysql_create_frm_image(THD *thd, const LEX_CSTRING &db,
Key *key;
while ((key= key_iterator++))
{
- if (key->type == Key::FOREIGN_KEY)
+ if (key->foreign)
{
- my_error(ER_FEATURE_NOT_SUPPORTED_WITH_PARTITIONING, MYF(0),
+ my_error(ER_FEATURE_NOT_SUPPORTED_WITH_PARTITIONING, MYF(0),
"FOREIGN KEY");
goto err;
}
@@ -4063,13 +4169,15 @@ 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))
+ file, key_info, key_count, foreign_keys,
+ referenced_keys, create_table_mode,
+ new_db, new_table_name))
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);
+ *key_info, foreign_keys, referenced_keys, file);
if (frm->str)
DBUG_RETURN(file);
@@ -4121,10 +4229,12 @@ int create_table_impl(THD *thd,
const LEX_CSTRING &orig_db,
const LEX_CSTRING &orig_table_name,
const LEX_CSTRING &db, const LEX_CSTRING &table_name,
+ const LEX_CSTRING &new_name,
const LEX_CSTRING &path, const DDL_options_st options,
HA_CREATE_INFO *create_info, Alter_info *alter_info,
int create_table_mode, bool *is_trans, KEY **key_info,
- uint *key_count, LEX_CUSTRING *frm)
+ uint *key_count, FK_list &foreign_keys,
+ FK_list &referenced_keys, LEX_CUSTRING *frm)
{
LEX_CSTRING *alias;
handler *file= 0;
@@ -4256,7 +4366,7 @@ int create_table_impl(THD *thd,
/* Remove normal table without logging. Keep tables locked */
if (mysql_rm_table_no_locks(thd, &table_list, &thd->db,
ddl_log_state_rm,
- 0, 0, 0, 0, 1, 1))
+ 0, 0, 0, 0, 0, 1, 1))
goto err;
debug_crash_here("ddl_log_create_after_drop");
@@ -4368,9 +4478,9 @@ 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,
+ file= mysql_create_frm_image(thd, orig_db, orig_table_name, db, new_name, create_info,
alter_info, create_table_mode, key_info,
- key_count, frm);
+ key_count, foreign_keys, referenced_keys, frm);
/*
TODO: remove this check of thd->is_error() (now it intercept
errors in some val_*() methods and bring some single place to
@@ -4393,7 +4503,7 @@ int create_table_impl(THD *thd,
{
debug_crash_here("ddl_log_create_before_create_table");
if (ha_create_table(thd, path.str, db.str, table_name.str, create_info,
- frm))
+ alter_info, frm, true))
{
file->ha_create_partitioning_metadata(path.str, NULL, CHF_DELETE_FLAG);
deletefrm(path.str);
@@ -4472,6 +4582,7 @@ int mysql_create_table_no_lock(THD *thd,
char path[FN_REFLEN + 1];
LEX_CSTRING cpath;
LEX_CUSTRING frm= {0,0};
+ FK_list foreign_keys, referenced_keys;
if (create_info->tmp_table())
path_length= build_tmptable_filename(thd, path, sizeof(path));
@@ -4492,10 +4603,11 @@ int mysql_create_table_no_lock(THD *thd,
lex_string_set3(&cpath, path, path_length);
res= create_table_impl(thd, ddl_log_state_create, ddl_log_state_rm,
- *db, *table_name, *db, *table_name, cpath,
- *create_info, create_info,
+ *db, *table_name, *db, *table_name, *table_name,
+ cpath, *create_info, create_info,
alter_info, create_table_mode,
- is_trans, &not_used_1, &not_used_2, &frm);
+ is_trans, &not_used_1, &not_used_2, foreign_keys, referenced_keys,
+ &frm);
my_free(const_cast<uchar*>(frm.str));
if (!res && create_info->sequence)
@@ -4515,6 +4627,7 @@ int mysql_create_table_no_lock(THD *thd,
1,
create_info->tmp_table(),
false, true /* Sequence*/,
+ false, /* Drop DB */
true /* Don't log_query */,
true /* Don't free locks */ ))
{
@@ -4688,23 +4801,6 @@ err:
}
-/*
-** Give the key name after the first field with an optional '_#' after
- @returns
- 0 if keyname does not exists
- [1..) index + 1 of duplicate key name
-**/
-
-static int
-check_if_keyname_exists(const char *name, KEY *start, KEY *end)
-{
- uint i= 1;
- for (KEY *key=start; key != end ; key++, i++)
- if (!my_strcasecmp(system_charset_info, name, key->name.str))
- return i;
- return 0;
-}
-
/**
Returns 1 if field name exists otherwise 0
*/
@@ -4721,28 +4817,65 @@ check_if_field_name_exists(const char *name, List<Create_field> * fields)
return 0;
}
-static char *
-make_unique_key_name(THD *thd, const char *field_name,KEY *start,KEY *end)
+
+/**
+ Generate key name with given prefix and '_N' suffix where 1 < N < 100
+*/
+static Lex_cstring
+make_unique_key_name(THD *thd, LEX_CSTRING prefix,
+ const Lex_ident_set &key_names, bool foreign)
{
- char buff[MAX_FIELD_NAME],*buff_end;
+ char buf[MAX_FIELD_NAME - 1];
+ char *ptr= buf;
+ static const LEX_CSTRING fk_prefix= { C_STRING_WITH_LEN("fk_") };
+ DBUG_ASSERT(fk_prefix.length < sizeof(buf));
- if (!check_if_keyname_exists(field_name,start,end) &&
- my_strcasecmp(system_charset_info,field_name,primary_key_name.str))
- return (char*) field_name; // Use fieldname
- buff_end=strmake(buff,field_name, sizeof(buff)-4);
+ if (foreign)
+ {
+ memcpy(ptr, LEX_STRING_WITH_LEN(fk_prefix));
+ ptr+= fk_prefix.length;
+ prefix.length= std::min(sizeof(buf) - fk_prefix.length - 1, prefix.length);
+ }
+ else
+ prefix.length= std::min(sizeof(buf) - 1, prefix.length);
+
+ memcpy(ptr, prefix.str, prefix.length);
+ ptr+= prefix.length;
+ DBUG_ASSERT(ptr - buf < (long int)sizeof(buf));
+ *ptr= 0;
+ prefix.str= buf;
+ if (foreign)
+ prefix.length+= fk_prefix.length;
+
+ if ((key_names.find(prefix) == key_names.end()) &&
+ my_strcasecmp(system_charset_info, prefix.str, primary_key_name.str))
+ {
+ Lex_cstring ret(prefix);
+ ret.strdup(thd->mem_root, ret);
+ return ret;
+ }
/*
Only 3 chars + '\0' left, so need to limit to 2 digit
This is ok as we can't have more than 100 keys anyway
*/
- for (uint i=2 ; i< 100; i++)
+ if (prefix.length > sizeof(buf) - 4)
+ prefix.length= sizeof(buf) - 4;
+
+ for (uint i= 2 ; i < 100; i++)
{
- *buff_end= '_';
- int10_to_str(i, buff_end+1, 10);
- if (!check_if_keyname_exists(buff,start,end))
- return thd->strdup(buff);
+ *ptr= '_';
+ size_t n= int10_to_str(i, ptr + 1, 10) - ptr;
+ Lex_cstring ret(buf, prefix.length + n);
+ if (key_names.find(ret) == key_names.end())
+ {
+ ret.strdup(thd->mem_root, ret);
+ return ret;
+ }
}
- return (char*) "not_specified"; // Should never happen
+ DBUG_ASSERT(0);
+ static Lex_cstring not_specified("not_specified");
+ return not_specified;
}
/**
@@ -5634,15 +5767,13 @@ drop_create_field:
}
}
}
- else
+ else if (!table->s->foreign_keys.is_empty())
{
- List <FOREIGN_KEY_INFO> fk_child_key_list;
- FOREIGN_KEY_INFO *f_key;
- table->file->get_foreign_key_list(thd, &fk_child_key_list);
- List_iterator<FOREIGN_KEY_INFO> fk_key_it(fk_child_key_list);
+ FK_info *f_key;
+ List_iterator<FK_info> fk_key_it(table->s->foreign_keys);
while ((f_key= fk_key_it++))
{
- if (my_strcasecmp(system_charset_info, f_key->foreign_id->str,
+ if (my_strcasecmp(system_charset_info, f_key->foreign_id.str,
drop->name) == 0)
{
remove_drop= FALSE;
@@ -5755,7 +5886,7 @@ drop_create_field:
continue;
}
}
- if (key->type != Key::FOREIGN_KEY)
+ if (!key->foreign)
{
for (n_key=0; n_key < table->s->keys; n_key++)
{
@@ -5766,17 +5897,53 @@ drop_create_field:
}
}
}
- else
+ else if (!table->s->foreign_keys.is_empty())
{
- List <FOREIGN_KEY_INFO> fk_child_key_list;
- FOREIGN_KEY_INFO *f_key;
- table->file->get_foreign_key_list(thd, &fk_child_key_list);
- List_iterator<FOREIGN_KEY_INFO> fk_key_it(fk_child_key_list);
- while ((f_key= fk_key_it++))
+ Foreign_key *new_fk= static_cast<Foreign_key *>(key);
+ FK_info *fk;
+ List_iterator_fast<FK_info> fk_it(table->s->foreign_keys);
+ if (new_fk->constraint_name.str)
+ {
+ while ((fk= fk_it++))
+ {
+ if (0 == cmp_ident(fk->foreign_id, new_fk->constraint_name))
+ goto remove_key;
+ }
+ }
+ else
{
- if (my_strcasecmp(system_charset_info, f_key->foreign_id->str,
- keyname) == 0)
+ // Match by parameters in case of no ID.
+ List_iterator_fast<Key_part_spec> col_it;
+ while ((fk= fk_it++))
+ {
+ if (fk->update_method != new_fk->update_opt ||
+ fk->delete_method != new_fk->delete_opt ||
+ fk->foreign_fields.elements != new_fk->columns.elements)
+ continue;
+ if (cmp_table(fk->ref_db(), new_fk->ref_db.str ?
+ new_fk->ref_db : table->s->db) ||
+ cmp_table(fk->referenced_table, new_fk->ref_table))
+ continue;
+ col_it.init(new_fk->columns);
+ for (const Lex_cstring &fld: fk->foreign_fields)
+ {
+ Key_part_spec *ref_col= col_it++;
+ if (cmp_ident(fld, ref_col->field_name))
+ break;
+ }
+ if (col_it.peek())
+ continue;
+ col_it.init(new_fk->ref_columns);
+ for (const Lex_cstring &fld: fk->referenced_fields)
+ {
+ Key_part_spec *ref_col= col_it++;
+ if (cmp_ident(fld, ref_col->field_name))
+ break;
+ }
+ if (col_it.peek())
+ continue;
goto remove_key;
+ } // while ((fk= fk_it++))
}
}
@@ -5809,18 +5976,13 @@ remove_key:
ER_DUP_KEYNAME, ER_THD(thd, dup_primary_key
? ER_MULTIPLE_PRI_KEY : ER_DUP_KEYNAME), keyname);
key_it.remove();
- if (key->type == Key::FOREIGN_KEY)
- {
- /* ADD FOREIGN KEY appends two items. */
- key_it.remove();
- }
if (alter_info->key_list.is_empty())
alter_info->flags&= ~(ALTER_ADD_INDEX | ALTER_ADD_FOREIGN_KEY);
}
else
{
DBUG_ASSERT(key->or_replace());
- Alter_drop::drop_type type= (key->type == Key::FOREIGN_KEY) ?
+ Alter_drop::drop_type type= key->foreign ?
Alter_drop::FOREIGN_KEY : Alter_drop::KEY;
Alter_drop *ad= new (thd->mem_root) Alter_drop(type, key->name.str, FALSE);
if (ad != NULL)
@@ -6687,13 +6849,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;
+ FK_list foreign_keys, referenced_keys;
/* 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))
+ &key_count, foreign_keys, referenced_keys,
+ create_table_mode, table->s->db,
+ table->s->table_name))
DBUG_RETURN(1);
/* Some very basic checks. */
@@ -7141,6 +7306,9 @@ static bool mysql_inplace_alter_table(THD *thd,
if (wait_while_table_is_used(thd, table, HA_EXTRA_PREPARE_FOR_RENAME))
goto rollback;
+ if (alter_ctx->fk_handle_alter(thd))
+ goto rollback;
+
/* Set MDL_BACKUP_DDL */
if (backup_reset_alter_copy_lock(thd))
goto rollback;
@@ -7208,10 +7376,13 @@ static bool mysql_inplace_alter_table(THD *thd,
&table->s->tabledef_version))
{
my_error(HA_ERR_INCOMPATIBLE_DEFINITION, MYF(0));
- DBUG_RETURN(true);
+ goto cleanup;
}
}
+ alter_ctx->fk_table_backup.commit();
+ table->s->frm_image= NULL;
+
close_all_tables_for_name(thd, table->s,
alter_ctx->is_table_renamed() ?
HA_EXTRA_PREPARE_FOR_RENAME :
@@ -7219,6 +7390,9 @@ static bool mysql_inplace_alter_table(THD *thd,
NULL);
table_list->table= table= NULL;
+ if (alter_ctx->fk_install_frms())
+ DBUG_RETURN(true);
+
/*
Replace the old .FRM with the new .FRM, but keep the old name for now.
Rename to the new name (if needed) will be handled separately below.
@@ -7273,10 +7447,13 @@ static bool mysql_inplace_alter_table(THD *thd,
DBUG_RETURN(false);
rollback:
+ alter_ctx->fk_rollback();
table->file->ha_commit_inplace_alter_table(altered_table,
ha_alter_info,
false);
cleanup:
+ alter_ctx->fk_release_locks(thd);
+ table->s->frm_image= NULL;
if (reopen_tables)
{
/* Close the only table instance which is still around. */
@@ -7385,6 +7562,7 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
/* New key definitions are added here */
List<Key> new_key_list;
List<Alter_rename_key> rename_key_list(alter_info->alter_rename_key_list);
+ mbd::set<FK_table_to_lock> fk_tables_to_lock;
List_iterator<Alter_drop> drop_it(alter_info->drop_list);
List_iterator<Create_field> def_it(alter_info->create_list);
List_iterator<Alter_column> alter_it(alter_info->alter_list);
@@ -7397,7 +7575,7 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
& ~(HA_OPTION_PACK_RECORD));
Item::func_processor_rename column_rename_param;
uint used_fields, dropped_sys_vers_fields= 0;
- KEY *key_info=table->key_info;
+ KEY *key_info;
bool rc= TRUE;
bool modified_primary_key= FALSE;
bool vers_system_invisible= false;
@@ -7412,6 +7590,8 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
period_start_name= table->s->period_start_field()->field_name;
period_end_name= table->s->period_end_field()->field_name;
}
+ if (!table->s->tmp_table)
+ alter_ctx->fk_table_backup.init(table->s);
DBUG_ENTER("mysql_prepare_alter_table");
/*
@@ -7493,7 +7673,7 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
break;
}
/*
- DROP COLULMN xxx
+ DROP COLUMN xxx
1. it does not see INVISIBLE_SYSTEM columns
2. otherwise, normally a column is dropped
3. unless it's a system versioning column (but see below).
@@ -7544,6 +7724,11 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
if (def && field->invisible < INVISIBLE_SYSTEM)
{ // Field is changed
def->field=field;
+ if ((alter_info->flags & ALTER_RENAME_COLUMN) &&
+ 0 != cmp_ident(def->change, def->field_name))
+ {
+ alter_ctx->fk_prepare_rename(thd, table, def, fk_tables_to_lock);
+ }
/*
Add column being updated to the list of new columns.
Note that columns with AFTER clauses are added to the end
@@ -7615,6 +7800,7 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
def->change= alter->name;
def->field_name= alter->new_name;
column_rename_param.fields.push_back(def);
+ alter_ctx->fk_prepare_rename(thd, table, def, fk_tables_to_lock);
if (field->flags & VERS_SYS_START_FLAG)
create_info->vers_info.as_row.start= alter->new_name;
else if (field->flags & VERS_SYS_END_FLAG)
@@ -7814,9 +8000,122 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
}
/*
+ Collect all referenced keys which are not self-refs
+ */
+ for (FK_info &rk: table->s->referenced_keys)
+ {
+ if (!rk.self_ref())
+ alter_ctx->referenced_keys.push_back(&rk);
+ }
+
+ /*
+ Collect all foreign keys which isn't in drop list.
+ */
+ for (const FK_info &fk: table->s->foreign_keys)
+ {
+ Foreign_key *key;
+ Alter_drop *drop;
+ DBUG_ASSERT(fk.foreign_id.str);
+ drop_it.rewind();
+ while ((drop= drop_it++))
+ {
+ if (drop->type == Alter_drop::FOREIGN_KEY &&
+ 0 == my_strcasecmp(system_charset_info, fk.foreign_id.str, drop->name))
+ break;
+ }
+ if (drop)
+ {
+ if (!table->s->tmp_table)
+ {
+ key_info= table->key_info;
+ for (uint i= 0 ; i < table->s->keys ; i++, key_info++)
+ {
+ const char *key_name= key_info->name.str;
+ if (0 == my_strcasecmp(system_charset_info, key_name, drop->name))
+ {
+ delete_statistics_for_index(thd, table, key_info, FALSE);
+ break;
+ }
+ }
+ }
+ Table_name t(fk.ref_table(thd->mem_root));
+ if (lower_case_table_names)
+ t.lowercase(thd->mem_root);
+ if (0 != cmp_table(t.db, table->s->db) ||
+ 0 != cmp_table(t.name, table->s->table_name))
+ {
+ if (alter_ctx->fk_dropped.push_back({t, &fk}))
+ goto err;
+ if (!fk_tables_to_lock.insert(t))
+ goto err;
+ }
+ alter_info->tmp_drop_list.push_back(drop); // FIXME: remove in MDEV-21052
+ drop_it.remove();
+ while ((drop= drop_it++))
+ {
+ if (drop->type == Alter_drop::FOREIGN_KEY &&
+ 0 == my_strcasecmp(system_charset_info, fk.foreign_id.str, drop->name))
+ drop_it.remove();
+ }
+ continue;
+ }
+ key= new (thd->mem_root) Foreign_key(fk, thd->mem_root);
+ if (!key || key->failed())
+ {
+ my_error(ER_OUT_OF_RESOURCES, MYF(0));
+ goto err;
+ }
+ // NB: add index component from table->s->keys below
+ key->ignore= true;
+ alter_info->tmp_old_fkeys++;
+ if (new_key_list.push_back(key, thd->mem_root))
+ {
+ my_error(ER_OUT_OF_RESOURCES, MYF(0));
+ goto err;
+ }
+ if (alter_ctx->is_table_renamed())
+ {
+ if (0 == cmp_table(fk.ref_db(), table->s->db) &&
+ 0 == cmp_table(fk.referenced_table, table->s->table_name))
+ {
+ key->ref_db= {NULL, 0};
+ key->ref_table= alter_ctx->new_name;
+ }
+ else
+ {
+ Table_name fk_table(fk.ref_table(thd->mem_root));
+ const FK_table_to_lock *x= fk_tables_to_lock.insert(fk_table);
+ if (!x)
+ goto err;
+ const_cast<FK_table_to_lock *>(x)->fail= true;
+ // Update foreign_table of referenced_keys. FRM write required.
+ if (alter_ctx->fk_renamed_table.push_back(fk_table))
+ goto err;
+ }
+ }
+ } // for (const FK_info &fk: table->s->foreign_keys)
+ if (alter_ctx->is_table_renamed())
+ {
+ for (const FK_info &rk: table->s->referenced_keys)
+ {
+ if (0 == cmp_table(rk.foreign_db, table->s->db) &&
+ 0 == cmp_table(rk.foreign_table, table->s->table_name))
+ continue;
+ Table_name rk_table(rk.for_table(thd->mem_root));
+ const FK_table_to_lock *x= fk_tables_to_lock.insert(rk_table);
+ if (!x)
+ goto err;
+ const_cast<FK_table_to_lock *>(x)->fail= true;
+ // Update referenced_table of foreign_keys. FRM write required.
+ if (alter_ctx->rk_renamed_table.push_back(rk_table))
+ goto err;
+ }
+ }
+ /*
Collect all keys which isn't in drop list. Add only those
for which some fields exists.
*/
+ key_info= table->key_info;
for (uint i=0 ; i < table->s->keys ; i++,key_info++)
{
bool long_hash_key= false;
@@ -8051,9 +8350,43 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
Key *key;
while ((key=key_it++)) // Add new keys
{
- if (key->type == Key::FOREIGN_KEY &&
- ((Foreign_key *)key)->validate(new_create_list))
- goto err;
+ if (key->foreign)
+ {
+ Foreign_key *fk= static_cast<Foreign_key*>(key);
+ if (fk->validate(new_create_list))
+ goto err;
+ // self-references have no ref_table and ref_db
+ DBUG_ASSERT(fk->ref_table.str || fk->ref_db.str);
+ if (fk->ref_table.str)
+ {
+ Table_name t(fk->ref_db.str ? fk->ref_db : table->s->db,
+ fk->ref_table);
+ if (lower_case_table_names)
+ t.lowercase(thd->mem_root);
+ if (0 != cmp_table(t.db, table->s->db) ||
+ 0 != cmp_table(t.name, table->s->table_name))
+ {
+ if (alter_ctx->fk_added.push_back({t, fk}))
+ goto err;
+ const FK_table_to_lock *x= fk_tables_to_lock.insert(t);
+ if (!x)
+ goto err;
+ const_cast<FK_table_to_lock *>(x)->fail= true;
+ }
+ }
+ if (key->name.str)
+ {
+ for (const Key &k: new_key_list)
+ {
+ if (k.foreign && k.name.str && 0 == cmp_ident(k.name, key->name))
+ {
+ my_error(ER_DUP_CONSTRAINT_NAME, MYF(0), "FOREIGN KEY",
+ k.name.str);
+ goto err;
+ }
+ }
+ }
+ }
new_key_list.push_back(key, thd->mem_root);
if (key->name.str &&
!my_strcasecmp(system_charset_info, key->name.str,
@@ -8177,13 +8510,12 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
}
}
- if (!alter_info->check_constraint_list.is_empty())
+ if (!alter_info->check_constraint_list.is_empty() &&
+ !table->s->foreign_keys.is_empty())
{
/* Check the table FOREIGN KEYs for name duplications. */
- List <FOREIGN_KEY_INFO> fk_child_key_list;
FOREIGN_KEY_INFO *f_key;
- table->file->get_foreign_key_list(thd, &fk_child_key_list);
- List_iterator<FOREIGN_KEY_INFO> fk_key_it(fk_child_key_list);
+ List_iterator<FOREIGN_KEY_INFO> fk_key_it(table->s->foreign_keys);
while ((f_key= fk_key_it++))
{
List_iterator_fast<Virtual_column_info>
@@ -8194,8 +8526,8 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
if (!check->name.length || check->automatic_name)
continue;
- if (check->name.length == f_key->foreign_id->length &&
- my_strcasecmp(system_charset_info, f_key->foreign_id->str,
+ if (check->name.length == f_key->foreign_id.length &&
+ my_strcasecmp(system_charset_info, f_key->foreign_id.str,
check->name.str) == 0)
{
my_error(ER_DUP_CONSTRAINT_NAME, MYF(0), "CHECK", check->name.str);
@@ -8210,21 +8542,56 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
if (alter_info->drop_list.elements)
{
- Alter_drop *drop;
- drop_it.rewind();
- while ((drop=drop_it++)) {
- switch (drop->type) {
- case Alter_drop::KEY:
- case Alter_drop::COLUMN:
- case Alter_drop::CHECK_CONSTRAINT:
- case Alter_drop::PERIOD:
- my_error(ER_CANT_DROP_FIELD_OR_KEY, MYF(0), drop->type_name(),
- alter_info->drop_list.head()->name);
+ my_error(ER_CANT_DROP_FIELD_OR_KEY, MYF(0),
+ alter_info->drop_list.head()->type_name(),
+ alter_info->drop_list.head()->name);
+ goto err;
+ }
+
+ // FIXME: remove in MDEV-21052
+ alter_info->drop_list= alter_info->tmp_drop_list;
+
+ if (!fk_tables_to_lock.empty())
+ {
+ for (const FK_table_to_lock &t: fk_tables_to_lock)
+ {
+ MDL_request *req= new (thd->mem_root) MDL_request;
+ if (!req)
+ {
+ my_error(ER_OUT_OF_RESOURCES, MYF(0));
+ goto err;
+ }
+ MDL_REQUEST_INIT(req, MDL_key::TABLE, t.table.db.str, t.table.name.str,
+ MDL_INTENTION_EXCLUSIVE, MDL_STATEMENT);
+ alter_ctx->fk_mdl_reqs.push_front(req);
+ }
+ if (thd->mdl_context.acquire_locks(&alter_ctx->fk_mdl_reqs,
+ thd->variables.lock_wait_timeout))
+ {
+ push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE, ER_UNKNOWN_ERROR,
+ "Could not lock referenced tables");
+ goto err;
+ }
+ /** Preacquire shares to get ER_NO_SUCH_TABLE before copy data */
+ for (const FK_table_to_lock &t: fk_tables_to_lock)
+ {
+ TABLE_LIST tl;
+ tl.init_one_table(&t.table.db, &t.table.name, NULL, TL_IGNORE);
+ Share_acquire sa(thd, tl);
+ if (!sa.share)
+ {
+ if (!(t.fail && thd->variables.check_foreign()) && thd->is_error() &&
+ thd->get_stmt_da()->sql_errno() == ER_NO_SUCH_TABLE)
+ {
+ // skip non-existing referenced shares, allow ALTER
+ thd->clear_error();
+ continue;
+ }
goto err;
- case Alter_drop::FOREIGN_KEY:
- // Leave the DROP FOREIGN KEY names in the alter_info->drop_list.
- break;
}
+ if (!alter_ctx->fk_shares.insert(t.table, std::move(sa)))
+ goto err;
+ DBUG_ASSERT(!sa.share);
}
}
@@ -8333,11 +8700,11 @@ enum fk_column_change_type
static enum fk_column_change_type
fk_check_column_changes(THD *thd, Alter_info *alter_info,
- List<LEX_CSTRING> &fk_columns,
+ List<Lex_cstring> &fk_columns,
const char **bad_column_name)
{
- List_iterator_fast<LEX_CSTRING> column_it(fk_columns);
- LEX_CSTRING *column;
+ List_iterator_fast<Lex_cstring> column_it(fk_columns);
+ Lex_cstring *column;
*bad_column_name= NULL;
@@ -8427,167 +8794,157 @@ static bool fk_prepare_copy_alter_table(THD *thd, TABLE *table,
Alter_info *alter_info,
Alter_table_ctx *alter_ctx)
{
- List <FOREIGN_KEY_INFO> fk_parent_key_list;
- List <FOREIGN_KEY_INFO> fk_child_key_list;
FOREIGN_KEY_INFO *f_key;
DBUG_ENTER("fk_prepare_copy_alter_table");
- table->file->get_parent_foreign_key_list(thd, &fk_parent_key_list);
-
- /* OOM when building list. */
- if (unlikely(thd->is_error()))
- DBUG_RETURN(true);
-
- /*
- Remove from the list all foreign keys in which table participates as
- parent which are to be dropped by this ALTER TABLE. This is possible
- when a foreign key has the same table as child and parent.
- */
- List_iterator<FOREIGN_KEY_INFO> fk_parent_key_it(fk_parent_key_list);
-
- while ((f_key= fk_parent_key_it++))
+ if (!table->s->referenced_keys.is_empty())
{
- Alter_drop *drop;
- List_iterator_fast<Alter_drop> drop_it(alter_info->drop_list);
+ /*
+ Remove from the list all foreign keys in which table participates as
+ parent which are to be dropped by this ALTER TABLE. This is possible
+ when a foreign key has the same table as child and parent.
+ */
+ List_iterator<FOREIGN_KEY_INFO> fk_parent_key_it(table->s->referenced_keys);
- while ((drop= drop_it++))
+ while ((f_key= fk_parent_key_it++))
{
- /*
- InnoDB treats foreign key names in case-insensitive fashion.
- So we do it here too. For database and table name type of
- comparison used depends on lower-case-table-names setting.
- For l_c_t_n = 0 we use case-sensitive comparison, for
- l_c_t_n > 0 modes case-insensitive comparison is used.
- */
- if ((drop->type == Alter_drop::FOREIGN_KEY) &&
- (my_strcasecmp(system_charset_info, f_key->foreign_id->str,
- drop->name) == 0) &&
- (lex_string_cmp(table_alias_charset, f_key->foreign_db,
- &table->s->db) == 0) &&
- (lex_string_cmp(table_alias_charset, f_key->foreign_table,
- &table->s->table_name) == 0))
- fk_parent_key_it.remove();
+ Alter_drop *drop;
+ List_iterator_fast<Alter_drop> drop_it(alter_info->drop_list);
+
+ while ((drop= drop_it++))
+ {
+ /*
+ InnoDB treats foreign key names in case-insensitive fashion.
+ So we do it here too. For database and table name type of
+ comparison used depends on lower-case-table-names setting.
+ For l_c_t_n = 0 we use case-sensitive comparison, for
+ l_c_t_n > 0 modes case-insensitive comparison is used.
+ */
+ if ((drop->type == Alter_drop::FOREIGN_KEY) &&
+ (my_strcasecmp(system_charset_info, f_key->foreign_id.str,
+ drop->name) == 0) &&
+ (cmp_table(f_key->foreign_db, table->s->db) == 0) &&
+ (cmp_table(f_key->foreign_table, table->s->table_name) == 0))
+ fk_parent_key_it.remove();
+ }
}
- }
- /*
- If there are FKs in which this table is parent which were not
- dropped we need to prevent ALTER deleting rows from the table,
- as it might break referential integrity. OTOH it is OK to do
- so if foreign_key_checks are disabled.
- */
- if (!fk_parent_key_list.is_empty() &&
- !(thd->variables.option_bits & OPTION_NO_FOREIGN_KEY_CHECKS))
- alter_ctx->set_fk_error_if_delete_row(fk_parent_key_list.head());
+ /*
+ If there are FKs in which this table is parent which were not
+ dropped we need to prevent ALTER deleting rows from the table,
+ as it might break referential integrity. OTOH it is OK to do
+ so if foreign_key_checks are disabled.
+ */
+ if (!table->s->referenced_keys.is_empty() &&
+ !(thd->variables.option_bits & OPTION_NO_FOREIGN_KEY_CHECKS))
+ alter_ctx->set_fk_error_if_delete_row(table->s->referenced_keys.head());
- fk_parent_key_it.rewind();
- while ((f_key= fk_parent_key_it++))
- {
- enum fk_column_change_type changes;
- const char *bad_column_name;
+ fk_parent_key_it.rewind();
+ while ((f_key= fk_parent_key_it++))
+ {
+ enum fk_column_change_type changes;
+ const char *bad_column_name;
- changes= fk_check_column_changes(thd, alter_info,
- f_key->referenced_fields,
- &bad_column_name);
+ changes= fk_check_column_changes(thd, alter_info,
+ f_key->referenced_fields,
+ &bad_column_name);
- switch(changes)
- {
- case FK_COLUMN_NO_CHANGE:
- /* No significant changes. We can proceed with ALTER! */
- break;
- case FK_COLUMN_DATA_CHANGE:
- {
- char buff[NAME_LEN*2+2];
- strxnmov(buff, sizeof(buff)-1, f_key->foreign_db->str, ".",
- f_key->foreign_table->str, NullS);
- my_error(ER_FK_COLUMN_CANNOT_CHANGE_CHILD, MYF(0), bad_column_name,
- f_key->foreign_id->str, buff);
- DBUG_RETURN(true);
- }
- case FK_COLUMN_RENAMED:
- my_error(ER_ALTER_OPERATION_NOT_SUPPORTED_REASON, MYF(0),
- "ALGORITHM=COPY",
- ER_THD(thd, ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_FK_RENAME),
- "ALGORITHM=INPLACE");
- DBUG_RETURN(true);
- case FK_COLUMN_DROPPED:
- {
- StringBuffer<NAME_LEN*2+2> buff(system_charset_info);
- LEX_CSTRING *db= f_key->foreign_db, *tbl= f_key->foreign_table;
+ switch(changes)
+ {
+ case FK_COLUMN_NO_CHANGE:
+ /* No significant changes. We can proceed with ALTER! */
+ break;
+ case FK_COLUMN_DATA_CHANGE:
+ {
+ char buff[NAME_LEN*2+2];
+ strxnmov(buff, sizeof(buff)-1, f_key->foreign_db.str, ".",
+ f_key->foreign_table.str, NullS);
+ my_error(ER_FK_COLUMN_CANNOT_CHANGE_CHILD, MYF(0), bad_column_name,
+ f_key->foreign_id.str, buff);
+ DBUG_RETURN(true);
+ }
+ case FK_COLUMN_RENAMED:
+ my_error(ER_ALTER_OPERATION_NOT_SUPPORTED_REASON, MYF(0),
+ "ALGORITHM=COPY",
+ ER_THD(thd, ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_FK_RENAME),
+ "ALGORITHM=INPLACE");
+ DBUG_RETURN(true);
+ case FK_COLUMN_DROPPED:
+ {
+ StringBuffer<NAME_LEN*2+2> buff(system_charset_info);
+ LEX_CSTRING *db= &f_key->foreign_db, *tbl= &f_key->foreign_table;
- append_identifier(thd, &buff, db);
- buff.append('.');
- append_identifier(thd, &buff, tbl);
- my_error(ER_FK_COLUMN_CANNOT_DROP_CHILD, MYF(0), bad_column_name,
- f_key->foreign_id->str, buff.c_ptr());
- DBUG_RETURN(true);
- }
- default:
- DBUG_ASSERT(0);
+ append_identifier(thd, &buff, db);
+ buff.append('.');
+ append_identifier(thd, &buff, tbl);
+ my_error(ER_FK_COLUMN_CANNOT_DROP_CHILD, MYF(0), bad_column_name,
+ f_key->foreign_id.str, buff.c_ptr());
+ DBUG_RETURN(true);
+ }
+ default:
+ DBUG_ASSERT(0);
+ }
}
}
- table->file->get_foreign_key_list(thd, &fk_child_key_list);
-
- /* OOM when building list. */
- if (unlikely(thd->is_error()))
- DBUG_RETURN(true);
-
- /*
- Remove from the list all foreign keys which are to be dropped
- by this ALTER TABLE.
- */
- List_iterator<FOREIGN_KEY_INFO> fk_key_it(fk_child_key_list);
-
- while ((f_key= fk_key_it++))
+ if (!table->s->foreign_keys.is_empty())
{
- Alter_drop *drop;
- List_iterator_fast<Alter_drop> drop_it(alter_info->drop_list);
+ /*
+ Remove from the list all foreign keys which are to be dropped
+ by this ALTER TABLE.
+ */
+ List_iterator<FOREIGN_KEY_INFO> fk_key_it(table->s->foreign_keys);
- while ((drop= drop_it++))
+ while ((f_key= fk_key_it++))
{
- /* Names of foreign keys in InnoDB are case-insensitive. */
- if ((drop->type == Alter_drop::FOREIGN_KEY) &&
- (my_strcasecmp(system_charset_info, f_key->foreign_id->str,
- drop->name) == 0))
- fk_key_it.remove();
+ Alter_drop *drop;
+ List_iterator_fast<Alter_drop> drop_it(alter_info->drop_list);
+
+ while ((drop= drop_it++))
+ {
+ /* Names of foreign keys in InnoDB are case-insensitive. */
+ if ((drop->type == Alter_drop::FOREIGN_KEY) &&
+ (my_strcasecmp(system_charset_info, f_key->foreign_id.str,
+ drop->name) == 0))
+ fk_key_it.remove();
+ }
}
- }
- fk_key_it.rewind();
- while ((f_key= fk_key_it++))
- {
- enum fk_column_change_type changes;
- const char *bad_column_name;
+ fk_key_it.rewind();
+ while ((f_key= fk_key_it++))
+ {
+ enum fk_column_change_type changes;
+ const char *bad_column_name;
- changes= fk_check_column_changes(thd, alter_info,
- f_key->foreign_fields,
- &bad_column_name);
+ changes= fk_check_column_changes(thd, alter_info,
+ f_key->foreign_fields,
+ &bad_column_name);
- switch(changes)
- {
- case FK_COLUMN_NO_CHANGE:
- /* No significant changes. We can proceed with ALTER! */
- break;
- case FK_COLUMN_DATA_CHANGE:
- my_error(ER_FK_COLUMN_CANNOT_CHANGE, MYF(0), bad_column_name,
- f_key->foreign_id->str);
- DBUG_RETURN(true);
- case FK_COLUMN_RENAMED:
- my_error(ER_ALTER_OPERATION_NOT_SUPPORTED_REASON, MYF(0),
- "ALGORITHM=COPY",
- ER_THD(thd, ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_FK_RENAME),
- "ALGORITHM=INPLACE");
- DBUG_RETURN(true);
- case FK_COLUMN_DROPPED:
- my_error(ER_FK_COLUMN_CANNOT_DROP, MYF(0), bad_column_name,
- f_key->foreign_id->str);
- DBUG_RETURN(true);
- default:
- DBUG_ASSERT(0);
+ switch(changes)
+ {
+ case FK_COLUMN_NO_CHANGE:
+ /* No significant changes. We can proceed with ALTER! */
+ break;
+ case FK_COLUMN_DATA_CHANGE:
+ my_error(ER_FK_COLUMN_CANNOT_CHANGE, MYF(0), bad_column_name,
+ f_key->foreign_id.str);
+ DBUG_RETURN(true);
+ case FK_COLUMN_RENAMED:
+ my_error(ER_ALTER_OPERATION_NOT_SUPPORTED_REASON, MYF(0),
+ "ALGORITHM=COPY",
+ ER_THD(thd, ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_FK_RENAME),
+ "ALGORITHM=INPLACE");
+ DBUG_RETURN(true);
+ case FK_COLUMN_DROPPED:
+ my_error(ER_FK_COLUMN_CANNOT_DROP, MYF(0), bad_column_name,
+ f_key->foreign_id.str);
+ DBUG_RETURN(true);
+ default:
+ DBUG_ASSERT(0);
+ }
}
- }
+ } // if (table->s->foreign_keys)
/*
Normally, an attempt to modify an FK parent table will cause
@@ -8605,7 +8962,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->foreign)
continue;
Foreign_key *fk= static_cast<Foreign_key*>(key);
@@ -8629,6 +8986,7 @@ static bool fk_prepare_copy_alter_table(THD *thd, TABLE *table,
MDL_REQUEST_INIT(&mdl_request, MDL_key::TABLE, ref_db, ref_table,
MDL_SHARED_NO_WRITE, MDL_TRANSACTION);
+ // TODO: is it needed now?
if (thd->mdl_context.acquire_lock(&mdl_request,
thd->variables.lock_wait_timeout))
DBUG_RETURN(true);
@@ -8746,6 +9104,7 @@ simple_rename_or_index_change(THD *thd, TABLE_LIST *table_list,
if (likely(!error) && alter_ctx->is_table_renamed())
{
THD_STAGE_INFO(thd, stage_rename);
+ FK_rename_vector fk_rename_backup;
handlerton *old_db_type= table->s->db_type();
/*
Then do a 'simple' rename of the table. First we need to close all
@@ -8757,31 +9116,49 @@ simple_rename_or_index_change(THD *thd, TABLE_LIST *table_list,
*/
if (wait_while_table_is_used(thd, table, extra_func))
DBUG_RETURN(true);
+
+ if (fk_handle_rename(thd, table_list, &alter_ctx->new_db,
+ &alter_ctx->new_name, fk_rename_backup))
+ DBUG_RETURN(true);
+
close_all_tables_for_name(thd, table->s, HA_EXTRA_PREPARE_FOR_RENAME,
NULL);
if (mysql_rename_table(old_db_type, &alter_ctx->db, &alter_ctx->table_name,
- &alter_ctx->new_db, &alter_ctx->new_alias, 0))
+ &alter_ctx->new_db, &alter_ctx->new_name, 0))
error= -1;
else if (Table_triggers_list::change_table_name(thd,
&alter_ctx->db,
&alter_ctx->alias,
&alter_ctx->table_name,
&alter_ctx->new_db,
- &alter_ctx->new_alias))
+ &alter_ctx->new_name))
{
(void) mysql_rename_table(old_db_type,
- &alter_ctx->new_db, &alter_ctx->new_alias,
+ &alter_ctx->new_db, &alter_ctx->new_name,
&alter_ctx->db, &alter_ctx->table_name,
NO_FK_CHECKS);
error= -1;
}
/* Update stat tables last. This is to be able to handle rename of a stat table */
if (error == 0)
+ {
(void) rename_table_in_stat_tables(thd, &alter_ctx->db,
&alter_ctx->table_name,
&alter_ctx->new_db,
- &alter_ctx->new_alias);
+ &alter_ctx->new_name);
+ for (FK_rename_backup &bak: fk_rename_backup)
+ {
+ error= fk_install_shadow_frm(bak.old_name, bak.new_name);
+ if (error)
+ break;
+ }
+ }
+ else
+ {
+ for (FK_rename_backup &bak: fk_rename_backup)
+ bak.rollback();
+ }
}
if (likely(!error))
@@ -8919,6 +9296,7 @@ bool mysql_alter_table(THD *thd, const LEX_CSTRING *new_db,
bool engine_changed, error;
bool no_ha_table= true; /* We have not created table in storage engine yet */
TABLE *table, *new_table;
+ ulonglong option_bits_save= thd->variables.option_bits;
#ifdef WITH_PARTITION_STORAGE_ENGINE
bool partition_changed= false;
bool fast_alter_partition= false;
@@ -9306,8 +9684,6 @@ bool mysql_alter_table(THD *thd, const LEX_CSTRING *new_db,
List_iterator<Alter_drop> drop_it(alter_info->drop_list);
Alter_drop *drop;
- List <FOREIGN_KEY_INFO> fk_child_key_list;
- table->file->get_foreign_key_list(thd, &fk_child_key_list);
alter_info->flags&= ~ALTER_DROP_CHECK_CONSTRAINT;
@@ -9315,14 +9691,15 @@ bool mysql_alter_table(THD *thd, const LEX_CSTRING *new_db,
{
if (drop->type == Alter_drop::CHECK_CONSTRAINT)
{
+ if (!table->s->foreign_keys.is_empty())
{
/* Test if there is a FOREIGN KEY with this name. */
FOREIGN_KEY_INFO *f_key;
- List_iterator<FOREIGN_KEY_INFO> fk_key_it(fk_child_key_list);
+ List_iterator<FOREIGN_KEY_INFO> fk_key_it(table->s->foreign_keys);
while ((f_key= fk_key_it++))
{
- if (my_strcasecmp(system_charset_info, f_key->foreign_id->str,
+ if (my_strcasecmp(system_charset_info, f_key->foreign_id.str,
drop->name) == 0)
{
drop->type= Alter_drop::FOREIGN_KEY;
@@ -9447,6 +9824,7 @@ do_continue:;
#ifdef WITH_PARTITION_STORAGE_ENGINE
if (fast_alter_partition)
{
+ alter_ctx.fk_release_locks(thd);
/*
ALGORITHM and LOCK clauses are generally not allowed by the
parser for operations related to partitioning.
@@ -9599,10 +9977,12 @@ do_continue:;
error= create_table_impl(thd, (DDL_LOG_STATE*) 0, (DDL_LOG_STATE*) 0,
alter_ctx.db, alter_ctx.table_name,
alter_ctx.new_db, alter_ctx.tmp_name,
+ alter_ctx.new_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);
+ &key_info, &key_count, alter_ctx.foreign_keys,
+ alter_ctx.referenced_keys, &frm);
reenable_binlog(thd);
if (unlikely(error))
{
@@ -9612,7 +9992,7 @@ do_continue:;
if (alter_info->algorithm(thd) != Alter_info::ALTER_TABLE_ALGORITHM_COPY)
{
- Alter_inplace_info ha_alter_info(create_info, alter_info,
+ Alter_inplace_info ha_alter_info(create_info, alter_info, &alter_ctx,
key_info, key_count,
IF_PARTITIONING(thd->work_part_info, NULL),
ignore, alter_ctx.error_if_not_empty);
@@ -9741,6 +10121,7 @@ do_continue:;
cleanup_table_after_inplace_alter(&altered_table);
DBUG_RETURN(true);
}
+
cleanup_table_after_inplace_alter_keep_files(&altered_table);
goto end_inplace;
@@ -9793,7 +10174,7 @@ do_continue:;
if (ha_create_table(thd, alter_ctx.get_tmp_path(),
alter_ctx.new_db.str, alter_ctx.new_name.str,
- create_info, &frm))
+ create_info, alter_info, &frm))
goto err_new_table_cleanup;
/* Mark that we have created table in storage engine. */
@@ -9995,6 +10376,12 @@ do_continue:;
if (wait_while_table_is_used(thd, table, HA_EXTRA_PREPARE_FOR_RENAME))
goto err_new_table_cleanup;
+ if (alter_ctx.fk_handle_alter(thd))
+ // NB: now after lock upgrade it jumps to "err_with_mdl" as well
+ goto err_new_table_cleanup;
+
+ alter_ctx.fk_table_backup.commit();
+
close_all_tables_for_name(thd, table->s,
alter_ctx.is_table_renamed() ?
HA_EXTRA_PREPARE_FOR_RENAME:
@@ -10013,6 +10400,7 @@ do_continue:;
char backup_name_buff[FN_LEN];
LEX_CSTRING backup_name;
backup_name.str= backup_name_buff;
+ thd->variables.option_bits|= OPTION_NO_FOREIGN_KEY_CHECKS;
DBUG_PRINT("info", ("is_table_renamed: %d engine_changed: %d",
alter_ctx.is_table_renamed(), engine_changed));
@@ -10043,6 +10431,9 @@ do_continue:;
alter_ctx.table_name.str, (int) alter_ctx.table_name.length);
}
+ if (alter_ctx.fk_install_frms())
+ goto err_with_mdl;
+
// Rename the new table to the correct name.
if (mysql_rename_table(new_db_type, &alter_ctx.new_db, &alter_ctx.tmp_name,
&alter_ctx.new_db, &alter_ctx.new_alias,
@@ -10121,6 +10512,8 @@ do_continue:;
goto err_with_mdl_after_alter;
}
+ thd->variables.option_bits= option_bits_save;
+
end_inplace:
thd->variables.option_bits&= ~OPTION_BIN_COMMIT_OFF;
@@ -10137,7 +10530,7 @@ end_inplace:
if (!binlog_as_create_select)
{
if (write_bin_log_with_if_exists(thd, true, false, log_if_exists))
- DBUG_RETURN(true);
+ goto err_with_mdl;
}
table_list->table= NULL; // For query cache
query_cache_invalidate3(thd, table_list, false);
@@ -10191,6 +10584,9 @@ err_new_table_cleanup:
(FN_IS_TMP | (no_ha_table ? NO_HA_TABLE : 0)),
alter_ctx.get_tmp_path());
+ if (table->mdl_ticket && table->mdl_ticket->get_type() == MDL_EXCLUSIVE)
+ goto err_with_mdl;
+
DBUG_RETURN(true);
err_with_mdl_after_alter:
@@ -10207,6 +10603,9 @@ err_with_mdl_after_alter:
write_bin_log_with_if_exists(thd, FALSE, FALSE, log_if_exists);
err_with_mdl:
+ thd->variables.option_bits= option_bits_save;
+ alter_ctx.fk_rollback();
+
/*
An error happened while we were holding exclusive name metadata lock
on table being altered. To be safe under LOCK TABLES we should
@@ -10216,6 +10615,9 @@ err_with_mdl:
thd->locked_tables_list.unlink_all_closed_tables(thd, NULL, 0);
if (!table_list->table)
thd->mdl_context.release_all_locks_for_name(mdl_ticket);
+
+ alter_ctx.fk_release_locks(thd);
+
DBUG_RETURN(true);
}
@@ -11223,3 +11625,1015 @@ wsrep_error_label:
DBUG_RETURN(true);
#endif
}
+
+
+// Used in CREATE TABLE
+bool TABLE_SHARE::fk_handle_create(THD *thd, FK_create_vector &shares)
+{
+ if (foreign_keys.is_empty())
+ return false;
+
+ mbd::set<Table_name> tables;
+
+ for (FK_info &fk: foreign_keys)
+ {
+ if (!cmp_table(fk.ref_db(), db) && !cmp_table(fk.referenced_table, table_name))
+ continue; // subject table name is already prelocked by caller DDL
+ if (!tables.insert(fk.ref_table(thd->mem_root)))
+ return true;
+ }
+ if (tables.empty())
+ return false;
+ MDL_request_list mdl_list;
+ for (const Table_name &ref: tables)
+ {
+ MDL_request *req= new (thd->mem_root) MDL_request;
+ if (!req)
+ {
+ my_error(ER_OUT_OF_RESOURCES, MYF(0));
+ return true;
+ }
+ MDL_REQUEST_INIT(req, MDL_key::TABLE, ref.db.str, ref.name.str, MDL_EXCLUSIVE,
+ MDL_STATEMENT);
+ mdl_list.push_front(req);
+ }
+ if (thd->mdl_context.acquire_locks(&mdl_list, thd->variables.lock_wait_timeout))
+ return true;
+
+ shares.reserve(tables.size());
+
+ // update referenced_keys of ref_tables
+ for (const Table_name &ref: tables)
+ {
+ TABLE_LIST tl;
+ tl.init_one_table(&ref.db, &ref.name, NULL, TL_IGNORE);
+ Share_acquire ref_sa(thd, tl);
+ if (!ref_sa.share)
+ {
+ if (!thd->variables.check_foreign() && thd->is_error() &&
+ thd->get_stmt_da()->sql_errno() == ER_NO_SUCH_TABLE)
+ {
+ // skip non-existing referenced shares, allow CREATE
+ thd->clear_error();
+ continue;
+ }
+ return true;
+ }
+ else if (ref_sa.share->partitioned())
+ {
+ my_error(ER_FEATURE_NOT_SUPPORTED_WITH_PARTITIONING, MYF(0), "FOREIGN KEY");
+ return true;
+ }
+ if (shares.push_back(std::move(ref_sa)))
+ {
+ my_error(ER_OUT_OF_RESOURCES, MYF(0));
+ return true;
+ }
+ DBUG_ASSERT(!ref_sa.share);
+ if (!shares.back().sa.share)
+ return true; // ctor failed, share was released
+ }
+
+ for (FK_ddl_backup &ref: shares)
+ {
+ TABLE_SHARE *ref_share= ref.sa.share;
+ for (const FK_info &fk: foreign_keys)
+ {
+ // Find keys referencing the acquired share and add them to referenced_keys
+ if (cmp_table(fk.ref_db(), ref_share->db) ||
+ cmp_table(fk.referenced_table, ref_share->table_name))
+ continue;
+
+ FK_info *dst= fk.clone(&ref_share->mem_root);
+ if (!dst ||
+ ref_share->referenced_keys.push_back(dst, &ref_share->mem_root))
+ {
+ my_error(ER_OUT_OF_RESOURCES, MYF(0));
+ return true;
+ }
+ } // for (const FK_info &fk: foreign_keys)
+
+ if (ref_share->fk_write_shadow_frm())
+ return true;
+ } // for (ref_tables)
+
+ return false;
+}
+
+
+/** 1. Check referenced fields existence and type compatibility.
+
+ 2. Fix foreign and referenced fields case. Fields must be fixed before FRM is
+ written and thus we need to acquire referenced shares now and then later in
+ fk_handle_c6reate() for refs X-locking (and update their FRMs). Note that
+ X-locking is done differently for ALTER so we'd better avoid it here.
+*/
+static
+bool fk_prepare_create_table(THD *thd, Alter_info &alter_info, FK_list &foreign_keys)
+{
+ List_iterator_fast<Create_field> cl_it(alter_info.create_list);
+ mbd::map<Table_name, Share_acquire, Table_name_lt> ref_shares;
+ const bool check_foreign= thd->variables.check_foreign();
+
+ /** Preacquire shares */
+ for (const FK_info &fk: foreign_keys)
+ {
+ if (fk.self_ref())
+ continue;
+ Table_name ref(fk.ref_db(), fk.referenced_table);
+ if (lower_case_table_names)
+ ref .lowercase(thd->mem_root);
+ if (ref_shares.find(ref) != ref_shares.end())
+ continue;
+ TABLE_LIST tl;
+ tl.init_one_table(&ref.db, &ref.name, NULL, TL_IGNORE);
+ Share_acquire sa(thd, tl);
+ if (!sa.share)
+ {
+ if (!check_foreign && thd->is_error() &&
+ thd->get_stmt_da()->sql_errno() == ER_NO_SUCH_TABLE)
+ {
+ // skip non-existing referenced shares, allow CREATE
+ thd->clear_error();
+ continue;
+ }
+ my_error(ER_WRONG_FK_DEF, MYF(0), ref.name.str,
+ "referenced table not found");
+ return true;
+ }
+ if (!ref_shares.insert(ref, std::move(sa)))
+ {
+ my_error(ER_OUT_OF_RESOURCES, MYF(0));
+ return true;
+ }
+ DBUG_ASSERT(!sa.share);
+ }
+
+ for (FK_info &fk: foreign_keys)
+ {
+ DBUG_ASSERT(fk.foreign_fields.elements == fk.referenced_fields.elements);
+ List_iterator_fast<Lex_cstring> rf_it(fk.referenced_fields);
+ for (Lex_cstring &ff: fk.foreign_fields)
+ {
+ TABLE_SHARE *ref_share= NULL;
+ if (!fk.self_ref())
+ {
+ Table_name ref(fk.ref_db(), fk.referenced_table);
+ auto ref_it= ref_shares.find(ref);
+ if (!check_foreign && ref_it == ref_shares.end())
+ continue;
+ DBUG_ASSERT(ref_it != ref_shares.end());
+ ref_share= ref_it->second.share;
+ DBUG_ASSERT(ref_share);
+ }
+ Lex_cstring &rf= *(rf_it++);
+ Create_field *cf;
+ cl_it.rewind();
+ while ((cf= cl_it++))
+ {
+ if (0 == cmp_ident(cf->field_name, ff))
+ break;
+ }
+ if (!cf)
+ {
+ my_error(ER_WRONG_FK_DEF, MYF(0), ff.str, "foreign field not found");
+ return true;
+ }
+ // NB: two variants non-self-ref/self-ref, two types Field/Create_field
+ if (ref_share)
+ {
+ Field *ref_field= ref_share->find_field_by_name(rf);
+ if (!ref_field)
+ {
+ if (!check_foreign)
+ continue;
+ my_error(ER_WRONG_FK_DEF, MYF(0), rf.str,
+ "referenced field not found");
+ return true;
+ }
+ // Do we really need cmp_type() and not result_type() here?
+ if (cf->cmp_type() != ref_field->cmp_type())
+ {
+ if (!check_foreign)
+ continue;
+ my_error(ER_WRONG_FK_DEF, MYF(0), ff.str,
+ "foreign-referenced fields type mismatch");
+ return true;
+ }
+ /* NB: case may be different. Let's store correct case. */
+ if (rf.strdup(thd->mem_root, LEX_STRING_WITH_LEN(ref_field->field_name)))
+ {
+ my_error(ER_OUT_OF_RESOURCES, MYF(0));
+ return true;
+ }
+ }
+ else
+ {
+ Create_field *ref_field;
+ cl_it.rewind();
+ while ((ref_field= cl_it++))
+ {
+ if (0 == cmp_ident(ref_field->field_name, rf))
+ break;
+ }
+ // NB: following code is 1-to-1 as if branch, only with Create_field type
+ if (!ref_field)
+ {
+ if (!check_foreign)
+ continue;
+ my_error(ER_WRONG_FK_DEF, MYF(0), rf.str,
+ "referenced field not found");
+ return true;
+ }
+ // Do we really need cmp_type() and not result_type() here?
+ if (cf->cmp_type() != ref_field->cmp_type())
+ {
+ if (!check_foreign)
+ continue;
+ my_error(ER_WRONG_FK_DEF, MYF(0), ff.str,
+ "foreign-referenced fields type mismatch");
+ return true;
+ }
+ /* NB: case may be different. Let's store correct case. */
+ if (rf.strdup(thd->mem_root, LEX_STRING_WITH_LEN(ref_field->field_name)))
+ {
+ my_error(ER_OUT_OF_RESOURCES, MYF(0));
+ return true;
+ }
+ } // else (!ref_share)
+ /* NB: case may be different. Let's store correct case. */
+ if (ff.strdup(thd->mem_root, LEX_STRING_WITH_LEN(cf->field_name)))
+ {
+ my_error(ER_OUT_OF_RESOURCES, MYF(0));
+ return true;
+ }
+ } // for (ff)
+ } // for (fk)
+ return false;
+}
+
+
+/**
+ @brief Used in ALTER TABLE. Prepares data for conducting update on relates shares
+ foreign_keys/referenced_keys which is done by fk_handle_alter().
+
+ Updates table's share as well. This is needed for prepare_create_table() and
+ for InnoDB engine which doesn't flush foreign cache on inplace alter.
+
+
+ @param[in] def Rename column action
+ @param[out] fk_tables_to_lock Referenced/foreign tables to be locked by
+ mysql_prepare_alter_table()
+
+ @return Error status
+*/
+
+bool Alter_table_ctx::fk_prepare_rename(THD *thd, TABLE *table, Create_field *def,
+ mbd::set<FK_table_to_lock> &fk_tables_to_lock)
+{
+ Table_name altered_table(table->s->db, table->s->table_name);
+ for (const FK_info &fk: table->s->foreign_keys)
+ {
+ if (0 == cmp_table(fk.ref_db(), table->s->db) &&
+ 0 == cmp_table(fk.referenced_table, table->s->table_name))
+ continue;
+ Table_name referenced_table(fk.ref_table(thd->mem_root));
+ for (Lex_cstring &fld: fk.foreign_fields)
+ {
+ if (0 == cmp_ident(fld, def->change))
+ {
+ fld= def->field_name;
+ /* Update foreign_fields of referenced tables.
+ No FRM write required. */
+ if (!fk_renamed_cols.insert({
+ referenced_table, altered_table, def->change, def->field_name}))
+ return true;
+ const FK_table_to_lock *x= fk_tables_to_lock.insert(referenced_table);
+ if (!x)
+ return true;
+ const_cast<FK_table_to_lock *>(x)->fail= true;
+ }
+ }
+ }
+ // NB: prepare_create_table() requires foreign_keys updated (see validate())
+ for (FK_info &fk: table->s->foreign_keys)
+ {
+ for (Lex_cstring &fld: fk.foreign_fields)
+ {
+ if (0 == cmp_ident(fld, def->change))
+ {
+ if (fld.strdup(&table->s->mem_root, def->field_name))
+ return true;
+ }
+ }
+ if (0 != cmp_table(fk.ref_db(), table->s->db) ||
+ 0 != cmp_table(fk.referenced_table, table->s->table_name))
+ continue;
+ for (Lex_cstring &fld: fk.referenced_fields)
+ {
+ if (0 == cmp_ident(fld, def->change))
+ {
+ if (fld.strdup(&table->s->mem_root, def->field_name))
+ return true;
+ }
+ }
+ }
+ for (const FK_info &rk: table->s->referenced_keys)
+ {
+ if (0 == cmp_table(rk.foreign_db, table->s->db) &&
+ 0 == cmp_table(rk.foreign_table, table->s->table_name))
+ continue;
+ Table_name foreign_table(rk.for_table(thd->mem_root));
+ for (Lex_cstring &fld: rk.referenced_fields)
+ {
+ if (0 == cmp_ident(fld, def->change))
+ {
+ fld= def->field_name;
+ /* Update referenced_fields of foreign tables.
+ FRM write is required in this case. */
+ if (!rk_renamed_cols.insert({
+ foreign_table, altered_table, def->change, def->field_name}))
+ return true;
+ const FK_table_to_lock *x= fk_tables_to_lock.insert(foreign_table);
+ if (!x)
+ return true;
+ const_cast<FK_table_to_lock *>(x)->fail= true;
+ }
+ }
+ }
+ // NB: prepare_create_table() doesn't require referenced_keys updated,
+ // but we keep consistency.
+ for (FK_info &rk: table->s->referenced_keys)
+ {
+ if (0 == cmp_table(rk.foreign_db, table->s->db) ||
+ 0 == cmp_table(rk.foreign_table, table->s->table_name))
+ {
+ for (Lex_cstring &fld: rk.foreign_fields)
+ {
+ if (0 == cmp_ident(fld, def->change))
+ {
+ if (fld.strdup(&table->s->mem_root, def->field_name))
+ return true;
+ }
+ }
+ }
+ if (0 != cmp_table(rk.ref_db(), table->s->db) ||
+ 0 != cmp_table(rk.referenced_table, table->s->table_name))
+ continue;
+ for (Lex_cstring &fld: rk.referenced_fields)
+ {
+ if (0 == cmp_ident(fld, def->change))
+ {
+ if (fld.strdup(&table->s->mem_root, def->field_name))
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+bool Alter_table_ctx::fk_handle_alter(THD *thd)
+{
+ mbd::set<TABLE_SHARE *> shares_to_write; // write FRMs to disk
+
+ DBUG_ASSERT(thd->mdl_context.is_lock_owner(MDL_key::TABLE, db.str,
+ table_name.str, MDL_EXCLUSIVE));
+
+
+ MDL_request_list::Iterator it(fk_mdl_reqs);
+ while (MDL_request *req= it++)
+ {
+ if (thd->mdl_context.upgrade_shared_lock(req->ticket, MDL_EXCLUSIVE,
+ thd->variables.lock_wait_timeout))
+ return true;
+ }
+
+ /* Update foreign_fields of referenced tables. No FRM write required. */
+ for (const FK_rename_col &ren_col: fk_renamed_cols)
+ {
+ auto i= fk_shares.find(ren_col.table);
+ if (i == fk_shares.end())
+ {
+ DBUG_ASSERT(!thd->variables.check_foreign());
+ continue;
+ }
+ Share_acquire &ref_table= i->second;
+ if (!ref_table.share)
+ return true;
+ TABLE_SHARE *ref_share= ref_table.share;
+ if (!fk_add_backup(ref_share))
+ return true;
+ for (FK_info &rk: ref_share->referenced_keys)
+ {
+ if (0 != ren_col.altered_table.cmp({rk.foreign_db, rk.foreign_table}))
+ continue;
+ for (Lex_cstring &col: rk.foreign_fields)
+ {
+ if (0 != cmp_ident(col, ren_col.col_name))
+ continue;
+ if (col.strdup(&ref_share->mem_root, ren_col.new_name))
+ {
+ my_error(ER_OUT_OF_RESOURCES, MYF(0));
+ return true;
+ }
+ }
+ }
+ }
+
+ /* Update referenced_fields of foreign tables. FRM write is required. */
+ for (const FK_rename_col &ren_col: rk_renamed_cols)
+ {
+ auto i= fk_shares.find(ren_col.table);
+ if (i == fk_shares.end())
+ {
+ DBUG_ASSERT(!thd->variables.check_foreign());
+ continue;
+ }
+ Share_acquire &fk_table= i->second;
+ if (!fk_table.share)
+ return true;
+ TABLE_SHARE *fk_share= fk_table.share;
+ FK_ref_backup *ref_bak= fk_add_backup(fk_share);
+ if (!ref_bak)
+ return true;
+ bool modified= false;
+ for (FK_info &fk: fk_share->foreign_keys)
+ {
+ if (0 != ren_col.altered_table.cmp({fk.referenced_db, fk.referenced_table}))
+ continue;
+ for (Lex_cstring &col: fk.referenced_fields)
+ {
+ if (0 != cmp_ident(col, ren_col.col_name))
+ continue;
+ if (col.strdup(&fk_share->mem_root, ren_col.new_name))
+ {
+ my_error(ER_OUT_OF_RESOURCES, MYF(0));
+ return true;
+ }
+ modified= true;
+ }
+ }
+ if (!modified)
+ continue;
+ if (!shares_to_write.insert(fk_share))
+ return true;
+ ref_bak->install_shadow= true;
+ }
+
+ /* Add new referenced_keys to referenced tables. FRM write is required. */
+
+ // Remove existing keys from fk_list, keep only newly added:
+ FK_list new_foreign_keys(foreign_keys);
+ size_t old_fkeys= foreign_keys.elements - fk_added.size();
+ for (uint i= 0; i < old_fkeys; ++i)
+ new_foreign_keys.pop();
+
+ for (const FK_add_new &new_fk: fk_added)
+ {
+ auto i= fk_shares.find(new_fk.ref);
+ if (i == fk_shares.end())
+ {
+ DBUG_ASSERT(!thd->variables.check_foreign());
+ continue;
+ }
+ Share_acquire &ref_table= i->second;
+ if (!ref_table.share)
+ return true;
+ TABLE_SHARE *ref_share= ref_table.share;
+ if (ref_share->partitioned())
+ {
+ my_error(ER_FEATURE_NOT_SUPPORTED_WITH_PARTITIONING, MYF(0), "FOREIGN KEY");
+ return true;
+ }
+ FK_ref_backup *ref_bak= fk_add_backup(ref_share);
+ if (!ref_bak)
+ return true;
+ ref_bak->install_shadow= true;
+ // Find prepared FK in fk_list. If ID exists, use it.
+ FK_info *fk;
+ List_iterator<FK_info> fk_it(new_foreign_keys);
+ DBUG_ASSERT(new_fk.fk->constraint_name.str);
+ while ((fk= fk_it++))
+ {
+ if (0 == cmp_ident(fk->foreign_id, new_fk.fk->constraint_name))
+ {
+ fk_it.remove();
+ break;
+ }
+ }
+ DBUG_ASSERT(fk);
+
+ // Found matched FK. Now let's add it to referenced table.
+ FK_info *dst= fk->clone(&ref_share->mem_root);
+ if (!dst ||
+ ref_share->referenced_keys.push_back(dst, &ref_share->mem_root))
+ {
+ my_error(ER_OUT_OF_RESOURCES, MYF(0));
+ return true;
+ }
+
+ if (!shares_to_write.insert(ref_share))
+ return true;
+ } // for (const FK_add_new &new_fk: fk_added_new)
+
+ /* Remove dropped referenced_keys in referenced tables. FRM write is required. */
+ for (const FK_drop_old &dropped_fk: fk_dropped)
+ {
+ auto i= fk_shares.find(dropped_fk.ref);
+ if (i == fk_shares.end())
+ continue;
+ Share_acquire &ref_table= i->second;
+ if (!ref_table.share)
+ return true;
+ TABLE_SHARE *ref_share= ref_table.share;
+ FK_ref_backup *ref_bak= fk_add_backup(ref_share);
+ if (!ref_bak)
+ return true;
+ FK_info *rk;
+ List_iterator<FK_info> ref_it(ref_share->referenced_keys);
+ while ((rk= ref_it++))
+ {
+ if (cmp_ident(rk->foreign_id, dropped_fk.fk->foreign_id))
+ continue;
+ ref_it.remove();
+ break;
+ }
+ if (!rk)
+ continue;
+ if (!shares_to_write.insert(ref_share))
+ return true;
+ ref_bak->install_shadow= true;
+ }
+
+ /* Handle table rename. FRM write is required. */
+ for (const Table_name &ref: fk_renamed_table)
+ {
+ DBUG_ASSERT(is_table_renamed());
+ auto i= fk_shares.find(ref);
+ if (i == fk_shares.end())
+ {
+ DBUG_ASSERT(!thd->variables.check_foreign());
+ continue;
+ }
+ Share_acquire &ref_table= i->second;
+ if (!ref_table.share)
+ return true;
+ TABLE_SHARE *ref_share= ref_table.share;
+ FK_ref_backup *ref_bak= fk_add_backup(ref_share);
+ if (!ref_bak)
+ return true;
+ // Update foreign_table of referenced_keys.
+ for (FK_info &rk: ref_share->referenced_keys)
+ {
+ if (0 == cmp_table(rk.foreign_db, db) &&
+ 0 == cmp_table(rk.foreign_table, table_name))
+ {
+ if (is_database_changed() &&
+ rk.foreign_db.strdup(&ref_share->mem_root, new_db))
+ {
+ my_error(ER_OUT_OF_RESOURCES, MYF(0));
+ return true;
+ }
+ if (new_name.str != table_name.str &&
+ rk.foreign_table.strdup(&ref_share->mem_root, new_name))
+ {
+ my_error(ER_OUT_OF_RESOURCES, MYF(0));
+ return true;
+ }
+ }
+ }
+ if (!shares_to_write.insert(ref_share))
+ return true;
+ ref_bak->install_shadow= true;
+ } // for (const Table_name &ref: fk_renamed_table)
+
+ for (const Table_name &ref: rk_renamed_table)
+ {
+ DBUG_ASSERT(is_table_renamed());
+ auto i= fk_shares.find(ref);
+ if (i == fk_shares.end())
+ {
+ DBUG_ASSERT(!thd->variables.check_foreign());
+ continue;
+ }
+ Share_acquire &fk_table= i->second;
+ if (!fk_table.share)
+ return true;
+ TABLE_SHARE *fk_share= fk_table.share;
+ FK_ref_backup *ref_bak= fk_add_backup(fk_share);
+ if (!ref_bak)
+ return true;
+ // Update referenced_table of foreign_keys.
+ for (FK_info &fk: fk_share->foreign_keys)
+ {
+ if (0 == cmp_table(fk.ref_db(), db) &&
+ 0 == cmp_table(fk.referenced_table, table_name))
+ {
+ if (is_database_changed() &&
+ fk.referenced_db.strdup(&fk_share->mem_root, new_db))
+ {
+ my_error(ER_OUT_OF_RESOURCES, MYF(0));
+ return true;
+ }
+ if (new_name.str != table_name.str &&
+ fk.referenced_table.strdup(&fk_share->mem_root, new_name))
+ {
+ my_error(ER_OUT_OF_RESOURCES, MYF(0));
+ return true;
+ }
+ }
+ }
+ if (!shares_to_write.insert(fk_share))
+ return true;
+ ref_bak->install_shadow= true;
+ } // for (const Table_name &ref: rk_renamed_table)
+
+ /* Update EXTRA2_FOREIGN_KEY_INFO section in FRM files. */
+ for (TABLE_SHARE *s: shares_to_write)
+ {
+ if (s->fk_write_shadow_frm())
+ return true;
+ }
+
+ return false;
+}
+
+
+FK_ref_backup* Alter_table_ctx::fk_add_backup(TABLE_SHARE *share)
+{
+ FK_ref_backup fk_bak;
+ if (fk_bak.init(share))
+ return NULL;
+ auto found= fk_ref_backup.find(share);
+ if (found != fk_ref_backup.end())
+ return &found->second;
+ return fk_ref_backup.insert(share, fk_bak);
+}
+
+
+void Alter_table_ctx::fk_rollback()
+{
+ for (auto &key_val: fk_ref_backup)
+ {
+ FK_ref_backup *ref_bak= const_cast<FK_ref_backup *>(&key_val.second);
+ if (ref_bak->install_shadow)
+ ref_bak->share->fk_drop_shadow_frm();
+ ref_bak->rollback();
+ }
+}
+
+
+void Alter_table_ctx::fk_release_locks(THD* thd)
+{
+ fk_ref_backup.clear();
+ if (fk_table_backup.share)
+ fk_table_backup.rollback();
+
+ MDL_request_list::Iterator it(fk_mdl_reqs);
+ while (MDL_request *req= it++)
+ {
+ if (req->ticket->get_type() == MDL_EXCLUSIVE)
+ thd->mdl_context.release_all_locks_for_name(req->ticket);
+ }
+}
+
+
+bool Alter_table_ctx::fk_install_frms()
+{
+ for (auto &key_val: fk_ref_backup)
+ {
+ FK_ref_backup *ref_bak= const_cast<FK_ref_backup *>(&key_val.second);
+ DBUG_ASSERT(ref_bak->share);
+ if (ref_bak->install_shadow && ref_bak->share->fk_install_shadow_frm())
+ return true;
+ }
+ return false;
+}
+
+
+/* Used in DROP TABLE: remove table from referenced_keys of referenced tables,
+ prohibit if foreign_keys is not empty. */
+static
+bool fk_handle_drop(THD *thd, TABLE_LIST *table, mbd::vector<FK_ddl_backup> &shares,
+ bool drop_db)
+{
+ DBUG_ASSERT(thd->mdl_context.is_lock_owner(MDL_key::TABLE, table->db.str,
+ table->table_name.str,
+ MDL_INTENTION_EXCLUSIVE));
+ DBUG_ASSERT(!table->view);
+ Share_acquire sa(thd, *table, GTS_FK_SHALLOW_HINTS);
+ if (!sa.share)
+ {
+ // We drop the table even if we can't read it (main.show_check)
+ thd->clear_error();
+ return false;
+ }
+ TABLE_SHARE *share= sa.share;
+ if (thd->variables.check_foreign())
+ {
+ for (const FK_info &rk: share->referenced_keys)
+ {
+ // fail DROP TABLE if other tables reference it
+ if (0 != cmp_table(rk.foreign_db, table->db) ||
+ (!drop_db && 0 != cmp_table(rk.foreign_table, table->table_name)))
+ {
+ // NB: we get ((null)) in foreign_id for GTS_FK_SHALLOW_HINTS
+ my_error(ER_ROW_IS_REFERENCED_2, MYF(0), rk.foreign_id.str);
+ return true;
+ }
+ }
+ }
+ if (share->foreign_keys.is_empty())
+ return false;
+ mbd::set<Table_name> tables;
+ for (const FK_info &fk: share->foreign_keys)
+ {
+ if (0 == cmp_table(fk.ref_db(), table->db) &&
+ (drop_db || 0 == cmp_table(fk.referenced_table, table->table_name)))
+ continue;
+ if (!tables.insert(fk.ref_table(thd->mem_root)))
+ return true;
+ }
+ if (tables.empty())
+ return false;
+ MDL_request_list mdl_list;
+ for (const Table_name &ref: tables)
+ {
+ MDL_request *req= new (thd->mem_root) MDL_request;
+ if (!req)
+ {
+ my_error(ER_OUT_OF_RESOURCES, MYF(0));
+ return true;
+ }
+ MDL_REQUEST_INIT(req, MDL_key::TABLE, ref.db.str, ref.name.str, MDL_EXCLUSIVE,
+ MDL_STATEMENT);
+ mdl_list.push_front(req);
+ }
+ if (thd->mdl_context.acquire_locks(&mdl_list, thd->variables.lock_wait_timeout))
+ return true;
+
+ // NB: we don't want needless reallocs and reconstruction of objects inside the loop
+ shares.reserve(tables.size());
+
+ for (const Table_name &ref: tables)
+ {
+ TABLE_LIST tl;
+ tl.init_one_table(&ref.db, &ref.name, &ref.name, TL_IGNORE);
+ Share_acquire ref_sa(thd, tl);
+ if (!ref_sa.share)
+ {
+ // skip non-existing referenced shares, allow DROP
+ thd->clear_error();
+ continue;
+ }
+ if (shares.push_back(FK_ddl_backup(std::move(ref_sa))))
+ {
+ my_error(ER_OUT_OF_RESOURCES, MYF(0));
+ return true;
+ }
+ DBUG_ASSERT(!ref_sa.share);
+ if (!shares.back().sa.share)
+ return true; // ctor failed, share was released
+ }
+
+ List_iterator<FK_info> ref_it;
+
+ // NB: another loop separates share acquisition which may fail
+ for (FK_ddl_backup &ref: shares)
+ {
+ ref_it.init(ref.sa.share->referenced_keys);
+ while (FK_info *rk= ref_it++)
+ {
+ if (0 == share->cmp_db_table(rk->foreign_db, rk->foreign_table))
+ {
+ // remove dropped table from referenced share
+ ref_it.remove();
+ }
+ }
+ int err= ref.sa.share->fk_write_shadow_frm();
+ if (err)
+ {
+ if (err > 2)
+ return true;
+ // ignore non-existent frm (main.drop_table_force, Test6)
+ thd->clear_error();
+ ref.sa.release();
+ }
+ }
+
+ return false;
+}
+
+
+/* Used in RENAME TABLE
+ Rename table in foreign_keys of this and referenced tables.
+ Rename table in referenced_keys of this and foreign tables.
+ In case of failed operation everything must reverted back.
+*/
+bool fk_handle_rename(THD *thd, TABLE_LIST *old_table, const LEX_CSTRING *new_db,
+ const LEX_CSTRING *new_table_name,
+ FK_rename_vector &fk_rename_backup)
+{
+ DBUG_ASSERT(thd->mdl_context.is_lock_owner(MDL_key::TABLE, old_table->db.str,
+ old_table->table_name.str,
+ MDL_INTENTION_EXCLUSIVE));
+ DBUG_ASSERT(!old_table->view);
+ /* NB: we have to acquire share before rename because it must read referenced
+ keys from foreign table by its old name. */
+ Share_acquire sa(thd, *old_table);
+ if (sa.is_error(thd))
+ return thd->is_error();
+ sa.flush_unused= true;
+ TABLE_SHARE *share= sa.share;
+ if (share->foreign_keys.is_empty() && share->referenced_keys.is_empty())
+ return false;
+ mbd::set<Table_name> tables;
+ MDL_request_list mdl_list;
+ for (FK_info &fk: share->foreign_keys)
+ {
+ if (fk.foreign_db.strdup(&share->mem_root, *new_db) ||
+ fk.foreign_table.strdup(&share->mem_root, *new_table_name))
+ goto mem_error;
+ if (0 == cmp_table(fk.ref_db(), old_table->db) &&
+ 0 == cmp_table(fk.referenced_table, old_table->table_name))
+ {
+ // NB: we don't have to lock self-references but we have to update share
+ if (0 != cmp_table(old_table->db, *new_db) &&
+ fk.referenced_db.strdup(&share->mem_root, *new_db))
+ goto mem_error;
+ if (fk.referenced_table.strdup(&share->mem_root, *new_table_name))
+ goto mem_error;
+ continue;
+ }
+ if (!tables.insert(fk.ref_table(thd->mem_root)))
+ goto mem_error;
+ }
+ for (FK_info &rk: share->referenced_keys)
+ {
+ if (rk.self_ref())
+ {
+ /*
+ NB: referenced_keys holds the same pointer as foreign_keys for self-refs
+ (see Foreign_key_io::parse()), so we already renamed it to new name
+ in share->foreign_keys above. Just skip it here.
+ */
+ DBUG_ASSERT(0 == cmp_table(*new_db, rk.foreign_db));
+ DBUG_ASSERT(0 == cmp_table(*new_table_name, rk.foreign_table));
+ continue;
+ }
+ if (0 != cmp_table(old_table->db, *new_db) &&
+ rk.referenced_db.strdup(&share->mem_root, *new_db))
+ goto mem_error;
+ if (rk.referenced_table.strdup(&share->mem_root, *new_table_name))
+ goto mem_error;
+ if (0 == cmp_table(rk.foreign_db, old_table->db) &&
+ 0 == cmp_table(rk.foreign_table, old_table->table_name))
+ {
+ if (rk.foreign_db.strdup(&share->mem_root, *new_db) ||
+ rk.foreign_table.strdup(&share->mem_root, *new_table_name))
+ goto mem_error;
+ continue;
+ }
+ if (!tables.insert(rk.for_table(thd->mem_root)))
+ goto mem_error;
+ }
+
+ if (share->fk_write_shadow_frm())
+ return true;
+
+ // NB: share is closed before rename, we can't store it into fk_rename_backup
+ fk_rename_backup.push_back({{old_table->db, old_table->table_name},
+ {*new_db, *new_table_name}});
+
+ if (tables.empty())
+ return false;
+
+ if (thd->mdl_context.upgrade_shared_lock(
+ old_table->mdl_request.ticket, MDL_EXCLUSIVE,
+ thd->variables.lock_wait_timeout))
+ return true;
+
+ for (const Table_name &ref: tables)
+ {
+ MDL_request *req= new (thd->mem_root) MDL_request;
+ if (!req)
+ goto mem_error;
+ MDL_REQUEST_INIT(req, MDL_key::TABLE, ref.db.str, ref.name.str, MDL_EXCLUSIVE,
+ MDL_STATEMENT);
+ mdl_list.push_front(req);
+ }
+ if (thd->mdl_context.acquire_locks(&mdl_list, thd->variables.lock_wait_timeout))
+ return true;
+
+ fk_rename_backup.reserve(1 + tables.size());
+
+ for (const Table_name &ref: tables)
+ {
+ TABLE_LIST tl;
+ tl.init_one_table(&ref.db, &ref.name, &ref.name, TL_IGNORE);
+ Share_acquire ref_sa(thd, tl);
+ if (!ref_sa.share)
+ return true;
+ if (fk_rename_backup.push_back(std::move(ref_sa)))
+ goto mem_error;
+ DBUG_ASSERT(!ref_sa.share);
+ if (!fk_rename_backup.back().sa.share)
+ return true; // ctor failed, share was released
+ }
+
+ for (FK_ddl_backup &ref: fk_rename_backup)
+ {
+ TABLE_SHARE *ref_share= ref.sa.share;
+ if (!ref_share)
+ continue; // renamed table backup
+ for (FK_info &fk: ref_share->foreign_keys)
+ {
+ if (cmp_table(fk.ref_db(), old_table->db) ||
+ cmp_table(fk.referenced_table, old_table->table_name))
+ continue;
+ if (0 != cmp_table(old_table->db, *new_db) &&
+ fk.referenced_db.strdup(&share->mem_root, *new_db))
+ goto mem_error;
+ if (fk.referenced_table.strdup(&ref_share->mem_root, *new_table_name))
+ goto mem_error;
+ }
+ for (FK_info &rk: ref_share->referenced_keys)
+ {
+ if (cmp_table(rk.foreign_db, old_table->db) ||
+ cmp_table(rk.foreign_table, old_table->table_name))
+ continue;
+ if (rk.foreign_db.strdup(&ref_share->mem_root, *new_db) ||
+ rk.foreign_table.strdup(&ref_share->mem_root, *new_table_name))
+ goto mem_error;
+ }
+ if (ref_share->fk_write_shadow_frm())
+ return true;
+ }
+
+ return false;
+
+mem_error:
+ my_error(ER_OUT_OF_RESOURCES, MYF(0));
+ return true;
+}
+
+
+FK_ddl_backup::FK_ddl_backup(Share_acquire&& _sa) :
+ sa(std::move(_sa))
+{
+ if (foreign_keys.copy(&sa.share->foreign_keys, &sa.share->mem_root) ||
+ list_copy_and_replace_each_value(foreign_keys, &sa.share->mem_root))
+ {
+ my_error(ER_OUT_OF_RESOURCES, MYF(0));
+ sa.release();
+ return;
+ }
+ if (referenced_keys.copy(&sa.share->referenced_keys, &sa.share->mem_root) ||
+ list_copy_and_replace_each_value(referenced_keys, &sa.share->mem_root))
+ {
+ my_error(ER_OUT_OF_RESOURCES, MYF(0));
+ sa.release();
+ return;
+ }
+}
+
+
+void
+FK_ddl_backup::rollback()
+{
+ DBUG_ASSERT(sa.share);
+ sa.share->foreign_keys= foreign_keys;
+ sa.share->referenced_keys= referenced_keys;
+ sa.share->fk_drop_shadow_frm();
+}
+
+
+void
+FK_rename_backup::rollback()
+{
+ if (sa.share)
+ FK_ddl_backup::rollback();
+ else
+ fk_drop_shadow_frm(old_name);
+}
+
+
+bool
+FK_table_backup::init(TABLE_SHARE *_share)
+{
+ DBUG_ASSERT(_share);
+ if (foreign_keys.copy(&_share->foreign_keys, &_share->mem_root) ||
+ list_copy_and_replace_each_value(foreign_keys, &_share->mem_root))
+ {
+ my_error(ER_OUT_OF_RESOURCES, MYF(0));
+ return true;
+ }
+ if (referenced_keys.copy(&_share->referenced_keys, &_share->mem_root) ||
+ list_copy_and_replace_each_value(referenced_keys, &_share->mem_root))
+ {
+ my_error(ER_OUT_OF_RESOURCES, MYF(0));
+ return true;
+ }
+ share= _share;
+ return false;
+}
diff --git a/sql/sql_table.h b/sql/sql_table.h
index 7b0ae21847d..3b5808fefb0 100644
--- a/sql/sql_table.h
+++ b/sql/sql_table.h
@@ -19,11 +19,14 @@
#include <my_sys.h> // pthread_mutex_t
#include "m_string.h" // LEX_CUSTRING
+#include "mdl.h" // MDL_request_list
+#include "handler.h"
class Alter_info;
class Alter_table_ctx;
class Column_definition;
class Create_field;
+class FK_rename_vector;
struct TABLE_LIST;
class THD;
struct TABLE;
@@ -77,7 +80,8 @@ bool check_mysql50_prefix(const char *name);
uint build_table_filename(char *buff, size_t bufflen, const char *db,
const char *table, const char *ext, uint flags);
uint build_table_shadow_filename(char *buff, size_t bufflen,
- ALTER_PARTITION_PARAM_TYPE *lpt);
+ const LEX_CSTRING &db,
+ const LEX_CSTRING &table_name);
void build_lower_case_table_filename(char *buff, size_t bufflen,
const LEX_CSTRING *db,
const LEX_CSTRING *table,
@@ -137,17 +141,22 @@ int mysql_create_table_no_lock(THD *thd,
handler *mysql_create_frm_image(THD *thd,
const LEX_CSTRING &db,
const LEX_CSTRING &table_name,
+ const LEX_CSTRING &new_db,
+ const LEX_CSTRING &new_table_name,
HA_CREATE_INFO *create_info,
Alter_info *alter_info,
int create_table_mode,
KEY **key_info,
uint *key_count,
+ FK_list &foreign_keys,
+ FK_list &referenced_keys,
LEX_CUSTRING *frm);
int mysql_discard_or_import_tablespace(THD *thd,
TABLE_LIST *table_list,
bool discard);
+class Share_acquire_vec;
bool mysql_prepare_alter_table(THD *thd, TABLE *table,
HA_CREATE_INFO *create_info,
Alter_info *alter_info,
@@ -186,8 +195,8 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables,
DDL_LOG_STATE *ddl_log_state,
bool if_exists,
bool drop_temporary, bool drop_view,
- bool drop_sequence,
- bool dont_log_query, bool dont_free_locks);
+ bool drop_sequence, bool drop_db,
+ bool dont_log_query /* MERGE: recheck calls */, bool dont_free_locks);
bool log_drop_table(THD *thd, const LEX_CSTRING *db_name,
const LEX_CSTRING *table_name, bool temporary_table);
bool quick_rm_table(THD *thd, handlerton *base, const LEX_CSTRING *db,
@@ -204,6 +213,10 @@ int write_bin_log(THD *thd, bool clear_error,
int write_bin_log_with_if_exists(THD *thd, bool clear_error,
bool is_trans, bool add_if_exists);
+bool fk_handle_rename(THD *thd, TABLE_LIST *old_table, const LEX_CSTRING *new_db,
+ const LEX_CSTRING *new_table_name,
+ FK_rename_vector &fk_rename_backup);
+
template<typename T> class List;
void promote_first_timestamp_column(List<Create_field> *column_definitions);
diff --git a/sql/sql_truncate.cc b/sql/sql_truncate.cc
index 46fee3f0b80..9bf291a4cbb 100644
--- a/sql/sql_truncate.cc
+++ b/sql/sql_truncate.cc
@@ -40,11 +40,11 @@
*/
static bool fk_info_append_fields(THD *thd, String *str,
- List<LEX_CSTRING> *fields)
+ List<Lex_cstring> *fields)
{
bool res= FALSE;
- LEX_CSTRING *field;
- List_iterator_fast<LEX_CSTRING> it(*fields);
+ Lex_cstring *field;
+ List_iterator_fast<Lex_cstring> it(*fields);
while ((field= it++))
{
@@ -80,17 +80,17 @@ static const char *fk_info_str(THD *thd, FOREIGN_KEY_INFO *fk_info)
`db`.`tbl`, CONSTRAINT `id` FOREIGN KEY (`fk`) REFERENCES `db`.`tbl` (`fk`)
*/
- res|= append_identifier(thd, &str, fk_info->foreign_db);
+ res|= append_identifier(thd, &str, &fk_info->foreign_db);
res|= str.append('.');
- res|= append_identifier(thd, &str, fk_info->foreign_table);
+ res|= append_identifier(thd, &str, &fk_info->foreign_table);
res|= str.append(STRING_WITH_LEN(", CONSTRAINT "));
- res|= append_identifier(thd, &str, fk_info->foreign_id);
+ res|= append_identifier(thd, &str, &fk_info->foreign_id);
res|= str.append(STRING_WITH_LEN(" FOREIGN KEY ("));
res|= fk_info_append_fields(thd, &str, &fk_info->foreign_fields);
res|= str.append(STRING_WITH_LEN(") REFERENCES "));
- res|= append_identifier(thd, &str, fk_info->referenced_db);
+ res|= append_identifier(thd, &str, fk_info->ref_db_ptr());
res|= str.append('.');
- res|= append_identifier(thd, &str, fk_info->referenced_table);
+ res|= append_identifier(thd, &str, &fk_info->referenced_table);
res|= str.append(STRING_WITH_LEN(" ("));
res|= fk_info_append_fields(thd, &str, &fk_info->referenced_fields);
res|= str.append(')');
@@ -120,14 +120,13 @@ static bool
fk_truncate_illegal_if_parent(THD *thd, TABLE *table)
{
FOREIGN_KEY_INFO *fk_info;
- List<FOREIGN_KEY_INFO> fk_list;
List_iterator_fast<FOREIGN_KEY_INFO> it;
/*
Bail out early if the table is not referenced by a foreign key.
In this case, the table could only be, if at all, a child table.
*/
- if (! table->file->referenced_by_foreign_key())
+ if (! table->s->referenced_by_foreign_key())
return FALSE;
/*
@@ -136,24 +135,17 @@ fk_truncate_illegal_if_parent(THD *thd, TABLE *table)
of foreign keys referencing this table in order to check the name
of the child (dependent) tables.
*/
- table->file->get_parent_foreign_key_list(thd, &fk_list);
-
- /* Out of memory when building list. */
- if (unlikely(thd->is_error()))
- return TRUE;
-
- it.init(fk_list);
+ it.init(table->s->referenced_keys);
/* Loop over the set of foreign keys for which this table is a parent. */
while ((fk_info= it++))
{
- if (lex_string_cmp(system_charset_info, fk_info->referenced_db,
- &table->s->db) ||
- lex_string_cmp(system_charset_info, fk_info->referenced_table,
+ if (cmp_table(fk_info->ref_db(), table->s->db) ||
+ lex_string_cmp(system_charset_info, &fk_info->referenced_table,
&table->s->table_name) ||
- lex_string_cmp(system_charset_info, fk_info->foreign_db,
+ lex_string_cmp(system_charset_info, &fk_info->foreign_db,
&table->s->db) ||
- lex_string_cmp(system_charset_info, fk_info->foreign_table,
+ lex_string_cmp(system_charset_info, &fk_info->foreign_table,
&table->s->table_name))
break;
}
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index f25cc42fc5c..6f780e24ece 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -5851,8 +5851,8 @@ column_def:
{ $$= $1; }
| field_spec opt_constraint references
{
- if (unlikely(Lex->add_column_foreign_key(&($1->field_name), &$2,
- $3, DDL_options())))
+ if (unlikely(Lex->add_column_foreign_key($1->field_name, $2,
+ *$3, DDL_options())))
MYSQL_YYABORT;
$$= $1;
}
@@ -5906,19 +5906,17 @@ key_def:
'(' key_list opt_without_overlaps ')' normal_key_options { }
| opt_constraint FOREIGN KEY_SYM opt_if_not_exists opt_ident
{
- if (unlikely(Lex->check_add_key($4)) ||
- unlikely(!(Lex->last_key= (new (thd->mem_root)
- Key(Key::MULTIPLE,
- $1.str ? &$1 : &$5,
- HA_KEY_ALG_UNDEF, true, $4)))))
+ if (unlikely(Lex->check_add_key($4)))
MYSQL_YYABORT;
+ if (unlikely(Lex->add_table_foreign_key($5.str ? $5 : $1,
+ $1.str ? $1 : $5, $4)))
+ MYSQL_YYABORT;
Lex->option_list= NULL;
}
'(' key_list ')' references
{
- if (unlikely(Lex->add_table_foreign_key($5.str ? &$5 : &$1,
- $1.str ? &$1 : &$5, $10, $4)))
- MYSQL_YYABORT;
+ Foreign_key &fk= static_cast<Foreign_key &>(*Lex->last_key);
+ fk.init($10->db, $10->table, Lex);
}
;
diff --git a/sql/table.cc b/sql/table.cc
index aba2483a58d..08753cc1b80 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -61,21 +61,6 @@ public:
}
};
-struct extra2_fields
-{
- LEX_CUSTRING version;
- LEX_CUSTRING options;
- Lex_ident engine;
- LEX_CUSTRING gis;
- LEX_CUSTRING field_flags;
- LEX_CUSTRING system_period;
- LEX_CUSTRING application_period;
- LEX_CUSTRING field_data_type_info;
- LEX_CUSTRING without_overlaps;
- void reset()
- { bzero((void*)this, sizeof(*this)); }
-};
-
static Virtual_column_info * unpack_vcol_info_from_frm(THD *, MEM_ROOT *,
TABLE *, String *, Virtual_column_info **, bool *);
static bool check_vcol_forward_refs(Field *, Virtual_column_info *,
@@ -357,6 +342,8 @@ TABLE_SHARE *alloc_table_share(const char *db, const char *table_name,
share->normalized_path.length= path_length;
share->table_category= get_table_category(& share->db, & share->table_name);
share->open_errno= ENOENT;
+ share->foreign_keys.empty();
+ share->referenced_keys.empty();
/* The following will be updated in open_table_from_share */
share->can_do_row_logging= 1;
if (share->table_category == TABLE_CATEGORY_LOG)
@@ -407,7 +394,7 @@ TABLE_SHARE *alloc_table_share(const char *db, const char *table_name,
NOTES
This is different from alloc_table_share() because temporary tables
- don't have to be shared between threads or put into the table def
+ dap on't have to be shared between threads or put into the table def
cache, so we can do some things notable simpler and faster
If table is not put in thd->temporary_tables (happens only when
@@ -444,6 +431,8 @@ void init_tmp_table_share(THD *thd, TABLE_SHARE *share, const char *key,
share->frm_version= FRM_VER_CURRENT;
share->not_usable_by_query_cache= 1;
share->can_do_row_logging= 0; // No row logging
+ share->foreign_keys.empty();
+ share->referenced_keys.empty();
/*
table_map_id is also used for MERGE tables to suppress repeated
@@ -624,6 +613,7 @@ enum open_frm_error open_table_def(THD *thd, TABLE_SHARE *share, uint flags)
share->table_name.str, share->normalized_path.str));
share->error= OPEN_FRM_OPEN_ERROR;
+ share->open_flags= flags;
length=(uint) (strxmov(path, share->normalized_path.str, reg_ext, NullS) -
path);
@@ -1507,105 +1497,6 @@ bool TABLE_SHARE::init_period_from_extra2(period_info_t *period,
}
-static size_t extra2_read_len(const uchar **extra2, const uchar *extra2_end)
-{
- size_t length= *(*extra2)++;
- if (length)
- return length;
-
- if ((*extra2) + 2 >= extra2_end)
- return 0;
- length= uint2korr(*extra2);
- (*extra2)+= 2;
- if (length < 256 || *extra2 + length > extra2_end)
- return 0;
- return length;
-}
-
-static
-bool read_extra2_section_once(const uchar *extra2, size_t len, LEX_CUSTRING *section)
-{
- if (section->str)
- return true;
- *section= {extra2, len};
- return false;
-}
-
-static
-bool read_extra2(const uchar *frm_image, size_t len, extra2_fields *fields)
-{
- const uchar *extra2= frm_image + 64;
-
- DBUG_ENTER("read_extra2");
-
- fields->reset();
-
- if (*extra2 != '/') // old frm had '/' there
- {
- const uchar *e2end= extra2 + len;
- while (extra2 + 3 <= e2end)
- {
- extra2_frm_value_type type= (extra2_frm_value_type)*extra2++;
- size_t length= extra2_read_len(&extra2, e2end);
- if (!length)
- DBUG_RETURN(true);
-
- bool fail= false;
- switch (type) {
- case EXTRA2_TABLEDEF_VERSION:
- if (fields->version.str) // see init_from_sql_statement_string()
- {
- if (length != fields->version.length)
- DBUG_RETURN(true);
- }
- else
- {
- fields->version.str= extra2;
- fields->version.length= length;
- }
- break;
- case EXTRA2_ENGINE_TABLEOPTS:
- fail= read_extra2_section_once(extra2, length, &fields->options);
- break;
- case EXTRA2_DEFAULT_PART_ENGINE:
- fields->engine.set((const char*)extra2, length);
- break;
- case EXTRA2_GIS:
- fail= read_extra2_section_once(extra2, length, &fields->gis);
- break;
- case EXTRA2_PERIOD_FOR_SYSTEM_TIME:
- fail= read_extra2_section_once(extra2, length, &fields->system_period)
- || length != 2 * frm_fieldno_size;
- break;
- case EXTRA2_FIELD_FLAGS:
- fail= read_extra2_section_once(extra2, length, &fields->field_flags);
- break;
- case EXTRA2_APPLICATION_TIME_PERIOD:
- fail= read_extra2_section_once(extra2, length, &fields->application_period);
- break;
- case EXTRA2_PERIOD_WITHOUT_OVERLAPS:
- fail= read_extra2_section_once(extra2, length, &fields->without_overlaps);
- break;
- case EXTRA2_FIELD_DATA_TYPE_INFO:
- fail= read_extra2_section_once(extra2, length, &fields->field_data_type_info);
- break;
- default:
- /* abort frm parsing if it's an unknown but important extra2 value */
- if (type >= EXTRA2_ENGINE_IMPORTANT)
- DBUG_RETURN(true);
- }
- if (fail)
- DBUG_RETURN(true);
-
- extra2+= length;
- }
- if (extra2 != e2end)
- DBUG_RETURN(true);
- }
- DBUG_RETURN(false);
-}
-
-
class Field_data_type_info_array
{
public:
@@ -1744,9 +1635,12 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
plugin_ref se_plugin= 0;
bool vers_can_native= false, frm_created= 0;
Field_data_type_info_array field_data_type_info_array;
+ Foreign_key_io foreign_key_io;
+
MEM_ROOT *old_root= thd->mem_root;
Virtual_column_info **table_check_constraints;
- extra2_fields extra2;
+ Extra2_info extra2;
+
DBUG_ENTER("TABLE_SHARE::init_from_binary_frm_image");
keyinfo= &first_keyinfo;
@@ -1781,10 +1675,7 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
new_frm_ver= (frm_image[2] - FRM_VER);
field_pack_length= new_frm_ver < 2 ? 11 : 17;
- /* Length of the MariaDB extra2 segment in the form file. */
- len = uint2korr(frm_image+4);
-
- if (read_extra2(frm_image, len, &extra2))
+ if (extra2.read(frm_image, frm_length))
goto err;
tabledef_version.length= extra2.version.length;
@@ -1805,8 +1696,8 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
}
#endif
- if (frm_length < FRM_HEADER_SIZE + len ||
- !(pos= uint4korr(frm_image + FRM_HEADER_SIZE + len)))
+ if (frm_length < FRM_HEADER_SIZE + extra2.read_size ||
+ !(pos= uint4korr(frm_image + FRM_HEADER_SIZE + extra2.read_size)))
goto err;
forminfo= frm_image + pos;
@@ -2297,11 +2188,11 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
{
const uchar *pos= extra2.application_period.str;
const uchar *end= pos + extra2.application_period.length;
- period.name.length= extra2_read_len(&pos, end);
+ period.name.length= dd_extra2_len(&pos, end);
period.name.str= strmake_root(&mem_root, (char*)pos, period.name.length);
pos+= period.name.length;
- period.constr_name.length= extra2_read_len(&pos, end);
+ period.constr_name.length= dd_extra2_len(&pos, end);
period.constr_name.str= strmake_root(&mem_root, (char*)pos,
period.constr_name.length);
pos+= period.constr_name.length;
@@ -3211,6 +3102,10 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
}
}
+ if (extra2.foreign_key_info.length &&
+ foreign_key_io.parse(thd, this, extra2.foreign_key_info))
+ goto err;
+
/*
the correct null_bytes can now be set, since bitfields have been taken
into account
@@ -3362,6 +3257,7 @@ int TABLE_SHARE::init_from_sql_statement_string(THD *thd, bool write,
LEX tmp_lex;
KEY *unused1;
uint unused2;
+ FK_list foreign_keys, referenced_keys;
handlerton *hton= plugin_hton(db_plugin);
LEX_CUSTRING frm= {0,0};
LEX_CSTRING db_backup= thd->db;
@@ -3407,9 +3303,11 @@ int TABLE_SHARE::init_from_sql_statement_string(THD *thd, bool write,
thd->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.alter_info= &thd->lex->alter_info;
+ file= mysql_create_frm_image(thd, db, table_name, db, table_name,
&thd->lex->create_info, &thd->lex->alter_info,
- C_ORDINARY_CREATE, &unused1, &unused2, &frm);
+ C_ORDINARY_CREATE, &unused1, &unused2,
+ foreign_keys, referenced_keys, &frm);
error|= file == 0;
delete file;
@@ -3460,7 +3358,7 @@ bool TABLE_SHARE::write_par_image(const uchar *par, size_t len)
}
-bool TABLE_SHARE::read_frm_image(const uchar **frm, size_t *len)
+int TABLE_SHARE::read_frm_image(const uchar **frm, size_t *len)
{
if (IF_PARTITIONING(partition_info_str, 0)) // cannot discover a partition
{
@@ -9511,6 +9409,350 @@ bool fk_modifies_child(enum_fk_option opt)
return can_write[opt];
}
+int TABLE_SHARE::cmp_db_table(const TABLE_LIST& tl) const
+{
+ return cmp_db_table(tl.db, tl.table_name);
+}
+
+
+class Local_da : public Diagnostics_area
+{
+ THD *thd;
+ Diagnostics_area *saved_da;
+
+public:
+ Local_da(THD *thd_arg) :
+ Diagnostics_area(thd_arg->query_id, false, true),
+ thd(thd_arg), saved_da(thd_arg->get_stmt_da())
+ {
+ thd->set_stmt_da(this);
+ }
+ ~Local_da()
+ {
+ if (saved_da)
+ thd->set_stmt_da(saved_da);
+ }
+ void finish()
+ {
+ DBUG_ASSERT(saved_da && thd);
+ thd->set_stmt_da(saved_da);
+ saved_da= NULL;
+ }
+};
+
+
+bool FK_info::assign(Foreign_key &src, Table_name table)
+{
+ DBUG_ASSERT(src.foreign);
+ DBUG_ASSERT(src.type == Key::MULTIPLE);
+
+ foreign_id= src.constraint_name.str ? src.constraint_name : src.name;
+ foreign_db= table.db;
+ foreign_table= table.name;
+ referenced_db= src.ref_db;
+ referenced_table= src.ref_table;
+ update_method= src.update_opt;
+ delete_method= src.delete_opt;
+
+ List_iterator_fast<Key_part_spec> ref_it(src.ref_columns);
+
+ for (const Key_part_spec &kp: src.columns)
+ {
+ if (foreign_fields.push_back((Lex_cstring *)(&kp.field_name)))
+ return true;
+ Key_part_spec *kp2= ref_it++;
+ if (referenced_fields.push_back((Lex_cstring *)(&kp2->field_name)))
+ return true;
+ }
+ return false;
+}
+
+
+FK_info * FK_info::clone(MEM_ROOT *mem_root) const
+{
+ FK_info *dst= new (mem_root) FK_info();
+ if (!dst)
+ return NULL;
+
+ if (dst->foreign_id.strdup(mem_root, foreign_id))
+ return NULL;
+ if (dst->foreign_db.strdup(mem_root, foreign_db))
+ return NULL;
+ if (dst->foreign_table.strdup(mem_root, foreign_table))
+ return NULL;
+ if (dst->referenced_db.strdup(mem_root, referenced_db))
+ return NULL;
+ if (dst->referenced_table.strdup(mem_root, referenced_table))
+ return NULL;
+ dst->update_method= update_method;
+ dst->delete_method= delete_method;
+
+ for (const Lex_cstring &src_f: foreign_fields)
+ {
+ Lex_cstring *dst_f= new (mem_root) Lex_cstring();
+ if (!dst_f)
+ return NULL;
+ if (dst_f->strdup(mem_root, src_f))
+ return NULL;
+ if (dst->foreign_fields.push_back(dst_f, mem_root))
+ return NULL;
+ }
+
+ for (const Lex_cstring &src_f: referenced_fields)
+ {
+ Lex_cstring *dst_f= new (mem_root) Lex_cstring();
+ if (!dst_f)
+ return NULL;
+ if (dst_f->strdup(mem_root, src_f))
+ return NULL;
+ if (dst->referenced_fields.push_back(dst_f, mem_root))
+ return NULL;
+ }
+
+ DBUG_ASSERT(foreign_fields.elements == referenced_fields.elements);
+ return dst;
+}
+
+
+Table_name FK_info::for_table(MEM_ROOT *mem_root) const
+{
+ Table_name result(foreign_db, foreign_table);
+ if (lower_case_table_names)
+ result.lowercase(mem_root);
+ return result;
+}
+
+
+Table_name FK_info::ref_table(MEM_ROOT *mem_root) const
+{
+ Table_name result(ref_db(), referenced_table);
+ if (lower_case_table_names)
+ result.lowercase(mem_root);
+ return result;
+}
+
+
+void FK_info::print(String& out)
+{
+ out.append(STRING_WITH_LEN("foreign_id: "));
+ out.append(foreign_id.print());
+ out.append(STRING_WITH_LEN("; foreign_db: "));
+ out.append(foreign_db.print());
+ out.append(STRING_WITH_LEN("; foreign_table: "));
+ out.append(foreign_table.print());
+ out.append(STRING_WITH_LEN("; referenced_db: "));
+ out.append(referenced_db.print());
+ out.append(STRING_WITH_LEN("; referenced_table: "));
+ out.append(referenced_table.print());
+ out.append(STRING_WITH_LEN("; update_method: "));
+ out.append(fk_option_name(update_method));
+ out.append(STRING_WITH_LEN("; delete_method: "));
+ out.append(fk_option_name(delete_method));
+ out.append(STRING_WITH_LEN("; foreign_fields: "));
+ uint i= 0;
+ for (const Lex_cstring &fld: foreign_fields)
+ {
+ if (i)
+ out.append(STRING_WITH_LEN("; "));
+ out.append(STRING_WITH_LEN("["));
+ out.append(i++, true);
+ out.append(STRING_WITH_LEN("]: "));
+ out.append(fld.print());
+ }
+ if (!i)
+ out.append(STRING_WITH_LEN("(empty)"));
+ out.append(STRING_WITH_LEN("; referenced_fields: "));
+ i= 0;
+ for (const Lex_cstring &fld: referenced_fields)
+ {
+ if (i)
+ out.append(STRING_WITH_LEN("; "));
+ out.append(STRING_WITH_LEN("["));
+ out.append(i++, true);
+ out.append(STRING_WITH_LEN("]: "));
+ out.append(fld.print());
+ }
+ if (!i)
+ out.append(STRING_WITH_LEN("(empty)"));
+}
+
+
+bool TABLE_SHARE::fk_check_consistency(THD *thd)
+{
+ mbd::set<Table_name> warned;
+ mbd::set<Table_name> warned_self;
+ bool error= false;
+ uint rk_self_refs= 0;
+ uint fk_self_refs= 0;
+ for (FK_info &rk: referenced_keys)
+ {
+ if (rk.self_ref())
+ {
+ if (cmp_db_table(rk.foreign_db, rk.foreign_table))
+ {
+ bool warn;
+ if (!warned_self.insert(Table_name(rk.foreign_db, rk.foreign_table), &warn))
+ return true;
+ if (warn)
+ {
+ my_printf_error(ER_UNKNOWN_ERROR,
+ "Self-reference in referenced list %s.%s does not point to this table",
+ MYF(0), rk.foreign_db, rk.foreign_table);
+ }
+ DBUG_ASSERT(warn || error);
+ error= true;
+ }
+ rk_self_refs++;
+ }
+ TABLE_LIST tl;
+ tl.init_one_table(&rk.foreign_db, &rk.foreign_table, NULL, TL_IGNORE);
+ Share_acquire sa(thd, tl);
+ if (!sa.share)
+ {
+ if (!ha_table_exists(thd, &rk.foreign_db, &rk.foreign_table))
+ {
+ my_printf_error(ER_UNKNOWN_ERROR, "Foreign table %s.%s not exists",
+ MYF(0), rk.foreign_db.str, rk.foreign_table.str);
+ }
+ return true;
+ }
+ List_iterator_fast<FK_info> fk_it(sa.share->foreign_keys);
+ FK_info *fk;
+ bool found_table= false;
+ /*
+ For each referenced key rk let's find foreign key fk with matching lists
+ of referenced_fields and foreign_fields.
+ */
+ while ((fk= fk_it++))
+ {
+ if (!cmp_db_table(fk->ref_db(), fk->referenced_table))
+ {
+ found_table= true;
+ if (fk->fields_eq(rk))
+ break;
+ }
+ }
+ if (!fk)
+ {
+ bool warn;
+ if (!warned.insert(Table_name(rk.foreign_db, rk.foreign_table), &warn))
+ return true;
+ if (warn)
+ {
+ my_printf_error(ER_UNKNOWN_ERROR,
+ found_table ?
+ "Foreign table %s.%s does not match foreign keys with referenced keys" :
+ "Foreign table %s.%s does not refer this table",
+ MYF(0), sa.share->db.str, sa.share->table_name.str);
+ }
+ DBUG_ASSERT(warn || error);
+ error= true;
+ }
+ }
+
+ warned.clear();
+ warned_self.clear();
+
+ if (referenced_keys.elements - rk_self_refs)
+ {
+ push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE,
+ ER_UNKNOWN_ERROR,
+ "Found %u referenced keys",
+ referenced_keys.elements - rk_self_refs);
+ }
+
+ for (FK_info &fk: foreign_keys)
+ {
+ if (fk.self_ref())
+ {
+ if (cmp_db_table(fk.foreign_db, fk.foreign_table))
+ {
+ bool warn;
+ if (!warned_self.insert(Table_name(fk.foreign_db, fk.foreign_table), &warn))
+ return true;
+ if (warn)
+ {
+ my_printf_error(ER_UNKNOWN_ERROR,
+ "Self-reference in foreign list %s.%s does not point to this table",
+ MYF(0), fk.foreign_db, fk.foreign_table);
+ }
+ DBUG_ASSERT(warn || error);
+ error= true;
+ }
+ fk_self_refs++;
+ }
+ TABLE_LIST tl;
+ tl.init_one_table(fk.ref_db_ptr(), &fk.referenced_table, NULL, TL_IGNORE);
+ Share_acquire sa(thd, tl);
+ if (!sa.share)
+ {
+ if (!ha_table_exists(thd, fk.ref_db_ptr(), &fk.referenced_table))
+ {
+ my_printf_error(ER_UNKNOWN_ERROR, "Referenced table %s.%s not exists",
+ MYF(0), fk.ref_db().str, fk.referenced_table.str);
+ }
+ return true;
+ }
+ List_iterator_fast<FK_info> ref_it(sa.share->referenced_keys);
+ FK_info *rk;
+ bool found_table= false;
+ /*
+ For each foreign key fk let's find referenced key rk with matching lists
+ of referenced_fields and foreign_fields.
+ */
+ while ((rk= ref_it++))
+ {
+ if (!cmp_db_table(rk->foreign_db, rk->foreign_table))
+ {
+ found_table= true;
+ if (rk->fields_eq(fk))
+ break;
+ }
+ }
+ if (!rk)
+ {
+ bool warn;
+ if (!warned.insert(Table_name(fk.foreign_db, fk.foreign_table), &warn))
+ return true;
+ if (warn)
+ {
+ my_printf_error(ER_UNKNOWN_ERROR,
+ found_table ?
+ "Referenced table %s.%s does not match referenced keys with foreign keys" :
+ "Referenced table %s.%s does not refer this table", MYF(0),
+ sa.share->db.str, sa.share->table_name.str);
+ }
+ DBUG_ASSERT(warn || error);
+ error= true;
+ }
+ }
+
+ if (foreign_keys.elements - fk_self_refs)
+ {
+ push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE,
+ ER_UNKNOWN_ERROR,
+ "Found %u foreign keys",
+ foreign_keys.elements - fk_self_refs);
+ }
+
+ if (fk_self_refs != rk_self_refs)
+ {
+ my_printf_error(ER_UNKNOWN_ERROR,
+ "Self-references count in foreign list and referenced list do not match: %u vs %u",
+ MYF(0), fk_self_refs, rk_self_refs);
+ }
+ else if (fk_self_refs)
+ {
+ push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE,
+ ER_UNKNOWN_ERROR,
+ "Found %u self-references",
+ fk_self_refs);
+ }
+
+ return error;
+}
+
+
enum TR_table::enabled TR_table::use_transaction_registry= TR_table::MAYBE;
TR_table::TR_table(THD* _thd, bool rw) :
@@ -9946,6 +10188,27 @@ Field *TABLE::find_field_by_name(LEX_CSTRING *str) const
}
+Field *TABLE_SHARE::find_field_by_name(const LEX_CSTRING n) const
+{
+ Field **f;
+ if (name_hash.records)
+ {
+ f= (Field**) my_hash_search(&name_hash, (uchar *) n.str, n.length);
+ return f ? *f : NULL;
+ }
+ else
+ {
+ for (f= field; *f; f++)
+ {
+ if ((*f)->field_name.length == n.length &&
+ 0 == cmp_ident((*f)->field_name, n))
+ return *f;
+ }
+ }
+ return NULL;
+}
+
+
bool TABLE::export_structure(THD *thd, Row_definition_list *defs)
{
for (Field **src= field; *src; src++)
diff --git a/sql/table.h b/sql/table.h
index 73bafb5400a..1c941fcebf6 100644
--- a/sql/table.h
+++ b/sql/table.h
@@ -52,6 +52,8 @@ struct TABLE_LIST;
class ACL_internal_schema_access;
class ACL_internal_table_access;
class Field;
+class FK_create_vector;
+class Table_name;
class Table_statistics;
class With_element;
struct TDC_element;
@@ -374,7 +376,6 @@ enum __attribute__((packed)) field_visibility_t {
INVISIBLE_FULL
};
-#define INVISIBLE_MAX_BITS 3
#define HA_HASH_FIELD_LENGTH 8
#define HA_HASH_KEY_LENGTH_WITHOUT_NULL 8
#define HA_HASH_KEY_LENGTH_WITH_NULL 9
@@ -730,6 +731,20 @@ struct TABLE_SHARE
Field **field;
Field **found_next_number_field;
KEY *key_info; /* data of keys in database */
+ FK_list foreign_keys;
+ FK_list referenced_keys;
+ Field *find_field_by_name(const LEX_CSTRING n) const;
+ bool fk_handle_create(THD *thd, FK_create_vector &shares);
+ bool fk_check_consistency(THD *thd);
+ bool referenced_by_foreign_key() const
+ {
+ return !referenced_keys.is_empty();
+ }
+ int fk_write_shadow_frm();
+ bool fk_install_shadow_frm();
+ void fk_drop_shadow_frm();
+ bool fk_resolve_referenced_keys(THD *thd, TABLE_SHARE *from);
+
Virtual_column_info **check_constraints;
uint *blob_field; /* Index to blobs in Field arrray*/
LEX_CUSTRING vcol_defs; /* definitions of generated columns */
@@ -759,6 +774,16 @@ struct TABLE_SHARE
LEX_CSTRING normalized_path; /* unpack_filename(path) */
LEX_CSTRING connect_string;
+ int cmp_db_table(const LEX_CSTRING &_db, const LEX_CSTRING &_table_name) const
+ {
+ int res= ::cmp_table(_db, db);
+ if (res)
+ return res;
+ return ::cmp_table(_table_name, table_name);
+ }
+
+ int cmp_db_table(const TABLE_LIST &tl) const;
+
/*
Set of keys in use, implemented as a Bitmap.
Excludes keys disabled by ALTER TABLE ... DISABLE KEYS.
@@ -828,6 +853,7 @@ struct TABLE_SHARE
uint next_number_keypart; /* autoinc keypart number in a key */
enum open_frm_error error; /* error from open_table_def() */
uint open_errno; /* error from open_table_def() */
+ uint open_flags; /* flags from open_table_def() */
uint column_bitmap_size;
uchar frm_version;
@@ -882,6 +908,11 @@ struct TABLE_SHARE
plugin_ref default_part_plugin;
#endif
+ bool partitioned() const
+ {
+ return IF_PARTITIONING(partition_info_str != NULL, false);
+ }
+
/**
System versioning and application-time periods support.
*/
@@ -1145,7 +1176,7 @@ struct TABLE_SHARE
returns an frm image for this table.
the memory is allocated and must be freed later
*/
- bool read_frm_image(const uchar **frm_image, size_t *frm_length);
+ int read_frm_image(const uchar **frm_image, size_t *frm_length);
/* frees the memory allocated in read_frm_image */
void free_frm_image(const uchar *frm);
@@ -1811,22 +1842,80 @@ enum enum_schema_table_state
PROCESSED_BY_JOIN_EXEC
};
-enum enum_fk_option { FK_OPTION_UNDEF, FK_OPTION_RESTRICT, FK_OPTION_CASCADE,
+enum enum_fk_option { FK_OPTION_UNDEF= 0, FK_OPTION_RESTRICT, FK_OPTION_CASCADE,
FK_OPTION_SET_NULL, FK_OPTION_NO_ACTION, FK_OPTION_SET_DEFAULT};
+class Foreign_key;
+class Table_name;
-typedef struct st_foreign_key_info
+class FK_info : public Sql_alloc
{
- LEX_CSTRING *foreign_id;
- LEX_CSTRING *foreign_db;
- LEX_CSTRING *foreign_table;
- LEX_CSTRING *referenced_db;
- LEX_CSTRING *referenced_table;
+public:
+ Lex_cstring foreign_id;
+ // TODO: use Table_name
+ Lex_cstring foreign_db;
+ Lex_cstring foreign_table;
+ Lex_cstring referenced_db;
+ Lex_cstring referenced_table;
enum_fk_option update_method;
enum_fk_option delete_method;
- LEX_CSTRING *referenced_key_name;
- List<LEX_CSTRING> foreign_fields;
- List<LEX_CSTRING> referenced_fields;
-} FOREIGN_KEY_INFO;
+ List<Lex_cstring> foreign_fields;
+ List<Lex_cstring> referenced_fields;
+
+public:
+ FK_info() :
+ update_method(FK_OPTION_UNDEF),
+ delete_method(FK_OPTION_UNDEF)
+ {}
+ Lex_cstring ref_db() const
+ {
+ return referenced_db.str ? referenced_db : foreign_db;
+ }
+ Lex_cstring* ref_db_ptr()
+ {
+ return referenced_db.str ? &referenced_db : &foreign_db;
+ }
+ bool self_ref() const
+ {
+ if (referenced_db.length && 0 != cmp_table(referenced_db, foreign_db))
+ return false;
+ // TODO: keep NULL in referenced_table for self-refs
+ return 0 == cmp_table(referenced_table, foreign_table);
+ }
+ bool fields_eq(/* const */ FK_info &fk) /* const */
+ {
+ if (foreign_fields.elements == 0 ||
+ foreign_fields.elements != referenced_fields.elements ||
+ fk.foreign_fields.elements != fk.referenced_fields.elements)
+ {
+ DBUG_ASSERT(0);
+ return false;
+ }
+ if (foreign_fields.elements != fk.foreign_fields.elements)
+ return false;
+ List_iterator_fast<Lex_cstring> ff_it(foreign_fields);
+ List_iterator_fast<Lex_cstring> ff_it2(fk.foreign_fields);
+ List_iterator_fast<Lex_cstring> rf_it(referenced_fields);
+ List_iterator_fast<Lex_cstring> rf_it2(fk.referenced_fields);
+ while (Lex_cstring *ff= ff_it++)
+ {
+ Lex_cstring *ff2= ff_it2++;
+ if (!ff2 || cmp(ff, ff2))
+ return false;
+ Lex_cstring *rf= rf_it++;
+ Lex_cstring *rf2= rf_it2++;
+ if (cmp(rf, rf2))
+ return false;
+ }
+ return true;
+ }
+ bool assign(Foreign_key &fk, Table_name table);
+ FK_info * clone(MEM_ROOT *mem_root) const;
+ Table_name for_table(MEM_ROOT *mem_root) const;
+ Table_name ref_table(MEM_ROOT *mem_root) const;
+ void print(String &out);
+};
+
+typedef class FK_info FOREIGN_KEY_INFO;
LEX_CSTRING *fk_option_name(enum_fk_option opt);
bool fk_modifies_child(enum_fk_option opt);
@@ -3112,7 +3201,8 @@ enum get_table_share_flags {
GTS_VIEW = 2,
GTS_NOLOCK = 4,
GTS_USE_DISCOVERY = 8,
- GTS_FORCE_DISCOVERY = 16
+ GTS_FORCE_DISCOVERY = 16,
+ GTS_FK_SHALLOW_HINTS = 32
};
size_t max_row_length(TABLE *table, MY_BITMAP const *cols, const uchar *data);
diff --git a/sql/table_cache.cc b/sql/table_cache.cc
index 62ccfba7e7d..57781506374 100644
--- a/sql/table_cache.cc
+++ b/sql/table_cache.cc
@@ -1291,3 +1291,37 @@ void TDC_element::flush_unused(bool mark_flushed)
while (auto table= purge_tables.pop_front())
intern_close_table(table);
}
+
+
+Share_acquire::~Share_acquire()
+{
+ if (share)
+ {
+ if (flush_unused)
+ share->tdc->flush_unused(true);
+ tdc_release_share(share);
+ }
+}
+
+
+void Share_acquire::acquire(THD *thd, TABLE_LIST &tl, uint flags)
+{
+ Diagnostics_area *da= thd->get_stmt_da();
+ Warning_info tmp_wi(thd->query_id, false, true);
+
+ da->push_warning_info(&tmp_wi);
+ share= tdc_acquire_share(thd, &tl, GTS_TABLE|flags);
+ da->pop_warning_info();
+}
+
+
+bool Share_acquire::is_error(THD *thd)
+{
+ if (share)
+ return false;
+ if (thd->is_error() && thd->get_stmt_da()->sql_errno() == ER_WRONG_OBJECT)
+ {
+ thd->clear_error();
+ }
+ return true;
+}
diff --git a/sql/table_cache.h b/sql/table_cache.h
index 433df5e0328..02ff69d4b2b 100644
--- a/sql/table_cache.h
+++ b/sql/table_cache.h
@@ -18,6 +18,8 @@
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */
+#include "table.h"
+
struct Share_free_tables
{
typedef I_P_List <TABLE, TABLE_share> List;
@@ -94,6 +96,59 @@ extern void tc_add_table(THD *thd, TABLE *table);
extern void tc_release_table(TABLE *table);
extern TABLE *tc_acquire_table(THD *thd, TDC_element *element);
+
+class Share_lock
+{
+public:
+ TDC_element *element;
+
+ Share_lock(THD *thd, const char *db, const char *table)
+ {
+ element= tdc_lock_share(thd, db, table);
+ }
+ ~Share_lock()
+ {
+ if (element)
+ tdc_unlock_share(element);
+ }
+};
+
+
+class Share_acquire
+{
+public:
+ bool flush_unused;
+ TABLE_SHARE *share;
+
+ Share_acquire() : flush_unused(false), share(NULL) {}
+ Share_acquire(THD *thd, TABLE_LIST &tl, uint flags= 0) : flush_unused(false)
+ {
+ acquire(thd, tl, flags);
+ }
+ Share_acquire(const Share_acquire &src)= delete;
+
+ // NB: noexcept is required for STL containers
+ Share_acquire(Share_acquire &&src) noexcept :
+ flush_unused(src.flush_unused), share(src.share)
+ {
+ src.share= NULL;
+ }
+ ~Share_acquire();
+ bool is_error(THD *thd);
+ void acquire(THD *thd, TABLE_LIST &tl, uint flags= 0);
+ void release()
+ {
+ if (share)
+ {
+ if (flush_unused)
+ share->tdc->flush_unused(true);
+ tdc_release_share(share);
+ share= NULL;
+ }
+ }
+};
+
+
/**
Create a table cache key for non-temporary table.
diff --git a/sql/unireg.cc b/sql/unireg.cc
index 5db9c84fbce..00a2bcd6853 100644
--- a/sql/unireg.cc
+++ b/sql/unireg.cc
@@ -32,6 +32,8 @@
#include "sql_class.h" // THD, Internal_error_handler
#include "create_options.h"
#include "discover.h"
+#include "datadict.h"
+#include "table_cache.h" // Share_acquire
#include <m_ctype.h>
#define FCOMP 17 /* Bytes for a packed field */
@@ -50,36 +52,29 @@ static size_t packed_fields_length(List<Create_field> &);
static bool make_empty_rec(THD *, uchar *, uint, List<Create_field> &, uint,
ulong);
+// TODO: move extra_ functions to datadict.cc
/*
write the length as
if ( 0 < length <= 255) one byte
- if (256 < length <= 65535) zero byte, then two bytes, low-endian
+ if (256 < length < 65535) zero byte, then two bytes, low-endian
*/
-static uchar *extra2_write_len(uchar *pos, size_t len)
+uchar *
+extra2_write_len(uchar *pos, size_t len)
{
- /* TODO: should be
- if (len > 0 && len <= 255)
- *pos++= (uchar)len;
- ...
- because extra2_read_len() uses 0 for 2-byte lengths.
- extra2_str_size() must be fixed too.
- */
if (len <= 255)
*pos++= (uchar)len;
else
{
- /*
- At the moment we support options_len up to 64K.
- We can easily extend it in the future, if the need arises.
- */
- DBUG_ASSERT(len <= 65535);
- int2store(pos + 1, len);
- pos+= 3;
+ DBUG_ASSERT(len <= 0xffff - FRM_HEADER_SIZE - 8);
+ *pos++= 0;
+ int2store(pos, len);
+ pos+= 2;
}
return pos;
}
-static uchar* extra2_write_str(uchar *pos, const LEX_CSTRING &str)
+uchar *
+extra2_write_str(uchar *pos, const LEX_CSTRING &str)
{
pos= extra2_write_len(pos, str.length);
memcpy(pos, str.str, str.length);
@@ -93,21 +88,8 @@ static uchar* extra2_write_str(uchar *pos, const Binary_string *str)
return pos + str->length();
}
-static uchar *extra2_write(uchar *pos, enum extra2_frm_value_type type,
- const LEX_CSTRING &str)
-{
- *pos++ = type;
- return extra2_write_str(pos, str);
-}
-
-static uchar *extra2_write(uchar *pos, enum extra2_frm_value_type type,
- const LEX_CUSTRING &str)
-{
- return extra2_write(pos, type, *reinterpret_cast<const LEX_CSTRING*>(&str));
-}
-
-static uchar *extra2_write_field_properties(uchar *pos,
- List<Create_field> &create_fields)
+uchar *
+extra2_write_field_properties(uchar *pos, List<Create_field> &create_fields)
{
List_iterator<Create_field> it(create_fields);
*pos++= EXTRA2_FIELD_FLAGS;
@@ -125,6 +107,7 @@ static uchar *extra2_write_field_properties(uchar *pos,
return pos;
}
+
static uint16
get_fieldno_by_name(HA_CREATE_INFO *create_info, List<Create_field> &create_fields,
const Lex_ident &field_name)
@@ -191,10 +174,6 @@ class Field_data_type_info_image: public BinaryStringBuffer<512>
memcpy(pos, str->ptr(), str->length());
return pos + str->length();
}
- static uint store_length_required_length(ulonglong length)
- {
- return net_length_size(length);
- }
public:
Field_data_type_info_image() { }
bool append(uint fieldnr, const Column_definition &def)
@@ -206,8 +185,8 @@ public:
return true; // Error
if (!type_info.length())
return false;
- size_t need_length= store_length_required_length(fieldnr) +
- store_length_required_length(type_info.length()) +
+ size_t need_length= net_length_size(fieldnr) +
+ net_length_size(type_info.length()) +
type_info.length();
if (reserve(need_length))
return true; // Error
@@ -250,14 +229,15 @@ public:
*/
LEX_CUSTRING build_frm_image(THD *thd, const LEX_CSTRING &table,
- HA_CREATE_INFO *create_info,
- List<Create_field> &create_fields,
- uint keys, KEY *key_info, handler *db_file)
+ HA_CREATE_INFO *create_info,
+ List<Create_field> &create_fields,
+ uint keys, KEY *key_info, FK_list &foreign_keys,
+ FK_list &referenced_keys,
+ handler *db_file)
{
LEX_CSTRING str_db_type;
uint reclength, key_info_length, i;
ulong key_buff_length;
- size_t filepos;
ulong data_offset;
uint options_len;
uint gis_extra2_len= 0;
@@ -275,6 +255,7 @@ LEX_CUSTRING build_frm_image(THD *thd, const LEX_CSTRING &table,
LEX_CUSTRING frm= {0,0};
StringBuffer<MAX_FIELD_WIDTH> vcols;
Field_data_type_info_image field_data_type_info_image;
+ Foreign_key_io foreign_key_io;
DBUG_ENTER("build_frm_image");
/* If fixed row records, we need one bit to check for deleted rows */
@@ -336,6 +317,33 @@ LEX_CUSTRING build_frm_image(THD *thd, const LEX_CSTRING &table,
MYF(0), table.str);
DBUG_RETURN(frm);
}
+ if (field_data_type_info_image.length() > 0xffff - FRM_HEADER_SIZE - 8)
+ {
+ my_printf_error(ER_CANT_CREATE_TABLE,
+ "Cannot create table %`s: "
+ "field data type info image is too large. "
+ "Decrease the number of columns with "
+ "extended data types.",
+ MYF(0), table.str);
+ DBUG_RETURN(frm);
+ }
+ if (foreign_key_io.store(foreign_keys, referenced_keys))
+ {
+ my_printf_error(ER_CANT_CREATE_TABLE,
+ "Cannot create table %`s: "
+ "Building the foreign key info image failed.",
+ MYF(0), table.str);
+ DBUG_RETURN(frm);
+ }
+ if (foreign_key_io.length() > 0xffff - FRM_HEADER_SIZE - 8)
+ {
+ my_printf_error(ER_CANT_CREATE_TABLE,
+ "Cannot create table %`s: "
+ "foreign key info image is too large.",
+ MYF(0), table.str);
+ DBUG_RETURN(frm);
+ }
+
DBUG_PRINT("info", ("Field data type info length: %u",
(uint) field_data_type_info_image.length()));
DBUG_EXECUTE_IF("frm_data_type_info",
@@ -392,6 +400,9 @@ LEX_CUSTRING build_frm_image(THD *thd, const LEX_CSTRING &table,
if (field_data_type_info_image.length())
extra2_size+= 1 + extra2_str_size(field_data_type_info_image.length());
+ if (foreign_key_io.length())
+ extra2_size+= 1 + extra2_str_size(foreign_key_io.length());
+
if (create_info->versioned())
{
extra2_size+= 1 + extra2_str_size(2 * frm_fieldno_size);
@@ -423,7 +434,7 @@ LEX_CUSTRING build_frm_image(THD *thd, const LEX_CSTRING &table,
frm.length+= reclength; // row with default values
frm.length+= create_info->extra_size;
- filepos= frm.length;
+ const size_t forminfo_pos= frm.length;
frm.length+= FRM_FORMINFO_SIZE; // forminfo
frm.length+= packed_fields_length(create_fields);
frm.length+= create_info->expression_length;
@@ -441,7 +452,7 @@ LEX_CUSTRING build_frm_image(THD *thd, const LEX_CSTRING &table,
DBUG_RETURN(frm);
/* write the extra2 segment */
- pos = frm_ptr + 64;
+ pos = frm_ptr + FRM_HEADER_SIZE;
compile_time_assert(EXTRA2_TABLEDEF_VERSION != '/');
pos= extra2_write(pos, EXTRA2_TABLEDEF_VERSION,
create_info->tabledef_version);
@@ -467,20 +478,28 @@ LEX_CUSTRING build_frm_image(THD *thd, const LEX_CSTRING &table,
if (field_data_type_info_image.length())
{
- if (field_data_type_info_image.length() > 0xFFFF)
- {
- my_printf_error(ER_CANT_CREATE_TABLE,
- "Cannot create table %`s: "
- "field data type info image is too large. "
- "Decrease the number of columns with "
- "extended data types.",
- MYF(0), table.str);
- goto err;
- }
*pos= EXTRA2_FIELD_DATA_TYPE_INFO;
pos= extra2_write_str(pos + 1, &field_data_type_info_image);
}
+ if (foreign_key_io.length())
+ {
+ *pos= EXTRA2_FOREIGN_KEY_INFO;
+ pos= extra2_write_str(pos + 1, foreign_key_io.lex_cstring());
+ }
+
+ if (create_info->versioned())
+ {
+ *pos++= EXTRA2_PERIOD_FOR_SYSTEM_TIME;
+ *pos++= 2 * frm_fieldno_size;
+ store_frm_fieldno(pos, get_fieldno_by_name(create_info, create_fields,
+ create_info->vers_info.as_row.start));
+ pos+= frm_fieldno_size;
+ store_frm_fieldno(pos, get_fieldno_by_name(create_info, create_fields,
+ create_info->vers_info.as_row.end));
+ pos+= frm_fieldno_size;
+ }
+
// PERIOD
if (create_info->period_info.is_set())
{
@@ -510,22 +529,10 @@ LEX_CUSTRING build_frm_image(THD *thd, const LEX_CSTRING &table,
}
}
- if (create_info->versioned())
- {
- *pos++= EXTRA2_PERIOD_FOR_SYSTEM_TIME;
- *pos++= 2 * frm_fieldno_size;
- store_frm_fieldno(pos, get_fieldno_by_name(create_info, create_fields,
- create_info->vers_info.as_row.start));
- pos+= frm_fieldno_size;
- store_frm_fieldno(pos, get_fieldno_by_name(create_info, create_fields,
- create_info->vers_info.as_row.end));
- pos+= frm_fieldno_size;
- }
-
if (has_extra2_field_flags_)
pos= extra2_write_field_properties(pos, create_fields);
- int4store(pos, filepos); // end of the extra2 segment
+ int4store(pos, forminfo_pos); // end of the extra2 segment
pos+= 4;
DBUG_ASSERT(pos == frm_ptr + uint2korr(fileinfo+6));
@@ -539,7 +546,7 @@ LEX_CUSTRING build_frm_image(THD *thd, const LEX_CSTRING &table,
goto err;
}
- int2store(forminfo+2, frm.length - filepos);
+ int2store(forminfo+2, frm.length - forminfo_pos);
int4store(fileinfo+10, frm.length);
fileinfo[26]= (uchar) MY_TEST((create_info->max_rows == 1) &&
(create_info->min_rows == 1) && (keys == 0));
@@ -599,8 +606,8 @@ LEX_CUSTRING build_frm_image(THD *thd, const LEX_CSTRING &table,
pos+= create_info->comment.length;
}
- memcpy(frm_ptr + filepos, forminfo, FRM_FORMINFO_SIZE);
- pos= frm_ptr + filepos + FRM_FORMINFO_SIZE;
+ memcpy(frm_ptr + forminfo_pos, forminfo, FRM_FORMINFO_SIZE);
+ pos= frm_ptr + forminfo_pos + FRM_FORMINFO_SIZE;
if (pack_fields(&pos, create_fields, create_info, data_offset))
goto err;
@@ -1218,3 +1225,367 @@ static bool make_empty_rec(THD *thd, uchar *buff, uint table_options,
err:
DBUG_RETURN(error);
} /* make_empty_rec */
+
+ulonglong Foreign_key_io::fk_size(FK_info &fk)
+{
+ ulonglong store_size= 0;
+ store_size+= string_size(fk.foreign_id);
+ store_size+= string_size(fk.referenced_db);
+ store_size+= string_size(fk.referenced_table);
+ store_size+= net_length_size(fk.update_method);
+ store_size+= net_length_size(fk.delete_method);
+ store_size+= net_length_size(fk.foreign_fields.elements);
+ DBUG_ASSERT(fk.foreign_fields.elements == fk.referenced_fields.elements);
+ List_iterator_fast<Lex_cstring> ref_it(fk.referenced_fields);
+ for (Lex_cstring &fcol: fk.foreign_fields)
+ {
+ store_size+= string_size(fcol);
+ Lex_cstring *ref_col= ref_it++;
+ store_size+= string_size(*ref_col);
+ }
+ return store_size;
+}
+
+ulonglong Foreign_key_io::hint_size(FK_info &rk)
+{
+ ulonglong store_size= 0;
+ DBUG_ASSERT(rk.foreign_db.str);
+ DBUG_ASSERT(rk.foreign_table.str);
+ store_size+= string_size(rk.foreign_db);
+ store_size+= string_size(rk.foreign_table);
+ return store_size;
+}
+
+void Foreign_key_io::store_fk(FK_info &fk, uchar *&pos)
+{
+#ifndef DBUG_OFF
+ uchar *old_pos= pos;
+#endif
+ pos= store_string(pos, fk.foreign_id);
+ pos= store_string(pos, fk.referenced_db, true);
+ pos= store_string(pos, fk.referenced_table);
+ pos= store_length(pos, fk.update_method);
+ pos= store_length(pos, fk.delete_method);
+ pos= store_length(pos, fk.foreign_fields.elements);
+ DBUG_ASSERT(fk.foreign_fields.elements == fk.referenced_fields.elements);
+ List_iterator_fast<Lex_cstring> ref_it(fk.referenced_fields);
+ for (Lex_cstring &fcol: fk.foreign_fields)
+ {
+ pos= store_string(pos, fcol);
+ Lex_cstring *ref_col= ref_it++;
+ pos= store_string(pos, *ref_col);
+ }
+ DBUG_ASSERT(pos - old_pos == (long int)fk_size(fk));
+}
+
+bool Foreign_key_io::store(FK_list &foreign_keys, FK_list &referenced_keys)
+{
+ DBUG_EXECUTE_IF("fk_skip_store", return false;);
+
+ ulonglong fk_count= 0;
+ mbd::set<Table_name> hints;
+ bool inserted;
+
+ if (foreign_keys.is_empty() && referenced_keys.is_empty())
+ return false;
+
+ ulonglong store_size= net_length_size(fk_io_version);
+ for (FK_info &fk: foreign_keys)
+ {
+ fk_count++;
+ store_size+= fk_size(fk);
+ }
+ store_size+= net_length_size(fk_count);
+
+ for (FK_info &rk: referenced_keys)
+ {
+ // NB: we do not store hints on self-refs, they are stored from foreign_keys.
+ if (rk.self_ref())
+ continue;
+
+ if (!hints.insert(Table_name(rk.foreign_db, rk.foreign_table), &inserted))
+ return true;
+
+ if (!inserted)
+ continue;
+
+ store_size+= hint_size(rk);
+ }
+ store_size+= net_length_size(referenced_keys.elements);
+ store_size+= net_length_size(0); // Reserved: stored referenced keys count
+ store_size+= net_length_size(hints.size());
+
+ if (reserve(store_size))
+ {
+ my_error(ER_OUT_OF_RESOURCES, MYF(0));
+ return true;
+ }
+ uchar *pos= (uchar *) end();
+ pos= store_length(pos, fk_io_version);
+
+ pos= store_length(pos, fk_count);
+ for (FK_info &fk: foreign_keys)
+ store_fk(fk, pos);
+
+ pos= store_length(pos, referenced_keys.elements);
+ pos= store_length(pos, 0); // Reserved: stored referenced keys count
+ pos= store_length(pos, hints.size());
+ for (const Table_name &hint: hints)
+ {
+ pos= store_string(pos, hint.db);
+ pos= store_string(pos, hint.name);
+ }
+
+ size_t new_length= (char *) pos - ptr();
+ DBUG_ASSERT(new_length < alloced_length());
+ length((uint32) new_length);
+ return false;
+}
+
+bool Foreign_key_io::parse(THD *thd, TABLE_SHARE *s, LEX_CUSTRING& image)
+{
+ Pos p(image);
+ size_t version, fk_count, rk_count, stored_rk_count, hint_count;
+ Lex_cstring hint_db, hint_table;
+
+ if (read_length(version, p))
+ {
+ push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, ER_CANNOT_ADD_FOREIGN,
+ "Foreign_key_io failed to read binary data version");
+ return true;
+ }
+ if (read_length(fk_count, p))
+ {
+ push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, ER_CANNOT_ADD_FOREIGN,
+ "Foreign_key_io failed to read foreign key count");
+ return true;
+ }
+ if (version > fk_io_version)
+ {
+ push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, ER_CANNOT_ADD_FOREIGN,
+ "Foreign_key_io does not support %d version of binary data", version);
+ push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE, ER_CANNOT_ADD_FOREIGN,
+ "Foreign_key_io max supported version is %d", fk_io_version);
+ return true;
+ }
+ for (uint i= 0; i < fk_count; ++i)
+ {
+ FK_info *dst= new (&s->mem_root) FK_info();
+ if (s->foreign_keys.push_back(dst, &s->mem_root))
+ {
+ my_error(ER_OUT_OF_RESOURCES, MYF(0));
+ return true;
+ }
+ if (read_string(dst->foreign_id, &s->mem_root, p))
+ return true;
+ dst->foreign_db= s->db;
+ dst->foreign_table= s->table_name;
+ if (read_string(dst->referenced_db, &s->mem_root, p))
+ return true;
+ if (!dst->referenced_db.length)
+ dst->referenced_db.strdup(&s->mem_root, s->db);
+ if (read_string(dst->referenced_table, &s->mem_root, p))
+ return true;
+ size_t update_method, delete_method;
+ if (read_length(update_method, p))
+ return true;
+ if (read_length(delete_method, p))
+ return true;
+ if (update_method > FK_OPTION_SET_DEFAULT || delete_method > FK_OPTION_SET_DEFAULT)
+ return true;
+ dst->update_method= (enum_fk_option) update_method;
+ dst->delete_method= (enum_fk_option) delete_method;
+ size_t col_count;
+ if (read_length(col_count, p))
+ return true;
+ for (uint j= 0; j < col_count; ++j)
+ {
+ Lex_cstring *field_name= new (&s->mem_root) Lex_cstring;
+ if (!field_name ||
+ dst->foreign_fields.push_back(field_name, &s->mem_root))
+ {
+ my_error(ER_OUT_OF_RESOURCES, MYF(0));
+ return true;
+ }
+ if (read_string(*field_name, &s->mem_root, p))
+ return true;
+ field_name= new (&s->mem_root) Lex_cstring;
+ if (!field_name ||
+ dst->referenced_fields.push_back(field_name, &s->mem_root))
+ {
+ my_error(ER_OUT_OF_RESOURCES, MYF(0));
+ return true;
+ }
+ if (read_string(*field_name, &s->mem_root, p))
+ return true;
+ }
+ /* If it is self-reference we also push to referenced_keys: */
+ if (dst->self_ref() && s->referenced_keys.push_back(dst, &s->mem_root))
+ {
+ my_error(ER_OUT_OF_RESOURCES, MYF(0));
+ return true;
+ }
+ }
+ if (read_length(rk_count, p))
+ {
+ push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, ER_CANNOT_ADD_FOREIGN,
+ "Foreign_key_io failed to read referenced keys count");
+ return true;
+ }
+ if (read_length(stored_rk_count, p))
+ {
+ push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, ER_CANNOT_ADD_FOREIGN,
+ "Foreign_key_io failed to read referenced keys count");
+ return true;
+ }
+ if (stored_rk_count > 0)
+ {
+ my_error(ER_NOT_SUPPORTED_YET, MYF(0), "stored referenced keys");
+ DBUG_ASSERT(0);
+ return true;
+ }
+ if (read_length(hint_count, p))
+ {
+ push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, ER_CANNOT_ADD_FOREIGN,
+ "Foreign_key_io failed to read reference hints count");
+ return true;
+ }
+
+ const bool shallow_hints= s->tmp_table || s->open_flags & GTS_FK_SHALLOW_HINTS;
+
+ for (uint i= 0; i < hint_count; ++i)
+ {
+ if (read_string(hint_db, &s->mem_root, p))
+ return true;
+ if (read_string(hint_table, &s->mem_root, p))
+ return true;
+ // NB: we do not store self-references into referenced hints
+ DBUG_ASSERT(cmp_table(hint_db, s->db) || cmp_table(hint_table, s->table_name));
+ if (shallow_hints)
+ {
+ /* For DROP TABLE we don't need full reference resolution. We just need
+ to know if anything from the outside references the dropped table. */
+ FK_info *dst= new (&s->mem_root) FK_info;
+ dst->foreign_db= hint_db;
+ dst->foreign_table= hint_table;
+ dst->referenced_db= s->db;
+ dst->referenced_table= s->table_name;
+ if (s->referenced_keys.push_back(dst, &s->mem_root))
+ {
+ my_error(ER_OUT_OF_RESOURCES, MYF(0));
+ return true;
+ }
+ continue;
+ }
+ TABLE_SHARE *fs= NULL;
+ for (TABLE_SHARE &c: thd->fk_circular_check)
+ {
+ if (!cmp_table(c.db, hint_db) && !cmp_table(c.table_name, hint_table))
+ {
+ fs= &c;
+ break;
+ }
+ }
+ TABLE_LIST tl;
+ Share_acquire sa;
+ tl.init_one_table(&hint_db, &hint_table, &hint_table, TL_IGNORE);
+ if (!fs)
+ {
+ if (thd->fk_circular_check.push_front(s))
+ {
+ my_error(ER_OUT_OF_RESOURCES, MYF(0));
+ return true;
+ }
+ sa.acquire(thd, tl);
+ thd->fk_circular_check.pop();
+ if (!sa.share)
+ {
+ DBUG_ASSERT(thd->is_error());
+ if (thd->get_stmt_da()->sql_errno() == ER_NO_SUCH_TABLE)
+ {
+ thd->clear_error();
+ push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, ER_CANNOT_ADD_FOREIGN,
+ "Reference hint to non-existent table `%s.%s` skipped",
+ hint_db.str, hint_table.str);
+ rk_count--;
+ continue;
+ }
+ return true;
+ }
+ fs= sa.share;
+ }
+ size_t refs_was= s->referenced_keys.elements;
+ if (s->fk_resolve_referenced_keys(thd, fs))
+ return true;
+ if (s->referenced_keys.elements == refs_was)
+ {
+ push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, ER_CANNOT_ADD_FOREIGN,
+ "Table `%s.%s` has no foreign keys to `%s.%s`",
+ hint_db.str, hint_table.str, s->db.str, s->table_name.str);
+ }
+ } // for (hint_count)
+ if (!shallow_hints && (s->referenced_keys.elements != rk_count))
+ {
+ push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, ER_CANNOT_ADD_FOREIGN,
+ "Expected %u refenced keys but found %u",
+ s->referenced_keys.elements, rk_count);
+ }
+ return p.pos < p.end; // Error if some data is still left
+}
+
+
+bool TABLE_SHARE::fk_resolve_referenced_keys(THD *thd, TABLE_SHARE *from)
+{
+ Lex_ident_set ids;
+ bool inserted;
+
+ for (FK_info &rk: referenced_keys)
+ {
+ DBUG_ASSERT(rk.foreign_id.length);
+ if (!ids.insert(rk.foreign_id, &inserted))
+ return true;
+
+ DBUG_ASSERT(inserted);
+ }
+
+ for (FK_info &fk: from->foreign_keys)
+ {
+ if (0 != cmp_db_table(fk.referenced_db, fk.referenced_table))
+ continue;
+
+ DBUG_ASSERT(fk.foreign_id.length);
+ if (!ids.insert(fk.foreign_id, &inserted))
+ return true;
+
+ if (!inserted)
+ {
+ push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, ER_DUP_CONSTRAINT_NAME,
+ "Foreign ID already exists `%s`", fk.foreign_id.str);
+ continue;
+ }
+
+ for (Lex_cstring &fld: fk.referenced_fields)
+ {
+ uint i;
+ for (i= 0; i < fields ; i++)
+ {
+ if (0 == cmp_ident(field[i]->field_name, fld))
+ break;
+ }
+ if (i == fields)
+ {
+ push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, ER_CANNOT_ADD_FOREIGN,
+ "Missing field `%s` hint table `%s.%s` refers to",
+ fld.str, from->db.str, from->table_name.str);
+ return true;
+ }
+ }
+ FK_info *dst= fk.clone(&mem_root);
+ if (referenced_keys.push_back(dst, &mem_root))
+ {
+ my_error(ER_OUT_OF_RESOURCES, MYF(0));
+ return true;
+ }
+ }
+ return false;
+}
diff --git a/sql/unireg.h b/sql/unireg.h
index dbff9ff77f8..ced4b54a9d6 100644
--- a/sql/unireg.h
+++ b/sql/unireg.h
@@ -155,47 +155,19 @@
#include "sql_list.h" /* List<> */
#include "field.h" /* Create_field */
-/*
- Types of values in the MariaDB extra2 frm segment.
- Each value is written as
- type: 1 byte
- length: 1 byte (1..255) or \0 and 2 bytes.
- binary value of the 'length' bytes.
-
- Older MariaDB servers can ignore values of unknown types if
- the type code is less than 128 (EXTRA2_ENGINE_IMPORTANT).
- Otherwise older (but newer than 10.0.1) servers are required
- to report an error.
-*/
-enum extra2_frm_value_type {
- EXTRA2_TABLEDEF_VERSION=0,
- EXTRA2_DEFAULT_PART_ENGINE=1,
- EXTRA2_GIS=2,
- EXTRA2_APPLICATION_TIME_PERIOD=3,
- EXTRA2_PERIOD_FOR_SYSTEM_TIME=4,
-
-#define EXTRA2_ENGINE_IMPORTANT 128
-
- EXTRA2_ENGINE_TABLEOPTS=128,
- EXTRA2_FIELD_FLAGS=129,
- EXTRA2_FIELD_DATA_TYPE_INFO=130,
- EXTRA2_PERIOD_WITHOUT_OVERLAPS=131,
-};
-
-enum extra2_field_flags {
- VERS_OPTIMIZED_UPDATE= 1 << INVISIBLE_MAX_BITS,
-};
LEX_CUSTRING build_frm_image(THD *thd, const LEX_CSTRING &table,
HA_CREATE_INFO *create_info,
List<Create_field> &create_fields,
- uint keys, KEY *key_info, handler *db_file);
+ uint keys, KEY *key_info, FK_list &foreign_keys,
+ FK_list &referenced_keys,
+ handler *db_file);
#define FRM_HEADER_SIZE 64
#define FRM_FORMINFO_SIZE 288
#define FRM_MAX_SIZE (1024*1024)
-static inline bool is_binary_frm_header(uchar *head)
+static inline bool is_binary_frm_header(const uchar *head)
{
return head[0] == 254
&& head[1] == 1
@@ -203,4 +175,76 @@ static inline bool is_binary_frm_header(uchar *head)
&& head[2] <= FRM_VER_CURRENT;
}
+
+class Key;
+class Foreign_key;
+class Foreign_key_io: public BinaryStringBuffer<512>
+{
+public:
+ static const ulonglong fk_io_version= 0;
+ struct Pos
+ {
+ uchar *pos;
+ const uchar *end;
+ Pos(LEX_CUSTRING& image)
+ {
+ pos= const_cast<uchar *>(image.str);
+ end= pos + image.length;
+ }
+ };
+ /* read */
+private:
+ static bool read_length(size_t &out, Pos &p)
+ {
+ ulonglong num= safe_net_field_length_ll(&p.pos, p.end - p.pos);
+ if (!p.pos || num > UINT_MAX32)
+ return true;
+ out= (uint32_t) num;
+ return false;
+ }
+ static bool read_string(Lex_cstring &to, MEM_ROOT *mem_root, Pos &p)
+ {
+ if (read_length(to.length, p) || p.pos + to.length > p.end)
+ return true; // Not enough data
+ if (!to.length)
+ return false;
+ to.str= strmake_root(mem_root, (char *) p.pos, to.length);
+ if (!to.str)
+ {
+ my_error(ER_OUT_OF_RESOURCES, MYF(0));
+ return true;
+ }
+ p.pos+= to.length;
+ return false;
+ }
+public:
+ Foreign_key_io() {}
+ bool parse(THD *thd, TABLE_SHARE *s, LEX_CUSTRING &image);
+
+ /* write */
+private:
+ static uchar *store_length(uchar *pos, ulonglong length)
+ {
+ return net_store_length(pos, length);
+ }
+ static uchar *store_string(uchar *pos, const LEX_CSTRING &str, bool nullable= false)
+ {
+ DBUG_ASSERT(nullable || str.length);
+ pos= store_length(pos, str.length);
+ if (str.length)
+ memcpy(pos, str.str, str.length);
+ return pos + str.length;
+ }
+ static ulonglong string_size(Lex_cstring str)
+ {
+ return net_length_size(str.length) + str.length;
+ }
+
+public:
+ ulonglong fk_size(FK_info &fk);
+ ulonglong hint_size(FK_info &rk);
+ void store_fk(FK_info &fk, uchar *&pos);
+ bool store(FK_list &foreign_keys, FK_list &referenced_keys);
+};
+
#endif
diff --git a/sql/wsrep_mysqld.cc b/sql/wsrep_mysqld.cc
index 8395bbc6cc2..873c0aab796 100644
--- a/sql/wsrep_mysqld.cc
+++ b/sql/wsrep_mysqld.cc
@@ -1285,16 +1285,11 @@ wsrep_append_fk_parent_table(THD* thd, TABLE_LIST* tables, wsrep::key_array* key
{
if (!is_temporary_table(table) && table->table)
{
- FOREIGN_KEY_INFO *f_key_info;
- List<FOREIGN_KEY_INFO> f_key_list;
-
- table->table->file->get_foreign_key_list(thd, &f_key_list);
- List_iterator_fast<FOREIGN_KEY_INFO> it(f_key_list);
- while ((f_key_info=it++))
+ for (const FK_info &fk: table->table->s->foreign_keys)
{
- WSREP_DEBUG("appended fkey %s", f_key_info->referenced_table->str);
- keys->push_back(wsrep_prepare_key_for_toi(f_key_info->referenced_db->str,
- f_key_info->referenced_table->str,
+ WSREP_DEBUG("appended fkey %s", fk.referenced_table.str);
+ keys->push_back(wsrep_prepare_key_for_toi(fk.ref_db().str,
+ fk.referenced_table.str,
wsrep::key::shared));
}
}
@@ -1403,7 +1398,7 @@ static bool wsrep_prepare_keys_for_alter_add_fk(const char* child_table_db,
List_iterator<Key> key_iterator(const_cast<Alter_info*>(alter_info)->key_list);
while ((key= key_iterator++))
{
- if (key->type == Key::FOREIGN_KEY)
+ if (key->foreign)
{
Foreign_key *fk_key= (Foreign_key *)key;
const char *db_name= fk_key->ref_db.str;
@@ -1544,7 +1539,7 @@ wsrep_prepare_keys_for_alter_add_fk(const char* child_table_db,
List_iterator<Key> key_iterator(const_cast<Alter_info*>(alter_info)->key_list);
while ((key= key_iterator++))
{
- if (key->type == Key::FOREIGN_KEY)
+ if (key->foreign)
{
Foreign_key *fk_key= (Foreign_key *)key;
const char *db_name= fk_key->ref_db.str;
diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc
index 49b43ac95a7..143c0610102 100644
--- a/storage/innobase/handler/ha_innodb.cc
+++ b/storage/innobase/handler/ha_innodb.cc
@@ -5639,6 +5639,7 @@ ha_innobase::open(const char* name, int, uint)
}
info(HA_STATUS_NO_LOCK | HA_STATUS_VARIABLE | HA_STATUS_CONST | HA_STATUS_OPEN);
+
DBUG_RETURN(0);
}
@@ -11668,30 +11669,31 @@ class key_text
char buf[MAX_TEXT + 1];
public:
- key_text(Key* key)
+ key_text(FK_info* key)
{
char* ptr = buf;
- if (key->name.str) {
- size_t len = std::min(key->name.length, MAX_TEXT - 2);
+ if (key->foreign_id.str) {
+ Lex_cstring& name = key->foreign_id;
+ size_t len = std::min(name.length, MAX_TEXT - 2);
*(ptr++) = '`';
- memcpy(ptr, key->name.str, len);
+ memcpy(ptr, name.str, len);
ptr += len;
*(ptr++) = '`';
*ptr = '\0';
return;
}
*(ptr++) = '(';
- List_iterator_fast<Key_part_spec> it(key->columns);
- while (Key_part_spec* k = it++) {
+ List_iterator_fast<Lex_cstring> it(key->foreign_fields);
+ while (Lex_cstring* field_name = it++) {
/* 3 is etc continuation ("...");
2 is comma separator (", ") in case of next exists;
1 is terminating ')' */
if (MAX_TEXT - (size_t)(ptr - buf)
>= (it.peek() ? 3 + 2 + 1 : 3 + 1)
- + k->field_name.length) {
- memcpy(ptr, k->field_name.str,
- k->field_name.length);
- ptr += k->field_name.length;
+ + field_name->length) {
+ memcpy(ptr, field_name->str,
+ field_name->length);
+ ptr += field_name->length;
if (it.peek()) {
*(ptr++) = ',';
*(ptr++) = ' ';
@@ -11730,12 +11732,26 @@ create_table_info_t::create_foreign_keys()
ulint err_col;
const bool tmp_table = m_flags2 & DICT_TF2_TEMPORARY;
const CHARSET_INFO* cs = thd_charset(m_thd);
- const char* operation = "Create ";
const char* name = m_table_name;
+ uint old_fkeys = m_create_info->alter_info->tmp_old_fkeys;
+
+ bool alter = enum_sql_command(thd_sql_command(m_thd)) == SQLCOM_ALTER_TABLE;
+ const char* operation = alter ? "Alter " : "Create ";
+
+ if (tmp_table && !m_form->s->foreign_keys.is_empty()) {
+ ib_foreign_warn(m_trx, DB_CANNOT_ADD_CONSTRAINT,
+ create_name,
+ "%s table `%s`.`%s` with foreign key "
+ "constraint failed. "
+ "Temporary tables can't have "
+ "foreign key constraints.",
+ operation, m_form->s->db.str,
+ m_form->s->table_name.str);
- enum_sql_command sqlcom = enum_sql_command(thd_sql_command(m_thd));
+ return (DB_CANNOT_ADD_CONSTRAINT);
+ }
- if (sqlcom == SQLCOM_ALTER_TABLE) {
+ if (alter) {
dict_table_t* table_to_alter;
mem_heap_t* heap = mem_heap_create(10000);
ulint highest_id_so_far;
@@ -11767,7 +11783,6 @@ create_table_info_t::create_foreign_keys()
create_name[bufend - create_name] = '\0';
number = highest_id_so_far + 1;
mem_heap_free(heap);
- operation = "Alter ";
} else if (strstr(name, "#P#") || strstr(name, "#p#")) {
/* Partitioned table */
create_name[0] = '\0';
@@ -11779,9 +11794,7 @@ create_table_info_t::create_foreign_keys()
create_name[bufend - create_name] = '\0';
}
- Alter_info* alter_info = m_create_info->alter_info;
- ut_ad(alter_info);
- List_iterator_fast<Key> key_it(alter_info->key_list);
+ List_iterator_fast<FK_info> key_it(m_form->s->foreign_keys);
dict_table_t* table = dict_table_get_low(name);
if (!table) {
@@ -11793,28 +11806,14 @@ create_table_info_t::create_foreign_keys()
return (DB_CANNOT_ADD_CONSTRAINT);
}
- while (Key* key = key_it++) {
- if (key->type != Key::FOREIGN_KEY)
- continue;
+ while (FK_info* fk = key_it++) {
- if (tmp_table) {
- ib_foreign_warn(m_trx, DB_CANNOT_ADD_CONSTRAINT,
- create_name,
- "%s table `%s`.`%s` with foreign key "
- "constraint failed. "
- "Temporary tables can't have "
- "foreign key constraints.",
- operation, m_form->s->db.str,
- m_form->s->table_name.str);
-
- return (DB_CANNOT_ADD_CONSTRAINT);
- } else if (!*create_name) {
- ut_ad("should be unreachable" == 0);
- return DB_CANNOT_ADD_CONSTRAINT;
+ if (old_fkeys) {
+ old_fkeys--;
+ continue;
}
- Foreign_key* fk = static_cast<Foreign_key*>(key);
- Key_part_spec* col;
+ LEX_CSTRING* col;
bool success;
dict_foreign_t* foreign = dict_mem_foreign_create();
@@ -11822,12 +11821,50 @@ create_table_info_t::create_foreign_keys()
return (DB_OUT_OF_MEMORY);
}
- List_iterator_fast<Key_part_spec> col_it(fk->columns);
+ if (fk->foreign_id.str) {
+ ulint db_len;
+
+ /* Catenate 'databasename/' to the constraint name
+ specified by the user: we conceive the constraint as
+ belonging to the same MySQL 'database' as the table
+ itself. We store the name to foreign->id. */
+
+ db_len = dict_get_db_name_len(table->name.m_name);
+
+ foreign->id = static_cast<char*>(mem_heap_alloc(
+ foreign->heap,
+ db_len + fk->foreign_id.length + 2));
+
+ memcpy(foreign->id, table->name.m_name, db_len);
+ foreign->id[db_len] = '/';
+ strcpy(foreign->id + db_len + 1,
+ fk->foreign_id.str);
+ }
+
+ if (foreign->id == NULL) {
+ error = dict_create_add_foreign_id(
+ &number, table->name.m_name, foreign);
+ if (error != DB_SUCCESS) {
+ dict_foreign_free(foreign);
+ return (error);
+ }
+ }
+
+ std::pair<dict_foreign_set::iterator, bool> ret
+ = local_fk_set.insert(foreign);
+
+ if (!ret.second) {
+ /* A duplicate foreign key name has been found */
+ dict_foreign_free(foreign);
+ return (DB_CANNOT_ADD_CONSTRAINT);
+ }
+
+
+ List_iterator_fast<Lex_cstring> col_it(fk->foreign_fields);
unsigned i = 0, j = 0;
while ((col = col_it++)) {
column_names[i] = mem_heap_strdupl(
- foreign->heap, col->field_name.str,
- col->field_name.length);
+ foreign->heap, col->str, col->length);
success = find_col(table, column_names + i);
if (!success) {
key_text k(fk);
@@ -11838,7 +11875,6 @@ create_table_info_t::create_foreign_keys()
" failed. Column %s was not found.",
operation, create_name, k.str(),
column_names[i]);
- dict_foreign_free(foreign);
return (DB_CANNOT_ADD_CONSTRAINT);
}
++i;
@@ -11852,7 +11888,6 @@ create_table_info_t::create_foreign_keys()
"allowed).",
operation, create_name, k.str(), i,
MAX_COLS_PER_FK);
- dict_foreign_free(foreign);
return (DB_CANNOT_ADD_CONSTRAINT);
}
}
@@ -11867,45 +11902,6 @@ create_table_info_t::create_foreign_keys()
k.str(), column_names,
index_error, err_col,
err_index, table);
- dict_foreign_free(foreign);
- return (DB_CANNOT_ADD_CONSTRAINT);
- }
-
- if (fk->constraint_name.str) {
- ulint db_len;
-
- /* Catenate 'databasename/' to the constraint name
- specified by the user: we conceive the constraint as
- belonging to the same MySQL 'database' as the table
- itself. We store the name to foreign->id. */
-
- db_len = dict_get_db_name_len(table->name.m_name);
-
- foreign->id = static_cast<char*>(mem_heap_alloc(
- foreign->heap,
- db_len + fk->constraint_name.length + 2));
-
- memcpy(foreign->id, table->name.m_name, db_len);
- foreign->id[db_len] = '/';
- strcpy(foreign->id + db_len + 1,
- fk->constraint_name.str);
- }
-
- if (foreign->id == NULL) {
- error = dict_create_add_foreign_id(
- &number, table->name.m_name, foreign);
- if (error != DB_SUCCESS) {
- dict_foreign_free(foreign);
- return (error);
- }
- }
-
- std::pair<dict_foreign_set::iterator, bool> ret
- = local_fk_set.insert(foreign);
-
- if (!ret.second) {
- /* A duplicate foreign key name has been found */
- dict_foreign_free(foreign);
return (DB_CANNOT_ADD_CONSTRAINT);
}
@@ -11931,8 +11927,8 @@ create_table_info_t::create_foreign_keys()
i * sizeof(void*));
foreign->referenced_table_name = dict_get_referenced_table(
- name, LEX_STRING_WITH_LEN(fk->ref_db),
- LEX_STRING_WITH_LEN(fk->ref_table),
+ name, LEX_STRING_WITH_LEN(fk->ref_db()),
+ LEX_STRING_WITH_LEN(fk->referenced_table),
&foreign->referenced_table, foreign->heap, cs);
if (!foreign->referenced_table_name) {
@@ -11969,11 +11965,10 @@ create_table_info_t::create_foreign_keys()
return (DB_CANNOT_ADD_CONSTRAINT);
}
- col_it.init(fk->ref_columns);
+ col_it.init(fk->referenced_fields);
while ((col = col_it++)) {
ref_column_names[j] = mem_heap_strdupl(
- foreign->heap, col->field_name.str,
- col->field_name.length);
+ foreign->heap, col->str, col->length);
if (foreign->referenced_table) {
success = find_col(foreign->referenced_table,
ref_column_names + j);
@@ -12034,8 +12029,8 @@ create_table_info_t::create_foreign_keys()
memcpy(foreign->referenced_col_names, ref_column_names,
i * sizeof(void*));
- if (fk->delete_opt == FK_OPTION_SET_NULL
- || fk->update_opt == FK_OPTION_SET_NULL) {
+ if (fk->delete_method == FK_OPTION_SET_NULL
+ || fk->update_method == FK_OPTION_SET_NULL) {
for (j = 0; j < foreign->n_fields; j++) {
if ((dict_index_get_nth_col(
foreign->foreign_index, j)
@@ -12073,7 +12068,7 @@ create_table_info_t::create_foreign_keys()
}
}
- switch (fk->delete_opt) {
+ switch (fk->delete_method) {
case FK_OPTION_UNDEF:
case FK_OPTION_RESTRICT:
break;
@@ -12094,7 +12089,7 @@ create_table_info_t::create_foreign_keys()
break;
}
- switch (fk->update_opt) {
+ switch (fk->update_method) {
case FK_OPTION_UNDEF:
case FK_OPTION_RESTRICT:
break;
@@ -12129,8 +12124,7 @@ create_table_info_t::create_foreign_keys()
trx_set_dict_operation(m_trx, TRX_DICT_OP_TABLE);
- error = dict_create_add_foreigns_to_dictionary(local_fk_set, table,
- m_trx);
+ error = dict_create_add_foreigns_to_dictionary(local_fk_set, table, m_trx);
if (error == DB_SUCCESS) {
@@ -12264,7 +12258,8 @@ int create_table_info_t::create_table(bool create_fk)
dict_table_get_all_fts_indexes(m_table, fts->indexes);
}
- dberr_t err = create_fk ? create_foreign_keys() : DB_SUCCESS;
+ dberr_t err = create_fk && !m_form->s->foreign_keys.is_empty()
+ ? create_foreign_keys() : DB_SUCCESS;
if (err == DB_SUCCESS) {
/* Check that also referencing constraints are ok */
@@ -14763,223 +14758,6 @@ ha_innobase::get_foreign_key_create_info(void)
return(fk_str);
}
-
-/***********************************************************************//**
-Maps a InnoDB foreign key constraint to a equivalent MySQL foreign key info.
-@return pointer to foreign key info */
-static
-FOREIGN_KEY_INFO*
-get_foreign_key_info(
-/*=================*/
- THD* thd, /*!< in: user thread handle */
- dict_foreign_t* foreign)/*!< in: foreign key constraint */
-{
- FOREIGN_KEY_INFO f_key_info;
- FOREIGN_KEY_INFO* pf_key_info;
- uint i = 0;
- size_t len;
- char tmp_buff[NAME_LEN+1];
- char name_buff[NAME_LEN+1];
- const char* ptr;
- LEX_CSTRING* referenced_key_name;
- LEX_CSTRING* name = NULL;
-
- if (dict_table_t::is_temporary_name(foreign->foreign_table_name)) {
- return NULL;
- }
-
- ptr = dict_remove_db_name(foreign->id);
- f_key_info.foreign_id = thd_make_lex_string(
- thd, 0, ptr, strlen(ptr), 1);
-
- /* Name format: database name, '/', table name, '\0' */
-
- /* Referenced (parent) database name */
- len = dict_get_db_name_len(foreign->referenced_table_name);
- ut_a(len < sizeof(tmp_buff));
- memcpy(tmp_buff, foreign->referenced_table_name, len);
- tmp_buff[len] = 0;
-
- len = filename_to_tablename(tmp_buff, name_buff, sizeof(name_buff));
- f_key_info.referenced_db = thd_make_lex_string(
- thd, 0, name_buff, len, 1);
-
- /* Referenced (parent) table name */
- ptr = dict_remove_db_name(foreign->referenced_table_name);
- len = filename_to_tablename(ptr, name_buff, sizeof(name_buff), 1);
- f_key_info.referenced_table = thd_make_lex_string(
- thd, 0, name_buff, len, 1);
-
- /* Dependent (child) database name */
- len = dict_get_db_name_len(foreign->foreign_table_name);
- ut_a(len < sizeof(tmp_buff));
- memcpy(tmp_buff, foreign->foreign_table_name, len);
- tmp_buff[len] = 0;
-
- len = filename_to_tablename(tmp_buff, name_buff, sizeof(name_buff));
- f_key_info.foreign_db = thd_make_lex_string(
- thd, 0, name_buff, len, 1);
-
- /* Dependent (child) table name */
- ptr = dict_remove_db_name(foreign->foreign_table_name);
- len = filename_to_tablename(ptr, name_buff, sizeof(name_buff), 1);
- f_key_info.foreign_table = thd_make_lex_string(
- thd, 0, name_buff, len, 1);
-
- do {
- ptr = foreign->foreign_col_names[i];
- name = thd_make_lex_string(thd, name, ptr,
- strlen(ptr), 1);
- f_key_info.foreign_fields.push_back(name);
- ptr = foreign->referenced_col_names[i];
- name = thd_make_lex_string(thd, name, ptr,
- strlen(ptr), 1);
- f_key_info.referenced_fields.push_back(name);
- } while (++i < foreign->n_fields);
-
- if (foreign->type & DICT_FOREIGN_ON_DELETE_CASCADE) {
- f_key_info.delete_method = FK_OPTION_CASCADE;
- } else if (foreign->type & DICT_FOREIGN_ON_DELETE_SET_NULL) {
- f_key_info.delete_method = FK_OPTION_SET_NULL;
- } else if (foreign->type & DICT_FOREIGN_ON_DELETE_NO_ACTION) {
- f_key_info.delete_method = FK_OPTION_NO_ACTION;
- } else {
- f_key_info.delete_method = FK_OPTION_RESTRICT;
- }
-
-
- if (foreign->type & DICT_FOREIGN_ON_UPDATE_CASCADE) {
- f_key_info.update_method = FK_OPTION_CASCADE;
- } else if (foreign->type & DICT_FOREIGN_ON_UPDATE_SET_NULL) {
- f_key_info.update_method = FK_OPTION_SET_NULL;
- } else if (foreign->type & DICT_FOREIGN_ON_UPDATE_NO_ACTION) {
- f_key_info.update_method = FK_OPTION_NO_ACTION;
- } else {
- f_key_info.update_method = FK_OPTION_RESTRICT;
- }
-
- /* Load referenced table to update FK referenced key name. */
- if (foreign->referenced_table == NULL) {
-
- dict_table_t* ref_table;
-
- dict_sys.assert_locked();
- ref_table = dict_table_open_on_name(
- foreign->referenced_table_name_lookup,
- TRUE, FALSE, DICT_ERR_IGNORE_NONE);
-
- if (ref_table == NULL) {
-
- if (!thd_test_options(
- thd, OPTION_NO_FOREIGN_KEY_CHECKS)) {
- ib::info()
- << "Foreign Key referenced table "
- << foreign->referenced_table_name
- << " not found for foreign table "
- << foreign->foreign_table_name;
- }
- } else {
-
- dict_table_close(ref_table, TRUE, FALSE);
- }
- }
-
- if (foreign->referenced_index
- && foreign->referenced_index->name != NULL) {
- referenced_key_name = thd_make_lex_string(
- thd,
- f_key_info.referenced_key_name,
- foreign->referenced_index->name,
- strlen(foreign->referenced_index->name),
- 1);
- } else {
- referenced_key_name = NULL;
- }
-
- f_key_info.referenced_key_name = referenced_key_name;
-
- pf_key_info = (FOREIGN_KEY_INFO*) thd_memdup(thd, &f_key_info,
- sizeof(FOREIGN_KEY_INFO));
-
- return(pf_key_info);
-}
-
-/*******************************************************************//**
-Gets the list of foreign keys in this table.
-@return always 0, that is, always succeeds */
-
-int
-ha_innobase::get_foreign_key_list(
-/*==============================*/
- THD* thd, /*!< in: user thread handle */
- List<FOREIGN_KEY_INFO>* f_key_list) /*!< out: foreign key list */
-{
- update_thd(ha_thd());
-
- m_prebuilt->trx->op_info = "getting list of foreign keys";
-
- dict_sys.mutex_lock();
-
- for (dict_foreign_set::iterator it
- = m_prebuilt->table->foreign_set.begin();
- it != m_prebuilt->table->foreign_set.end();
- ++it) {
-
- FOREIGN_KEY_INFO* pf_key_info;
- dict_foreign_t* foreign = *it;
-
- pf_key_info = get_foreign_key_info(thd, foreign);
-
- if (pf_key_info != NULL) {
- f_key_list->push_back(pf_key_info);
- }
- }
-
- dict_sys.mutex_unlock();
-
- m_prebuilt->trx->op_info = "";
-
- return(0);
-}
-
-/*******************************************************************//**
-Gets the set of foreign keys where this table is the referenced table.
-@return always 0, that is, always succeeds */
-
-int
-ha_innobase::get_parent_foreign_key_list(
-/*=====================================*/
- THD* thd, /*!< in: user thread handle */
- List<FOREIGN_KEY_INFO>* f_key_list) /*!< out: foreign key list */
-{
- update_thd(ha_thd());
-
- m_prebuilt->trx->op_info = "getting list of referencing foreign keys";
-
- dict_sys.mutex_lock();
-
- for (dict_foreign_set::iterator it
- = m_prebuilt->table->referenced_set.begin();
- it != m_prebuilt->table->referenced_set.end();
- ++it) {
-
- FOREIGN_KEY_INFO* pf_key_info;
- dict_foreign_t* foreign = *it;
-
- pf_key_info = get_foreign_key_info(thd, foreign);
-
- if (pf_key_info != NULL) {
- f_key_list->push_back(pf_key_info);
- }
- }
-
- dict_sys.mutex_unlock();
-
- m_prebuilt->trx->op_info = "";
-
- return(0);
-}
-
/** Table list item structure is used to store only the table
and name. It is used by get_cascade_foreign_key_table_list to store
the intermediate result for fetching the table set. */
diff --git a/storage/innobase/handler/ha_innodb.h b/storage/innobase/handler/ha_innodb.h
index 7eec6eb5a8c..ebaba2dbb10 100644
--- a/storage/innobase/handler/ha_innodb.h
+++ b/storage/innobase/handler/ha_innodb.h
@@ -213,16 +213,9 @@ public:
char* get_foreign_key_create_info() override;
- int get_foreign_key_list(THD *thd,
- List<FOREIGN_KEY_INFO> *f_key_list) override;
-
- int get_parent_foreign_key_list(
- THD* thd,
- List<FOREIGN_KEY_INFO>* f_key_list) override;
-
bool can_switch_engines() override;
- uint referenced_by_foreign_key() override;
+ uint referenced_by_foreign_key();
void free_foreign_key_create_info(char* str) override;
diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc
index a2aefe4bdac..da712f909d3 100644
--- a/storage/innobase/handler/handler0alter.cc
+++ b/storage/innobase/handler/handler0alter.cc
@@ -2697,12 +2697,10 @@ bool
innobase_set_foreign_key_option(
/*============================*/
dict_foreign_t* foreign, /*!< in:InnoDB Foreign key */
- Foreign_key* fk_key) /*!< in: Foreign key info from
+ FK_info* fk_key) /*!< in: Foreign key info from
MySQL */
{
- ut_ad(!foreign->type);
-
- switch (fk_key->delete_opt) {
+ switch (fk_key->delete_method) {
case FK_OPTION_NO_ACTION:
case FK_OPTION_RESTRICT:
case FK_OPTION_SET_DEFAULT:
@@ -2718,7 +2716,7 @@ innobase_set_foreign_key_option(
break;
}
- switch (fk_key->update_opt) {
+ switch (fk_key->update_method) {
case FK_OPTION_NO_ACTION:
case FK_OPTION_RESTRICT:
case FK_OPTION_SET_DEFAULT:
@@ -2932,16 +2930,21 @@ innobase_get_foreign_key_info(
ulint num_fk = 0;
Alter_info* alter_info = ha_alter_info->alter_info;
const CHARSET_INFO* cs = thd_charset(trx->mysql_thd);
+ uint old_fkeys = alter_info->tmp_old_fkeys;
DBUG_ENTER("innobase_get_foreign_key_info");
*n_add_fk = 0;
- for (Key& key : alter_info->key_list) {
- if (key.type != Key::FOREIGN_KEY) {
+ for (FK_info& fk_key: ha_alter_info->alter_ctx->foreign_keys) {
+
+ if (old_fkeys) {
+ old_fkeys--;
continue;
}
+ DBUG_ASSERT(fk_key.foreign_id.str); // generated by mysql_prepare_create_table()
+
const char* column_names[MAX_NUM_FK_COLUMNS];
dict_index_t* index = NULL;
const char* referenced_column_names[MAX_NUM_FK_COLUMNS];
@@ -2950,15 +2953,13 @@ innobase_get_foreign_key_info(
ulint referenced_num_col = 0;
bool correct_option;
- Foreign_key* fk_key = static_cast<Foreign_key*>(&key);
-
- if (fk_key->columns.elements > 0) {
+ if (fk_key.foreign_fields.elements > 0) {
ulint i = 0;
/* Get all the foreign key column info for the
current table */
- for (const Key_part_spec& column : fk_key->columns) {
- column_names[i] = column.field_name.str;
+ for (Lex_cstring& column: fk_key.foreign_fields) {
+ column_names[i] = column.str;
ut_ad(i < MAX_NUM_FK_COLUMNS);
i++;
}
@@ -2985,8 +2986,7 @@ innobase_get_foreign_key_info(
my_error(
ER_FK_NO_INDEX_CHILD,
MYF(0),
- fk_key->name.str
- ? fk_key->name.str : "",
+ fk_key.foreign_id.str,
table_share->table_name.str);
goto err_exit;
}
@@ -3000,8 +3000,8 @@ innobase_get_foreign_key_info(
referenced_table_name = dict_get_referenced_table(
table->name.m_name,
- LEX_STRING_WITH_LEN(fk_key->ref_db),
- LEX_STRING_WITH_LEN(fk_key->ref_table),
+ LEX_STRING_WITH_LEN(fk_key.ref_db()),
+ LEX_STRING_WITH_LEN(fk_key.referenced_table),
&referenced_table,
add_fk[num_fk]->heap, cs);
@@ -3014,17 +3014,16 @@ innobase_get_foreign_key_info(
if (!referenced_table && trx->check_foreigns) {
dict_sys.mutex_unlock();
my_error(ER_FK_CANNOT_OPEN_PARENT,
- MYF(0), fk_key->ref_table.str);
+ MYF(0), fk_key.referenced_table.str);
goto err_exit;
}
- if (fk_key->ref_columns.elements > 0) {
+ if (fk_key.referenced_fields.elements > 0) {
ulint i = 0;
- for (Key_part_spec &column : fk_key->ref_columns) {
- referenced_column_names[i] =
- column.field_name.str;
+ for (Lex_cstring &column: fk_key.referenced_fields) {
+ referenced_column_names[i] = column.str;
ut_ad(i < MAX_NUM_FK_COLUMNS);
i++;
}
@@ -3047,9 +3046,8 @@ innobase_get_foreign_key_info(
if (!referenced_index) {
dict_sys.mutex_unlock();
my_error(ER_FK_NO_INDEX_PARENT, MYF(0),
- fk_key->name.str
- ? fk_key->name.str : "",
- fk_key->ref_table.str);
+ fk_key.foreign_id.str,
+ fk_key.referenced_table.str);
goto err_exit;
}
} else {
@@ -3062,12 +3060,12 @@ innobase_get_foreign_key_info(
referenced column */
dict_sys.mutex_unlock();
my_error(ER_CANNOT_ADD_FOREIGN, MYF(0),
- fk_key->ref_table.str);
+ fk_key.referenced_table.str);
goto err_exit;
}
if (!innobase_init_foreign(
- add_fk[num_fk], fk_key->name.str,
+ add_fk[num_fk], fk_key.foreign_id.str,
table, index, column_names,
num_col, referenced_table_name,
referenced_table, referenced_index,
@@ -3083,7 +3081,7 @@ innobase_get_foreign_key_info(
dict_sys.mutex_unlock();
correct_option = innobase_set_foreign_key_option(
- add_fk[num_fk], fk_key);
+ add_fk[num_fk], &fk_key);
DBUG_EXECUTE_IF("innodb_test_wrong_fk_option",
correct_option = false;);
@@ -7781,6 +7779,7 @@ check_if_ok_to_rename:
if (ha_alter_info->handler_flags
& ALTER_DROP_FOREIGN_KEY) {
+ // FIXME: remove in MDEV-21052
DBUG_ASSERT(ha_alter_info->alter_info->drop_list.elements > 0);
drop_fk = static_cast<dict_foreign_t**>(
diff --git a/storage/mroonga/ha_mroonga.cpp b/storage/mroonga/ha_mroonga.cpp
index 4747495fd22..1bb231c9c97 100644
--- a/storage/mroonga/ha_mroonga.cpp
+++ b/storage/mroonga/ha_mroonga.cpp
@@ -3635,7 +3635,7 @@ bool ha_mroonga::storage_create_foreign_key(TABLE *table,
char ref_db_buff[NAME_LEN + 1], ref_table_buff[NAME_LEN + 1];
while ((key = key_iterator++))
{
- if (key->type != MRN_KEYTYPE_FOREIGN)
+ if (!key->foreign)
{
continue;
}
@@ -16505,10 +16505,8 @@ char *ha_mroonga::storage_get_foreign_key_create_info()
LEX_CSTRING table_name= { ref_table_buff, (size_t) ref_table_name_length };
table_list.init_one_table(&table_share->db, &table_name, 0, TL_WRITE);
- mrn_open_mutex_lock(table_share);
tmp_ref_table_share =
mrn_create_tmp_table_share(&table_list, ref_path, &error);
- mrn_open_mutex_unlock(table_share);
if (!tmp_ref_table_share) {
DBUG_RETURN(NULL);
}
@@ -16517,9 +16515,7 @@ char *ha_mroonga::storage_get_foreign_key_create_info()
Field *ref_field = &ref_key_info->key_part->field[0];
append_identifier(ha_thd(), &create_info_str, ref_field->field_name.str,
ref_field->field_name.length);
- mrn_open_mutex_lock(table_share);
mrn_free_tmp_table_share(tmp_ref_table_share);
- mrn_open_mutex_unlock(table_share);
if (create_info_str.reserve(39)) {
DBUG_RETURN(NULL);
}
@@ -16623,19 +16619,6 @@ bool ha_mroonga::can_switch_engines()
DBUG_RETURN(res);
}
-int ha_mroonga::wrapper_get_foreign_key_list(THD *thd,
- List<FOREIGN_KEY_INFO> *f_key_list)
-{
- MRN_DBUG_ENTER_METHOD();
- int res;
- MRN_SET_WRAP_SHARE_KEY(share, table->s);
- MRN_SET_WRAP_TABLE_KEY(this, table);
- res = wrap_handler->get_foreign_key_list(thd, f_key_list);
- MRN_SET_BASE_SHARE_KEY(share, table->s);
- MRN_SET_BASE_TABLE_KEY(this, table);
- DBUG_RETURN(res);
-}
-
#ifdef MRN_SUPPORT_FOREIGN_KEYS
int ha_mroonga::storage_get_foreign_key_list(THD *thd,
List<FOREIGN_KEY_INFO> *f_key_list)
@@ -16664,19 +16647,12 @@ int ha_mroonga::storage_get_foreign_key_list(THD *thd,
grn_id ref_table_id = grn_obj_get_range(ctx, column);
grn_obj *ref_table = grn_ctx_at(ctx, ref_table_id);
FOREIGN_KEY_INFO f_key_info;
- f_key_info.foreign_id = thd_make_lex_string(thd,
- NULL,
- column_name.c_str(),
- column_name.length(),
- TRUE);
- f_key_info.foreign_db = thd_make_lex_string(thd, NULL,
- table_share->db.str,
- table_share->db.length,
- TRUE);
- f_key_info.foreign_table = thd_make_lex_string(thd, NULL,
- table_share->table_name.str,
- table_share->table_name.length,
- TRUE);
+ thd_make_lex_string(thd, &f_key_info.foreign_id, column_name.c_str(),
+ column_name.length(), false);
+ thd_make_lex_string(thd, &f_key_info.foreign_db, table_share->db.str,
+ table_share->db.length, false);
+ thd_make_lex_string(thd, &f_key_info.foreign_table, table_share->table_name.str,
+ table_share->table_name.length, false);
f_key_info.referenced_db = f_key_info.foreign_db;
char ref_table_buff[NAME_LEN + 1];
@@ -16685,20 +16661,16 @@ int ha_mroonga::storage_get_foreign_key_list(THD *thd,
ref_table_buff[ref_table_name_length] = '\0';
DBUG_PRINT("info", ("mroonga: ref_table_buff=%s", ref_table_buff));
DBUG_PRINT("info", ("mroonga: ref_table_name_length=%d", ref_table_name_length));
- f_key_info.referenced_table = thd_make_lex_string(thd, NULL,
- ref_table_buff,
- ref_table_name_length,
- TRUE);
+ thd_make_lex_string(thd, &f_key_info.referenced_table, ref_table_buff,
+ ref_table_name_length, false);
f_key_info.update_method = FK_OPTION_RESTRICT;
f_key_info.delete_method = FK_OPTION_RESTRICT;
- f_key_info.referenced_key_name = thd_make_lex_string(thd, NULL, "PRIMARY",
- 7, TRUE);
LEX_CSTRING *field_name = thd_make_lex_string(thd,
NULL,
column_name.c_str(),
column_name.length(),
TRUE);
- f_key_info.foreign_fields.push_back(field_name);
+ f_key_info.foreign_fields.push_back(static_cast<Lex_cstring *>(field_name));
char ref_path[FN_REFLEN + 1];
TABLE_LIST table_list;
@@ -16723,7 +16695,7 @@ int ha_mroonga::storage_get_foreign_key_list(THD *thd,
ref_field->field_name.str,
ref_field->field_name.length,
TRUE);
- f_key_info.referenced_fields.push_back(ref_col_name);
+ f_key_info.referenced_fields.push_back(static_cast<Lex_cstring *>(ref_col_name));
mrn_open_mutex_lock(table_share);
mrn_free_tmp_table_share(tmp_ref_table_share);
mrn_open_mutex_unlock(table_share);
@@ -16742,92 +16714,10 @@ int ha_mroonga::storage_get_foreign_key_list(THD *thd,
List<FOREIGN_KEY_INFO> *f_key_list)
{
MRN_DBUG_ENTER_METHOD();
- int res = handler::get_foreign_key_list(thd, f_key_list);
- DBUG_RETURN(res);
+ DBUG_RETURN(0);
}
#endif
-int ha_mroonga::get_foreign_key_list(THD *thd,
- List<FOREIGN_KEY_INFO> *f_key_list)
-{
- MRN_DBUG_ENTER_METHOD();
- int res;
- if (share->wrapper_mode)
- {
- res = wrapper_get_foreign_key_list(thd, f_key_list);
- } else {
- res = storage_get_foreign_key_list(thd, f_key_list);
- }
- DBUG_RETURN(res);
-}
-
-int ha_mroonga::wrapper_get_parent_foreign_key_list(THD *thd,
- List<FOREIGN_KEY_INFO> *f_key_list)
-{
- MRN_DBUG_ENTER_METHOD();
- int res;
- MRN_SET_WRAP_SHARE_KEY(share, table->s);
- MRN_SET_WRAP_TABLE_KEY(this, table);
- res = wrap_handler->get_parent_foreign_key_list(thd, f_key_list);
- MRN_SET_BASE_SHARE_KEY(share, table->s);
- MRN_SET_BASE_TABLE_KEY(this, table);
- DBUG_RETURN(res);
-}
-
-int ha_mroonga::storage_get_parent_foreign_key_list(THD *thd,
- List<FOREIGN_KEY_INFO> *f_key_list)
-{
- MRN_DBUG_ENTER_METHOD();
- int res = handler::get_parent_foreign_key_list(thd, f_key_list);
- DBUG_RETURN(res);
-}
-
-int ha_mroonga::get_parent_foreign_key_list(THD *thd,
- List<FOREIGN_KEY_INFO> *f_key_list)
-{
- MRN_DBUG_ENTER_METHOD();
- int res;
- if (share->wrapper_mode)
- {
- res = wrapper_get_parent_foreign_key_list(thd, f_key_list);
- } else {
- res = storage_get_parent_foreign_key_list(thd, f_key_list);
- }
- DBUG_RETURN(res);
-}
-
-uint ha_mroonga::wrapper_referenced_by_foreign_key()
-{
- MRN_DBUG_ENTER_METHOD();
- uint res;
- MRN_SET_WRAP_SHARE_KEY(share, table->s);
- MRN_SET_WRAP_TABLE_KEY(this, table);
- res = wrap_handler->referenced_by_foreign_key();
- MRN_SET_BASE_SHARE_KEY(share, table->s);
- MRN_SET_BASE_TABLE_KEY(this, table);
- DBUG_RETURN(res);
-}
-
-uint ha_mroonga::storage_referenced_by_foreign_key()
-{
- MRN_DBUG_ENTER_METHOD();
- uint res = handler::referenced_by_foreign_key();
- DBUG_RETURN(res);
-}
-
-uint ha_mroonga::referenced_by_foreign_key()
-{
- MRN_DBUG_ENTER_METHOD();
- uint res;
- if (share->wrapper_mode)
- {
- res = wrapper_referenced_by_foreign_key();
- } else {
- res = storage_referenced_by_foreign_key();
- }
- DBUG_RETURN(res);
-}
-
void ha_mroonga::wrapper_init_table_handle_for_HANDLER()
{
MRN_DBUG_ENTER_METHOD();
diff --git a/storage/mroonga/ha_mroonga.hpp b/storage/mroonga/ha_mroonga.hpp
index 66767899e21..2daffb3f497 100644
--- a/storage/mroonga/ha_mroonga.hpp
+++ b/storage/mroonga/ha_mroonga.hpp
@@ -619,9 +619,6 @@ protected:
char *get_tablespace_name(THD *thd, char *name, uint name_len);
#endif
bool can_switch_engines() mrn_override;
- int get_foreign_key_list(THD *thd, List<FOREIGN_KEY_INFO> *f_key_list) mrn_override;
- int get_parent_foreign_key_list(THD *thd, List<FOREIGN_KEY_INFO> *f_key_list) mrn_override;
- uint referenced_by_foreign_key() mrn_override;
void init_table_handle_for_HANDLER() mrn_override;
void free_foreign_key_create_info(char* str) mrn_override;
#ifdef MRN_HAVE_HA_REBIND_PSI
@@ -1267,12 +1264,7 @@ private:
#endif
bool wrapper_can_switch_engines();
bool storage_can_switch_engines();
- int wrapper_get_foreign_key_list(THD *thd, List<FOREIGN_KEY_INFO> *f_key_list);
int storage_get_foreign_key_list(THD *thd, List<FOREIGN_KEY_INFO> *f_key_list);
- int wrapper_get_parent_foreign_key_list(THD *thd, List<FOREIGN_KEY_INFO> *f_key_list);
- int storage_get_parent_foreign_key_list(THD *thd, List<FOREIGN_KEY_INFO> *f_key_list);
- uint wrapper_referenced_by_foreign_key();
- uint storage_referenced_by_foreign_key();
void wrapper_init_table_handle_for_HANDLER();
void storage_init_table_handle_for_HANDLER();
void wrapper_free_foreign_key_create_info(char* str);
diff --git a/storage/mroonga/mrn_table.cpp b/storage/mroonga/mrn_table.cpp
index 037a6a59487..11332e0abbb 100644
--- a/storage/mroonga/mrn_table.cpp
+++ b/storage/mroonga/mrn_table.cpp
@@ -1072,7 +1072,7 @@ TABLE_SHARE *mrn_create_tmp_table_share(TABLE_LIST *table_list, const char *path
*error = ER_CANT_OPEN_FILE;
DBUG_RETURN(NULL);
}
- share->tmp_table = NO_TMP_TABLE; // TODO: is this right?
+ share->tmp_table = INTERNAL_TMP_TABLE;
share->path.str = (char *) path;
share->path.length = strlen(share->path.str);
share->normalized_path.str = mrn_my_strdup(path, MYF(MY_WME));
diff --git a/storage/mroonga/mysql-test/mroonga/storage/r/foreign_key_alter_add.result b/storage/mroonga/mysql-test/mroonga/storage/r/foreign_key_alter_add.result
index e2e712af4b6..67a4b790d45 100644
--- a/storage/mroonga/mysql-test/mroonga/storage/r/foreign_key_alter_add.result
+++ b/storage/mroonga/mysql-test/mroonga/storage/r/foreign_key_alter_add.result
@@ -14,11 +14,13 @@ Table Create Table
articles CREATE TABLE `articles` (
`content` text NOT NULL,
`comment` int(10) unsigned DEFAULT NULL,
- KEY `comment` (`comment`),
- CONSTRAINT `comment` FOREIGN KEY (`comment`) REFERENCES `test`.`comments` (`comment`) ON DELETE RESTRICT ON UPDATE RESTRICT
+ KEY `fk_articles` (`comment`),
+ CONSTRAINT `fk_articles` FOREIGN KEY (`comment`) REFERENCES `comments` (`comment`)
) ENGINE=Mroonga DEFAULT CHARSET=latin1
SELECT * FROM information_schema.referential_constraints;
CONSTRAINT_CATALOG CONSTRAINT_SCHEMA CONSTRAINT_NAME UNIQUE_CONSTRAINT_CATALOG UNIQUE_CONSTRAINT_SCHEMA UNIQUE_CONSTRAINT_NAME MATCH_OPTION UPDATE_RULE DELETE_RULE TABLE_NAME REFERENCED_TABLE_NAME
-def test comment def test PRIMARY NONE RESTRICT RESTRICT articles comments
+def test fk_articles def test fk_articles NONE ??? ??? articles comments
+def mysql fk_help_relation def mysql fk_help_relation NONE ??? ??? help_relation help_topic
+def mysql fk_help_relation_2 def mysql fk_help_relation_2 NONE ??? ??? help_relation help_keyword
DROP TABLE articles;
DROP TABLE comments;
diff --git a/storage/mroonga/mysql-test/mroonga/storage/r/foreign_key_alter_drop.result b/storage/mroonga/mysql-test/mroonga/storage/r/foreign_key_alter_drop.result
index fc3cda00499..d1747e54b4f 100644
--- a/storage/mroonga/mysql-test/mroonga/storage/r/foreign_key_alter_drop.result
+++ b/storage/mroonga/mysql-test/mroonga/storage/r/foreign_key_alter_drop.result
@@ -7,7 +7,7 @@ content text NOT NULL
CREATE TABLE articles (
content text NOT NULL,
comment int unsigned,
-FOREIGN KEY (comment) REFERENCES comments (comment)
+FOREIGN KEY comment (comment) REFERENCES comments (comment)
);
ALTER TABLE articles DROP FOREIGN KEY comment;
SHOW CREATE TABLE articles;
@@ -19,5 +19,7 @@ articles CREATE TABLE `articles` (
) ENGINE=Mroonga DEFAULT CHARSET=latin1
SELECT * FROM information_schema.referential_constraints;
CONSTRAINT_CATALOG CONSTRAINT_SCHEMA CONSTRAINT_NAME UNIQUE_CONSTRAINT_CATALOG UNIQUE_CONSTRAINT_SCHEMA UNIQUE_CONSTRAINT_NAME MATCH_OPTION UPDATE_RULE DELETE_RULE TABLE_NAME REFERENCED_TABLE_NAME
+def mysql fk_help_relation def mysql fk_help_relation NONE ??? ??? help_relation help_topic
+def mysql fk_help_relation_2 def mysql fk_help_relation_2 NONE ??? ??? help_relation help_keyword
DROP TABLE articles;
DROP TABLE comments;
diff --git a/storage/mroonga/mysql-test/mroonga/storage/r/foreign_key_rename.result b/storage/mroonga/mysql-test/mroonga/storage/r/foreign_key_rename.result
index 5ea0ae3e3ac..250e232abd8 100644
--- a/storage/mroonga/mysql-test/mroonga/storage/r/foreign_key_rename.result
+++ b/storage/mroonga/mysql-test/mroonga/storage/r/foreign_key_rename.result
@@ -18,11 +18,13 @@ Table Create Table
articles2 CREATE TABLE `articles2` (
`content` text NOT NULL,
`comment` int(10) unsigned DEFAULT NULL,
- KEY `comment` (`comment`),
- CONSTRAINT `comment` FOREIGN KEY (`comment`) REFERENCES `test`.`comments2` (`comment`) ON DELETE RESTRICT ON UPDATE RESTRICT
+ KEY `fk_articles` (`comment`),
+ CONSTRAINT `fk_articles` FOREIGN KEY (`comment`) REFERENCES `comments2` (`comment`)
) ENGINE=Mroonga DEFAULT CHARSET=latin1
SELECT * FROM information_schema.referential_constraints;
CONSTRAINT_CATALOG CONSTRAINT_SCHEMA CONSTRAINT_NAME UNIQUE_CONSTRAINT_CATALOG UNIQUE_CONSTRAINT_SCHEMA UNIQUE_CONSTRAINT_NAME MATCH_OPTION UPDATE_RULE DELETE_RULE TABLE_NAME REFERENCED_TABLE_NAME
-def test comment def test PRIMARY NONE RESTRICT RESTRICT articles2 comments2
+def test fk_articles def test fk_articles NONE ??? ??? articles2 comments2
+def mysql fk_help_relation def mysql fk_help_relation NONE ??? ??? help_relation help_topic
+def mysql fk_help_relation_2 def mysql fk_help_relation_2 NONE ??? ??? help_relation help_keyword
DROP TABLE articles2;
DROP TABLE comments2;
diff --git a/storage/mroonga/mysql-test/mroonga/storage/t/foreign_key_alter_drop.test b/storage/mroonga/mysql-test/mroonga/storage/t/foreign_key_alter_drop.test
index d6ef43fad53..67539e40437 100644
--- a/storage/mroonga/mysql-test/mroonga/storage/t/foreign_key_alter_drop.test
+++ b/storage/mroonga/mysql-test/mroonga/storage/t/foreign_key_alter_drop.test
@@ -33,7 +33,7 @@ CREATE TABLE comments (
CREATE TABLE articles (
content text NOT NULL,
comment int unsigned,
- FOREIGN KEY (comment) REFERENCES comments (comment)
+ FOREIGN KEY comment (comment) REFERENCES comments (comment)
);
ALTER TABLE articles DROP FOREIGN KEY comment;
diff --git a/storage/perfschema/unittest/CMakeLists.txt b/storage/perfschema/unittest/CMakeLists.txt
index 1bba2673a1a..cf30a3780cf 100644
--- a/storage/perfschema/unittest/CMakeLists.txt
+++ b/storage/perfschema/unittest/CMakeLists.txt
@@ -32,9 +32,9 @@ ADD_DEFINITIONS(-DMYSQL_SERVER ${SSL_DEFINES})
ADD_CONVENIENCE_LIBRARY(pfs_server_stubs pfs_server_stubs.cc)
-ADD_DEPENDENCIES(pfs_server_stubs GenError)
+ADD_DEPENDENCIES(pfs_server_stubs GenError sql)
MY_ADD_TESTS(pfs_instr_class pfs_instr_class-oom pfs_instr pfs_instr-oom
pfs_account-oom pfs_host-oom pfs_timer pfs_user-oom pfs_noop pfs
pfs_misc
- EXT "cc" LINK_LIBRARIES perfschema mysys pfs_server_stubs)
+ EXT "cc" LINK_LIBRARIES perfschema mysys pfs_server_stubs sql)
diff --git a/storage/rocksdb/mysql-test/rocksdb/r/index_file_map.result b/storage/rocksdb/mysql-test/rocksdb/r/index_file_map.result
index ad007d71e15..8982d588971 100644
--- a/storage/rocksdb/mysql-test/rocksdb/r/index_file_map.result
+++ b/storage/rocksdb/mysql-test/rocksdb/r/index_file_map.result
@@ -1,7 +1,7 @@
DROP TABLE IF EXISTS t1;
DROP TABLE IF EXISTS t2;
CREATE TABLE t1 (i INT PRIMARY KEY, j INT, INDEX(j)) ENGINE = ROCKSDB;
-CREATE TABLE t2 (k INT PRIMARY KEY, l INT REFERENCES t1.i) ENGINE = ROCKSDB;
+CREATE TABLE t2 (k INT PRIMARY KEY, l INT REFERENCES t1(i)) ENGINE = ROCKSDB;
INSERT INTO t1 VALUES (1,2), (2,4), (3,6), (4,8), (5,10);
INSERT INTO t2 VALUES (100,1), (200,2), (300,3), (400,4);
COMMIT;
@@ -27,5 +27,5 @@ COLUMN_FAMILY INDEX_NUMBER SST_NAME NUM_ROWS DATA_SIZE ENTRY_DELETES ENTRY_SINGL
select count(*) > 0 from information_schema.rocksdb_sst_props;
count(*) > 0
1
-DROP TABLE t1;
DROP TABLE t2;
+DROP TABLE t1;
diff --git a/storage/rocksdb/mysql-test/rocksdb/r/misc.result b/storage/rocksdb/mysql-test/rocksdb/r/misc.result
index b2e5d04f6f8..b96966d546b 100644
--- a/storage/rocksdb/mysql-test/rocksdb/r/misc.result
+++ b/storage/rocksdb/mysql-test/rocksdb/r/misc.result
@@ -55,7 +55,9 @@ help_category name NULL NULL
help_keyword help_keyword_id NULL NULL
help_keyword name NULL NULL
help_relation help_keyword_id NULL NULL
+help_relation help_keyword_id help_keyword help_keyword_id
help_relation help_topic_id NULL NULL
+help_relation help_topic_id help_topic help_topic_id
help_topic help_topic_id NULL NULL
help_topic name NULL NULL
index_stats db_name NULL NULL
diff --git a/storage/rocksdb/mysql-test/rocksdb/t/index_file_map.test b/storage/rocksdb/mysql-test/rocksdb/t/index_file_map.test
index 8b0e2339426..2f1a527fe0e 100644
--- a/storage/rocksdb/mysql-test/rocksdb/t/index_file_map.test
+++ b/storage/rocksdb/mysql-test/rocksdb/t/index_file_map.test
@@ -11,7 +11,7 @@ DROP TABLE IF EXISTS t2;
CREATE TABLE t1 (i INT PRIMARY KEY, j INT, INDEX(j)) ENGINE = ROCKSDB;
-CREATE TABLE t2 (k INT PRIMARY KEY, l INT REFERENCES t1.i) ENGINE = ROCKSDB;
+CREATE TABLE t2 (k INT PRIMARY KEY, l INT REFERENCES t1(i)) ENGINE = ROCKSDB;
INSERT INTO t1 VALUES (1,2), (2,4), (3,6), (4,8), (5,10);
INSERT INTO t2 VALUES (100,1), (200,2), (300,3), (400,4);
@@ -50,5 +50,5 @@ WHERE INDEX_NUMBER =
select count(*) > 0 from information_schema.rocksdb_sst_props;
# cleanup
-DROP TABLE t1;
DROP TABLE t2;
+DROP TABLE t1;
diff --git a/storage/spider/spd_sys_table.cc b/storage/spider/spd_sys_table.cc
index 871dbb77027..25dfc5a9671 100644
--- a/storage/spider/spd_sys_table.cc
+++ b/storage/spider/spd_sys_table.cc
@@ -3704,7 +3704,7 @@ int spider_sys_replace(
if (
last_uniq_key &&
- !table->file->referenced_by_foreign_key()
+ !table->s->referenced_by_foreign_key()
) {
if ((error_num = spider_update_sys_table_row(table)))
goto error;