From dd6af1f71385e23490672f973bee9cc551f8d8e8 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 13 Apr 2006 16:19:19 +0200 Subject: [PATCH] Bug#18129 - Fast (online) add index leaves temporary table frm in case of errors ALTER TABLE temporarily creates a new table with a .frm file and optionally other files. For fast ALTER TABLE only the .frm file is created. If the operation succeeds, The temporary files are renamed to their final target. In case of an error, the temporary file was forgotten to remove. Manually tested. The test requires to look at files, which I think cannot be done portably with the test suite. The test file is attached to the bug report. sql/sql_table.cc: Bug#18129 - Fast (online) add index leaves temporary table frm in case of errors Moved closing or removing of the temporary table to an 'err1' label at the end of mysql_alter_table(). Added gotos to this label from all error checks between create or open and remove or close of the temporary table. --- sql/sql_table.cc | 49 ++++++++++++++++++------------------------------ 1 file changed, 18 insertions(+), 31 deletions(-) diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 0c08c960785..3747a83d8cd 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -4738,10 +4738,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, new_table=open_temporary_table(thd, path, new_db, tmp_name,0); } if (!new_table) - { - VOID(quick_rm_table(new_db_type,new_db,tmp_name)); - goto err; - } + goto err1; } /* Copy the data if necessary. */ @@ -4794,7 +4791,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, table->file->create_handler_files(path, create_info)); VOID(pthread_mutex_unlock(&LOCK_open)); if (error) - goto err; + goto err1; #endif /* The add_index() method takes an array of KEY structs. */ @@ -4822,7 +4819,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, table->key_info= key_info; table->file->print_error(error, MYF(0)); table->key_info= save_key_info; - goto err; + goto err1; } } /*end of if (index_add_count)*/ @@ -4840,7 +4837,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, table->file->create_handler_files(path, create_info)); VOID(pthread_mutex_unlock(&LOCK_open)); if (error) - goto err; + goto err1; if (! need_lock_for_indexes) { @@ -4874,7 +4871,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, index_drop_count))) { table->file->print_error(error, MYF(0)); - goto err; + goto err1; } #ifdef XXX_TO_BE_DONE_LATER_BY_WL3020 @@ -4902,7 +4899,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, if ((error= table->file->final_drop_index(table))) { table->file->print_error(error, MYF(0)); - goto err; + goto err1; } } /*end of if (index_drop_count)*/ @@ -4915,7 +4912,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, /* Need to commit before a table is unlocked (NDB requirement). */ DBUG_PRINT("info", ("Committing before unlocking table")); if (ha_commit_stmt(thd) || ha_commit(thd)) - goto err; + goto err1; committed= 1; } /*end of if (! new_table) for add/drop index*/ @@ -4924,17 +4921,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, { /* We changed a temporary table */ if (error) - { - /* - The following function call will free the new_table pointer, - in close_temporary_table(), so we can safely directly jump to err - */ - if (new_table) - close_temporary_table(thd, new_table, 1, 1); - else - VOID(quick_rm_table(new_db_type,new_db,tmp_name)); - goto err; - } + goto err1; /* Close lock if this is a transactional table */ if (thd->lock) { @@ -4945,16 +4932,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, close_temporary_table(thd, table, 1, 1); /* Should pass the 'new_name' as we store table name in the cache */ if (rename_temporary_table(thd, new_table, new_db, new_name)) - { // Fatal error - if (new_table) - { - close_temporary_table(thd, new_table, 1, 1); - my_free((gptr) new_table,MYF(0)); - } - else - VOID(quick_rm_table(new_db_type,new_db,tmp_name)); - goto err; - } + goto err1; /* We don't replicate alter table statement on temporary tables */ if (!thd->current_stmt_binlog_row_based) write_bin_log(thd, TRUE, thd->query, thd->query_length); @@ -5169,6 +5147,15 @@ end_temporary: thd->some_tables_deleted=0; DBUG_RETURN(FALSE); + err1: + if (new_table) + { + /* close_temporary_table() frees the new_table pointer. */ + close_temporary_table(thd, new_table, 1, 1); + } + else + VOID(quick_rm_table(new_db_type,new_db,tmp_name)); + err: DBUG_RETURN(TRUE); }