mirror of
https://github.com/MariaDB/server.git
synced 2025-07-27 18:02:13 +03:00
MDEV-14943 Alter table ORDER BY bug
Problem was that if copy_data_between_tables() didn't do proper clean up in case of failures: - copy object was not properly freed - end_bulk_insert() was not called - mysql_trans_prepare_alter_copy_data() set THD->transaction.on to false which was not properly restored The last part caused a crash in Aria as Aria depends on that THD is correct. Other things: - Reset info->switched_transactional after usage (safety) - Reset bulk_insert_single_undo (safety)
This commit is contained in:
@ -9356,9 +9356,7 @@ bool mysql_trans_prepare_alter_copy_data(THD *thd)
|
||||
|
||||
This needs to be done before external_lock.
|
||||
*/
|
||||
if (ha_enable_transaction(thd, FALSE))
|
||||
DBUG_RETURN(TRUE);
|
||||
DBUG_RETURN(FALSE);
|
||||
DBUG_RETURN(ha_enable_transaction(thd, FALSE) != 0);
|
||||
}
|
||||
|
||||
|
||||
@ -9409,6 +9407,7 @@ copy_data_between_tables(THD *thd, TABLE *from, TABLE *to,
|
||||
ha_rows examined_rows;
|
||||
ha_rows found_rows;
|
||||
bool auto_increment_field_copied= 0;
|
||||
bool cleanup_done= 0;
|
||||
ulonglong save_sql_mode= thd->variables.sql_mode;
|
||||
ulonglong prev_insert_id, time_to_report_progress;
|
||||
Field **dfield_ptr= to->default_field;
|
||||
@ -9417,15 +9416,23 @@ copy_data_between_tables(THD *thd, TABLE *from, TABLE *to,
|
||||
/* Two or 3 stages; Sorting, copying data and update indexes */
|
||||
thd_progress_init(thd, 2 + MY_TEST(order));
|
||||
|
||||
if (mysql_trans_prepare_alter_copy_data(thd))
|
||||
DBUG_RETURN(-1);
|
||||
|
||||
if (!(copy= new Copy_field[to->s->fields]))
|
||||
DBUG_RETURN(-1); /* purecov: inspected */
|
||||
|
||||
if (mysql_trans_prepare_alter_copy_data(thd))
|
||||
{
|
||||
delete [] copy;
|
||||
DBUG_RETURN(-1);
|
||||
}
|
||||
|
||||
/* We need external lock before we can disable/enable keys */
|
||||
if (to->file->ha_external_lock(thd, F_WRLCK))
|
||||
{
|
||||
/* Undo call to mysql_trans_prepare_alter_copy_data() */
|
||||
ha_enable_transaction(thd, TRUE);
|
||||
delete [] copy;
|
||||
DBUG_RETURN(-1);
|
||||
}
|
||||
|
||||
alter_table_manage_keys(to, from->file->indexes_are_disabled(), keys_onoff);
|
||||
|
||||
@ -9435,7 +9442,6 @@ copy_data_between_tables(THD *thd, TABLE *from, TABLE *to,
|
||||
from->file->info(HA_STATUS_VARIABLE);
|
||||
to->file->ha_start_bulk_insert(from->file->stats.records,
|
||||
ignore ? 0 : HA_CREATE_UNIQUE_INDEX_BY_SORT);
|
||||
|
||||
List_iterator<Create_field> it(create);
|
||||
Create_field *def;
|
||||
copy_end=copy;
|
||||
@ -9637,7 +9643,6 @@ copy_data_between_tables(THD *thd, TABLE *from, TABLE *to,
|
||||
}
|
||||
end_read_record(&info);
|
||||
free_io_cache(from);
|
||||
delete [] copy;
|
||||
|
||||
THD_STAGE_INFO(thd, stage_enabling_keys);
|
||||
thd_progress_next_stage(thd);
|
||||
@ -9652,6 +9657,7 @@ copy_data_between_tables(THD *thd, TABLE *from, TABLE *to,
|
||||
to->file->print_error(my_errno,MYF(0));
|
||||
error= 1;
|
||||
}
|
||||
cleanup_done= 1;
|
||||
to->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
|
||||
|
||||
if (mysql_trans_commit_alter_copy_data(thd))
|
||||
@ -9663,6 +9669,16 @@ copy_data_between_tables(THD *thd, TABLE *from, TABLE *to,
|
||||
*copied= found_count;
|
||||
*deleted=delete_count;
|
||||
to->file->ha_release_auto_increment();
|
||||
delete [] copy;
|
||||
|
||||
if (!cleanup_done)
|
||||
{
|
||||
/* This happens if we get an error during initialzation of data */
|
||||
DBUG_ASSERT(error);
|
||||
to->file->ha_end_bulk_insert();
|
||||
ha_enable_transaction(thd, TRUE);
|
||||
}
|
||||
|
||||
if (to->file->ha_external_lock(thd,F_UNLCK))
|
||||
error=1;
|
||||
if (error < 0 && to->file->extra(HA_EXTRA_PREPARE_FOR_RENAME))
|
||||
|
Reference in New Issue
Block a user