#At file:///home/dlenev/src/bzr/mysql-trunk-12652385/ based on revid:dmitry.lenev@stripped
3218 Dmitry Lenev 2011-06-17
A follow-up for patch that fixed bug #12652385 - "61493:
REORDERING COLUMNS TO POSITION FIRST CAN CAUSE DATA TO
BE CORRUPTED".
Moved code which is responsible for detecting that ALTER
TABLE can't be carried out using in-place algorithm because
it reorders some columns or replaces some old columns with
a newly added to one place. Introduced a new auxiliary
function for performing this check.
Note that we cannot easily make this check part of
mysql_compare_tables() call as this check is specific to
normal ALTER TABLE (i.e. assumes that there are old columns
and new columns). While mysql_compare_tables() is also
used by ALTER TABLE EXCHANGE PARTITION implementation for
checking that table and partitioned table has identical
structure (i.e. in situation when there are no old and
new columns).
modified:
sql/sql_table.cc
=== modified file 'sql/sql_table.cc'
--- a/sql/sql_table.cc 2011-06-16 23:45:58 +0000
+++ b/sql/sql_table.cc 2011-06-17 19:08:51 +0000
@@ -4978,6 +4978,35 @@ err:
DBUG_RETURN(-1);
}
+
+/**
+ Check if ALTER TABLE statement changes position of any column
+ in the table or adds new columns.
+
+ @param alter_info Alter_info object describing structure of new
+ version of table.
+
+ @retval True - some column is added or changes its position.
+ @retval False - no columns are added or change their positions.
+*/
+
+static bool has_columns_new_or_reordered(Alter_info *alter_info)
+{
+ List_iterator_fast<Create_field> new_field_it(alter_info->create_list);
+ Create_field *new_field;
+ uint new_field_idx;
+
+ for (new_field_idx= 0, new_field= new_field_it++; new_field;
+ new_field_idx++, new_field= new_field_it++)
+ {
+ if (! new_field->field ||
+ new_field->field->field_index != new_field_idx)
+ return true;
+ }
+ return false;
+}
+
+
/**
@brief Check if both DROP and CREATE are present for an index in ALTER TABLE
@@ -5577,12 +5606,6 @@ mysql_prepare_alter_table(THD *thd, TABL
if (drop)
{
drop_it.remove();
- /*
- ALTER TABLE DROP COLUMN always changes table data even in cases
- when new version of the table has the same structure as the old
- one.
- */
- alter_info->change_level= ALTER_TABLE_DATA_CHANGED;
continue;
}
/* Check if field is changed */
@@ -5662,11 +5685,6 @@ mysql_prepare_alter_table(THD *thd, TABL
else if (def->after == first_keyword)
{
new_create_list.push_front(def);
- /*
- Re-ordering columns in table can't be done using in-place algorithm
- as it always changes table data.
- */
- alter_info->change_level= ALTER_TABLE_DATA_CHANGED;
}
else
{
@@ -5683,11 +5701,6 @@ mysql_prepare_alter_table(THD *thd, TABL
goto err;
}
find_it.after(def); // Put element after this
- /*
- Re-ordering columns in table can't be done using in-place algorithm
- as it always changes table data.
- */
- alter_info->change_level= ALTER_TABLE_DATA_CHANGED;
}
}
if (alter_info->alter_list.elements)
@@ -6368,6 +6381,17 @@ bool mysql_alter_table(THD *thd,char *ne
if (need_copy_table == ALTER_TABLE_METADATA_ONLY)
need_copy_table= need_copy_table_res;
+ if (need_copy_table != ALTER_TABLE_DATA_CHANGED &&
+ has_columns_new_or_reordered(alter_info))
+ {
+ /*
+ ALTER TABLE which adds new columns (e.g. instead columns being
+ removed) or changes their order can't be executed using in-place
+ algorithm even if table structure stays the same.
+ */
+ need_copy_table= ALTER_TABLE_DATA_CHANGED;
+ }
+
if (need_copy_table == ALTER_TABLE_INDEX_CHANGED)
{
if (is_index_maintenance_unique(table, key_info_buffer,
Attachment: [text/bzr-bundle] bzr/dmitry.lenev@oracle.com-20110617190851-9r4032yo9bchjf4l.bundle