Ok to push.
On 04/12/11 17:13, Dmitry Lenev wrote:
> #At file:///home/dlenev/src/bzr/mysql-5.5-11938039/ based on
> revid:alexander.barkov@stripped
>
> 3431 Dmitry Lenev 2011-04-12
> Bug#11938039 "RE-EXECUTION OF FRM-ONLY ALTER TABLE WITH RENAME
> CLAUSE FAILS OR ABORTS SERVER".
>
> Attempt to re-execute prepared ALTER TABLE statement which
> involves .FRM-only changes and also have RENAME clause led
> to unwarranted 'Table doesn't exist' error in production
> builds and assertion failure for debug builds.
>
> This problem stemmed from the fact that for such ALTER TABLE
> mysql_alter_table() code changed table list element for table
> to be altered when it tried to re-open table under new name.
> Since this change was not reverted back before next
> re-execution, it made this statement re-execution unsafe.
>
> This fix addresses this problem by avoiding changing table list
> element from the main table list in such a situation. Instead
> temporary TABLE_LIST object is used.
> @ mysql-test/r/alter_table.result
> Added test case for bug#11938039 "RE-EXECUTION OF FRM-ONLY
> ALTER TABLE WITH RENAME CLAUSE FAILS OR ABORTS SERVER".
> @ mysql-test/t/alter_table.test
> Added test case for bug#11938039 "RE-EXECUTION OF FRM-ONLY
> ALTER TABLE WITH RENAME CLAUSE FAILS OR ABORTS SERVER".
> @ sql/sql_table.cc
> Changed mysql_alter_table() not to modify table list element
> for the table being altered while re-opening table after
> .FRM-only changes. Doing this made .FRM-only ALTER TABLE
> which also had RENAME clause unsafe for re-execution.
>
> modified:
> mysql-test/r/alter_table.result
> mysql-test/t/alter_table.test
> sql/sql_table.cc
> === modified file 'mysql-test/r/alter_table.result'
> --- a/mysql-test/r/alter_table.result 2011-02-21 11:30:08 +0000
> +++ b/mysql-test/r/alter_table.result 2011-04-12 13:13:05 +0000
> @@ -1391,3 +1391,16 @@ CREATE DATABASE db1 CHARACTER SET utf8;
> CREATE TABLE db1.t1 (bar TINYTEXT, KEY (bar(100)));
> ALTER TABLE db1.t1 ADD baz INT;
> DROP DATABASE db1;
> +#
> +# Bug#11938039 RE-EXECUTION OF FRM-ONLY ALTER TABLE WITH RENAME
> +# CLAUSE FAILS OR ABORTS SERVER.
> +#
> +drop table if exists t1;
> +create table t1 (a int);
> +prepare stmt1 from 'alter table t1 alter column a set default 1, rename to t2';
> +execute stmt1;
> +rename table t2 to t1;
> +# The below statement should succeed and not emit error or abort server.
> +execute stmt1;
> +deallocate prepare stmt1;
> +drop table t2;
>
> === modified file 'mysql-test/t/alter_table.test'
> --- a/mysql-test/t/alter_table.test 2011-02-21 11:30:08 +0000
> +++ b/mysql-test/t/alter_table.test 2011-04-12 13:13:05 +0000
> @@ -1159,3 +1159,20 @@ CREATE TABLE db1.t1 (bar TINYTEXT, KEY (
> ALTER TABLE db1.t1 ADD baz INT;
>
> DROP DATABASE db1;
> +
> +
> +--echo #
> +--echo # Bug#11938039 RE-EXECUTION OF FRM-ONLY ALTER TABLE WITH RENAME
> +--echo # CLAUSE FAILS OR ABORTS SERVER.
> +--echo #
> +--disable_warnings
> +drop table if exists t1;
> +--enable_warnings
> +create table t1 (a int);
> +prepare stmt1 from 'alter table t1 alter column a set default 1, rename to t2';
> +execute stmt1;
> +rename table t2 to t1;
> +--echo # The below statement should succeed and not emit error or abort server.
> +execute stmt1;
> +deallocate prepare stmt1;
> +drop table t2;
>
> === modified file 'sql/sql_table.cc'
> --- a/sql/sql_table.cc 2011-03-25 14:03:44 +0000
> +++ b/sql/sql_table.cc 2011-04-12 13:13:05 +0000
> @@ -6660,15 +6660,15 @@ bool mysql_alter_table(THD *thd,char *ne
> NO need to tamper with MERGE tables. The real open is done later.
> */
> Open_table_context ot_ctx(thd, MYSQL_OPEN_REOPEN);
> - TABLE *t_table;
> + TABLE_LIST temp_table_list;
> + TABLE_LIST *t_table_list;
> if (new_name != table_name || new_db != db)
> {
> - table_list->alias= new_name;
> - table_list->table_name= new_name;
> - table_list->table_name_length= strlen(new_name);
> - table_list->db= new_db;
> - table_list->db_length= strlen(new_db);
> - table_list->mdl_request.ticket= target_mdl_request.ticket;
> + temp_table_list.init_one_table(new_db, strlen(new_db),
> + new_name, strlen(new_name),
> + new_name, TL_READ_NO_INSERT);
> + temp_table_list.mdl_request.ticket= target_mdl_request.ticket;
> + t_table_list=&temp_table_list;
> }
> else
> {
> @@ -6678,20 +6678,21 @@ bool mysql_alter_table(THD *thd,char *ne
> to request the lock.
> */
> table_list->mdl_request.ticket= mdl_ticket;
> + t_table_list= table_list;
> }
> - if (open_table(thd, table_list, thd->mem_root,&ot_ctx))
> + if (open_table(thd, t_table_list, thd->mem_root,&ot_ctx))
> {
> goto err_with_mdl;
> }
> - t_table= table_list->table;
>
> /* Tell the handler that a new frm file is in place. */
> - error= t_table->file->ha_create_handler_files(path, NULL, CHF_INDEX_FLAG,
> - create_info);
> + error= t_table_list->table->file->ha_create_handler_files(path, NULL,
> + CHF_INDEX_FLAG,
> + create_info);
>
> - DBUG_ASSERT(thd->open_tables == t_table);
> + DBUG_ASSERT(thd->open_tables == t_table_list->table);
> close_thread_table(thd,&thd->open_tables);
> - table_list->table= 0;
> + t_table_list->table= NULL;
>
> if (error)
> goto err_with_mdl;
>
>
>
>
>