Commit dd6af1f7 authored by unknown's avatar unknown

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.
parent c6f311a0
...@@ -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 @@ end_temporary: ...@@ -5169,6 +5147,15 @@ end_temporary:
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