Commit a9f50934 authored by unknown's avatar unknown

BUG#17001 - Table and server crash on ALTER TABLE

frm and data files for tables created by earlier MySQL
versions becomes out of sync after certain ALTER TABLE statements:
- One that changes column default value;
- One that changes table comment;
- One that changes table password.

As a result one can expirience either server crash or data corruption/loss.

This fix ensures that running ALTER TABLE on tables created by earlier
MySQL versions recreates data files.


sql/sql_table.cc:
  Ensure that running ALTER TABLE on tables created by earlier
  MySQL versions recreates data files.
parent 564253c7
...@@ -3197,7 +3197,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, ...@@ -3197,7 +3197,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
uint db_create_options, used_fields; uint db_create_options, used_fields;
enum db_type old_db_type,new_db_type; enum db_type old_db_type,new_db_type;
bool need_copy_table; bool need_copy_table;
bool no_table_reopen= FALSE; bool no_table_reopen= FALSE, varchar= FALSE;
DBUG_ENTER("mysql_alter_table"); DBUG_ENTER("mysql_alter_table");
thd->proc_info="init"; thd->proc_info="init";
...@@ -3399,6 +3399,8 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, ...@@ -3399,6 +3399,8 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
Field **f_ptr,*field; Field **f_ptr,*field;
for (f_ptr=table->field ; (field= *f_ptr) ; f_ptr++) for (f_ptr=table->field ; (field= *f_ptr) ; f_ptr++)
{ {
if (field->type() == MYSQL_TYPE_STRING)
varchar= TRUE;
/* Check if field should be dropped */ /* Check if field should be dropped */
Alter_drop *drop; Alter_drop *drop;
drop_it.rewind(); drop_it.rewind();
...@@ -3660,12 +3662,18 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, ...@@ -3660,12 +3662,18 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
better have a negative test here, instead of positive, like better have a negative test here, instead of positive, like
alter_info->flags & ALTER_ADD_COLUMN|ALTER_ADD_INDEX|... alter_info->flags & ALTER_ADD_COLUMN|ALTER_ADD_INDEX|...
so that ALTER TABLE won't break when somebody will add new flag so that ALTER TABLE won't break when somebody will add new flag
MySQL uses frm version to determine the type of the data fields and
their layout. See Field_string::type() for details.
Thus, if the table is too old we may have to rebuild the data to
update the layout.
*/ */
need_copy_table= (alter_info->flags & need_copy_table= (alter_info->flags &
~(ALTER_CHANGE_COLUMN_DEFAULT|ALTER_OPTIONS) || ~(ALTER_CHANGE_COLUMN_DEFAULT|ALTER_OPTIONS) ||
(create_info->used_fields & (create_info->used_fields &
~(HA_CREATE_USED_COMMENT|HA_CREATE_USED_PASSWORD)) || ~(HA_CREATE_USED_COMMENT|HA_CREATE_USED_PASSWORD)) ||
table->s->tmp_table); table->s->tmp_table ||
(table->s->frm_version < FRM_VER_TRUE_VARCHAR && varchar));
create_info->frm_only= !need_copy_table; create_info->frm_only= !need_copy_table;
/* /*
......
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