From: Dmitry Lenev Date: June 21 2011 12:15pm Subject: bzr commit into mysql-5.5 branch (Dmitry.Lenev:3452) Bug#11754210 List-Archive: http://lists.mysql.com/commits/139560 X-Bug: 11754210 Message-Id: <20110621121530.A0B1C7404E9@bandersnatch> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="===============0180183808==" --===============0180183808== MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Content-Disposition: inline #At file:///home/dlenev/src/bzr/mysql-5.5-11754210/ based on revid:marko.makela@stripped 3452 Dmitry Lenev 2011-06-21 Tentative fix for bug #11754210 - "45777: CHECK TABLE DOESN'T SHOW ALL PROBLEMS FOR MERGE TABLE COMPLIANCE IN 5.1". The problem was that CHECK/REPAIR TABLE for a MERGE table which had several children missing or in wrong engine reported only issue with the first such table in its result-set. While in 5.0 this statement returned the whole list of problematic tables in this case. Ability to report problems for all children was lost during significant refactorings of MERGE code which were done as part of work on 5.1 and 5.5 releases. This patch restores status quo ante refactorings by changing code in such a way that: 1) Failure to open child table during CHECK/REPAIR TABLE for a MERGE table is not reported immediately when its absence is discovered in open_tables(). Instead handling/error reporting in such a situation is postponed until the moment when children are attached. 2) Code performing attaching of children no longer stops when it encounters first problem with one of the children during CHECK/REPAIR TABLE. Instead it continues iteration through the child list until all problems caused by child absence/ wrong engine are reported. Note that even after this change problem with mismatch of child/parent definition won't be reported if there is also another child missing, but this is how it was in 5.0 as well. @ mysql-test/r/merge.result Added test case for bug #11754210 - "45777: CHECK TABLE DOESN'T SHOW ALL PROBLEMS FOR MERGE TABLE COMPLIANCE IN 5.1". Adjusted results of existing tests to the fact that CHECK/REPAIR TABLE statements now try to report problems about missing table/ wrong engine for all underlying tables, and to the fact that mismatch of parent/child definitions is always reported as an error and not a warning. @ mysql-test/t/merge.test Added test case for bug #11754210 - "45777: CHECK TABLE DOESN'T SHOW ALL PROBLEMS FOR MERGE TABLE COMPLIANCE IN 5.1". @ sql/sql_base.cc Changed code responsible for opening tables to ignore the fact that underlying tables of a MERGE table are missing, if this table is opened for CHECK/REPAIR TABLE. The absence of underlying tables in this case is now detected and appropriate error is reported at the point when child tables are attached. At this point we can produce full list of problematic child tables/errors to be returned as part of CHECK/REPAIR TABLE result-set. @ storage/myisammrg/ha_myisammrg.cc Changed myisammrg_attach_children_callback() to handle new situation, when during CHECK/REPAIR TABLE we do not report error about missing child immediately when this fact is discovered during open_tables() but postpone error-reporting till the time when children are attached. Also this callback is now responsible for pushing an error mentioning problematic child table to the list of errors to be reported by CHECK/REPAIR TABLE statements. Changed myrg_print_wrong_table() to always report a problem with child table as an error and not as a warning. This makes reporting for different types of issues with child tables more consistent and compatible with 5.0 behavior. @ storage/myisammrg/myrg_open.c Changed code in myrg_attach_children() not to abort on the first problem with a child table when attaching children to parent MERGE table during CHECK/REPAIR TABLE statement execution. This allows CHECK/REPAIR TABLE to report problems about absence/wrong engine for all underlying tables as part of their result-set. modified: mysql-test/r/merge.result mysql-test/t/merge.test sql/sql_base.cc storage/myisammrg/ha_myisammrg.cc storage/myisammrg/myrg_open.c === modified file 'mysql-test/r/merge.result' --- a/mysql-test/r/merge.result 2010-11-30 17:53:11 +0000 +++ b/mysql-test/r/merge.result 2011-06-21 12:15:22 +0000 @@ -904,7 +904,8 @@ SELECT * FROM tm1; ERROR HY000: Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exist CHECK TABLE tm1; Table Op Msg_type Msg_text -test.tm1 check Error Table 'test.t1' doesn't exist +test.tm1 check Error Table 'test.t1' is differently defined or of non-MyISAM type or doesn't exist +test.tm1 check Error Table 'test.t2' is differently defined or of non-MyISAM type or doesn't exist test.tm1 check Error Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exist test.tm1 check error Corrupt CREATE TABLE t1(a INT); @@ -912,7 +913,7 @@ SELECT * FROM tm1; ERROR HY000: Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exist CHECK TABLE tm1; Table Op Msg_type Msg_text -test.tm1 check Error Table 'test.t2' doesn't exist +test.tm1 check Error Table 'test.t2' is differently defined or of non-MyISAM type or doesn't exist test.tm1 check Error Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exist test.tm1 check error Corrupt CREATE TABLE t2(a BLOB); @@ -920,7 +921,7 @@ SELECT * FROM tm1; ERROR HY000: Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exist CHECK TABLE tm1; Table Op Msg_type Msg_text -test.tm1 check Warning Table 'test.t2' is differently defined or of non-MyISAM type or doesn't exist +test.tm1 check Error Table 'test.t2' is differently defined or of non-MyISAM type or doesn't exist test.tm1 check Error Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exist test.tm1 check error Corrupt ALTER TABLE t2 MODIFY a INT; @@ -3634,7 +3635,7 @@ test.t1 analyze Error Unable to open und test.t1 analyze error Corrupt CHECK TABLE t1; Table Op Msg_type Msg_text -test.t1 check Error Table 'test.t_not_exists' doesn't exist +test.t1 check Error Table 'test.t_not_exists' is differently defined or of non-MyISAM type or doesn't exist test.t1 check Error Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exist test.t1 check error Corrupt CHECKSUM TABLE t1; @@ -3650,7 +3651,7 @@ test.t1 optimize Error Unable to open un test.t1 optimize error Corrupt REPAIR TABLE t1; Table Op Msg_type Msg_text -test.t1 repair Error Table 'test.t_not_exists' doesn't exist +test.t1 repair Error Table 'test.t_not_exists' is differently defined or of non-MyISAM type or doesn't exist test.t1 repair Error Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exist test.t1 repair error Corrupt REPAIR TABLE t1 USE_FRM; @@ -3676,4 +3677,37 @@ ALTER TABLE t1 engine=myisam; ERROR HY000: Table 't1' was locked with a READ lock and can't be updated UNLOCK TABLES; DROP TABLE m1, t1; -End of 6.0 tests +# +# Test for bug #11754210 - "45777: CHECK TABLE DOESN'T SHOW ALL +# PROBLEMS FOR MERGE TABLE COMPLIANCE IN 5.1" +# +drop tables if exists t1, t2, t3, t4, m1; +create table t1(id int) engine=myisam; +create view t3 as select 1 as id; +create table t4(id int) engine=memory; +create table m1(id int) engine=merge union=(t1,t2,t3,t4); +select * from m1; +ERROR HY000: Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exist +# The below CHECK and REPAIR TABLE statements should +# report all problems with underlying tables: +# - absence of 't2', +# - missing base table for 't3', +# - wrong engine of 't4'. +check table m1; +Table Op Msg_type Msg_text +test.m1 check Error Table 'test.t2' is differently defined or of non-MyISAM type or doesn't exist +test.m1 check Error Table 'test.t3' is differently defined or of non-MyISAM type or doesn't exist +test.m1 check Error Table 'test.t4' is differently defined or of non-MyISAM type or doesn't exist +test.m1 check Error Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exist +test.m1 check error Corrupt +repair table m1; +Table Op Msg_type Msg_text +test.m1 repair Error Table 'test.t2' is differently defined or of non-MyISAM type or doesn't exist +test.m1 repair Error Table 'test.t3' is differently defined or of non-MyISAM type or doesn't exist +test.m1 repair Error Table 'test.t4' is differently defined or of non-MyISAM type or doesn't exist +test.m1 repair Error Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exist +test.m1 repair error Corrupt +# Clean-up. +drop tables m1, t1, t4; +drop view t3; +End of 5.5 tests === modified file 'mysql-test/t/merge.test' --- a/mysql-test/t/merge.test 2010-10-06 07:56:29 +0000 +++ b/mysql-test/t/merge.test 2011-06-21 12:15:22 +0000 @@ -2798,7 +2798,32 @@ UNLOCK TABLES; DROP TABLE m1, t1; ---echo End of 6.0 tests +--echo # +--echo # Test for bug #11754210 - "45777: CHECK TABLE DOESN'T SHOW ALL +--echo # PROBLEMS FOR MERGE TABLE COMPLIANCE IN 5.1" +--echo # +--disable_warnings +drop tables if exists t1, t2, t3, t4, m1; +--enable_warnings +create table t1(id int) engine=myisam; +create view t3 as select 1 as id; +create table t4(id int) engine=memory; +create table m1(id int) engine=merge union=(t1,t2,t3,t4); +--error ER_WRONG_MRG_TABLE +select * from m1; +--echo # The below CHECK and REPAIR TABLE statements should +--echo # report all problems with underlying tables: +--echo # - absence of 't2', +--echo # - missing base table for 't3', +--echo # - wrong engine of 't4'. +check table m1; +repair table m1; +--echo # Clean-up. +drop tables m1, t1, t4; +drop view t3; + + +--echo End of 5.5 tests --disable_result_log --disable_query_log === modified file 'sql/sql_base.cc' --- a/sql/sql_base.cc 2011-05-21 08:21:08 +0000 +++ b/sql/sql_base.cc 2011-06-21 12:15:22 +0000 @@ -68,7 +68,7 @@ No_such_table_error_handler::handle_cond MYSQL_ERROR ** cond_hdl) { *cond_hdl= NULL; - if (sql_errno == ER_NO_SUCH_TABLE) + if (sql_errno == ER_NO_SUCH_TABLE || sql_errno == ER_WRONG_MRG_TABLE) { m_handled_errors++; return TRUE; @@ -4363,13 +4363,25 @@ open_and_process_table(THD *thd, LEX *le /* Not a placeholder: must be a base table or a view. Let us open it. */ DBUG_ASSERT(!tables->table); - if (tables->prelocking_placeholder) + if (tables->prelocking_placeholder || + (tables->parent_l && (thd->open_options & HA_OPEN_FOR_REPAIR))) { /* For the tables added by the pre-locking code, attempt to open the table but fail silently if the table does not exist. The real failure will occur when/if a statement attempts to use that table. + + Do similar thing for underlying tables of a MERGE table if this + table is opened for CHECK/REPAIR TABLE statement. This is needed + to provide complete list of problematic underlying tables in + CHECK/REPAIR TABLE output. + + QQ: Maybe it makes sense to split branch for prelocking case + and MERGE + CHECK TABLES and use different, more specific + error handlers for each case? I.e. currently we somewhat + rely that for tables from prelocking list we won't get + ER_WRONG_MRG_TABLE... */ No_such_table_error_handler no_such_table_handler; thd->push_internal_handler(&no_such_table_handler); === modified file 'storage/myisammrg/ha_myisammrg.cc' --- a/storage/myisammrg/ha_myisammrg.cc 2011-04-20 17:53:08 +0000 +++ b/storage/myisammrg/ha_myisammrg.cc 2011-06-21 12:15:22 +0000 @@ -159,9 +159,7 @@ extern "C" void myrg_print_wrong_table(c buf[db.length]= '.'; memcpy(buf + db.length + 1, name.str, name.length); buf[db.length + name.length + 1]= 0; - push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN, - ER_ADMIN_WRONG_MRG_TABLE, ER(ER_ADMIN_WRONG_MRG_TABLE), - buf); + my_error(ER_ADMIN_WRONG_MRG_TABLE, MYF(0), buf); } @@ -625,6 +623,23 @@ extern "C" MI_INFO *myisammrg_attach_chi param->next(); /* + When MERGE table is opened for CHECK or REPAIR TABLE statements failure + to open any of underlying tables is ignored until this moment (this is + needed to provide complete list of problematic underlying tables in + CHECK/REPAIR TABLE output). + Here we detect such a situation and report an appropriate error. + */ + if (! child) + { + DBUG_PRINT("error", ("failed to open underlying table '%s'.'%s'", + child_l->db, child_l->table_name)); + /* This should only happen inside of CHECK/REPAIR TABLE. */ + DBUG_ASSERT(current_thd->open_options & HA_OPEN_FOR_REPAIR); + my_errno= HA_ERR_WRONG_MRG_TABLE_DEF; + goto end; + } + + /* Do a quick compatibility check. The table def version is set when the table share is created. The child def version is copied from the table def version after a successful compatibility check. @@ -670,6 +685,15 @@ extern "C" MI_INFO *myisammrg_attach_chi my_errno ? 0L : (long) myisam, my_errno)); end: + + if (child_l && !myisam && + (current_thd->open_options & HA_OPEN_FOR_REPAIR)) + { + char buf[2*NAME_LEN + 1 + 1]; + strxnmov(buf, sizeof(buf) - 1, child_l->db, ".", child_l->table_name, NULL); + my_error(ER_ADMIN_WRONG_MRG_TABLE, MYF(0), buf); + } + DBUG_RETURN(myisam); } === modified file 'storage/myisammrg/myrg_open.c' --- a/storage/myisammrg/myrg_open.c 2011-02-11 14:00:09 +0000 +++ b/storage/myisammrg/myrg_open.c 2011-06-21 12:15:22 +0000 @@ -385,6 +385,7 @@ int myrg_attach_children(MYRG_INFO *m_in uint UNINIT_VAR(key_parts); uint min_keys; my_bool bad_children= FALSE; + my_bool first_child= TRUE; DBUG_ENTER("myrg_attach_children"); DBUG_PRINT("myrg", ("handle_locking: %d", handle_locking)); @@ -399,16 +400,26 @@ int myrg_attach_children(MYRG_INFO *m_in errpos= 0; file_offset= 0; min_keys= 0; - child_nr= 0; - while ((myisam= (*callback)(callback_param))) + for (child_nr= 0; child_nr < m_info->tables; child_nr++) { + if (! (myisam= (*callback)(callback_param))) + { + if (handle_locking & HA_OPEN_FOR_REPAIR) + { + /* An appropriate error should've been already pushed by callback. */ + bad_children= TRUE; + continue; + } + goto bad_children; + } + DBUG_PRINT("myrg", ("child_nr: %u table: '%s'", child_nr, myisam->filename)); - DBUG_ASSERT(child_nr < m_info->tables); /* Special handling when the first child is attached. */ - if (!child_nr) + if (first_child) { + first_child= FALSE; m_info->reclength= myisam->s->base.reclength; min_keys= myisam->s->base.keys; key_parts= myisam->s->base.key_parts; @@ -456,7 +467,6 @@ int myrg_attach_children(MYRG_INFO *m_in for (idx= 0; idx < key_parts; idx++) m_info->rec_per_key_part[idx]+= (myisam->s->state.rec_per_key_part[idx] / m_info->tables); - child_nr++; } if (bad_children) --===============0180183808== MIME-Version: 1.0 Content-Type: text/bzr-bundle; charset="us-ascii"; name="bzr/dmitry.lenev@stripped" Content-Transfer-Encoding: 7bit Content-Disposition: inline # Bazaar merge directive format 2 (Bazaar 0.90) # revision_id: dmitry.lenev@stripped # target_branch: file:///home/dlenev/src/bzr/mysql-5.5-11754210/ # testament_sha1: bae8ce00ba9a9e17c13d97b274e5d6eb72b3677b # timestamp: 2011-06-21 16:15:30 +0400 # base_revision_id: marko.makela@stripped\ # hobymycvru129t9a # # Begin bundle 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 m0Hd3fAePYf/8XckU4UJCggRhUA= --===============0180183808==--