MySQL Lists are EOL. Please join:

List:Commits« Previous MessageNext Message »
From:Sergey Vojtovich Date:February 4 2009 11:46am
Subject:bzr commit into mysql-5.0-bugteam branch (svoj:2737) Bug#32047
View as plain text  
#At file:///home/svoj/devel/bzr-mysql/mysql-5.0-bugteam-bug32047/ based on revid:patrick.crews@stripped

 2737 Sergey Vojtovich	2009-02-04
      BUG#32047 - 'Spurious' errors while opening MERGE tables
      
      Accessing well defined MERGE table may return an error
      stating that the merge table is incorrectly defined. This
      happens if MERGE child tables were accessed before and we
      failed to open another incorrectly defined MERGE table in
      this connection.
      
      myrg_open() internally used my_errno as a variable for determining
      failure, and thus could be tricked into a wrong decision by other
      uses of my_errno.
      
      With this fix we use function local boolean flag instead of my_errno
      to determine failure.
modified:
  myisammrg/myrg_open.c
  mysql-test/r/merge.result
  mysql-test/t/merge.test

per-file messages:
  myisammrg/myrg_open.c
    There are two requirement for accessing/setting my_errno variable,
    which were not followed by myrg_open():
    - it must be checked immediately after a function returned an error. There
      must be no calls to other functions that may change it's value between.
    - my_errno value must be set right before a function is going to return an
      error. There must be no calls to other functions that may change it's
      value between (that's why we have these tricks with save_errno at the
      bottom of myrg_open()).
    
    myrg_open() internally used my_errno as a variable for determining
    failure, and thus could be tricked into a wrong decision by other
    uses of my_errno.
  mysql-test/r/merge.result
    A test case for BUG#32047.
  mysql-test/t/merge.test
    A test case for BUG#32047.
=== modified file 'myisammrg/myrg_open.c'
--- a/myisammrg/myrg_open.c	2007-06-05 23:42:41 +0000
+++ b/myisammrg/myrg_open.c	2009-02-04 11:46:23 +0000
@@ -40,6 +40,7 @@ MYRG_INFO *myrg_open(const char *name, i
   IO_CACHE file;
   MI_INFO *isam=0;
   uint found_merge_insert_method= 0;
+  my_bool bad_children= FALSE;
   DBUG_ENTER("myrg_open");
 
   LINT_INIT(key_parts);
@@ -89,13 +90,13 @@ MYRG_INFO *myrg_open(const char *name, i
       fn_format(buff, buff, "", "", 0);
     if (!(isam=mi_open(buff,mode,(handle_locking?HA_OPEN_WAIT_IF_LOCKED:0))))
     {
-      my_errno= HA_ERR_WRONG_MRG_TABLE_DEF;
       if (handle_locking & HA_OPEN_FOR_REPAIR)
       {
         myrg_print_wrong_table(buff);
+        bad_children= TRUE;
         continue;
       }
-      goto err;
+      goto bad_children;
     }
     if (!m_info)                                /* First file */
     {
@@ -122,13 +123,13 @@ MYRG_INFO *myrg_open(const char *name, i
     files++;
     if (m_info->reclength != isam->s->base.reclength)
     {
-      my_errno=HA_ERR_WRONG_MRG_TABLE_DEF;
       if (handle_locking & HA_OPEN_FOR_REPAIR)
       {
         myrg_print_wrong_table(buff);
+        bad_children= TRUE;
         continue;
       }
-      goto err;
+      goto bad_children;
     }
     m_info->options|= isam->s->options;
     m_info->records+= isam->state->records;
@@ -141,8 +142,8 @@ MYRG_INFO *myrg_open(const char *name, i
                                      m_info->tables);
   }
 
-  if (my_errno == HA_ERR_WRONG_MRG_TABLE_DEF)
-    goto err;
+  if (bad_children)
+    goto bad_children;
   if (!m_info && !(m_info= (MYRG_INFO*) my_malloc(sizeof(MYRG_INFO),
                                                   MYF(MY_WME | MY_ZEROFILL))))
     goto err;
@@ -170,12 +171,14 @@ MYRG_INFO *myrg_open(const char *name, i
   pthread_mutex_unlock(&THR_LOCK_open);
   DBUG_RETURN(m_info);
 
+bad_children:
+  my_errno= HA_ERR_WRONG_MRG_TABLE_DEF;
 err:
   save_errno=my_errno;
   switch (errpos) {
   case 3:
     while (files)
-      mi_close(m_info->open_tables[--files].table);
+      (void) mi_close(m_info->open_tables[--files].table);
     my_free((char*) m_info,MYF(0));
     /* Fall through */
   case 2:

=== modified file 'mysql-test/r/merge.result'
--- a/mysql-test/r/merge.result	2008-03-14 15:38:22 +0000
+++ b/mysql-test/r/merge.result	2009-02-04 11:46:23 +0000
@@ -940,4 +940,15 @@ m1	CREATE TABLE `m1` (
   `a` int(11) default NULL
 ) ENGINE=MRG_MyISAM DEFAULT CHARSET=latin1
 DROP TABLE t1, m1;
+CREATE TABLE t1(a INT);
+CREATE TABLE t2(a VARCHAR(10));
+CREATE TABLE m1(a INT) ENGINE=MERGE UNION=(t1, t2);
+CREATE TABLE m2(a INT) ENGINE=MERGE UNION=(t1);
+SELECT * FROM t1;
+a
+SELECT * FROM m1;
+ERROR HY000: Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exist
+SELECT * FROM m2;
+a
+DROP TABLE t1, t2, m1, m2;
 End of 5.0 tests

=== modified file 'mysql-test/t/merge.test'
--- a/mysql-test/t/merge.test	2008-03-14 15:38:22 +0000
+++ b/mysql-test/t/merge.test	2009-02-04 11:46:23 +0000
@@ -556,4 +556,17 @@ ALTER TABLE m1 UNION=();
 SHOW CREATE TABLE m1;
 DROP TABLE t1, m1;
 
+#
+# BUG#32047 - 'Spurious' errors while opening MERGE tables
+#
+CREATE TABLE t1(a INT);
+CREATE TABLE t2(a VARCHAR(10));
+CREATE TABLE m1(a INT) ENGINE=MERGE UNION=(t1, t2);
+CREATE TABLE m2(a INT) ENGINE=MERGE UNION=(t1);
+SELECT * FROM t1;
+--error ER_WRONG_MRG_TABLE
+SELECT * FROM m1;
+SELECT * FROM m2;
+DROP TABLE t1, t2, m1, m2;
+
 --echo End of 5.0 tests

Thread
bzr commit into mysql-5.0-bugteam branch (svoj:2737) Bug#32047Sergey Vojtovich4 Feb