summaryrefslogtreecommitdiff
path: root/sql/sql_table.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sql/sql_table.cc')
-rw-r--r--sql/sql_table.cc129
1 files changed, 53 insertions, 76 deletions
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index 11d71cc972d..9806bf001b8 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -683,12 +683,11 @@ void build_lower_case_table_filename(char *buff, size_t bufflen,
uint build_table_shadow_filename(char *buff, size_t bufflen,
ALTER_PARTITION_PARAM_TYPE *lpt,
- bool backup)
+ const char *infix)
{
char tmp_name[FN_REFLEN];
my_snprintf(tmp_name, sizeof (tmp_name), "%s-%s-%lx-%s", tmp_file_prefix,
- backup ? "backup" : "shadow",
- (ulong) current_thd->thread_id, lpt->table_name.str);
+ infix, (ulong) current_thd->thread_id, lpt->table_name.str);
return build_table_filename(buff, bufflen, lpt->db.str, tmp_name, "",
FN_IS_TMP);
}
@@ -721,6 +720,7 @@ uint build_table_shadow_filename(char *buff, size_t bufflen,
TODO: Partitioning atomic DDL refactoring: WFRM_WRITE_SHADOW
should be merged with create_table_impl(frm_only == true).
*/
+#ifdef WITH_PARTITION_STORAGE_ENGINE
bool mysql_write_frm(ALTER_PARTITION_PARAM_TYPE *lpt, uint flags)
{
/*
@@ -729,17 +729,16 @@ bool mysql_write_frm(ALTER_PARTITION_PARAM_TYPE *lpt, uint flags)
We set tmp_table to avoid get errors on naming of primary key index.
*/
int error= 0;
- char path[FN_REFLEN+1];
+ const char *path= lpt->path;
char shadow_path[FN_REFLEN+1];
char shadow_frm_name[FN_REFLEN+1];
char frm_name[FN_REFLEN+1];
-#ifdef WITH_PARTITION_STORAGE_ENGINE
char bak_path[FN_REFLEN+1];
char bak_frm_name[FN_REFLEN+1];
char *part_syntax_buf;
uint syntax_len;
partition_info *part_info= lpt->part_info;
-#endif
+ DDL_LOG_STATE *rollback_chain= &lpt->rollback_chain;
DBUG_ENTER("mysql_write_frm");
/*
@@ -756,7 +755,6 @@ bool mysql_write_frm(ALTER_PARTITION_PARAM_TYPE *lpt, uint flags)
{
DBUG_RETURN(TRUE);
}
-#ifdef WITH_PARTITION_STORAGE_ENGINE
{
partition_info *part_info= lpt->table->part_info;
if (part_info)
@@ -769,7 +767,6 @@ bool mysql_write_frm(ALTER_PARTITION_PARAM_TYPE *lpt, uint flags)
part_info->part_info_len= syntax_len;
}
}
-#endif
/* Write shadow frm file */
lpt->create_info->table_options= lpt->db_options;
LEX_CUSTRING frm= build_frm_image(lpt->thd, lpt->table_name,
@@ -797,7 +794,6 @@ bool mysql_write_frm(ALTER_PARTITION_PARAM_TYPE *lpt, uint flags)
goto end;
}
}
-#ifdef WITH_PARTITION_STORAGE_ENGINE
if (flags & WFRM_WRITE_CONVERTED_TO)
{
THD *thd= lpt->thd;
@@ -818,7 +814,7 @@ bool mysql_write_frm(ALTER_PARTITION_PARAM_TYPE *lpt, uint flags)
create_info->db_type= work_part_info->default_engine_type;
/* NOTE: partitioned temporary tables are not supported. */
DBUG_ASSERT(!create_info->tmp_table());
- if (ddl_log_create_table(part_info, create_info->db_type, &new_path,
+ if (ddl_log_create_table(rollback_chain, create_info->db_type, &new_path,
&alter_ctx->new_db, &alter_ctx->new_name, true) ||
ERROR_INJECT("create_before_create_frm"))
DBUG_RETURN(TRUE);
@@ -838,15 +834,20 @@ bool mysql_write_frm(ALTER_PARTITION_PARAM_TYPE *lpt, uint flags)
if (unlikely(!frm.str))
DBUG_RETURN(TRUE);
+ if (ERROR_INJECT("alter_partition_after_create_frm"))
+ {
+ my_free((void *) frm.str);
+ DBUG_RETURN(true);
+ }
+
thd->work_part_info= work_part_info;
create_info->db_type= db_type;
- ERROR_INJECT("alter_partition_after_create_frm");
-
error= writefile(frm_name, alter_ctx->new_db.str, alter_ctx->new_name.str,
create_info->tmp_table(), frm.str, frm.length);
my_free((void *) frm.str);
- if (unlikely(error) || ERROR_INJECT("alter_partition_after_write_frm"))
+ if (unlikely(error) ||
+ ERROR_INJECT("alter_partition_after_write_frm"))
{
mysql_file_delete(key_file_frm, frm_name, MYF(0));
DBUG_RETURN(TRUE);
@@ -854,47 +855,34 @@ bool mysql_write_frm(ALTER_PARTITION_PARAM_TYPE *lpt, uint flags)
DBUG_RETURN(false);
}
- if (flags & WFRM_BACKUP_ORIGINAL)
+ if (flags & WFRM_LOG_RESTORE)
{
- build_table_filename(path, sizeof(path) - 1, lpt->db.str,
- lpt->table_name.str, "", 0);
strxnmov(frm_name, sizeof(frm_name), path, reg_ext, NullS);
- build_table_shadow_filename(bak_path, sizeof(bak_path) - 1, lpt, true);
+ build_table_shadow_filename(bak_path, sizeof(bak_path) - 1, lpt, "backup");
strxmov(bak_frm_name, bak_path, reg_ext, NullS);
- DDL_LOG_MEMORY_ENTRY *main_entry= part_info->main_entry;
mysql_mutex_lock(&LOCK_gdl);
- if (write_log_replace_frm(lpt, part_info->list->entry_pos,
- (const char*) bak_path,
- (const char*) path) ||
- ddl_log_write_execute_entry(part_info->list->entry_pos, 0,
- &part_info->execute_entry))
+ if (ddl_log_rename_frm(&lpt->rollback_chain,
+ (const char*) bak_path, (const char*) path) ||
+ ddl_log_write_execute_entry(rollback_chain->list->entry_pos, 0,
+ &rollback_chain->execute_entry))
{
mysql_mutex_unlock(&LOCK_gdl);
DBUG_RETURN(TRUE);
}
mysql_mutex_unlock(&LOCK_gdl);
- part_info->main_entry= main_entry;
if (mysql_file_rename(key_file_frm, frm_name, bak_frm_name, MYF(MY_WME)))
DBUG_RETURN(TRUE);
if (lpt->table->file->ha_create_partitioning_metadata(bak_path, path,
CHF_RENAME_FLAG))
DBUG_RETURN(TRUE);
}
-#else /* !WITH_PARTITION_STORAGE_ENGINE */
- DBUG_ASSERT(!(flags & WFRM_BACKUP_ORIGINAL));
-#endif /* !WITH_PARTITION_STORAGE_ENGINE */
- if (flags & WFRM_INSTALL_SHADOW)
+ if (flags & WFRM_BACKUP_AND_INSTALL)
{
-#ifdef WITH_PARTITION_STORAGE_ENGINE
- partition_info *part_info= lpt->part_info;
-#endif
/*
Build frm file name
*/
- build_table_filename(path, sizeof(path) - 1, lpt->db.str,
- lpt->table_name.str, "", 0);
strxnmov(frm_name, sizeof(frm_name), path, reg_ext, NullS);
/*
When we are changing to use new frm file we need to ensure that we
@@ -906,42 +894,20 @@ bool mysql_write_frm(ALTER_PARTITION_PARAM_TYPE *lpt, uint flags)
completing this we write a new phase to the log entry that will
deactivate it.
*/
- if (!(flags & WFRM_BACKUP_ORIGINAL) && (
- mysql_file_delete(key_file_frm, frm_name, MYF(MY_WME))
-#ifdef WITH_PARTITION_STORAGE_ENGINE
- || lpt->table->file->ha_create_partitioning_metadata(path, shadow_path,
- CHF_DELETE_FLAG) ||
- ddl_log_increment_phase(part_info->main_entry->entry_pos) ||
- (ddl_log_sync(), FALSE)
-#endif
- ))
- {
- error= 1;
- goto err;
- }
if (mysql_file_rename(key_file_frm, shadow_frm_name, frm_name, MYF(MY_WME))
-#ifdef WITH_PARTITION_STORAGE_ENGINE
|| lpt->table->file->ha_create_partitioning_metadata(path, shadow_path,
CHF_RENAME_FLAG)
-#endif
)
{
error= 1;
- goto err;
+ goto end;
}
-
-err:
-#ifdef WITH_PARTITION_STORAGE_ENGINE
- ddl_log_increment_phase(part_info->main_entry->entry_pos);
- part_info->main_entry= NULL;
- (void) ddl_log_sync();
-#endif
- ;
}
end:
DBUG_RETURN(error);
}
+#endif /* WITH_PARTITION_STORAGE_ENGINE */
/*
@@ -4403,7 +4369,8 @@ bool HA_CREATE_INFO::finalize_atomic_replace(THD *thd, TABLE_LIST *orig_table)
Cleanup chain (ddl_log_state_rm) will not be executed unless
rollback chain (ddl_log_state_create) is active.
*/
- ddl_log_link_chains(ddl_log_state_rm, ddl_log_state_create);
+ if (ddl_log_link_chains(ddl_log_state_rm, ddl_log_state_create))
+ return true;
cpath.length= build_table_filename(path, sizeof(path) - 1,
backup_name.db.str,
@@ -4550,7 +4517,7 @@ void HA_CREATE_INFO::finalize_ddl(THD *thd, bool roll_back)
debug_crash_here("ddl_log_create_fk_fail2");
ulonglong option_bits_save= thd->variables.option_bits;
thd->variables.option_bits|= OPTION_NO_FOREIGN_KEY_CHECKS;
- (void) ddl_log_revert(thd, ddl_log_state_create);
+ (void) ddl_log_revert(thd, ddl_log_state_create, true);
thd->variables.option_bits= option_bits_save;
debug_crash_here("ddl_log_create_fk_fail3");
}
@@ -4565,7 +4532,7 @@ void HA_CREATE_INFO::finalize_ddl(THD *thd, bool roll_back)
ddl_log_complete(ddl_log_state_create);
debug_crash_here("ddl_log_create_log_complete2");
if (is_atomic_replace())
- (void) ddl_log_revert(thd, ddl_log_state_rm);
+ (void) ddl_log_revert(thd, ddl_log_state_rm, true);
else
ddl_log_complete(ddl_log_state_rm);
debug_crash_here("ddl_log_create_log_complete3");
@@ -11980,7 +11947,7 @@ err_with_mdl:
Prepare the transaction for the alter table's copy phase.
*/
-bool mysql_trans_prepare_alter_copy_data(THD *thd)
+int mysql_trans_prepare_alter_copy_data(THD *thd)
{
DBUG_ENTER("mysql_trans_prepare_alter_copy_data");
/*
@@ -11997,9 +11964,9 @@ bool mysql_trans_prepare_alter_copy_data(THD *thd)
Commit the copy phase of the alter table.
*/
-bool mysql_trans_commit_alter_copy_data(THD *thd)
+int mysql_trans_commit_alter_copy_data(THD *thd, bool rollback)
{
- bool error= FALSE;
+ int error= 0;
uint save_unsafe_rollback_flags;
DBUG_ENTER("mysql_trans_commit_alter_copy_data");
@@ -12008,19 +11975,29 @@ bool mysql_trans_commit_alter_copy_data(THD *thd)
DEBUG_SYNC(thd, "alter_table_copy_trans_commit");
- if (ha_enable_transaction(thd, TRUE))
- DBUG_RETURN(TRUE);
+ if ((error= ha_enable_transaction(thd, TRUE)))
+ DBUG_RETURN(error);
- /*
- Ensure that the new table is saved properly to disk before installing
- the new .frm.
- And that InnoDB's internal latches are released, to avoid deadlock
- when waiting on other instances of the table before rename (Bug#54747).
- */
- if (trans_commit_stmt(thd))
- error= TRUE;
- if (trans_commit_implicit(thd))
- error= TRUE;
+ if (!rollback)
+ {
+ /*
+ Ensure that the new table is saved properly to disk before installing
+ the new .frm.
+ And that InnoDB's internal latches are released, to avoid deadlock
+ when waiting on other instances of the table before rename (Bug#54747).
+ */
+ if (trans_commit_stmt(thd))
+ error= HA_ERR_COMMIT_ERROR;
+ if (trans_commit_implicit(thd))
+ error= HA_ERR_COMMIT_ERROR;
+ }
+ else
+ {
+ if (trans_rollback_stmt(thd))
+ error= HA_ERR_COMMIT_ERROR;
+ if (trans_rollback_implicit(thd))
+ error= HA_ERR_COMMIT_ERROR;
+ }
thd->transaction->stmt.m_unsafe_rollback_flags= save_unsafe_rollback_flags;
DBUG_RETURN(error);
@@ -12377,7 +12354,7 @@ copy_data_between_tables(THD *thd, TABLE *from, TABLE *to,
if (backup_reset_alter_copy_lock(thd))
error= 1;
- if (unlikely(mysql_trans_commit_alter_copy_data(thd)))
+ if (unlikely(mysql_trans_commit_alter_copy_data(thd, false)))
error= 1;
err: