diff options
-rw-r--r-- | mysql-test/suite/innodb/r/innodb-fkcheck.result | 8 | ||||
-rw-r--r-- | mysql-test/suite/innodb/r/innodb.result | 12 | ||||
-rw-r--r-- | mysql-test/suite/innodb/r/instant_alter_crash.result | 16 | ||||
-rw-r--r-- | mysql-test/suite/innodb/r/truncate_foreign.result | 10 | ||||
-rw-r--r-- | mysql-test/suite/innodb/t/innodb-fkcheck.test | 13 | ||||
-rw-r--r-- | mysql-test/suite/innodb/t/innodb.test | 12 | ||||
-rw-r--r-- | mysql-test/suite/innodb/t/instant_alter_crash.test | 19 | ||||
-rw-r--r-- | mysql-test/suite/innodb/t/truncate_foreign.test | 11 | ||||
-rw-r--r-- | mysql-test/suite/innodb_fts/r/misc_debug.result | 1 | ||||
-rw-r--r-- | mysql-test/suite/innodb_fts/t/misc_debug.test | 1 | ||||
-rw-r--r-- | storage/innobase/dict/dict0dict.cc | 22 | ||||
-rw-r--r-- | storage/innobase/handler/ha_innodb.cc | 702 | ||||
-rw-r--r-- | storage/innobase/handler/ha_innodb.h | 22 | ||||
-rw-r--r-- | storage/innobase/handler/handler0alter.cc | 5 | ||||
-rw-r--r-- | storage/innobase/include/dict0dict.h | 25 | ||||
-rw-r--r-- | storage/innobase/include/dict0load.h | 2 | ||||
-rw-r--r-- | storage/innobase/lock/lock0lock.cc | 3 |
17 files changed, 448 insertions, 436 deletions
diff --git a/mysql-test/suite/innodb/r/innodb-fkcheck.result b/mysql-test/suite/innodb/r/innodb-fkcheck.result index 2c2be83a3ff..f86ba50597f 100644 --- a/mysql-test/suite/innodb/r/innodb-fkcheck.result +++ b/mysql-test/suite/innodb/r/innodb-fkcheck.result @@ -33,11 +33,19 @@ b bigint unsigned NOT NULL, d1 date NOT NULL, PRIMARY KEY (b,d1) ) ENGINE=InnoDB; +DROP TABLE b; +set foreign_key_checks = 1; +CREATE TABLE b ( +b bigint unsigned NOT NULL, +d1 date NOT NULL, +PRIMARY KEY (b,d1) +) ENGINE=InnoDB; ERROR HY000: Can't create table `bug_fk`.`b` (errno: 150 "Foreign key constraint is incorrectly formed") show warnings; Level Code Message Error 1005 Can't create table `bug_fk`.`b` (errno: 150 "Foreign key constraint is incorrectly formed") Warning 1215 Cannot add foreign key constraint for `b` +set foreign_key_checks = 0; DROP TABLE IF EXISTS d; Warnings: Note 1051 Unknown table 'bug_fk.d' diff --git a/mysql-test/suite/innodb/r/innodb.result b/mysql-test/suite/innodb/r/innodb.result index edbdcd2b28e..47e5f0f5c94 100644 --- a/mysql-test/suite/innodb/r/innodb.result +++ b/mysql-test/suite/innodb/r/innodb.result @@ -2531,9 +2531,19 @@ disconnect b; set foreign_key_checks=0; create table t2 (a int primary key, b int, foreign key (b) references t1(a)) engine = innodb; create table t1(a char(10) primary key, b varchar(20)) engine = innodb; -ERROR HY000: Can't create table `test`.`t1` (errno: 150 "Foreign key constraint is incorrectly formed") set foreign_key_checks=1; +insert into t2 values (1,1); +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`)) +set foreign_key_checks=0; +drop table t1; +set foreign_key_checks=1; +insert into t2 values (1,1); +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`)) +create table t1(a char(10) primary key, b varchar(20)) engine = innodb; +ERROR HY000: Can't create table `test`.`t1` (errno: 150 "Foreign key constraint is incorrectly formed") drop table t2; +create table t1(a char(10) primary key, b varchar(20)) engine = innodb; +drop table t1; set foreign_key_checks=0; create table t1(a varchar(10) primary key) engine = innodb DEFAULT CHARSET=latin1; create table t2 (a varchar(10), foreign key (a) references t1(a)) engine = innodb DEFAULT CHARSET=utf8; diff --git a/mysql-test/suite/innodb/r/instant_alter_crash.result b/mysql-test/suite/innodb/r/instant_alter_crash.result index 843f33fddd1..f0fedcc7673 100644 --- a/mysql-test/suite/innodb/r/instant_alter_crash.result +++ b/mysql-test/suite/innodb/r/instant_alter_crash.result @@ -34,13 +34,15 @@ ROLLBACK; InnoDB 0 transactions not purged INSERT INTO t2 VALUES (16,1551,'Omnium enim rerum'),(128,1571,' principia parva sunt'); +BEGIN; +UPDATE t1 SET c2=c2+1; connect ddl, localhost, root; SET DEBUG_SYNC='innodb_alter_inplace_before_commit SIGNAL ddl WAIT_FOR ever'; ALTER TABLE t2 DROP COLUMN c3, ADD COLUMN c5 TEXT DEFAULT 'naturam abhorrere'; connection default; SET DEBUG_SYNC='now WAIT_FOR ddl'; SET GLOBAL innodb_flush_log_at_trx_commit=1; -UPDATE t1 SET c2=c2+1; +COMMIT; # Kill the server disconnect ddl; # restart @@ -61,6 +63,8 @@ DELETE FROM t2; ROLLBACK; InnoDB 0 transactions not purged INSERT INTO t2 VALUES (64,42,'De finibus bonorum'), (347,33101,' et malorum'); +BEGIN; +DELETE FROM t1; connect ddl, localhost, root; ALTER TABLE t2 DROP COLUMN c3; SET DEBUG_SYNC='innodb_alter_inplace_before_commit SIGNAL ddl WAIT_FOR ever'; @@ -68,7 +72,7 @@ ALTER TABLE t2 ADD COLUMN (c4 TEXT NOT NULL DEFAULT ' et malorum'); connection default; SET DEBUG_SYNC='now WAIT_FOR ddl'; SET GLOBAL innodb_flush_log_at_trx_commit=1; -DELETE FROM t1; +COMMIT; # Kill the server disconnect ddl; # restart @@ -138,6 +142,8 @@ InnoDB 0 transactions not purged # # MDEV-24323 Crash on recovery after kill during instant ADD COLUMN # +BEGIN; +INSERT INTO t1 VALUES(0,0); connect ddl, localhost, root; CREATE TABLE t3(id INT PRIMARY KEY, c2 INT, v2 INT AS(c2) VIRTUAL, UNIQUE(v2)) ENGINE=InnoDB; @@ -147,7 +153,7 @@ ALTER TABLE t3 ADD COLUMN c3 TEXT NOT NULL DEFAULT 'sic transit gloria mundi'; connection default; SET DEBUG_SYNC='now WAIT_FOR ddl'; SET GLOBAL innodb_flush_log_at_trx_commit=1; -INSERT INTO t1 VALUES(0,0); +COMMIT; # Kill the server disconnect ddl; # restart @@ -183,13 +189,15 @@ DROP TABLE t2,t3; # CREATE TABLE t2(a INT UNSIGNED PRIMARY KEY) ENGINE=InnoDB; INSERT INTO t2 VALUES (1),(2),(3),(4),(5),(6); +BEGIN; +DELETE FROM t1; connect ddl, localhost, root; SET DEBUG_SYNC='innodb_alter_inplace_before_commit SIGNAL ddl WAIT_FOR ever'; ALTER TABLE t2 ADD COLUMN b TINYINT UNSIGNED NOT NULL DEFAULT 42 FIRST; connection default; SET DEBUG_SYNC='now WAIT_FOR ddl'; SET GLOBAL innodb_flush_log_at_trx_commit=1; -DELETE FROM t1; +COMMIT; # Kill the server disconnect ddl; # restart diff --git a/mysql-test/suite/innodb/r/truncate_foreign.result b/mysql-test/suite/innodb/r/truncate_foreign.result index 3154674aabf..e587baa5288 100644 --- a/mysql-test/suite/innodb/r/truncate_foreign.result +++ b/mysql-test/suite/innodb/r/truncate_foreign.result @@ -80,9 +80,19 @@ SET FOREIGN_KEY_CHECKS=0; ALTER TABLE t1 ADD FOREIGN KEY (a) REFERENCES t1 (a), ALGORITHM=COPY; INSERT INTO t1 VALUES (1,1); LOCK TABLES t1 WRITE; +SET FOREIGN_KEY_CHECKS=1; TRUNCATE t1; ERROR HY000: Cannot add foreign key constraint for `t1` INSERT INTO t1 VALUES (2,2); +ERROR HY000: Table 't1' was not locked with LOCK TABLES +SELECT * FROM t1; +pk a +1 1 +UNLOCK TABLES; +INSERT INTO t1 VALUES (2,2); +ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test`.`t1`, CONSTRAINT `t1_ibfk_1` FOREIGN KEY (`a`) REFERENCES `t1` (`a`)) +SET FOREIGN_KEY_CHECKS=0; +INSERT INTO t1 VALUES (2,2); SELECT * FROM t1; pk a 1 1 diff --git a/mysql-test/suite/innodb/t/innodb-fkcheck.test b/mysql-test/suite/innodb/t/innodb-fkcheck.test index 4657edc4d65..5ff3533fce1 100644 --- a/mysql-test/suite/innodb/t/innodb-fkcheck.test +++ b/mysql-test/suite/innodb/t/innodb-fkcheck.test @@ -46,7 +46,15 @@ show create table c; # # Note that column b has different type in parent table # ---error 1005 +CREATE TABLE b ( + b bigint unsigned NOT NULL, + d1 date NOT NULL, + PRIMARY KEY (b,d1) +) ENGINE=InnoDB; +DROP TABLE b; + +set foreign_key_checks = 1; +--error ER_CANT_CREATE_TABLE CREATE TABLE b ( b bigint unsigned NOT NULL, d1 date NOT NULL, @@ -54,6 +62,7 @@ CREATE TABLE b ( ) ENGINE=InnoDB; show warnings; +set foreign_key_checks = 0; DROP TABLE IF EXISTS d; @@ -64,7 +73,7 @@ CREATE TABLE d ( CONSTRAINT bd_fk FOREIGN KEY (b) REFERENCES b (b) ) ENGINE=InnoDB; -show warnings; +show warnings; set foreign_key_checks = 1; diff --git a/mysql-test/suite/innodb/t/innodb.test b/mysql-test/suite/innodb/t/innodb.test index 3a8c12dfbbd..3b3b2770df7 100644 --- a/mysql-test/suite/innodb/t/innodb.test +++ b/mysql-test/suite/innodb/t/innodb.test @@ -1598,12 +1598,22 @@ disconnect b; set foreign_key_checks=0; create table t2 (a int primary key, b int, foreign key (b) references t1(a)) engine = innodb; +create table t1(a char(10) primary key, b varchar(20)) engine = innodb; +set foreign_key_checks=1; +--error ER_NO_REFERENCED_ROW_2 +insert into t2 values (1,1); +set foreign_key_checks=0; +drop table t1; +set foreign_key_checks=1; +--error ER_NO_REFERENCED_ROW_2 +insert into t2 values (1,1); # Embedded server doesn't chdir to data directory --replace_result $MYSQLTEST_VARDIR . master-data/ '' --error ER_CANT_CREATE_TABLE create table t1(a char(10) primary key, b varchar(20)) engine = innodb; -set foreign_key_checks=1; drop table t2; +create table t1(a char(10) primary key, b varchar(20)) engine = innodb; +drop table t1; # test that FKs between different charsets are not accepted in CREATE even # when f_k_c is 0 diff --git a/mysql-test/suite/innodb/t/instant_alter_crash.test b/mysql-test/suite/innodb/t/instant_alter_crash.test index 4d211ece106..0bd983a2b4c 100644 --- a/mysql-test/suite/innodb/t/instant_alter_crash.test +++ b/mysql-test/suite/innodb/t/instant_alter_crash.test @@ -47,6 +47,9 @@ ROLLBACK; INSERT INTO t2 VALUES (16,1551,'Omnium enim rerum'),(128,1571,' principia parva sunt'); +BEGIN; +UPDATE t1 SET c2=c2+1; + connect ddl, localhost, root; SET DEBUG_SYNC='innodb_alter_inplace_before_commit SIGNAL ddl WAIT_FOR ever'; --send @@ -55,7 +58,7 @@ ALTER TABLE t2 DROP COLUMN c3, ADD COLUMN c5 TEXT DEFAULT 'naturam abhorrere'; connection default; SET DEBUG_SYNC='now WAIT_FOR ddl'; SET GLOBAL innodb_flush_log_at_trx_commit=1; -UPDATE t1 SET c2=c2+1; +COMMIT; --source include/kill_mysqld.inc disconnect ddl; @@ -73,6 +76,8 @@ ROLLBACK; --source include/wait_all_purged.inc INSERT INTO t2 VALUES (64,42,'De finibus bonorum'), (347,33101,' et malorum'); +BEGIN; +DELETE FROM t1; connect ddl, localhost, root; ALTER TABLE t2 DROP COLUMN c3; @@ -83,7 +88,7 @@ ALTER TABLE t2 ADD COLUMN (c4 TEXT NOT NULL DEFAULT ' et malorum'); connection default; SET DEBUG_SYNC='now WAIT_FOR ddl'; SET GLOBAL innodb_flush_log_at_trx_commit=1; -DELETE FROM t1; +COMMIT; --source include/kill_mysqld.inc disconnect ddl; @@ -177,6 +182,9 @@ DELETE FROM t2; --echo # --echo # MDEV-24323 Crash on recovery after kill during instant ADD COLUMN --echo # +BEGIN; +INSERT INTO t1 VALUES(0,0); + connect ddl, localhost, root; CREATE TABLE t3(id INT PRIMARY KEY, c2 INT, v2 INT AS(c2) VIRTUAL, UNIQUE(v2)) ENGINE=InnoDB; @@ -189,7 +197,7 @@ ALTER TABLE t3 ADD COLUMN c3 TEXT NOT NULL DEFAULT 'sic transit gloria mundi'; connection default; SET DEBUG_SYNC='now WAIT_FOR ddl'; SET GLOBAL innodb_flush_log_at_trx_commit=1; -INSERT INTO t1 VALUES(0,0); +COMMIT; --source include/kill_mysqld.inc disconnect ddl; @@ -207,6 +215,9 @@ DROP TABLE t2,t3; CREATE TABLE t2(a INT UNSIGNED PRIMARY KEY) ENGINE=InnoDB; INSERT INTO t2 VALUES (1),(2),(3),(4),(5),(6); +BEGIN; +DELETE FROM t1; + connect ddl, localhost, root; SET DEBUG_SYNC='innodb_alter_inplace_before_commit SIGNAL ddl WAIT_FOR ever'; --send @@ -215,7 +226,7 @@ ALTER TABLE t2 ADD COLUMN b TINYINT UNSIGNED NOT NULL DEFAULT 42 FIRST; connection default; SET DEBUG_SYNC='now WAIT_FOR ddl'; SET GLOBAL innodb_flush_log_at_trx_commit=1; -DELETE FROM t1; +COMMIT; --source include/kill_mysqld.inc disconnect ddl; diff --git a/mysql-test/suite/innodb/t/truncate_foreign.test b/mysql-test/suite/innodb/t/truncate_foreign.test index e40029e18be..abbe1b3df87 100644 --- a/mysql-test/suite/innodb/t/truncate_foreign.test +++ b/mysql-test/suite/innodb/t/truncate_foreign.test @@ -92,8 +92,19 @@ SET FOREIGN_KEY_CHECKS=0; ALTER TABLE t1 ADD FOREIGN KEY (a) REFERENCES t1 (a), ALGORITHM=COPY; INSERT INTO t1 VALUES (1,1); LOCK TABLES t1 WRITE; +SET FOREIGN_KEY_CHECKS=1; --error ER_CANNOT_ADD_FOREIGN TRUNCATE t1; +# Whether TRUNCATE succeeds or fails, it will reload FOREIGN KEY constraints. +# As a result, ha_innobase::referenced_by_foreign_key() will retun TRUE +# (for the self-referential key), and the statement will fail. +--error ER_TABLE_NOT_LOCKED +INSERT INTO t1 VALUES (2,2); +SELECT * FROM t1; +UNLOCK TABLES; +--error ER_NO_REFERENCED_ROW_2 +INSERT INTO t1 VALUES (2,2); +SET FOREIGN_KEY_CHECKS=0; INSERT INTO t1 VALUES (2,2); SELECT * FROM t1; DROP TABLE t1; diff --git a/mysql-test/suite/innodb_fts/r/misc_debug.result b/mysql-test/suite/innodb_fts/r/misc_debug.result index 18f715b9d95..11df7d89f0b 100644 --- a/mysql-test/suite/innodb_fts/r/misc_debug.result +++ b/mysql-test/suite/innodb_fts/r/misc_debug.result @@ -62,7 +62,6 @@ SET @saved_debug_dbug= @@debug_dbug; CREATE TABLE t1 (b CHAR(12), FULLTEXT KEY(b)) engine=InnoDB; SET debug_dbug='+d,ib_create_table_fail_too_many_trx'; TRUNCATE t1; -ERROR HY000: Got error -1 "Internal error < 0 (Not system error)" from storage engine InnoDB SET debug_dbug=@saved_debug_dbug; DROP TABLE t1; # End of 10.3 tests diff --git a/mysql-test/suite/innodb_fts/t/misc_debug.test b/mysql-test/suite/innodb_fts/t/misc_debug.test index c086348b631..9246d27a704 100644 --- a/mysql-test/suite/innodb_fts/t/misc_debug.test +++ b/mysql-test/suite/innodb_fts/t/misc_debug.test @@ -91,7 +91,6 @@ SET @saved_debug_dbug= @@debug_dbug; CREATE TABLE t1 (b CHAR(12), FULLTEXT KEY(b)) engine=InnoDB; SET debug_dbug='+d,ib_create_table_fail_too_many_trx'; ---error ER_GET_ERRNO TRUNCATE t1; SET debug_dbug=@saved_debug_dbug; DROP TABLE t1; diff --git a/storage/innobase/dict/dict0dict.cc b/storage/innobase/dict/dict0dict.cc index 43ccf8c4d09..362b949e10f 100644 --- a/storage/innobase/dict/dict0dict.cc +++ b/storage/innobase/dict/dict0dict.cc @@ -685,8 +685,7 @@ dict_acquire_mdl_shared(dict_table_t *table, } else { - ut_ad(dict_sys.frozen()); - ut_ad(!dict_sys.locked()); + ut_ad(dict_sys.frozen_not_locked()); db_len= dict_get_db_name_len(table->name.m_name); } @@ -1003,7 +1002,7 @@ void dict_sys_t::lock_wait(SRW_LOCK_ARGS(const char *file, unsigned line)) latch_ex_wait_start.store(0, std::memory_order_relaxed); ut_ad(!latch_readers); ut_ad(!latch_ex); - ut_d(latch_ex= true); + ut_d(latch_ex= pthread_self()); return; } @@ -1021,15 +1020,15 @@ void dict_sys_t::lock_wait(SRW_LOCK_ARGS(const char *file, unsigned line)) latch.wr_lock(SRW_LOCK_ARGS(file, line)); ut_ad(!latch_readers); ut_ad(!latch_ex); - ut_d(latch_ex= true); + ut_d(latch_ex= pthread_self()); } #ifdef UNIV_PFS_RWLOCK ATTRIBUTE_NOINLINE void dict_sys_t::unlock() { - ut_ad(latch_ex); + ut_ad(latch_ex == pthread_self()); ut_ad(!latch_readers); - ut_d(latch_ex= false); + ut_d(latch_ex= 0); latch.wr_unlock(); } @@ -2749,17 +2748,6 @@ dict_index_build_internal_fts( } /*====================== FOREIGN KEY PROCESSING ========================*/ -/*********************************************************************//** -Checks if a table is referenced by foreign keys. -@return TRUE if table is referenced by a foreign key */ -ibool -dict_table_is_referenced_by_foreign_key( -/*====================================*/ - const dict_table_t* table) /*!< in: InnoDB table */ -{ - return(!table->referenced_set.empty()); -} - /**********************************************************************//** Removes a foreign constraint struct from the dictionary cache. */ void diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index d2b6bd62520..b6180f51ebb 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -11473,6 +11473,8 @@ innobase_fts_load_stopword( trx_t* trx, /*!< in: transaction */ THD* thd) /*!< in: current thread */ { + ut_ad(dict_sys.locked()); + const char *stopword_table= THDVAR(thd, ft_user_stopword_table); if (!stopword_table) { @@ -11482,9 +11484,11 @@ innobase_fts_load_stopword( mysql_mutex_unlock(&LOCK_global_system_variables); } - return !high_level_read_only && - fts_load_stopword(table, trx, stopword_table, - THDVAR(thd, ft_enable_stopword), false); + table->fts->dict_locked= true; + bool success= fts_load_stopword(table, trx, stopword_table, + THDVAR(thd, ft_enable_stopword), false); + table->fts->dict_locked= false; + return success; } /** Parse the table name into normal name and remote path if needed. @@ -12820,15 +12824,18 @@ int create_table_info_t::create_table(bool create_fk) dberr_t err = create_fk ? create_foreign_keys() : DB_SUCCESS; if (err == DB_SUCCESS) { + const dict_err_ignore_t ignore_err = m_trx->check_foreigns + ? DICT_ERR_IGNORE_NONE : DICT_ERR_IGNORE_FK_NOKEY; + /* Check that also referencing constraints are ok */ dict_names_t fk_tables; err = dict_load_foreigns(m_table_name, nullptr, m_trx->id, true, - DICT_ERR_IGNORE_NONE, fk_tables); + ignore_err, fk_tables); while (err == DB_SUCCESS && !fk_tables.empty()) { dict_sys.load_table( {fk_tables.front(), strlen(fk_tables.front())}, - DICT_ERR_IGNORE_NONE); + ignore_err); fk_tables.pop_front(); } } @@ -13109,96 +13116,59 @@ bool create_table_info_t::row_size_is_acceptable( return true; } -/** Update a new table in an InnoDB database. -@return error number */ -int -create_table_info_t::create_table_update_dict() +void create_table_info_t::create_table_update_dict(dict_table_t *table, + THD *thd, + const HA_CREATE_INFO &info, + const TABLE &t) { - dict_table_t* innobase_table; - - DBUG_ENTER("create_table_update_dict"); - - innobase_table = dict_table_open_on_name( - m_table_name, false, DICT_ERR_IGNORE_NONE); - - DBUG_ASSERT(innobase_table != 0); - if (innobase_table->fts != NULL) { - if (innobase_table->fts_doc_id_index == NULL) { - innobase_table->fts_doc_id_index - = dict_table_get_index_on_name( - innobase_table, FTS_DOC_ID_INDEX_NAME); - DBUG_ASSERT(innobase_table->fts_doc_id_index != NULL); - } else { - DBUG_ASSERT(innobase_table->fts_doc_id_index - == dict_table_get_index_on_name( - innobase_table, - FTS_DOC_ID_INDEX_NAME)); - } - } - - DBUG_ASSERT((innobase_table->fts == NULL) - == (innobase_table->fts_doc_id_index == NULL)); - - innobase_copy_frm_flags_from_create_info(innobase_table, m_create_info); - - dict_stats_update(innobase_table, DICT_STATS_EMPTY_TABLE); - - /* Load server stopword into FTS cache */ - if (m_flags2 & DICT_TF2_FTS) { - if (!innobase_fts_load_stopword(innobase_table, NULL, m_thd)) { - innobase_table->release(); - DBUG_RETURN(-1); - } + ut_ad(dict_sys.locked()); - dict_sys.lock(SRW_LOCK_CALL); - fts_optimize_add_table(innobase_table); - dict_sys.unlock(); - } + DBUG_ASSERT(table->get_ref_count()); + if (table->fts) + { + if (!table->fts_doc_id_index) + table->fts_doc_id_index= + dict_table_get_index_on_name(table, FTS_DOC_ID_INDEX_NAME); + else + DBUG_ASSERT(table->fts_doc_id_index == + dict_table_get_index_on_name(table, FTS_DOC_ID_INDEX_NAME)); + } - if (const Field* ai = m_form->found_next_number_field) { - ut_ad(ai->stored_in_db()); + DBUG_ASSERT(!table->fts == !table->fts_doc_id_index); - ib_uint64_t autoinc = m_create_info->auto_increment_value; + innobase_copy_frm_flags_from_create_info(table, &info); - if (autoinc == 0) { - autoinc = 1; - } + /* Load server stopword into FTS cache */ + if (table->flags2 & DICT_TF2_FTS && + innobase_fts_load_stopword(table, nullptr, thd)) + fts_optimize_add_table(table); - innobase_table->autoinc_mutex.wr_lock(); - dict_table_autoinc_initialize(innobase_table, autoinc); + if (const Field *ai = t.found_next_number_field) + { + ut_ad(ai->stored_in_db()); + ib_uint64_t autoinc= info.auto_increment_value; + if (autoinc == 0) + autoinc= 1; - if (innobase_table->is_temporary()) { - /* AUTO_INCREMENT is not persistent for - TEMPORARY TABLE. Temporary tables are never - evicted. Keep the counter in memory only. */ - } else { - const unsigned col_no = innodb_col_no(ai); - - innobase_table->persistent_autoinc - = static_cast<uint16_t>( - dict_table_get_nth_col_pos( - innobase_table, col_no, NULL) - + 1) - & dict_index_t::MAX_N_FIELDS; - - /* Persist the "last used" value, which - typically is AUTO_INCREMENT - 1. - In btr_create(), the value 0 was already written. */ - if (--autoinc) { - btr_write_autoinc( - dict_table_get_first_index( - innobase_table), - autoinc); - } - } + table->autoinc_mutex.wr_lock(); + dict_table_autoinc_initialize(table, autoinc); - innobase_table->autoinc_mutex.wr_unlock(); - } + if (!table->is_temporary()) + { + const unsigned col_no= innodb_col_no(ai); + table->persistent_autoinc= static_cast<uint16_t> + (dict_table_get_nth_col_pos(table, col_no, nullptr) + 1) & + dict_index_t::MAX_N_FIELDS; + /* Persist the "last used" value, which typically is AUTO_INCREMENT - 1. + In btr_create(), the value 0 was already written. */ + if (--autoinc) + btr_write_autoinc(dict_table_get_first_index(table), autoinc); + } - innobase_parse_hint_from_comment(m_thd, innobase_table, m_form->s); + table->autoinc_mutex.wr_unlock(); + } - dict_table_close(innobase_table); - DBUG_RETURN(0); + innobase_parse_hint_from_comment(thd, table, t.s); } /** Allocate a new trx. */ @@ -13215,89 +13185,80 @@ create_table_info_t::allocate_trx() @param[in] create_info Create info (including create statement string). @param[in] file_per_table whether to create .ibd file @param[in,out] trx dictionary transaction, or NULL to create new -@return 0 if success else error number. */ -inline int -ha_innobase::create( - const char* name, - TABLE* form, - HA_CREATE_INFO* create_info, - bool file_per_table, - trx_t* trx) +@return error code +@retval 0 on success */ +int +ha_innobase::create(const char *name, TABLE *form, HA_CREATE_INFO *create_info, + bool file_per_table, trx_t *trx= nullptr) { - char norm_name[FN_REFLEN]; /* {database}/{tablename} */ - char remote_path[FN_REFLEN]; /* Absolute path of table */ + char norm_name[FN_REFLEN]; /* {database}/{tablename} */ + char remote_path[FN_REFLEN]; /* Absolute path of table */ - DBUG_ENTER("ha_innobase::create"); + DBUG_ENTER("ha_innobase::create"); + DBUG_ASSERT(form->s == table_share); + DBUG_ASSERT(table_share->table_type == TABLE_TYPE_SEQUENCE || + table_share->table_type == TABLE_TYPE_NORMAL); - DBUG_ASSERT(form->s == table_share); - DBUG_ASSERT(table_share->table_type == TABLE_TYPE_SEQUENCE - || table_share->table_type == TABLE_TYPE_NORMAL); + create_table_info_t info(ha_thd(), form, create_info, norm_name, + remote_path, file_per_table, trx); - create_table_info_t info(ha_thd(), - form, - create_info, - norm_name, - remote_path, - file_per_table, trx); + int error= info.initialize(); + if (!error) + error= info.prepare_create_table(name, !trx); + if (error) + DBUG_RETURN(error); - { - int error = info.initialize(); - if (!error) { - error = info.prepare_create_table(name, !trx); - } - if (error) { - if (trx) { - trx_rollback_for_mysql(trx); - row_mysql_unlock_data_dictionary(trx); - } - DBUG_RETURN(error); - } - } + const bool own_trx= !trx; + if (own_trx) + { + info.allocate_trx(); + trx= info.trx(); + DBUG_ASSERT(trx_state_eq(trx, TRX_STATE_NOT_STARTED)); - const bool own_trx = !trx; - int error = 0; + if (!(info.flags2() & DICT_TF2_TEMPORARY)) + { + trx_start_for_ddl(trx); + if (dberr_t err= lock_sys_tables(trx)) + error= convert_error_code_to_mysql(err, 0, nullptr); + } + row_mysql_lock_data_dictionary(trx); + } - if (own_trx) { - info.allocate_trx(); - trx = info.trx(); - DBUG_ASSERT(trx_state_eq(trx, TRX_STATE_NOT_STARTED)); - } - if (own_trx && !(info.flags2() & DICT_TF2_TEMPORARY)) { - trx_start_for_ddl(trx); - if (dberr_t err = lock_sys_tables(trx)) { - error = convert_error_code_to_mysql(err, 0, nullptr); - } - } - if (own_trx) { - row_mysql_lock_data_dictionary(trx); - } + if (!error) + error= info.create_table(own_trx); - if (!error) { - error = info.create_table(own_trx); - } + if (own_trx || (info.flags2() & DICT_TF2_TEMPORARY)) + { + if (error) + trx_rollback_for_mysql(trx); + else + { + std::vector<pfs_os_file_t> deleted; + trx->commit(deleted); + ut_ad(deleted.empty()); + info.table()->acquire(); + info.create_table_update_dict(info.table(), info.thd(), + *create_info, *form); + } - if (error) { - /* Rollback will drop the being-created table. */ - trx_rollback_for_mysql(trx); - row_mysql_unlock_data_dictionary(trx); - } else { - /* When this is invoked as part of ha_innobase::truncate(), - the old copy of the table will be deleted here. */ - std::vector<pfs_os_file_t> deleted; - trx->commit(deleted); - row_mysql_unlock_data_dictionary(trx); - for (pfs_os_file_t d : deleted) os_file_close(d); - error = info.create_table_update_dict(); - if (!(info.flags2() & DICT_TF2_TEMPORARY)) { - log_write_up_to(trx->commit_lsn, true); - } - } + if (own_trx) + { + row_mysql_unlock_data_dictionary(trx); - if (own_trx) { - trx->free(); - } + if (!error) + { + dict_stats_update(info.table(), DICT_STATS_EMPTY_TABLE); + if (!info.table()->is_temporary()) + log_write_up_to(trx->commit_lsn, true); + info.table()->release(); + } + trx->free(); + } + } + else if (!error && m_prebuilt) + m_prebuilt->table= info.table(); - DBUG_RETURN(error); + DBUG_RETURN(error); } /** Create a new table to an InnoDB database. @@ -13305,13 +13266,10 @@ ha_innobase::create( @param[in] form Table format; columns and index information. @param[in] create_info Create info (including create statement string). @return 0 if success else error number. */ -int -ha_innobase::create( - const char* name, - TABLE* form, - HA_CREATE_INFO* create_info) +int ha_innobase::create(const char *name, TABLE *form, + HA_CREATE_INFO *create_info) { - return create(name, form, create_info, srv_file_per_table); + return create(name, form, create_info, srv_file_per_table); } /*****************************************************************//** @@ -13840,229 +13798,247 @@ static dberr_t innobase_rename_table(trx_t *trx, const char *from, @retval 0 on success */ int ha_innobase::truncate() { - DBUG_ENTER("ha_innobase::truncate"); + DBUG_ENTER("ha_innobase::truncate"); - update_thd(); + update_thd(); - if (is_read_only()) { - DBUG_RETURN(HA_ERR_TABLE_READONLY); - } + if (is_read_only()) + DBUG_RETURN(HA_ERR_TABLE_READONLY); - HA_CREATE_INFO info; - dict_table_t* ib_table = m_prebuilt->table; - info.init(); - update_create_info_from_table(&info, table); - switch (dict_tf_get_rec_format(ib_table->flags)) { - case REC_FORMAT_REDUNDANT: - info.row_type = ROW_TYPE_REDUNDANT; - break; - case REC_FORMAT_COMPACT: - info.row_type = ROW_TYPE_COMPACT; - break; - case REC_FORMAT_COMPRESSED: - info.row_type = ROW_TYPE_COMPRESSED; - break; - case REC_FORMAT_DYNAMIC: - info.row_type = ROW_TYPE_DYNAMIC; - break; - } + HA_CREATE_INFO info; + dict_table_t *ib_table= m_prebuilt->table; + info.init(); + update_create_info_from_table(&info, table); + switch (dict_tf_get_rec_format(ib_table->flags)) { + case REC_FORMAT_REDUNDANT: + info.row_type= ROW_TYPE_REDUNDANT; + break; + case REC_FORMAT_COMPACT: + info.row_type= ROW_TYPE_COMPACT; + break; + case REC_FORMAT_COMPRESSED: + info.row_type= ROW_TYPE_COMPRESSED; + break; + case REC_FORMAT_DYNAMIC: + info.row_type= ROW_TYPE_DYNAMIC; + break; + } - const auto stored_lock = m_prebuilt->stored_select_lock_type; - trx_t* trx = innobase_trx_allocate(m_user_thd); - trx_start_for_ddl(trx); + const auto stored_lock= m_prebuilt->stored_select_lock_type; + trx_t *trx= innobase_trx_allocate(m_user_thd); + trx_start_for_ddl(trx); - if (ib_table->is_temporary()) { - info.options|= HA_LEX_CREATE_TMP_TABLE; - btr_drop_temporary_table(*ib_table); - m_prebuilt->table = nullptr; - row_prebuilt_free(m_prebuilt); - m_prebuilt = nullptr; - my_free(m_upd_buf); - m_upd_buf = nullptr; - m_upd_buf_size = 0; + if (ib_table->is_temporary()) + { + info.options|= HA_LEX_CREATE_TMP_TABLE; + btr_drop_temporary_table(*ib_table); + m_prebuilt->table= nullptr; + row_prebuilt_free(m_prebuilt); + m_prebuilt= nullptr; + my_free(m_upd_buf); + m_upd_buf= nullptr; + m_upd_buf_size= 0; - row_mysql_lock_data_dictionary(trx); - ib_table->release(); - dict_sys.remove(ib_table, false, true); + row_mysql_lock_data_dictionary(trx); + ib_table->release(); + dict_sys.remove(ib_table, false, true); + int err= create(ib_table->name.m_name, table, &info, true, trx); + row_mysql_unlock_data_dictionary(trx); - int err = create(ib_table->name.m_name, table, &info, true, - trx); - ut_ad(!err); - if (!err) { - err = open(ib_table->name.m_name, 0, 0); - m_prebuilt->stored_select_lock_type = stored_lock; - } + ut_ad(!err); + if (!err) + { + err= open(ib_table->name.m_name, 0, 0); + m_prebuilt->table->release(); + m_prebuilt->stored_select_lock_type= stored_lock; + } - trx->free(); + trx->free(); #ifdef BTR_CUR_HASH_ADAPT - if (UT_LIST_GET_LEN(ib_table->freed_indexes)) { - ib_table->vc_templ = nullptr; - ib_table->id = 0; - DBUG_RETURN(err); - } + if (UT_LIST_GET_LEN(ib_table->freed_indexes)) + { + ib_table->vc_templ= nullptr; + ib_table->id= 0; + } + else #endif /* BTR_CUR_HASH_ADAPT */ + dict_mem_table_free(ib_table); - dict_mem_table_free(ib_table); - DBUG_RETURN(err); - } + DBUG_RETURN(err); + } - mem_heap_t* heap = mem_heap_create(1000); + mem_heap_t *heap= mem_heap_create(1000); - dict_get_and_save_data_dir_path(ib_table); - info.data_file_name = ib_table->data_dir_path; - const char* temp_name = dict_mem_create_temporary_tablename( - heap, ib_table->name.m_name, ib_table->id); - const char* name = mem_heap_strdup(heap, ib_table->name.m_name); + dict_get_and_save_data_dir_path(ib_table); + info.data_file_name= ib_table->data_dir_path; + const char *temp_name= + dict_mem_create_temporary_tablename(heap, + ib_table->name.m_name, ib_table->id); + const char *name= mem_heap_strdup(heap, ib_table->name.m_name); - dict_table_t *table_stats = nullptr, *index_stats = nullptr; - MDL_ticket *mdl_table = nullptr, *mdl_index = nullptr; + dict_table_t *table_stats = nullptr, *index_stats = nullptr; + MDL_ticket *mdl_table = nullptr, *mdl_index = nullptr; - dberr_t error = DB_SUCCESS; + dberr_t error= DB_SUCCESS; - dict_sys.freeze(SRW_LOCK_CALL); - for (const dict_foreign_t* f : ib_table->referenced_set) { - if (dict_table_t* child = f->foreign_table) { - error = lock_table_for_trx(child, trx, LOCK_X); - if (error != DB_SUCCESS) { - break; - } - } - } - dict_sys.unfreeze(); + dict_sys.freeze(SRW_LOCK_CALL); + for (const dict_foreign_t *f : ib_table->referenced_set) + if (dict_table_t *child= f->foreign_table) + if ((error= lock_table_for_trx(child, trx, LOCK_X)) != DB_SUCCESS) + break; + dict_sys.unfreeze(); - if (error == DB_SUCCESS) { - error = lock_table_for_trx(ib_table, trx, LOCK_X); - } + if (error == DB_SUCCESS) + error= lock_table_for_trx(ib_table, trx, LOCK_X); - const bool fts = error == DB_SUCCESS - && ib_table->flags2 & (DICT_TF2_FTS_HAS_DOC_ID | DICT_TF2_FTS); + const bool fts= error == DB_SUCCESS && + ib_table->flags2 & (DICT_TF2_FTS_HAS_DOC_ID | DICT_TF2_FTS); - if (fts) { - fts_optimize_remove_table(ib_table); - purge_sys.stop_FTS(*ib_table); - error = fts_lock_tables(trx, *ib_table); - } + if (fts) + { + fts_optimize_remove_table(ib_table); + purge_sys.stop_FTS(*ib_table); + error= fts_lock_tables(trx, *ib_table); + } - /* Wait for purge threads to stop using the table. */ - for (uint n = 15; ib_table->get_ref_count() > 1; ) { - if (!--n) { - error = DB_LOCK_WAIT_TIMEOUT; - break; - } + /* Wait for purge threads to stop using the table. */ + for (uint n = 15; ib_table->get_ref_count() > 1; ) + { + if (!--n) + { + error= DB_LOCK_WAIT_TIMEOUT; + break; + } + std::this_thread::sleep_for(std::chrono::milliseconds(50)); + } - std::this_thread::sleep_for(std::chrono::milliseconds(50)); - } + if (error == DB_SUCCESS && dict_stats_is_persistent_enabled(ib_table) && + !ib_table->is_stats_table()) + { + table_stats= dict_table_open_on_name(TABLE_STATS_NAME, false, + DICT_ERR_IGNORE_NONE); + if (table_stats) + { + dict_sys.freeze(SRW_LOCK_CALL); + table_stats= dict_acquire_mdl_shared<false>(table_stats, m_user_thd, + &mdl_table); + dict_sys.unfreeze(); + } + index_stats= dict_table_open_on_name(INDEX_STATS_NAME, false, + DICT_ERR_IGNORE_NONE); + if (index_stats) + { + dict_sys.freeze(SRW_LOCK_CALL); + index_stats= dict_acquire_mdl_shared<false>(index_stats, m_user_thd, + &mdl_index); + dict_sys.unfreeze(); + } - if (error == DB_SUCCESS && dict_stats_is_persistent_enabled(ib_table) - && !ib_table->is_stats_table()) { - table_stats= dict_table_open_on_name(TABLE_STATS_NAME, false, - DICT_ERR_IGNORE_NONE); - if (table_stats) { - dict_sys.freeze(SRW_LOCK_CALL); - table_stats = dict_acquire_mdl_shared<false>( - table_stats, m_user_thd, &mdl_table); - dict_sys.unfreeze(); - } - index_stats = dict_table_open_on_name(INDEX_STATS_NAME, false, - DICT_ERR_IGNORE_NONE); - if (index_stats) { - dict_sys.freeze(SRW_LOCK_CALL); - index_stats = dict_acquire_mdl_shared<false>( - index_stats, m_user_thd, &mdl_index); - dict_sys.unfreeze(); - } + if (table_stats && index_stats && + !strcmp(table_stats->name.m_name, TABLE_STATS_NAME) && + !strcmp(index_stats->name.m_name, INDEX_STATS_NAME) && + !(error= lock_table_for_trx(table_stats, trx, LOCK_X))) + error= lock_table_for_trx(index_stats, trx, LOCK_X); + } - if (table_stats && index_stats - && !strcmp(table_stats->name.m_name, TABLE_STATS_NAME) - && !strcmp(index_stats->name.m_name, INDEX_STATS_NAME) && - !(error = lock_table_for_trx(table_stats, trx, LOCK_X))) { - error = lock_table_for_trx(index_stats, trx, LOCK_X); - } - } + if (error == DB_SUCCESS) + error= lock_sys_tables(trx); - if (error == DB_SUCCESS) { - error = lock_sys_tables(trx); - } + std::vector<pfs_os_file_t> deleted; - row_mysql_lock_data_dictionary(trx); + row_mysql_lock_data_dictionary(trx); - if (error == DB_SUCCESS) { - error = innobase_rename_table(trx, ib_table->name.m_name, - temp_name, false); + if (error == DB_SUCCESS) + { + error= innobase_rename_table(trx, ib_table->name.m_name, temp_name, false); + if (error == DB_SUCCESS) + error= trx->drop_table(*ib_table); + } - if (error == DB_SUCCESS) { - error = trx->drop_table(*ib_table); - } - } + int err = convert_error_code_to_mysql(error, ib_table->flags, m_user_thd); + const auto update_time = ib_table->update_time; - int err = convert_error_code_to_mysql(error, ib_table->flags, - m_user_thd); - if (err) { - trx_rollback_for_mysql(trx); - if (fts) { - fts_optimize_add_table(ib_table); - purge_sys.resume_FTS(); - } - row_mysql_unlock_data_dictionary(trx); - } else { - const auto update_time = ib_table->update_time; - const auto stored_lock = m_prebuilt->stored_select_lock_type; - const auto def_trx_id = ib_table->def_trx_id; - ib_table->release(); - m_prebuilt->table = nullptr; + if (err) + { + trx_rollback_for_mysql(trx); + if (fts) + fts_optimize_add_table(ib_table); + } + else + { + const auto def_trx_id= ib_table->def_trx_id; + ib_table->release(); + m_prebuilt->table= nullptr; - err = create(name, table, &info, - dict_table_is_file_per_table(ib_table), trx); - /* On success, create() durably committed trx. */ - if (fts) { - purge_sys.resume_FTS(); - } + err= create(name, table, &info, dict_table_is_file_per_table(ib_table), + trx); + if (!err) + { + m_prebuilt->table->acquire(); + create_table_info_t::create_table_update_dict(m_prebuilt->table, + m_user_thd, info, *table); + trx->commit(deleted); + } + else + { + trx_rollback_for_mysql(trx); + m_prebuilt->table= dict_table_open_on_name(name, true, + DICT_ERR_IGNORE_FK_NOKEY); + m_prebuilt->table->def_trx_id= def_trx_id; + } + dict_names_t fk_tables; + dict_load_foreigns(m_prebuilt->table->name.m_name, nullptr, 1, true, + DICT_ERR_IGNORE_FK_NOKEY, fk_tables); + for (const char *f : fk_tables) + dict_sys.load_table({f, strlen(f)}); + } - if (err) { -reload: - m_prebuilt->table = dict_table_open_on_name( - name, false, DICT_ERR_IGNORE_NONE); - m_prebuilt->table->def_trx_id = def_trx_id; - } else { - row_prebuilt_t* prebuilt = m_prebuilt; - uchar* upd_buf = m_upd_buf; - ulint upd_buf_size = m_upd_buf_size; - /* Mimic ha_innobase::close(). */ - m_prebuilt = nullptr; - m_upd_buf = nullptr; - m_upd_buf_size = 0; + if (fts) + purge_sys.resume_FTS(); - err = open(name, 0, 0); + row_mysql_unlock_data_dictionary(trx); + for (pfs_os_file_t d : deleted) os_file_close(d); - if (!err) { - m_prebuilt->stored_select_lock_type - = stored_lock; - m_prebuilt->table->update_time = update_time; - row_prebuilt_free(prebuilt); - my_free(upd_buf); - } else { - /* Revert to the old table. */ - m_prebuilt = prebuilt; - m_upd_buf = upd_buf; - m_upd_buf_size = upd_buf_size; - goto reload; - } - } - } + if (!err) + { + dict_stats_update(m_prebuilt->table, DICT_STATS_EMPTY_TABLE); + log_write_up_to(trx->commit_lsn, true); + row_prebuilt_t *prebuilt= m_prebuilt; + uchar *upd_buf= m_upd_buf; + ulint upd_buf_size= m_upd_buf_size; + /* Mimic ha_innobase::close(). */ + m_prebuilt= nullptr; + m_upd_buf= nullptr; + m_upd_buf_size= 0; + + err= open(name, 0, 0); + if (!err) + { + m_prebuilt->stored_select_lock_type= stored_lock; + m_prebuilt->table->update_time= update_time; + row_prebuilt_free(prebuilt); + my_free(upd_buf); + } + else + { + /* Revert to the old table. */ + m_prebuilt= prebuilt; + m_upd_buf= upd_buf; + m_upd_buf_size= upd_buf_size; + } + } - trx->free(); + trx->free(); - mem_heap_free(heap); + mem_heap_free(heap); - if (table_stats) { - dict_table_close(table_stats, false, m_user_thd, mdl_table); - } - if (index_stats) { - dict_table_close(index_stats, false, m_user_thd, mdl_index); - } + if (table_stats) + dict_table_close(table_stats, false, m_user_thd, mdl_table); + if (index_stats) + dict_table_close(index_stats, false, m_user_thd, mdl_index); - DBUG_RETURN(err); + DBUG_RETURN(err); } /*********************************************************************//** @@ -15656,30 +15632,12 @@ delete is then allowed internally to resolve a duplicate key conflict in REPLACE, not an update. @return > 0 if referenced by a FOREIGN KEY */ -uint -ha_innobase::referenced_by_foreign_key(void) -/*========================================*/ -{ - if (dict_table_is_referenced_by_foreign_key(m_prebuilt->table)) { - - return(1); - } - - return(0); -} - -/*******************************************************************//** -Frees the foreign key create info for a table stored in InnoDB, if it is -non-NULL. */ - -void -ha_innobase::free_foreign_key_create_info( -/*======================================*/ - char* str) /*!< in, own: create info string to free */ +uint ha_innobase::referenced_by_foreign_key() { - if (str != NULL) { - my_free(str); - } + dict_sys.freeze(SRW_LOCK_CALL); + const bool empty= m_prebuilt->table->referenced_set.empty(); + dict_sys.unfreeze(); + return !empty; } /*******************************************************************//** diff --git a/storage/innobase/handler/ha_innodb.h b/storage/innobase/handler/ha_innodb.h index 01acde3d8e6..3c6452f1966 100644 --- a/storage/innobase/handler/ha_innodb.h +++ b/storage/innobase/handler/ha_innodb.h @@ -190,12 +190,12 @@ public: void update_create_info(HA_CREATE_INFO* create_info) override; - inline int create( + int create( const char* name, TABLE* form, HA_CREATE_INFO* create_info, bool file_per_table, - trx_t* trx = NULL); + trx_t* trx); int create( const char* name, @@ -225,7 +225,7 @@ public: uint referenced_by_foreign_key() override; - void free_foreign_key_create_info(char* str) override; + void free_foreign_key_create_info(char* str) override { my_free(str); } uint lock_count(void) const override; @@ -639,8 +639,9 @@ public: @param create_fk whether to add FOREIGN KEY constraints */ int create_table(bool create_fk = true); - /** Update the internal data dictionary. */ - int create_table_update_dict(); + static void create_table_update_dict(dict_table_t* table, THD* thd, + const HA_CREATE_INFO& info, + const TABLE& t); /** Validates the create options. Checks that the options KEY_BLOCK_SIZE, ROW_FORMAT, DATA DIRECTORY, TEMPORARY & TABLESPACE @@ -700,12 +701,13 @@ public: trx_t* trx() const { return(m_trx); } - /** Return table name. */ - const char* table_name() const - { return(m_table_name); } + /** @return table name */ + const char* table_name() const { return(m_table_name); } + + /** @return the created table */ + dict_table_t *table() const { return m_table; } - THD* thd() const - { return(m_thd); } + THD* thd() const { return(m_thd); } private: /** Parses the table name into normal name and either temp path or diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc index fa86a920dd8..8ef58d64167 100644 --- a/storage/innobase/handler/handler0alter.cc +++ b/storage/innobase/handler/handler0alter.cc @@ -7286,13 +7286,10 @@ error_handling_drop_uncached: goto error_handling; } - ctx->new_table->fts->dict_locked = true; - error = innobase_fts_load_stopword( ctx->new_table, ctx->trx, ctx->prebuilt->trx->mysql_thd) ? DB_SUCCESS : DB_ERROR; - ctx->new_table->fts->dict_locked = false; if (error != DB_SUCCESS) { goto error_handling; @@ -9882,7 +9879,7 @@ innobase_update_foreign_cache( err = dict_load_foreigns(user_table->name.m_name, ctx->col_names, 1, true, - DICT_ERR_IGNORE_NONE, + DICT_ERR_IGNORE_FK_NOKEY, fk_tables); if (err == DB_CANNOT_ADD_CONSTRAINT) { diff --git a/storage/innobase/include/dict0dict.h b/storage/innobase/include/dict0dict.h index cfaf4fab83e..e54a138cc02 100644 --- a/storage/innobase/include/dict0dict.h +++ b/storage/innobase/include/dict0dict.h @@ -421,14 +421,6 @@ dict_foreign_add_to_cache( dict_err_ignore_t ignore_err) /*!< in: error to be ignored */ MY_ATTRIBUTE((nonnull(1), warn_unused_result)); -/*********************************************************************//** -Checks if a table is referenced by foreign keys. -@return TRUE if table is referenced by a foreign key */ -ibool -dict_table_is_referenced_by_foreign_key( -/*====================================*/ - const dict_table_t* table) /*!< in: InnoDB table */ - MY_ATTRIBUTE((nonnull, warn_unused_result)); /**********************************************************************//** Replace the index passed in with another equivalent index in the foreign key lists of the table. @@ -1329,7 +1321,7 @@ class dict_sys_t alignas(CPU_LEVEL1_DCACHE_LINESIZE) srw_lock latch; #ifdef UNIV_DEBUG /** whether latch is being held in exclusive mode (by any thread) */ - bool latch_ex; + Atomic_relaxed<pthread_t> latch_ex; /** number of S-latch holders */ Atomic_counter<uint32_t> latch_readers; #endif @@ -1503,11 +1495,12 @@ public: /** @return whether any thread (not necessarily the current thread) is holding the latch; that is, this check may return false positives */ - bool frozen() const { return latch_readers || locked(); } + bool frozen() const { return latch_readers || latch_ex; } /** @return whether any thread (not necessarily the current thread) - is holding the exclusive latch; that is, this check may return false - positives */ - bool locked() const { return latch_ex; } + is holding a shared latch */ + bool frozen_not_locked() const { return latch_readers; } + /** @return whether the current thread holds the exclusive latch */ + bool locked() const { return latch_ex == pthread_self(); } #endif private: /** Acquire the exclusive latch */ @@ -1526,7 +1519,7 @@ public: { ut_ad(!latch_readers); ut_ad(!latch_ex); - ut_d(latch_ex= true); + ut_d(latch_ex= pthread_self()); } else lock_wait(SRW_LOCK_ARGS(file, line)); @@ -1543,9 +1536,9 @@ public: /** Unlock the data dictionary cache. */ void unlock() { - ut_ad(latch_ex); + ut_ad(latch_ex == pthread_self()); ut_ad(!latch_readers); - ut_d(latch_ex= false); + ut_d(latch_ex= 0); latch.wr_unlock(); } /** Acquire a shared lock on the dictionary cache. */ diff --git a/storage/innobase/include/dict0load.h b/storage/innobase/include/dict0load.h index a94823b4a86..f7d33d5b43b 100644 --- a/storage/innobase/include/dict0load.h +++ b/storage/innobase/include/dict0load.h @@ -100,7 +100,7 @@ dict_load_foreigns( which must be loaded subsequently to load all the foreign key constraints. */ - MY_ATTRIBUTE((nonnull(1), warn_unused_result)); + MY_ATTRIBUTE((nonnull(1))); /********************************************************************//** This function opens a system table, and return the first record. diff --git a/storage/innobase/lock/lock0lock.cc b/storage/innobase/lock/lock0lock.cc index 448021d840a..db4035157b0 100644 --- a/storage/innobase/lock/lock0lock.cc +++ b/storage/innobase/lock/lock0lock.cc @@ -3934,8 +3934,7 @@ void lock_release(trx_t *trx) #ifdef UNIV_DEBUG std::set<table_id_t> to_evict; if (innodb_evict_tables_on_commit_debug && - !trx->is_recovered && !trx->dict_operation && - !trx->dict_operation_lock_mode) + !trx->is_recovered && !dict_sys.locked()) for (const auto& p : trx->mod_tables) if (!p.first->is_temporary()) to_evict.emplace(p.first->id); |