From: Date: September 22 2007 11:08am Subject: bk commit into 5.1 tree (istruewing:1.2610) BUG#26379 List-Archive: http://lists.mysql.com/commits/34477 X-Bug: 26379 Message-Id: Below is the list of changes that have just been committed into a local 5.1 repository of istruewing. When istruewing does a push these changes will be propagated to the main repository and, within 24 hours after the push, to the public repository. For information on how to access the public repository see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html ChangeSet@stripped, 2007-09-22 11:08:21+02:00, istruewing@stripped +3 -0 Bug#26379 - Combination of FLUSH TABLE and REPAIR TABLE corrupts a MERGE table Not to be pushed. These are fixes on top of the second patch. They fix problems detected during first coarse review. mysql-test/r/merge.result@stripped, 2007-09-22 11:08:17+02:00, istruewing@stripped +20 -0 Bug#26379 - Combination of FLUSH TABLE and REPAIR TABLE corrupts a MERGE table Added test result. mysql-test/t/merge.test@stripped, 2007-09-22 11:08:17+02:00, istruewing@stripped +14 -0 Bug#26379 - Combination of FLUSH TABLE and REPAIR TABLE corrupts a MERGE table Added tests. sql/sql_base.cc@stripped, 2007-09-22 11:08:17+02:00, istruewing@stripped +26 -13 Bug#26379 - Combination of FLUSH TABLE and REPAIR TABLE corrupts a MERGE table Fixed explicit use of MERGE child under LOCK TABLES when they have not been locked explicitly. Fixed dropping a locked MERGE table by detaching children first. Removed children list from open_tables() TABLE_LIST list regardless of the type of failure in open_table(). The list might be reused in any case. diff -Nrup a/mysql-test/r/merge.result b/mysql-test/r/merge.result --- a/mysql-test/r/merge.result 2007-09-12 22:11:44 +02:00 +++ b/mysql-test/r/merge.result 2007-09-22 11:08:17 +02:00 @@ -953,6 +953,20 @@ c1 1 2 DROP TABLE t4; +CREATE TABLE t4 (c1 INT) ENGINE=MRG_MYISAM UNION=(t1,t2) +INSERT_METHOD=FIRST SELECT * FROM t3; +SHOW CREATE TABLE t4; +Table Create Table +t4 CREATE TABLE `t4` ( + `c1` int(11) DEFAULT NULL +) ENGINE=MRG_MyISAM DEFAULT CHARSET=latin1 INSERT_METHOD=FIRST UNION=(`t1`,`t2`) +SELECT * FROM t4; +c1 +1 +2 +1 +2 +DROP TABLE t4; LOCK TABLES t1 WRITE, t2 WRITE, t3 READ; CREATE TABLE t4 (c1 INT); DROP TABLE t4; @@ -961,6 +975,12 @@ ERROR HY000: Table 't4' was not locked w CREATE TABLE t4 (c1 INT) ENGINE=MRG_MYISAM UNION=(t1,t2) INSERT_METHOD=LAST SELECT * FROM t3; ERROR HY000: Table 't4' was not locked with LOCK TABLES +UNLOCK TABLES; +CREATE TABLE t4 (c1 INT) ENGINE=MRG_MYISAM UNION=(t1,t2); +LOCK TABLES t4 READ; +SELECT * from t1, t4; +ERROR HY000: Table 't1' was not locked with LOCK TABLES +DROP TABLE t4; UNLOCK TABLES; DROP TABLE t1, t2, t3; CREATE TABLE t1 (c1 INT) ENGINE= MyISAM; diff -Nrup a/mysql-test/t/merge.test b/mysql-test/t/merge.test --- a/mysql-test/t/merge.test 2007-09-12 22:11:44 +02:00 +++ b/mysql-test/t/merge.test 2007-09-22 11:08:17 +02:00 @@ -676,11 +676,18 @@ CREATE TABLE t1 (c1 INT); CREATE TABLE t2 (c1 INT); CREATE TABLE t3 (c1 INT); INSERT INTO t3 VALUES (1), (2); +# Show that LAST table is opened. CREATE TABLE t4 (c1 INT) ENGINE=MRG_MYISAM UNION=(t1,t2) INSERT_METHOD=LAST SELECT * FROM t3; SHOW CREATE TABLE t4; SELECT * FROM t4; DROP TABLE t4; +# Show that FIRST table is opened. +CREATE TABLE t4 (c1 INT) ENGINE=MRG_MYISAM UNION=(t1,t2) + INSERT_METHOD=FIRST SELECT * FROM t3; +SHOW CREATE TABLE t4; +SELECT * FROM t4; +DROP TABLE t4; LOCK TABLES t1 WRITE, t2 WRITE, t3 READ; CREATE TABLE t4 (c1 INT); DROP TABLE t4; @@ -689,6 +696,13 @@ CREATE TABLE t4 (c1 INT) SELECT * FROM t --error ER_TABLE_NOT_LOCKED CREATE TABLE t4 (c1 INT) ENGINE=MRG_MYISAM UNION=(t1,t2) INSERT_METHOD=LAST SELECT * FROM t3; +UNLOCK TABLES; +CREATE TABLE t4 (c1 INT) ENGINE=MRG_MYISAM UNION=(t1,t2); +LOCK TABLES t4 READ; +--error ER_TABLE_NOT_LOCKED +SELECT * from t1, t4; +# Show that dropping a lcked MERGE table works. +DROP TABLE t4; UNLOCK TABLES; DROP TABLE t1, t2, t3; diff -Nrup a/sql/sql_base.cc b/sql/sql_base.cc --- a/sql/sql_base.cc 2007-09-12 22:11:44 +02:00 +++ b/sql/sql_base.cc 2007-09-22 11:08:17 +02:00 @@ -1850,6 +1850,7 @@ void close_temporary(TABLE *table, bool DBUG_PRINT("tmptable", ("closing table: '%s'.'%s'", table->s->db.str, table->s->table_name.str)); + /* Detach MERGE children, but do not clear references. It's deleted anyway. */ if (table->child_l) detach_merge_children(table, FALSE); free_io_cache(table); @@ -2437,9 +2438,14 @@ TABLE *open_table(THD *thd, TABLE_LIST * table->s->table_name.str); DBUG_RETURN(0); } + /* + When looking for a usable TABLE, ignore MERGE children, as they + belong to their parent and cannot be used explicitly. + */ if (!my_strcasecmp(system_charset_info, table->alias, alias) && table->query_id != thd->query_id && /* skip tables already used */ - !(thd->prelocked_mode && table->query_id)) + !(thd->prelocked_mode && table->query_id) && + !table->parent) { int distance= ((int) table->reginfo.lock_type - (int) table_list->lock_type); @@ -3419,6 +3425,12 @@ TABLE *drop_locked_tables(THD *thd,const if (table->db_stat) { table->db_stat= 0; + /* + When closing a MERGE parent table, detach its children first. + Clear child table references in case this object is opened again. + */ + if (table->child_l) + detach_merge_children(table, TRUE); table->file->close(); } } @@ -4009,6 +4021,19 @@ int open_tables(THD *thd, TABLE_LIST **s goto process_view_routines; } + /* + If in a MERGE table open, we need to remove the children list + from statement table list before restarting. Otherwise the list + will be inserted another time. + */ + if (tables->parent_l) + { + TABLE_LIST *parent_l= tables->parent_l; + /* The parent table should be correctly open at this point. */ + DBUG_ASSERT(parent_l->table); + parent_l->next_global= *parent_l->table->child_last_l; + } + if (refresh) // Refresh in progress { /* @@ -4027,18 +4052,6 @@ int open_tables(THD *thd, TABLE_LIST **s */ if (query_tables_last_own) thd->lex->mark_as_requiring_prelocking(query_tables_last_own); - /* - If in a MERGE table open, we need to remove the children list - from statement table list before restarting. Otherwise the list - will be inserted another time. - */ - if (tables->parent_l) - { - TABLE_LIST *parent_l= tables->parent_l; - /* The parent table should be correctly open at this point. */ - DBUG_ASSERT(parent_l->table); - parent_l->next_global= *parent_l->table->child_last_l; - } close_tables_for_reopen(thd, start); goto restart; }