summaryrefslogtreecommitdiff
path: root/myisammrg/myrg_open.c
diff options
context:
space:
mode:
authorSergey Vojtovich <svoj@mysql.com>2009-02-04 15:46:23 +0400
committerSergey Vojtovich <svoj@mysql.com>2009-02-04 15:46:23 +0400
commit97bd763544bbaf882a083b1952b47901bc9a335b (patch)
tree7d95641d44dc2e7ee80d8585280e19b50723a33e /myisammrg/myrg_open.c
parent9a3afd1a121fe3ffdc7a58c45341ce4b2e9fb144 (diff)
downloadmariadb-git-97bd763544bbaf882a083b1952b47901bc9a335b.tar.gz
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. 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.
Diffstat (limited to 'myisammrg/myrg_open.c')
-rw-r--r--myisammrg/myrg_open.c17
1 files changed, 10 insertions, 7 deletions
diff --git a/myisammrg/myrg_open.c b/myisammrg/myrg_open.c
index 0e82e429afd..4e61f42efce 100644
--- a/myisammrg/myrg_open.c
+++ b/myisammrg/myrg_open.c
@@ -40,6 +40,7 @@ MYRG_INFO *myrg_open(const char *name, int mode, int handle_locking)
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, int mode, int handle_locking)
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, int mode, int handle_locking)
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, int mode, int handle_locking)
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, int mode, int handle_locking)
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: