📄 dict0crea.c
字号:
} if (node->state == TABLE_COMMIT_WORK) { /* Table was correctly defined: do NOT commit the transaction (CREATE TABLE does NOT do an implicit commit of the current transaction) */ node->state = TABLE_ADD_TO_CACHE; /* thr->run_node = node->commit_node; return(thr); */ } if (node->state == TABLE_ADD_TO_CACHE) { dict_table_add_to_cache(node->table); err = DB_SUCCESS; }function_exit: trx->error_state = err; if (err == DB_SUCCESS) { /* Ok: do nothing */ } else if (err == DB_LOCK_WAIT) { return(NULL); } else { /* SQL error detected */ return(NULL); } thr->run_node = que_node_get_parent(node); return(thr);} /***************************************************************Creates an index. This is a high-level function used in SQL executiongraphs. */que_thr_t*dict_create_index_step(/*===================*/ /* out: query thread to run next or NULL */ que_thr_t* thr) /* in: query thread */{ ind_node_t* node; ibool success; ulint err = DB_ERROR; trx_t* trx; ut_ad(thr);#ifdef UNIV_SYNC_DEBUG ut_ad(mutex_own(&(dict_sys->mutex)));#endif /* UNIV_SYNC_DEBUG */ trx = thr_get_trx(thr); node = thr->run_node; ut_ad(que_node_get_type(node) == QUE_NODE_CREATE_INDEX); if (thr->prev_node == que_node_get_parent(node)) { node->state = INDEX_BUILD_INDEX_DEF; } if (node->state == INDEX_BUILD_INDEX_DEF) { /* DO THE CHECKS OF THE CONSISTENCY CONSTRAINTS HERE */ err = dict_build_index_def_step(thr, node); if (err != DB_SUCCESS) { goto function_exit; } node->state = INDEX_BUILD_FIELD_DEF; node->field_no = 0; thr->run_node = node->ind_def; return(thr); } if (node->state == INDEX_BUILD_FIELD_DEF) { if (node->field_no < (node->index)->n_fields) { err = dict_build_field_def_step(node); if (err != DB_SUCCESS) { goto function_exit; } node->field_no++; thr->run_node = node->field_def; return(thr); } else { node->state = INDEX_CREATE_INDEX_TREE; } } if (node->state == INDEX_CREATE_INDEX_TREE) { err = dict_create_index_tree_step(node); if (err != DB_SUCCESS) { goto function_exit; } node->state = INDEX_COMMIT_WORK; } if (node->state == INDEX_COMMIT_WORK) { /* Index was correctly defined: do NOT commit the transaction (CREATE INDEX does NOT currently do an implicit commit of the current transaction) */ node->state = INDEX_ADD_TO_CACHE; /* thr->run_node = node->commit_node; return(thr); */ } if (node->state == INDEX_ADD_TO_CACHE) { success = dict_index_add_to_cache(node->table, node->index, node->page_no); ut_a(success); err = DB_SUCCESS; }function_exit: trx->error_state = err; if (err == DB_SUCCESS) { /* Ok: do nothing */ } else if (err == DB_LOCK_WAIT) { return(NULL); } else { /* SQL error detected */ return(NULL); } thr->run_node = que_node_get_parent(node); return(thr);} /********************************************************************Creates the foreign key constraints system tables inside InnoDBat database creation or database start if they are not found or arenot of the right form. */ulintdict_create_or_check_foreign_constraint_tables(void)/*================================================*/ /* out: DB_SUCCESS or error code */{ dict_table_t* table1; dict_table_t* table2; que_thr_t* thr; que_t* graph; ulint error; trx_t* trx; const char* str; mutex_enter(&(dict_sys->mutex)); table1 = dict_table_get_low("SYS_FOREIGN"); table2 = dict_table_get_low("SYS_FOREIGN_COLS"); if (table1 && table2 && UT_LIST_GET_LEN(table1->indexes) == 3 && UT_LIST_GET_LEN(table2->indexes) == 1) { /* Foreign constraint system tables have already been created, and they are ok */ mutex_exit(&(dict_sys->mutex)); return(DB_SUCCESS); } mutex_exit(&(dict_sys->mutex)); trx = trx_allocate_for_mysql(); trx->op_info = "creating foreign key sys tables"; row_mysql_lock_data_dictionary(trx); if (table1) { fprintf(stderr, "InnoDB: dropping incompletely created SYS_FOREIGN table\n"); row_drop_table_for_mysql("SYS_FOREIGN", trx, TRUE); } if (table2) { fprintf(stderr, "InnoDB: dropping incompletely created SYS_FOREIGN_COLS table\n"); row_drop_table_for_mysql("SYS_FOREIGN_COLS", trx, TRUE); } fprintf(stderr, "InnoDB: Creating foreign key constraint system tables\n"); /* NOTE: in dict_load_foreigns we use the fact that there are 2 secondary indexes on SYS_FOREIGN, and they are defined just like below */ /* NOTE: when designing InnoDB's foreign key support in 2001, we made an error and made the table names and the foreign key id of type 'CHAR' (internally, really a VARCHAR). We should have made the type VARBINARY, like in other InnoDB system tables, to get a clean design. */ str = "PROCEDURE CREATE_FOREIGN_SYS_TABLES_PROC () IS\n" "BEGIN\n" "CREATE TABLE\n" "SYS_FOREIGN(ID CHAR, FOR_NAME CHAR, REF_NAME CHAR, N_COLS INT);\n" "CREATE UNIQUE CLUSTERED INDEX ID_IND ON SYS_FOREIGN (ID);\n" "CREATE INDEX FOR_IND ON SYS_FOREIGN (FOR_NAME);\n" "CREATE INDEX REF_IND ON SYS_FOREIGN (REF_NAME);\n" "CREATE TABLE\n" "SYS_FOREIGN_COLS(ID CHAR, POS INT, FOR_COL_NAME CHAR, REF_COL_NAME CHAR);\n" "CREATE UNIQUE CLUSTERED INDEX ID_IND ON SYS_FOREIGN_COLS (ID, POS);\n" "COMMIT WORK;\n" "END;\n"; graph = pars_sql(str); ut_a(graph); graph->trx = trx; trx->graph = NULL; graph->fork_type = QUE_FORK_MYSQL_INTERFACE; ut_a(thr = que_fork_start_command(graph)); que_run_threads(thr); error = trx->error_state; if (error != DB_SUCCESS) { fprintf(stderr, "InnoDB: error %lu in creation\n", (ulong) error); ut_a(error == DB_OUT_OF_FILE_SPACE); fprintf(stderr, "InnoDB: creation failed\n"); fprintf(stderr, "InnoDB: tablespace is full\n"); fprintf(stderr, "InnoDB: dropping incompletely created SYS_FOREIGN tables\n"); row_drop_table_for_mysql("SYS_FOREIGN", trx, TRUE); row_drop_table_for_mysql("SYS_FOREIGN_COLS", trx, TRUE); error = DB_MUST_GET_MORE_FILE_SPACE; } que_graph_free(graph); trx->op_info = ""; row_mysql_unlock_data_dictionary(trx); trx_free_for_mysql(trx); if (error == DB_SUCCESS) { fprintf(stderr, "InnoDB: Foreign key constraint system tables created\n"); } return(error);}/************************************************************************Adds foreign key definitions to data dictionary tables in the database. Welook at table->foreign_list, and also generate names to constraints that werenot named by the user. A generated constraint has a name of the formatdatabasename/tablename_ibfk_<number>, where the numbers start from 1, and aregiven locally for this table, that is, the number is not global, as in theold format constraints < 4.0.18 it used to be. */ulintdict_create_add_foreigns_to_dictionary(/*===================================*/ /* out: error code or DB_SUCCESS */ ulint start_id,/* in: if we are actually doing ALTER TABLE ADD CONSTRAINT, we want to generate constraint numbers which are bigger than in the table so far; we number the constraints from start_id + 1 up; start_id should be set to 0 if we are creating a new table, or if the table so far has no constraints for which the name was generated here */ dict_table_t* table, /* in: table */ trx_t* trx) /* in: transaction */{ dict_foreign_t* foreign; que_thr_t* thr; que_t* graph; ulint number = start_id + 1; ulint len; ulint error; FILE* ef = dict_foreign_err_file; ulint i; char* sql; char* sqlend; /* This procedure builds an InnoDB stored procedure which will insert the necessary rows into SYS_FOREIGN and SYS_FOREIGN_COLS. */ static const char str1[] = "PROCEDURE ADD_FOREIGN_DEFS_PROC () IS\n" "BEGIN\n" "INSERT INTO SYS_FOREIGN VALUES("; static const char str2[] = ");\n"; static const char str3[] = "INSERT INTO SYS_FOREIGN_COLS VALUES("; static const char str4[] = "COMMIT WORK;\n" "END;\n";#ifdef UNIV_SYNC_DEBUG ut_ad(mutex_own(&(dict_sys->mutex)));#endif /* UNIV_SYNC_DEBUG */ if (NULL == dict_table_get_low("SYS_FOREIGN")) { fprintf(stderr, "InnoDB: table SYS_FOREIGN not found from internal data dictionary\n"); return(DB_ERROR); } foreign = UT_LIST_GET_FIRST(table->foreign_list);loop: if (foreign == NULL) { return(DB_SUCCESS); } if (foreign->id == NULL) { /* Generate a new constraint id */ ulint namelen = strlen(table->name); char* id = mem_heap_alloc(foreign->heap, namelen + 20); /* no overflow if number < 1e13 */ sprintf(id, "%s_ibfk_%lu", table->name, (ulong) number++); foreign->id = id; } len = (sizeof str1) + (sizeof str2) + (sizeof str4) - 3 + 9/* ' and , chars */ + 10/* 32-bit integer */ + ut_strlenq(foreign->id, '\'') * (foreign->n_fields + 1) + ut_strlenq(table->name, '\'') + ut_strlenq(foreign->referenced_table_name, '\''); for (i = 0; i < foreign->n_fields; i++) { len += 9/* ' and , chars */ + 10/* 32-bit integer */ + (sizeof str3) + (sizeof str2) - 2 + ut_strlenq(foreign->foreign_col_names[i], '\'') + ut_strlenq(foreign->referenced_col_names[i], '\''); } sql = sqlend = mem_alloc(len + 1); /* INSERT INTO SYS_FOREIGN VALUES(...); */ memcpy(sqlend, str1, (sizeof str1) - 1); sqlend += (sizeof str1) - 1; *sqlend++ = '\''; sqlend = ut_strcpyq(sqlend, '\'', foreign->id); *sqlend++ = '\'', *sqlend++ = ',', *sqlend++ = '\''; sqlend = ut_strcpyq(sqlend, '\'', table->name); *sqlend++ = '\'', *sqlend++ = ',', *sqlend++ = '\''; sqlend = ut_strcpyq(sqlend, '\'', foreign->referenced_table_name); *sqlend++ = '\'', *sqlend++ = ','; sqlend += sprintf(sqlend, "%010lu", foreign->n_fields + (foreign->type << 24)); memcpy(sqlend, str2, (sizeof str2) - 1); sqlend += (sizeof str2) - 1; for (i = 0; i < foreign->n_fields; i++) { /* INSERT INTO SYS_FOREIGN_COLS VALUES(...); */ memcpy(sqlend, str3, (sizeof str3) - 1); sqlend += (sizeof str3) - 1; *sqlend++ = '\''; sqlend = ut_strcpyq(sqlend, '\'', foreign->id); *sqlend++ = '\''; *sqlend++ = ','; sqlend += sprintf(sqlend, "%010lu", (ulong) i); *sqlend++ = ','; *sqlend++ = '\''; sqlend = ut_strcpyq(sqlend, '\'', foreign->foreign_col_names[i]); *sqlend++ = '\''; *sqlend++ = ','; *sqlend++ = '\''; sqlend = ut_strcpyq(sqlend, '\'', foreign->referenced_col_names[i]); *sqlend++ = '\''; memcpy(sqlend, str2, (sizeof str2) - 1); sqlend += (sizeof str2) - 1; } memcpy(sqlend, str4, sizeof str4); sqlend += sizeof str4; ut_a(sqlend == sql + len + 1); graph = pars_sql(sql); ut_a(graph); mem_free(sql); graph->trx = trx; trx->graph = NULL; graph->fork_type = QUE_FORK_MYSQL_INTERFACE; ut_a(thr = que_fork_start_command(graph)); que_run_threads(thr); error = trx->error_state; que_graph_free(graph); if (error == DB_DUPLICATE_KEY) { mutex_enter(&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, table->name); fputs(".\nA foreign key constraint of name ", ef); ut_print_name(ef, trx, foreign->id); fputs("\nalready exists." " (Note that internally InnoDB adds 'databasename/'\n" "in front of the user-defined constraint name).\n", ef); fputs("Note that InnoDB's FOREIGN KEY system tables store\n" "constraint names as case-insensitive, with the\n" "MySQL 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); mutex_exit(&dict_foreign_err_mutex); return(error); } if (error != DB_SUCCESS) { fprintf(stderr, "InnoDB: Foreign key constraint creation failed:\n" "InnoDB: internal error number %lu\n", (ulong) error); mutex_enter(&dict_foreign_err_mutex); ut_print_timestamp(ef); fputs(" Internal error in foreign key constraint creation" " for table ", ef); ut_print_name(ef, trx, table->name); fputs(".\n" "See the MySQL .err log in the datadir for more information.\n", ef); mutex_exit(&dict_foreign_err_mutex); return(error); } foreign = UT_LIST_GET_NEXT(foreign_list, foreign); goto loop;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -