3293 Dmitry Lenev 2011-07-22 [merge]
Merged fix for bug #11754210 - "45777: CHECK TABLE
DOESN'T SHOW ALL PROBLEMS FOR MERGE TABLE COMPLIANCE
IN 5.1" into mysql-trunk.
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
3292 Tor Didriksen 2011-07-22
Bug#12532830 post-push fix: windows case sensitivity ....
modified:
mysql-test/suite/innodb/r/innodb_bug54044.result
mysql-test/suite/innodb/t/innodb_bug54044.test
=== modified file 'mysql-test/r/merge.result'
--- a/mysql-test/r/merge.result 2011-03-26 10:56:27 +0000
+++ b/mysql-test/r/merge.result 2011-07-22 15:52:42 +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;
@@ -3635,7 +3636,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;
@@ -3651,7 +3652,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;
@@ -3678,6 +3679,40 @@ ERROR HY000: Table 't1' was locked with
UNLOCK TABLES;
DROP TABLE m1, t1;
#
+# 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
+#
# Additional coverage for refactoring which is made as part
# of fix for bug #27480 "Extend CREATE TEMPORARY TABLES privilege
# to allow temp table operations".
@@ -3766,4 +3801,3 @@ ERROR HY000: Unable to open underlying t
DROP TRIGGER trg1;
DROP TABLE t1;
DROP TABLE m1;
-End of 6.0 tests
=== modified file 'mysql-test/t/merge.test'
--- a/mysql-test/t/merge.test 2011-03-26 10:56:27 +0000
+++ b/mysql-test/t/merge.test 2011-07-22 15:52:42 +0000
@@ -2800,6 +2800,34 @@ DROP TABLE m1, t1;
--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
+
+
+--echo #
--echo # Additional coverage for refactoring which is made as part
--echo # of fix for bug #27480 "Extend CREATE TEMPORARY TABLES privilege
--echo # to allow temp table operations".
@@ -2877,7 +2905,6 @@ DROP TRIGGER trg1;
DROP TABLE t1;
DROP TABLE m1;
---echo End of 6.0 tests
--disable_result_log
--disable_query_log
=== modified file 'sql/sql_base.cc'
--- a/sql/sql_base.cc 2011-07-20 14:40:52 +0000
+++ b/sql/sql_base.cc 2011-07-22 15:52:42 +0000
@@ -88,6 +88,69 @@ bool No_such_table_error_handler::safely
return ((m_handled_errors > 0) && (m_unhandled_errors == 0));
}
+
+/**
+ This internal handler is used to trap ER_NO_SUCH_TABLE and
+ ER_WRONG_MRG_TABLE errors during CHECK/REPAIR TABLE for MERGE
+ tables.
+*/
+
+class Repair_mrg_table_error_handler : public Internal_error_handler
+{
+public:
+ Repair_mrg_table_error_handler()
+ : m_handled_errors(false), m_unhandled_errors(false)
+ {}
+
+ bool handle_condition(THD *thd,
+ uint sql_errno,
+ const char* sqlstate,
+ MYSQL_ERROR::enum_warning_level level,
+ const char* msg,
+ MYSQL_ERROR ** cond_hdl);
+
+ /**
+ Returns TRUE if there were ER_NO_SUCH_/WRONG_MRG_TABLE and there
+ were no unhandled errors. FALSE otherwise.
+ */
+ bool safely_trapped_errors()
+ {
+ /*
+ Check for m_handled_errors is here for extra safety.
+ It can be useful in situation when call to open_table()
+ fails because some error which was suppressed by another
+ error handler (e.g. in case of MDL deadlock which we
+ decided to solve by back-off and retry).
+ */
+ return (m_handled_errors && (! m_unhandled_errors));
+ }
+
+private:
+ bool m_handled_errors;
+ bool m_unhandled_errors;
+};
+
+
+bool
+Repair_mrg_table_error_handler::handle_condition(THD *,
+ uint sql_errno,
+ const char*,
+ MYSQL_ERROR::enum_warning_level level,
+ const char*,
+ MYSQL_ERROR ** cond_hdl)
+{
+ *cond_hdl= NULL;
+ if (sql_errno == ER_NO_SUCH_TABLE || sql_errno == ER_WRONG_MRG_TABLE)
+ {
+ m_handled_errors= true;
+ return TRUE;
+ }
+
+ m_unhandled_errors= true;
+ return FALSE;
+}
+
+
/**
@defgroup Data_Dictionary Data Dictionary
@{
@@ -4430,6 +4493,24 @@ open_and_process_table(THD *thd, LEX *le
thd->pop_internal_handler();
safe_to_ignore_table= no_such_table_handler.safely_trapped_errors();
}
+ else if (tables->parent_l && (thd->open_options & HA_OPEN_FOR_REPAIR))
+ {
+ /*
+ Also fail silently 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.
+ */
+ Repair_mrg_table_error_handler repair_mrg_table_handler;
+ thd->push_internal_handler(&repair_mrg_table_handler);
+
+ error= open_temporary_table(thd, tables);
+ if (!error && !tables->table)
+ error= open_table(thd, tables, new_frm_mem, ot_ctx);
+
+ thd->pop_internal_handler();
+ safe_to_ignore_table= repair_mrg_table_handler.safely_trapped_errors();
+ }
else
{
if (tables->parent_l)
=== modified file 'storage/myisammrg/ha_myisammrg.cc'
--- a/storage/myisammrg/ha_myisammrg.cc 2011-07-04 00:25:46 +0000
+++ b/storage/myisammrg/ha_myisammrg.cc 2011-07-22 15:52:42 +0000
@@ -155,9 +155,14 @@ 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);
+ /*
+ Push an error to be reported as part of CHECK/REPAIR result-set.
+ Note that calling my_error() from handler is a hack which is kept
+ here to avoid refactoring. Normally engines should report errors
+ through return value which will be interpreted by caller using
+ handler::print_error() call.
+ */
+ my_error(ER_ADMIN_WRONG_MRG_TABLE, MYF(0), buf);
}
@@ -594,8 +599,7 @@ public:
@return pointer to open MyISAM table structure
@retval !=NULL OK, returning pointer
- @retval NULL, my_errno == 0 Ok, no more child tables
- @retval NULL, my_errno != 0 error
+ @retval NULL, Error.
@detail
This function retrieves the MyISAM table handle from the
@@ -615,22 +619,23 @@ extern "C" MI_INFO *myisammrg_attach_chi
MI_INFO *myisam= NULL;
DBUG_ENTER("myisammrg_attach_children_callback");
- if (!child_l)
- {
- DBUG_PRINT("myrg", ("No more children to attach"));
- my_errno= 0; /* Ok, no more child tables. */
- goto end;
- }
+ /*
+ Number of children in the list and MYRG_INFO::tables_count,
+ which is used by caller of this function, should always match.
+ */
+ DBUG_ASSERT(child_l);
+
child= child_l->table;
+ /* Prepare for next child. */
+ param->next();
+
if (!child)
{
- DBUG_PRINT("myrg", ("Child table does not exist"));
- my_errno= HA_ERR_WRONG_MRG_TABLE_DEF;
+ DBUG_PRINT("error", ("failed to open underlying table '%s'.'%s'",
+ child_l->db, child_l->table_name));
goto end;
}
- /* Prepare for next child. */
- param->next();
/*
Do a quick compatibility check. The table def version is set when
@@ -661,7 +666,6 @@ extern "C" MI_INFO *myisammrg_attach_chi
{
DBUG_PRINT("error", ("temporary table mismatch parent: %d child: %d",
parent->s->tmp_table, child->s->tmp_table));
- my_errno= HA_ERR_WRONG_MRG_TABLE_DEF;
goto end;
}
@@ -672,12 +676,27 @@ extern "C" MI_INFO *myisammrg_attach_chi
DBUG_PRINT("error", ("no MyISAM handle for child table: '%s'.'%s' 0x%lx",
child->s->db.str, child->s->table_name.str,
(long) child));
- my_errno= HA_ERR_WRONG_MRG_TABLE_DEF;
}
- DBUG_PRINT("myrg", ("MyISAM handle: 0x%lx my_errno: %d",
- my_errno ? 0L : (long) myisam, my_errno));
+
+ DBUG_PRINT("myrg", ("MyISAM handle: 0x%lx", (long) myisam));
end:
+
+ if (!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);
+ /*
+ Push an error to be reported as part of CHECK/REPAIR result-set.
+ Note that calling my_error() from handler is a hack which is kept
+ here to avoid refactoring. Normally engines should report errors
+ through return value which will be interpreted by caller using
+ handler::print_error() call.
+ */
+ my_error(ER_ADMIN_WRONG_MRG_TABLE, MYF(0), buf);
+ }
+
DBUG_RETURN(myisam);
}
@@ -791,12 +810,6 @@ int ha_myisammrg::attach_children(void)
/* Must call this with children list in place. */
DBUG_ASSERT(this->table->pos_in_table_list->next_global == this->children_l);
- /*
- 'my_errno' is set by myisammrg_attach_children_callback() in
- case of an error.
- */
- my_errno= 0;
-
if (myrg_attach_children(this->file, this->test_if_locked |
current_thd->open_options,
myisammrg_attach_children_callback, ¶m,
=== modified file 'storage/myisammrg/myrg_open.c'
--- a/storage/myisammrg/myrg_open.c 2011-06-30 15:50:45 +0000
+++ b/storage/myisammrg/myrg_open.c 2011-07-22 15:52:42 +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,14 +467,11 @@ 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)
goto bad_children;
- /* Note: callback() resets my_errno, so it is safe to check it here */
- if (my_errno == HA_ERR_WRONG_MRG_TABLE_DEF)
- goto err;
+
if (sizeof(my_off_t) == 4 && file_offset > (ulonglong) (ulong) ~0L)
{
my_errno= HA_ERR_RECORD_FILE_FULL;
No bundle (reason: useless for push emails).
| Thread |
|---|
| • bzr push into mysql-trunk branch (Dmitry.Lenev:3292 to 3293) Bug#11754210 | Dmitry Lenev | 22 Jul |