Commit 09fc514b authored by unknown's avatar unknown
Browse files

Fix for bug#24219 ALTER TABLE ... RENAME TO ... , DISABLE KEYS leads to crash

There was an improper order of doing chained operations.

To the documentor: ENABLE|DISABLE KEYS combined with RENAME TO, and no other
ALTER TABLE clause, leads to server crash independent of the presence of
indices and data in the table.


mysql-test/r/alter_table.result:
  update result
mysql-test/t/alter_table.test:
  add test for bug#24129
sql/sql_table.cc:
  If there is operation on the KEYS, first do it
  and then do a rename if there is such. Or, we will crash because
  the underlying table has changed.
parent 78278bc4
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -543,3 +543,14 @@ ERROR 3D000: No database selected
alter table test.t1 rename test.t1;
use test;
drop table t1;
DROP TABLE IF EXISTS bug24219;
DROP TABLE IF EXISTS bug24219_2;
CREATE TABLE bug24219 (a INT, INDEX(a));
SHOW INDEX FROM bug24219;
Table	Non_unique	Key_name	Seq_in_index	Column_name	Collation	Cardinality	Sub_part	Packed	Null	Index_type	Comment
bug24219	1	a	1	a	A	NULL	NULL	NULL	YES	BTREE	
ALTER TABLE bug24219 RENAME TO bug24219_2, DISABLE KEYS;
SHOW INDEX FROM bug24219_2;
Table	Non_unique	Key_name	Seq_in_index	Column_name	Collation	Cardinality	Sub_part	Packed	Null	Index_type	Comment
bug24219_2	1	a	1	a	A	NULL	NULL	NULL	YES	BTREE	disabled
DROP TABLE bug24219_2;
+18 −0
Original line number Diff line number Diff line
@@ -392,4 +392,22 @@ alter table test.t1 rename test.t1;
use test;
drop table t1;

#
# Bug#24219 - ALTER TABLE ... RENAME TO ... , DISABLE KEYS leads to crash
#
--disable_warnings
DROP TABLE IF EXISTS bug24219;
DROP TABLE IF EXISTS bug24219_2;
--enable_warnings

CREATE TABLE bug24219 (a INT, INDEX(a));

SHOW INDEX FROM bug24219;

ALTER TABLE bug24219 RENAME TO bug24219_2, DISABLE KEYS;

SHOW INDEX FROM bug24219_2;

DROP TABLE bug24219_2;

# End of 4.1 tests
+30 −23
Original line number Diff line number Diff line
@@ -2949,8 +2949,35 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
  thd->proc_info="setup";
  if (alter_info->is_simple && !table->tmp_table)
  {
    switch (alter_info->keys_onoff) {
    case LEAVE_AS_IS:
      error= 0;
    if (new_name != table_name || new_db != db)
      break;
    case ENABLE:
      VOID(pthread_mutex_lock(&LOCK_open));
      wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN);
      VOID(pthread_mutex_unlock(&LOCK_open));
      error= table->file->enable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
      /* COND_refresh will be signaled in close_thread_tables() */
      break;
    case DISABLE:
      VOID(pthread_mutex_lock(&LOCK_open));
      wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN);
      VOID(pthread_mutex_unlock(&LOCK_open));
      error= table->file->disable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
      /* COND_refresh will be signaled in close_thread_tables() */
      break;
    }

    if (error == HA_ERR_WRONG_COMMAND)
    {
      push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
			  ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA),
			  table->table_name);
      error= 0;
    }

    if (!error && (new_name != table_name || new_db != db))
    {
      thd->proc_info="rename";
      VOID(pthread_mutex_lock(&LOCK_open));
@@ -2971,27 +2998,6 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
      VOID(pthread_mutex_unlock(&LOCK_open));
    }

    if (!error)
    {
      switch (alter_info->keys_onoff) {
      case LEAVE_AS_IS:
	break;
      case ENABLE:
	VOID(pthread_mutex_lock(&LOCK_open));
	wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN);
	VOID(pthread_mutex_unlock(&LOCK_open));
	error= table->file->enable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
	/* COND_refresh will be signaled in close_thread_tables() */
	break;
      case DISABLE:
	VOID(pthread_mutex_lock(&LOCK_open));
	wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN);
	VOID(pthread_mutex_unlock(&LOCK_open));
	error=table->file->disable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
	/* COND_refresh will be signaled in close_thread_tables() */
	break;
      }
    }
    if (error == HA_ERR_WRONG_COMMAND)
    {
      push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
@@ -2999,6 +3005,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
			  table->table_name);
      error=0;
    }

    if (!error)
    {
      mysql_update_log.write(thd, thd->query, thd->query_length);