From 09fc514bd57be466589a8a4cc119ac34062d983e Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 16 Nov 2006 13:18:37 +0100 Subject: [PATCH 1/2] 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. --- mysql-test/r/alter_table.result | 11 +++++++ mysql-test/t/alter_table.test | 18 +++++++++++ sql/sql_table.cc | 53 +++++++++++++++++++-------------- 3 files changed, 59 insertions(+), 23 deletions(-) diff --git a/mysql-test/r/alter_table.result b/mysql-test/r/alter_table.result index e9c9c873750..eade19e85df 100644 --- a/mysql-test/r/alter_table.result +++ b/mysql-test/r/alter_table.result @@ -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; diff --git a/mysql-test/t/alter_table.test b/mysql-test/t/alter_table.test index 9bd34c2a610..eba456982c8 100644 --- a/mysql-test/t/alter_table.test +++ b/mysql-test/t/alter_table.test @@ -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 diff --git a/sql/sql_table.cc b/sql/sql_table.cc index da66b556b5e..256b9281e9f 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -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) { - error=0; - if (new_name != table_name || new_db != db) + switch (alter_info->keys_onoff) { + case LEAVE_AS_IS: + error= 0; + 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); From d63fa0a4078985e656e4c057583fc572add8d3a5 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 16 Nov 2006 14:01:51 +0100 Subject: [PATCH 2/2] Fix for bug#24219 ALTER TABLE ... RENAME TO ... , DISABLE KEYS leads to crash (this is the 5.0 patch, because 4.1 differs) 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: post-merge fix my locale is utf8, and this breaks non-utf8 stuff when doing manual merge :( 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. --- mysql-test/r/alter_table.result | 42 +++++++++++++-------------- sql/sql_table.cc | 51 ++++++++++++++++++--------------- 2 files changed, 49 insertions(+), 44 deletions(-) diff --git a/mysql-test/r/alter_table.result b/mysql-test/r/alter_table.result index a8d7b917f37..ba8c11efbe1 100644 --- a/mysql-test/r/alter_table.result +++ b/mysql-test/r/alter_table.result @@ -428,42 +428,42 @@ t1 MyISAM 10 Fixed 1 37 X X X X X X X X latin1_swedish_ci NULL drop table t1; set names koi8r; create table t1 (a char(10) character set koi8r); -insert into t1 values ('ÔÅÓÔ'); +insert into t1 values ('ÔÅÓÔ'); select a,hex(a) from t1; a hex(a) -ÔÅÓÔ D4C5D3D4 +ÔÅÓÔ D4C5D3D4 alter table t1 change a a char(10) character set cp1251; select a,hex(a) from t1; a hex(a) -ÔÅÓÔ F2E5F1F2 +ÔÅÓÔ F2E5F1F2 alter table t1 change a a binary(4); select a,hex(a) from t1; a hex(a) -òåñò F2E5F1F2 +òåñò F2E5F1F2 alter table t1 change a a char(10) character set cp1251; select a,hex(a) from t1; a hex(a) -ÔÅÓÔ F2E5F1F2 +ÔÅÓÔ F2E5F1F2 alter table t1 change a a char(10) character set koi8r; select a,hex(a) from t1; a hex(a) -ÔÅÓÔ D4C5D3D4 +ÔÅÓÔ D4C5D3D4 alter table t1 change a a varchar(10) character set cp1251; select a,hex(a) from t1; a hex(a) -ÔÅÓÔ F2E5F1F2 +ÔÅÓÔ F2E5F1F2 alter table t1 change a a char(10) character set koi8r; select a,hex(a) from t1; a hex(a) -ÔÅÓÔ D4C5D3D4 +ÔÅÓÔ D4C5D3D4 alter table t1 change a a text character set cp1251; select a,hex(a) from t1; a hex(a) -ÔÅÓÔ F2E5F1F2 +ÔÅÓÔ F2E5F1F2 alter table t1 change a a char(10) character set koi8r; select a,hex(a) from t1; a hex(a) -ÔÅÓÔ D4C5D3D4 +ÔÅÓÔ D4C5D3D4 delete from t1; show create table t1; Table Create Table @@ -528,7 +528,7 @@ ALTER TABLE T12207 DISCARD TABLESPACE; ERROR HY000: Table storage engine for 'T12207' doesn't have this option DROP TABLE T12207; create table t1 (a text) character set koi8r; -insert into t1 values (_koi8r'ÔÅÓÔ'); +insert into t1 values (_koi8r'ÔÅÓÔ'); select hex(a) from t1; hex(a) D4C5D3D4 @@ -556,16 +556,6 @@ ERROR 3D000: No database selected alter table test.t1 rename test.t1; use test; drop table t1; -create table t1 (mycol int(10) not null); -alter table t1 alter column mycol set default 0; -desc t1; -Field Type Null Key Default Extra -mycol int(10) NO 0 -drop table t1; -create table t1 (t varchar(255) default null, key t (t(80))) -engine=myisam default charset=latin1; -alter table t1 change t t text; -drop table t1; DROP TABLE IF EXISTS bug24219; DROP TABLE IF EXISTS bug24219_2; CREATE TABLE bug24219 (a INT, INDEX(a)); @@ -577,3 +567,13 @@ 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; +create table t1 (mycol int(10) not null); +alter table t1 alter column mycol set default 0; +desc t1; +Field Type Null Key Default Extra +mycol int(10) NO 0 +drop table t1; +create table t1 (t varchar(255) default null, key t (t(80))) +engine=myisam default charset=latin1; +alter table t1 change t t text; +drop table t1; diff --git a/sql/sql_table.cc b/sql/sql_table.cc index c76ebe7ef49..e7e08837b65 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -3300,13 +3300,35 @@ view_err: if (!(alter_info->flags & ~(ALTER_RENAME | ALTER_KEYS_ONOFF)) && !table->s->tmp_table) // no need to touch frm { - error=0; VOID(pthread_mutex_lock(&LOCK_open)); - if (new_name != table_name || new_db != db) + + switch (alter_info->keys_onoff) { + case LEAVE_AS_IS: + error= 0; + break; + case ENABLE: + wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN); + error= table->file->enable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE); + /* COND_refresh will be signaled in close_thread_tables() */ + break; + case DISABLE: + wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN); + 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->alias); + error= 0; + } + + if (!error && (new_name != table_name || new_db != db)) { thd->proc_info="rename"; /* Then do a 'simple' rename of the table */ - error=0; if (!access(new_name_buff,F_OK)) { my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_name); @@ -3328,31 +3350,14 @@ view_err: } } - if (!error) - { - switch (alter_info->keys_onoff) { - case LEAVE_AS_IS: - break; - case ENABLE: - wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN); - error= table->file->enable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE); - /* COND_refresh will be signaled in close_thread_tables() */ - break; - case DISABLE: - wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN); - 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->alias); - error=0; + error= 0; } + if (!error) { if (mysql_bin_log.is_open()) @@ -3370,7 +3375,7 @@ view_err: error= -1; } VOID(pthread_mutex_unlock(&LOCK_open)); - table_list->table=0; // For query cache + table_list->table= NULL; // For query cache query_cache_invalidate3(thd, table_list, 0); DBUG_RETURN(error); }