From: Alexander Nozdrin Date: April 12 2011 8:28pm Subject: Re: bzr commit into mysql-5.5 branch (Dmitry.Lenev:3431) Bug#11938039 List-Archive: http://lists.mysql.com/commits/135289 Message-Id: <4DA4B5D3.3030900@oracle.com> MIME-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit 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; > > > > >