summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mysql-test/main/mysql_upgrade.result4
-rw-r--r--mysql-test/suite/innodb/r/innodb-fkcheck.result8
-rw-r--r--mysql-test/suite/innodb/r/innodb.result12
-rw-r--r--mysql-test/suite/innodb/r/instant_alter_crash.result16
-rw-r--r--mysql-test/suite/innodb/r/truncate_foreign.result10
-rw-r--r--mysql-test/suite/innodb/t/innodb-fkcheck.test13
-rw-r--r--mysql-test/suite/innodb/t/innodb.test12
-rw-r--r--mysql-test/suite/innodb/t/instant_alter_crash.test19
-rw-r--r--mysql-test/suite/innodb/t/truncate_foreign.test11
-rw-r--r--mysql-test/suite/innodb_fts/r/misc_debug.result1
-rw-r--r--mysql-test/suite/innodb_fts/t/misc_debug.test1
-rw-r--r--storage/innobase/dict/dict0dict.cc22
-rw-r--r--storage/innobase/handler/ha_innodb.cc702
-rw-r--r--storage/innobase/handler/ha_innodb.h22
-rw-r--r--storage/innobase/handler/handler0alter.cc5
-rw-r--r--storage/innobase/include/dict0dict.h25
-rw-r--r--storage/innobase/include/dict0load.h2
-rw-r--r--storage/innobase/lock/lock0lock.cc3
18 files changed, 448 insertions, 440 deletions
diff --git a/mysql-test/main/mysql_upgrade.result b/mysql-test/main/mysql_upgrade.result
index 34af8eb6466..b6160bd3525 100644
--- a/mysql-test/main/mysql_upgrade.result
+++ b/mysql-test/main/mysql_upgrade.result
@@ -1319,10 +1319,6 @@ partition p2008 values less than (2009)
);
select length(table_name) from mysql.innodb_table_stats;
length(table_name)
-79
-79
-79
-79
drop table extralongname_extralongname_extralongname_extralongname_ext;
# End of 10.0 tests
set sql_mode=default;
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);