summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--extra/mariabackup/xtrabackup.cc8
-rw-r--r--mysql-test/suite/innodb/r/restart.result2
-rw-r--r--mysql-test/suite/innodb/r/row_format_redundant.result2
-rw-r--r--mysql-test/suite/innodb/r/table_flags.result4
-rw-r--r--mysql-test/suite/innodb/r/truncate_missing.result2
-rw-r--r--mysql-test/suite/innodb/t/alter_missing_tablespace.test2
-rw-r--r--mysql-test/suite/innodb/t/log_file_name.test2
-rw-r--r--mysql-test/suite/innodb/t/restart.test2
-rw-r--r--mysql-test/suite/innodb/t/row_format_redundant.test4
-rw-r--r--mysql-test/suite/innodb/t/table_flags.test8
-rw-r--r--mysql-test/suite/innodb/t/truncate_missing.test2
-rw-r--r--mysql-test/suite/innodb_fts/t/crash_recovery.test2
-rw-r--r--mysql-test/suite/innodb_zip/r/wl5522_debug_zip.result2
-rw-r--r--mysql-test/suite/innodb_zip/t/wl5522_debug_zip.test2
-rw-r--r--mysql-test/suite/mariabackup/missing_ibd.test2
-rw-r--r--storage/innobase/CMakeLists.txt2
-rw-r--r--storage/innobase/dict/dict0boot.cc180
-rw-r--r--storage/innobase/dict/dict0crea.cc470
-rw-r--r--storage/innobase/dict/dict0dict.cc51
-rw-r--r--storage/innobase/dict/dict0load.cc445
-rw-r--r--storage/innobase/dict/dict0mem.cc118
-rw-r--r--storage/innobase/dict/dict0stats.cc23
-rw-r--r--storage/innobase/fil/fil0fil.cc94
-rw-r--r--storage/innobase/fsp/fsp0file.cc2
-rw-r--r--storage/innobase/fts/fts0fts.cc9
-rw-r--r--storage/innobase/fts/fts0opt.cc2
-rw-r--r--storage/innobase/handler/ha_innodb.cc36
-rw-r--r--storage/innobase/handler/handler0alter.cc35
-rw-r--r--storage/innobase/handler/i_s.cc94
-rw-r--r--storage/innobase/ibuf/ibuf0ibuf.cc10
-rw-r--r--storage/innobase/include/dict0crea.h16
-rw-r--r--storage/innobase/include/dict0dict.h188
-rw-r--r--storage/innobase/include/dict0load.h53
-rw-r--r--storage/innobase/include/dict0mem.h37
-rw-r--r--storage/innobase/include/dict0priv.h50
-rw-r--r--storage/innobase/include/dict0priv.ic91
-rw-r--r--storage/innobase/include/dict0types.h3
-rw-r--r--storage/innobase/include/fil0fil.h7
-rw-r--r--storage/innobase/include/fsp0file.h2
-rw-r--r--storage/innobase/include/row0mysql.h24
-rw-r--r--storage/innobase/include/trx0trx.h2
-rw-r--r--storage/innobase/lock/lock0lock.cc2
-rw-r--r--storage/innobase/page/page0zip.cc4
-rw-r--r--storage/innobase/pars/pars0pars.cc5
-rw-r--r--storage/innobase/row/row0import.cc7
-rw-r--r--storage/innobase/row/row0mysql.cc105
-rw-r--r--storage/innobase/row/row0uins.cc4
-rw-r--r--storage/innobase/row/row0umod.cc4
-rw-r--r--storage/innobase/srv/srv0start.cc7
-rw-r--r--storage/innobase/trx/trx0roll.cc1
-rw-r--r--storage/innobase/trx/trx0trx.cc13
51 files changed, 918 insertions, 1324 deletions
diff --git a/extra/mariabackup/xtrabackup.cc b/extra/mariabackup/xtrabackup.cc
index a0b09d434f7..223f8d56ecf 100644
--- a/extra/mariabackup/xtrabackup.cc
+++ b/extra/mariabackup/xtrabackup.cc
@@ -71,7 +71,6 @@ Street, Fifth Floor, Boston, MA 02110-1335 USA
#include <btr0sea.h>
-#include <dict0priv.h>
#include <lock0lock.h>
#include <log0recv.h>
#include <log0crypt.h>
@@ -3315,19 +3314,18 @@ static void xb_load_single_table_tablespace(const char *dirname,
name[pathlen - 5] = 0;
}
+ const fil_space_t::name_type n{name, pathlen - 5};
Datafile *file;
if (is_remote) {
RemoteDatafile* rf = new RemoteDatafile();
- if (!rf->open_link_file(name)) {
+ if (!rf->open_link_file(n)) {
die("Can't open datafile %s", name);
}
file = rf;
} else {
file = new Datafile();
- file->make_filepath(".",
- fil_space_t::name_type{name, strlen(name)},
- IBD);
+ file->make_filepath(".", n, IBD);
}
if (file->open_read_only(true) != DB_SUCCESS) {
diff --git a/mysql-test/suite/innodb/r/restart.result b/mysql-test/suite/innodb/r/restart.result
index 9bbcc3285cf..ea9734d5a01 100644
--- a/mysql-test/suite/innodb/r/restart.result
+++ b/mysql-test/suite/innodb/r/restart.result
@@ -7,7 +7,7 @@
call mtr.add_suppression("\\[ERROR\\] InnoDB: Tablespace flags are invalid in datafile: .*test.t[rcd]\\.ibd");
call mtr.add_suppression("\\[ERROR\\] InnoDB: Operating system error number .* in a file operation\\.");
call mtr.add_suppression("\\[ERROR\\] InnoDB: The error means the system cannot find the path specified\\.");
-call mtr.add_suppression("\\[Warning\\] InnoDB: Ignoring tablespace for `test`\\.`td` because it could not be opened\\.");
+call mtr.add_suppression("\\[Warning\\] InnoDB: Ignoring tablespace for test/td because it could not be opened\\.");
CREATE TABLE tr(a INT)ENGINE=InnoDB ROW_FORMAT=REDUNDANT;
CREATE TABLE tc(a INT)ENGINE=InnoDB ROW_FORMAT=COMPACT
PAGE_COMPRESSED=1 PAGE_COMPRESSION_LEVEL=9;
diff --git a/mysql-test/suite/innodb/r/row_format_redundant.result b/mysql-test/suite/innodb/r/row_format_redundant.result
index 0eede61b175..f354666f645 100644
--- a/mysql-test/suite/innodb/r/row_format_redundant.result
+++ b/mysql-test/suite/innodb/r/row_format_redundant.result
@@ -75,7 +75,7 @@ DROP TABLE t1;
Warnings:
Warning 1932 Table 'test.t1' doesn't exist in engine
DROP TABLE t2,t3;
-FOUND 5 /\[ERROR\] InnoDB: Table `test`\.`t1` in InnoDB data dictionary contains invalid flags\. SYS_TABLES\.TYPE=1 SYS_TABLES\.MIX_LEN=511\b/ in mysqld.1.err
+FOUND 5 /\[ERROR\] InnoDB: Table test/t1 in InnoDB data dictionary contains invalid flags\. SYS_TABLES\.TYPE=1 SYS_TABLES\.MIX_LEN=511\b/ in mysqld.1.err
# restart
ib_buffer_pool
ib_logfile0
diff --git a/mysql-test/suite/innodb/r/table_flags.result b/mysql-test/suite/innodb/r/table_flags.result
index 210d370aab4..ce71d9b022d 100644
--- a/mysql-test/suite/innodb/r/table_flags.result
+++ b/mysql-test/suite/innodb/r/table_flags.result
@@ -122,8 +122,8 @@ a
42
SHOW CREATE TABLE tp;
ERROR 42S02: Table 'test.tp' doesn't exist in engine
-FOUND 5 /InnoDB: Table `test`.`t[cp]` in InnoDB data dictionary contains invalid flags\. SYS_TABLES\.TYPE=(129|289|3873|1232[13]) SYS_TABLES\.N_COLS=2147483649/ in mysqld.1.err
-FOUND 2 /InnoDB: Table `test`\.`tr` in InnoDB data dictionary contains invalid flags\. SYS_TABLES\.TYPE=65 SYS_TABLES\.MIX_LEN=4294967295\b/ in mysqld.1.err
+FOUND 5 /InnoDB: Table test/t[cp] in InnoDB data dictionary contains invalid flags\. SYS_TABLES\.TYPE=(129|289|3873|1232[13]) SYS_TABLES\.N_COLS=2147483649/ in mysqld.1.err
+FOUND 2 /InnoDB: Table test/tr in InnoDB data dictionary contains invalid flags\. SYS_TABLES\.TYPE=65 SYS_TABLES\.MIX_LEN=4294967295\b/ in mysqld.1.err
Restoring SYS_TABLES clustered index root page (8)
# restart: with restart_parameters
SHOW CREATE TABLE tr;
diff --git a/mysql-test/suite/innodb/r/truncate_missing.result b/mysql-test/suite/innodb/r/truncate_missing.result
index 938bd5f2213..1cc654f0d7e 100644
--- a/mysql-test/suite/innodb/r/truncate_missing.result
+++ b/mysql-test/suite/innodb/r/truncate_missing.result
@@ -1,6 +1,6 @@
call mtr.add_suppression("InnoDB: Operating system error number ");
call mtr.add_suppression("InnoDB: (The error means|If you are|Cannot open datafile) ");
-call mtr.add_suppression("InnoDB: Ignoring tablespace for `test`\.`t`");
+call mtr.add_suppression("InnoDB: Ignoring tablespace for test/t ");
call mtr.add_suppression("InnoDB: Table test/t .* does not exist");
CREATE TABLE t (a SERIAL) ENGINE=InnoDB;
INSERT INTO t() VALUES();
diff --git a/mysql-test/suite/innodb/t/alter_missing_tablespace.test b/mysql-test/suite/innodb/t/alter_missing_tablespace.test
index c615c9ff537..bf7111509bd 100644
--- a/mysql-test/suite/innodb/t/alter_missing_tablespace.test
+++ b/mysql-test/suite/innodb/t/alter_missing_tablespace.test
@@ -10,7 +10,7 @@
call mtr.add_suppression("InnoDB: Cannot open datafile for read-only: ");
call mtr.add_suppression("InnoDB: Operating system error number .* in a file operation");
call mtr.add_suppression("InnoDB: The error means the system cannot find the path specified");
-call mtr.add_suppression("InnoDB: Ignoring tablespace for `test`.`\(t\|x\.\.d\)` because it could not be opened");
+call mtr.add_suppression("InnoDB: Ignoring tablespace for test/\(t\|x@002e@002ed\) because it could not be opened");
call mtr.add_suppression("InnoDB: Cannot calculate statistics for table .* because the .ibd file is missing");
call mtr.add_suppression("Could not find a valid tablespace file for");
call mtr.add_suppression("InnoDB: Failed to find tablespace for table `test`\.`\(t\|x\.\.d\)` in the cache");
diff --git a/mysql-test/suite/innodb/t/log_file_name.test b/mysql-test/suite/innodb/t/log_file_name.test
index f6a32b93dd9..534c4e6984f 100644
--- a/mysql-test/suite/innodb/t/log_file_name.test
+++ b/mysql-test/suite/innodb/t/log_file_name.test
@@ -164,7 +164,7 @@ call mtr.add_suppression("InnoDB: The error means the system cannot find the pat
call mtr.add_suppression("InnoDB: .*you must create directories");
call mtr.add_suppression("InnoDB: Cannot open datafile for read-only: '.*u[1-5]\.ibd'");
call mtr.add_suppression("InnoDB: Could not find a valid tablespace file for `test/u[1-5]`");
-call mtr.add_suppression("InnoDB: Ignoring tablespace for `test`.`u[1-3]` because it could not be opened.");
+call mtr.add_suppression("InnoDB: Ignoring tablespace for test/u[1-3] because it could not be opened\\.");
call mtr.add_suppression("InnoDB: Failed to find tablespace for table .* in the cache. Attempting to load the tablespace with space id");
call mtr.add_suppression("InnoDB: Plugin initialization aborted");
call mtr.add_suppression("Plugin 'InnoDB' \(init function returned error\|registration as a STORAGE ENGINE failed\)");
diff --git a/mysql-test/suite/innodb/t/restart.test b/mysql-test/suite/innodb/t/restart.test
index 2af0f2dd570..a5f2e5a42e8 100644
--- a/mysql-test/suite/innodb/t/restart.test
+++ b/mysql-test/suite/innodb/t/restart.test
@@ -18,7 +18,7 @@ let page_size= `select @@innodb_page_size`;
call mtr.add_suppression("\\[ERROR\\] InnoDB: Tablespace flags are invalid in datafile: .*test.t[rcd]\\.ibd");
call mtr.add_suppression("\\[ERROR\\] InnoDB: Operating system error number .* in a file operation\\.");
call mtr.add_suppression("\\[ERROR\\] InnoDB: The error means the system cannot find the path specified\\.");
-call mtr.add_suppression("\\[Warning\\] InnoDB: Ignoring tablespace for `test`\\.`td` because it could not be opened\\.");
+call mtr.add_suppression("\\[Warning\\] InnoDB: Ignoring tablespace for test/td because it could not be opened\\.");
CREATE TABLE tr(a INT)ENGINE=InnoDB ROW_FORMAT=REDUNDANT;
CREATE TABLE tc(a INT)ENGINE=InnoDB ROW_FORMAT=COMPACT
diff --git a/mysql-test/suite/innodb/t/row_format_redundant.test b/mysql-test/suite/innodb/t/row_format_redundant.test
index e8869b886c8..aadbfd2b773 100644
--- a/mysql-test/suite/innodb/t/row_format_redundant.test
+++ b/mysql-test/suite/innodb/t/row_format_redundant.test
@@ -4,7 +4,7 @@
--disable_query_log
call mtr.add_suppression("InnoDB: Table `mysql`\\.`innodb_table_stats` not found");
-call mtr.add_suppression("InnoDB: Table `test`.`t1` in InnoDB data dictionary contains invalid flags. SYS_TABLES\\.TYPE=1 SYS_TABLES\\.MIX_LEN=511\\r?$");
+call mtr.add_suppression("InnoDB: Table test/t1 in InnoDB data dictionary contains invalid flags. SYS_TABLES\\.TYPE=1 SYS_TABLES\\.MIX_LEN=511\\r?$");
call mtr.add_suppression("InnoDB: Parent table of FTS auxiliary table test/FTS_.* not found");
call mtr.add_suppression("InnoDB: Cannot open table test/t1 from the internal data dictionary");
call mtr.add_suppression("InnoDB: Table `test`.`t1` does not exist in the InnoDB internal data dictionary though MariaDB is trying to (rename|drop)");
@@ -153,7 +153,7 @@ RENAME TABLE t1 TO tee_one;
DROP TABLE t1;
DROP TABLE t2,t3;
---let SEARCH_PATTERN= \[ERROR\] InnoDB: Table `test`\.`t1` in InnoDB data dictionary contains invalid flags\. SYS_TABLES\.TYPE=1 SYS_TABLES\.MIX_LEN=511\b
+--let SEARCH_PATTERN= \[ERROR\] InnoDB: Table test/t1 in InnoDB data dictionary contains invalid flags\. SYS_TABLES\.TYPE=1 SYS_TABLES\.MIX_LEN=511\b
--source include/search_pattern_in_file.inc
--let $restart_parameters=
diff --git a/mysql-test/suite/innodb/t/table_flags.test b/mysql-test/suite/innodb/t/table_flags.test
index b037e46fb4f..f3a2c856af2 100644
--- a/mysql-test/suite/innodb/t/table_flags.test
+++ b/mysql-test/suite/innodb/t/table_flags.test
@@ -6,8 +6,8 @@
--disable_query_log
call mtr.add_suppression("InnoDB: Table `mysql`\\.`innodb_table_stats` not found");
call mtr.add_suppression("InnoDB: incorrect flags in SYS_TABLES");
-call mtr.add_suppression("InnoDB: Table `test`.`t[cp]` in InnoDB data dictionary contains invalid flags\\. SYS_TABLES\\.TYPE=(129|289|3873|1232[31]) SYS_TABLES\\.N_COLS=2147483649\\r?$");
-call mtr.add_suppression("InnoDB: Table `test`\\.`tr` in InnoDB data dictionary contains invalid flags\\. SYS_TABLES\\.TYPE=65 SYS_TABLES\\.MIX_LEN=4294967295\\r?$");
+call mtr.add_suppression("InnoDB: Table test/t[cp] in InnoDB data dictionary contains invalid flags\\. SYS_TABLES\\.TYPE=(129|289|3873|1232[31]) SYS_TABLES\\.N_COLS=2147483649\\r?$");
+call mtr.add_suppression("InnoDB: Table test/tr in InnoDB data dictionary contains invalid flags\\. SYS_TABLES\\.TYPE=65 SYS_TABLES\\.MIX_LEN=4294967295\\r?$");
call mtr.add_suppression("InnoDB: Refusing to load '\\..test.td\\.ibd' \\(id=3, flags=0x([2e]1)\\); dictionary contains id=3, flags=0x100\\1\\r?$");
call mtr.add_suppression("InnoDB: Refusing to load '\\..test.td\\.ibd' \\(id=3, flags=0x(1[2ae]1)\\); dictionary contains id=3, flags=0x10\\1\\r?$");
call mtr.add_suppression("InnoDB: Ignoring tablespace for `test`.`td` because it could not be opened\\.");
@@ -170,9 +170,9 @@ SHOW CREATE TABLE tp;
--source include/shutdown_mysqld.inc
let SEARCH_FILE= $MYSQLTEST_VARDIR/log/mysqld.1.err;
---let SEARCH_PATTERN= InnoDB: Table `test`.`t[cp]` in InnoDB data dictionary contains invalid flags\. SYS_TABLES\.TYPE=(129|289|3873|1232[13]) SYS_TABLES\.N_COLS=2147483649
+--let SEARCH_PATTERN= InnoDB: Table test/t[cp] in InnoDB data dictionary contains invalid flags\. SYS_TABLES\.TYPE=(129|289|3873|1232[13]) SYS_TABLES\.N_COLS=2147483649
--source include/search_pattern_in_file.inc
---let SEARCH_PATTERN= InnoDB: Table `test`\.`tr` in InnoDB data dictionary contains invalid flags\. SYS_TABLES\.TYPE=65 SYS_TABLES\.MIX_LEN=4294967295\b
+--let SEARCH_PATTERN= InnoDB: Table test/tr in InnoDB data dictionary contains invalid flags\. SYS_TABLES\.TYPE=65 SYS_TABLES\.MIX_LEN=4294967295\b
--source include/search_pattern_in_file.inc
# Restore the backup of the corrupted SYS_TABLES clustered index root page
diff --git a/mysql-test/suite/innodb/t/truncate_missing.test b/mysql-test/suite/innodb/t/truncate_missing.test
index c357f5bae72..fb6bd678237 100644
--- a/mysql-test/suite/innodb/t/truncate_missing.test
+++ b/mysql-test/suite/innodb/t/truncate_missing.test
@@ -3,7 +3,7 @@
call mtr.add_suppression("InnoDB: Operating system error number ");
call mtr.add_suppression("InnoDB: (The error means|If you are|Cannot open datafile) ");
-call mtr.add_suppression("InnoDB: Ignoring tablespace for `test`\.`t`");
+call mtr.add_suppression("InnoDB: Ignoring tablespace for test/t ");
call mtr.add_suppression("InnoDB: Table test/t .* does not exist");
CREATE TABLE t (a SERIAL) ENGINE=InnoDB;
diff --git a/mysql-test/suite/innodb_fts/t/crash_recovery.test b/mysql-test/suite/innodb_fts/t/crash_recovery.test
index fe58ca0addf..d5518b91590 100644
--- a/mysql-test/suite/innodb_fts/t/crash_recovery.test
+++ b/mysql-test/suite/innodb_fts/t/crash_recovery.test
@@ -252,7 +252,7 @@ if (!$have_debug)
call mtr.add_suppression("InnoDB: Cannot (read first page of|open datafile for read-only:) '\\./test/(FTS_|#sql-(alter|backup)-).*\\.ibd'");
call mtr.add_suppression("InnoDB: Datafile '\\./test/(FTS_|#sql-(alter|backup)-).*\\.ibd' is corrupted");
call mtr.add_suppression("InnoDB: (The error means|Operating system error)");
-call mtr.add_suppression("InnoDB: Ignoring tablespace for `test`\\.`(FTS_|#sql-(backup|alter)-).*` because it could not be opened\\.");
+call mtr.add_suppression("InnoDB: Ignoring tablespace for test/(FTS_|#sql-(backup|alter)-).* because it could not be opened\\.");
call mtr.add_suppression("InnoDB: Expected tablespace id [1-9][0-9]* but found 0 in the file .*/test/(FTS_|#sql-(alter|backup)-).*\\.ibd");
--enable_query_log
}
diff --git a/mysql-test/suite/innodb_zip/r/wl5522_debug_zip.result b/mysql-test/suite/innodb_zip/r/wl5522_debug_zip.result
index 92886ef7505..8708f26a653 100644
--- a/mysql-test/suite/innodb_zip/r/wl5522_debug_zip.result
+++ b/mysql-test/suite/innodb_zip/r/wl5522_debug_zip.result
@@ -7,7 +7,7 @@ call mtr.add_suppression("InnoDB: Unknown index id .* on page");
call mtr.add_suppression("InnoDB: Operating system error number");
call mtr.add_suppression("InnoDB: The error means");
call mtr.add_suppression("InnoDB: Cannot open datafile .*t1\\.ibd");
-call mtr.add_suppression("InnoDB: Ignoring tablespace for `test`\\.`t1`");
+call mtr.add_suppression("InnoDB: Ignoring tablespace for test/t1 ");
FLUSH TABLES;
SET SESSION innodb_strict_mode=1;
CREATE TABLE t1 (c1 INT) ENGINE = Innodb
diff --git a/mysql-test/suite/innodb_zip/t/wl5522_debug_zip.test b/mysql-test/suite/innodb_zip/t/wl5522_debug_zip.test
index a543fc956d4..0c9bcb6cf9d 100644
--- a/mysql-test/suite/innodb_zip/t/wl5522_debug_zip.test
+++ b/mysql-test/suite/innodb_zip/t/wl5522_debug_zip.test
@@ -23,7 +23,7 @@ call mtr.add_suppression("InnoDB: Unknown index id .* on page");
call mtr.add_suppression("InnoDB: Operating system error number");
call mtr.add_suppression("InnoDB: The error means");
call mtr.add_suppression("InnoDB: Cannot open datafile .*t1\\.ibd");
-call mtr.add_suppression("InnoDB: Ignoring tablespace for `test`\\.`t1`");
+call mtr.add_suppression("InnoDB: Ignoring tablespace for test/t1 ");
FLUSH TABLES;
let MYSQLD_DATADIR =`SELECT @@datadir`;
diff --git a/mysql-test/suite/mariabackup/missing_ibd.test b/mysql-test/suite/mariabackup/missing_ibd.test
index 5e34b873b09..dc1406039e7 100644
--- a/mysql-test/suite/mariabackup/missing_ibd.test
+++ b/mysql-test/suite/mariabackup/missing_ibd.test
@@ -12,7 +12,7 @@ call mtr.add_suppression("InnoDB: Cannot open datafile for read-only: '.*test.t1
call mtr.add_suppression('InnoDB: Operating system error number');
call mtr.add_suppression('InnoDB: The error means the system cannot find the path specified\.');
call mtr.add_suppression('InnoDB: Table test/t1 in the InnoDB data dictionary has tablespace id .*, but tablespace with that id or name does not exist');
-call mtr.add_suppression('InnoDB: Ignoring tablespace for `test`\.`t1` because it could not be opened\.');
+call mtr.add_suppression('InnoDB: Ignoring tablespace for test/t1 because it could not be opened\.');
--enable_query_log
--source include/shutdown_mysqld.inc
diff --git a/storage/innobase/CMakeLists.txt b/storage/innobase/CMakeLists.txt
index 35a1330cbd2..222e671a900 100644
--- a/storage/innobase/CMakeLists.txt
+++ b/storage/innobase/CMakeLists.txt
@@ -115,8 +115,6 @@ SET(INNOBASE_SOURCES
include/dict0mem.ic
include/dict0pagecompress.h
include/dict0pagecompress.ic
- include/dict0priv.h
- include/dict0priv.ic
include/dict0stats.h
include/dict0stats.ic
include/dict0stats_bg.h
diff --git a/storage/innobase/dict/dict0boot.cc b/storage/innobase/dict/dict0boot.cc
index afe8b5ec165..2792f71376d 100644
--- a/storage/innobase/dict/dict0boot.cc
+++ b/storage/innobase/dict/dict0boot.cc
@@ -96,45 +96,41 @@ void dict_hdr_flush_row_id(row_id_t id)
mtr.commit();
}
-/*****************************************************************//**
-Creates the file page for the dictionary header. This function is
-called only at the database creation.
-@return TRUE if succeed */
-static
-ibool
-dict_hdr_create(
-/*============*/
- mtr_t* mtr) /*!< in: mtr */
+/** Create the DICT_HDR page on database initialization.
+@return whether the operation failed */
+static bool dict_hdr_create()
{
buf_block_t* block;
ulint root_page_no;
- ut_ad(mtr);
+ bool fail = false;
+ mtr_t mtr;
+ mtr.start();
compile_time_assert(DICT_HDR_SPACE == 0);
/* Create the dictionary header file block in a new, allocated file
segment in the system tablespace */
block = fseg_create(fil_system.sys_space,
- DICT_HDR + DICT_HDR_FSEG_HEADER, mtr);
+ DICT_HDR + DICT_HDR_FSEG_HEADER, &mtr);
ut_a(block->page.id() == page_id_t(DICT_HDR_SPACE, DICT_HDR_PAGE_NO));
- buf_block_t* d = dict_hdr_get(mtr);
+ buf_block_t* d = dict_hdr_get(&mtr);
/* Start counting row, table, index, and tree ids from
DICT_HDR_FIRST_ID */
- mtr->write<8>(*d, DICT_HDR + DICT_HDR_ROW_ID + d->frame,
- DICT_HDR_FIRST_ID);
- mtr->write<8>(*d, DICT_HDR + DICT_HDR_TABLE_ID + d->frame,
- DICT_HDR_FIRST_ID);
- mtr->write<8>(*d, DICT_HDR + DICT_HDR_INDEX_ID + d->frame,
- DICT_HDR_FIRST_ID);
+ mtr.write<8>(*d, DICT_HDR + DICT_HDR_ROW_ID + d->frame,
+ DICT_HDR_FIRST_ID);
+ mtr.write<8>(*d, DICT_HDR + DICT_HDR_TABLE_ID + d->frame,
+ DICT_HDR_FIRST_ID);
+ mtr.write<8>(*d, DICT_HDR + DICT_HDR_INDEX_ID + d->frame,
+ DICT_HDR_FIRST_ID);
ut_ad(!mach_read_from_4(DICT_HDR + DICT_HDR_MAX_SPACE_ID + d->frame));
/* Obsolete, but we must initialize it anyway. */
- mtr->write<4>(*d, DICT_HDR + DICT_HDR_MIX_ID_LOW + d->frame,
- DICT_HDR_FIRST_ID);
+ mtr.write<4>(*d, DICT_HDR + DICT_HDR_MIX_ID_LOW + d->frame,
+ DICT_HDR_FIRST_ID);
/* Create the B-tree roots for the clustered indexes of the basic
system tables */
@@ -142,59 +138,55 @@ dict_hdr_create(
/*--------------------------*/
root_page_no = btr_create(DICT_CLUSTERED | DICT_UNIQUE,
fil_system.sys_space, DICT_TABLES_ID,
- nullptr, mtr);
+ nullptr, &mtr);
if (root_page_no == FIL_NULL) {
-
- return(FALSE);
+failed:
+ fail = true;
+ goto func_exit;
}
- mtr->write<4>(*d, DICT_HDR + DICT_HDR_TABLES + d->frame, root_page_no);
+ mtr.write<4>(*d, DICT_HDR + DICT_HDR_TABLES + d->frame, root_page_no);
/*--------------------------*/
root_page_no = btr_create(DICT_UNIQUE,
fil_system.sys_space, DICT_TABLE_IDS_ID,
- nullptr, mtr);
+ nullptr, &mtr);
if (root_page_no == FIL_NULL) {
-
- return(FALSE);
+ goto failed;
}
- mtr->write<4>(*d, DICT_HDR + DICT_HDR_TABLE_IDS + d->frame,
- root_page_no);
+ mtr.write<4>(*d, DICT_HDR + DICT_HDR_TABLE_IDS + d->frame,
+ root_page_no);
/*--------------------------*/
root_page_no = btr_create(DICT_CLUSTERED | DICT_UNIQUE,
fil_system.sys_space, DICT_COLUMNS_ID,
- nullptr, mtr);
+ nullptr, &mtr);
if (root_page_no == FIL_NULL) {
-
- return(FALSE);
+ goto failed;
}
- mtr->write<4>(*d, DICT_HDR + DICT_HDR_COLUMNS + d->frame,
- root_page_no);
+ mtr.write<4>(*d, DICT_HDR + DICT_HDR_COLUMNS + d->frame,
+ root_page_no);
/*--------------------------*/
root_page_no = btr_create(DICT_CLUSTERED | DICT_UNIQUE,
fil_system.sys_space, DICT_INDEXES_ID,
- nullptr, mtr);
+ nullptr, &mtr);
if (root_page_no == FIL_NULL) {
-
- return(FALSE);
+ goto failed;
}
- mtr->write<4>(*d, DICT_HDR + DICT_HDR_INDEXES + d->frame,
- root_page_no);
+ mtr.write<4>(*d, DICT_HDR + DICT_HDR_INDEXES + d->frame, root_page_no);
/*--------------------------*/
root_page_no = btr_create(DICT_CLUSTERED | DICT_UNIQUE,
fil_system.sys_space, DICT_FIELDS_ID,
- nullptr, mtr);
+ nullptr, &mtr);
if (root_page_no == FIL_NULL) {
-
- return(FALSE);
+ goto failed;
}
- mtr->write<4>(*d, DICT_HDR + DICT_HDR_FIELDS + d->frame, root_page_no);
- /*--------------------------*/
-
- return(TRUE);
+ mtr.write<4>(*d, DICT_HDR + DICT_HDR_FIELDS + d->frame, root_page_no);
+func_exit:
+ mtr.commit();
+ return fail;
}
/*****************************************************************//**
@@ -210,23 +202,21 @@ dict_boot(void)
mem_heap_t* heap;
mtr_t mtr;
- /* Be sure these constants do not ever change. To avoid bloat,
- only check the *NUM_FIELDS* in each table */
-
- ut_ad(DICT_NUM_COLS__SYS_TABLES == 8);
- ut_ad(DICT_NUM_FIELDS__SYS_TABLES == 10);
- ut_ad(DICT_NUM_FIELDS__SYS_TABLE_IDS == 2);
- ut_ad(DICT_NUM_COLS__SYS_COLUMNS == 7);
- ut_ad(DICT_NUM_FIELDS__SYS_COLUMNS == 9);
- ut_ad(DICT_NUM_COLS__SYS_INDEXES == 8);
- ut_ad(DICT_NUM_FIELDS__SYS_INDEXES == 10);
- ut_ad(DICT_NUM_COLS__SYS_FIELDS == 3);
- ut_ad(DICT_NUM_FIELDS__SYS_FIELDS == 5);
- ut_ad(DICT_NUM_COLS__SYS_FOREIGN == 4);
- ut_ad(DICT_NUM_FIELDS__SYS_FOREIGN == 6);
- ut_ad(DICT_NUM_FIELDS__SYS_FOREIGN_FOR_NAME == 2);
- ut_ad(DICT_NUM_COLS__SYS_FOREIGN_COLS == 4);
- ut_ad(DICT_NUM_FIELDS__SYS_FOREIGN_COLS == 6);
+ static_assert(DICT_NUM_COLS__SYS_TABLES == 8, "compatibility");
+ static_assert(DICT_NUM_FIELDS__SYS_TABLES == 10, "compatibility");
+ static_assert(DICT_NUM_FIELDS__SYS_TABLE_IDS == 2, "compatibility");
+ static_assert(DICT_NUM_COLS__SYS_COLUMNS == 7, "compatibility");
+ static_assert(DICT_NUM_FIELDS__SYS_COLUMNS == 9, "compatibility");
+ static_assert(DICT_NUM_COLS__SYS_INDEXES == 8, "compatibility");
+ static_assert(DICT_NUM_FIELDS__SYS_INDEXES == 10, "compatibility");
+ static_assert(DICT_NUM_COLS__SYS_FIELDS == 3, "compatibility");
+ static_assert(DICT_NUM_FIELDS__SYS_FIELDS == 5, "compatibility");
+ static_assert(DICT_NUM_COLS__SYS_FOREIGN == 4, "compatibility");
+ static_assert(DICT_NUM_FIELDS__SYS_FOREIGN == 6, "compatibility");
+ static_assert(DICT_NUM_FIELDS__SYS_FOREIGN_FOR_NAME == 2,
+ "compatibility");
+ static_assert(DICT_NUM_COLS__SYS_FOREIGN_COLS == 4, "compatibility");
+ static_assert(DICT_NUM_FIELDS__SYS_FOREIGN_COLS == 6, "compatibility");
mtr_start(&mtr);
@@ -260,9 +250,9 @@ dict_boot(void)
/* Insert into the dictionary cache the descriptions of the basic
system tables */
/*-------------------------*/
- table = dict_mem_table_create("SYS_TABLES", fil_system.sys_space,
- 8, 0, 0, 0);
-
+ table = dict_table_t::create(dict_sys.SYS_TABLE[dict_sys.SYS_TABLES],
+ fil_system.sys_space,
+ DICT_NUM_COLS__SYS_TABLES, 0, 0, 0);
dict_mem_table_add_col(table, heap, "NAME", DATA_BINARY, 0,
MAX_FULL_NAME_LEN);
dict_mem_table_add_col(table, heap, "ID", DATA_BINARY, 0, 8);
@@ -308,9 +298,9 @@ dict_boot(void)
ut_a(error == DB_SUCCESS);
/*-------------------------*/
- table = dict_mem_table_create("SYS_COLUMNS", fil_system.sys_space,
- 7, 0, 0, 0);
-
+ table = dict_table_t::create(dict_sys.SYS_TABLE[dict_sys.SYS_COLUMNS],
+ fil_system.sys_space,
+ DICT_NUM_COLS__SYS_COLUMNS, 0, 0, 0);
dict_mem_table_add_col(table, heap, "TABLE_ID", DATA_BINARY, 0, 8);
dict_mem_table_add_col(table, heap, "POS", DATA_INT, 0, 4);
dict_mem_table_add_col(table, heap, "NAME", DATA_BINARY, 0, 0);
@@ -341,8 +331,9 @@ dict_boot(void)
UT_BITS_IN_BYTES(unsigned(table->indexes.start->n_nullable)));
/*-------------------------*/
- table = dict_mem_table_create("SYS_INDEXES", fil_system.sys_space,
- DICT_NUM_COLS__SYS_INDEXES, 0, 0, 0);
+ table = dict_table_t::create(dict_sys.SYS_TABLE[dict_sys.SYS_INDEXES],
+ fil_system.sys_space,
+ DICT_NUM_COLS__SYS_INDEXES, 0, 0, 0);
dict_mem_table_add_col(table, heap, "TABLE_ID", DATA_BINARY, 0, 8);
dict_mem_table_add_col(table, heap, "ID", DATA_BINARY, 0, 8);
@@ -383,9 +374,9 @@ dict_boot(void)
UT_BITS_IN_BYTES(unsigned(table->indexes.start->n_nullable)));
/*-------------------------*/
- table = dict_mem_table_create("SYS_FIELDS", fil_system.sys_space,
- 3, 0, 0, 0);
-
+ table = dict_table_t::create(dict_sys.SYS_TABLE[dict_sys.SYS_FIELDS],
+ fil_system.sys_space,
+ DICT_NUM_COLS__SYS_FIELDS, 0, 0, 0);
dict_mem_table_add_col(table, heap, "INDEX_ID", DATA_BINARY, 0, 8);
dict_mem_table_add_col(table, heap, "POS", DATA_INT, 0, 4);
dict_mem_table_add_col(table, heap, "COL_NAME", DATA_BINARY, 0, 0);
@@ -413,10 +404,6 @@ dict_boot(void)
mtr_commit(&mtr);
- /*-------------------------*/
-
- /* Initialize the insert buffer table and index for each tablespace */
-
dberr_t err = ibuf_init_at_db_start();
if (err == DB_SUCCESS) {
@@ -426,44 +413,19 @@ dict_boot(void)
dict_load_sys_table(dict_sys.sys_columns);
dict_load_sys_table(dict_sys.sys_indexes);
dict_load_sys_table(dict_sys.sys_fields);
+ dict_sys.mutex_unlock();
+ dict_sys.load_sys_tables();
+ } else {
+ dict_sys.mutex_unlock();
}
- dict_sys.mutex_unlock();
-
return(err);
}
/*****************************************************************//**
-Inserts the basic system table data into themselves in the database
-creation. */
-static
-void
-dict_insert_initial_data(void)
-/*==========================*/
-{
- /* Does nothing yet */
-}
-
-/*****************************************************************//**
Creates and initializes the data dictionary at the server bootstrap.
@return DB_SUCCESS or error code. */
-dberr_t
-dict_create(void)
-/*=============*/
+dberr_t dict_create()
{
- mtr_t mtr;
-
- mtr_start(&mtr);
-
- dict_hdr_create(&mtr);
-
- mtr_commit(&mtr);
-
- dberr_t err = dict_boot();
-
- if (err == DB_SUCCESS) {
- dict_insert_initial_data();
- }
-
- return(err);
+ return dict_hdr_create() ? DB_ERROR : dict_boot();
}
diff --git a/storage/innobase/dict/dict0crea.cc b/storage/innobase/dict/dict0crea.cc
index 1d2f4f1abb1..0efc8a89903 100644
--- a/storage/innobase/dict/dict0crea.cc
+++ b/storage/innobase/dict/dict0crea.cc
@@ -41,9 +41,9 @@ Created 1/8/1996 Heikki Tuuri
#include "trx0rseg.h"
#include "trx0undo.h"
#include "ut0vec.h"
-#include "dict0priv.h"
#include "fts0priv.h"
#include "srv0start.h"
+#include "log.h"
/*****************************************************************//**
Based on a table object, this function builds the entry to be inserted
@@ -897,6 +897,17 @@ rec_corrupted:
return 0;
}
+/** @return whether SYS_TABLES.NAME is for a '#sql-ib' table */
+bool dict_table_t::is_garbage_name(const void *data, size_t size)
+{
+ constexpr size_t suffix= sizeof TEMP_FILE_PREFIX_INNODB;
+ if (size <= suffix)
+ return false;
+ const char *f= static_cast<const char*>(memchr(data, '/', size - suffix));
+ return f && !memcmp(f + 1, TEMP_FILE_PREFIX_INNODB,
+ (sizeof TEMP_FILE_PREFIX_INNODB) - 1);
+}
+
/*********************************************************************//**
Creates a table create graph.
@return own: table create node */
@@ -1315,259 +1326,196 @@ function_exit:
return(thr);
}
-/****************************************************************//**
-Check whether a system table exists. Additionally, if it exists,
-move it to the non-LRU end of the table LRU list. This is only used
-for system tables that can be upgraded or added to an older database,
-which include SYS_FOREIGN and SYS_FOREIGN_COLS.
-@return DB_SUCCESS if the sys table exists, DB_CORRUPTION if it exists
-but is not current, DB_TABLE_NOT_FOUND if it does not exist*/
-static
-dberr_t
-dict_check_if_system_table_exists(
-/*==============================*/
- const char* tablename, /*!< in: name of table */
- ulint num_fields, /*!< in: number of fields */
- ulint num_indexes) /*!< in: number of indexes */
-{
- dict_table_t* sys_table;
- dberr_t error = DB_SUCCESS;
-
- ut_ad(!srv_any_background_activity());
-
- dict_sys.mutex_lock();
-
- sys_table = dict_table_get_low(tablename);
-
- if (sys_table == NULL) {
- error = DB_TABLE_NOT_FOUND;
-
- } else if (UT_LIST_GET_LEN(sys_table->indexes) != num_indexes
- || sys_table->n_cols != num_fields) {
- error = DB_CORRUPTION;
-
- } else {
- /* This table has already been created, and it is OK.
- Ensure that it can't be evicted from the table LRU cache. */
-
- dict_table_prevent_eviction(sys_table);
- }
-
- dict_sys.mutex_unlock();
-
- return(error);
-}
-
-/****************************************************************//**
-Creates the foreign key constraints system tables inside InnoDB
-at server bootstrap or server start if they are not found or are
-not of the right form.
-@return DB_SUCCESS or error code */
-dberr_t
-dict_create_or_check_foreign_constraint_tables(void)
-/*================================================*/
+bool dict_sys_t::load_sys_tables()
{
- trx_t* trx;
- my_bool srv_file_per_table_backup;
- dberr_t err;
- dberr_t sys_foreign_err;
- dberr_t sys_foreign_cols_err;
-
- ut_ad(!srv_any_background_activity());
-
- sys_foreign_err = dict_check_if_system_table_exists(
- "SYS_FOREIGN", DICT_NUM_FIELDS__SYS_FOREIGN + 1, 3);
- sys_foreign_cols_err = dict_check_if_system_table_exists(
- "SYS_FOREIGN_COLS", DICT_NUM_FIELDS__SYS_FOREIGN_COLS + 1, 1);
-
- if (sys_foreign_err == DB_SUCCESS
- && sys_foreign_cols_err == DB_SUCCESS) {
- return(DB_SUCCESS);
- }
-
- if (srv_read_only_mode
- || srv_force_recovery >= SRV_FORCE_NO_TRX_UNDO) {
- return(DB_READ_ONLY);
- }
-
- trx = trx_create();
-
- trx->dict_operation = true;
-
- trx->op_info = "creating foreign key sys tables";
-
- row_mysql_lock_data_dictionary(trx);
-
- DBUG_EXECUTE_IF(
- "create_and_drop_garbage",
- err = que_eval_sql(
- NULL,
- "PROCEDURE CREATE_GARBAGE_TABLE_PROC () IS\n"
- "BEGIN\n"
- "CREATE TABLE\n"
- "\"test/" TEMP_FILE_PREFIX_INNODB "-garbage\""
- "(ID CHAR);\n"
- "CREATE UNIQUE CLUSTERED INDEX PRIMARY ON "
- "\"test/" TEMP_FILE_PREFIX_INNODB "-garbage\"(ID);\n"
- "END;\n", FALSE, trx);
- ut_ad(err == DB_SUCCESS);
- row_drop_table_for_mysql("test/"
- TEMP_FILE_PREFIX_INNODB "-garbage",
- trx, SQLCOM_DROP_DB, true););
-
- ib::info() << "Creating foreign key constraint system tables.";
-
- /* NOTE: in dict_load_foreigns we use the fact that
- there are 2 secondary indexes on SYS_FOREIGN, and they
- are defined just like below */
-
- /* NOTE: when designing InnoDB's foreign key support in 2001, we made
- an error and made the table names and the foreign key id of type
- 'CHAR' (internally, really a VARCHAR). We should have made the type
- VARBINARY, like in other InnoDB system tables, to get a clean
- design. */
-
- srv_file_per_table_backup = srv_file_per_table;
-
- /* We always want SYSTEM tables to be created inside the system
- tablespace. */
-
- srv_file_per_table = 0;
-
- err = que_eval_sql(
- NULL,
- "PROCEDURE CREATE_FOREIGN_SYS_TABLES_PROC () IS\n"
- "BEGIN\n"
- "CREATE TABLE\n"
- "SYS_FOREIGN(ID CHAR, FOR_NAME CHAR,"
- " REF_NAME CHAR, N_COLS INT);\n"
- "CREATE UNIQUE CLUSTERED INDEX ID_IND"
- " ON SYS_FOREIGN (ID);\n"
- "CREATE INDEX FOR_IND"
- " ON SYS_FOREIGN (FOR_NAME);\n"
- "CREATE INDEX REF_IND"
- " ON SYS_FOREIGN (REF_NAME);\n"
- "CREATE TABLE\n"
- "SYS_FOREIGN_COLS(ID CHAR, POS INT,"
- " FOR_COL_NAME CHAR, REF_COL_NAME CHAR);\n"
- "CREATE UNIQUE CLUSTERED INDEX ID_IND"
- " ON SYS_FOREIGN_COLS (ID, POS);\n"
- "END;\n",
- FALSE, trx);
-
- if (UNIV_UNLIKELY(err != DB_SUCCESS)) {
- ib::error() << "Creation of SYS_FOREIGN and SYS_FOREIGN_COLS"
- " failed: " << err;
-
- ut_ad(err == DB_OUT_OF_FILE_SPACE
- || err == DB_TOO_MANY_CONCURRENT_TRXS);
- trx->rollback();
- } else {
- trx_commit_for_mysql(trx);
- }
-
- row_mysql_unlock_data_dictionary(trx);
-
- trx->free();
-
- srv_file_per_table = srv_file_per_table_backup;
-
- /* Note: The master thread has not been started at this point. */
- /* Confirm and move to the non-LRU part of the table LRU list. */
- sys_foreign_err = dict_check_if_system_table_exists(
- "SYS_FOREIGN", DICT_NUM_FIELDS__SYS_FOREIGN + 1, 3);
- ut_a(sys_foreign_err == DB_SUCCESS);
-
- sys_foreign_cols_err = dict_check_if_system_table_exists(
- "SYS_FOREIGN_COLS", DICT_NUM_FIELDS__SYS_FOREIGN_COLS + 1, 1);
- ut_a(sys_foreign_cols_err == DB_SUCCESS);
-
- return(err);
+ ut_ad(!srv_any_background_activity());
+ bool mismatch= false;
+ mutex_lock();
+ if (!(sys_foreign= load_table(SYS_TABLE[SYS_FOREIGN],
+ DICT_ERR_IGNORE_FK_NOKEY)));
+ else if (UT_LIST_GET_LEN(sys_foreign->indexes) == 3 &&
+ sys_foreign->n_cols == DICT_NUM_COLS__SYS_FOREIGN + DATA_N_SYS_COLS)
+ prevent_eviction(sys_foreign);
+ else
+ {
+ sys_foreign= nullptr;
+ mismatch= true;
+ ib::error() << "Invalid definition of SYS_FOREIGN";
+ }
+ if (!(sys_foreign_cols= load_table(SYS_TABLE[SYS_FOREIGN_COLS],
+ DICT_ERR_IGNORE_FK_NOKEY)));
+ else if (UT_LIST_GET_LEN(sys_foreign_cols->indexes) == 1 &&
+ sys_foreign_cols->n_cols ==
+ DICT_NUM_COLS__SYS_FOREIGN_COLS + DATA_N_SYS_COLS)
+ prevent_eviction(sys_foreign_cols);
+ else
+ {
+ sys_foreign_cols= nullptr;
+ mismatch= true;
+ ib::error() << "Invalid definition of SYS_FOREIGN_COLS";
+ }
+ if (!(sys_virtual= load_table(SYS_TABLE[SYS_VIRTUAL],
+ DICT_ERR_IGNORE_FK_NOKEY)));
+ else if (UT_LIST_GET_LEN(sys_virtual->indexes) == 1 &&
+ sys_virtual->n_cols == DICT_NUM_COLS__SYS_VIRTUAL + DATA_N_SYS_COLS)
+ prevent_eviction(sys_virtual);
+ else
+ {
+ sys_virtual= nullptr;
+ mismatch= true;
+ ib::error() << "Invalid definition of SYS_VIRTUAL";
+ }
+ mutex_unlock();
+ return mismatch;
}
-/** Creates the virtual column system table (SYS_VIRTUAL) inside InnoDB
-at server bootstrap or server start if the table is not found or is
-not of the right form.
-@return DB_SUCCESS or error code */
-dberr_t
-dict_create_or_check_sys_virtual()
+dberr_t dict_sys_t::create_or_check_sys_tables()
{
- trx_t* trx;
- my_bool srv_file_per_table_backup;
- dberr_t err;
-
- ut_ad(!srv_any_background_activity());
-
- err = dict_check_if_system_table_exists(
- "SYS_VIRTUAL", DICT_NUM_FIELDS__SYS_VIRTUAL + 1, 1);
-
- if (err == DB_SUCCESS) {
- dict_sys.mutex_lock();
- dict_sys.sys_virtual = dict_table_get_low("SYS_VIRTUAL");
- dict_sys.mutex_unlock();
- return(DB_SUCCESS);
- }
-
- if (srv_read_only_mode
- || srv_force_recovery >= SRV_FORCE_NO_TRX_UNDO) {
- return(DB_READ_ONLY);
- }
-
- trx = trx_create();
-
- trx->dict_operation = true;
-
- trx->op_info = "creating sys_virtual tables";
-
- row_mysql_lock_data_dictionary(trx);
-
- ib::info() << "Creating sys_virtual system tables.";
-
- srv_file_per_table_backup = srv_file_per_table;
-
- /* We always want SYSTEM tables to be created inside the system
- tablespace. */
+ if (sys_tables_exist())
+ return DB_SUCCESS;
- srv_file_per_table = 0;
+ if (srv_read_only_mode || srv_force_recovery >= SRV_FORCE_NO_TRX_UNDO)
+ return DB_READ_ONLY;
- err = que_eval_sql(
- NULL,
- "PROCEDURE CREATE_SYS_VIRTUAL_TABLES_PROC () IS\n"
- "BEGIN\n"
- "CREATE TABLE\n"
- "SYS_VIRTUAL(TABLE_ID BIGINT, POS INT,"
- " BASE_POS INT);\n"
- "CREATE UNIQUE CLUSTERED INDEX BASE_IDX"
- " ON SYS_VIRTUAL(TABLE_ID, POS, BASE_POS);\n"
- "END;\n",
- FALSE, trx);
+ if (load_sys_tables())
+ {
+ ib::info() << "Set innodb_read_only=1 or innodb_force_recovery=3"
+ " to start up";
+ return DB_CORRUPTION;
+ }
- if (UNIV_UNLIKELY(err != DB_SUCCESS)) {
- ib::error() << "Creation of SYS_VIRTUAL failed: " << err;
+ if (sys_tables_exist())
+ return DB_SUCCESS;
- ut_ad(err == DB_OUT_OF_FILE_SPACE
- || err == DB_TOO_MANY_CONCURRENT_TRXS);
- trx->rollback();
- } else {
- trx_commit_for_mysql(trx);
- }
+ trx_t *trx= trx_create();
+ trx->dict_operation = true;
+ row_mysql_lock_data_dictionary(trx);
+
+ DBUG_EXECUTE_IF("create_and_drop_garbage",
+ ut_ad(DB_SUCCESS == que_eval_sql(
+ nullptr,
+ "PROCEDURE CREATE_GARBAGE_TABLE_PROC () IS\n"
+ "BEGIN\n"
+ "CREATE TABLE\n"
+ "\"test/" TEMP_FILE_PREFIX_INNODB "-garbage\""
+ "(ID CHAR);\n"
+ "CREATE UNIQUE CLUSTERED INDEX PRIMARY ON "
+ "\"test/" TEMP_FILE_PREFIX_INNODB
+ "-garbage\"(ID);\n"
+ "END;\n", false, trx));
+ row_drop_table_for_mysql("test/"
+ TEMP_FILE_PREFIX_INNODB "-garbage",
+ trx, SQLCOM_DROP_DB, true););
+
+ /* NOTE: when designing InnoDB's foreign key support in 2001, Heikki Tuuri
+ made a mistake defined table names and the foreign key id to be of type
+ 'CHAR' (internally, really a VARCHAR).
+ The type should have been VARBINARY. */
+
+ const auto srv_file_per_table_backup= srv_file_per_table;
+
+ /* We always want SYSTEM tables to be created inside the system
+ tablespace. */
+ srv_file_per_table= 0;
+ dberr_t error;
+ const char *tablename;
+
+ if (!sys_foreign)
+ {
+ error= que_eval_sql(nullptr, "PROCEDURE CREATE_FOREIGN() IS\n"
+ "BEGIN\n"
+ "CREATE TABLE\n"
+ "SYS_FOREIGN(ID CHAR, FOR_NAME CHAR,"
+ " REF_NAME CHAR, N_COLS INT);\n"
+ "CREATE UNIQUE CLUSTERED INDEX ID_IND"
+ " ON SYS_FOREIGN (ID);\n"
+ "CREATE INDEX FOR_IND"
+ " ON SYS_FOREIGN (FOR_NAME);\n"
+ "CREATE INDEX REF_IND"
+ " ON SYS_FOREIGN (REF_NAME);\n"
+ "END;\n", false, trx);
+ if (UNIV_UNLIKELY(error != DB_SUCCESS))
+ {
+ tablename= SYS_TABLE[SYS_FOREIGN].data();
+err_exit:
+ ib::error() << "Creation of " << tablename << " failed: " << error;
+ trx->rollback();
+ row_mysql_unlock_data_dictionary(trx);
+ trx->free();
+ srv_file_per_table= srv_file_per_table_backup;
+ return error;
+ }
+ }
+ if (!sys_foreign_cols)
+ {
+ error= que_eval_sql(nullptr, "PROCEDURE CREATE_FOREIGN_COLS() IS\n"
+ "BEGIN\n"
+ "CREATE TABLE\n"
+ "SYS_FOREIGN_COLS(ID CHAR, POS INT,"
+ " FOR_COL_NAME CHAR, REF_COL_NAME CHAR);\n"
+ "CREATE UNIQUE CLUSTERED INDEX ID_IND"
+ " ON SYS_FOREIGN_COLS (ID, POS);\n"
+ "END;\n", false, trx);
+ if (UNIV_UNLIKELY(error != DB_SUCCESS))
+ {
+ tablename= SYS_TABLE[SYS_FOREIGN_COLS].data();
+ goto err_exit;
+ }
+ }
+ if (!sys_virtual)
+ {
+ error= que_eval_sql(nullptr, "PROCEDURE CREATE_VIRTUAL() IS\n"
+ "BEGIN\n"
+ "CREATE TABLE\n"
+ "SYS_VIRTUAL(TABLE_ID BIGINT,POS INT,BASE_POS INT);\n"
+ "CREATE UNIQUE CLUSTERED INDEX BASE_IDX"
+ " ON SYS_VIRTUAL(TABLE_ID, POS, BASE_POS);\n"
+ "END;\n", false, trx);
+ if (UNIV_UNLIKELY(error != DB_SUCCESS))
+ {
+ tablename= SYS_TABLE[SYS_VIRTUAL].data();
+ goto err_exit;
+ }
+ }
- row_mysql_unlock_data_dictionary(trx);
+ trx->commit();
+ row_mysql_unlock_data_dictionary(trx);
+ trx->free();
+ srv_file_per_table= srv_file_per_table_backup;
- trx->free();
+ mutex_lock();
+ if (sys_foreign);
+ else if (!(sys_foreign= load_table(SYS_TABLE[SYS_FOREIGN])))
+ {
+ tablename= SYS_TABLE[SYS_FOREIGN].data();
+load_fail:
+ mutex_unlock();
+ ib::error() << "Failed to CREATE TABLE " << tablename;
+ return DB_TABLE_NOT_FOUND;
+ }
+ else
+ prevent_eviction(sys_foreign);
- srv_file_per_table = srv_file_per_table_backup;
+ if (sys_foreign_cols);
+ else if (!(sys_foreign_cols= load_table(SYS_TABLE[SYS_FOREIGN_COLS])))
+ {
+ tablename= SYS_TABLE[SYS_FOREIGN_COLS].data();
+ goto load_fail;
+ }
+ else
+ prevent_eviction(sys_foreign_cols);
- /* Note: The master thread has not been started at this point. */
- /* Confirm and move to the non-LRU part of the table LRU list. */
- dberr_t sys_virtual_err = dict_check_if_system_table_exists(
- "SYS_VIRTUAL", DICT_NUM_FIELDS__SYS_VIRTUAL + 1, 1);
- ut_a(sys_virtual_err == DB_SUCCESS);
- dict_sys.mutex_lock();
- dict_sys.sys_virtual = dict_table_get_low("SYS_VIRTUAL");
- dict_sys.mutex_unlock();
+ if (sys_virtual);
+ else if (!(sys_virtual= load_table(SYS_TABLE[SYS_VIRTUAL])))
+ {
+ tablename= SYS_TABLE[SYS_VIRTUAL].data();
+ goto load_fail;
+ }
+ else
+ prevent_eviction(sys_virtual);
- return(err);
+ mutex_unlock();
+ return DB_SUCCESS;
}
/****************************************************************//**
@@ -1959,35 +1907,19 @@ dict_create_add_foreigns_to_dictionary(
const dict_table_t* table,
trx_t* trx)
{
- dict_foreign_t* foreign;
- dberr_t error;
-
- dict_sys.assert_locked();
-
- if (NULL == dict_table_get_low("SYS_FOREIGN")) {
-
- ib::error() << "Table SYS_FOREIGN not found"
- " in internal data dictionary";
+ dict_sys.assert_locked();
- return(DB_ERROR);
- }
-
- error = DB_SUCCESS;
-
- for (dict_foreign_set::const_iterator it = local_fk_set.begin();
- it != local_fk_set.end();
- ++it) {
-
- foreign = *it;
- ut_ad(foreign->id != NULL);
-
- error = dict_create_add_foreign_to_dictionary(
- table->name.m_name, foreign, trx);
+ if (!dict_sys.sys_foreign)
+ {
+ sql_print_error("InnoDB: Table SYS_FOREIGN not found"
+ " in internal data dictionary");
+ return DB_ERROR;
+ }
- if (error != DB_SUCCESS) {
- break;
- }
- }
+ for (auto fk : local_fk_set)
+ if (dberr_t error=
+ dict_create_add_foreign_to_dictionary(table->name.m_name, fk, trx))
+ return error;
- return error;
+ return DB_SUCCESS;
}
diff --git a/storage/innobase/dict/dict0dict.cc b/storage/innobase/dict/dict0dict.cc
index 1a6ff572bda..74f7af216e3 100644
--- a/storage/innobase/dict/dict0dict.cc
+++ b/storage/innobase/dict/dict0dict.cc
@@ -51,9 +51,9 @@ extern uint ibuf_debug;
#include "buf0buf.h"
#include "data0type.h"
#include "dict0boot.h"
+#include "dict0load.h"
#include "dict0crea.h"
#include "dict0mem.h"
-#include "dict0priv.h"
#include "dict0stats.h"
#include "fts0fts.h"
#include "fts0types.h"
@@ -80,6 +80,15 @@ extern uint ibuf_debug;
/** the dictionary system */
dict_sys_t dict_sys;
+/** System table names; @see dict_system_id_t */
+const span<const char> dict_sys_t::SYS_TABLE[]=
+{
+ {C_STRING_WITH_LEN("SYS_TABLES")},{C_STRING_WITH_LEN("SYS_INDEXES")},
+ {C_STRING_WITH_LEN("SYS_COLUMNS")},{C_STRING_WITH_LEN("SYS_FIELDS")},
+ {C_STRING_WITH_LEN("SYS_FOREIGN")},{C_STRING_WITH_LEN("SYS_FOREIGN_COLS")},
+ {C_STRING_WITH_LEN("SYS_VIRTUAL")}
+};
+
/** Diagnostic message for exceeding the mutex_lock_wait() timeout */
const char dict_sys_t::fatal_msg[]=
"innodb_fatal_semaphore_wait_threshold was exceeded for dict_sys.mutex. "
@@ -216,7 +225,7 @@ static dict_table_t* dict_table_open_on_id_low(
dict_err_ignore_t ignore_err,
bool cached_only)
{
- dict_table_t* table = dict_sys.get_table(table_id);
+ dict_table_t* table = dict_sys.find_table(table_id);
if (!table && !cached_only) {
table = dict_load_table_on_id(table_id, ignore_err);
@@ -1097,17 +1106,11 @@ dict_table_open_on_name(
}
ut_ad(table_name);
- dict_sys.assert_locked();
+ table = dict_sys.load_table({table_name, strlen(table_name)},
+ ignore_err);
- table = dict_table_check_if_in_cache_low(table_name);
-
- if (table == NULL) {
- table = dict_load_table(table_name, ignore_err);
- }
-
- ut_ad(!table || table->cached);
-
- if (table != NULL) {
+ if (table) {
+ ut_ad(table->cached);
/* If table is encrypted or corrupted */
if (!(ignore_err & ~DICT_ERR_IGNORE_FK_NOKEY)
@@ -2984,11 +2987,13 @@ dict_foreign_add_to_cache(
dict_sys.assert_locked();
- for_table = dict_table_check_if_in_cache_low(
- foreign->foreign_table_name_lookup);
+ for_table = dict_sys.find_table(
+ {foreign->foreign_table_name_lookup,
+ strlen(foreign->foreign_table_name_lookup)});
- ref_table = dict_table_check_if_in_cache_low(
- foreign->referenced_table_name_lookup);
+ ref_table = dict_sys.find_table(
+ {foreign->referenced_table_name_lookup,
+ strlen(foreign->referenced_table_name_lookup)});
ut_a(for_table || ref_table);
if (for_table) {
@@ -3384,8 +3389,8 @@ dict_get_referenced_table(
}
/* Copy database_name, '/', table_name, '\0' */
- ref = static_cast<char*>(mem_heap_alloc(
- heap, database_name_len + table_name_len + 2));
+ const size_t len = database_name_len + table_name_len + 1;
+ ref = static_cast<char*>(mem_heap_alloc(heap, len + 1));
memcpy(ref, database_name, database_name_len);
ref[database_name_len] = '/';
memcpy(ref + database_name_len + 1, table_name, table_name_len + 1);
@@ -3395,7 +3400,7 @@ dict_get_referenced_table(
2 = Store as given, compare in lower; case semi-sensitive */
if (lower_case_table_names == 2) {
innobase_casedn_str(ref);
- *table = dict_table_get_low(ref);
+ *table = dict_sys.load_table({ref, len});
memcpy(ref, database_name, database_name_len);
ref[database_name_len] = '/';
memcpy(ref + database_name_len + 1, table_name, table_name_len + 1);
@@ -3408,7 +3413,7 @@ dict_get_referenced_table(
#else
innobase_casedn_str(ref);
#endif /* !_WIN32 */
- *table = dict_table_get_low(ref);
+ *table = dict_sys.load_table({ref, len});
}
return(ref);
@@ -5031,9 +5036,3 @@ dict_tf_to_row_format_string(
ut_error;
return(0);
}
-
-bool dict_table_t::is_stats_table() const
-{
- return !strcmp(name.m_name, TABLE_STATS_NAME) ||
- !strcmp(name.m_name, INDEX_STATS_NAME);
-}
diff --git a/storage/innobase/dict/dict0load.cc b/storage/innobase/dict/dict0load.cc
index a0e8088831b..3fe0104f484 100644
--- a/storage/innobase/dict/dict0load.cc
+++ b/storage/innobase/dict/dict0load.cc
@@ -27,14 +27,13 @@ Created 4/24/1996 Heikki Tuuri
#include "dict0load.h"
-#include "mysql_version.h"
+#include "log.h"
#include "btr0pcur.h"
#include "btr0btr.h"
#include "dict0boot.h"
#include "dict0crea.h"
#include "dict0dict.h"
#include "dict0mem.h"
-#include "dict0priv.h"
#include "dict0stats.h"
#include "fsp0file.h"
#include "fts0priv.h"
@@ -45,18 +44,6 @@ Created 4/24/1996 Heikki Tuuri
#include "srv0srv.h"
#include "fts0opt.h"
-/** Following are the InnoDB system tables. The positions in
-this array are referenced by enum dict_system_table_id. */
-static const char* SYSTEM_TABLE_NAME[] = {
- "SYS_TABLES",
- "SYS_INDEXES",
- "SYS_COLUMNS",
- "SYS_FIELDS",
- "SYS_FOREIGN",
- "SYS_FOREIGN_COLS",
- "SYS_VIRTUAL"
-};
-
/** Loads a table definition and also all its index definitions.
Loads those foreign key constraints whose referenced table is already in
@@ -71,26 +58,11 @@ key constraints are loaded into memory.
@param[out] fk_tables Related table names that must also be
loaded to ensure that all foreign key
constraints are loaded.
-@return table, NULL if does not exist; if the table is stored in an
-.ibd file, but the file does not exist, then we set the
-file_unreadable flag in the table object we return */
-static
-dict_table_t*
-dict_load_table_one(
- const table_name_t& name,
- dict_err_ignore_t ignore_err,
- dict_names_t& fk_tables);
-
-/** Load a table definition from a SYS_TABLES record to dict_table_t.
-Do not load any columns or indexes.
-@param[in] name Table name
-@param[in] rec SYS_TABLES record
-@param[out,own] table table, or NULL
-@return error message
-@retval NULL on success */
-static const char* dict_load_table_low(const table_name_t& name,
- const rec_t* rec, dict_table_t** table)
- MY_ATTRIBUTE((nonnull, warn_unused_result));
+@return table, possibly with file_unreadable flag set
+@retval nullptr if the table does not exist */
+static dict_table_t *dict_load_table_one(const span<const char> &name,
+ dict_err_ignore_t ignore_err,
+ dict_names_t &fk_tables);
/** Load an index definition from a SYS_INDEXES record to dict_index_t.
If allocate=TRUE, we will create a dict_index_t structure and fill it
@@ -239,24 +211,11 @@ dict_startscan_system(
btr_pcur_t* pcur, /*!< out: persistent cursor to
the record */
mtr_t* mtr, /*!< in: the mini-transaction */
- dict_system_id_t system_id) /*!< in: which system table to open */
+ dict_table_t* table) /*!< in: system table */
{
- dict_table_t* system_table;
- dict_index_t* clust_index;
- const rec_t* rec;
-
- ut_a(system_id < SYS_NUM_SYSTEM_TABLES);
-
- system_table = dict_table_get_low(SYSTEM_TABLE_NAME[system_id]);
-
- clust_index = UT_LIST_GET_FIRST(system_table->indexes);
-
- btr_pcur_open_at_index_side(true, clust_index, BTR_SEARCH_LEAF, pcur,
- true, 0, mtr);
-
- rec = dict_getnext_system_low(pcur, mtr);
-
- return(rec);
+ btr_pcur_open_at_index_side(true, table->indexes.start,
+ BTR_SEARCH_LEAF, pcur, true, 0, mtr);
+ return dict_getnext_system_low(pcur, mtr);
}
/********************************************************************//**
@@ -281,46 +240,6 @@ dict_getnext_system(
}
/********************************************************************//**
-This function processes one SYS_TABLES record and populate the dict_table_t
-struct for the table.
-@return error message, or NULL on success */
-const char*
-dict_process_sys_tables_rec_and_mtr_commit(
-/*=======================================*/
- mem_heap_t* heap, /*!< in/out: temporary memory heap */
- const rec_t* rec, /*!< in: SYS_TABLES record */
- dict_table_t** table, /*!< out: dict_table_t to fill */
- bool cached, /*!< in: whether to load from cache */
- mtr_t* mtr) /*!< in/out: mini-transaction,
- will be committed */
-{
- ulint len;
- const char* field;
-
- field = (const char*) rec_get_nth_field_old(
- rec, DICT_FLD__SYS_TABLES__NAME, &len);
-
- ut_a(!rec_get_deleted_flag(rec, 0));
-
- ut_ad(mtr->memo_contains_page_flagged(rec, MTR_MEMO_PAGE_S_FIX));
-
- /* Get the table name */
- table_name_t table_name(mem_heap_strdupl(heap, field, len));
-
- if (cached) {
- /* Commit before load the table again */
- mtr_commit(mtr);
-
- *table = dict_table_get_low(table_name.m_name);
- return *table ? NULL : "Table not found in cache";
- } else {
- const char* err = dict_load_table_low(table_name, rec, table);
- mtr_commit(mtr);
- return err;
- }
-}
-
-/********************************************************************//**
This function parses a SYS_INDEXES record and populate a dict_index_t
structure with the information from the record. For detail information
about SYS_INDEXES fields, please refer to dict_boot() function.
@@ -724,7 +643,7 @@ dict_sys_tables_type_to_tf(ulint type, bool not_redundant)
/** Read and return 5 integer fields from a SYS_TABLES record.
@param[in] rec A record of SYS_TABLES
-@param[in] name Table Name, the same as SYS_TABLES.NAME
+@param[in] name SYS_TABLES.NAME
@param[out] table_id Pointer to the table_id for this table
@param[out] space_id Pointer to the space_id for this table
@param[out] n_cols Pointer to number of columns for this table.
@@ -736,7 +655,7 @@ static
bool
dict_sys_tables_rec_read(
const rec_t* rec,
- const table_name_t& table_name,
+ const span<const char>& name,
table_id_t* table_id,
ulint* space_id,
ulint* n_cols,
@@ -850,10 +769,11 @@ dict_sys_tables_rec_read(
const bool not_redundant = 0 != (*n_cols & DICT_N_COLS_COMPACT);
if (!dict_sys_tables_type_valid(type, not_redundant)) {
- ib::error() << "Table " << table_name << " in InnoDB"
- " data dictionary contains invalid flags."
- " SYS_TABLES.TYPE=" << type <<
- " SYS_TABLES.N_COLS=" << *n_cols;
+ sql_print_error("InnoDB: Table %.*s in InnoDB"
+ " data dictionary contains invalid flags."
+ " SYS_TABLES.TYPE=" ULINTPF
+ " SYS_TABLES.N_COLS=" ULINTPF,
+ name.size(), name.data(), type, *n_cols);
return(false);
}
@@ -873,10 +793,13 @@ dict_sys_tables_rec_read(
*flags2 = mach_read_from_4(field);
if (!dict_tf2_is_valid(*flags, *flags2)) {
- ib::error() << "Table " << table_name << " in InnoDB"
- " data dictionary contains invalid flags."
- " SYS_TABLES.TYPE=" << type
- << " SYS_TABLES.MIX_LEN=" << *flags2;
+ sql_print_error("InnoDB: Table %.*s in InnoDB"
+ " data dictionary"
+ " contains invalid flags."
+ " SYS_TABLES.TYPE=" ULINTPF
+ " SYS_TABLES.MIX_LEN=" ULINTPF,
+ name.size(), name.data(),
+ type, *flags2);
return(false);
}
@@ -901,7 +824,6 @@ static ulint dict_check_sys_tables()
{
ulint max_space_id = 0;
btr_pcur_t pcur;
- const rec_t* rec;
mtr_t mtr;
DBUG_ENTER("dict_check_sys_tables");
@@ -910,11 +832,9 @@ static ulint dict_check_sys_tables()
mtr_start(&mtr);
- for (rec = dict_startscan_system(&pcur, &mtr, SYS_TABLES);
- rec != NULL;
- mtr.commit(), mtr.start(),
- rec = dict_getnext_system(&pcur, &mtr)) {
- const byte* field;
+ for (const rec_t *rec = dict_startscan_system(&pcur, &mtr,
+ dict_sys.sys_tables);
+ rec; rec = dict_getnext_system(&pcur, &mtr)) {
ulint len;
table_id_t table_id;
ulint space_id;
@@ -924,39 +844,40 @@ static ulint dict_check_sys_tables()
/* If a table record is not useable, ignore it and continue
on to the next record. Error messages were logged. */
- if (dict_sys_tables_rec_check(rec) != NULL) {
+ if (dict_sys_tables_rec_check(rec)) {
continue;
}
/* Copy the table name from rec */
- field = rec_get_nth_field_old(
- rec, DICT_FLD__SYS_TABLES__NAME, &len);
+ const char *field = reinterpret_cast<const char*>(
+ rec_get_nth_field_old(rec, DICT_FLD__SYS_TABLES__NAME,
+ &len));
+
+ if (len == UNIV_SQL_NULL
+ || dict_table_t::is_garbage_name(field, len)) {
+ /* This table will be dropped by
+ dict_table_t::drop_garbage().
+ We do not care if the file exists. */
+ continue;
+ }
- table_name_t table_name(mem_strdupl((char*) field, len));
DBUG_PRINT("dict_check_sys_tables",
- ("name: %p, '%s'", table_name.m_name,
- table_name.m_name));
+ ("name: %*.s", static_cast<int>(len), field));
+
+ const span<const char> name{field, len};
- if (!dict_sys_tables_rec_read(rec, table_name,
- &table_id, &space_id,
+ if (!dict_sys_tables_rec_read(rec, name, &table_id, &space_id,
&n_cols, &flags, &flags2)
|| space_id == TRX_SYS_SPACE) {
-next:
- ut_free(table_name.m_name);
continue;
}
- if (strstr(table_name.m_name, "/" TEMP_FILE_PREFIX_INNODB)) {
- /* This table will be dropped by
- row_mysql_drop_garbage_tables().
- We do not care if the file exists. */
- goto next;
- }
-
if (flags2 & DICT_TF2_DISCARDED) {
- ib::info() << "Ignoring tablespace for " << table_name
- << " because the DISCARD flag is set .";
- goto next;
+ sql_print_information("InnoDB: Ignoring tablespace"
+ " for %.*s because "
+ "the DISCARD flag is set",
+ static_cast<int>(len), field);
+ continue;
}
/* For tables or partitions using .ibd files, the flag
@@ -968,10 +889,10 @@ next:
will otherwise ignore the flag. */
if (fil_space_for_table_exists_in_mem(space_id, flags)) {
- goto next;
+ continue;
}
- char* filepath = fil_make_filepath(nullptr, table_name,
+ char* filepath = fil_make_filepath(nullptr, name,
IBD, false);
/* Check that the .ibd file exists. */
@@ -979,16 +900,17 @@ next:
false,
FIL_TYPE_TABLESPACE,
space_id, dict_tf_to_fsp_flags(flags),
- table_name, filepath)) {
- ib::warn() << "Ignoring tablespace for "
- << table_name
- << " because it could not be opened.";
+ name, filepath)) {
+ sql_print_warning("InnoDB: Ignoring tablespace for"
+ " %.*s because it"
+ " could not be opened.",
+ static_cast<int>(name.size()),
+ name.data());
}
max_space_id = ut_max(max_space_id, space_id);
ut_free(filepath);
- goto next;
}
mtr_commit(&mtr);
@@ -1307,8 +1229,6 @@ dict_load_columns(
mem_heap_t* heap) /*!< in/out: memory heap
for temporary storage */
{
- dict_table_t* sys_columns;
- dict_index_t* sys_index;
btr_pcur_t pcur;
dtuple_t* tuple;
dfield_t* dfield;
@@ -1322,13 +1242,12 @@ dict_load_columns(
mtr_start(&mtr);
- sys_columns = dict_table_get_low("SYS_COLUMNS");
- sys_index = UT_LIST_GET_FIRST(sys_columns->indexes);
- ut_ad(!dict_table_is_comp(sys_columns));
+ dict_index_t* sys_index = dict_sys.sys_columns->indexes.start;
+ ut_ad(!dict_sys.sys_columns->not_redundant());
- ut_ad(name_of_col_is(sys_columns, sys_index,
+ ut_ad(name_of_col_is(dict_sys.sys_columns, sys_index,
DICT_FLD__SYS_COLUMNS__NAME, "NAME"));
- ut_ad(name_of_col_is(sys_columns, sys_index,
+ ut_ad(name_of_col_is(dict_sys.sys_columns, sys_index,
DICT_FLD__SYS_COLUMNS__PREC, "PREC"));
tuple = dtuple_create(heap, 1);
@@ -1423,7 +1342,6 @@ dict_load_virtual_one_col(
dict_v_col_t* v_col,
mem_heap_t* heap)
{
- dict_table_t* sys_virtual;
dict_index_t* sys_virtual_index;
btr_pcur_t pcur;
dtuple_t* tuple;
@@ -1442,11 +1360,10 @@ dict_load_virtual_one_col(
mtr_start(&mtr);
- sys_virtual = dict_table_get_low("SYS_VIRTUAL");
- sys_virtual_index = UT_LIST_GET_FIRST(sys_virtual->indexes);
- ut_ad(!dict_table_is_comp(sys_virtual));
+ sys_virtual_index = dict_sys.sys_virtual->indexes.start;
+ ut_ad(!dict_sys.sys_virtual->not_redundant());
- ut_ad(name_of_col_is(sys_virtual, sys_virtual_index,
+ ut_ad(name_of_col_is(dict_sys.sys_virtual, sys_virtual_index,
DICT_FLD__SYS_VIRTUAL__POS, "POS"));
tuple = dtuple_create(heap, 2);
@@ -1656,8 +1573,6 @@ dict_load_fields(
dict_index_t* index, /*!< in/out: index whose fields to load */
mem_heap_t* heap) /*!< in: memory heap for temporary storage */
{
- dict_table_t* sys_fields;
- dict_index_t* sys_index;
btr_pcur_t pcur;
dtuple_t* tuple;
dfield_t* dfield;
@@ -1671,10 +1586,9 @@ dict_load_fields(
mtr_start(&mtr);
- sys_fields = dict_table_get_low("SYS_FIELDS");
- sys_index = UT_LIST_GET_FIRST(sys_fields->indexes);
- ut_ad(!dict_table_is_comp(sys_fields));
- ut_ad(name_of_col_is(sys_fields, sys_index,
+ dict_index_t* sys_index = dict_sys.sys_fields->indexes.start;
+ ut_ad(!dict_sys.sys_fields->not_redundant());
+ ut_ad(name_of_col_is(dict_sys.sys_fields, sys_index,
DICT_FLD__SYS_FIELDS__COL_NAME, "COL_NAME"));
tuple = dtuple_create(heap, 1);
@@ -1889,7 +1803,6 @@ dict_load_indexes(
/*!< in: error to be ignored when
loading the index definition */
{
- dict_table_t* sys_indexes;
dict_index_t* sys_index;
btr_pcur_t pcur;
dtuple_t* tuple;
@@ -1903,12 +1816,11 @@ dict_load_indexes(
mtr_start(&mtr);
- sys_indexes = dict_table_get_low("SYS_INDEXES");
- sys_index = UT_LIST_GET_FIRST(sys_indexes->indexes);
- ut_ad(!dict_table_is_comp(sys_indexes));
- ut_ad(name_of_col_is(sys_indexes, sys_index,
+ sys_index = dict_sys.sys_indexes->indexes.start;
+ ut_ad(!dict_sys.sys_indexes->not_redundant());
+ ut_ad(name_of_col_is(dict_sys.sys_indexes, sys_index,
DICT_FLD__SYS_INDEXES__NAME, "NAME"));
- ut_ad(name_of_col_is(sys_indexes, sys_index,
+ ut_ad(name_of_col_is(dict_sys.sys_indexes, sys_index,
DICT_FLD__SYS_INDEXES__PAGE_NO, "PAGE_NO"));
tuple = dtuple_create(heap, 1);
@@ -2156,11 +2068,11 @@ func_exit:
Do not load any columns or indexes.
@param[in] name Table name
@param[in] rec SYS_TABLES record
-@param[out,own] table table, or NULL
+@param[out,own] table table, or nullptr
@return error message
-@retval NULL on success */
-static const char* dict_load_table_low(const table_name_t& name,
- const rec_t* rec, dict_table_t** table)
+@retval nullptr on success */
+const char *dict_load_table_low(const span<const char> &name,
+ const rec_t *rec, dict_table_t **table)
{
table_id_t table_id;
ulint space_id;
@@ -2183,8 +2095,8 @@ static const char* dict_load_table_low(const table_name_t& name,
dict_table_decode_n_col(t_num, &n_cols, &n_v_col);
- *table = dict_mem_table_create(
- name.m_name, NULL, n_cols + n_v_col, n_v_col, flags, flags2);
+ *table = dict_table_t::create(name, nullptr, n_cols + n_v_col,
+ n_v_col, flags, flags2);
(*table)->space_id = space_id;
(*table)->id = table_id;
(*table)->file_unreadable = !!(flags2 & DICT_TF2_DISCARDED);
@@ -2271,44 +2183,6 @@ dict_get_and_save_data_dir_path(
}
}
-/** Loads a table definition and also all its index definitions, and also
-the cluster definition if the table is a member in a cluster. Also loads
-all foreign key constraints where the foreign key is in the table or where
-a foreign key references columns in this table.
-@param[in] name Table name in the dbname/tablename format
-@param[in] ignore_err Error to be ignored when loading
- table and its index definition
-@return table, NULL if does not exist; if the table is stored in an
-.ibd file, but the file does not exist, then we set the file_unreadable
-flag in the table object we return. */
-dict_table_t* dict_load_table(const char* name, dict_err_ignore_t ignore_err)
-{
- dict_names_t fk_list;
- dict_table_t* result;
- dict_names_t::iterator i;
-
- DBUG_ENTER("dict_load_table");
- DBUG_PRINT("dict_load_table", ("loading table: '%s'", name));
-
- dict_sys.assert_locked();
-
- result = dict_table_check_if_in_cache_low(name);
-
- if (!result) {
- result = dict_load_table_one(const_cast<char*>(name),
- ignore_err, fk_list);
- while (!fk_list.empty()) {
- if (!dict_table_check_if_in_cache_low(fk_list.front()))
- dict_load_table_one(
- const_cast<char*>(fk_list.front()),
- ignore_err, fk_list);
- fk_list.pop_front();
- }
- }
-
- DBUG_RETURN(result);
-}
-
/** Opens a tablespace for dict_load_table_one()
@param[in,out] table A table that refers to the tablespace to open
@param[in] ignore_err Whether to ignore an error. */
@@ -2368,12 +2242,10 @@ dict_load_tablespace(
}
}
- /* Try to open the tablespace. We set the 2nd param (fix_dict) to
- false because we do not have an x-lock on dict_sys.latch */
table->space = fil_ibd_open(
true, FIL_TYPE_TABLESPACE, table->space_id,
dict_tf_to_fsp_flags(table->flags),
- table->name, filepath);
+ {table->name.m_name, strlen(table->name.m_name)}, filepath);
if (!table->space) {
/* We failed to find a sensible tablespace file */
@@ -2397,20 +2269,14 @@ key constraints are loaded into memory.
@param[out] fk_tables Related table names that must also be
loaded to ensure that all foreign key
constraints are loaded.
-@return table, NULL if does not exist; if the table is stored in an
-.ibd file, but the file does not exist, then we set the
-file_unreadable flag in the table object we return */
-static
-dict_table_t*
-dict_load_table_one(
- const table_name_t& name,
- dict_err_ignore_t ignore_err,
- dict_names_t& fk_tables)
+@return table, possibly with file_unreadable flag set
+@retval nullptr if the table does not exist */
+static dict_table_t *dict_load_table_one(const span<const char> &name,
+ dict_err_ignore_t ignore_err,
+ dict_names_t &fk_tables)
{
dberr_t err;
- dict_table_t* sys_tables;
btr_pcur_t pcur;
- dict_index_t* sys_index;
dtuple_t* tuple;
mem_heap_t* heap;
dfield_t* dfield;
@@ -2420,7 +2286,8 @@ dict_load_table_one(
mtr_t mtr;
DBUG_ENTER("dict_load_table_one");
- DBUG_PRINT("dict_load_table_one", ("table: %s", name.m_name));
+ DBUG_PRINT("dict_load_table_one",
+ ("table: %.*s", name.size(), name.data()));
dict_sys.assert_locked();
@@ -2428,24 +2295,23 @@ dict_load_table_one(
mtr_start(&mtr);
- sys_tables = dict_table_get_low("SYS_TABLES");
- sys_index = UT_LIST_GET_FIRST(sys_tables->indexes);
- ut_ad(!dict_table_is_comp(sys_tables));
- ut_ad(name_of_col_is(sys_tables, sys_index,
+ dict_index_t *sys_index = dict_sys.sys_tables->indexes.start;
+ ut_ad(!dict_sys.sys_tables->not_redundant());
+ ut_ad(name_of_col_is(dict_sys.sys_tables, sys_index,
DICT_FLD__SYS_TABLES__ID, "ID"));
- ut_ad(name_of_col_is(sys_tables, sys_index,
+ ut_ad(name_of_col_is(dict_sys.sys_tables, sys_index,
DICT_FLD__SYS_TABLES__N_COLS, "N_COLS"));
- ut_ad(name_of_col_is(sys_tables, sys_index,
+ ut_ad(name_of_col_is(dict_sys.sys_tables, sys_index,
DICT_FLD__SYS_TABLES__TYPE, "TYPE"));
- ut_ad(name_of_col_is(sys_tables, sys_index,
+ ut_ad(name_of_col_is(dict_sys.sys_tables, sys_index,
DICT_FLD__SYS_TABLES__MIX_LEN, "MIX_LEN"));
- ut_ad(name_of_col_is(sys_tables, sys_index,
+ ut_ad(name_of_col_is(dict_sys.sys_tables, sys_index,
DICT_FLD__SYS_TABLES__SPACE, "SPACE"));
tuple = dtuple_create(heap, 1);
dfield = dtuple_get_nth_field(tuple, 0);
- dfield_set_data(dfield, name.m_name, strlen(name.m_name));
+ dfield_set_data(dfield, name.data(), name.size());
dict_index_copy_types(tuple, sys_index, 1);
btr_pcur_open_on_user_rec(sys_index, tuple, PAGE_CUR_GE,
@@ -2467,9 +2333,7 @@ err_exit:
rec, DICT_FLD__SYS_TABLES__NAME, &len);
/* Check if the table name in record is the searched one */
- if (len != strlen(name.m_name)
- || memcmp(name.m_name, field, len)) {
-
+ if (len != name.size() || memcmp(name.data(), field, len)) {
goto err_exit;
}
@@ -2645,6 +2509,25 @@ func_exit:
DBUG_RETURN(table);
}
+dict_table_t *dict_sys_t::load_table(const span<const char> &name,
+ dict_err_ignore_t ignore)
+{
+ if (dict_table_t *table= find_table(name))
+ return table;
+ dict_names_t fk_list;
+ dict_table_t *table= dict_load_table_one(name, ignore, fk_list);
+ while (!fk_list.empty())
+ {
+ const char *f= fk_list.front();
+ const span<const char> name{f, strlen(f)};
+ if (!find_table(name))
+ dict_load_table_one(name, ignore, fk_list);
+ fk_list.pop_front();
+ }
+
+ return table;
+}
+
/***********************************************************************//**
Loads a table object based on the table id.
@return table; NULL if table does not exist */
@@ -2657,48 +2540,41 @@ dict_load_table_on_id(
{
byte id_buf[8];
btr_pcur_t pcur;
- mem_heap_t* heap;
- dtuple_t* tuple;
- dfield_t* dfield;
- dict_index_t* sys_table_ids;
- dict_table_t* sys_tables;
- const rec_t* rec;
const byte* field;
ulint len;
- dict_table_t* table;
mtr_t mtr;
dict_sys.assert_locked();
- table = NULL;
-
/* NOTE that the operation of this function is protected by
the dictionary mutex, and therefore no deadlocks can occur
with other dictionary operations. */
- mtr_start(&mtr);
+ mtr.start();
/*---------------------------------------------------*/
/* Get the secondary index based on ID for table SYS_TABLES */
- sys_tables = dict_sys.sys_tables;
- sys_table_ids = dict_table_get_next_index(
- dict_table_get_first_index(sys_tables));
- ut_ad(!dict_table_is_comp(sys_tables));
- ut_ad(!dict_index_is_clust(sys_table_ids));
- heap = mem_heap_create(256);
-
- tuple = dtuple_create(heap, 1);
- dfield = dtuple_get_nth_field(tuple, 0);
+ dict_index_t *sys_table_ids =
+ dict_sys.sys_tables->indexes.start->indexes.next;
+
+ dfield_t dfield;
+ dtuple_t tuple{
+ 0,1,1,&dfield,0,nullptr
+#ifdef UNIV_DEBUG
+ , DATA_TUPLE_MAGIC_N
+#endif
+ };
/* Write the table id in byte format to id_buf */
mach_write_to_8(id_buf, table_id);
+ dfield_set_data(&dfield, id_buf, 8);
+ dict_index_copy_types(&tuple, sys_table_ids, 1);
- dfield_set_data(dfield, id_buf, 8);
- dict_index_copy_types(tuple, sys_table_ids, 1);
-
- btr_pcur_open_on_user_rec(sys_table_ids, tuple, PAGE_CUR_GE,
+ btr_pcur_open_on_user_rec(sys_table_ids, &tuple, PAGE_CUR_GE,
BTR_SEARCH_LEAF, &pcur, &mtr);
- rec = btr_pcur_get_rec(&pcur);
+
+ const rec_t* rec = btr_pcur_get_rec(&pcur);
+ dict_table_t* table = nullptr;
if (page_rec_is_user_rec(rec)) {
/*---------------------------------------------------*/
@@ -2727,17 +2603,15 @@ check_rec:
/* Now we get the table name from the record */
field = rec_get_nth_field_old(rec,
DICT_FLD__SYS_TABLE_IDS__NAME, &len);
- /* Load the table definition to memory */
- char* table_name = mem_heap_strdupl(
- heap, (char*) field, len);
- table = dict_load_table(table_name, ignore_err);
+ table = dict_sys.load_table(
+ {reinterpret_cast<const char*>(field),
+ len}, ignore_err);
}
}
}
btr_pcur_close(&pcur);
- mtr_commit(&mtr);
- mem_heap_free(heap);
+ mtr.commit();
return(table);
}
@@ -2778,8 +2652,6 @@ dict_load_foreign_cols(
/*===================*/
dict_foreign_t* foreign)/*!< in/out: foreign constraint object */
{
- dict_table_t* sys_foreign_cols;
- dict_index_t* sys_index;
btr_pcur_t pcur;
dtuple_t* tuple;
dfield_t* dfield;
@@ -2804,10 +2676,8 @@ dict_load_foreign_cols(
mtr_start(&mtr);
- sys_foreign_cols = dict_table_get_low("SYS_FOREIGN_COLS");
-
- sys_index = UT_LIST_GET_FIRST(sys_foreign_cols->indexes);
- ut_ad(!dict_table_is_comp(sys_foreign_cols));
+ dict_index_t* sys_index = dict_sys.sys_foreign_cols->indexes.start;
+ ut_ad(!dict_sys.sys_foreign_cols->not_redundant());
tuple = dtuple_create(foreign->heap, 1);
dfield = dtuple_get_nth_field(tuple, 0);
@@ -2918,9 +2788,7 @@ dict_load_foreign(
stack. */
{
dict_foreign_t* foreign;
- dict_table_t* sys_foreign;
btr_pcur_t pcur;
- dict_index_t* sys_index;
dtuple_t* tuple;
mem_heap_t* heap2;
dfield_t* dfield;
@@ -2944,10 +2812,8 @@ dict_load_foreign(
mtr_start(&mtr);
- sys_foreign = dict_table_get_low("SYS_FOREIGN");
-
- sys_index = UT_LIST_GET_FIRST(sys_foreign->indexes);
- ut_ad(!dict_table_is_comp(sys_foreign));
+ dict_index_t* sys_index = dict_sys.sys_foreign->indexes.start;
+ ut_ad(!dict_sys.sys_foreign->not_redundant());
tuple = dtuple_create(heap2, 1);
dfield = dtuple_get_nth_field(tuple, 0);
@@ -2965,7 +2831,7 @@ dict_load_foreign(
ib::error() << "Cannot load foreign constraint " << id
<< ": could not find the relevant record in "
- << "SYS_FOREIGN";
+ "SYS_FOREIGN";
btr_pcur_close(&pcur);
mtr_commit(&mtr);
@@ -3033,10 +2899,12 @@ dict_load_foreign(
dict_load_foreign_cols(foreign);
- ref_table = dict_table_check_if_in_cache_low(
- foreign->referenced_table_name_lookup);
- for_table = dict_table_check_if_in_cache_low(
- foreign->foreign_table_name_lookup);
+ ref_table = dict_sys.find_table(
+ {foreign->referenced_table_name_lookup,
+ strlen(foreign->referenced_table_name_lookup)});
+ for_table = dict_sys.find_table(
+ {foreign->foreign_table_name_lookup,
+ strlen(foreign->foreign_table_name_lookup)});
if (!for_table) {
/* To avoid recursively loading the tables related through
@@ -3101,8 +2969,6 @@ dict_load_foreigns(
btr_pcur_t pcur;
dtuple_t* tuple;
dfield_t* dfield;
- dict_index_t* sec_index;
- dict_table_t* sys_foreign;
const rec_t* rec;
const byte* field;
ulint len;
@@ -3113,24 +2979,21 @@ dict_load_foreigns(
dict_sys.assert_locked();
- sys_foreign = dict_table_get_low("SYS_FOREIGN");
-
- if (sys_foreign == NULL) {
- /* No foreign keys defined yet in this database */
-
- ib::info() << "No foreign key system tables in the database";
+ if (!dict_sys.sys_foreign || !dict_sys.sys_foreign_cols) {
+ if (ignore_err & DICT_ERR_IGNORE_FK_NOKEY) {
+ DBUG_RETURN(DB_SUCCESS);
+ }
+ sql_print_information("InnoDB: No foreign key system tables"
+ " in the database");
DBUG_RETURN(DB_ERROR);
}
- ut_ad(!dict_table_is_comp(sys_foreign));
+ ut_ad(!dict_sys.sys_foreign->not_redundant());
mtr_start(&mtr);
- /* Get the secondary index based on FOR_NAME from table
- SYS_FOREIGN */
-
- sec_index = dict_table_get_next_index(
- dict_table_get_first_index(sys_foreign));
- ut_ad(!dict_index_is_clust(sec_index));
+ dict_index_t *sec_index = dict_table_get_next_index(
+ dict_table_get_first_index(dict_sys.sys_foreign));
+ ut_ad(!strcmp(sec_index->fields[0].name, "FOR_NAME"));
start_load:
tuple = dtuple_create_from_mem(tuple_buf, sizeof(tuple_buf), 1, 0);
diff --git a/storage/innobase/dict/dict0mem.cc b/storage/innobase/dict/dict0mem.cc
index ef7bb87e635..0631bd24bc0 100644
--- a/storage/innobase/dict/dict0mem.cc
+++ b/storage/innobase/dict/dict0mem.cc
@@ -123,85 +123,73 @@ bool dict_col_t::same_encoding(uint16_t a, uint16_t b)
return false;
}
-/** Create a table memory object.
+/** Create metadata.
@param name table name
@param space tablespace
@param n_cols total number of columns (both virtual and non-virtual)
@param n_v_cols number of virtual columns
@param flags table flags
@param flags2 table flags2
-@return own: table object */
-dict_table_t *dict_mem_table_create(const char *name, fil_space_t *space,
- ulint n_cols, ulint n_v_cols, ulint flags,
- ulint flags2)
+@return newly allocated table object */
+dict_table_t *dict_table_t::create(const span<const char> &name,
+ fil_space_t *space,
+ ulint n_cols, ulint n_v_cols, ulint flags,
+ ulint flags2)
{
- dict_table_t* table;
- mem_heap_t* heap;
-
- ut_ad(name);
- ut_ad(!space
- || space->purpose == FIL_TYPE_TABLESPACE
- || space->purpose == FIL_TYPE_TEMPORARY
- || space->purpose == FIL_TYPE_IMPORT);
- ut_a(dict_tf2_is_valid(flags, flags2));
- ut_a(!(flags2 & DICT_TF2_UNUSED_BIT_MASK));
+ ut_ad(!space || space->purpose == FIL_TYPE_TABLESPACE ||
+ space->purpose == FIL_TYPE_TEMPORARY ||
+ space->purpose == FIL_TYPE_IMPORT);
+ ut_a(dict_tf2_is_valid(flags, flags2));
+ ut_a(!(flags2 & DICT_TF2_UNUSED_BIT_MASK));
- heap = mem_heap_create(DICT_HEAP_SIZE);
+ mem_heap_t *heap= mem_heap_create(DICT_HEAP_SIZE);
- table = static_cast<dict_table_t*>(
- mem_heap_zalloc(heap, sizeof(*table)));
+ dict_table_t *table= static_cast<dict_table_t*>
+ (mem_heap_zalloc(heap, sizeof(*table)));
- lock_table_lock_list_init(&table->locks);
-
- UT_LIST_INIT(table->indexes, &dict_index_t::indexes);
+ lock_table_lock_list_init(&table->locks);
+ UT_LIST_INIT(table->indexes, &dict_index_t::indexes);
#ifdef BTR_CUR_HASH_ADAPT
- UT_LIST_INIT(table->freed_indexes, &dict_index_t::indexes);
+ UT_LIST_INIT(table->freed_indexes, &dict_index_t::indexes);
#endif /* BTR_CUR_HASH_ADAPT */
+ table->heap= heap;
+
+ ut_d(table->magic_n= DICT_TABLE_MAGIC_N);
+
+ table->flags= static_cast<unsigned>(flags) & ((1U << DICT_TF_BITS) - 1);
+ table->flags2= static_cast<unsigned>(flags2) & ((1U << DICT_TF2_BITS) - 1);
+ table->name.m_name= mem_strdupl(name.data(), name.size());
+ table->is_system_db= dict_mem_table_is_system(table->name.m_name);
+ table->space= space;
+ table->space_id= space ? space->id : ULINT_UNDEFINED;
+ table->n_t_cols= static_cast<unsigned>(n_cols + DATA_N_SYS_COLS) &
+ dict_index_t::MAX_N_FIELDS;
+ table->n_v_cols= static_cast<unsigned>(n_v_cols) &
+ dict_index_t::MAX_N_FIELDS;
+ table->n_cols= static_cast<unsigned>(table->n_t_cols - table->n_v_cols) &
+ dict_index_t::MAX_N_FIELDS;
+ table->cols= static_cast<dict_col_t*>
+ (mem_heap_alloc(heap, table->n_cols * sizeof *table->cols));
+ table->v_cols= static_cast<dict_v_col_t*>
+ (mem_heap_alloc(heap, n_v_cols * sizeof *table->v_cols));
+ for (ulint i = n_v_cols; i--; )
+ new (&table->v_cols[i]) dict_v_col_t();
+ table->autoinc_lock= static_cast<ib_lock_t*>
+ (mem_heap_alloc(heap, sizeof *table->autoinc_lock));
+ /* If the table has an FTS index or we are in the process
+ of building one, create the table->fts */
+ if (dict_table_has_fts_index(table) ||
+ DICT_TF2_FLAG_IS_SET(table, DICT_TF2_FTS_HAS_DOC_ID |
+ DICT_TF2_FTS_ADD_DOC_ID))
+ {
+ table->fts= fts_create(table);
+ table->fts->cache= fts_cache_create(table);
+ }
- table->heap = heap;
-
- ut_d(table->magic_n = DICT_TABLE_MAGIC_N);
-
- table->flags = static_cast<unsigned>(flags)
- & ((1U << DICT_TF_BITS) - 1);
- table->flags2 = static_cast<unsigned>(flags2)
- & ((1U << DICT_TF2_BITS) - 1);
- table->name.m_name = mem_strdup(name);
- table->is_system_db = dict_mem_table_is_system(table->name.m_name);
- table->space = space;
- table->space_id = space ? space->id : ULINT_UNDEFINED;
- table->n_t_cols = static_cast<unsigned>(n_cols + DATA_N_SYS_COLS)
- & dict_index_t::MAX_N_FIELDS;
- table->n_v_cols = static_cast<unsigned>(n_v_cols)
- & dict_index_t::MAX_N_FIELDS;
- table->n_cols = static_cast<unsigned>(
- table->n_t_cols - table->n_v_cols)
- & dict_index_t::MAX_N_FIELDS;
-
- table->cols = static_cast<dict_col_t*>(
- mem_heap_alloc(heap, table->n_cols * sizeof(dict_col_t)));
- table->v_cols = static_cast<dict_v_col_t*>(
- mem_heap_alloc(heap, n_v_cols * sizeof(*table->v_cols)));
- for (ulint i = n_v_cols; i--; ) {
- new (&table->v_cols[i]) dict_v_col_t();
- }
-
- table->autoinc_lock = static_cast<ib_lock_t*>(
- mem_heap_alloc(heap, sizeof *table->autoinc_lock));
-
- /* If the table has an FTS index or we are in the process
- of building one, create the table->fts */
- if (dict_table_has_fts_index(table)
- || DICT_TF2_FLAG_IS_SET(table, DICT_TF2_FTS_HAS_DOC_ID)
- || DICT_TF2_FLAG_IS_SET(table, DICT_TF2_FTS_ADD_DOC_ID)) {
- table->fts = fts_create(table);
- table->fts->cache = fts_cache_create(table);
- }
-
- new(&table->foreign_set) dict_foreign_set();
- new(&table->referenced_set) dict_foreign_set();
+ new (&table->foreign_set) dict_foreign_set();
+ new (&table->referenced_set) dict_foreign_set();
- return(table);
+ return table;
}
/****************************************************************//**
diff --git a/storage/innobase/dict/dict0stats.cc b/storage/innobase/dict/dict0stats.cc
index e3a1b874d7d..e9e91f730d5 100644
--- a/storage/innobase/dict/dict0stats.cc
+++ b/storage/innobase/dict/dict0stats.cc
@@ -25,7 +25,6 @@ Created Jan 06, 2010 Vasil Dimov
*******************************************************/
#include "dict0stats.h"
-#include "dict0priv.h"
#include "ut0ut.h"
#include "ut0rnd.h"
#include "dyn0buf.h"
@@ -143,6 +142,20 @@ typedef ut_allocator<std::pair<const char* const, dict_index_t*> >
typedef std::map<const char*, dict_index_t*, ut_strcmp_functor,
index_map_t_allocator> index_map_t;
+inline bool dict_table_t::is_stats_table() const
+{
+ return !strcmp(name.m_name, TABLE_STATS_NAME) ||
+ !strcmp(name.m_name, INDEX_STATS_NAME);
+}
+
+bool trx_t::has_stats_table_lock() const
+{
+ for (const lock_t *l : lock.table_locks)
+ if (l && l->un_member.tab_lock.table->is_stats_table())
+ return true;
+ return false;
+}
+
/*********************************************************************//**
Checks whether an index should be ignored in stats manipulations:
* stats fetch
@@ -179,7 +192,7 @@ struct dict_col_meta_t
struct dict_table_schema_t
{
/** table name */
- const char *table_name;
+ span<const char> table_name;
/** table name in SQL */
const char *table_name_sql;
/** number of columns */
@@ -190,7 +203,7 @@ struct dict_table_schema_t
static const dict_table_schema_t table_stats_schema =
{
- TABLE_STATS_NAME, TABLE_STATS_NAME_PRINT, 6,
+ {C_STRING_WITH_LEN(TABLE_STATS_NAME)}, TABLE_STATS_NAME_PRINT, 6,
{
{"database_name", DATA_VARMYSQL, DATA_NOT_NULL, 192},
{"table_name", DATA_VARMYSQL, DATA_NOT_NULL, 597},
@@ -203,7 +216,7 @@ static const dict_table_schema_t table_stats_schema =
static const dict_table_schema_t index_stats_schema =
{
- INDEX_STATS_NAME, INDEX_STATS_NAME_PRINT, 8,
+ {C_STRING_WITH_LEN(INDEX_STATS_NAME)}, INDEX_STATS_NAME_PRINT, 8,
{
{"database_name", DATA_VARMYSQL, DATA_NOT_NULL, 192},
{"table_name", DATA_VARMYSQL, DATA_NOT_NULL, 597},
@@ -327,7 +340,7 @@ dict_table_schema_check(
returned */
size_t errstr_sz) /*!< in: errstr size */
{
- const dict_table_t* table = dict_table_get_low(req_schema->table_name);
+ const dict_table_t* table= dict_sys.load_table(req_schema->table_name);
if (!table) {
if (req_schema == &table_stats_schema) {
diff --git a/storage/innobase/fil/fil0fil.cc b/storage/innobase/fil/fil0fil.cc
index 9615ff2d096..3ffec8efe4b 100644
--- a/storage/innobase/fil/fil0fil.cc
+++ b/storage/innobase/fil/fil0fil.cc
@@ -47,6 +47,7 @@ Created 10/25/1995 Heikki Tuuri
#include "buf0lru.h"
#include "ibuf0ibuf.h"
#include "buf0flu.h"
+#include "log.h"
#ifdef UNIV_LINUX
# include <sys/types.h>
# include <sys/sysmacros.h>
@@ -2195,7 +2196,7 @@ statement to update the dictionary tables if they are incorrect.
@param[in] purpose FIL_TYPE_TABLESPACE or FIL_TYPE_TEMPORARY
@param[in] id tablespace ID
@param[in] flags expected FSP_SPACE_FLAGS
-@param[in] space_name tablespace name of the datafile
+@param[in] name table name
If file-per-table, it is the table name in the databasename/tablename format
@param[in] path_in expected filepath, usually read from dictionary
@param[out] err DB_SUCCESS or error code
@@ -2207,37 +2208,40 @@ fil_ibd_open(
fil_type_t purpose,
ulint id,
ulint flags,
- const table_name_t tablename,
+ fil_space_t::name_type name,
const char* path_in,
dberr_t* err)
{
mysql_mutex_lock(&fil_system.mutex);
- if (fil_space_t* space = fil_space_get_by_id(id)) {
- mysql_mutex_unlock(&fil_system.mutex);
-
- if (space && validate && !srv_read_only_mode) {
+ fil_space_t* space = fil_space_get_by_id(id);
+ mysql_mutex_unlock(&fil_system.mutex);
+ if (space) {
+ if (validate && !srv_read_only_mode) {
fsp_flags_try_adjust(space,
flags & ~FSP_FLAGS_MEM_MASK);
}
-
return space;
}
- mysql_mutex_unlock(&fil_system.mutex);
- Datafile df_default; /* default location */
- RemoteDatafile df_remote; /* remote location */
- ulint tablespaces_found = 0;
- ulint valid_tablespaces_found = 0;
+ dberr_t local_err = DB_SUCCESS;
/* Table flags can be ULINT_UNDEFINED if
dict_tf_to_fsp_flags_failure is set. */
if (flags == ULINT_UNDEFINED) {
corrupted:
- if (err) *err = DB_CORRUPTION;
- return NULL;
+ local_err = DB_CORRUPTION;
+func_exit:
+ if (err) *err = local_err;
+ return space;
}
ut_ad(fil_space_t::is_valid_flags(flags & ~FSP_FLAGS_MEM_MASK, id));
+
+ Datafile df_default; /* default location */
+ RemoteDatafile df_remote; /* remote location */
+ ulint tablespaces_found = 0;
+ ulint valid_tablespaces_found = 0;
+
df_default.init(flags);
df_remote.init(flags);
@@ -2245,12 +2249,11 @@ corrupted:
while avoiding unecessary effort. */
/* We will always look for an ibd in the default location. */
- df_default.make_filepath(nullptr, {tablename.m_name,
- strlen(tablename.m_name)}, IBD);
+ df_default.make_filepath(nullptr, name, IBD);
/* Look for a filepath embedded in an ISL where the default file
would be. */
- if (df_remote.open_link_file(tablename)) {
+ if (df_remote.open_link_file(name)) {
validate = true;
if (df_remote.open_read_only(true) == DB_SUCCESS) {
ut_ad(df_remote.is_open());
@@ -2314,8 +2317,10 @@ corrupted:
First, bail out if no tablespace files were found. */
if (valid_tablespaces_found == 0) {
os_file_get_last_error(true);
- ib::error() << "Could not find a valid tablespace file for `"
- << tablename << "`. " << TROUBLESHOOT_DATADICT_MSG;
+ sql_print_error("InnoDB: Could not find a valid tablespace"
+ " file for %.*s. %s",
+ static_cast<int>(name.size()), name.data(),
+ TROUBLESHOOT_DATADICT_MSG);
goto corrupted;
}
if (!validate) {
@@ -2324,22 +2329,19 @@ corrupted:
/* Do not open any tablespaces if more than one tablespace with
the correct space ID and flags were found. */
- if (tablespaces_found > 1) {
- ib::error() << "A tablespace for `" << tablename
- << "` has been found in multiple places;";
-
- if (df_default.is_open()) {
- ib::error() << "Default location: "
- << df_default.filepath()
- << ", Space ID=" << df_default.space_id()
- << ", Flags=" << df_default.flags();
- }
- if (df_remote.is_open()) {
- ib::error() << "Remote location: "
- << df_remote.filepath()
- << ", Space ID=" << df_remote.space_id()
- << ", Flags=" << df_remote.flags();
- }
+ if (df_default.is_open() && df_remote.is_open()) {
+ ib::error()
+ << "A tablespace has been found in multiple places: "
+ << df_default.filepath()
+ << "(Space ID=" << df_default.space_id()
+ << ", Flags=" << df_default.flags()
+ << ") and "
+ << df_remote.filepath()
+ << "(Space ID=" << df_remote.space_id()
+ << ", Flags=" << df_remote.flags()
+ << (valid_tablespaces_found > 1 || srv_force_recovery
+ ? "); will not open"
+ : ")");
/* Force-recovery will allow some tablespaces to be
skipped by REDO if there was more than one file found.
@@ -2349,9 +2351,6 @@ corrupted:
recovery and there is only one good tablespace, ignore
any bad tablespaces. */
if (valid_tablespaces_found > 1 || srv_force_recovery > 0) {
- ib::error() << "Will not open tablespace `"
- << tablename << "`";
-
/* If the file is not open it cannot be valid. */
ut_ad(df_default.is_open() || !df_default.is_valid());
ut_ad(df_remote.is_open() || !df_remote.is_valid());
@@ -2363,8 +2362,8 @@ corrupted:
goto corrupted;
}
error:
- if (err) *err = DB_ERROR;
- return NULL;
+ local_err = DB_ERROR;
+ goto func_exit;
}
/* There is only one valid tablespace found and we did
@@ -2395,8 +2394,7 @@ skip_validate:
first_page)
: NULL;
- fil_space_t* space = fil_space_t::create(
- id, flags, purpose, crypt_data);
+ space = fil_space_t::create(id, flags, purpose, crypt_data);
if (!space) {
goto error;
}
@@ -2420,8 +2418,7 @@ skip_validate:
}
}
- if (err) *err = DB_SUCCESS;
- return space;
+ goto func_exit;
}
/** Discover the correct IBD file to open given a remote or missing
@@ -2485,14 +2482,11 @@ fil_ibd_discover(
case SRV_OPERATION_RESTORE:
break;
case SRV_OPERATION_NORMAL:
- char* name = const_cast<char*>(db);
- size_t len= strlen(name);
- if (len <= 4 || strcmp(name + len - 4, dot_ext[IBD])) {
+ size_t len= strlen(db);
+ if (len <= 4 || strcmp(db + len - 4, dot_ext[IBD])) {
break;
}
- name[len - 4] = '\0';
- df_rem_per.open_link_file(table_name_t{name});
- name[len - 4] = *dot_ext[IBD];
+ df_rem_per.open_link_file({db, len - 4});
if (!df_rem_per.filepath()) {
break;
diff --git a/storage/innobase/fsp/fsp0file.cc b/storage/innobase/fsp/fsp0file.cc
index 5d49d14f65c..966febd056c 100644
--- a/storage/innobase/fsp/fsp0file.cc
+++ b/storage/innobase/fsp/fsp0file.cc
@@ -837,7 +837,7 @@ open that file, and read the contents into m_filepath.
@param name table name
@return filepath()
@retval nullptr if the .isl file does not exist or cannot be read */
-const char *RemoteDatafile::open_link_file(const table_name_t &name)
+const char *RemoteDatafile::open_link_file(const fil_space_t::name_type name)
{
if (!m_link_filepath)
m_link_filepath= fil_make_filepath(nullptr, name, ISL, false);
diff --git a/storage/innobase/fts/fts0fts.cc b/storage/innobase/fts/fts0fts.cc
index ac324525772..515abf94060 100644
--- a/storage/innobase/fts/fts0fts.cc
+++ b/storage/innobase/fts/fts0fts.cc
@@ -34,7 +34,6 @@ Full Text Search interface
#include "fts0types.ic"
#include "fts0vlc.ic"
#include "fts0plugin.h"
-#include "dict0priv.h"
#include "dict0stats.h"
#include "btr0pcur.h"
@@ -1675,8 +1674,9 @@ fts_create_in_mem_aux_table(
const dict_table_t* table,
ulint n_cols)
{
- dict_table_t* new_table = dict_mem_table_create(
- aux_table_name, NULL, n_cols, 0, table->flags,
+ dict_table_t* new_table = dict_table_t::create(
+ {aux_table_name,strlen(aux_table_name)},
+ nullptr, n_cols, 0, table->flags,
table->space_id == TRX_SYS_SPACE
? 0 : table->space_id == SRV_TMP_SPACE_ID
? DICT_TF2_TEMPORARY : DICT_TF2_USE_FILE_PER_TABLE);
@@ -5645,7 +5645,8 @@ fts_valid_stopword_table(
return(NULL);
}
- table = dict_table_get_low(stopword_table_name);
+ table = dict_sys.load_table(
+ {stopword_table_name, strlen(stopword_table_name)});
if (!table) {
ib::error() << "User stopword table " << stopword_table_name
diff --git a/storage/innobase/fts/fts0opt.cc b/storage/innobase/fts/fts0opt.cc
index b815d23394f..7a83930fb1a 100644
--- a/storage/innobase/fts/fts0opt.cc
+++ b/storage/innobase/fts/fts0opt.cc
@@ -2554,7 +2554,7 @@ void fts_optimize_add_table(dict_table_t* table)
}
/* Make sure table with FTS index cannot be evicted */
- dict_table_prevent_eviction(table);
+ dict_sys.prevent_eviction(table);
msg = fts_optimize_create_msg(FTS_MSG_ADD_TABLE, table);
diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc
index d57c0bd4a24..2b6089c4814 100644
--- a/storage/innobase/handler/ha_innodb.cc
+++ b/storage/innobase/handler/ha_innodb.cc
@@ -80,7 +80,6 @@ this program; if not, write to the Free Software Foundation, Inc.,
#include "btr0defragment.h"
#include "dict0crea.h"
#include "dict0dict.h"
-#include "dict0priv.h"
#include "dict0stats.h"
#include "dict0stats_bg.h"
#include "fil0fil.h"
@@ -148,7 +147,6 @@ void close_thread_tables(THD* thd);
#include <sstream>
#ifdef WITH_WSREP
-#include "dict0priv.h"
#include <mysql/service_md5.h>
#include "wsrep_sst.h"
#endif /* WITH_WSREP */
@@ -1277,7 +1275,7 @@ static ibool innodb_drop_database_ignore_fk(void*,void*) { return false; }
struct innodb_drop_database_fk_report
{
/** database name, with trailing '/' */
- const st_::span<char> name;
+ const span<const char> name;
/** whether errors were found */
bool violated;
};
@@ -9798,8 +9796,11 @@ wsrep_append_foreign_key(
if (referenced) {
foreign->referenced_table =
- dict_table_get_low(
- foreign->referenced_table_name_lookup);
+ dict_sys.load_table(
+ {foreign->referenced_table_name_lookup,
+ strlen(foreign->
+ referenced_table_name_lookup)
+ });
if (foreign->referenced_table) {
foreign->referenced_index =
dict_foreign_find_index(
@@ -9811,8 +9812,10 @@ wsrep_append_foreign_key(
}
} else {
foreign->foreign_table =
- dict_table_get_low(
- foreign->foreign_table_name_lookup);
+ dict_sys.load_table(
+ {foreign->foreign_table_name_lookup,
+ strlen(foreign->
+ foreign_table_name_lookup)});
if (foreign->foreign_table) {
foreign->foreign_index =
@@ -10478,8 +10481,8 @@ create_table_info_t::create_table_def()
const ulint actual_n_cols = n_cols
+ (m_flags2 & DICT_TF2_FTS && !has_doc_id_col);
- table = dict_mem_table_create(m_table_name, NULL,
- actual_n_cols, num_v, m_flags, m_flags2);
+ table = dict_table_t::create({m_table_name,table_name_len}, nullptr,
+ actual_n_cols, num_v, m_flags, m_flags2);
/* Set the hidden doc_id column. */
if (m_flags2 & DICT_TF2_FTS) {
@@ -10696,7 +10699,7 @@ err_col:
"temporary table creation.");
}
- table->id = dict_sys.get_temporary_table_id();
+ table->id = dict_sys.acquire_temporary_table_id();
ut_ad(dict_tf_get_rec_format(table->flags)
!= REC_FORMAT_COMPRESSED);
table->space_id = SRV_TMP_SPACE_ID;
@@ -12140,7 +12143,7 @@ create_table_info_t::create_foreign_keys()
ut_ad(alter_info);
List_iterator_fast<Key> key_it(alter_info->key_list);
- dict_table_t* table = dict_table_get_low(name);
+ dict_table_t* table = dict_sys.find_table({name,strlen(name)});
if (!table) {
ib_foreign_warn(m_trx, DB_CANNOT_ADD_CONSTRAINT, create_name,
"%s table %s foreign key constraint"
@@ -12630,13 +12633,12 @@ int create_table_info_t::create_table(bool create_fk)
if (err == DB_SUCCESS) {
/* Check that also referencing constraints are ok */
dict_names_t fk_tables;
- err = dict_load_foreigns(m_table_name, NULL,
- false, true,
- DICT_ERR_IGNORE_NONE,
- fk_tables);
+ err = dict_load_foreigns(m_table_name, NULL, false, true,
+ DICT_ERR_IGNORE_NONE, fk_tables);
while (err == DB_SUCCESS && !fk_tables.empty()) {
- dict_load_table(fk_tables.front(),
- DICT_ERR_IGNORE_NONE);
+ dict_sys.load_table(
+ {fk_tables.front(), strlen(fk_tables.front())},
+ DICT_ERR_IGNORE_NONE);
fk_tables.pop_front();
}
}
diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc
index 8583a084c94..6277283b3e0 100644
--- a/storage/innobase/handler/handler0alter.cc
+++ b/storage/innobase/handler/handler0alter.cc
@@ -35,7 +35,7 @@ Smart ALTER TABLE
#include "btr0sea.h"
#include "dict0crea.h"
#include "dict0dict.h"
-#include "dict0priv.h"
+#include "dict0load.h"
#include "dict0stats.h"
#include "dict0stats_bg.h"
#include "log0log.h"
@@ -56,11 +56,9 @@ Smart ALTER TABLE
#include "row0sel.h"
#include "ha_innodb.h"
#include "ut0stage.h"
-#include "span.h"
#include <thread>
#include <sstream>
-using st_::span;
/** File format constraint for ALTER TABLE */
extern ulong innodb_instant_alter_column_allowed;
@@ -2054,6 +2052,12 @@ ha_innobase::check_if_supported_inplace_alter(
DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED);
}
+ if (!dict_sys.sys_tables_exist()) {
+ ha_alter_info->unsupported_reason
+ = "missing InnoDB system tables";
+ DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED);
+ }
+
/* Only support online add foreign key constraint when
check_foreigns is turned off */
if ((ha_alter_info->handler_flags & ALTER_ADD_FOREIGN_KEY)
@@ -6397,9 +6401,9 @@ new_clustered_failed:
DBUG_ASSERT(!add_fts_doc_id_idx || (flags2 & DICT_TF2_FTS));
- ctx->new_table = dict_mem_table_create(
- new_table_name, NULL, n_cols + n_v_cols, n_v_cols,
- flags, flags2);
+ ctx->new_table = dict_table_t::create(
+ {new_table_name, tablen + partlen}, nullptr,
+ n_cols + n_v_cols, n_v_cols, flags, flags2);
/* The rebuilt indexed_table will use the renamed
column names. */
@@ -6796,7 +6800,9 @@ wrong_column_name:
}
}
- if (dict_table_get_low(ctx->new_table->name.m_name)) {
+ if (dict_sys.find_table(
+ {ctx->new_table->name.m_name,
+ strlen(ctx->new_table->name.m_name)})) {
my_error(ER_TABLE_EXISTS_ERROR, MYF(0),
ctx->new_table->name.m_name);
goto new_clustered_failed;
@@ -9731,17 +9737,14 @@ innobase_update_foreign_cache(
/* For complete loading of foreign keys, all associated tables must
also be loaded. */
while (err == DB_SUCCESS && !fk_tables.empty()) {
- dict_table_t* table = dict_load_table(
- fk_tables.front(), DICT_ERR_IGNORE_NONE);
-
- if (table == NULL) {
+ const char *f = fk_tables.front();
+ if (!dict_sys.load_table({f, strlen(f)})) {
err = DB_TABLE_NOT_FOUND;
ib::error()
- << "Failed to load table '"
- << table_name_t(const_cast<char*>
- (fk_tables.front()))
- << "' which has a foreign key constraint with"
- << " table '" << user_table->name << "'.";
+ << "Failed to load table "
+ << table_name_t(const_cast<char*>(f))
+ << " which has a foreign key constraint with"
+ << user_table->name;
break;
}
diff --git a/storage/innobase/handler/i_s.cc b/storage/innobase/handler/i_s.cc
index edf2acfa068..fc719557e4f 100644
--- a/storage/innobase/handler/i_s.cc
+++ b/storage/innobase/handler/i_s.cc
@@ -4820,6 +4820,41 @@ i_s_dict_fill_sys_tables(
DBUG_RETURN(0);
}
+
+/** Convert one SYS_TABLES record to dict_table_t.
+@param pcur persistent cursor position on SYS_TABLES record
+@param rec record to read from (nullptr=use the dict_sys cache)
+@param table the converted dict_table_t
+@return error message
+@retval nullptr on success */
+static const char *i_s_sys_tables_rec(const btr_pcur_t &pcur, const rec_t *rec,
+ dict_table_t **table)
+{
+ static_assert(DICT_FLD__SYS_TABLES__NAME == 0, "compatibility");
+ size_t len;
+ if (rec_get_1byte_offs_flag(pcur.old_rec))
+ {
+ len= rec_1_get_field_end_info(pcur.old_rec, 0);
+ if (len & REC_1BYTE_SQL_NULL_MASK)
+ return "corrupted SYS_TABLES.NAME";
+ }
+ else
+ {
+ len= rec_2_get_field_end_info(pcur.old_rec, 0);
+ static_assert(REC_2BYTE_EXTERN_MASK == 16384, "compatibility");
+ if (len >= REC_2BYTE_EXTERN_MASK)
+ return "corrupted SYS_TABLES.NAME";
+ }
+
+ const span<const char>name{reinterpret_cast<const char*>(pcur.old_rec), len};
+
+ if (rec)
+ return dict_load_table_low(name, rec, table);
+
+ *table= dict_sys.load_table(name);
+ return *table ? nullptr : "Table not found in cache";
+}
+
/*******************************************************************//**
Function to go through each record in SYS_TABLES table, and fill the
information_schema.innodb_sys_tables table with related table information
@@ -4833,8 +4868,6 @@ i_s_sys_tables_fill_table(
Item* ) /*!< in: condition (not used) */
{
btr_pcur_t pcur;
- const rec_t* rec;
- mem_heap_t* heap;
mtr_t mtr;
DBUG_ENTER("i_s_sys_tables_fill_table");
@@ -4845,21 +4878,23 @@ i_s_sys_tables_fill_table(
DBUG_RETURN(0);
}
- heap = mem_heap_create(1000);
dict_sys.mutex_lock();
mtr_start(&mtr);
- rec = dict_startscan_system(&pcur, &mtr, SYS_TABLES);
+ for (const rec_t *rec = dict_startscan_system(&pcur, &mtr,
+ dict_sys.sys_tables);
+ rec; rec = dict_getnext_system(&pcur, &mtr)) {
+ if (rec_get_deleted_flag(rec, 0)) {
+ continue;
+ }
- while (rec) {
const char* err_msg;
dict_table_t* table_rec;
/* Create and populate a dict_table_t structure with
information from SYS_TABLES row */
- err_msg = dict_process_sys_tables_rec_and_mtr_commit(
- heap, rec, &table_rec, false, &mtr);
-
+ err_msg = i_s_sys_tables_rec(pcur, rec, &table_rec);
+ mtr.commit();
dict_sys.mutex_unlock();
if (!err_msg) {
@@ -4875,17 +4910,13 @@ i_s_sys_tables_fill_table(
dict_mem_table_free(table_rec);
}
- mem_heap_empty(heap);
-
/* Get the next record */
dict_sys.mutex_lock();
- mtr_start(&mtr);
- rec = dict_getnext_system(&pcur, &mtr);
+ mtr.start();
}
- mtr_commit(&mtr);
+ mtr.commit();
dict_sys.mutex_unlock();
- mem_heap_free(heap);
DBUG_RETURN(0);
}
@@ -5078,7 +5109,6 @@ i_s_sys_tables_fill_table_stats(
{
btr_pcur_t pcur;
const rec_t* rec;
- mem_heap_t* heap;
mtr_t mtr;
DBUG_ENTER("i_s_sys_tables_fill_table_stats");
@@ -5089,30 +5119,24 @@ i_s_sys_tables_fill_table_stats(
DBUG_RETURN(0);
}
- heap = mem_heap_create(1000);
dict_sys.freeze();
dict_sys.mutex_lock();
mtr_start(&mtr);
- rec = dict_startscan_system(&pcur, &mtr, SYS_TABLES);
+ rec = dict_startscan_system(&pcur, &mtr, dict_sys.sys_tables);
while (rec) {
const char* err_msg;
dict_table_t* table_rec;
+ mtr.commit();
/* Fetch the dict_table_t structure corresponding to
this SYS_TABLES record */
- err_msg = dict_process_sys_tables_rec_and_mtr_commit(
- heap, rec, &table_rec, true, &mtr);
+ err_msg = i_s_sys_tables_rec(pcur, nullptr, &table_rec);
ulint ref_count = table_rec ? table_rec->get_ref_count() : 0;
dict_sys.mutex_unlock();
- DBUG_EXECUTE_IF("test_sys_tablestats", {
- if (strcmp("test/t1", table_rec->name.m_name) == 0 ) {
- DEBUG_SYNC_C("dict_table_not_protected");
- }});
-
if (table_rec != NULL) {
ut_ad(err_msg == NULL);
i_s_dict_fill_sys_tablestats(thd, table_rec, ref_count,
@@ -5125,7 +5149,6 @@ i_s_sys_tables_fill_table_stats(
}
dict_sys.unfreeze();
- mem_heap_empty(heap);
/* Get the next record */
dict_sys.freeze();
@@ -5138,7 +5161,6 @@ i_s_sys_tables_fill_table_stats(
mtr_commit(&mtr);
dict_sys.mutex_unlock();
dict_sys.unfreeze();
- mem_heap_free(heap);
DBUG_RETURN(0);
}
@@ -5335,7 +5357,7 @@ i_s_sys_indexes_fill_table(
mtr_start(&mtr);
/* Start scan the SYS_INDEXES table */
- rec = dict_startscan_system(&pcur, &mtr, SYS_INDEXES);
+ rec = dict_startscan_system(&pcur, &mtr, dict_sys.sys_indexes);
/* Process each record in the table */
while (rec) {
@@ -5553,7 +5575,7 @@ i_s_sys_columns_fill_table(
dict_sys.mutex_lock();
mtr_start(&mtr);
- rec = dict_startscan_system(&pcur, &mtr, SYS_COLUMNS);
+ rec = dict_startscan_system(&pcur, &mtr, dict_sys.sys_columns);
while (rec) {
const char* err_msg;
@@ -5739,14 +5761,14 @@ i_s_sys_virtual_fill_table(
RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name.str);
/* deny access to user without PROCESS_ACL privilege */
- if (check_global_access(thd, PROCESS_ACL)) {
+ if (check_global_access(thd, PROCESS_ACL) || !dict_sys.sys_virtual) {
DBUG_RETURN(0);
}
dict_sys.mutex_lock();
mtr_start(&mtr);
- rec = dict_startscan_system(&pcur, &mtr, SYS_VIRTUAL);
+ rec = dict_startscan_system(&pcur, &mtr, dict_sys.sys_virtual);
while (rec) {
const char* err_msg;
@@ -5936,7 +5958,7 @@ i_s_sys_fields_fill_table(
the next index. This is used to calculate prefix length */
last_id = 0;
- rec = dict_startscan_system(&pcur, &mtr, SYS_FIELDS);
+ rec = dict_startscan_system(&pcur, &mtr, dict_sys.sys_fields);
while (rec) {
ulint pos;
@@ -6127,8 +6149,7 @@ i_s_sys_foreign_fill_table(
RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name.str);
/* deny access to user without PROCESS_ACL privilege */
- if (check_global_access(thd, PROCESS_ACL)) {
-
+ if (check_global_access(thd, PROCESS_ACL) || !dict_sys.sys_foreign) {
DBUG_RETURN(0);
}
@@ -6136,7 +6157,7 @@ i_s_sys_foreign_fill_table(
dict_sys.mutex_lock();
mtr_start(&mtr);
- rec = dict_startscan_system(&pcur, &mtr, SYS_FOREIGN);
+ rec = dict_startscan_system(&pcur, &mtr, dict_sys.sys_foreign);
while (rec) {
const char* err_msg;
@@ -6320,7 +6341,8 @@ i_s_sys_foreign_cols_fill_table(
RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name.str);
/* deny access to user without PROCESS_ACL privilege */
- if (check_global_access(thd, PROCESS_ACL)) {
+ if (check_global_access(thd, PROCESS_ACL)
+ || !dict_sys.sys_foreign_cols) {
DBUG_RETURN(0);
}
@@ -6328,7 +6350,7 @@ i_s_sys_foreign_cols_fill_table(
dict_sys.mutex_lock();
mtr_start(&mtr);
- rec = dict_startscan_system(&pcur, &mtr, SYS_FOREIGN_COLS);
+ rec = dict_startscan_system(&pcur, &mtr, dict_sys.sys_foreign_cols);
while (rec) {
const char* err_msg;
diff --git a/storage/innobase/ibuf/ibuf0ibuf.cc b/storage/innobase/ibuf/ibuf0ibuf.cc
index d357011bf22..178f94684f2 100644
--- a/storage/innobase/ibuf/ibuf0ibuf.cc
+++ b/storage/innobase/ibuf/ibuf0ibuf.cc
@@ -455,8 +455,9 @@ ibuf_init_at_db_start(void)
mtr.commit();
ibuf.index = dict_mem_index_create(
- dict_mem_table_create("innodb_change_buffer",
- fil_system.sys_space, 1, 0, 0, 0),
+ dict_table_t::create(
+ {C_STRING_WITH_LEN("innodb_change_buffer")},
+ fil_system.sys_space, 1, 0, 0, 0),
"CLUST_IND",
DICT_CLUSTERED | DICT_IBUF, 1);
ibuf.index->id = DICT_IBUF_ID_MIN + IBUF_SPACE_ID;
@@ -1266,8 +1267,9 @@ ibuf_dummy_index_create(
dict_table_t* table;
dict_index_t* index;
- table = dict_mem_table_create("IBUF_DUMMY", NULL, n, 0,
- comp ? DICT_TF_COMPACT : 0, 0);
+ table = dict_table_t::create({C_STRING_WITH_LEN("IBUF_DUMMY")},
+ nullptr, n, 0,
+ comp ? DICT_TF_COMPACT : 0, 0);
index = dict_mem_index_create(table, "IBUF_DUMMY", 0, n);
diff --git a/storage/innobase/include/dict0crea.h b/storage/innobase/include/dict0crea.h
index d53c8f7ac33..59c18fde8f2 100644
--- a/storage/innobase/include/dict0crea.h
+++ b/storage/innobase/include/dict0crea.h
@@ -117,15 +117,6 @@ dict_create_index_tree_in_mem(
dict_index_t* index, /*!< in/out: index */
const trx_t* trx); /*!< in: InnoDB transaction handle */
-/****************************************************************//**
-Creates the foreign key constraints system tables inside InnoDB
-at server bootstrap or server start if they are not found or are
-not of the right form.
-@return DB_SUCCESS or error code */
-dberr_t
-dict_create_or_check_foreign_constraint_tables(void);
-/*================================================*/
-
/********************************************************************//**
Generate a foreign key constraint name when it was not named by the user.
A generated constraint has a name of the format dbname/tablename_ibfk_NUMBER,
@@ -171,13 +162,6 @@ dict_foreigns_has_s_base_col(
const dict_foreign_set& local_fk_set,
const dict_table_t* table);
-/** Creates the virtual column system tables inside InnoDB
-at server bootstrap or server start if they are not found or are
-not of the right form.
-@return DB_SUCCESS or error code */
-dberr_t
-dict_create_or_check_sys_virtual();
-
/********************************************************************//**
Add a foreign key definition to the data dictionary tables.
@return error code or DB_SUCCESS */
diff --git a/storage/innobase/include/dict0dict.h b/storage/innobase/include/dict0dict.h
index 67f5ad9ada8..73008b7560a 100644
--- a/storage/innobase/include/dict0dict.h
+++ b/storage/innobase/include/dict0dict.h
@@ -1373,23 +1373,48 @@ class dict_sys_t
FIXME: merge the mutex and the latch, once MDEV-23484 has been fixed */
mysql_mutex_t mutex;
public:
- hash_table_t table_hash; /*!< hash table of the tables, based
- on name */
- /** hash table of persistent table IDs */
- hash_table_t table_id_hash;
- dict_table_t* sys_tables; /*!< SYS_TABLES table */
- dict_table_t* sys_columns; /*!< SYS_COLUMNS table */
- dict_table_t* sys_indexes; /*!< SYS_INDEXES table */
- dict_table_t* sys_fields; /*!< SYS_FIELDS table */
- dict_table_t* sys_virtual; /*!< SYS_VIRTUAL table */
-
- /*=============================*/
- UT_LIST_BASE_NODE_T(dict_table_t)
- table_LRU; /*!< List of tables that can be evicted
- from the cache */
- UT_LIST_BASE_NODE_T(dict_table_t)
- table_non_LRU; /*!< List of tables that can't be
- evicted from the cache */
+ /** Indexes of SYS_TABLE[] */
+ enum
+ {
+ SYS_TABLES= 0,
+ SYS_INDEXES,
+ SYS_COLUMNS,
+ SYS_FIELDS,
+ SYS_FOREIGN,
+ SYS_FOREIGN_COLS,
+ SYS_VIRTUAL
+ };
+ /** System table names */
+ static const span<const char> SYS_TABLE[];
+
+ /** all tables (persistent and temporary), hashed by name */
+ hash_table_t table_hash;
+ /** hash table of persistent table IDs */
+ hash_table_t table_id_hash;
+
+ /** the SYS_TABLES table */
+ dict_table_t *sys_tables;
+ /** the SYS_COLUMNS table */
+ dict_table_t *sys_columns;
+ /** the SYS_INDEXES table */
+ dict_table_t *sys_indexes;
+ /** the SYS_FIELDS table */
+ dict_table_t *sys_fields;
+ /** the SYS_FOREIGN table */
+ dict_table_t *sys_foreign;
+ /** the SYS_FOREIGN_COLS table */
+ dict_table_t *sys_foreign_cols;
+ /** the SYS_VIRTUAL table */
+ dict_table_t *sys_virtual;
+
+ /** @return whether all non-hard-coded system tables exist */
+ bool sys_tables_exist() const
+ { return UNIV_LIKELY(sys_foreign && sys_foreign_cols && sys_virtual); }
+
+ /** list of persistent tables that can be evicted */
+ UT_LIST_BASE_NODE_T(dict_table_t) table_LRU;
+ /** list of persistent tables that cannot be evicted */
+ UT_LIST_BASE_NODE_T(dict_table_t) table_non_LRU;
private:
bool m_initialised= false;
@@ -1418,46 +1443,47 @@ public:
row_id= ut_uint64_align_up(id, ROW_ID_WRITE_MARGIN) + ROW_ID_WRITE_MARGIN;
}
- /** @return a new temporary table ID */
- table_id_t get_temporary_table_id() {
- return temp_table_id.fetch_add(1, std::memory_order_relaxed);
- }
+ /** @return a new temporary table ID */
+ table_id_t acquire_temporary_table_id()
+ {
+ return temp_table_id.fetch_add(1, std::memory_order_relaxed);
+ }
- /** Look up a temporary table.
- @param id temporary table ID
- @return temporary table
- @retval NULL if the table does not exist
- (should only happen during the rollback of CREATE...SELECT) */
- dict_table_t* get_temporary_table(table_id_t id)
- {
- mysql_mutex_assert_owner(&mutex);
- dict_table_t* table;
- ulint fold = ut_fold_ull(id);
- HASH_SEARCH(id_hash, &temp_id_hash, fold, dict_table_t*, table,
- ut_ad(table->cached), table->id == id);
- if (UNIV_LIKELY(table != NULL)) {
- DBUG_ASSERT(table->is_temporary());
- DBUG_ASSERT(table->id >= DICT_HDR_FIRST_ID);
- table->acquire();
- }
- return table;
- }
+ /** Look up a temporary table.
+ @param id temporary table ID
+ @return temporary table
+ @retval nullptr if the table does not exist
+ (should only happen during the rollback of CREATE...SELECT) */
+ dict_table_t *acquire_temporary_table(table_id_t id)
+ {
+ mysql_mutex_assert_owner(&mutex);
+ dict_table_t *table;
+ ulint fold = ut_fold_ull(id);
+ HASH_SEARCH(id_hash, &temp_id_hash, fold, dict_table_t*, table,
+ ut_ad(table->cached), table->id == id);
+ if (UNIV_LIKELY(table != nullptr))
+ {
+ DBUG_ASSERT(table->is_temporary());
+ DBUG_ASSERT(table->id >= DICT_HDR_FIRST_ID);
+ table->acquire();
+ }
+ return table;
+ }
- /** Look up a persistent table.
- @param id table ID
- @return table
- @retval NULL if not cached */
- dict_table_t* get_table(table_id_t id)
- {
- mysql_mutex_assert_owner(&mutex);
- dict_table_t* table;
- ulint fold = ut_fold_ull(id);
- HASH_SEARCH(id_hash, &table_id_hash, fold, dict_table_t*,
- table,
- ut_ad(table->cached), table->id == id);
- DBUG_ASSERT(!table || !table->is_temporary());
- return table;
- }
+ /** Look up a persistent table.
+ @param id table ID
+ @return table
+ @retval nullptr if not cached */
+ dict_table_t *find_table(table_id_t id)
+ {
+ mysql_mutex_assert_owner(&mutex);
+ dict_table_t *table;
+ ulint fold = ut_fold_ull(id);
+ HASH_SEARCH(id_hash, &table_id_hash, fold, dict_table_t*, table,
+ ut_ad(table->cached), table->id == id);
+ DBUG_ASSERT(!table || !table->is_temporary());
+ return table;
+ }
bool is_initialised() const { return m_initialised; }
@@ -1480,14 +1506,13 @@ public:
#ifdef UNIV_DEBUG
/** Find a table */
- template <bool in_lru> bool find(dict_table_t* table)
+ template <bool in_lru> bool find(const dict_table_t *table)
{
ut_ad(table);
ut_ad(table->can_be_evicted == in_lru);
mysql_mutex_assert_owner(&mutex);
- for (const dict_table_t* t = UT_LIST_GET_FIRST(in_lru
- ? table_LRU : table_non_LRU);
- t; t = UT_LIST_GET_NEXT(table_LRU, t))
+ for (const dict_table_t* t= in_lru ? table_LRU.start : table_non_LRU.start;
+ t; t = UT_LIST_GET_NEXT(table_LRU, t))
{
if (t == table) return true;
ut_ad(t->can_be_evicted == in_lru);
@@ -1495,25 +1520,25 @@ public:
return false;
}
/** Find a table */
- bool find(dict_table_t* table)
+ bool find(const dict_table_t *table)
{
return table->can_be_evicted ? find<true>(table) : find<false>(table);
}
#endif
/** Move a table to the non-LRU list from the LRU list. */
- void prevent_eviction(dict_table_t* table)
+ void prevent_eviction(dict_table_t *table)
{
ut_ad(find(table));
if (table->can_be_evicted)
{
- table->can_be_evicted = FALSE;
+ table->can_be_evicted= false;
UT_LIST_REMOVE(table_LRU, table);
UT_LIST_ADD_LAST(table_non_LRU, table);
}
}
/** Acquire a reference to a cached table. */
- inline void acquire(dict_table_t* table);
+ inline void acquire(dict_table_t *table);
/** Assert that the mutex is locked */
void assert_locked() const { mysql_mutex_assert_owner(&mutex); }
@@ -1573,8 +1598,8 @@ public:
+ (sizeof(dict_col_t) + sizeof(dict_field_t)) * 10
+ sizeof(dict_field_t) * 5 /* total number of key fields */
+ 200; /* arbitrary, covering names and overhead */
- size += (table_hash.n_cells + table_id_hash.n_cells
- + temp_id_hash.n_cells) * sizeof(hash_cell_t);
+ size += (table_hash.n_cells + table_id_hash.n_cells +
+ temp_id_hash.n_cells) * sizeof(hash_cell_t);
return size;
}
@@ -1582,12 +1607,43 @@ public:
@param half whether to consider half the tables only (instead of all)
@return number of tables evicted */
ulint evict_table_LRU(bool half);
+
+ /** Look up a table in the dictionary cache.
+ @param name table name
+ @return table handle
+ @retval nullptr if not found */
+ dict_table_t *find_table(const span<const char> &name) const
+ {
+ assert_locked();
+ for (dict_table_t *table= static_cast<dict_table_t*>
+ (HASH_GET_FIRST(&table_hash, table_hash.calc_hash
+ (ut_fold_binary(reinterpret_cast<const byte*>
+ (name.data()), name.size()))));
+ table; table= table->name_hash)
+ if (strlen(table->name.m_name) == name.size() &&
+ !memcmp(table->name.m_name, name.data(), name.size()))
+ return table;
+ return nullptr;
+ }
+
+ /** Look up or load a table definition
+ @param name table name
+ @param ignore errors to ignore when loading the table definition
+ @return table handle
+ @retval nullptr if not found */
+ dict_table_t *load_table(const span<const char> &name,
+ dict_err_ignore_t ignore= DICT_ERR_IGNORE_NONE);
+
+ /** Attempt to load the system tables on startup
+ @return whether any discrepancy with the expected definition was found */
+ bool load_sys_tables();
+ /** Create or check system tables on startup */
+ dberr_t create_or_check_sys_tables();
};
/** the data dictionary cache */
extern dict_sys_t dict_sys;
-#define dict_table_prevent_eviction(table) dict_sys.prevent_eviction(table)
#define dict_sys_lock() dict_sys.lock(SRW_LOCK_CALL)
#define dict_sys_unlock() dict_sys.unlock()
diff --git a/storage/innobase/include/dict0load.h b/storage/innobase/include/dict0load.h
index 645dbc12c80..591dd30f211 100644
--- a/storage/innobase/include/dict0load.h
+++ b/storage/innobase/include/dict0load.h
@@ -39,20 +39,6 @@ Created 4/24/1996 Heikki Tuuri
/** A stack of table names related through foreign key constraints */
typedef std::deque<const char*, ut_allocator<const char*> > dict_names_t;
-/** enum that defines all system table IDs. @see SYSTEM_TABLE_NAME[] */
-enum dict_system_id_t {
- SYS_TABLES = 0,
- SYS_INDEXES,
- SYS_COLUMNS,
- SYS_FIELDS,
- SYS_FOREIGN,
- SYS_FOREIGN_COLS,
- SYS_VIRTUAL,
-
- /* This must be last item. Defines the number of system tables. */
- SYS_NUM_SYSTEM_TABLES
-};
-
/** Check each tablespace found in the data dictionary.
Then look at each table defined in SYS_TABLES that has a space_id > 0
to find all the file-per-table tablespaces.
@@ -74,18 +60,6 @@ dict_get_and_save_data_dir_path(
dict_table_t* table,
bool dict_mutex_own);
-/** Loads a table definition and also all its index definitions, and also
-the cluster definition if the table is a member in a cluster. Also loads
-all foreign key constraints where the foreign key is in the table or where
-a foreign key references columns in this table.
-@param[in] name Table name in the dbname/tablename format
-@param[in] ignore_err Error to be ignored when loading
- table and its index definition
-@return table, NULL if does not exist; if the table is stored in an
-.ibd file, but the file does not exist, then we set the file_unreadable
-flag in the table object we return. */
-dict_table_t* dict_load_table(const char* name, dict_err_ignore_t ignore_err);
-
/***********************************************************************//**
Loads a table object based on the table id.
@return table; NULL if table does not exist */
@@ -140,7 +114,7 @@ dict_startscan_system(
btr_pcur_t* pcur, /*!< out: persistent cursor to
the record */
mtr_t* mtr, /*!< in: the mini-transaction */
- dict_system_id_t system_id); /*!< in: which system table to open */
+ dict_table_t* table); /*!< in: system table */
/********************************************************************//**
This function get the next system table record as we scan the table.
@return the record if found, NULL if end of scan. */
@@ -150,19 +124,18 @@ dict_getnext_system(
btr_pcur_t* pcur, /*!< in/out: persistent cursor
to the record */
mtr_t* mtr); /*!< in: the mini-transaction */
-/********************************************************************//**
-This function processes one SYS_TABLES record and populate the dict_table_t
-struct for the table.
-@return error message, or NULL on success */
-const char*
-dict_process_sys_tables_rec_and_mtr_commit(
-/*=======================================*/
- mem_heap_t* heap, /*!< in: temporary memory heap */
- const rec_t* rec, /*!< in: SYS_TABLES record */
- dict_table_t** table, /*!< out: dict_table_t to fill */
- bool cached, /*!< in: whether to load from cache */
- mtr_t* mtr); /*!< in/out: mini-transaction,
- will be committed */
+
+/** Load a table definition from a SYS_TABLES record to dict_table_t.
+Do not load any columns or indexes.
+@param[in] name Table name
+@param[in] rec SYS_TABLES record
+@param[out,own] table table, or nullptr
+@return error message
+@retval nullptr on success */
+const char *dict_load_table_low(const span<const char> &name,
+ const rec_t *rec, dict_table_t **table)
+ MY_ATTRIBUTE((nonnull, warn_unused_result));
+
/********************************************************************//**
This function parses a SYS_INDEXES record and populate a dict_index_t
structure with the information from the record. For detail information
diff --git a/storage/innobase/include/dict0mem.h b/storage/innobase/include/dict0mem.h
index 71554e116eb..867826f92d6 100644
--- a/storage/innobase/include/dict0mem.h
+++ b/storage/innobase/include/dict0mem.h
@@ -28,10 +28,10 @@ Created 1/8/1996 Heikki Tuuri
#ifndef dict0mem_h
#define dict0mem_h
+#include "dict0types.h"
#include "data0type.h"
#include "mem0mem.h"
#include "row0types.h"
-#include "rem0types.h"
#include "btr0types.h"
#include "lock0types.h"
#include "que0types.h"
@@ -298,17 +298,6 @@ parent table will fail, and user has to drop excessive foreign constraint
before proceeds. */
#define FK_MAX_CASCADE_DEL 15
-/** Create a table memory object.
-@param name table name
-@param space tablespace
-@param n_cols total number of columns (both virtual and non-virtual)
-@param n_v_cols number of virtual columns
-@param flags table flags
-@param flags2 table flags2
-@return own: table object */
-dict_table_t *dict_mem_table_create(const char *name, fil_space_t *space,
- ulint n_cols, ulint n_v_cols, ulint flags,
- ulint flags2);
/****************************************************************/ /**
Free a table memory object. */
void
@@ -1816,7 +1805,7 @@ typedef enum {
} dict_frm_t;
/** Data structure for a database table. Most fields will be
-initialized to 0, NULL or FALSE in dict_mem_table_create(). */
+zero-initialized in dict_table_t::create(). */
struct dict_table_t {
/** Get reference count.
@@ -2435,10 +2424,24 @@ public:
return false;
}
- /** Check whether the table name is same as mysql/innodb_stats_table
- or mysql/innodb_index_stats.
- @return true if the table name is same as stats table */
- bool is_stats_table() const;
+ /** @return whether the name is
+ mysql.innodb_index_stats or mysql.innodb_table_stats */
+ inline bool is_stats_table() const;
+
+ /** Create metadata.
+ @param name table name
+ @param space tablespace
+ @param n_cols total number of columns (both virtual and non-virtual)
+ @param n_v_cols number of virtual columns
+ @param flags table flags
+ @param flags2 table flags2
+ @return newly allocated table object */
+ static dict_table_t *create(const span<const char> &name, fil_space_t *space,
+ ulint n_cols, ulint n_v_cols, ulint flags,
+ ulint flags2);
+
+ /** @return whether SYS_TABLES.NAME is for a '#sql-ib' table */
+ static bool is_garbage_name(const void *data, size_t size);
};
inline void dict_index_t::set_modified(mtr_t& mtr) const
diff --git a/storage/innobase/include/dict0priv.h b/storage/innobase/include/dict0priv.h
deleted file mode 100644
index 3f2792054e0..00000000000
--- a/storage/innobase/include/dict0priv.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/*****************************************************************************
-
-Copyright (c) 2010, 2016, Oracle and/or its affiliates. All Rights Reserved.
-
-This program is free software; you can redistribute it and/or modify it under
-the terms of the GNU General Public License as published by the Free Software
-Foundation; version 2 of the License.
-
-This program is distributed in the hope that it will be useful, but WITHOUT
-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License along with
-this program; if not, write to the Free Software Foundation, Inc.,
-51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA
-
-*****************************************************************************/
-
-/**************************************************//**
-@file include/dict0priv.h
-Data dictionary private functions
-
-Created Fri 2 Jul 2010 13:30:38 EST - Sunny Bains
-*******************************************************/
-
-#ifndef dict0priv_h
-#define dict0priv_h
-
-/**********************************************************************//**
-Gets a table; loads it to the dictionary cache if necessary. A low-level
-function. Note: Not to be called from outside dict0*c functions.
-@return table, NULL if not found */
-UNIV_INLINE
-dict_table_t*
-dict_table_get_low(
-/*===============*/
- const char* table_name); /*!< in: table name */
-
-/**********************************************************************//**
-Checks if a table is in the dictionary cache.
-@return table, NULL if not found */
-UNIV_INLINE
-dict_table_t*
-dict_table_check_if_in_cache_low(
-/*=============================*/
- const char* table_name); /*!< in: table name */
-
-#include "dict0priv.ic"
-
-#endif /* dict0priv.h */
diff --git a/storage/innobase/include/dict0priv.ic b/storage/innobase/include/dict0priv.ic
deleted file mode 100644
index 36d0ba66524..00000000000
--- a/storage/innobase/include/dict0priv.ic
+++ /dev/null
@@ -1,91 +0,0 @@
-/*****************************************************************************
-
-Copyright (c) 2010, 2014, Oracle and/or its affiliates. All Rights Reserved.
-
-This program is free software; you can redistribute it and/or modify it under
-the terms of the GNU General Public License as published by the Free Software
-Foundation; version 2 of the License.
-
-This program is distributed in the hope that it will be useful, but WITHOUT
-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License along with
-this program; if not, write to the Free Software Foundation, Inc.,
-51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA
-
-*****************************************************************************/
-
-/******************************************************************//**
-@file include/dict0priv.ic
-Data dictionary system private include file
-
-Created Wed 13 Oct 2010 16:10:14 EST Sunny Bains
-***********************************************************************/
-
-#include "dict0dict.h"
-#include "dict0load.h"
-
-/**********************************************************************//**
-Gets a table; loads it to the dictionary cache if necessary. A low-level
-function.
-@return table, NULL if not found */
-UNIV_INLINE
-dict_table_t*
-dict_table_get_low(
-/*===============*/
- const char* table_name) /*!< in: table name */
-{
- dict_table_t* table;
-
- ut_ad(table_name);
- dict_sys.assert_locked();
-
- table = dict_table_check_if_in_cache_low(table_name);
-
- if (table && table->corrupted) {
- ib::error error;
- error << "Table " << table->name << "is corrupted";
- if (srv_load_corrupted) {
- error << ", but innodb_force_load_corrupted is set";
- } else {
- return(NULL);
- }
- }
-
- if (table == NULL) {
- table = dict_load_table(table_name, DICT_ERR_IGNORE_NONE);
- }
-
- ut_ad(!table || table->cached);
-
- return(table);
-}
-
-/**********************************************************************//**
-Checks if a table is in the dictionary cache.
-@return table, NULL if not found */
-UNIV_INLINE
-dict_table_t*
-dict_table_check_if_in_cache_low(
-/*=============================*/
- const char* table_name) /*!< in: table name */
-{
- dict_table_t* table;
- ulint table_fold;
-
- DBUG_ENTER("dict_table_check_if_in_cache_low");
- DBUG_PRINT("dict_table_check_if_in_cache_low",
- ("table: '%s'", table_name));
-
- ut_ad(table_name);
- dict_sys.assert_locked();
-
- /* Look for the table name in the hash table */
- table_fold = ut_fold_string(table_name);
-
- HASH_SEARCH(name_hash, &dict_sys.table_hash, table_fold,
- dict_table_t*, table, ut_ad(table->cached),
- !strcmp(table->name.m_name, table_name));
- DBUG_RETURN(table);
-}
diff --git a/storage/innobase/include/dict0types.h b/storage/innobase/include/dict0types.h
index 24bc84d776c..cfd0ff98912 100644
--- a/storage/innobase/include/dict0types.h
+++ b/storage/innobase/include/dict0types.h
@@ -28,8 +28,11 @@ Created 1/8/1996 Heikki Tuuri
#define dict0types_h
#include "univ.i"
+#include "span.h"
#include <rem0types.h>
+using st_::span;
+
struct dict_col_t;
struct dict_field_t;
struct dict_index_t;
diff --git a/storage/innobase/include/fil0fil.h b/storage/innobase/include/fil0fil.h
index 85ee8ce6f99..c59b4c54265 100644
--- a/storage/innobase/include/fil0fil.h
+++ b/storage/innobase/include/fil0fil.h
@@ -39,7 +39,6 @@ Created 10/25/1995 Heikki Tuuri
#include "log0recv.h"
#include "dict0types.h"
#include "ilist.h"
-#include "span.h"
#include <set>
#include <mutex>
@@ -1621,7 +1620,7 @@ char* fil_make_filepath(const char *path, const fil_space_t::name_type &name,
ib_extention ext, bool trim_name);
char *fil_make_filepath(const char* path, const table_name_t name,
- ib_extention ext, bool trim_name);
+ ib_extention suffix, bool strip_name);
/** Create a tablespace file.
@param[in] space_id Tablespace ID
@@ -1677,7 +1676,7 @@ statement to update the dictionary tables if they are incorrect.
@param[in] purpose FIL_TYPE_TABLESPACE or FIL_TYPE_TEMPORARY
@param[in] id tablespace ID
@param[in] flags expected FSP_SPACE_FLAGS
-@param[in] tablename table name
+@param[in] name table name
If file-per-table, it is the table name in the databasename/tablename format
@param[in] path_in expected filepath, usually read from dictionary
@param[out] err DB_SUCCESS or error code
@@ -1689,7 +1688,7 @@ fil_ibd_open(
fil_type_t purpose,
ulint id,
ulint flags,
- const table_name_t tablename,
+ fil_space_t::name_type name,
const char* path_in,
dberr_t* err = NULL)
MY_ATTRIBUTE((warn_unused_result));
diff --git a/storage/innobase/include/fsp0file.h b/storage/innobase/include/fsp0file.h
index 3ec56c75476..8c11d61c5aa 100644
--- a/storage/innobase/include/fsp0file.h
+++ b/storage/innobase/include/fsp0file.h
@@ -501,7 +501,7 @@ public:
@param name table name
@return filepath()
@retval nullptr if the .isl file does not exist or cannot be read */
- const char* open_link_file(const table_name_t& name);
+ const char* open_link_file(const fil_space_t::name_type name);
/** Delete an InnoDB Symbolic Link (ISL) file. */
void delete_link_file(void);
diff --git a/storage/innobase/include/row0mysql.h b/storage/innobase/include/row0mysql.h
index 6674d2f4fbc..0b4590b67bc 100644
--- a/storage/innobase/include/row0mysql.h
+++ b/storage/innobase/include/row0mysql.h
@@ -377,25 +377,17 @@ row_create_index_for_mysql(
fil_encryption_t mode, /*!< in: encryption mode */
uint32_t key_id) /*!< in: encryption key_id */
MY_ATTRIBUTE((warn_unused_result));
-/*********************************************************************//**
-The master thread in srv0srv.cc calls this regularly to drop tables which
-we must drop in background after queries to them have ended. Such lazy
-dropping of tables is needed in ALTER TABLE on Unix.
+
+/** The master task calls this regularly to drop tables which
+we must drop in background after queries to them have ended.
@return how many tables dropped + remaining tables in list */
-ulint
-row_drop_tables_for_mysql_in_background(void);
-/*=========================================*/
-/*********************************************************************//**
-Get the background drop list length. NOTE: the caller must own the kernel
-mutex!
-@return how many tables in list */
-ulint
-row_get_background_drop_list_len_low(void);
-/*======================================*/
+ulint row_drop_tables_for_mysql_in_background();
+
+/** @return number of tables in the background drop list */
+ulint row_get_background_drop_list_len_low();
/** Drop garbage tables during recovery. */
-void
-row_mysql_drop_garbage_tables();
+void row_mysql_drop_garbage_tables();
/*********************************************************************//**
Sets an exclusive lock on a table.
diff --git a/storage/innobase/include/trx0trx.h b/storage/innobase/include/trx0trx.h
index 813afd4763a..a570f3cb5e0 100644
--- a/storage/innobase/include/trx0trx.h
+++ b/storage/innobase/include/trx0trx.h
@@ -964,7 +964,7 @@ public:
}
/** @return whether the table has lock on
- mysql.innodb_table_stats and mysql.innodb_index_stats */
+ mysql.innodb_table_stats or mysql.innodb_index_stats */
bool has_stats_table_lock() const;
/** Free the memory to trx_pools */
diff --git a/storage/innobase/lock/lock0lock.cc b/storage/innobase/lock/lock0lock.cc
index 2b75a6bf8d7..058f8386434 100644
--- a/storage/innobase/lock/lock0lock.cc
+++ b/storage/innobase/lock/lock0lock.cc
@@ -3857,7 +3857,7 @@ released:
LockMutexGuard g{SRW_LOCK_CALL};
for (const table_id_t id : to_evict)
{
- if (dict_table_t *table= dict_sys.get_table(id))
+ if (dict_table_t *table= dict_sys.find_table(id))
if (!table->get_ref_count() && !UT_LIST_GET_LEN(table->locks))
dict_sys.remove(table, true);
}
diff --git a/storage/innobase/page/page0zip.cc b/storage/innobase/page/page0zip.cc
index 09ac48bce0f..ca73ede64ae 100644
--- a/storage/innobase/page/page0zip.cc
+++ b/storage/innobase/page/page0zip.cc
@@ -1652,8 +1652,8 @@ page_zip_fields_decode(
return(NULL);
}
- table = dict_mem_table_create("ZIP_DUMMY", NULL, n, 0,
- DICT_TF_COMPACT, 0);
+ table = dict_table_t::create({C_STRING_WITH_LEN("ZIP_DUMMY")},
+ nullptr, n, 0, DICT_TF_COMPACT, 0);
index = dict_mem_index_create(table, "ZIP_DUMMY", 0, n);
index->n_uniq = static_cast<unsigned>(n) & dict_index_t::MAX_N_FIELDS;
/* avoid ut_ad(index->cached) in dict_index_get_n_unique_in_tree */
diff --git a/storage/innobase/pars/pars0pars.cc b/storage/innobase/pars/pars0pars.cc
index 5ec408342a8..abd8dd9b26a 100644
--- a/storage/innobase/pars/pars0pars.cc
+++ b/storage/innobase/pars/pars0pars.cc
@@ -1783,8 +1783,9 @@ pars_create_table(
n_cols = que_node_list_get_len(column_defs);
- table = dict_mem_table_create(
- table_sym->name, NULL, n_cols, 0, flags, flags2);
+ table = dict_table_t::create(
+ {table_sym->name, strlen(table_sym->name)},
+ nullptr, n_cols, 0, flags, flags2);
mem_heap_t* heap = pars_sym_tab_global->heap;
column = column_defs;
diff --git a/storage/innobase/row/row0import.cc b/storage/innobase/row/row0import.cc
index 5ad7de3fb8c..0d8b2007f07 100644
--- a/storage/innobase/row/row0import.cc
+++ b/storage/innobase/row/row0import.cc
@@ -4091,7 +4091,10 @@ row_import_for_mysql(
ut_ad(!DICT_TF_HAS_DATA_DIR(table->flags) || table->data_dir_path);
const char *data_dir_path = DICT_TF_HAS_DATA_DIR(table->flags)
? table->data_dir_path : nullptr;
- filepath = fil_make_filepath(data_dir_path, table->name, IBD,
+ fil_space_t::name_type name{
+ table->name.m_name, strlen(table->name.m_name)};
+
+ filepath = fil_make_filepath(data_dir_path, name, IBD,
data_dir_path != nullptr);
DBUG_EXECUTE_IF(
@@ -4116,7 +4119,7 @@ row_import_for_mysql(
table->space = fil_ibd_open(
true, FIL_TYPE_IMPORT, table->space_id,
- fsp_flags, table->name, filepath, &err);
+ fsp_flags, name, filepath, &err);
ut_ad((table->space == NULL) == (err != DB_SUCCESS));
DBUG_EXECUTE_IF("ib_import_open_tablespace_failure",
diff --git a/storage/innobase/row/row0mysql.cc b/storage/innobase/row/row0mysql.cc
index 8b12714d3d4..77dffca290c 100644
--- a/storage/innobase/row/row0mysql.cc
+++ b/storage/innobase/row/row0mysql.cc
@@ -36,7 +36,6 @@ Created 9/17/2000 Heikki Tuuri
#include "dict0crea.h"
#include "dict0dict.h"
#include "dict0load.h"
-#include "dict0priv.h"
#include "dict0stats.h"
#include "dict0stats_bg.h"
#include "dict0defrag_bg.h"
@@ -2321,9 +2320,8 @@ row_create_table_for_mysql(
ib::error() << "Trying to create a MySQL system table "
<< table->name << " of type InnoDB. MySQL system"
" tables must be of the MyISAM type!";
-#ifndef DBUG_OFF
+
err_exit:
-#endif /* !DBUG_OFF */
dict_mem_table_free(table);
trx->op_info = "";
@@ -2331,6 +2329,11 @@ err_exit:
return(DB_ERROR);
}
+ if (!dict_sys.sys_tables_exist()) {
+ ib::error() << "Some InnoDB system tables are missing";
+ goto err_exit;
+ }
+
trx_start_if_not_started_xa(trx, true);
heap = mem_heap_create(512);
@@ -2622,10 +2625,8 @@ row_get_background_drop_list_len_low(void)
}
/** Drop garbage tables during recovery. */
-void
-row_mysql_drop_garbage_tables()
+void row_mysql_drop_garbage_tables()
{
- mem_heap_t* heap = mem_heap_create(FN_REFLEN);
btr_pcur_t pcur;
mtr_t mtr;
trx_t* trx = trx_create();
@@ -2641,7 +2642,6 @@ row_mysql_drop_garbage_tables()
const rec_t* rec;
const byte* field;
ulint len;
- const char* table_name;
btr_pcur_move_to_next_user_rec(&pcur, &mtr);
@@ -2655,38 +2655,37 @@ row_mysql_drop_garbage_tables()
}
field = rec_get_nth_field_old(rec, 0/*NAME*/, &len);
- if (len == UNIV_SQL_NULL || len == 0) {
+ if (len == UNIV_SQL_NULL) {
/* Corrupted SYS_TABLES.NAME */
continue;
}
- table_name = mem_heap_strdupl(
- heap,
- reinterpret_cast<const char*>(field), len);
- if (strstr(table_name, "/" TEMP_FILE_PREFIX_INNODB)) {
- btr_pcur_store_position(&pcur, &mtr);
- btr_pcur_commit_specify_mtr(&pcur, &mtr);
-
- if (dict_load_table(table_name,
- DICT_ERR_IGNORE_DROP)) {
- row_drop_table_for_mysql(table_name, trx,
- SQLCOM_DROP_TABLE);
- trx_commit_for_mysql(trx);
- }
+ if (!dict_table_t::is_garbage_name(field, len)) {
+ continue;
+ }
- mtr.start();
- btr_pcur_restore_position(BTR_SEARCH_LEAF,
- &pcur, &mtr);
+ btr_pcur_store_position(&pcur, &mtr);
+ btr_pcur_commit_specify_mtr(&pcur, &mtr);
+
+ const span<const char> name = {
+ reinterpret_cast<const char*>(pcur.old_rec), len
+ };
+ if (dict_sys.load_table(name, DICT_ERR_IGNORE_DROP)) {
+ char* table_name = mem_strdupl(name.data(), len);
+ row_drop_table_for_mysql(table_name, trx,
+ SQLCOM_DROP_TABLE);
+ ut_free(table_name);
+ trx_commit_for_mysql(trx);
}
- mem_heap_empty(heap);
+ mtr.start();
+ btr_pcur_restore_position(BTR_SEARCH_LEAF, &pcur, &mtr);
}
btr_pcur_close(&pcur);
mtr.commit();
row_mysql_unlock_data_dictionary(trx);
trx->free();
- mem_heap_free(heap);
}
/*********************************************************************//**
@@ -3160,38 +3159,6 @@ row_drop_ancillary_fts_tables(
return(DB_SUCCESS);
}
-/** Drop a table from the memory cache as part of dropping a table.
-@param[in] tablename A copy of table->name. Used when table == null
-@param[in,out] table Table cache entry
-@param[in,out] trx Transaction handle
-@return error code or DB_SUCCESS */
-UNIV_INLINE
-dberr_t
-row_drop_table_from_cache(
- const char* tablename,
- dict_table_t* table,
- trx_t* trx)
-{
- dberr_t err = DB_SUCCESS;
- ut_ad(!table->is_temporary());
-
- /* Remove the pointer to this table object from the list
- of modified tables by the transaction because the object
- is going to be destroyed below. */
- trx->mod_tables.erase(table);
-
- dict_sys.remove(table);
-
- if (dict_load_table(tablename, DICT_ERR_IGNORE_FK_NOKEY)) {
- ib::error() << "Not able to remove table "
- << ut_get_name(trx, tablename)
- << " from the dictionary cache!";
- err = DB_ERROR;
- }
-
- return(err);
-}
-
/** Drop a table for MySQL.
If the data dictionary was not already locked by the transaction,
the transaction will be committed. Otherwise, the data dictionary
@@ -3331,7 +3298,7 @@ row_drop_table_for_mysql(
}
}
- dict_table_prevent_eviction(table);
+ dict_sys.prevent_eviction(table);
dict_table_close(table, TRUE, FALSE);
/* Check if the table is referenced by foreign key constraints from
@@ -3475,10 +3442,8 @@ defer:
pars_info_add_str_literal(info, "name", name);
- if (sqlcom != SQLCOM_TRUNCATE
- && strchr(name, '/')
- && dict_table_get_low("SYS_FOREIGN")
- && dict_table_get_low("SYS_FOREIGN_COLS")) {
+ if (sqlcom != SQLCOM_TRUNCATE && strchr(name, '/')
+ && dict_sys.sys_foreign && dict_sys.sys_foreign_cols) {
err = que_eval_sql(
info,
"PROCEDURE DROP_FOREIGN_PROC () IS\n"
@@ -3507,7 +3472,7 @@ defer:
}
} else {
do_drop:
- if (dict_table_get_low("SYS_VIRTUAL")) {
+ if (dict_sys.sys_virtual) {
err = que_eval_sql(
info,
"PROCEDURE DROP_VIRTUAL_PROC () IS\n"
@@ -3588,12 +3553,8 @@ do_drop:
IBD,
table->data_dir_path != nullptr);
- /* Free the dict_table_t object. */
- err = row_drop_table_from_cache(tablename, table, trx);
- if (err != DB_SUCCESS) {
- ut_free(filepath);
- break;
- }
+ trx->mod_tables.erase(table);
+ dict_sys.remove(table);
/* Do not attempt to drop known-to-be-missing tablespaces,
nor the system tablespace. */
@@ -4136,8 +4097,8 @@ row_rename_table_for_mysql(
dict_mem_table_fill_foreign_vcol_set(table);
while (!fk_tables.empty()) {
- dict_load_table(fk_tables.front(),
- DICT_ERR_IGNORE_NONE);
+ const char *f = fk_tables.front();
+ dict_sys.load_table({f, strlen(f)});
fk_tables.pop_front();
}
diff --git a/storage/innobase/row/row0uins.cc b/storage/innobase/row/row0uins.cc
index 9a598718616..51a5d30e7d3 100644
--- a/storage/innobase/row/row0uins.cc
+++ b/storage/innobase/row/row0uins.cc
@@ -428,10 +428,10 @@ static bool row_undo_ins_parse_undo_rec(undo_node_t* node, bool dict_locked)
DICT_TABLE_OP_NORMAL);
} else if (!dict_locked) {
dict_sys.mutex_lock();
- node->table = dict_sys.get_temporary_table(table_id);
+ node->table = dict_sys.acquire_temporary_table(table_id);
dict_sys.mutex_unlock();
} else {
- node->table = dict_sys.get_temporary_table(table_id);
+ node->table = dict_sys.acquire_temporary_table(table_id);
}
if (!node->table) {
diff --git a/storage/innobase/row/row0umod.cc b/storage/innobase/row/row0umod.cc
index d363e82f1f1..5452229d9cb 100644
--- a/storage/innobase/row/row0umod.cc
+++ b/storage/innobase/row/row0umod.cc
@@ -1256,10 +1256,10 @@ static bool row_undo_mod_parse_undo_rec(undo_node_t* node, bool dict_locked)
DICT_TABLE_OP_NORMAL);
} else if (!dict_locked) {
dict_sys.mutex_lock();
- node->table = dict_sys.get_temporary_table(table_id);
+ node->table = dict_sys.acquire_temporary_table(table_id);
dict_sys.mutex_unlock();
} else {
- node->table = dict_sys.get_temporary_table(table_id);
+ node->table = dict_sys.acquire_temporary_table(table_id);
}
if (!node->table) {
diff --git a/storage/innobase/srv/srv0start.cc b/storage/innobase/srv/srv0start.cc
index 524964e0124..6d4412f5c42 100644
--- a/storage/innobase/srv/srv0start.cc
+++ b/storage/innobase/srv/srv0start.cc
@@ -1454,6 +1454,7 @@ file_checked:
if (srv_operation == SRV_OPERATION_RESTORE) {
break;
}
+ dict_sys.load_sys_tables();
trx_lists_init_at_db_start();
break;
case SRV_OPERATION_RESTORE_DELTA:
@@ -1796,11 +1797,7 @@ skip_monitors:
}
}
- /* Create the SYS_FOREIGN and SYS_FOREIGN_COLS system tables */
- err = dict_create_or_check_foreign_constraint_tables();
- if (err == DB_SUCCESS) {
- err = dict_create_or_check_sys_virtual();
- }
+ err = dict_sys.create_or_check_sys_tables();
switch (err) {
case DB_SUCCESS:
break;
diff --git a/storage/innobase/trx/trx0roll.cc b/storage/innobase/trx/trx0roll.cc
index fbf78393021..4ccacaff683 100644
--- a/storage/innobase/trx/trx0roll.cc
+++ b/storage/innobase/trx/trx0roll.cc
@@ -703,7 +703,6 @@ static my_bool trx_rollback_recovered_callback(rw_trx_hash_element_t *element,
return 0;
}
-
/**
Rollback any incomplete transactions which were encountered in crash recovery.
diff --git a/storage/innobase/trx/trx0trx.cc b/storage/innobase/trx/trx0trx.cc
index 0ebb4a493b8..353273ac046 100644
--- a/storage/innobase/trx/trx0trx.cc
+++ b/storage/innobase/trx/trx0trx.cc
@@ -2214,16 +2214,3 @@ trx_set_rw_mode(
trx->read_view.set_creator_trx_id(trx->id);
}
}
-
-bool trx_t::has_stats_table_lock() const
-{
- for (lock_list::const_iterator it= lock.table_locks.begin(),
- end= lock.table_locks.end(); it != end; ++it)
- {
- const lock_t *lock= *it;
- if (lock && lock->un_member.tab_lock.table->is_stats_table())
- return true;
- }
-
- return false;
-}