diff options
-rw-r--r-- | mysql-test/suite/innodb/r/foreign_key.result | 19 | ||||
-rw-r--r-- | mysql-test/suite/innodb/t/foreign_key.test | 24 | ||||
-rw-r--r-- | sql/sql_base.cc | 5 |
3 files changed, 46 insertions, 2 deletions
diff --git a/mysql-test/suite/innodb/r/foreign_key.result b/mysql-test/suite/innodb/r/foreign_key.result index c0a6b37c1a0..33b5ea1dc56 100644 --- a/mysql-test/suite/innodb/r/foreign_key.result +++ b/mysql-test/suite/innodb/r/foreign_key.result @@ -150,3 +150,22 @@ unique_constraint_name PRIMARY DROP TABLE t2; DROP TABLE t1; +SET FOREIGN_KEY_CHECKS=0; +CREATE TABLE staff ( +staff_id TINYINT UNSIGNED NOT NULL AUTO_INCREMENT, +store_id TINYINT UNSIGNED NOT NULL, +PRIMARY KEY (staff_id), +KEY idx_fk_store_id (store_id), +CONSTRAINT fk_staff_store FOREIGN KEY (store_id) REFERENCES store (store_id) ON DELETE RESTRICT ON UPDATE CASCADE +) ENGINE=InnoDB; +CREATE TABLE store ( +store_id TINYINT UNSIGNED NOT NULL AUTO_INCREMENT, +manager_staff_id TINYINT UNSIGNED NOT NULL, +PRIMARY KEY (store_id), +UNIQUE KEY idx_unique_manager (manager_staff_id), +CONSTRAINT fk_store_staff FOREIGN KEY (manager_staff_id) REFERENCES staff (staff_id) ON DELETE RESTRICT ON UPDATE CASCADE +) ENGINE=InnoDB; +SET FOREIGN_KEY_CHECKS=DEFAULT; +LOCK TABLE staff WRITE; +UNLOCK TABLES; +DROP TABLES staff, store; diff --git a/mysql-test/suite/innodb/t/foreign_key.test b/mysql-test/suite/innodb/t/foreign_key.test index 750465f2b85..4a8da381e8c 100644 --- a/mysql-test/suite/innodb/t/foreign_key.test +++ b/mysql-test/suite/innodb/t/foreign_key.test @@ -113,3 +113,27 @@ WHERE table_name = 't2'; DROP TABLE t2; DROP TABLE t1; + +# +# MDEV-12669 Circular foreign keys cause a loop and OOM upon LOCK TABLE +# +SET FOREIGN_KEY_CHECKS=0; +CREATE TABLE staff ( + staff_id TINYINT UNSIGNED NOT NULL AUTO_INCREMENT, + store_id TINYINT UNSIGNED NOT NULL, + PRIMARY KEY (staff_id), + KEY idx_fk_store_id (store_id), + CONSTRAINT fk_staff_store FOREIGN KEY (store_id) REFERENCES store (store_id) ON DELETE RESTRICT ON UPDATE CASCADE +) ENGINE=InnoDB; +CREATE TABLE store ( + store_id TINYINT UNSIGNED NOT NULL AUTO_INCREMENT, + manager_staff_id TINYINT UNSIGNED NOT NULL, + PRIMARY KEY (store_id), + UNIQUE KEY idx_unique_manager (manager_staff_id), + CONSTRAINT fk_store_staff FOREIGN KEY (manager_staff_id) REFERENCES staff (staff_id) ON DELETE RESTRICT ON UPDATE CASCADE +) ENGINE=InnoDB; +SET FOREIGN_KEY_CHECKS=DEFAULT; + +LOCK TABLE staff WRITE; +UNLOCK TABLES; +DROP TABLES staff, store; diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 93511bb9188..5922106c7d0 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -4255,8 +4255,9 @@ handle_table(THD *thd, Query_tables_list *prelocking_ctx, else lock_type= TL_READ; - if (table_already_fk_prelocked(table_list, fk->foreign_db, - fk->foreign_table, lock_type)) + if (table_already_fk_prelocked(prelocking_ctx->query_tables, + fk->foreign_db, fk->foreign_table, + lock_type)) continue; TABLE_LIST *tl= (TABLE_LIST *) thd->alloc(sizeof(TABLE_LIST)); |