/*****************************************************************//**
Based on a table object, this function builds the entry to be inserted
in the SYS_TABLES system table.
@return the tuple which should be inserted */ static
dtuple_t*
dict_create_sys_tables_tuple( /*=========================*/ const dict_table_t* table, /*!< in: table */
mem_heap_t* heap) /*!< in: memory heap from whichthememoryforthebuilt
tuple is allocated */
{
dtuple_t* entry;
dfield_t* dfield;
byte* ptr;
ulint type;
/* If there is any virtual column, encode it in N_COLS */
mach_write_to_4(ptr, dict_table_encode_n_col(
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);
/* Validate the table flags and convert them to what is saved in SYS_TABLES.TYPE.Tableflagvalues0and1arebothwrittento
SYS_TABLES.TYPE as 1. */
type = dict_tf_to_sys_tables_type(table->flags);
mach_write_to_4(ptr, type);
/*****************************************************************//**
Based on a table object, this function builds the entry to be inserted
in the SYS_COLUMNS system table.
@return the tuple which should be inserted */ static
dtuple_t*
dict_create_sys_columns_tuple( /*==========================*/ const dict_table_t* table, /*!< in: table */
ulint i, /*!< in: column number */
mem_heap_t* heap) /*!< in: memory heap from whichthememoryforthebuilt
tuple is allocated */
{
dtuple_t* entry; const dict_col_t* column;
dfield_t* dfield;
byte* ptr;
ulint num_base = 0;
ulint v_col_no = ULINT_UNDEFINED;
ut_ad(table);
ut_ad(heap);
/* Any column beyond table->n_def would be virtual columns */ if (i >= table->n_def) {
dict_v_col_t* v_col = dict_table_get_nth_v_col(
table, i - table->n_def);
column = &v_col->m_col;
num_base = v_col->num_base;
v_col_no = column->ind;
} else {
column = dict_table_get_nth_col(table, i);
ut_ad(!column->is_virtual());
}
if (v_col_no != ULINT_UNDEFINED) { /* encode virtual column's position in MySQL table and InnoDB
table in "POS" */
mach_write_to_4(ptr, dict_create_v_col_pos(
i - table->n_def, v_col_no));
} else {
mach_write_to_4(ptr, i);
}
dfield_set_data(dfield, ptr, 4);
/* 2: DB_TRX_ID added later */ /* 3: DB_ROLL_PTR added later */ /* 4: NAME ---------------------------*/
dfield = dtuple_get_nth_field(entry, DICT_COL__SYS_COLUMNS__NAME);
Lex_ident_column col_name= i >= table->n_def ?
dict_table_get_v_col_name(table, i - table->n_def) :
dict_table_get_col_name(table, i);
/** Based on a table object, this function builds the entry to be inserted intheSYS_VIRTUALsystemtable.Eachrowmapsavirtualcolumntooneof itsbasecolumn. @param[in]tabletable @param[in]v_col_nvirtualcolumnnumber @param[in]b_col_nbasecolumnsequencenum @param[in]heapmemoryheap
@return the tuple which should be inserted */ static
dtuple_t*
dict_create_sys_virtual_tuple( const dict_table_t* table,
ulint v_col_n,
ulint b_col_n,
mem_heap_t* heap)
{
dtuple_t* entry; const dict_col_t* base_column;
dfield_t* dfield;
byte* ptr;
/*****************************************************************//**
Based on an index object, this function builds the entry to be inserted
in the SYS_INDEXES system table.
@return the tuple which should be inserted */ static MY_ATTRIBUTE((nonnull, warn_unused_result))
dtuple_t*
dict_create_sys_indexes_tuple( /*==========================*/ const dict_index_t* index, /*!< in: index */
mem_heap_t* heap) /*!< in: memory heap from whichthememoryforthebuilt
tuple is allocated */
{
dtuple_t* entry;
dfield_t* dfield;
byte* ptr;
/*****************************************************************//**
Based on an index object, this function builds the entry to be inserted
in the SYS_FIELDS system table.
@return the tuple which should be inserted */ static
dtuple_t*
dict_create_sys_fields_tuple( /*=========================*/ const dict_index_t* index, /*!< in: index */
ulint fld_no, /*!< in: field number */
mem_heap_t* heap) /*!< in: memory heap from whichthememoryforthebuilt
tuple is allocated */
{
dtuple_t* entry;
dict_field_t* field;
dfield_t* dfield;
byte* ptr; bool wide_pos = false;
ut_ad(index);
ut_ad(heap);
for (unsigned j = 0; j < index->n_fields; j++) { const dict_field_t* f = dict_index_get_nth_field(index, j); if (f->prefix_len || f->descending) {
wide_pos = true; break;
}
}
if (wide_pos) { /* If there are column prefixes or columns with descendingorderintheindex,thenwewritethe fieldnumbertothe16mostsignificantbits, theDESCflagtobit15,andtheprefixlength
in the 15 least significant bits. */
mach_write_to_4(ptr, (fld_no << 16)
| (!!field->descending) << 15
| field->prefix_len);
} else { /* Else we store the number of the field to the 2 LOW bytes. Thisistokeepthestorageformatcompatiblewith
InnoDB versions < 4.0.14. */
mach_write_to_4(ptr, fld_no);
}
dfield_set_data(dfield, ptr, 4);
/* 2: DB_TRX_ID added later */ /* 3: DB_ROLL_PTR added later */ /* 4: COL_NAME -------------------------*/
dfield = dtuple_get_nth_field(entry, DICT_COL__SYS_FIELDS__COL_NAME);
/*****************************************************************//**
Creates the tuple with which the index entry is searched for writing the index
tree root page number, if such a tree is created.
@return the tuple for search */ static
dtuple_t*
dict_create_search_tuple( /*=====================*/ const dtuple_t* tuple, /*!< in: the tuple inserted in the SYS_INDEXES
table */
mem_heap_t* heap) /*!< in: memory heap from which the memory for
the built tuple is allocated */
{
dtuple_t* search_tuple; const dfield_t* field1;
dfield_t* field2;
/* Note that the index was created by this transaction. */
index->trx_id = trx->id;
ut_ad(table->def_trx_id <= trx->id);
table->def_trx_id = trx->id;
table->release();
return(DB_SUCCESS);
}
/***************************************************************//**
Builds an index definition without updating SYSTEM TABLES.
@return DB_SUCCESS or error code */ void
dict_build_index_def( /*=================*/ const dict_table_t* table, /*!< in: table */
dict_index_t* index, /*!< in/out: index */
trx_t* trx) /*!< in/out: InnoDB transaction handle */
{
ut_ad(dict_sys.locked());
/***************************************************************//**
Creates an index tree for the index.
@return DB_SUCCESS or DB_OUT_OF_FILE_SPACE */ static MY_ATTRIBUTE((nonnull, warn_unused_result))
dberr_t dict_create_index_tree_step(ind_node_t *node, trx_t *trx)
{
mtr_t mtr{trx};
btr_pcur_t pcur;
dict_index_t* index;
dtuple_t* search_tuple;
ut_ad(dict_sys.locked());
index = node->index;
if (index->type == DICT_FTS) { /* FTS index does not need an index tree */ return(DB_SUCCESS);
}
/* Run a mini-transaction in which the index tree is allocated for theindexanditsrootaddressiswrittentotheindexentryin
sys_indexes */
/***************************************************************//**
Creates an index tree for the index if it is not a member of a cluster.
Don't update SYSTEM TABLES.
@return error code */
dberr_t
dict_create_index_tree_in_mem( /*==========================*/
dict_index_t* index, /*!< in/out: index */
trx_t* trx) /*!< in: InnoDB transaction handle */
{
mtr_t mtr{trx};
/* 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(!(index->table->flags2 & DICT_TF2_DISCARDED));
/** Drop the index tree associated with a row in SYS_INDEXES table. @param[in,out]pcurpersistentcursoronrec @param[in,out]trxdictionarytransaction @param[in,out]mtrmini-transaction @returntablespaceIDtodrop(ifthisistheclusteredindex)
@retval 0 if no tablespace is to be dropped */
uint32_t dict_drop_index_tree(btr_pcur_t *pcur, trx_t *trx, mtr_t *mtr)
{
rec_t *rec= btr_pcur_get_rec(pcur);
if (space_id && (type & DICT_CLUSTERED)) return space_id;
if (root_page_no == FIL_NULL) /* The tree has already been freed */; elseif (fil_space_t*s= fil_space_t::get(space_id))
{ /* Ensure that the tablespace file exists
in order to avoid a crash in buf_page_get_gen(). */ if (root_page_no < s->get_size())
{
static_assert(FIL_NULL == 0xffffffff, "compatibility");
static_assert(DICT_FLD__SYS_INDEXES__PAGE_NO ==
DICT_FLD__SYS_INDEXES__SPACE + 1, "compatibility");
mtr->memset(btr_pcur_get_block(pcur), p + 4 - btr_pcur_get_page(pcur), 4, 0xff);
btr_free_if_exists(s, root_page_no, mach_read_from_8(rec + 8), mtr);
}
s->release();
}
return0;
}
/*********************************************************************//**
Creates a table create graph.
@return own: table create node */
tab_node_t*
tab_create_graph_create( /*====================*/
dict_table_t* table, /*!< in: table to create, built as a memory data
structure */
mem_heap_t* heap) /*!< in: heap where created */
{
tab_node_t* node;
/***********************************************************//**
Creates a table. This is a high-level function used in SQL execution graphs.
@return query thread to run next or NULL */
que_thr_t*
dict_create_table_step( /*===================*/
que_thr_t* thr) /*!< in: query thread */
{
tab_node_t* node;
dberr_t err = DB_ERROR;
trx_t* trx;
/* If no base column */ while (v_col->num_base == 0) {
node->col_no++; if (node->col_no == static_cast<ulint>(
(node->table)->n_v_def)) {
node->state = TABLE_ADD_TO_CACHE; break;
}
if (node->state != TABLE_ADD_TO_CACHE) {
ut_ad(node->col_no == v_col->v_pos);
dict_build_v_col_def_step(node);
if (node->base_col_no
< unsigned{v_col->num_base} - 1) { /* move on to next base column */
node->base_col_no++;
} else { /* move on to next virtual column */
node->col_no++;
node->base_col_no = 0;
}
/* We create a new single-table tablespace for the table. Weinitiallyletitbe4pages: -page0isthefspheaderandanextentdescriptorpage, -page1isanibufbitmappage, -page2isthefirstinodepage, -page3willcontaintherootoftheclusteredindexof
the table we create here. */
dberr_t err;
table->space= fil_ibd_create(table->space_id, table->name, filepath,
dict_tf_to_fsp_flags(table->flags),
FIL_IBD_FILE_INITIAL_SIZE,
node.mode, node.key_id, &err);
ut_ad((err != DB_SUCCESS) == !table->space);
ut_free(filepath);
return err;
}
/***********************************************************//**
Creates an index. This is a high-level function used in SQL execution
graphs.
@return query thread to run next or NULL */
que_thr_t*
dict_create_index_step( /*===================*/
que_thr_t* thr) /*!< in: query thread */
{
ind_node_t* node;
dberr_t err = DB_ERROR;
trx_t* trx;
if (err != DB_SUCCESS) {
dict_table_t* table = node->index->table; /* If this is a FTS index, we will need to remove
it from fts->cache->indexes list as well */ if (!(node->index->type & DICT_FTS)) {
} elseif (auto fts = table->fts) {
fts_index_cache_t* index_cache;
node->index->page = node->page_no; /* These should have been set in dict_build_index_def_step()and
dict_index_add_to_cache(). */
ut_ad(node->index->trx_id == trx->id);
ut_ad(node->index->table->def_trx_id == trx->id);
}
function_exit:
trx->error_state = err;
if (UNIV_UNLIKELY(err != DB_SUCCESS)) { return nullptr;
}
if (recv_sys.rpo || srv_force_recovery >= SRV_FORCE_NO_TRX_UNDO) return DB_READ_ONLY;
if (load_sys_tables())
{
sql_print_information("InnoDB: Set innodb_read_only=1 " "or innodb_force_recovery=3 to start up"); return DB_CORRUPTION;
}
if (sys_tables_exist()) return DB_SUCCESS;
trx_t *trx= trx_create();
trx_start_for_ddl(trx);
{ /* Do not bother with transactional memory; this is only
executed at startup, with no conflicts present. */
LockMutexGuard g{SRW_LOCK_CALL};
trx->mutex_lock();
lock_table_create(dict_sys.sys_tables, LOCK_X, trx);
lock_table_create(dict_sys.sys_columns, LOCK_X, trx);
lock_table_create(dict_sys.sys_indexes, LOCK_X, trx);
lock_table_create(dict_sys.sys_fields, LOCK_X, trx);
trx->mutex_unlock();
}
row_mysql_lock_data_dictionary(trx);
/* NOTE: when designing InnoDB's foreign key support in 2001, Heikki Tuuri madeamistakeanddefinedtablenamesandtheforeignkeyidtobeoftype
CHAR (internally, really VARCHAR). The type should have been VARBINARY. */
/* System tables are always created inside the system tablespace. */ constauto srv_file_per_table_backup= srv_file_per_table;
srv_file_per_table= 0;
dberr_t error;
span<constchar> tablename;
if (!sys_foreign)
{
error= que_eval_sql(nullptr, "PROCEDURE CREATE_FOREIGN() IS\n" "BEGIN\n" "CREATE TABLE\n" "SYS_FOREIGN(ID CHAR, FOR_NAME CHAR," " REF_NAME CHAR, N_COLS INT);\n" "CREATE UNIQUE CLUSTERED INDEX ID_IND" " ON SYS_FOREIGN (ID);\n" "CREATE INDEX FOR_IND" " ON SYS_FOREIGN (FOR_NAME);\n" "CREATE INDEX REF_IND" " ON SYS_FOREIGN (REF_NAME);\n" "END;\n", trx); if (UNIV_UNLIKELY(error != DB_SUCCESS))
{
tablename= SYS_TABLE[SYS_FOREIGN];
err_exit:
sql_print_error("InnoDB: Creation of %.*s failed: %s", int(tablename.size()), tablename.data(),
ut_strerr(error));
trx->rollback();
row_mysql_unlock_data_dictionary(trx);
trx->clear_and_free();
srv_file_per_table= srv_file_per_table_backup; return error;
}
} if (!sys_foreign_cols)
{
error= que_eval_sql(nullptr, "PROCEDURE CREATE_FOREIGN_COLS() IS\n" "BEGIN\n" "CREATE TABLE\n" "SYS_FOREIGN_COLS(ID CHAR, POS INT," " FOR_COL_NAME CHAR, REF_COL_NAME CHAR);\n" "CREATE UNIQUE CLUSTERED INDEX ID_IND" " ON SYS_FOREIGN_COLS (ID, POS);\n" "END;\n", trx); if (UNIV_UNLIKELY(error != DB_SUCCESS))
{
tablename= SYS_TABLE[SYS_FOREIGN_COLS]; goto err_exit;
}
} if (!sys_virtual)
{
DBUG_EXECUTE_IF("defer_sys_virtual", goto commit_trx;);
error= que_eval_sql(nullptr, "PROCEDURE CREATE_VIRTUAL() IS\n" "BEGIN\n" "CREATE TABLE\n" "SYS_VIRTUAL(TABLE_ID BIGINT,POS INT,BASE_POS INT);\n" "CREATE UNIQUE CLUSTERED INDEX BASE_IDX" " ON SYS_VIRTUAL(TABLE_ID, POS, BASE_POS);\n" "END;\n", trx); if (UNIV_UNLIKELY(error != DB_SUCCESS))
{
tablename= SYS_TABLE[SYS_VIRTUAL]; goto err_exit;
}
}
DBUG_EXECUTE_IF("create_sys_tablespaces",
{
error= que_eval_sql(
nullptr, "PROCEDURE CREATE_DUMMY_1() IS\n" "BEGIN\n" "CREATE TABLE\n" "SYS_TABLESPACES(DUMMY_ID BIGINT, POS INT);\n" "CREATE UNIQUE CLUSTERED INDEX DUMMY_IND" " ON SYS_TABLESPACES(DUMMY_ID, POS);\n" "CREATE TABLE\n" "SYS_METADATA(DUMMY_ID_1 BIGINT, POS INT);\n" "CREATE UNIQUE CLUSTERED INDEX DUMMY_IND_1" " ON SYS_METADATA(DUMMY_ID_1, POS);\n" "DELETE FROM SYS_TABLES WHERE NAME= 'SYS_METADATA';" "END;\n", trx); if (error)
{
tablename = "DUMMY"; goto err_exit;
}
}); #ifndef DBUG_OFF
commit_trx: #endif/* !DBUG_OFF */
trx->commit();
row_mysql_unlock_data_dictionary(trx);
trx->clear_and_free();
srv_file_per_table= srv_file_per_table_backup;
/****************************************************************//**
Evaluate the given foreign key SQL statement.
@return error code or DB_SUCCESS */ static MY_ATTRIBUTE((nonnull, warn_unused_result))
dberr_t
dict_foreign_eval_sql( /*==================*/
pars_info_t* info, /*!< in: info struct */ constchar* sql, /*!< in: SQL string to evaluate */ constchar* name, /*!< in: table name (for diagnostics) */ constchar* id, /*!< in: foreign key id */
trx_t* trx) /*!< in/out: transaction */
{
FILE* ef = dict_foreign_err_file;
dberr_t error = que_eval_sql(info, sql, trx);
switch (error) { case DB_SUCCESS: break; case DB_DUPLICATE_KEY:
mysql_mutex_lock(&dict_foreign_err_mutex);
rewind(ef);
ut_print_timestamp(ef);
fputs(" Error in foreign key constraint creation for table ",
ef);
ut_print_name(ef, trx, name);
fputs(".\nA foreign key constraint of name ", ef);
ut_print_name(ef, trx, id);
fputs("\nalready exists." " (Note that internally InnoDB adds 'databasename'\n" "in front of the user-defined constraint name.)\n" "Note that InnoDB's FOREIGN KEY system tables store\n" "constraint names as case-insensitive, with the\n" "MariaDB standard latin1_swedish_ci collation. If you\n" "create tables or databases whose names differ only in\n" "the character case, then collisions in constraint\n" "names can occur. Workaround: name your constraints\n" "explicitly with unique names.\n",
ef); goto release; default:
sql_print_error("InnoDB: " "Foreign key constraint creation failed: %s",
ut_strerr(error));
mysql_mutex_lock(&dict_foreign_err_mutex);
ut_print_timestamp(ef);
fputs(" Internal error in foreign key constraint creation" " for table ", ef);
ut_print_name(ef, trx, name);
fputs(".\n" "See the MariaDB .err log in the datadir" " for more information.\n", ef);
release:
mysql_mutex_unlock(&dict_foreign_err_mutex);
}
return error;
}
/********************************************************************//**
Add a single foreign key field definition to the data dictionary tables in
the database.
@return error code or DB_SUCCESS */ static MY_ATTRIBUTE((nonnull, warn_unused_result))
dberr_t
dict_create_add_foreign_field_to_dictionary( /*========================================*/
ulint field_nr, /*!< in: field number */ constchar* table_name, /*!< in: table name */ const dict_foreign_t* foreign, /*!< in: foreign */
trx_t* trx) /*!< in/out: transaction */
{
DBUG_ENTER("dict_create_add_foreign_field_to_dictionary");
for (ulint i = 0; i < foreign->n_fields; i++) {
error = dict_create_add_foreign_field_to_dictionary(
i, name, foreign, trx);
if (error != DB_SUCCESS) { goto err_exit;
}
}
DBUG_RETURN(error);
}
/** Check if a foreign constraint is on the given column name. @param[in]col_namecolumnnametobesearchedforfkconstraint @param[in]tabletabletowhichforeignkeyconstraintbelongs
@return true if fk constraint is present on the table, false otherwise. */ static bool
dict_foreign_base_for_stored( constchar* col_name, const dict_table_t* table)
{ /* Loop through each stored column and check if its base column has
the same name as the column name being checked */
dict_s_col_list::const_iterator it; for (it = table->s_cols->begin();
it != table->s_cols->end(); ++it) {
dict_s_col_t s_col = *it;
/** Check if a foreign constraint is on columns served as base columns ofanystoredcolumn.ThisistopreventcreatingSETNULLorCASCADE constraintonsuchcolumns @param[in]local_fk_setsetofforeignkeyobjects,tobeaddedto thedictionarytables @param[in]tabletabletowhichtheforeignkeyobjectsin local_fk_setbelongto
@return true if yes, otherwise, false */ bool
dict_foreigns_has_s_base_col( const dict_foreign_set& local_fk_set, const dict_table_t* table)
{
dict_foreign_t* foreign;
if (table->s_cols == NULL) { return (false);
}
for (dict_foreign_set::const_iterator it = local_fk_set.begin();
it != local_fk_set.end(); ++it) {
foreign = *it;
ulint type = foreign->type;
type &= ~(foreign->DELETE_NO_ACTION
| foreign->UPDATE_NO_ACTION);
if (type == 0) { continue;
}
for (ulint i = 0; i < foreign->n_fields; i++) { /* Check if the constraint is on a column that
is a base column of any stored column */ if (dict_foreign_base_for_stored(
foreign->foreign_col_names[i], table)) { return(true);
}
}
}
return(false);
}
/** Adds the given set of foreign key objects to the dictionary tables inthedatabase.Thisfunctiondoesnotmodifythedictionarycache.The callermustensurethatallforeignkeyobjectscontainavalidconstraint nameinforeign->id. @param[in]local_fk_setsetofforeignkeyobjects,tobeaddedto thedictionarytables @param[in]tabletabletowhichtheforeignkeyobjectsin local_fk_setbelongto @param[in,out]trxtransaction
@return error code or DB_SUCCESS */
dberr_t
dict_create_add_foreigns_to_dictionary( /*===================================*/ const dict_foreign_set& local_fk_set, const dict_table_t* table,
trx_t* trx)
{
ut_ad(dict_sys.locked());
if (!dict_sys.sys_foreign)
{
sql_print_error("InnoDB: Table SYS_FOREIGN not found" " in internal data dictionary"); return DB_ERROR;
}
bool strict_mode = trx->mysql_thd->is_strict_mode(); for (auto fk : local_fk_set) if (strict_mode && !fk->check_fk_constraint_valid()) return DB_CANNOT_ADD_CONSTRAINT; elseif (dberr_t error= dict_create_add_foreign_to_dictionary
(table->name.m_name, fk, trx)) return error;
return DB_SUCCESS;
}
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.31 Sekunden
(vorverarbeitet am 2026-10-08)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.