diff options
Diffstat (limited to 'innobase/row/row0mysql.c')
-rw-r--r-- | innobase/row/row0mysql.c | 137 |
1 files changed, 98 insertions, 39 deletions
diff --git a/innobase/row/row0mysql.c b/innobase/row/row0mysql.c index 1bb33551da8..6d1f6f6e40e 100644 --- a/innobase/row/row0mysql.c +++ b/innobase/row/row0mysql.c @@ -6,7 +6,7 @@ Contains also create table and other data dictionary operations. Created 9/17/2000 Heikki Tuuri *******************************************************/ - + #include "row0mysql.h" #ifdef UNIV_NONINL @@ -289,6 +289,17 @@ handle_new_error: "InnoDB: my.cnf and restart the database.\n"); exit(1); + } else if (err == DB_CORRUPTION) { + + fprintf(stderr, + "InnoDB: We detected index corruption in an InnoDB type table.\n" + "InnoDB: You have to dump + drop + reimport the table or, in\n" + "InnoDB: a case of widespread corruption, dump all InnoDB\n" + "InnoDB: tables and recreate the whole InnoDB tablespace.\n" + "InnoDB: If the mysqld server crashes after the startup or when\n" + "InnoDB: you dump the tables, look at section 6.1 of\n" + "InnoDB: http://www.innodb.com/ibman.html for help.\n"); + } else { fprintf(stderr, "InnoDB: unknown error code %lu\n", err); ut_a(0); @@ -337,6 +348,9 @@ row_create_prebuilt( prebuilt->mysql_has_locked = FALSE; prebuilt->index = NULL; + + prebuilt->used_in_HANDLER = FALSE; + prebuilt->n_template = 0; prebuilt->mysql_template = NULL; @@ -1169,7 +1183,7 @@ row_mysql_recover_tmp_table( return(DB_ERROR); } - if (0 == ut_memcmp(ptr, "/rsql", 5)) { + if (0 == ut_memcmp(ptr, (char*)"/rsql", 5)) { ptr++; *ptr = '#'; @@ -1293,10 +1307,10 @@ row_create_table_for_mysql( } trx->op_info = (char *) "creating table"; - - if (0 == ut_strcmp(table->name, "mysql/host") - || 0 == ut_strcmp(table->name, "mysql/user") - || 0 == ut_strcmp(table->name, "mysql/db")) { + + if (0 == ut_strcmp(table->name, (char*)"mysql/host") + || 0 == ut_strcmp(table->name, (char*)"mysql/user") + || 0 == ut_strcmp(table->name, (char*)"mysql/db")) { fprintf(stderr, "InnoDB: Error: trying to create a MySQL system table %s of type InnoDB.\n" @@ -1316,7 +1330,7 @@ row_create_table_for_mysql( if (namelen >= keywordlen && 0 == ut_memcmp(table->name + namelen - keywordlen, - "_recover_innodb_tmp_table", keywordlen)) { + (char*)"_recover_innodb_tmp_table", keywordlen)) { /* MySQL prevents accessing of tables whose name begins with #sql, that is temporary tables. If mysqld crashes in @@ -1384,7 +1398,7 @@ row_create_table_for_mysql( if (namelen >= keywordlen && 0 == ut_memcmp(table->name + namelen - keywordlen, - "innodb_mem_validate", keywordlen)) { + (char*)"innodb_mem_validate", keywordlen)) { /* We define here a debugging feature intended for developers */ @@ -1494,7 +1508,7 @@ row_create_index_for_mysql( if (namelen >= keywordlen && 0 == ut_memcmp( index->table_name + namelen - keywordlen, - "_recover_innodb_tmp_table", keywordlen)) { + (char*)"_recover_innodb_tmp_table", keywordlen)) { return(DB_SUCCESS); } @@ -1599,7 +1613,7 @@ row_table_add_foreign_constraints( if (namelen >= keywordlen && 0 == ut_memcmp( name + namelen - keywordlen, - "_recover_innodb_tmp_table", keywordlen)) { + (char*)"_recover_innodb_tmp_table", keywordlen)) { return(DB_SUCCESS); } @@ -1663,7 +1677,7 @@ row_drop_table_for_mysql_in_background( the InnoDB data dictionary get out-of-sync if the user runs with innodb_flush_log_at_trx_commit = 0 */ - log_flush_up_to(ut_dulint_max, LOG_WAIT_ONE_GROUP); + log_write_up_to(ut_dulint_max, LOG_WAIT_ONE_GROUP, TRUE); trx_commit_for_mysql(trx); @@ -1821,7 +1835,6 @@ row_drop_table_for_mysql( ulint len; ulint namelen; ulint keywordlen; - ulint rounds = 0; ibool locked_dictionary = FALSE; char buf[10000]; @@ -2168,7 +2181,7 @@ row_is_mysql_tmp_table_name( ulint i; for (i = 0; i <= ut_strlen(name) - 5; i++) { - if (ut_memcmp(name + i, "/#sql", 5) == 0) { + if (ut_memcmp(name + i, (char*)"/#sql", 5) == 0) { return(TRUE); } @@ -2190,12 +2203,16 @@ row_rename_table_for_mysql( { dict_table_t* table; que_thr_t* thr; - que_t* graph; + que_t* graph = NULL; ulint err; char* str1; char* str2; char* str3; + mem_heap_t* heap = NULL; + char** constraints_to_drop = NULL; + ulint n_constraints_to_drop = 0; ulint len; + ulint i; char buf[10000]; ut_ad(trx->mysql_thread_id == os_thread_get_curr_id()); @@ -2213,10 +2230,10 @@ row_rename_table_for_mysql( trx_commit_for_mysql(trx); return(DB_ERROR); } - - if (0 == ut_strcmp(new_name, "mysql/host") - || 0 == ut_strcmp(new_name, "mysql/user") - || 0 == ut_strcmp(new_name, "mysql/db")) { + + if (0 == ut_strcmp(new_name, (char*)"mysql/host") + || 0 == ut_strcmp(new_name, (char*)"mysql/user") + || 0 == ut_strcmp(new_name, (char*)"mysql/db")) { fprintf(stderr, "InnoDB: Error: trying to create a MySQL system table %s of type InnoDB.\n" @@ -2230,6 +2247,19 @@ row_rename_table_for_mysql( trx->op_info = (char *) "renaming table"; trx_start_if_not_started(trx); + /* Serialize data dictionary operations with dictionary mutex: + no deadlocks can occur then in these operations */ + + row_mysql_lock_data_dictionary(trx); + + table = dict_table_get_low(old_name); + + if (!table) { + err = DB_TABLE_NOT_FOUND; + + goto funct_exit; + } + str1 = (char *) "PROCEDURE RENAME_TABLE_PROC () IS\n" "new_table_name CHAR;\n" @@ -2242,14 +2272,43 @@ row_rename_table_for_mysql( if (row_is_mysql_tmp_table_name(new_name)) { - /* We want to preserve the original foreign key - constraint definitions despite the name change */ + /* MySQL is doing an ALTER TABLE command and it renames the + original table to a temporary table name. We want to preserve + the original foreign key constraint definitions despite the + name change. An exception is those constraints for which + the ALTER TABLE contained DROP FOREIGN KEY <foreign key id>.*/ - str3 = (char*) - "';\n" - "UPDATE SYS_TABLES SET NAME = new_table_name\n" - "WHERE NAME = old_table_name;\n" - "END;\n"; + heap = mem_heap_create(100); + + err = dict_foreign_parse_drop_constraints(heap, trx, + table, + &n_constraints_to_drop, + &constraints_to_drop); + if (err != DB_SUCCESS) { + + goto funct_exit; + } + + str3 = mem_heap_alloc(heap, + 1000 + 500 * n_constraints_to_drop); + *str3 = '\0'; + sprintf(str3, + "';\n" + "UPDATE SYS_TABLES SET NAME = new_table_name\n" + "WHERE NAME = old_table_name;\n"); + + for (i = 0; i < n_constraints_to_drop; i++) { + sprintf(str3 + strlen(str3), + "DELETE FROM SYS_FOREIGN_COLS WHERE ID = '%s';\n" + "DELETE FROM SYS_FOREIGN WHERE ID = '%s';\n", + constraints_to_drop[i], + constraints_to_drop[i]); + } + + sprintf(str3 + strlen(str3), + "END;\n"); + + ut_a(strlen(str3) < 1000 + 500 * n_constraints_to_drop); } else { str3 = (char*) "';\n" @@ -2280,13 +2339,6 @@ row_rename_table_for_mysql( ut_memcpy(buf + len, str3, ut_strlen(str3) + 1); - /* Serialize data dictionary operations with dictionary mutex: - no deadlocks can occur then in these operations */ - - row_mysql_lock_data_dictionary(trx); - - table = dict_table_get_low(old_name); - graph = pars_sql(buf); ut_a(graph); @@ -2296,12 +2348,6 @@ row_rename_table_for_mysql( graph->fork_type = QUE_FORK_MYSQL_INTERFACE; - if (!table) { - err = DB_TABLE_NOT_FOUND; - - goto funct_exit; - } - ut_a(thr = que_fork_start_command(graph, SESS_COMM_EXECUTE, 0)); que_run_threads(thr); @@ -2342,6 +2388,13 @@ row_rename_table_for_mysql( if (row_is_mysql_tmp_table_name(old_name)) { + /* MySQL is doing an ALTER TABLE command and it + renames the created temporary table to the name + of the original table. In the ALTER TABLE we maybe + created some FOREIGN KEY constraints for the temporary + table. But we want to load also the foreign key + constraint definitions for the original table name. */ + err = dict_load_foreigns(new_name); if (err != DB_SUCCESS) { @@ -2367,7 +2420,13 @@ row_rename_table_for_mysql( funct_exit: row_mysql_unlock_data_dictionary(trx); - que_graph_free(graph); + if (graph) { + que_graph_free(graph); + } + + if (heap) { + mem_heap_free(heap); + } trx_commit_for_mysql(trx); |