summaryrefslogtreecommitdiff
path: root/storage/innobase/dict
diff options
context:
space:
mode:
Diffstat (limited to 'storage/innobase/dict')
-rw-r--r--storage/innobase/dict/dict0boot.cc109
-rw-r--r--storage/innobase/dict/dict0crea.cc351
-rw-r--r--storage/innobase/dict/dict0defrag_bg.cc6
-rw-r--r--storage/innobase/dict/dict0dict.cc446
-rw-r--r--storage/innobase/dict/dict0load.cc260
-rw-r--r--storage/innobase/dict/dict0mem.cc485
-rw-r--r--storage/innobase/dict/dict0stats.cc100
-rw-r--r--storage/innobase/dict/dict0stats_bg.cc23
8 files changed, 938 insertions, 842 deletions
diff --git a/storage/innobase/dict/dict0boot.cc b/storage/innobase/dict/dict0boot.cc
index 9294cf6263c..87a2fe3f03f 100644
--- a/storage/innobase/dict/dict0boot.cc
+++ b/storage/innobase/dict/dict0boot.cc
@@ -176,10 +176,11 @@ dict_hdr_create(
ulint root_page_no;
ut_ad(mtr);
+ 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(DICT_HDR_SPACE, 0,
+ block = fseg_create(fil_system.sys_space, 0,
DICT_HDR + DICT_HDR_FSEG_HEADER, mtr);
ut_a(DICT_HDR_PAGE_NO == block->page.id.page_no());
@@ -207,8 +208,8 @@ dict_hdr_create(
system tables */
/*--------------------------*/
- root_page_no = btr_create(DICT_CLUSTERED | DICT_UNIQUE, DICT_HDR_SPACE,
- univ_page_size, DICT_TABLES_ID,
+ root_page_no = btr_create(DICT_CLUSTERED | DICT_UNIQUE,
+ fil_system.sys_space, DICT_TABLES_ID,
dict_ind_redundant, NULL, mtr);
if (root_page_no == FIL_NULL) {
@@ -218,8 +219,8 @@ dict_hdr_create(
mlog_write_ulint(dict_header + DICT_HDR_TABLES, root_page_no,
MLOG_4BYTES, mtr);
/*--------------------------*/
- root_page_no = btr_create(DICT_UNIQUE, DICT_HDR_SPACE,
- univ_page_size, DICT_TABLE_IDS_ID,
+ root_page_no = btr_create(DICT_UNIQUE,
+ fil_system.sys_space, DICT_TABLE_IDS_ID,
dict_ind_redundant, NULL, mtr);
if (root_page_no == FIL_NULL) {
@@ -229,8 +230,8 @@ dict_hdr_create(
mlog_write_ulint(dict_header + DICT_HDR_TABLE_IDS, root_page_no,
MLOG_4BYTES, mtr);
/*--------------------------*/
- root_page_no = btr_create(DICT_CLUSTERED | DICT_UNIQUE, DICT_HDR_SPACE,
- univ_page_size, DICT_COLUMNS_ID,
+ root_page_no = btr_create(DICT_CLUSTERED | DICT_UNIQUE,
+ fil_system.sys_space, DICT_COLUMNS_ID,
dict_ind_redundant, NULL, mtr);
if (root_page_no == FIL_NULL) {
@@ -240,8 +241,8 @@ dict_hdr_create(
mlog_write_ulint(dict_header + DICT_HDR_COLUMNS, root_page_no,
MLOG_4BYTES, mtr);
/*--------------------------*/
- root_page_no = btr_create(DICT_CLUSTERED | DICT_UNIQUE, DICT_HDR_SPACE,
- univ_page_size, DICT_INDEXES_ID,
+ root_page_no = btr_create(DICT_CLUSTERED | DICT_UNIQUE,
+ fil_system.sys_space, DICT_INDEXES_ID,
dict_ind_redundant, NULL, mtr);
if (root_page_no == FIL_NULL) {
@@ -251,8 +252,8 @@ dict_hdr_create(
mlog_write_ulint(dict_header + DICT_HDR_INDEXES, root_page_no,
MLOG_4BYTES, mtr);
/*--------------------------*/
- root_page_no = btr_create(DICT_CLUSTERED | DICT_UNIQUE, DICT_HDR_SPACE,
- univ_page_size, DICT_FIELDS_ID,
+ root_page_no = btr_create(DICT_CLUSTERED | DICT_UNIQUE,
+ fil_system.sys_space, DICT_FIELDS_ID,
dict_ind_redundant, NULL, mtr);
if (root_page_no == FIL_NULL) {
@@ -279,7 +280,6 @@ dict_boot(void)
dict_hdr_t* dict_hdr;
mem_heap_t* heap;
mtr_t mtr;
- dberr_t error;
/* Be sure these constants do not ever change. To avoid bloat,
only check the *NUM_FIELDS* in each table */
@@ -328,15 +328,16 @@ dict_boot(void)
/* Insert into the dictionary cache the descriptions of the basic
system tables */
/*-------------------------*/
- table = dict_mem_table_create("SYS_TABLES", DICT_HDR_SPACE, 8, 0, 0, 0);
+ table = dict_mem_table_create("SYS_TABLES", fil_system.sys_space,
+ 8, 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);
/* ROW_FORMAT = (N_COLS >> 31) ? COMPACT : REDUNDANT */
dict_mem_table_add_col(table, heap, "N_COLS", DATA_INT, 0, 4);
- /* The low order bit of TYPE is always set to 1. If the format
- is UNIV_FORMAT_B or higher, this field matches table->flags. */
+ /* The low order bit of TYPE is always set to 1. If ROW_FORMAT
+ is not REDUNDANT or COMPACT, this field matches table->flags. */
dict_mem_table_add_col(table, heap, "TYPE", DATA_INT, 0, 4);
dict_mem_table_add_col(table, heap, "MIX_ID", DATA_BINARY, 0, 0);
/* MIX_LEN may contain additional table flags when
@@ -347,35 +348,35 @@ dict_boot(void)
table->id = DICT_TABLES_ID;
- dict_table_add_to_cache(table, FALSE, heap);
+ dict_table_add_system_columns(table, heap);
+ table->add_to_cache();
dict_sys->sys_tables = table;
mem_heap_empty(heap);
- index = dict_mem_index_create("SYS_TABLES", "CLUST_IND",
- DICT_HDR_SPACE,
+ index = dict_mem_index_create(table, "CLUST_IND",
DICT_UNIQUE | DICT_CLUSTERED, 1);
dict_mem_index_add_field(index, "NAME", 0);
index->id = DICT_TABLES_ID;
-
- error = dict_index_add_to_cache(table, index,
- mach_read_from_4(dict_hdr
- + DICT_HDR_TABLES));
+ dberr_t error = dict_index_add_to_cache(
+ index, mach_read_from_4(dict_hdr + DICT_HDR_TABLES));
ut_a(error == DB_SUCCESS);
+ ut_ad(!table->is_instant());
+ table->indexes.start->n_core_null_bytes = UT_BITS_IN_BYTES(
+ unsigned(table->indexes.start->n_nullable));
/*-------------------------*/
- index = dict_mem_index_create("SYS_TABLES", "ID_IND",
- DICT_HDR_SPACE, DICT_UNIQUE, 1);
+ index = dict_mem_index_create(table, "ID_IND", DICT_UNIQUE, 1);
dict_mem_index_add_field(index, "ID", 0);
index->id = DICT_TABLE_IDS_ID;
error = dict_index_add_to_cache(
- table, index, mach_read_from_4(dict_hdr + DICT_HDR_TABLE_IDS));
+ index, mach_read_from_4(dict_hdr + DICT_HDR_TABLE_IDS));
ut_a(error == DB_SUCCESS);
/*-------------------------*/
- table = dict_mem_table_create("SYS_COLUMNS", DICT_HDR_SPACE,
+ table = dict_mem_table_create("SYS_COLUMNS", fil_system.sys_space,
7, 0, 0, 0);
dict_mem_table_add_col(table, heap, "TABLE_ID", DATA_BINARY, 0, 8);
@@ -388,25 +389,27 @@ dict_boot(void)
table->id = DICT_COLUMNS_ID;
- dict_table_add_to_cache(table, FALSE, heap);
+ dict_table_add_system_columns(table, heap);
+ table->add_to_cache();
dict_sys->sys_columns = table;
mem_heap_empty(heap);
- index = dict_mem_index_create("SYS_COLUMNS", "CLUST_IND",
- DICT_HDR_SPACE,
+ index = dict_mem_index_create(table, "CLUST_IND",
DICT_UNIQUE | DICT_CLUSTERED, 2);
dict_mem_index_add_field(index, "TABLE_ID", 0);
dict_mem_index_add_field(index, "POS", 0);
index->id = DICT_COLUMNS_ID;
- error = dict_index_add_to_cache(table, index,
- mach_read_from_4(dict_hdr
- + DICT_HDR_COLUMNS));
+ error = dict_index_add_to_cache(
+ index, mach_read_from_4(dict_hdr + DICT_HDR_COLUMNS));
ut_a(error == DB_SUCCESS);
+ ut_ad(!table->is_instant());
+ table->indexes.start->n_core_null_bytes = UT_BITS_IN_BYTES(
+ unsigned(table->indexes.start->n_nullable));
/*-------------------------*/
- table = dict_mem_table_create("SYS_INDEXES", DICT_HDR_SPACE,
+ table = dict_mem_table_create("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);
@@ -414,31 +417,43 @@ dict_boot(void)
dict_mem_table_add_col(table, heap, "NAME", DATA_BINARY, 0, 0);
dict_mem_table_add_col(table, heap, "N_FIELDS", DATA_INT, 0, 4);
dict_mem_table_add_col(table, heap, "TYPE", DATA_INT, 0, 4);
+ /* SYS_INDEXES.SPACE is redundant and not being read;
+ SYS_TABLES.SPACE is being used instead. */
dict_mem_table_add_col(table, heap, "SPACE", DATA_INT, 0, 4);
dict_mem_table_add_col(table, heap, "PAGE_NO", DATA_INT, 0, 4);
dict_mem_table_add_col(table, heap, "MERGE_THRESHOLD", DATA_INT, 0, 4);
table->id = DICT_INDEXES_ID;
- dict_table_add_to_cache(table, FALSE, heap);
+ dict_table_add_system_columns(table, heap);
+ /* The column SYS_INDEXES.MERGE_THRESHOLD was "instantly"
+ added in MySQL 5.7 and MariaDB 10.2.2. Assign it DEFAULT NULL.
+ Because of file format compatibility, we must treat SYS_INDEXES
+ as a special case, relaxing some debug assertions
+ for DICT_INDEXES_ID. */
+ dict_table_get_nth_col(table, DICT_COL__SYS_INDEXES__MERGE_THRESHOLD)
+ ->def_val.len = UNIV_SQL_NULL;
+ table->add_to_cache();
dict_sys->sys_indexes = table;
mem_heap_empty(heap);
- index = dict_mem_index_create("SYS_INDEXES", "CLUST_IND",
- DICT_HDR_SPACE,
+ index = dict_mem_index_create(table, "CLUST_IND",
DICT_UNIQUE | DICT_CLUSTERED, 2);
dict_mem_index_add_field(index, "TABLE_ID", 0);
dict_mem_index_add_field(index, "ID", 0);
index->id = DICT_INDEXES_ID;
- error = dict_index_add_to_cache(table, index,
- mach_read_from_4(dict_hdr
- + DICT_HDR_INDEXES));
+ error = dict_index_add_to_cache(
+ index, mach_read_from_4(dict_hdr + DICT_HDR_INDEXES));
ut_a(error == DB_SUCCESS);
+ ut_ad(!table->is_instant());
+ table->indexes.start->n_core_null_bytes = UT_BITS_IN_BYTES(
+ unsigned(table->indexes.start->n_nullable));
/*-------------------------*/
- table = dict_mem_table_create("SYS_FIELDS", DICT_HDR_SPACE, 3, 0, 0, 0);
+ table = dict_mem_table_create("SYS_FIELDS", fil_system.sys_space,
+ 3, 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);
@@ -446,22 +461,24 @@ dict_boot(void)
table->id = DICT_FIELDS_ID;
- dict_table_add_to_cache(table, FALSE, heap);
+ dict_table_add_system_columns(table, heap);
+ table->add_to_cache();
dict_sys->sys_fields = table;
mem_heap_free(heap);
- index = dict_mem_index_create("SYS_FIELDS", "CLUST_IND",
- DICT_HDR_SPACE,
+ index = dict_mem_index_create(table, "CLUST_IND",
DICT_UNIQUE | DICT_CLUSTERED, 2);
dict_mem_index_add_field(index, "INDEX_ID", 0);
dict_mem_index_add_field(index, "POS", 0);
index->id = DICT_FIELDS_ID;
- error = dict_index_add_to_cache(table, index,
- mach_read_from_4(dict_hdr
- + DICT_HDR_FIELDS));
+ error = dict_index_add_to_cache(
+ index, mach_read_from_4(dict_hdr + DICT_HDR_FIELDS));
ut_a(error == DB_SUCCESS);
+ ut_ad(!table->is_instant());
+ table->indexes.start->n_core_null_bytes = UT_BITS_IN_BYTES(
+ unsigned(table->indexes.start->n_nullable));
mtr_commit(&mtr);
diff --git a/storage/innobase/dict/dict0crea.cc b/storage/innobase/dict/dict0crea.cc
index 2976581c19f..fd45aee407d 100644
--- a/storage/innobase/dict/dict0crea.cc
+++ b/storage/innobase/dict/dict0crea.cc
@@ -38,6 +38,7 @@ Created 1/8/1996 Heikki Tuuri
#include "row0mysql.h"
#include "pars0pars.h"
#include "trx0roll.h"
+#include "trx0rseg.h"
#include "trx0undo.h"
#include "ut0vec.h"
#include "dict0priv.h"
@@ -64,7 +65,9 @@ dict_create_sys_tables_tuple(
ulint type;
ut_ad(table);
+ ut_ad(!table->space || table->space->id == table->space_id);
ut_ad(heap);
+ ut_ad(table->n_cols >= DATA_N_SYS_COLS);
sys_tables = dict_sys->sys_tables;
@@ -98,12 +101,11 @@ dict_create_sys_tables_tuple(
/* If there is any virtual column, encode it in N_COLS */
mach_write_to_4(ptr, dict_table_encode_n_col(
- static_cast<ulint>(table->n_def),
- static_cast<ulint>(table->n_v_def))
- | ((table->flags & DICT_TF_COMPACT) << 31));
+ ulint(table->n_cols - DATA_N_SYS_COLS),
+ ulint(table->n_v_def))
+ | (ulint(table->flags & DICT_TF_COMPACT) << 31));
dfield_set_data(dfield, ptr, 4);
-
/* 5: TYPE (table flags) -----------------------------*/
dfield = dtuple_get_nth_field(
entry, DICT_COL__SYS_TABLES__TYPE);
@@ -147,7 +149,7 @@ dict_create_sys_tables_tuple(
entry, DICT_COL__SYS_TABLES__SPACE);
ptr = static_cast<byte*>(mem_heap_alloc(heap, 4));
- mach_write_to_4(ptr, table->space);
+ mach_write_to_4(ptr, table->space_id);
dfield_set_data(dfield, ptr, 4);
/*----------------------------------*/
@@ -190,7 +192,7 @@ dict_create_sys_columns_tuple(
v_col_no = column->ind;
} else {
column = dict_table_get_nth_col(table, i);
- ut_ad(!dict_col_is_virtual(column));
+ ut_ad(!column->is_virtual());
}
sys_columns = dict_sys->sys_columns;
@@ -350,15 +352,12 @@ dict_build_table_def_step(
que_thr_t* thr, /*!< in: query thread */
tab_node_t* node) /*!< in: table create node */
{
- dict_table_t* table;
-
- table = node->table;
- ut_ad(!dict_table_is_temporary(table));
-
- trx_t* trx = thr_get_trx(thr);
- dict_table_assign_new_id(table, trx);
-
ut_ad(mutex_own(&dict_sys->mutex));
+ dict_table_t* table = node->table;
+ ut_ad(!table->is_temporary());
+ ut_ad(!table->space);
+ ut_ad(table->space_id == ULINT_UNDEFINED);
+ dict_table_assign_new_id(table, thr_get_trx(thr));
/* Always set this bit for all new created tables */
DICT_TF2_FLAG_SET(table, DICT_TF2_FTS_AUX_HEX_NAME);
@@ -369,12 +368,12 @@ dict_build_table_def_step(
if (DICT_TF2_FLAG_IS_SET(table, DICT_TF2_USE_FILE_PER_TABLE)) {
/* This table will need a new tablespace. */
- ut_ad(dict_table_get_format(table) <= UNIV_FORMAT_MAX);
ut_ad(DICT_TF_GET_ZIP_SSIZE(table->flags) == 0
- || dict_table_get_format(table) >= UNIV_FORMAT_B);
+ || dict_table_has_atomic_blobs(table));
+ trx_t* trx = thr_get_trx(thr);
ut_ad(trx->table_id);
mtr_t mtr;
- trx_undo_t* undo = trx->rsegs.m_redo.insert_undo;
+ trx_undo_t* undo = trx->rsegs.m_redo.undo;
if (undo && !undo->table_id
&& trx_get_dict_operation(trx) == TRX_DICT_OP_TABLE) {
/* This must be a TRUNCATE operation where
@@ -383,41 +382,43 @@ dict_build_table_def_step(
associated with the new empty table, so that
we can remove it on recovery. */
mtr.start();
- trx_undo_mark_as_dict(trx, undo, &mtr);
+ undo->table_id = trx->table_id;
+ undo->dict_operation = TRUE;
+ page_t* page = trx_undo_page_get(
+ page_id_t(trx->rsegs.m_redo.rseg->space->id,
+ undo->hdr_page_no),
+ &mtr);
+ mlog_write_ulint(page + undo->hdr_offset
+ + TRX_UNDO_DICT_TRANS,
+ TRUE, MLOG_1BYTE, &mtr);
+ mlog_write_ull(page + undo->hdr_offset
+ + TRX_UNDO_TABLE_ID,
+ trx->table_id, &mtr);
mtr.commit();
log_write_up_to(mtr.commit_lsn(), true);
}
- ulint space;
/* Get a new tablespace ID */
- dict_hdr_get_new_id(NULL, NULL, &space, table, false);
+ ulint space_id;
+ dict_hdr_get_new_id(NULL, NULL, &space_id, table, false);
DBUG_EXECUTE_IF(
"ib_create_table_fail_out_of_space_ids",
- space = ULINT_UNDEFINED;
+ space_id = ULINT_UNDEFINED;
);
- if (space == ULINT_UNDEFINED) {
+ if (space_id == ULINT_UNDEFINED) {
return DB_ERROR;
}
- table->space = unsigned(space);
/* Determine the tablespace flags. */
bool has_data_dir = DICT_TF_HAS_DATA_DIR(table->flags);
ulint fsp_flags = dict_tf_to_fsp_flags(table->flags);
- char* filepath;
-
- if (has_data_dir) {
- ut_ad(table->data_dir_path);
- filepath = fil_make_filepath(
- table->data_dir_path,
- table->name.m_name, IBD, true);
-
- } else {
- /* Make the tablespace file in the default dir
- using the table name */
- filepath = fil_make_filepath(
- NULL, table->name.m_name, IBD, false);
- }
+ ut_ad(!has_data_dir || table->data_dir_path);
+ char* filepath = has_data_dir
+ ? fil_make_filepath(table->data_dir_path,
+ table->name.m_name, IBD, true)
+ : fil_make_filepath(NULL,
+ table->name.m_name, IBD, false);
/* We create a new single-table tablespace for the table.
We initially let it be 4 pages:
@@ -427,49 +428,36 @@ dict_build_table_def_step(
- page 3 will contain the root of the clustered index of
the table we create here. */
- dberr_t err = fil_ibd_create(
- space, table->name.m_name, filepath, fsp_flags,
- FIL_IBD_FILE_INITIAL_SIZE, node->mode, node->key_id);
+ dberr_t err;
+ table->space = fil_ibd_create(
+ space_id, table->name.m_name, filepath, fsp_flags,
+ FIL_IBD_FILE_INITIAL_SIZE,
+ node->mode, node->key_id, &err);
ut_free(filepath);
- if (err != DB_SUCCESS) {
+ if (!table->space) {
+ ut_ad(err != DB_SUCCESS);
return err;
}
+ table->space_id = space_id;
mtr.start();
mtr.set_named_space(table->space);
-
fsp_header_init(table->space, FIL_IBD_FILE_INITIAL_SIZE, &mtr);
-
mtr.commit();
} else {
ut_ad(dict_tf_get_rec_format(table->flags)
!= REC_FORMAT_COMPRESSED);
- ut_ad(table->space == srv_sys_space.space_id());
+ table->space = fil_system.sys_space;
+ table->space_id = TRX_SYS_SPACE;
}
ins_node_set_new_row(node->tab_def,
dict_create_sys_tables_tuple(table, node->heap));
-
return DB_SUCCESS;
}
-/***************************************************************//**
-Builds a column definition to insert. */
-static
-void
-dict_build_col_def_step(
-/*====================*/
- tab_node_t* node) /*!< in: table create node */
-{
- dtuple_t* row;
-
- row = dict_create_sys_columns_tuple(node->table, node->col_no,
- node->heap);
- ins_node_set_new_row(node->col_def, row);
-}
-
/** Builds a SYS_VIRTUAL row definition to insert.
@param[in] node table create node */
static
@@ -499,19 +487,19 @@ dict_create_sys_indexes_tuple(
tuple is allocated */
{
dict_table_t* sys_indexes;
- dict_table_t* table;
dtuple_t* entry;
dfield_t* dfield;
byte* ptr;
ut_ad(mutex_own(&dict_sys->mutex));
ut_ad(index);
+ ut_ad(index->table->space || index->table->file_unreadable);
+ ut_ad(!index->table->space
+ || index->table->space->id == index->table->space_id);
ut_ad(heap);
sys_indexes = dict_sys->sys_indexes;
- table = dict_table_get_low(index->table_name);
-
entry = dtuple_create(
heap, DICT_NUM_COLS__SYS_INDEXES + DATA_N_SYS_COLS);
@@ -522,7 +510,7 @@ dict_create_sys_indexes_tuple(
entry, DICT_COL__SYS_INDEXES__TABLE_ID);
ptr = static_cast<byte*>(mem_heap_alloc(heap, 8));
- mach_write_to_8(ptr, table->id);
+ mach_write_to_8(ptr, index->table->id);
dfield_set_data(dfield, ptr, 8);
@@ -576,7 +564,7 @@ dict_create_sys_indexes_tuple(
entry, DICT_COL__SYS_INDEXES__SPACE);
ptr = static_cast<byte*>(mem_heap_alloc(heap, 4));
- mach_write_to_4(ptr, index->space);
+ mach_write_to_4(ptr, index->table->space_id);
dfield_set_data(dfield, ptr, 4);
@@ -744,7 +732,8 @@ dict_build_index_def_step(
index = node->index;
- table = dict_table_get_low(index->table_name);
+ table = index->table = node->table = dict_table_open_on_name(
+ node->table_name, TRUE, FALSE, DICT_ERR_IGNORE_NONE);
if (table == NULL) {
return(DB_TABLE_NOT_FOUND);
@@ -755,8 +744,6 @@ dict_build_index_def_step(
trx->table_id = table->id;
}
- node->table = table;
-
ut_ad((UT_LIST_GET_LEN(table->indexes) > 0)
|| dict_index_is_clust(index));
@@ -765,7 +752,6 @@ dict_build_index_def_step(
/* Inherit the space id from the table; we store all indexes of a
table in the same tablespace */
- index->space = table->space;
node->page_no = FIL_NULL;
row = dict_create_sys_indexes_tuple(index, node->heap);
node->ind_row = row;
@@ -776,6 +762,7 @@ dict_build_index_def_step(
index->trx_id = trx->id;
ut_ad(table->def_trx_id <= trx->id);
table->def_trx_id = trx->id;
+ dict_table_close(table, true, false);
return(DB_SUCCESS);
}
@@ -802,11 +789,6 @@ dict_build_index_def(
dict_hdr_get_new_id(NULL, &index->id, NULL, table, false);
- /* Inherit the space id from the table; we store all indexes of a
- table in the same tablespace */
-
- index->space = table->space;
-
/* Note that the index was created by this transaction. */
index->trx_id = trx->id;
}
@@ -859,14 +841,7 @@ dict_create_index_tree_step(
the index and its root address is written to the index entry in
sys_indexes */
- mtr_start(&mtr);
-
- const bool missing = !index->is_readable()
- || dict_table_is_discarded(index->table);
-
- if (!missing) {
- mtr.set_named_space(index->space);
- }
+ mtr.start();
search_tuple = dict_create_search_tuple(node->ind_row, node->heap);
@@ -879,12 +854,13 @@ dict_create_index_tree_step(
dberr_t err = DB_SUCCESS;
- if (missing) {
+ if (!index->is_readable()) {
node->page_no = FIL_NULL;
} else {
+ index->set_modified(mtr);
+
node->page_no = btr_create(
- index->type, index->space,
- dict_table_page_size(index->table),
+ index->type, index->table->space,
index->id, index, NULL, &mtr);
if (node->page_no == FIL_NULL) {
@@ -905,7 +881,7 @@ dict_create_index_tree_step(
mlog_write_ulint(data, node->page_no, MLOG_4BYTES, &mtr);
}
- mtr_commit(&mtr);
+ mtr.commit();
return(err);
}
@@ -921,7 +897,6 @@ dict_create_index_tree_in_mem(
const trx_t* trx) /*!< in: InnoDB transaction handle */
{
mtr_t mtr;
- ulint page_no;
ut_ad(mutex_own(&dict_sys->mutex));
ut_ad(!(index->type & DICT_FTS));
@@ -929,28 +904,18 @@ dict_create_index_tree_in_mem(
mtr_start(&mtr);
mtr_set_log_mode(&mtr, MTR_LOG_NO_REDO);
- dberr_t err = DB_SUCCESS;
-
/* Currently this function is being used by temp-tables only.
Import/Discard of temp-table is blocked and so this assert. */
ut_ad(index->is_readable());
- ut_ad(!dict_table_is_discarded(index->table));
+ ut_ad(!(index->table->flags2 & DICT_TF2_DISCARDED));
- page_no = btr_create(
- index->type, index->space,
- dict_table_page_size(index->table),
- index->id, index, NULL, &mtr);
+ index->page = btr_create(index->type, index->table->space,
+ index->id, index, NULL, &mtr);
+ mtr_commit(&mtr);
- index->page = page_no;
index->trx_id = trx->id;
- if (page_no == FIL_NULL) {
- err = DB_OUT_OF_FILE_SPACE;
- }
-
- mtr_commit(&mtr);
-
- return(err);
+ return index->page == FIL_NULL ? DB_OUT_OF_FILE_SPACE : DB_SUCCESS;
}
/** Drop the index tree associated with a row in SYS_INDEXES table.
@@ -992,7 +957,6 @@ bool dict_drop_index_tree(rec_t* rec, btr_pcur_t* pcur, trx_t* trx, mtr_t* mtr)
const uint32_t space_id = mach_read_from_4(ptr);
ut_ad(space_id < SRV_TMP_SPACE_ID);
if (space_id != TRX_SYS_SPACE
- && srv_safe_truncate
&& trx_get_dict_operation(trx) == TRX_DICT_OP_TABLE) {
/* We are about to delete the entire .ibd file;
do not bother to free pages inside it. */
@@ -1029,31 +993,6 @@ bool dict_drop_index_tree(rec_t* rec, btr_pcur_t* pcur, trx_t* trx, mtr_t* mtr)
}
/*******************************************************************//**
-Drops the index tree but don't update SYS_INDEXES table. */
-void
-dict_drop_index_tree_in_mem(
-/*========================*/
- const dict_index_t* index, /*!< in: index */
- ulint page_no) /*!< in: index page-no */
-{
- ut_ad(mutex_own(&dict_sys->mutex));
- ut_ad(dict_table_is_temporary(index->table));
-
- ulint root_page_no = page_no;
- ulint space = index->space;
- bool found;
- const page_size_t page_size(fil_space_get_page_size(space,
- &found));
-
- /* If tree has already been freed or it is a single table
- tablespace and the .ibd file is missing do nothing,
- else free the all the pages */
- if (root_page_no != FIL_NULL && found) {
- btr_free(page_id_t(space, root_page_no), page_size);
- }
-}
-
-/*******************************************************************//**
Recreate the index tree associated with a row in SYS_INDEXES table.
@return new root page number, or FIL_NULL on failure */
ulint
@@ -1070,28 +1009,22 @@ dict_recreate_index_tree(
{
ut_ad(mutex_own(&dict_sys->mutex));
ut_a(!dict_table_is_comp(dict_sys->sys_indexes));
+ ut_ad(!table->space || table->space->id == table->space_id);
ulint len;
- rec_t* rec = btr_pcur_get_rec(pcur);
+ const rec_t* rec = btr_pcur_get_rec(pcur);
const byte* ptr = rec_get_nth_field_old(
rec, DICT_FLD__SYS_INDEXES__PAGE_NO, &len);
ut_ad(len == 4);
- ulint root_page_no = mtr_read_ulint(ptr, MLOG_4BYTES, mtr);
-
- ptr = rec_get_nth_field_old(rec, DICT_FLD__SYS_INDEXES__SPACE, &len);
+ ut_ad(table->space_id == mach_read_from_4(
+ rec_get_nth_field_old(rec, DICT_FLD__SYS_INDEXES__SPACE,
+ &len)));
ut_ad(len == 4);
- ut_a(table->space == mtr_read_ulint(ptr, MLOG_4BYTES, mtr));
-
- ulint space = table->space;
- bool found;
- const page_size_t page_size(fil_space_get_page_size(space,
- &found));
-
- if (!found) {
+ if (!table->space) {
/* It is a single table tablespae and the .ibd file is
missing: do nothing. */
@@ -1117,7 +1050,7 @@ dict_recreate_index_tree(
mtr_commit(mtr);
mtr_start(mtr);
- mtr->set_named_space(space);
+ mtr->set_named_space(table->space);
btr_pcur_restore_position(BTR_MODIFY_LEAF, pcur, mtr);
/* Find the index corresponding to this SYS_INDEXES record. */
@@ -1125,15 +1058,12 @@ dict_recreate_index_tree(
index != NULL;
index = UT_LIST_GET_NEXT(indexes, index)) {
if (index->id == index_id) {
- if (index->type & DICT_FTS) {
- return(FIL_NULL);
- } else {
- root_page_no = btr_create(
- type, space, page_size, index_id,
- index, NULL, mtr);
- index->page = (unsigned int) root_page_no;
- return(root_page_no);
- }
+ ulint root_page_no = (index->type & DICT_FTS)
+ ? FIL_NULL
+ : btr_create(type, table->space,
+ index_id, index, NULL, mtr);
+ index->page = unsigned(root_page_no);
+ return root_page_no;
}
}
@@ -1143,73 +1073,6 @@ dict_recreate_index_tree(
return(FIL_NULL);
}
-/*******************************************************************//**
-Truncates the index tree but don't update SYSTEM TABLES.
-@return DB_SUCCESS or error */
-dberr_t
-dict_truncate_index_tree_in_mem(
-/*============================*/
- dict_index_t* index) /*!< in/out: index */
-{
- mtr_t mtr;
- bool truncate;
- ulint space = index->space;
-
- ut_ad(mutex_own(&dict_sys->mutex));
- ut_ad(dict_table_is_temporary(index->table));
-
- ulint type = index->type;
- ulint root_page_no = index->page;
-
- if (root_page_no == FIL_NULL) {
-
- /* The tree has been freed. */
- ib::warn() << "Trying to TRUNCATE a missing index of table "
- << index->table->name << "!";
-
- truncate = false;
- } else {
- truncate = true;
- }
-
- bool found;
- const page_size_t page_size(fil_space_get_page_size(space,
- &found));
-
- if (!found) {
-
- /* It is a single table tablespace and the .ibd file is
- missing: do nothing */
-
- ib::warn()
- << "Trying to TRUNCATE a missing .ibd file of table "
- << index->table->name << "!";
- }
-
- /* If table to truncate resides in its on own tablespace that will
- be re-created on truncate then we can ignore freeing of existing
- tablespace objects. */
-
- if (truncate) {
- btr_free(page_id_t(space, root_page_no), page_size);
- }
-
- mtr_start(&mtr);
- mtr_set_log_mode(&mtr, MTR_LOG_NO_REDO);
-
- root_page_no = btr_create(
- type, space, page_size, index->id, index, NULL, &mtr);
-
- DBUG_EXECUTE_IF("ib_err_trunc_temp_recreate_index",
- root_page_no = FIL_NULL;);
-
- index->page = root_page_no;
-
- mtr_commit(&mtr);
-
- return(index->page == FIL_NULL ? DB_ERROR : DB_SUCCESS);
-}
-
/*********************************************************************//**
Creates a table create graph.
@return own: table create node */
@@ -1253,6 +1116,7 @@ tab_create_graph_create(
/** Creates an index create graph.
@param[in] index index to create, built as a memory data structure
+@param[in] table table name
@param[in,out] heap heap where created
@param[in] add_v new virtual columns added in the same clause with
add index
@@ -1260,6 +1124,7 @@ tab_create_graph_create(
ind_node_t*
ind_create_graph_create(
dict_index_t* index,
+ const char* table,
mem_heap_t* heap,
const dict_add_v_col_t* add_v)
{
@@ -1272,6 +1137,8 @@ ind_create_graph_create(
node->index = index;
+ node->table_name = table;
+
node->add_v = add_v;
node->state = INDEX_BUILD_INDEX_DEF;
@@ -1334,12 +1201,19 @@ dict_create_table_step(
if (node->state == TABLE_BUILD_COL_DEF) {
- if (node->col_no < (static_cast<ulint>(node->table->n_def)
- + static_cast<ulint>(node->table->n_v_def))) {
+ if (node->col_no + DATA_N_SYS_COLS
+ < (static_cast<ulint>(node->table->n_def)
+ + static_cast<ulint>(node->table->n_v_def))) {
- dict_build_col_def_step(node);
+ ulint i = node->col_no++;
+ if (i + DATA_N_SYS_COLS >= node->table->n_def) {
+ i += DATA_N_SYS_COLS;
+ }
- node->col_no++;
+ ins_node_set_new_row(
+ node->col_def,
+ dict_create_sys_columns_tuple(node->table, i,
+ node->heap));
thr->run_node = node->col_def;
@@ -1397,7 +1271,8 @@ dict_create_table_step(
if (node->state == TABLE_ADD_TO_CACHE) {
DBUG_EXECUTE_IF("ib_ddl_crash_during_create", DBUG_SUICIDE(););
- dict_table_add_to_cache(node->table, TRUE, node->heap);
+ node->table->can_be_evicted = true;
+ node->table->add_to_cache();
err = DB_SUCCESS;
}
@@ -1482,16 +1357,25 @@ dict_create_index_step(
}
if (node->state == INDEX_ADD_TO_CACHE) {
- err = dict_index_add_to_cache(
- node->table, node->index, FIL_NULL, node->add_v);
+ ut_ad(node->index->table == node->table);
+ err = dict_index_add_to_cache(node->index, FIL_NULL,
+ node->add_v);
ut_ad((node->index == NULL) == (err != DB_SUCCESS));
- if (err != DB_SUCCESS) {
-
+ if (!node->index) {
goto function_exit;
}
+ ut_ad(!node->index->is_instant());
+ ut_ad(node->index->n_core_null_bytes
+ == ((dict_index_is_clust(node->index)
+ && node->table->supports_instant())
+ ? dict_index_t::NO_CORE_NULL_BYTES
+ : UT_BITS_IN_BYTES(
+ unsigned(node->index->n_nullable))));
+ node->index->n_core_null_bytes = UT_BITS_IN_BYTES(
+ unsigned(node->index->n_nullable));
node->state = INDEX_CREATE_INDEX_TREE;
}
@@ -1646,7 +1530,7 @@ dict_create_or_check_foreign_constraint_tables(void)
return(DB_READ_ONLY);
}
- trx = trx_allocate_for_mysql();
+ trx = trx_create();
trx_set_dict_operation(trx, TRX_DICT_OP_TABLE);
@@ -1739,7 +1623,7 @@ dict_create_or_check_foreign_constraint_tables(void)
row_mysql_unlock_data_dictionary(trx);
- trx_free_for_mysql(trx);
+ trx_free(trx);
srv_file_per_table = srv_file_per_table_backup;
@@ -1785,7 +1669,7 @@ dict_create_or_check_sys_virtual()
return(DB_READ_ONLY);
}
- trx = trx_allocate_for_mysql();
+ trx = trx_create();
trx_set_dict_operation(trx, TRX_DICT_OP_TABLE);
@@ -1840,7 +1724,7 @@ dict_create_or_check_sys_virtual()
row_mysql_unlock_data_dictionary(trx);
- trx_free_for_mysql(trx);
+ trx_free(trx);
srv_file_per_table = srv_file_per_table_backup;
@@ -2079,7 +1963,8 @@ dict_create_add_foreign_to_dictionary(
foreign->referenced_table_name);
pars_info_add_int4_literal(info, "n_cols",
- foreign->n_fields + (foreign->type << 24));
+ ulint(foreign->n_fields)
+ | (ulint(foreign->type) << 24));
DBUG_PRINT("dict_create_add_foreign_to_dictionary",
("'%s', '%s', '%s', %d", foreign->id, name,
@@ -2311,7 +2196,7 @@ dict_create_or_check_sys_tablespace(void)
return(DB_READ_ONLY);
}
- trx = trx_allocate_for_mysql();
+ trx = trx_create();
trx_set_dict_operation(trx, TRX_DICT_OP_TABLE);
@@ -2372,7 +2257,7 @@ dict_create_or_check_sys_tablespace(void)
row_mysql_unlock_data_dictionary(trx);
- trx_free_for_mysql(trx);
+ trx_free(trx);
srv_file_per_table = srv_file_per_table_backup;
diff --git a/storage/innobase/dict/dict0defrag_bg.cc b/storage/innobase/dict/dict0defrag_bg.cc
index 73f55cc8667..7c6f5d75b5d 100644
--- a/storage/innobase/dict/dict0defrag_bg.cc
+++ b/storage/innobase/dict/dict0defrag_bg.cc
@@ -281,11 +281,11 @@ dict_stats_save_defrag_stats(
mtr_t mtr;
ulint n_leaf_pages;
ulint n_leaf_reserved;
- mtr_start(&mtr);
- mtr_s_lock(dict_index_get_lock(index), &mtr);
+ mtr.start();
+ mtr_s_lock_index(index, &mtr);
n_leaf_reserved = btr_get_size_and_reserved(index, BTR_N_LEAF_PAGES,
&n_leaf_pages, &mtr);
- mtr_commit(&mtr);
+ mtr.commit();
if (n_leaf_reserved == ULINT_UNDEFINED) {
// The index name is different during fast index creation,
diff --git a/storage/innobase/dict/dict0dict.cc b/storage/innobase/dict/dict0dict.cc
index 5fb6f676e80..93a86b29af0 100644
--- a/storage/innobase/dict/dict0dict.cc
+++ b/storage/innobase/dict/dict0dict.cc
@@ -118,14 +118,12 @@ static bool innodb_index_stats_not_found_reported = false;
/*******************************************************************//**
Tries to find column names for the index and sets the col field of the
index.
-@param[in] table table
@param[in] index index
@param[in] add_v new virtual columns added along with an add index call
-@return TRUE if the column names were found */
+@return whether the column names were found */
static
-ibool
+bool
dict_index_find_cols(
- const dict_table_t* table,
dict_index_t* index,
const dict_add_v_col_t* add_v);
/*******************************************************************//**
@@ -136,7 +134,6 @@ static
dict_index_t*
dict_index_build_internal_clust(
/*============================*/
- const dict_table_t* table, /*!< in: table */
dict_index_t* index); /*!< in: user representation of
a clustered index */
/*******************************************************************//**
@@ -147,7 +144,6 @@ static
dict_index_t*
dict_index_build_internal_non_clust(
/*================================*/
- const dict_table_t* table, /*!< in: table */
dict_index_t* index); /*!< in: user representation of
a non-clustered index */
/**********************************************************************//**
@@ -157,7 +153,6 @@ static
dict_index_t*
dict_index_build_internal_fts(
/*==========================*/
- dict_table_t* table, /*!< in: table */
dict_index_t* index); /*!< in: user representation of an FTS index */
/**********************************************************************//**
@@ -249,7 +244,7 @@ dict_get_db_name_len(
const char* s;
s = strchr(name, '/');
ut_a(s);
- return(s - name);
+ return ulint(s - name);
}
/** Reserve the dictionary system mutex. */
@@ -420,7 +415,7 @@ dict_table_try_drop_aborted(
{
trx_t* trx;
- trx = trx_allocate_for_background();
+ trx = trx_create();
trx->op_info = "try to drop any indexes after an aborted index creation";
row_mysql_lock_data_dictionary(trx);
trx_set_dict_operation(trx, TRX_DICT_OP_INDEX);
@@ -443,7 +438,7 @@ dict_table_try_drop_aborted(
}
row_mysql_unlock_data_dictionary(trx);
- trx_free_for_background(trx);
+ trx_free(trx);
}
/**********************************************************************//**
@@ -611,26 +606,28 @@ dict_table_has_column(
return(col_max);
}
-/**********************************************************************//**
-Returns a column's name.
-@return column name. NOTE: not guaranteed to stay valid if table is
-modified in any way (columns added, etc.). */
-const char*
-dict_table_get_col_name(
-/*====================*/
- const dict_table_t* table, /*!< in: table */
- ulint col_nr) /*!< in: column number */
+/** Retrieve the column name.
+@param[in] table the table of this column */
+const char* dict_col_t::name(const dict_table_t& table) const
{
- ulint i;
- const char* s;
+ ut_ad(table.magic_n == DICT_TABLE_MAGIC_N);
- ut_ad(table);
- ut_ad(col_nr < table->n_def);
- ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
+ size_t col_nr;
+ const char *s;
+
+ if (is_virtual()) {
+ col_nr = size_t(reinterpret_cast<const dict_v_col_t*>(this)
+ - table.v_cols);
+ ut_ad(col_nr < table.n_v_def);
+ s = table.v_col_names;
+ } else {
+ col_nr = size_t(this - table.cols);
+ ut_ad(col_nr < table.n_def);
+ s = table.col_names;
+ }
- s = table->col_names;
if (s) {
- for (i = 0; i < col_nr; i++) {
+ for (size_t i = 0; i < col_nr; i++) {
s += strlen(s) + 1;
}
}
@@ -890,7 +887,7 @@ dict_index_get_nth_col_or_prefix_pos(
@param[in] n column number
@param[in] is_virtual whether it is a virtual col
@return TRUE if contains the column or its prefix */
-ibool
+bool
dict_index_contains_col_or_prefix(
const dict_index_t* index,
ulint n,
@@ -921,11 +918,11 @@ dict_index_contains_col_or_prefix(
if (col == field->col) {
- return(TRUE);
+ return(true);
}
}
- return(FALSE);
+ return(false);
}
/********************************************************************//**
@@ -1098,7 +1095,7 @@ dict_init(void)
&dict_operation_lock, SYNC_DICT_OPERATION);
if (!srv_read_only_mode) {
- dict_foreign_err_file = os_file_create_tmpfile(NULL);
+ dict_foreign_err_file = os_file_create_tmpfile();
ut_a(dict_foreign_err_file);
}
@@ -1235,65 +1232,46 @@ dict_table_add_system_columns(
DATA_ROW_ID | DATA_NOT_NULL,
DATA_ROW_ID_LEN);
-#if DATA_ROW_ID != 0
-#error "DATA_ROW_ID != 0"
-#endif
+ compile_time_assert(DATA_ROW_ID == 0);
dict_mem_table_add_col(table, heap, "DB_TRX_ID", DATA_SYS,
DATA_TRX_ID | DATA_NOT_NULL,
DATA_TRX_ID_LEN);
-#if DATA_TRX_ID != 1
-#error "DATA_TRX_ID != 1"
-#endif
-
+ compile_time_assert(DATA_TRX_ID == 1);
dict_mem_table_add_col(table, heap, "DB_ROLL_PTR", DATA_SYS,
DATA_ROLL_PTR | DATA_NOT_NULL,
DATA_ROLL_PTR_LEN);
-#if DATA_ROLL_PTR != 2
-#error "DATA_ROLL_PTR != 2"
-#endif
+ compile_time_assert(DATA_ROLL_PTR == 2);
/* This check reminds that if a new system column is added to
the program, it should be dealt with here */
-#if DATA_N_SYS_COLS != 3
-#error "DATA_N_SYS_COLS != 3"
-#endif
+ compile_time_assert(DATA_N_SYS_COLS == 3);
}
-/**********************************************************************//**
-Adds a table object to the dictionary cache. */
+/** Add the table definition to the data dictionary cache */
void
-dict_table_add_to_cache(
-/*====================*/
- dict_table_t* table, /*!< in: table */
- bool can_be_evicted, /*!< in: whether can be evicted */
- mem_heap_t* heap) /*!< in: temporary heap */
+dict_table_t::add_to_cache()
{
- ulint fold;
- ulint id_fold;
-
ut_ad(dict_lru_validate());
ut_ad(mutex_own(&dict_sys->mutex));
- dict_table_add_system_columns(table, heap);
-
- table->cached = TRUE;
+ cached = TRUE;
- fold = ut_fold_string(table->name.m_name);
- id_fold = ut_fold_ull(table->id);
+ ulint fold = ut_fold_string(name.m_name);
+ ulint id_fold = ut_fold_ull(id);
/* Look for a table with the same name: error if such exists */
{
dict_table_t* table2;
HASH_SEARCH(name_hash, dict_sys->table_hash, fold,
dict_table_t*, table2, ut_ad(table2->cached),
- !strcmp(table2->name.m_name, table->name.m_name));
+ !strcmp(table2->name.m_name, name.m_name));
ut_a(table2 == NULL);
#ifdef UNIV_DEBUG
/* Look for the same table pointer with a different name */
HASH_SEARCH_ALL(name_hash, dict_sys->table_hash,
dict_table_t*, table2, ut_ad(table2->cached),
- table2 == table);
+ table2 == this);
ut_ad(table2 == NULL);
#endif /* UNIV_DEBUG */
}
@@ -1303,32 +1281,30 @@ dict_table_add_to_cache(
dict_table_t* table2;
HASH_SEARCH(id_hash, dict_sys->table_id_hash, id_fold,
dict_table_t*, table2, ut_ad(table2->cached),
- table2->id == table->id);
+ table2->id == id);
ut_a(table2 == NULL);
#ifdef UNIV_DEBUG
/* Look for the same table pointer with a different id */
HASH_SEARCH_ALL(id_hash, dict_sys->table_id_hash,
dict_table_t*, table2, ut_ad(table2->cached),
- table2 == table);
+ table2 == this);
ut_ad(table2 == NULL);
#endif /* UNIV_DEBUG */
}
/* Add table to hash table of tables */
HASH_INSERT(dict_table_t, name_hash, dict_sys->table_hash, fold,
- table);
+ this);
/* Add table to hash table of tables based on table id */
HASH_INSERT(dict_table_t, id_hash, dict_sys->table_id_hash, id_fold,
- table);
+ this);
- table->can_be_evicted = can_be_evicted;
-
- if (table->can_be_evicted) {
- UT_LIST_ADD_FIRST(dict_sys->table_LRU, table);
+ if (can_be_evicted) {
+ UT_LIST_ADD_FIRST(dict_sys->table_LRU, this);
} else {
- UT_LIST_ADD_FIRST(dict_sys->table_non_LRU, table);
+ UT_LIST_ADD_FIRST(dict_sys->table_non_LRU, this);
}
ut_ad(dict_lru_validate());
@@ -1625,7 +1601,6 @@ dict_table_rename_in_cache(
{
dberr_t err;
dict_foreign_t* foreign;
- dict_index_t* index;
ulint fold;
char old_name[MAX_FULL_NAME_LEN + 1];
os_file_type_t ftype;
@@ -1657,12 +1632,12 @@ dict_table_rename_in_cache(
/* If the table is stored in a single-table tablespace, rename the
.ibd file and rebuild the .isl file if needed. */
- if (dict_table_is_discarded(table)) {
+ if (!table->space) {
bool exists;
char* filepath;
ut_ad(dict_table_is_file_per_table(table));
- ut_ad(!dict_table_is_temporary(table));
+ ut_ad(!table->is_temporary());
/* Make sure the data_dir_path is set. */
dict_get_and_save_data_dir_path(table, true);
@@ -1682,8 +1657,7 @@ dict_table_rename_in_cache(
return(DB_OUT_OF_MEMORY);
}
- fil_delete_tablespace(table->space,
- dict_table_is_discarded(table));
+ fil_delete_tablespace(table->space_id, !table->space);
/* Delete any temp file hanging around. */
if (os_file_status(filepath, &exists, &ftype)
@@ -1696,10 +1670,11 @@ dict_table_rename_in_cache(
ut_free(filepath);
} else if (dict_table_is_file_per_table(table)) {
- char* new_path = NULL;
- char* old_path = fil_space_get_first_path(table->space);
+ char* new_path;
+ const char* old_path = UT_LIST_GET_FIRST(table->space->chain)
+ ->name;
- ut_ad(!dict_table_is_temporary(table));
+ ut_ad(!table->is_temporary());
if (DICT_TF_HAS_DATA_DIR(table->flags)) {
new_path = os_file_make_new_pathname(
@@ -1709,7 +1684,6 @@ dict_table_rename_in_cache(
if (err != DB_SUCCESS) {
ut_free(new_path);
- ut_free(old_path);
return(DB_TABLESPACE_EXISTS);
}
} else {
@@ -1718,32 +1692,19 @@ dict_table_rename_in_cache(
}
/* New filepath must not exist. */
- err = fil_rename_tablespace_check(
- table->space, old_path, new_path, false,
- replace_new_file);
- if (err != DB_SUCCESS) {
- ut_free(old_path);
- ut_free(new_path);
- return(err);
- }
-
- fil_name_write_rename(table->space, old_path, new_path);
-
- bool success = fil_rename_tablespace(
- table->space, old_path, new_name, new_path);
-
- ut_free(old_path);
+ err = table->space->rename(new_name, new_path, true,
+ replace_new_file);
ut_free(new_path);
/* If the tablespace is remote, a new .isl file was created
If success, delete the old one. If not, delete the new one. */
if (DICT_TF_HAS_DATA_DIR(table->flags)) {
RemoteDatafile::delete_link_file(
- success ? old_name : new_name);
+ err == DB_SUCCESS ? old_name : new_name);
}
- if (!success) {
- return(DB_ERROR);
+ if (err != DB_SUCCESS) {
+ return err;
}
}
@@ -1766,14 +1727,6 @@ dict_table_rename_in_cache(
HASH_INSERT(dict_table_t, name_hash, dict_sys->table_hash, fold,
table);
- /* Update the table_name field in indexes */
- for (index = dict_table_get_first_index(table);
- index != NULL;
- index = dict_table_get_next_index(index)) {
-
- index->table_name = table->name.m_name;
- }
-
if (!rename_also_foreigns) {
/* In ALTER TABLE we think of the rename table operation
in the direction table -> temporary table (#sql...)
@@ -2112,7 +2065,7 @@ dict_table_remove_from_cache_low(
/* When evicting the table definition,
drop the orphan indexes from the data dictionary
and free the index pages. */
- trx_t* trx = trx_allocate_for_background();
+ trx_t* trx = trx_create();
ut_ad(mutex_own(&dict_sys->mutex));
ut_ad(rw_lock_own(&dict_operation_lock, RW_LOCK_X));
@@ -2124,7 +2077,7 @@ dict_table_remove_from_cache_low(
row_merge_drop_indexes_dict(trx, table->id);
trx_commit_for_mysql(trx);
trx->dict_operation_lock_mode = 0;
- trx_free_for_background(trx);
+ trx_free(trx);
}
/* Free virtual column template if any */
@@ -2163,19 +2116,13 @@ dict_col_name_is_reserved(
/*======================*/
const char* name) /*!< in: column name */
{
- /* This check reminds that if a new system column is added to
- the program, it should be dealt with here. */
-#if DATA_N_SYS_COLS != 3
-#error "DATA_N_SYS_COLS != 3"
-#endif
-
static const char* reserved_names[] = {
"DB_ROW_ID", "DB_TRX_ID", "DB_ROLL_PTR"
};
- ulint i;
+ compile_time_assert(UT_ARR_SIZE(reserved_names) == DATA_N_SYS_COLS);
- for (i = 0; i < UT_ARR_SIZE(reserved_names); i++) {
+ for (ulint i = 0; i < UT_ARR_SIZE(reserved_names); i++) {
if (innobase_strcasecmp(name, reserved_names[i]) == 0) {
return(TRUE);
@@ -2188,8 +2135,8 @@ dict_col_name_is_reserved(
/** Clears the virtual column's index list before index is
being freed.
@param[in] index Index being freed */
-void
-dict_index_remove_from_v_col_list(dict_index_t* index) {
+void dict_index_remove_from_v_col_list(dict_index_t* index)
+{
/* Index is not completely formed */
if (!index->cached) {
return;
@@ -2225,7 +2172,6 @@ dict_index_remove_from_v_col_list(dict_index_t* index) {
/** Adds an index to the dictionary cache, with possible indexing newly
added column.
-@param[in,out] table table on which the index is
@param[in,out] index index; NOTE! The index memory
object is freed in this function!
@param[in] page_no root page number of the index
@@ -2233,7 +2179,6 @@ added column.
@return DB_SUCCESS, or DB_CORRUPTION */
dberr_t
dict_index_add_to_cache(
- dict_table_t* table,
dict_index_t*& index,
ulint page_no,
const dict_add_v_col_t* add_v)
@@ -2250,9 +2195,10 @@ dict_index_add_to_cache(
ut_d(mem_heap_validate(index->heap));
ut_a(!dict_index_is_clust(index)
- || UT_LIST_GET_LEN(table->indexes) == 0);
+ || UT_LIST_GET_LEN(index->table->indexes) == 0);
+ ut_ad(dict_index_is_clust(index) || !index->table->no_rollback());
- if (!dict_index_find_cols(table, index, add_v)) {
+ if (!dict_index_find_cols(index, add_v)) {
dict_mem_index_free(index);
index = NULL;
@@ -2262,12 +2208,14 @@ dict_index_add_to_cache(
/* Build the cache internal representation of the index,
containing also the added system fields */
- if (index->type == DICT_FTS) {
- new_index = dict_index_build_internal_fts(table, index);
- } else if (dict_index_is_clust(index)) {
- new_index = dict_index_build_internal_clust(table, index);
+ if (dict_index_is_clust(index)) {
+ new_index = dict_index_build_internal_clust(index);
} else {
- new_index = dict_index_build_internal_non_clust(table, index);
+ new_index = (index->type & DICT_FTS)
+ ? dict_index_build_internal_fts(index)
+ : dict_index_build_internal_non_clust(index);
+ new_index->n_core_null_bytes = UT_BITS_IN_BYTES(
+ unsigned(new_index->n_nullable));
}
/* Set the n_fields value in new_index to the actual defined
@@ -2339,9 +2287,7 @@ dict_index_add_to_cache(
/* Add the new index as the last index for the table */
- UT_LIST_ADD_LAST(table->indexes, new_index);
- new_index->table = table;
- new_index->table_name = table->name.m_name;
+ UT_LIST_ADD_LAST(new_index->table->indexes, new_index);
#ifdef BTR_CUR_ADAPT
new_index->search_info = btr_search_info_create(new_index->heap);
#endif /* BTR_CUR_ADAPT */
@@ -2350,6 +2296,8 @@ dict_index_add_to_cache(
rw_lock_create(index_tree_rw_lock_key, &new_index->lock,
SYNC_INDEX_TREE);
+ new_index->n_core_fields = new_index->n_fields;
+
dict_mem_index_free(index);
index = new_index;
return DB_SUCCESS;
@@ -2436,18 +2384,17 @@ index.
@param[in] table table
@param[in,out] index index
@param[in] add_v new virtual columns added along with an add index call
-@return TRUE if the column names were found */
+@return whether the column names were found */
static
-ibool
+bool
dict_index_find_cols(
- const dict_table_t* table,
dict_index_t* index,
const dict_add_v_col_t* add_v)
{
std::vector<ulint, ut_allocator<ulint> > col_added;
std::vector<ulint, ut_allocator<ulint> > v_col_added;
- ut_ad(table != NULL && index != NULL);
+ const dict_table_t* table = index->table;
ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
ut_ad(mutex_own(&dict_sys->mutex));
@@ -2545,7 +2492,7 @@ dict_index_add_col(
dict_field_t* field;
const char* col_name;
- if (dict_col_is_virtual(col)) {
+ if (col->is_virtual()) {
dict_v_col_t* v_col = reinterpret_cast<dict_v_col_t*>(col);
/* When v_col->v_indexes==NULL,
@@ -2555,11 +2502,8 @@ dict_index_add_col(
if (v_col->v_indexes != NULL) {
/* Register the index with the virtual column index
list */
- struct dict_v_idx_t new_idx
- = {index, index->n_def};
-
- v_col->v_indexes->push_back(new_idx);
-
+ v_col->v_indexes->push_back(
+ dict_v_idx_t(index, index->n_def));
}
col_name = dict_table_get_v_col_name_mysql(
@@ -2570,7 +2514,7 @@ dict_index_add_col(
dict_mem_index_add_field(index, col_name, prefix_len);
- field = dict_index_get_nth_field(index, index->n_def - 1);
+ field = dict_index_get_nth_field(index, unsigned(index->n_def) - 1);
field->col = col;
field->fixed_len = static_cast<unsigned int>(
@@ -2588,12 +2532,11 @@ dict_index_add_col(
if (field->fixed_len > DICT_MAX_FIXED_COL_LEN) {
field->fixed_len = 0;
}
-#if DICT_MAX_FIXED_COL_LEN != 768
+
/* The comparison limit above must be constant. If it were
changed, the disk format of some fixed-length columns would
change, which would be a disaster. */
-# error "DICT_MAX_FIXED_COL_LEN != 768"
-#endif
+ compile_time_assert(DICT_MAX_FIXED_COL_LEN == 768);
if (!(col->prtype & DATA_NOT_NULL)) {
index->n_nullable++;
@@ -2607,8 +2550,7 @@ void
dict_index_copy(
/*============*/
dict_index_t* index1, /*!< in: index to copy to */
- dict_index_t* index2, /*!< in: index to copy from */
- const dict_table_t* table, /*!< in: table */
+ const dict_index_t* index2, /*!< in: index to copy from */
ulint start, /*!< in: first position to copy */
ulint end) /*!< in: last position to copy */
{
@@ -2621,7 +2563,7 @@ dict_index_copy(
field = dict_index_get_nth_field(index2, i);
- dict_index_add_col(index1, table, field->col,
+ dict_index_add_col(index1, index2->table, field->col,
field->prefix_len);
}
}
@@ -2718,28 +2660,26 @@ static
dict_index_t*
dict_index_build_internal_clust(
/*============================*/
- const dict_table_t* table, /*!< in: table */
dict_index_t* index) /*!< in: user representation of
a clustered index */
{
+ dict_table_t* table = index->table;
dict_index_t* new_index;
dict_field_t* field;
ulint trx_id_pos;
ulint i;
ibool* indexed;
- ut_ad(table && index);
ut_ad(dict_index_is_clust(index));
ut_ad(!dict_index_is_ibuf(index));
ut_ad(mutex_own(&dict_sys->mutex));
- ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
/* Create a new index object with certainly enough fields */
- new_index = dict_mem_index_create(table->name.m_name,
- index->name, table->space,
+ new_index = dict_mem_index_create(index->table, index->name,
index->type,
- index->n_fields + table->n_cols);
+ unsigned(index->n_fields
+ + table->n_cols));
/* Copy other relevant data from the old index struct to the new
struct: it inherits the values */
@@ -2749,7 +2689,7 @@ dict_index_build_internal_clust(
new_index->id = index->id;
/* Copy the fields of index */
- dict_index_copy(new_index, index, table, 0, index->n_fields);
+ dict_index_copy(new_index, index, 0, index->n_fields);
if (dict_index_is_unique(index)) {
/* Only the fields defined so far are needed to identify
@@ -2758,7 +2698,7 @@ dict_index_build_internal_clust(
new_index->n_uniq = new_index->n_def;
} else {
/* Also the row id is needed to identify the entry */
- new_index->n_uniq = 1 + new_index->n_def;
+ new_index->n_uniq = 1 + unsigned(new_index->n_def);
}
new_index->trx_id_offset = 0;
@@ -2767,15 +2707,9 @@ dict_index_build_internal_clust(
trx_id_pos = new_index->n_def;
-#if DATA_ROW_ID != 0
-# error "DATA_ROW_ID != 0"
-#endif
-#if DATA_TRX_ID != 1
-# error "DATA_TRX_ID != 1"
-#endif
-#if DATA_ROLL_PTR != 2
-# error "DATA_ROLL_PTR != 2"
-#endif
+ compile_time_assert(DATA_ROW_ID == 0);
+ compile_time_assert(DATA_TRX_ID == 1);
+ compile_time_assert(DATA_ROLL_PTR == 2);
if (!dict_index_is_unique(index)) {
dict_index_add_col(new_index, table,
@@ -2862,6 +2796,9 @@ dict_index_build_internal_clust(
ut_ad(UT_LIST_GET_LEN(table->indexes) == 0);
+ new_index->n_core_null_bytes = table->supports_instant()
+ ? dict_index_t::NO_CORE_NULL_BYTES
+ : UT_BITS_IN_BYTES(unsigned(new_index->n_nullable));
new_index->cached = TRUE;
return(new_index);
@@ -2875,13 +2812,13 @@ static
dict_index_t*
dict_index_build_internal_non_clust(
/*================================*/
- const dict_table_t* table, /*!< in: table */
dict_index_t* index) /*!< in: user representation of
a non-clustered index */
{
dict_field_t* field;
dict_index_t* new_index;
dict_index_t* clust_index;
+ dict_table_t* table = index->table;
ulint i;
ibool* indexed;
@@ -2889,7 +2826,6 @@ dict_index_build_internal_non_clust(
ut_ad(!dict_index_is_clust(index));
ut_ad(!dict_index_is_ibuf(index));
ut_ad(mutex_own(&dict_sys->mutex));
- ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
/* The clustered index should be the first in the list of indexes */
clust_index = UT_LIST_GET_FIRST(table->indexes);
@@ -2900,8 +2836,8 @@ dict_index_build_internal_non_clust(
/* Create a new index */
new_index = dict_mem_index_create(
- table->name.m_name, index->name, index->space, index->type,
- index->n_fields + 1 + clust_index->n_uniq);
+ index->table, index->name, index->type,
+ ulint(index->n_fields + 1 + clust_index->n_uniq));
/* Copy other relevant data from the old index
struct to the new struct: it inherits the values */
@@ -2911,7 +2847,7 @@ dict_index_build_internal_non_clust(
new_index->id = index->id;
/* Copy fields from index to new_index */
- dict_index_copy(new_index, index, table, 0, index->n_fields);
+ dict_index_copy(new_index, index, 0, index->n_fields);
/* Remember the table columns already contained in new_index */
indexed = static_cast<ibool*>(
@@ -2922,7 +2858,7 @@ dict_index_build_internal_non_clust(
field = dict_index_get_nth_field(new_index, i);
- if (dict_col_is_virtual(field->col)) {
+ if (field->col->is_virtual()) {
continue;
}
@@ -2978,20 +2914,16 @@ static
dict_index_t*
dict_index_build_internal_fts(
/*==========================*/
- dict_table_t* table, /*!< in: table */
dict_index_t* index) /*!< in: user representation of an FTS index */
{
dict_index_t* new_index;
- ut_ad(table && index);
ut_ad(index->type == DICT_FTS);
ut_ad(mutex_own(&dict_sys->mutex));
- ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
/* Create a new index */
- new_index = dict_mem_index_create(
- table->name.m_name, index->name, index->space, index->type,
- index->n_fields);
+ new_index = dict_mem_index_create(index->table, index->name,
+ index->type, index->n_fields);
/* Copy other relevant data from the old index struct to the new
struct: it inherits the values */
@@ -3001,11 +2933,13 @@ dict_index_build_internal_fts(
new_index->id = index->id;
/* Copy fields from index to new_index */
- dict_index_copy(new_index, index, table, 0, index->n_fields);
+ dict_index_copy(new_index, index, 0, index->n_fields);
new_index->n_uniq = 0;
new_index->cached = TRUE;
+ dict_table_t* table = index->table;
+
if (table->fts->cache == NULL) {
table->fts->cache = fts_cache_create(table);
}
@@ -3516,7 +3450,7 @@ dict_scan_id(
ptr++;
}
- len = ptr - s;
+ len = ulint(ptr - s);
}
if (heap == NULL) {
@@ -3537,7 +3471,7 @@ dict_scan_id(
}
}
*d++ = 0;
- len = d - str;
+ len = ulint(d - str);
ut_ad(*s == quote);
ut_ad(s + 1 == ptr);
} else {
@@ -3756,7 +3690,7 @@ dict_scan_table_name(
for (s = scan_name; *s; s++) {
if (*s == '.') {
database_name = scan_name;
- database_name_len = s - scan_name;
+ database_name_len = ulint(s - scan_name);
scan_name = ++s;
break;/* to do: multiple dots? */
}
@@ -4067,7 +4001,7 @@ dict_foreign_push_index_error(
const char* col_name;
field = dict_index_get_nth_field(err_index, err_col);
- col_name = dict_col_is_virtual(field->col)
+ col_name = field->col->is_virtual()
? "(null)"
: dict_table_get_col_name(
table, dict_col_get_no(field->col));
@@ -4325,6 +4259,11 @@ loop:
/**********************************************************/
/* The following call adds the foreign key constraints
to the data dictionary system tables on disk */
+ trx->op_info = "adding foreign keys";
+
+ trx_start_if_not_started_xa(trx, true);
+
+ trx_set_dict_operation(trx, TRX_DICT_OP_TABLE);
error = dict_create_add_foreigns_to_dictionary(
local_fk_set, table, trx);
@@ -4539,23 +4478,6 @@ col_loop1:
return(DB_CANNOT_ADD_CONSTRAINT);
}
- /* Don't allow foreign keys on partitioned tables yet. */
- ptr1 = dict_scan_to(ptr, "PARTITION");
- if (ptr1) {
- ptr1 = dict_accept(cs, ptr1, "PARTITION", &success);
- if (success && my_isspace(cs, *ptr1)) {
- ptr2 = dict_accept(cs, ptr1, "BY", &success);
- if (success) {
- my_error(ER_FOREIGN_KEY_ON_PARTITIONED,MYF(0));
- return(DB_CANNOT_ADD_CONSTRAINT);
- }
- }
- }
- if (dict_table_is_partition(table)) {
- my_error(ER_FOREIGN_KEY_ON_PARTITIONED,MYF(0));
- return(DB_CANNOT_ADD_CONSTRAINT);
- }
-
/* Let us create a constraint struct */
foreign = dict_mem_foreign_create();
@@ -5308,19 +5230,19 @@ dict_index_copy_rec_order_prefix(
UNIV_PREFETCH_R(rec);
if (dict_index_is_ibuf(index)) {
- ut_a(!dict_table_is_comp(index->table));
+ ut_ad(!dict_table_is_comp(index->table));
n = rec_get_n_fields_old(rec);
} else {
if (page_rec_is_leaf(rec)) {
n = dict_index_get_n_unique_in_tree(index);
+ } else if (dict_index_is_spatial(index)) {
+ ut_ad(dict_index_get_n_unique_in_tree_nonleaf(index)
+ == DICT_INDEX_SPATIAL_NODEPTR_SIZE);
+ /* For R-tree, we have to compare
+ the child page numbers as well. */
+ n = DICT_INDEX_SPATIAL_NODEPTR_SIZE + 1;
} else {
- n = dict_index_get_n_unique_in_tree_nonleaf(index);
- /* For internal node of R-tree, since we need to
- compare the page no field, so, we need to copy this
- field as well. */
- if (dict_index_is_spatial(index)) {
- n++;
- }
+ n = dict_index_get_n_unique_in_tree(index);
}
}
@@ -5336,21 +5258,14 @@ dict_index_copy_rec_order_prefix(
@param[in,out] heap memory heap for allocation
@return own: data tuple */
dtuple_t*
-dict_index_build_data_tuple_func(
+dict_index_build_data_tuple(
const rec_t* rec,
const dict_index_t* index,
-#ifdef UNIV_DEBUG
bool leaf,
-#endif /* UNIV_DEBUG */
ulint n_fields,
mem_heap_t* heap)
{
- dtuple_t* tuple;
-
- ut_ad(dict_table_is_comp(index->table)
- || n_fields <= rec_get_n_fields_old(rec));
-
- tuple = dtuple_create(heap, n_fields);
+ dtuple_t* tuple = dtuple_create(heap, n_fields);
dict_index_copy_types(tuple, index, n_fields);
@@ -5600,18 +5515,17 @@ dict_print_info_on_foreign_keys(
/** Given a space_id of a file-per-table tablespace, search the
dict_sys->table_LRU list and return the dict_table_t* pointer for it.
-@param space_id Tablespace ID
+@param space tablespace
@return table if found, NULL if not */
static
dict_table_t*
-dict_find_single_table_by_space(
- ulint space_id)
+dict_find_single_table_by_space(const fil_space_t* space)
{
dict_table_t* table;
ulint num_item;
ulint count = 0;
- ut_ad(space_id > 0);
+ ut_ad(space->id > 0);
if (dict_sys == NULL) {
/* This could happen when it's in redo processing. */
@@ -5626,7 +5540,7 @@ dict_find_single_table_by_space(
killing the server, so it worth to risk some consequences for
the action. */
while (table && count < num_item) {
- if (table->space == space_id) {
+ if (table->space == space) {
if (dict_table_is_file_per_table(table)) {
return(table);
}
@@ -5643,41 +5557,28 @@ dict_find_single_table_by_space(
/**********************************************************************//**
Flags a table with specified space_id corrupted in the data dictionary
cache
-@return TRUE if successful */
-ibool
-dict_set_corrupted_by_space(
-/*========================*/
- ulint space_id) /*!< in: space ID */
+@return true if successful */
+bool dict_set_corrupted_by_space(const fil_space_t* space)
{
dict_table_t* table;
- table = dict_find_single_table_by_space(space_id);
+ table = dict_find_single_table_by_space(space);
if (!table) {
- return(FALSE);
+ return false;
}
/* mark the table->corrupted bit only, since the caller
could be too deep in the stack for SYS_INDEXES update */
table->corrupted = true;
table->file_unreadable = true;
-
- return(TRUE);
+ return true;
}
-
-/** Flag a table with specified space_id encrypted in the data dictionary
-cache
-@param[in] space_id Tablespace id */
-UNIV_INTERN
-void
-dict_set_encrypted_by_space(ulint space_id)
+/** Flag a table encrypted in the data dictionary cache. */
+void dict_set_encrypted_by_space(const fil_space_t* space)
{
- dict_table_t* table;
-
- table = dict_find_single_table_by_space(space_id);
-
- if (table) {
+ if (dict_table_t* table = dict_find_single_table_by_space(space)) {
table->file_unreadable = true;
}
}
@@ -5755,7 +5656,7 @@ dict_set_corrupted(
btr_cur_search_to_nth_level(sys_index, 0, tuple, PAGE_CUR_LE,
BTR_MODIFY_LEAF,
- &cursor, 0, __FILE__, __LINE__, &mtr, 0);
+ &cursor, 0, __FILE__, __LINE__, &mtr);
if (cursor.low_match == dtuple_get_n_fields(tuple)) {
/* UPDATE SYS_INDEXES SET TYPE=index->type
@@ -5857,7 +5758,7 @@ dict_index_set_merge_threshold(
btr_cur_search_to_nth_level(sys_index, 0, tuple, PAGE_CUR_GE,
BTR_MODIFY_LEAF,
- &cursor, 0, __FILE__, __LINE__, &mtr, 0);
+ &cursor, 0, __FILE__, __LINE__, &mtr);
if (cursor.up_match == dtuple_get_n_fields(tuple)
&& rec_get_n_fields_old(btr_cur_get_rec(&cursor))
@@ -5929,15 +5830,13 @@ dict_ind_init()
dict_table_t* table;
/* create dummy table and index for REDUNDANT infimum and supremum */
- table = dict_mem_table_create("SYS_DUMMY1", DICT_HDR_SPACE, 1, 0, 0, 0);
+ table = dict_mem_table_create("SYS_DUMMY1", NULL, 1, 0, 0, 0);
dict_mem_table_add_col(table, NULL, NULL, DATA_CHAR,
DATA_ENGLISH | DATA_NOT_NULL, 8);
- dict_ind_redundant = dict_mem_index_create("SYS_DUMMY1", "SYS_DUMMY1",
- DICT_HDR_SPACE, 0, 1);
+ dict_ind_redundant = dict_mem_index_create(table, "SYS_DUMMY1", 0, 1);
dict_index_add_col(dict_ind_redundant, table,
dict_table_get_nth_col(table, 0), 0);
- dict_ind_redundant->table = table;
/* avoid ut_ad(index->cached) in dict_index_get_n_unique_in_tree */
dict_ind_redundant->cached = TRUE;
}
@@ -6177,8 +6076,7 @@ dict_table_schema_check(
}
}
- if (!table->is_readable() &&
- fil_space_get(table->space) == NULL) {
+ if (!table->is_readable() && !table->space) {
/* missing tablespace */
snprintf(errstr, errstr_sz,
@@ -6189,14 +6087,13 @@ dict_table_schema_check(
return(DB_TABLE_NOT_FOUND);
}
- if (ulint(table->n_def) - DATA_N_SYS_COLS != req_schema->n_cols) {
+ if (ulint(table->n_def - DATA_N_SYS_COLS) != req_schema->n_cols) {
/* the table has a different number of columns than required */
snprintf(errstr, errstr_sz,
- "%s has " ULINTPF " columns but should have "
- ULINTPF ".",
+ "%s has %d columns but should have " ULINTPF ".",
ut_format_name(req_schema->table_name, buf,
sizeof buf),
- ulint(table->n_def) - DATA_N_SYS_COLS,
+ table->n_def - DATA_N_SYS_COLS,
req_schema->n_cols);
return(DB_ERROR);
@@ -6441,11 +6338,18 @@ void
dict_close(void)
/*============*/
{
- ulint i;
+ if (dict_sys == NULL) {
+ /* This should only happen if a failure occurred
+ during redo log processing. */
+ return;
+ }
+
+ /* Acquire only because it's a pre-condition. */
+ mutex_enter(&dict_sys->mutex);
/* Free the hash elements. We don't remove them from the table
because we are going to destroy the table anyway. */
- for (i = 0; i < hash_get_n_cells(dict_sys->table_hash); i++) {
+ for (ulint i = 0; i < hash_get_n_cells(dict_sys->table_id_hash); i++) {
dict_table_t* table;
table = static_cast<dict_table_t*>(
@@ -6457,12 +6361,7 @@ dict_close(void)
table = static_cast<dict_table_t*>(
HASH_GET_NEXT(name_hash, prev_table));
ut_ad(prev_table->magic_n == DICT_TABLE_MAGIC_N);
- /* Acquire only because it's a pre-condition. */
- mutex_enter(&dict_sys->mutex);
-
dict_table_remove_from_cache(prev_table);
-
- mutex_exit(&dict_sys->mutex);
}
}
@@ -6472,12 +6371,18 @@ dict_close(void)
therefore we don't delete the individual elements. */
hash_table_free(dict_sys->table_id_hash);
+ mutex_exit(&dict_sys->mutex);
mutex_free(&dict_sys->mutex);
rw_lock_free(&dict_operation_lock);
mutex_free(&dict_foreign_err_mutex);
+ if (dict_foreign_err_file) {
+ fclose(dict_foreign_err_file);
+ dict_foreign_err_file = NULL;
+ }
+
ut_free(dict_sys);
dict_sys = NULL;
@@ -6641,7 +6546,7 @@ dict_foreign_qualify_index(
return(false);
}
- if (dict_col_is_virtual(field->col)) {
+ if (field->col->is_virtual()) {
col_name = "";
for (ulint j = 0; j < table->n_v_def; j++) {
col_name = dict_table_get_v_col_name(table, j);
@@ -6721,7 +6626,7 @@ dict_index_zip_pad_update(
/* Only do increment if it won't increase padding
beyond max pad size. */
if (info->pad + ZIP_PAD_INCR
- < (UNIV_PAGE_SIZE * zip_pad_max) / 100) {
+ < (srv_page_size * zip_pad_max) / 100) {
/* Use atomics even though we have the mutex.
This is to ensure that we are able to read
info->pad atomically. */
@@ -6747,7 +6652,7 @@ dict_index_zip_pad_update(
/* Use atomics even though we have the mutex.
This is to ensure that we are able to read
info->pad atomically. */
- my_atomic_addlint(&info->pad, -ZIP_PAD_INCR);
+ my_atomic_addlint(&info->pad, ulint(-ZIP_PAD_INCR));
info->n_rounds = 0;
@@ -6811,17 +6716,17 @@ dict_index_zip_pad_optimal_page_size(
if (!zip_failure_threshold_pct) {
/* Disabled by user. */
- return(UNIV_PAGE_SIZE);
+ return(srv_page_size);
}
pad = my_atomic_loadlint(&index->zip_pad.pad);
- ut_ad(pad < UNIV_PAGE_SIZE);
- sz = UNIV_PAGE_SIZE - pad;
+ ut_ad(pad < srv_page_size);
+ sz = srv_page_size - pad;
/* Min size allowed by user. */
ut_ad(zip_pad_max < 100);
- min_sz = (UNIV_PAGE_SIZE * (100 - zip_pad_max)) / 100;
+ min_sz = (srv_page_size * (100 - zip_pad_max)) / 100;
return(ut_max(sz, min_sz));
}
@@ -7009,11 +6914,10 @@ dict_table_extent_size(
size_t
dict_table_t::get_overflow_field_local_len() const
{
- if (dict_table_get_format(this) < UNIV_FORMAT_B) {
- /* up to MySQL 5.1: store a 768-byte prefix locally */
- return BTR_EXTERN_FIELD_REF_SIZE
- + DICT_ANTELOPE_MAX_INDEX_COL_LEN;
+ if (dict_table_has_atomic_blobs(this)) {
+ /* new-format table: do not store any BLOB prefix locally */
+ return BTR_EXTERN_FIELD_REF_SIZE;
}
- /* new-format table: do not store any BLOB prefix locally */
- return BTR_EXTERN_FIELD_REF_SIZE;
+ /* up to MySQL 5.1: store a 768-byte prefix locally */
+ return BTR_EXTERN_FIELD_REF_SIZE + DICT_ANTELOPE_MAX_INDEX_COL_LEN;
}
diff --git a/storage/innobase/dict/dict0load.cc b/storage/innobase/dict/dict0load.cc
index 63ccf6bbb96..0c5343205a7 100644
--- a/storage/innobase/dict/dict0load.cc
+++ b/storage/innobase/dict/dict0load.cc
@@ -85,9 +85,9 @@ dict_load_table_one(
/** 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
+@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,
@@ -106,7 +106,6 @@ dict_load_index_low(
byte* table_id, /*!< in/out: table id (8 bytes),
an "in" value if allocate=TRUE
and "out" when allocate=FALSE */
- const char* table_name, /*!< in: table name */
mem_heap_t* heap, /*!< in/out: temporary memory heap */
const rec_t* rec, /*!< in: SYS_INDEXES record */
ibool allocate, /*!< in: TRUE=allocate *index,
@@ -138,7 +137,6 @@ dict_load_column_low(
/** Load a virtual column "mapping" (to base columns) information
from a SYS_VIRTUAL record
@param[in,out] table table
-@param[in,out] heap memory heap
@param[in,out] column mapped base column's dict_column_t
@param[in,out] table_id table id
@param[in,out] pos virtual column position
@@ -150,7 +148,6 @@ static
const char*
dict_load_virtual_low(
dict_table_t* table,
- mem_heap_t* heap,
dict_col_t** column,
table_id_t* table_id,
ulint* pos,
@@ -378,16 +375,12 @@ 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 */
- dict_table_info_t status, /*!< in: status bit controls
- options such as whether we shall
- look for dict_table_t from cache
- first */
+ bool cached, /*!< in: whether to load from cache */
mtr_t* mtr) /*!< in/out: mini-transaction,
will be committed */
{
ulint len;
const char* field;
- const char* err_msg = NULL;
field = (const char*) rec_get_nth_field_old(
rec, DICT_FLD__SYS_TABLES__NAME, &len);
@@ -399,28 +392,17 @@ dict_process_sys_tables_rec_and_mtr_commit(
/* Get the table name */
table_name_t table_name(mem_heap_strdupl(heap, field, len));
- /* If DICT_TABLE_LOAD_FROM_CACHE is set, first check
- whether there is cached dict_table_t struct */
- if (status & DICT_TABLE_LOAD_FROM_CACHE) {
-
+ if (cached) {
/* Commit before load the table again */
mtr_commit(mtr);
*table = dict_table_get_low(table_name.m_name);
-
- if (!(*table)) {
- err_msg = "Table not found in cache";
- }
+ return *table ? NULL : "Table not found in cache";
} else {
- err_msg = dict_load_table_low(table_name, rec, table);
+ const char* err = dict_load_table_low(table_name, rec, table);
mtr_commit(mtr);
+ return err;
}
-
- if (err_msg) {
- return(err_msg);
- }
-
- return(NULL);
}
/********************************************************************//**
@@ -442,8 +424,7 @@ dict_process_sys_indexes_rec(
buf = static_cast<byte*>(mem_heap_alloc(heap, 8));
/* Parse the record, and get "dict_index_t" struct filled */
- err_msg = dict_load_index_low(buf, NULL,
- heap, rec, FALSE, &index);
+ err_msg = dict_load_index_low(buf, heap, rec, FALSE, &index);
*table_id = mach_read_from_8(buf);
@@ -476,7 +457,6 @@ dict_process_sys_columns_rec(
/** This function parses a SYS_VIRTUAL record and extracts virtual column
information
-@param[in,out] heap heap memory
@param[in] rec current SYS_COLUMNS rec
@param[in,out] table_id table id
@param[in,out] pos virtual column position
@@ -484,7 +464,6 @@ information
@return error message, or NULL on success */
const char*
dict_process_sys_virtual_rec(
- mem_heap_t* heap,
const rec_t* rec,
table_id_t* table_id,
ulint* pos,
@@ -493,7 +472,7 @@ dict_process_sys_virtual_rec(
const char* err_msg;
/* Parse the record, and get "dict_col_t" struct filled */
- err_msg = dict_load_virtual_low(NULL, heap, NULL, table_id,
+ err_msg = dict_load_virtual_low(NULL, NULL, table_id,
pos, base_pos, rec);
return(err_msg);
@@ -903,7 +882,7 @@ dict_update_filepath(
ut_ad(rw_lock_own(&dict_operation_lock, RW_LOCK_X));
ut_ad(mutex_own(&dict_sys->mutex));
- trx = trx_allocate_for_background();
+ trx = trx_create();
trx->op_info = "update filepath";
trx->dict_operation_lock_mode = RW_X_LATCH;
trx_start_for_ddl(trx, TRX_DICT_OP_INDEX);
@@ -923,7 +902,7 @@ dict_update_filepath(
trx_commit_for_mysql(trx);
trx->dict_operation_lock_mode = 0;
- trx_free_for_background(trx);
+ trx_free(trx);
if (UNIV_LIKELY(err == DB_SUCCESS)) {
/* We just updated SYS_DATAFILES due to the contents in
@@ -972,7 +951,7 @@ dict_replace_tablespace_and_filepath(
ut_ad(mutex_own(&dict_sys->mutex));
ut_ad(filepath);
- trx = trx_allocate_for_background();
+ trx = trx_create();
trx->op_info = "insert tablespace and filepath";
trx->dict_operation_lock_mode = RW_X_LATCH;
trx_start_for_ddl(trx, TRX_DICT_OP_INDEX);
@@ -985,7 +964,7 @@ dict_replace_tablespace_and_filepath(
trx_commit_for_mysql(trx);
trx->dict_operation_lock_mode = 0;
- trx_free_for_background(trx);
+ trx_free(trx);
return(err);
}
@@ -1145,8 +1124,9 @@ dict_sys_tables_type_valid(ulint type, bool not_redundant)
}
if (!not_redundant) {
- /* SYS_TABLES.TYPE must be 1 for ROW_FORMAT=REDUNDANT. */
- return(false);
+ /* SYS_TABLES.TYPE must be 1 or 1|DICT_TF_MASK_NO_ROLLBACK
+ for ROW_FORMAT=REDUNDANT. */
+ return !(type & ~(1U | DICT_TF_MASK_NO_ROLLBACK));
}
if (type >= 1U << DICT_TF_POS_UNUSED) {
@@ -1154,11 +1134,6 @@ dict_sys_tables_type_valid(ulint type, bool not_redundant)
return(false);
}
- /* ATOMIC_WRITES cannot be 3; it is the 10.3 NO_ROLLBACK flag. */
- if (!(~type & DICT_TF_MASK_ATOMIC_WRITES)) {
- return(false);
- }
-
return(dict_tf_is_valid_not_redundant(type));
}
@@ -1179,7 +1154,8 @@ dict_sys_tables_type_to_tf(ulint type, bool not_redundant)
| DICT_TF_MASK_ATOMIC_BLOBS
| DICT_TF_MASK_DATA_DIR
| DICT_TF_MASK_PAGE_COMPRESSION
- | DICT_TF_MASK_PAGE_COMPRESSION_LEVEL);
+ | DICT_TF_MASK_PAGE_COMPRESSION_LEVEL
+ | DICT_TF_MASK_NO_ROLLBACK);
ut_ad(dict_tf_is_valid(flags));
return(flags);
@@ -1231,7 +1207,8 @@ dict_sys_tables_rec_read(
MariaDB 10.2.2 introduced the SHARED_SPACE flag from MySQL 5.7,
shifting the flags PAGE_COMPRESSION, PAGE_COMPRESSION_LEVEL,
- ATOMIC_WRITES by one bit. The SHARED_SPACE flag would always
+ ATOMIC_WRITES (repurposed to NO_ROLLBACK in 10.3.1) by one bit.
+ The SHARED_SPACE flag would always
be written as 0 by MariaDB, because MariaDB does not support
CREATE TABLESPACE or CREATE TABLE...TABLESPACE for InnoDB.
@@ -1300,7 +1277,7 @@ dict_sys_tables_rec_read(
/* The low order bit of SYS_TABLES.TYPE is always set to 1. But in
dict_table_t::flags the low order bit is used to determine if the
- row format is Redundant (0) or Compact (1) when the format is Antelope.
+ ROW_FORMAT=REDUNDANT (0) or anything else (1).
Read the 4 byte N_COLS field and look at the high order bit. It
should be set for COMPACT and later. It should not be set for
REDUNDANT. */
@@ -1382,10 +1359,6 @@ static ulint dict_check_sys_tables()
sys_datafiles = dict_table_get_low("SYS_DATAFILES");
ut_a(sys_datafiles != NULL);
- const bool validate = recv_needed_recovery
- && !srv_safe_truncate
- && !srv_force_recovery;
-
for (rec = dict_startscan_system(&pcur, &mtr, SYS_TABLES);
rec != NULL;
mtr.commit(), mtr.start(),
@@ -1422,8 +1395,7 @@ next:
continue;
}
- if (srv_safe_truncate
- && strstr(table_name.m_name, "/" TEMP_FILE_PREFIX "-")) {
+ if (strstr(table_name.m_name, "/" TEMP_FILE_PREFIX "-")) {
/* This table will be dropped by
row_mysql_drop_garbage_tables().
We do not care if the file exists. */
@@ -1446,19 +1418,19 @@ next:
/* Now that we have the proper name for this tablespace,
look to see if it is already in the tablespace cache. */
- if (fil_space_for_table_exists_in_mem(
+ if (const fil_space_t* space
+ = fil_space_for_table_exists_in_mem(
space_id, table_name.m_name, flags)) {
/* Recovery can open a datafile that does not
match SYS_DATAFILES. If they don't match, update
SYS_DATAFILES. */
char *dict_path = dict_get_first_path(space_id);
- char *fil_path = fil_space_get_first_path(space_id);
- if (dict_path && fil_path
+ const char *fil_path = space->chain.start->name;
+ if (dict_path
&& strcmp(dict_path, fil_path)) {
dict_update_filepath(space_id, fil_path);
}
ut_free(dict_path);
- ut_free(fil_path);
ut_free(table_name.m_name);
continue;
}
@@ -1471,15 +1443,12 @@ next:
char* filepath = dict_get_first_path(space_id);
/* Check that the .ibd file exists. */
- dberr_t err = fil_ibd_open(
- validate,
- !srv_read_only_mode && srv_log_file_size != 0,
- FIL_TYPE_TABLESPACE,
- space_id, dict_tf_to_fsp_flags(flags),
- table_name.m_name,
- filepath);
-
- if (err != DB_SUCCESS) {
+ if (!fil_ibd_open(
+ false,
+ !srv_read_only_mode && srv_log_file_size != 0,
+ 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.";
@@ -1712,7 +1681,6 @@ static const char* dict_load_virtual_del = "delete-marked record in SYS_VIRTUAL"
/** Load a virtual column "mapping" (to base columns) information
from a SYS_VIRTUAL record
@param[in,out] table table
-@param[in,out] heap memory heap
@param[in,out] column mapped base column's dict_column_t
@param[in,out] table_id table id
@param[in,out] pos virtual column position
@@ -1724,7 +1692,6 @@ static
const char*
dict_load_virtual_low(
dict_table_t* table,
- mem_heap_t* heap,
dict_col_t** column,
table_id_t* table_id,
ulint* pos,
@@ -1984,7 +1951,7 @@ dict_load_virtual_one_col(
ut_a(btr_pcur_is_on_user_rec(&pcur));
- err_msg = dict_load_virtual_low(table, heap,
+ err_msg = dict_load_virtual_low(table,
&v_col->base_col[i - skipped],
NULL,
&pos, NULL, rec);
@@ -2051,7 +2018,7 @@ dict_load_field_low(
ulint len;
unsigned pos_and_prefix_len;
unsigned prefix_len;
- ibool first_field;
+ bool first_field;
ulint position;
/* Either index or sys_field is supplied, not both */
@@ -2240,7 +2207,6 @@ dict_load_index_low(
byte* table_id, /*!< in/out: table id (8 bytes),
an "in" value if allocate=TRUE
and "out" when allocate=FALSE */
- const char* table_name, /*!< in: table name */
mem_heap_t* heap, /*!< in/out: temporary memory heap */
const rec_t* rec, /*!< in: SYS_INDEXES record */
ibool allocate, /*!< in: TRUE=allocate *index,
@@ -2255,7 +2221,6 @@ dict_load_index_low(
index_id_t id;
ulint n_fields;
ulint type;
- ulint space;
unsigned merge_threshold;
if (allocate) {
@@ -2354,26 +2319,18 @@ err_len:
}
field = rec_get_nth_field_old(
- rec, DICT_FLD__SYS_INDEXES__SPACE, &len);
- if (len != 4) {
- goto err_len;
- }
- space = mach_read_from_4(field);
-
- field = rec_get_nth_field_old(
rec, DICT_FLD__SYS_INDEXES__PAGE_NO, &len);
if (len != 4) {
goto err_len;
}
if (allocate) {
- *index = dict_mem_index_create(table_name, name_buf,
- space, type, n_fields);
+ *index = dict_mem_index_create(NULL, name_buf, type, n_fields);
} else {
ut_a(*index);
- dict_mem_fill_index_struct(*index, NULL, NULL, name_buf,
- space, type, n_fields);
+ dict_mem_fill_index_struct(*index, NULL, name_buf,
+ type, n_fields);
}
(*index)->id = id;
@@ -2480,8 +2437,7 @@ dict_load_indexes(
}
}
- err_msg = dict_load_index_low(
- buf, table->name.m_name, heap, rec, TRUE, &index);
+ err_msg = dict_load_index_low(buf, heap, rec, TRUE, &index);
ut_ad((index == NULL && err_msg != NULL)
|| (index != NULL && err_msg == NULL));
@@ -2612,17 +2568,16 @@ corrupted:
dict_mem_index_free(index);
} else {
dict_load_fields(index, heap);
-
- error = dict_index_add_to_cache(
- table, index, index->page, FALSE);
+ index->table = table;
/* The data dictionary tables should never contain
invalid index definitions. If we ignored this error
and simply did not load this index definition, the
.frm file would disagree with the index definitions
inside InnoDB. */
- if (UNIV_UNLIKELY(error != DB_SUCCESS)) {
-
+ if ((error = dict_index_add_to_cache(index,
+ index->page))
+ != DB_SUCCESS) {
goto func_exit;
}
}
@@ -2654,9 +2609,9 @@ func_exit:
/** 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
+@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,
@@ -2684,7 +2639,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, space_id, n_cols + n_v_col, n_v_col, flags, flags2);
+ name.m_name, NULL, n_cols + n_v_col, n_v_col, flags, flags2);
+ (*table)->space_id = space_id;
(*table)->id = table_id;
(*table)->file_unreadable = false;
@@ -2702,7 +2658,7 @@ void
dict_save_data_dir_path(
/*====================*/
dict_table_t* table, /*!< in/out: table */
- char* filepath) /*!< in: filepath of tablespace */
+ const char* filepath) /*!< in: filepath of tablespace */
{
ut_ad(mutex_own(&dict_sys->mutex));
ut_a(DICT_TF_HAS_DATA_DIR(table->flags));
@@ -2737,20 +2693,19 @@ dict_get_and_save_data_dir_path(
dict_table_t* table,
bool dict_mutex_own)
{
- ut_ad(!dict_table_is_temporary(table));
-
- if (!table->data_dir_path && table->space) {
- char* path = fil_space_get_first_path(table->space);
+ ut_ad(!table->is_temporary());
+ ut_ad(!table->space || table->space->id == table->space_id);
+ if (!table->data_dir_path && table->space_id) {
if (!dict_mutex_own) {
dict_mutex_enter_for_mysql();
}
- if (path == NULL) {
- path = dict_get_first_path(table->space);
- }
-
- if (path != NULL) {
+ if (const char* p = table->space
+ ? table->space->chain.start->name : NULL) {
+ table->flags |= (1 << DICT_TF_POS_DATA_DIR);
+ dict_save_data_dir_path(table, p);
+ } else if (char* path = dict_get_first_path(table->space_id)) {
table->flags |= (1 << DICT_TF_POS_DATA_DIR);
dict_save_data_dir_path(table, path);
ut_free(path);
@@ -2817,10 +2772,13 @@ dict_load_tablespace(
dict_table_t* table,
dict_err_ignore_t ignore_err)
{
- ut_ad(!dict_table_is_temporary(table));
+ ut_ad(!table->is_temporary());
+ ut_ad(!table->space);
+ ut_ad(table->space_id < SRV_LOG_SPACE_FIRST_ID);
+ ut_ad(fil_system.sys_space);
- /* The system tablespace is always available. */
- if (is_system_tablespace(table->space)) {
+ if (table->space_id == TRX_SYS_SPACE) {
+ table->space = fil_system.sys_space;
return;
}
@@ -2831,11 +2789,10 @@ dict_load_tablespace(
return;
}
- char* space_name = table->name.m_name;
-
/* The tablespace may already be open. */
- if (fil_space_for_table_exists_in_mem(
- table->space, space_name, table->flags)) {
+ table->space = fil_space_for_table_exists_in_mem(
+ table->space_id, table->name.m_name, table->flags);
+ if (table->space) {
return;
}
@@ -2848,12 +2805,12 @@ dict_load_tablespace(
ib::error() << "Failed to find tablespace for table "
<< table->name << " in the cache. Attempting"
" to load the tablespace with space id "
- << table->space;
+ << table->space_id;
}
/* Use the remote filepath if needed. This parameter is optional
in the call to fil_ibd_open(). If not supplied, it will be built
- from the space_name. */
+ from the table->name. */
char* filepath = NULL;
if (DICT_TF_HAS_DATA_DIR(table->flags)) {
/* This will set table->data_dir_path from either
@@ -2869,12 +2826,12 @@ 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_operation_lock */
- dberr_t err = fil_ibd_open(
- true, false, FIL_TYPE_TABLESPACE, table->space,
+ table->space = fil_ibd_open(
+ true, false, FIL_TYPE_TABLESPACE, table->space_id,
dict_tf_to_fsp_flags(table->flags),
- space_name, filepath);
+ table->name, filepath);
- if (err != DB_SUCCESS) {
+ if (!table->space) {
/* We failed to find a sensible tablespace file */
table->file_unreadable = true;
}
@@ -2907,7 +2864,6 @@ dict_load_table_one(
dict_names_t& fk_tables)
{
dberr_t err;
- dict_table_t* table;
dict_table_t* sys_tables;
btr_pcur_t pcur;
dict_index_t* sys_index;
@@ -2973,6 +2929,7 @@ err_exit:
goto err_exit;
}
+ dict_table_t* table;
if (const char* err_msg = dict_load_table_low(name, rec, &table)) {
if (err_msg != dict_load_table_flags) {
ib::error() << err_msg;
@@ -2989,7 +2946,10 @@ err_exit:
dict_load_virtual(table, heap);
- dict_table_add_to_cache(table, TRUE, heap);
+ dict_table_add_system_columns(table, heap);
+
+ table->can_be_evicted = true;
+ table->add_to_cache();
mem_heap_empty(heap);
@@ -3027,6 +2987,43 @@ err_exit:
}
}
+ if (err == DB_SUCCESS && table->is_readable()) {
+ if (table->space && !fil_space_get_size(table->space_id)) {
+corrupted:
+ table->corrupted = true;
+ table->file_unreadable = true;
+ err = DB_CORRUPTION;
+ } else {
+ const page_id_t page_id(
+ table->space->id,
+ dict_table_get_first_index(table)->page);
+ mtr.start();
+ buf_block_t* block = buf_page_get(
+ page_id,
+ dict_table_page_size(table),
+ RW_S_LATCH, &mtr);
+ const bool corrupted = !block
+ || page_get_space_id(block->frame)
+ != page_id.space()
+ || page_get_page_no(block->frame)
+ != page_id.page_no()
+ || (mach_read_from_2(FIL_PAGE_TYPE
+ + block->frame)
+ != FIL_PAGE_INDEX
+ && mach_read_from_2(FIL_PAGE_TYPE
+ + block->frame)
+ != FIL_PAGE_TYPE_INSTANT);
+ mtr.commit();
+ if (corrupted) {
+ goto corrupted;
+ }
+
+ if (table->supports_instant()) {
+ err = btr_cur_instant_init(table);
+ }
+ }
+ }
+
/* Initialize table foreign_child value. Its value could be
changed when dict_load_foreigns() is called below */
table->fk_max_recusive_level = 0;
@@ -3053,35 +3050,6 @@ err_exit:
} else {
dict_mem_table_fill_foreign_vcol_set(table);
table->fk_max_recusive_level = 0;
-
- if (table->space
- && !fil_space_get_size(table->space)) {
-corrupted:
- table->corrupted = true;
- table->file_unreadable = true;
- } else {
- const page_id_t page_id(
- table->space,
- dict_table_get_first_index(table)
- ->page);
- mtr.start();
- buf_block_t* block = buf_page_get(
- page_id,
- dict_table_page_size(table),
- RW_S_LATCH, &mtr);
- const bool corrupted = !block
- || page_get_space_id(block->frame)
- != page_id.space()
- || page_get_page_no(block->frame)
- != page_id.page_no()
- || mach_read_from_2(FIL_PAGE_TYPE
- + block->frame)
- != FIL_PAGE_INDEX;
- mtr.commit();
- if (corrupted) {
- goto corrupted;
- }
- }
}
} else {
dict_index_t* index;
diff --git a/storage/innobase/dict/dict0mem.cc b/storage/innobase/dict/dict0mem.cc
index 8327318e46c..f380feff7ef 100644
--- a/storage/innobase/dict/dict0mem.cc
+++ b/storage/innobase/dict/dict0mem.cc
@@ -34,9 +34,9 @@ Created 1/8/1996 Heikki Tuuri
#include "mach0data.h"
#include "dict0dict.h"
#include "fts0priv.h"
-#include "ut0crc32.h"
#include "lock0lock.h"
#include "sync0sync.h"
+#include "row0row.h"
#include <iostream>
#define DICT_HEAP_SIZE 100 /*!< initial memory heap size when
@@ -50,6 +50,29 @@ static const char* innobase_system_databases[] = {
NullS
};
+/** Determine if a table belongs to innobase_system_databases[]
+@param[in] name database_name/table_name
+@return whether the database_name is in innobase_system_databases[] */
+static bool dict_mem_table_is_system(const char *name)
+{
+ /* table has the following format: database/table
+ and some system table are of the form SYS_* */
+ if (!strchr(name, '/')) {
+ return true;
+ }
+ size_t table_len = strlen(name);
+ const char *system_db;
+ int i = 0;
+ while ((system_db = innobase_system_databases[i++])
+ && (system_db != NullS)) {
+ size_t len = strlen(system_db);
+ if (table_len > len && !strncmp(name, system_db, len)) {
+ return true;
+ }
+ }
+ return false;
+}
+
/** The start of the table basename suffix for partitioned tables */
const char table_name_t::part_suffix[4]
#ifdef _WIN32
@@ -58,10 +81,6 @@ const char table_name_t::part_suffix[4]
= "#P#";
#endif
-/** An interger randomly initialized at startup used to make a temporary
-table name as unuique as possible. */
-static ib_uint32_t dict_temp_file_num;
-
/** Display an identifier.
@param[in,out] s output stream
@param[in] id_name SQL identifier (other than table name)
@@ -103,8 +122,7 @@ dict_table_t*
dict_mem_table_create(
/*==================*/
const char* name, /*!< in: table name */
- ulint space, /*!< in: space where the clustered index of
- the table is placed */
+ fil_space_t* space, /*!< in: tablespace */
ulint n_cols, /*!< in: total number of columns including
virtual and non-virtual columns */
ulint n_v_cols,/*!< in: number of virtual columns */
@@ -115,6 +133,10 @@ dict_mem_table_create(
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));
@@ -138,10 +160,11 @@ dict_mem_table_create(
table->flags2 = (unsigned int) flags2;
table->name.m_name = mem_strdup(name);
table->is_system_db = dict_mem_table_is_system(table->name.m_name);
- table->space = (unsigned int) space;
+ table->space = space;
+ table->space_id = space ? space->id : ULINT_UNDEFINED;
table->n_t_cols = unsigned(n_cols + DATA_N_SYS_COLS);
table->n_v_cols = (unsigned int) (n_v_cols);
- table->n_cols = table->n_t_cols - table->n_v_cols;
+ table->n_cols = unsigned(table->n_t_cols - table->n_v_cols);
table->cols = static_cast<dict_col_t*>(
mem_heap_alloc(heap, table->n_cols * sizeof(dict_col_t)));
@@ -255,7 +278,7 @@ dict_add_col_name(
s += strlen(s) + 1;
}
- old_len = s - col_names;
+ old_len = unsigned(s - col_names);
} else {
old_len = 0;
}
@@ -317,6 +340,16 @@ dict_mem_table_add_col(
col = dict_table_get_nth_col(table, i);
dict_mem_fill_column_struct(col, i, mtype, prtype, len);
+
+ switch (prtype & DATA_VERSIONED) {
+ case DATA_VERS_START:
+ ut_ad(!table->vers_start);
+ table->vers_start = i;
+ break;
+ case DATA_VERS_END:
+ ut_ad(!table->vers_end);
+ table->vers_end = i;
+ }
}
/** Adds a virtual column definition to a table.
@@ -374,7 +407,7 @@ dict_mem_table_add_v_col(
i, name, heap);
}
- v_col = dict_table_get_nth_v_col(table, i);
+ v_col = &table->v_cols[i];
dict_mem_fill_column_struct(&v_col->m_col, pos, mtype, prtype, len);
v_col->v_pos = i;
@@ -403,7 +436,7 @@ dict_mem_table_add_s_col(
dict_table_t* table,
ulint num_base)
{
- ulint i = table->n_def - 1;
+ unsigned i = unsigned(table->n_def) - 1;
dict_col_t* col = dict_table_get_nth_col(table, i);
dict_s_col_t s_col;
@@ -464,13 +497,13 @@ dict_mem_table_col_rename_low(
/* We need to adjust all affected index->field
pointers, as in dict_index_add_col(). First, copy
table->col_names. */
- ulint prefix_len = s - t_col_names;
+ ulint prefix_len = ulint(s - t_col_names);
for (; i < n_col; i++) {
s += strlen(s) + 1;
}
- ulint full_len = s - t_col_names;
+ ulint full_len = ulint(s - t_col_names);
char* col_names;
if (to_len > from_len) {
@@ -503,12 +536,12 @@ dict_mem_table_col_rename_low(
/* if is_virtual and that in field->col does
not match, continue */
if ((!is_virtual) !=
- (!dict_col_is_virtual(field->col))) {
+ (!field->col->is_virtual())) {
continue;
}
ulint name_ofs
- = field->name - t_col_names;
+ = ulint(field->name - t_col_names);
if (name_ofs <= prefix_len) {
field->name = col_names + name_ofs;
} else {
@@ -712,9 +745,11 @@ dict_mem_fill_column_struct(
column->mtype = (unsigned int) mtype;
column->prtype = (unsigned int) prtype;
column->len = (unsigned int) col_len;
- dtype_get_mblen(mtype, prtype, &mbminlen, &mbmaxlen);
+ dtype_get_mblen(mtype, prtype, &mbminlen, &mbmaxlen);
column->mbminlen = mbminlen;
column->mbmaxlen = mbmaxlen;
+ column->def_val.data = NULL;
+ column->def_val.len = UNIV_SQL_DEFAULT;
}
/**********************************************************************//**
@@ -723,11 +758,8 @@ Creates an index memory object.
dict_index_t*
dict_mem_index_create(
/*==================*/
- const char* table_name, /*!< in: table name */
+ dict_table_t* table, /*!< in: table */
const char* index_name, /*!< in: index name */
- ulint space, /*!< in: space where the index tree is
- placed, ignored if the index is of
- the clustered type */
ulint type, /*!< in: DICT_UNIQUE,
DICT_CLUSTERED, ... ORed */
ulint n_fields) /*!< in: number of fields */
@@ -735,15 +767,16 @@ dict_mem_index_create(
dict_index_t* index;
mem_heap_t* heap;
- ut_ad(table_name && index_name);
+ ut_ad(!table || table->magic_n == DICT_TABLE_MAGIC_N);
+ ut_ad(index_name);
heap = mem_heap_create(DICT_HEAP_SIZE);
index = static_cast<dict_index_t*>(
mem_heap_zalloc(heap, sizeof(*index)));
+ index->table = table;
- dict_mem_fill_index_struct(index, heap, table_name, index_name,
- space, type, n_fields);
+ dict_mem_fill_index_struct(index, heap, index_name, type, n_fields);
dict_index_zip_pad_mutex_create_lazy(index);
@@ -1044,7 +1077,7 @@ dict_mem_index_add_field(
index->n_def++;
- field = dict_index_get_nth_field(index, index->n_def - 1);
+ field = dict_index_get_nth_field(index, unsigned(index->n_def) - 1);
field->name = name;
field->prefix_len = (unsigned int) prefix_len;
@@ -1098,46 +1131,15 @@ dict_mem_create_temporary_tablename(
ut_ad(dbend);
size_t dblen = size_t(dbend - dbtab) + 1;
- if (srv_safe_truncate) {
- /* InnoDB will drop all #sql tables at startup.
- Therefore, the id alone should generate a unique
- and previously non-existent name. */
- size = dblen + (sizeof(TEMP_FILE_PREFIX) + 3 + 20);
- name = static_cast<char*>(mem_heap_alloc(heap, size));
- memcpy(name, dbtab, dblen);
- snprintf(name + dblen, size - dblen,
- TEMP_FILE_PREFIX_INNODB UINT64PF, id);
- return name;
- }
- /* Increment a randomly initialized number for each temp file. */
- my_atomic_add32((int32*) &dict_temp_file_num, 1);
-
- size = dblen + (sizeof(TEMP_FILE_PREFIX) + 3 + 20 + 1 + 10);
+ size = dblen + (sizeof(TEMP_FILE_PREFIX) + 3 + 20);
name = static_cast<char*>(mem_heap_alloc(heap, size));
memcpy(name, dbtab, dblen);
snprintf(name + dblen, size - dblen,
- TEMP_FILE_PREFIX_INNODB UINT64PF "-" UINT32PF,
- id, dict_temp_file_num);
+ TEMP_FILE_PREFIX_INNODB UINT64PF, id);
return(name);
}
-/** Initialize dict memory variables */
-void
-dict_mem_init(void)
-{
- /* Initialize a randomly distributed temporary file number */
- ib_uint32_t now = static_cast<ib_uint32_t>(time(NULL));
-
- const byte* buf = reinterpret_cast<const byte*>(&now);
-
- dict_temp_file_num = ut_crc32(buf, sizeof(now));
-
- DBUG_PRINT("dict_mem_init",
- ("Starting Temporary file number is " UINT32PF,
- dict_temp_file_num));
-}
-
/** Validate the search order in the foreign key set.
@param[in] fk_set the foreign key set to be validated
@return true if search order is fine in the set, false otherwise. */
@@ -1195,31 +1197,354 @@ operator<< (std::ostream& out, const dict_foreign_set& fk_set)
return(out);
}
-/****************************************************************//**
-Determines if a table belongs to a system database
-@return */
-bool
-dict_mem_table_is_system(
-/*================*/
- char *name) /*!< in: table name */
+/** Adjust clustered index metadata for instant ADD COLUMN.
+@param[in] clustered index definition after instant ADD COLUMN */
+inline void dict_index_t::instant_add_field(const dict_index_t& instant)
{
- ut_ad(name);
+ DBUG_ASSERT(is_primary());
+ DBUG_ASSERT(instant.is_primary());
+ DBUG_ASSERT(!instant.is_instant());
+ DBUG_ASSERT(n_def == n_fields);
+ DBUG_ASSERT(instant.n_def == instant.n_fields);
+
+ DBUG_ASSERT(type == instant.type);
+ DBUG_ASSERT(trx_id_offset == instant.trx_id_offset);
+ DBUG_ASSERT(n_user_defined_cols == instant.n_user_defined_cols);
+ DBUG_ASSERT(n_uniq == instant.n_uniq);
+ DBUG_ASSERT(instant.n_fields > n_fields);
+ DBUG_ASSERT(instant.n_def > n_def);
+ DBUG_ASSERT(instant.n_nullable >= n_nullable);
+ DBUG_ASSERT(instant.n_core_fields >= n_core_fields);
+ DBUG_ASSERT(instant.n_core_null_bytes >= n_core_null_bytes);
+
+ n_fields = instant.n_fields;
+ n_def = instant.n_def;
+ n_nullable = instant.n_nullable;
+ fields = static_cast<dict_field_t*>(
+ mem_heap_dup(heap, instant.fields, n_fields * sizeof *fields));
+
+ ut_d(unsigned n_null = 0);
+
+ for (unsigned i = 0; i < n_fields; i++) {
+ DBUG_ASSERT(fields[i].same(instant.fields[i]));
+ const dict_col_t* icol = instant.fields[i].col;
+ DBUG_ASSERT(!icol->is_virtual());
+ dict_col_t* col = fields[i].col = &table->cols[
+ icol - instant.table->cols];
+ fields[i].name = col->name(*table);
+ ut_d(n_null += col->is_nullable());
+ }
- /* table has the following format: database/table
- and some system table are of the form SYS_* */
- if (strchr(name, '/')) {
- size_t table_len = strlen(name);
- const char *system_db;
- int i = 0;
- while ((system_db = innobase_system_databases[i++])
- && (system_db != NullS)) {
- size_t len = strlen(system_db);
- if (table_len > len && !strncmp(name, system_db, len)) {
- return true;
+ ut_ad(n_null == n_nullable);
+}
+
+/** Adjust metadata for instant ADD COLUMN.
+@param[in] table table definition after instant ADD COLUMN */
+void dict_table_t::instant_add_column(const dict_table_t& table)
+{
+ DBUG_ASSERT(!table.cached);
+ DBUG_ASSERT(table.n_def == table.n_cols);
+ DBUG_ASSERT(table.n_t_def == table.n_t_cols);
+ DBUG_ASSERT(n_def == n_cols);
+ DBUG_ASSERT(n_t_def == n_t_cols);
+ DBUG_ASSERT(table.n_cols > n_cols);
+ ut_ad(mutex_own(&dict_sys->mutex));
+
+ const char* end = table.col_names;
+ for (unsigned i = table.n_cols; i--; ) end += strlen(end) + 1;
+
+ col_names = static_cast<char*>(
+ mem_heap_dup(heap, table.col_names,
+ ulint(end - table.col_names)));
+ const dict_col_t* const old_cols = cols;
+ const dict_col_t* const old_cols_end = cols + n_cols;
+ cols = static_cast<dict_col_t*>(mem_heap_dup(heap, table.cols,
+ table.n_cols
+ * sizeof *cols));
+
+ /* Preserve the default values of previously instantly
+ added columns. */
+ for (unsigned i = unsigned(n_cols) - DATA_N_SYS_COLS; i--; ) {
+ cols[i].def_val = old_cols[i].def_val;
+ }
+
+ /* Copy the new default values to this->heap. */
+ for (unsigned i = n_cols; i < table.n_cols; i++) {
+ dict_col_t& c = cols[i - DATA_N_SYS_COLS];
+ DBUG_ASSERT(c.is_instant());
+ if (c.def_val.len == 0) {
+ c.def_val.data = field_ref_zero;
+ } else if (const void*& d = c.def_val.data) {
+ d = mem_heap_dup(heap, d, c.def_val.len);
+ } else {
+ DBUG_ASSERT(c.def_val.len == UNIV_SQL_NULL);
+ }
+ }
+
+ const unsigned old_n_cols = n_cols;
+ const unsigned n_add = unsigned(table.n_cols - n_cols);
+
+ n_t_def += n_add;
+ n_t_cols += n_add;
+ n_cols = table.n_cols;
+ n_def = n_cols;
+
+ for (unsigned i = n_v_def; i--; ) {
+ const dict_v_col_t& v = v_cols[i];
+ for (ulint n = v.num_base; n--; ) {
+ dict_col_t*& base = v.base_col[n];
+ if (!base->is_virtual()) {
+ DBUG_ASSERT(base >= old_cols);
+ size_t n = size_t(base - old_cols);
+ DBUG_ASSERT(n + DATA_N_SYS_COLS < old_n_cols);
+ base = &cols[n];
}
}
- return false;
- } else {
- return true;
}
+
+ dict_index_t* index = dict_table_get_first_index(this);
+
+ index->instant_add_field(*dict_table_get_first_index(&table));
+
+ while ((index = dict_table_get_next_index(index)) != NULL) {
+ for (unsigned i = 0; i < index->n_fields; i++) {
+ dict_field_t& field = index->fields[i];
+ if (field.col < old_cols
+ || field.col >= old_cols_end) {
+ DBUG_ASSERT(field.col->is_virtual());
+ } else {
+ /* Secondary indexes may contain user
+ columns and DB_ROW_ID (if there is
+ GEN_CLUST_INDEX instead of PRIMARY KEY),
+ but not DB_TRX_ID,DB_ROLL_PTR. */
+ DBUG_ASSERT(field.col >= old_cols);
+ size_t n = size_t(field.col - old_cols);
+ DBUG_ASSERT(n + DATA_N_SYS_COLS <= old_n_cols);
+ if (n + DATA_N_SYS_COLS >= old_n_cols) {
+ /* Replace DB_ROW_ID */
+ n += n_add;
+ }
+ field.col = &cols[n];
+ DBUG_ASSERT(!field.col->is_virtual());
+ field.name = field.col->name(*this);
+ }
+ }
+ }
+}
+
+/** Roll back instant_add_column().
+@param[in] old_n_cols original n_cols
+@param[in] old_cols original cols
+@param[in] old_col_names original col_names */
+void
+dict_table_t::rollback_instant(
+ unsigned old_n_cols,
+ dict_col_t* old_cols,
+ const char* old_col_names)
+{
+ ut_ad(mutex_own(&dict_sys->mutex));
+ dict_index_t* index = indexes.start;
+ /* index->is_instant() does not necessarily hold here, because
+ the table may have been emptied */
+ DBUG_ASSERT(old_n_cols >= DATA_N_SYS_COLS);
+ DBUG_ASSERT(n_cols >= old_n_cols);
+ DBUG_ASSERT(n_cols == n_def);
+ DBUG_ASSERT(index->n_def == index->n_fields);
+
+ const unsigned n_remove = n_cols - old_n_cols;
+
+ for (unsigned i = index->n_fields - n_remove; i < index->n_fields;
+ i++) {
+ if (index->fields[i].col->is_nullable()) {
+ index->n_nullable--;
+ }
+ }
+
+ index->n_fields -= n_remove;
+ index->n_def = index->n_fields;
+ if (index->n_core_fields > index->n_fields) {
+ index->n_core_fields = index->n_fields;
+ index->n_core_null_bytes
+ = UT_BITS_IN_BYTES(unsigned(index->n_nullable));
+ }
+
+ const dict_col_t* const new_cols = cols;
+ const dict_col_t* const new_cols_end = cols + n_cols;
+
+ cols = old_cols;
+ col_names = old_col_names;
+ n_cols = old_n_cols;
+ n_def = old_n_cols;
+ n_t_def -= n_remove;
+ n_t_cols -= n_remove;
+
+ for (unsigned i = n_v_def; i--; ) {
+ const dict_v_col_t& v = v_cols[i];
+ for (ulint n = v.num_base; n--; ) {
+ dict_col_t*& base = v.base_col[n];
+ if (!base->is_virtual()) {
+ base = &cols[base - new_cols];
+ }
+ }
+ }
+
+ do {
+ for (unsigned i = 0; i < index->n_fields; i++) {
+ dict_field_t& field = index->fields[i];
+ if (field.col < new_cols
+ || field.col >= new_cols_end) {
+ DBUG_ASSERT(field.col->is_virtual());
+ } else {
+ DBUG_ASSERT(field.col >= new_cols);
+ size_t n = size_t(field.col - new_cols);
+ DBUG_ASSERT(n <= n_cols);
+ if (n + DATA_N_SYS_COLS >= n_cols) {
+ n -= n_remove;
+ }
+ field.col = &cols[n];
+ DBUG_ASSERT(!field.col->is_virtual());
+ field.name = field.col->name(*this);
+ }
+ }
+ } while ((index = dict_table_get_next_index(index)) != NULL);
+}
+
+/** Trim the instantly added columns when an insert into SYS_COLUMNS
+is rolled back during ALTER TABLE or recovery.
+@param[in] n number of surviving non-system columns */
+void dict_table_t::rollback_instant(unsigned n)
+{
+ ut_ad(mutex_own(&dict_sys->mutex));
+ dict_index_t* index = indexes.start;
+ DBUG_ASSERT(index->is_instant());
+ DBUG_ASSERT(index->n_def == index->n_fields);
+ DBUG_ASSERT(n_cols == n_def);
+ DBUG_ASSERT(n >= index->n_uniq);
+ DBUG_ASSERT(n_cols > n + DATA_N_SYS_COLS);
+ const unsigned n_remove = n_cols - n - DATA_N_SYS_COLS;
+
+ char* names = const_cast<char*>(dict_table_get_col_name(this, n));
+ const char* sys = names;
+ for (unsigned i = n_remove; i--; ) {
+ sys += strlen(sys) + 1;
+ }
+ static const char system[] = "DB_ROW_ID\0DB_TRX_ID\0DB_ROLL_PTR";
+ DBUG_ASSERT(!memcmp(sys, system, sizeof system));
+ for (unsigned i = index->n_fields - n_remove; i < index->n_fields;
+ i++) {
+ if (index->fields[i].col->is_nullable()) {
+ index->n_nullable--;
+ }
+ }
+ index->n_fields -= n_remove;
+ index->n_def = index->n_fields;
+ memmove(names, sys, sizeof system);
+ memmove(cols + n, cols + n_cols - DATA_N_SYS_COLS,
+ DATA_N_SYS_COLS * sizeof *cols);
+ n_cols -= n_remove;
+ n_def = n_cols;
+ n_t_cols -= n_remove;
+ n_t_def -= n_remove;
+
+ for (unsigned i = DATA_N_SYS_COLS; i--; ) {
+ cols[n_cols - i].ind--;
+ }
+
+ if (dict_index_is_auto_gen_clust(index)) {
+ DBUG_ASSERT(index->n_uniq == 1);
+ dict_field_t* field = index->fields;
+ field->name = sys;
+ field->col = dict_table_get_sys_col(this, DATA_ROW_ID);
+ field++;
+ field->name = sys + sizeof "DB_ROW_ID";
+ field->col = dict_table_get_sys_col(this, DATA_TRX_ID);
+ field++;
+ field->name = sys + sizeof "DB_ROW_ID\0DB_TRX_ID";
+ field->col = dict_table_get_sys_col(this, DATA_ROLL_PTR);
+
+ /* Replace the DB_ROW_ID column in secondary indexes. */
+ while ((index = dict_table_get_next_index(index)) != NULL) {
+ field = &index->fields[index->n_fields - 1];
+ DBUG_ASSERT(field->col->mtype == DATA_SYS);
+ DBUG_ASSERT(field->col->prtype
+ == DATA_NOT_NULL + DATA_TRX_ID);
+ field->col--;
+ field->name = sys;
+ }
+
+ return;
+ }
+
+ dict_field_t* field = &index->fields[index->n_uniq];
+ field->name = sys + sizeof "DB_ROW_ID";
+ field->col = dict_table_get_sys_col(this, DATA_TRX_ID);
+ field++;
+ field->name = sys + sizeof "DB_ROW_ID\0DB_TRX_ID";
+ field->col = dict_table_get_sys_col(this, DATA_ROLL_PTR);
+}
+
+
+/** Check if record in clustered index is historical row.
+@param[in] rec clustered row
+@param[in] offsets offsets
+@return true if row is historical */
+bool
+dict_index_t::vers_history_row(
+ const rec_t* rec,
+ const rec_offs* offsets)
+{
+ ut_ad(is_primary());
+
+ ulint len;
+ dict_col_t& col= table->cols[table->vers_end];
+ ut_ad(col.vers_sys_end());
+ ulint nfield = dict_col_get_clust_pos(&col, this);
+ const byte *data = rec_get_nth_field(rec, offsets, nfield, &len);
+ if (col.vers_native()) {
+ ut_ad(len == sizeof trx_id_max_bytes);
+ return 0 != memcmp(data, trx_id_max_bytes, len);
+ }
+ ut_ad(len == sizeof timestamp_max_bytes);
+ return 0 != memcmp(data, timestamp_max_bytes, len);
+}
+
+/** Check if record in secondary index is historical row.
+@param[in] rec record in a secondary index
+@param[out] history_row true if row is historical
+@return true on error */
+bool
+dict_index_t::vers_history_row(
+ const rec_t* rec,
+ bool &history_row)
+{
+ ut_ad(!is_primary());
+
+ bool error = false;
+ mem_heap_t* heap = NULL;
+ dict_index_t* clust_index = NULL;
+ rec_offs offsets_[REC_OFFS_NORMAL_SIZE];
+ rec_offs* offsets = offsets_;
+ rec_offs_init(offsets_);
+
+ mtr_t mtr;
+ mtr.start();
+
+ rec_t* clust_rec =
+ row_get_clust_rec(BTR_SEARCH_LEAF, rec, this, &clust_index, &mtr);
+ if (clust_rec) {
+ offsets = rec_get_offsets(clust_rec, clust_index, offsets, true,
+ ULINT_UNDEFINED, &heap);
+
+ history_row = clust_index->vers_history_row(clust_rec, offsets);
+ } else {
+ ib::error() << "foreign constraints: secondary index is out of "
+ "sync";
+ ut_ad(!"secondary index is out of sync");
+ error = true;
+ }
+ mtr.commit();
+ if (heap) {
+ mem_heap_free(heap);
+ }
+ return(error);
}
diff --git a/storage/innobase/dict/dict0stats.cc b/storage/innobase/dict/dict0stats.cc
index 77c1e9627eb..4e6fb9d3ae4 100644
--- a/storage/innobase/dict/dict0stats.cc
+++ b/storage/innobase/dict/dict0stats.cc
@@ -292,7 +292,7 @@ dict_stats_exec_sql(
}
if (trx == NULL) {
- trx = trx_allocate_for_background();
+ trx = trx_create();
trx_started = true;
if (srv_read_only_mode) {
@@ -326,7 +326,7 @@ dict_stats_exec_sql(
}
if (trx_started) {
- trx_free_for_background(trx);
+ trx_free(trx);
}
return(err);
@@ -447,8 +447,6 @@ dict_stats_table_clone_create(
idx->name = mem_heap_strdup(heap, index->name);
- idx->table_name = t->name.m_name;
-
idx->table = t;
idx->type = index->type;
@@ -859,10 +857,8 @@ dict_stats_update_transient_for_index(
mtr_t mtr;
ulint size;
- mtr_start(&mtr);
-
- mtr_s_lock(dict_index_get_lock(index), &mtr);
-
+ mtr.start();
+ mtr_s_lock_index(index, &mtr);
size = btr_get_size(index, BTR_TOTAL_SIZE, &mtr);
if (size != ULINT_UNDEFINED) {
@@ -872,7 +868,7 @@ dict_stats_update_transient_for_index(
index, BTR_N_LEAF_PAGES, &mtr);
}
- mtr_commit(&mtr);
+ mtr.commit();
switch (size) {
case ULINT_UNDEFINED:
@@ -917,7 +913,7 @@ dict_stats_update_transient(
index = dict_table_get_first_index(table);
- if (dict_table_is_discarded(table)) {
+ if (!table->space) {
/* Nothing to do. */
dict_stats_empty_table(table, true);
return;
@@ -1037,10 +1033,10 @@ dict_stats_analyze_index_level(
memset(n_diff, 0x0, n_uniq * sizeof(n_diff[0]));
/* Allocate space for the offsets header (the allocation size at
- offsets[0] and the REC_OFFS_HEADER_SIZE bytes), and n_fields + 1,
+ offsets[0] and the REC_OFFS_HEADER_SIZE bytes), and n_uniq + 1,
so that this will never be less than the size calculated in
rec_get_offsets_func(). */
- i = (REC_OFFS_HEADER_SIZE + 1 + 1) + index->n_fields;
+ i = (REC_OFFS_HEADER_SIZE + 1 + 1) + n_uniq;
heap = mem_heap_create((2 * sizeof *rec_offsets) * i);
rec_offsets = static_cast<rec_offs*>(
@@ -1076,16 +1072,24 @@ dict_stats_analyze_index_level(
== page_rec_get_next_const(page_get_infimum_rec(page)));
/* check that we are indeed on the desired level */
- ut_a(btr_page_get_level(page, mtr) == level);
+ ut_a(btr_page_get_level(page) == level);
/* there should not be any pages on the left */
ut_a(!page_has_prev(page));
- /* check whether the first record on the leftmost page is marked
- as such, if we are on a non-leaf level */
- ut_a((level == 0)
- == !(REC_INFO_MIN_REC_FLAG & rec_get_info_bits(
- btr_pcur_get_rec(&pcur), page_is_comp(page))));
+ if (REC_INFO_MIN_REC_FLAG & rec_get_info_bits(
+ btr_pcur_get_rec(&pcur), page_is_comp(page))) {
+ ut_ad(btr_pcur_is_on_user_rec(&pcur));
+ if (level == 0) {
+ /* Skip the metadata pseudo-record */
+ ut_ad(index->is_instant());
+ btr_pcur_move_to_next_user_rec(&pcur, mtr);
+ }
+ } else {
+ /* The first record on the leftmost page must be
+ marked as such on each level except the leaf level. */
+ ut_a(level == 0);
+ }
prev_rec = NULL;
prev_rec_is_copied = false;
@@ -1148,8 +1152,7 @@ dict_stats_analyze_index_level(
n_uniq, &heap);
prev_rec = rec_copy_prefix_to_buf(
- prev_rec, index,
- rec_offs_n_fields(prev_rec_offsets),
+ prev_rec, index, n_uniq,
&prev_rec_buf, &prev_rec_buf_size);
prev_rec_is_copied = true;
@@ -1218,7 +1221,7 @@ dict_stats_analyze_index_level(
btr_pcur_move_to_next_user_rec() will release the
latch on the page that prev_rec is on */
prev_rec = rec_copy_prefix_to_buf(
- rec, index, rec_offs_n_fields(rec_offsets),
+ rec, index, n_uniq,
&prev_rec_buf, &prev_rec_buf_size);
prev_rec_is_copied = true;
@@ -1488,10 +1491,10 @@ dict_stats_analyze_index_below_cur(
offsets_rec = rec_get_offsets(rec, index, offsets1, false,
ULINT_UNDEFINED, &heap);
- page_id_t page_id(dict_index_get_space(index),
+ page_id_t page_id(index->table->space_id,
btr_node_ptr_get_child_page_no(
rec, offsets_rec));
- const page_size_t page_size(dict_table_page_size(index->table));
+ const page_size_t page_size(index->table->space->flags);
/* assume no external pages by default - in case we quit from this
function without analyzing any leaf pages */
@@ -1677,7 +1680,7 @@ dict_stats_analyze_index_for_n_prefix(
ut_ad(first_rec == page_rec_get_next_const(page_get_infimum_rec(page)));
/* check that we are indeed on the desired level */
- ut_a(btr_page_get_level(page, mtr) == n_diff_data->level);
+ ut_a(btr_page_get_level(page) == n_diff_data->level);
/* there should not be any pages on the left */
ut_a(!page_has_prev(page));
@@ -1734,9 +1737,6 @@ dict_stats_analyze_index_for_n_prefix(
ut_a(left <= right);
ut_a(right <= last_idx_on_level);
- /* we do not pass (left, right) because we do not want to ask
- ut_rnd_interval() to work with too big numbers since
- ib_uint64_t could be bigger than ulint */
const ulint rnd = ut_rnd_interval(
static_cast<ulint>(right - left));
@@ -1918,10 +1918,8 @@ dict_stats_analyze_index(
dict_stats_empty_index(index, false);
- mtr_start(&mtr);
-
- mtr_s_lock(dict_index_get_lock(index), &mtr);
-
+ mtr.start();
+ mtr_s_lock_index(index, &mtr);
size = btr_get_size(index, BTR_TOTAL_SIZE, &mtr);
if (size != ULINT_UNDEFINED) {
@@ -1930,7 +1928,7 @@ dict_stats_analyze_index(
}
/* Release the X locks on the root page taken by btr_get_size() */
- mtr_commit(&mtr);
+ mtr.commit();
switch (size) {
case ULINT_UNDEFINED:
@@ -1943,10 +1941,8 @@ dict_stats_analyze_index(
index->stat_n_leaf_pages = size;
- mtr_start(&mtr);
-
- mtr_sx_lock(dict_index_get_lock(index), &mtr);
-
+ mtr.start();
+ mtr_sx_lock_index(index, &mtr);
root_level = btr_height_get(index, &mtr);
n_uniq = dict_index_get_n_unique(index);
@@ -1986,7 +1982,7 @@ dict_stats_analyze_index(
index->stat_n_sample_sizes[i] = total_pages;
}
- mtr_commit(&mtr);
+ mtr.commit();
dict_stats_assert_initialized_index(index);
DBUG_VOID_RETURN;
@@ -2032,9 +2028,9 @@ dict_stats_analyze_index(
/* Commit the mtr to release the tree S lock to allow
other threads to do some work too. */
- mtr_commit(&mtr);
- mtr_start(&mtr);
- mtr_sx_lock(dict_index_get_lock(index), &mtr);
+ mtr.commit();
+ mtr.start();
+ mtr_sx_lock_index(index, &mtr);
if (root_level != btr_height_get(index, &mtr)) {
/* Just quit if the tree has changed beyond
recognition here. The old stats from previous
@@ -2172,7 +2168,7 @@ found_level:
data, &mtr);
}
- mtr_commit(&mtr);
+ mtr.commit();
UT_DELETE_ARRAY(n_diff_boundaries);
@@ -2301,7 +2297,7 @@ dict_stats_save_index_stat(
char db_utf8[MAX_DB_UTF8_LEN];
char table_utf8[MAX_TABLE_UTF8_LEN];
- ut_ad(!trx || trx->internal || trx->in_mysql_trx_list);
+ ut_ad(!trx || trx->internal || trx->mysql_thd);
ut_ad(rw_lock_own(&dict_operation_lock, RW_LOCK_X));
ut_ad(mutex_own(&dict_sys->mutex));
@@ -2313,7 +2309,7 @@ dict_stats_save_index_stat(
pars_info_add_str_literal(pinfo, "table_name", table_utf8);
pars_info_add_str_literal(pinfo, "index_name", index->name);
UNIV_MEM_ASSERT_RW_ABORT(&last_update, 4);
- pars_info_add_int4_literal(pinfo, "last_update", (lint)last_update);
+ pars_info_add_int4_literal(pinfo, "last_update", uint32(last_update));
UNIV_MEM_ASSERT_RW_ABORT(stat_name, strlen(stat_name));
pars_info_add_str_literal(pinfo, "stat_name", stat_name);
UNIV_MEM_ASSERT_RW_ABORT(&stat_value, 8);
@@ -2382,10 +2378,9 @@ dict_stats_report_error(dict_table_t* table, bool defragment)
{
dberr_t err;
- FilSpace space(table->space);
const char* df = defragment ? " defragment" : "";
- if (!space()) {
+ if (!table->space) {
ib::warn() << "Cannot save" << df << " statistics for table "
<< table->name
<< " because the .ibd file is missing. "
@@ -2394,7 +2389,8 @@ dict_stats_report_error(dict_table_t* table, bool defragment)
} else {
ib::warn() << "Cannot save" << df << " statistics for table "
<< table->name
- << " because file " << space()->chain.start->name
+ << " because file "
+ << table->space->chain.start->name
<< (table->corrupted
? " is corrupted."
: " cannot be decrypted.");
@@ -2444,7 +2440,7 @@ dict_stats_save(
pars_info_add_str_literal(pinfo, "database_name", db_utf8);
pars_info_add_str_literal(pinfo, "table_name", table_utf8);
- pars_info_add_int4_literal(pinfo, "last_update", (lint)now);
+ pars_info_add_int4_literal(pinfo, "last_update", uint32(now));
pars_info_add_ull_literal(pinfo, "n_rows", table->stat_n_rows);
pars_info_add_ull_literal(pinfo, "clustered_index_size",
table->stat_clustered_index_size);
@@ -2485,7 +2481,7 @@ dict_stats_save(
return(ret);
}
- trx_t* trx = trx_allocate_for_background();
+ trx_t* trx = trx_create();
trx_start_internal(trx);
dict_index_t* index;
@@ -2582,7 +2578,7 @@ dict_stats_save(
trx_commit_for_mysql(trx);
end:
- trx_free_for_background(trx);
+ trx_free(trx);
mutex_exit(&dict_sys->mutex);
rw_lock_x_unlock(&dict_operation_lock);
@@ -2890,7 +2886,7 @@ dict_stats_fetch_index_stats_step(
/* extract 12 from "n_diff_pfx12..." into n_pfx
note that stat_name does not have a terminating '\0' */
- n_pfx = (num_ptr[0] - '0') * 10 + (num_ptr[1] - '0');
+ n_pfx = ulong(num_ptr[0] - '0') * 10 + ulong(num_ptr[1] - '0');
ulint n_uniq = index->n_uniq;
@@ -2964,7 +2960,7 @@ dict_stats_fetch_from_ps(
stats. */
dict_stats_empty_table(table, true);
- trx = trx_allocate_for_background();
+ trx = trx_create();
/* Use 'read-uncommitted' so that the SELECTs we execute
do not get blocked in case some user has locked the rows we
@@ -3058,7 +3054,7 @@ dict_stats_fetch_from_ps(
trx_commit_for_mysql(trx);
- trx_free_for_background(trx);
+ trx_free(trx);
if (!index_fetch_arg.stats_were_modified) {
return(DB_STATS_DO_NOT_EXIST);
diff --git a/storage/innobase/dict/dict0stats_bg.cc b/storage/innobase/dict/dict0stats_bg.cc
index 589f53dde38..126de450ca5 100644
--- a/storage/innobase/dict/dict0stats_bg.cc
+++ b/storage/innobase/dict/dict0stats_bg.cc
@@ -83,6 +83,8 @@ typedef recalc_pool_t::iterator
/** Pool where we store information on which tables are to be processed
by background statistics gathering. */
static recalc_pool_t recalc_pool;
+/** Whether the global data structures have been initialized */
+static bool stats_initialised;
/*****************************************************************//**
Free the resources occupied by the recalc pool, called once during
@@ -299,7 +301,6 @@ dict_stats_thread_init()
dict_stats_event = os_event_create(0);
dict_stats_shutdown_event = os_event_create(0);
-
ut_d(dict_stats_disabled_event = os_event_create(0));
/* The recalc_pool_mutex is acquired from:
@@ -319,6 +320,7 @@ dict_stats_thread_init()
mutex_create(LATCH_ID_RECALC_POOL, &recalc_pool_mutex);
dict_defrag_pool_init();
+ stats_initialised = true;
}
/*****************************************************************//**
@@ -331,6 +333,12 @@ dict_stats_thread_deinit()
ut_a(!srv_read_only_mode);
ut_ad(!srv_dict_stats_thread_active);
+ if (!stats_initialised) {
+ return;
+ }
+
+ stats_initialised = false;
+
dict_stats_recalc_pool_deinit();
dict_defrag_pool_deinit();
@@ -373,7 +381,7 @@ dict_stats_process_entry_from_recalc_pool()
return;
}
- ut_ad(!dict_table_is_temporary(table));
+ ut_ad(!table->is_temporary());
if (!fil_table_accessible(table)) {
dict_table_close(table, TRUE, FALSE);
@@ -418,16 +426,9 @@ dict_stats_process_entry_from_recalc_pool()
#ifdef UNIV_DEBUG
/** Disables dict stats thread. It's used by:
SET GLOBAL innodb_dict_stats_disabled_debug = 1 (0).
-@param[in] thd thread handle
-@param[in] var pointer to system variable
-@param[out] var_ptr where the formal string goes
@param[in] save immediate result from check function */
-void
-dict_stats_disabled_debug_update(
- THD* thd,
- struct st_mysql_sys_var* var,
- void* var_ptr,
- const void* save)
+void dict_stats_disabled_debug_update(THD*, st_mysql_sys_var*, void*,
+ const void* save)
{
/* This method is protected by mutex, as every SET GLOBAL .. */
ut_ad(dict_stats_disabled_event != NULL);