summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorunknown <serg@serg.mylan>2004-06-24 19:46:50 +0200
committerunknown <serg@serg.mylan>2004-06-24 19:46:50 +0200
commitff736789672632d415d7d75d8b0a2e85b7b7eae4 (patch)
tree99d5fd1b33e2fdbeb208cef9dae2aa9acf28c5ce /sql
parentc6840712f55f9df9951474b0688e221f0f7c7403 (diff)
downloadmariadb-git-ff736789672632d415d7d75d8b0a2e85b7b7eae4.tar.gz
bug#4089 - JOIN::join_free calling mysql_unlock w/o index_end() before
sql/ha_myisam.h: cleanup mysql-test/r/bdb.result: bug#4089 mysql-test/t/bdb.test: bug#4089 sql/opt_range.cc: be sloppy sql/sql_select.cc: JOIN::join_free - pass it down the tree (of selects) call mysql_unlock_tables only in top-level select
Diffstat (limited to 'sql')
-rw-r--r--sql/ha_myisam.h2
-rw-r--r--sql/opt_range.cc3
-rw-r--r--sql/sql_select.cc34
3 files changed, 29 insertions, 10 deletions
diff --git a/sql/ha_myisam.h b/sql/ha_myisam.h
index 9069b41364d..f4c45e6524b 100644
--- a/sql/ha_myisam.h
+++ b/sql/ha_myisam.h
@@ -81,7 +81,7 @@ class ha_myisam: public handler
int index_first(byte * buf);
int index_last(byte * buf);
int index_next_same(byte *buf, const byte *key, uint keylen);
- int index_end() { ft_handler=NULL; return handler::index_end(); }
+ int index_end() { ft_handler=NULL; return 0; }
int ft_init()
{
if (!ft_handler)
diff --git a/sql/opt_range.cc b/sql/opt_range.cc
index 3a1d441caac..804bb0a413c 100644
--- a/sql/opt_range.cc
+++ b/sql/opt_range.cc
@@ -413,7 +413,8 @@ QUICK_SELECT::~QUICK_SELECT()
{
if (!dont_free)
{
- file->ha_index_end();
+ if (file->inited)
+ file->ha_index_end();
free_root(&alloc,MYF(0));
}
}
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 7d0c56aed2b..68da87bc210 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -3851,6 +3851,8 @@ JOIN::join_free(bool full)
JOIN_TAB *tab,*end;
DBUG_ENTER("JOIN::join_free");
+ full= full || !select_lex->uncacheable;
+
if (table)
{
/*
@@ -3862,7 +3864,18 @@ JOIN::join_free(bool full)
free_io_cache(table[const_tables]);
filesort_free_buffers(table[const_tables]);
}
- if (full || !select_lex->uncacheable)
+
+ for (SELECT_LEX_UNIT *unit= select_lex->first_inner_unit(); unit;
+ unit= unit->next_unit())
+ {
+ JOIN *join;
+ for (SELECT_LEX *sl= unit->first_select_in_union(); sl;
+ sl= sl->next_select())
+ if ((join= sl->join))
+ join->join_free(full);
+ }
+
+ if (full)
{
for (tab= join_tab, end= tab+tables; tab != end; tab++)
tab->cleanup();
@@ -3872,22 +3885,27 @@ JOIN::join_free(bool full)
{
for (tab= join_tab, end= tab+tables; tab != end; tab++)
{
- if (tab->table && tab->table->file->inited == handler::RND)
- tab->table->file->ha_rnd_end();
+ if (tab->table)
+ tab->table->file->ha_index_or_rnd_end();
}
}
}
+
/*
We are not using tables anymore
Unlock all tables. We may be in an INSERT .... SELECT statement.
*/
- if ((full || !select_lex->uncacheable) &&
- lock && thd->lock &&
- !(select_options & SELECT_NO_UNLOCK))
+ if (full && lock && thd->lock && !(select_options & SELECT_NO_UNLOCK))
{
- mysql_unlock_read_tables(thd, lock);// Don't free join->lock
- lock=0;
+ // TODO: unlock tables even if the join isn't top level select in the tree
+ if (select_lex == (thd->lex->unit.fake_select_lex ?
+ thd->lex->unit.fake_select_lex : &thd->lex->select_lex))
+ {
+ mysql_unlock_read_tables(thd, lock); // Don't free join->lock
+ lock=0;
+ }
}
+
if (full)
{
group_fields.delete_elements();