Commit 56d414b0 authored by ingo@mysql.com's avatar ingo@mysql.com

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.
parent 5cb592ac
...@@ -4738,10 +4738,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, ...@@ -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); new_table=open_temporary_table(thd, path, new_db, tmp_name,0);
} }
if (!new_table) if (!new_table)
{ goto err1;
VOID(quick_rm_table(new_db_type,new_db,tmp_name));
goto err;
}
} }
/* Copy the data if necessary. */ /* Copy the data if necessary. */
...@@ -4794,7 +4791,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, ...@@ -4794,7 +4791,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
table->file->create_handler_files(path, create_info)); table->file->create_handler_files(path, create_info));
VOID(pthread_mutex_unlock(&LOCK_open)); VOID(pthread_mutex_unlock(&LOCK_open));
if (error) if (error)
goto err; goto err1;
#endif #endif
/* The add_index() method takes an array of KEY structs. */ /* 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, ...@@ -4822,7 +4819,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
table->key_info= key_info; table->key_info= key_info;
table->file->print_error(error, MYF(0)); table->file->print_error(error, MYF(0));
table->key_info= save_key_info; table->key_info= save_key_info;
goto err; goto err1;
} }
} }
/*end of if (index_add_count)*/ /*end of if (index_add_count)*/
...@@ -4840,7 +4837,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, ...@@ -4840,7 +4837,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
table->file->create_handler_files(path, create_info)); table->file->create_handler_files(path, create_info));
VOID(pthread_mutex_unlock(&LOCK_open)); VOID(pthread_mutex_unlock(&LOCK_open));
if (error) if (error)
goto err; goto err1;
if (! need_lock_for_indexes) if (! need_lock_for_indexes)
{ {
...@@ -4874,7 +4871,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, ...@@ -4874,7 +4871,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
index_drop_count))) index_drop_count)))
{ {
table->file->print_error(error, MYF(0)); table->file->print_error(error, MYF(0));
goto err; goto err1;
} }
#ifdef XXX_TO_BE_DONE_LATER_BY_WL3020 #ifdef XXX_TO_BE_DONE_LATER_BY_WL3020
...@@ -4902,7 +4899,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, ...@@ -4902,7 +4899,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
if ((error= table->file->final_drop_index(table))) if ((error= table->file->final_drop_index(table)))
{ {
table->file->print_error(error, MYF(0)); table->file->print_error(error, MYF(0));
goto err; goto err1;
} }
} }
/*end of if (index_drop_count)*/ /*end of if (index_drop_count)*/
...@@ -4915,7 +4912,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, ...@@ -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). */ /* Need to commit before a table is unlocked (NDB requirement). */
DBUG_PRINT("info", ("Committing before unlocking table")); DBUG_PRINT("info", ("Committing before unlocking table"));
if (ha_commit_stmt(thd) || ha_commit(thd)) if (ha_commit_stmt(thd) || ha_commit(thd))
goto err; goto err1;
committed= 1; committed= 1;
} }
/*end of if (! new_table) for add/drop index*/ /*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, ...@@ -4924,17 +4921,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
{ {
/* We changed a temporary table */ /* We changed a temporary table */
if (error) if (error)
{ goto err1;
/*
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;
}
/* Close lock if this is a transactional table */ /* Close lock if this is a transactional table */
if (thd->lock) if (thd->lock)
{ {
...@@ -4945,16 +4932,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, ...@@ -4945,16 +4932,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
close_temporary_table(thd, table, 1, 1); close_temporary_table(thd, table, 1, 1);
/* Should pass the 'new_name' as we store table name in the cache */ /* Should pass the 'new_name' as we store table name in the cache */
if (rename_temporary_table(thd, new_table, new_db, new_name)) if (rename_temporary_table(thd, new_table, new_db, new_name))
{ // Fatal error goto err1;
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;
}
/* We don't replicate alter table statement on temporary tables */ /* We don't replicate alter table statement on temporary tables */
if (!thd->current_stmt_binlog_row_based) if (!thd->current_stmt_binlog_row_based)
write_bin_log(thd, TRUE, thd->query, thd->query_length); write_bin_log(thd, TRUE, thd->query, thd->query_length);
...@@ -5169,6 +5147,15 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, ...@@ -5169,6 +5147,15 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
thd->some_tables_deleted=0; thd->some_tables_deleted=0;
DBUG_RETURN(FALSE); 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: err:
DBUG_RETURN(TRUE); DBUG_RETURN(TRUE);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment