Commit 1ff21a9e authored by serg@serg.mylan's avatar serg@serg.mylan

bug#4089 - JOIN::join_free calling mysql_unlock w/o index_end() before

parent 334eb773
...@@ -1190,3 +1190,23 @@ exists (select 'two' from t1 where 'two' = outer_table.b); ...@@ -1190,3 +1190,23 @@ exists (select 'two' from t1 where 'two' = outer_table.b);
b b
drop table t1; drop table t1;
set autocommit=1; set autocommit=1;
create table t1(a int primary key, b varchar(30)) engine=bdb;
insert into t1 values (1,'one'), (2,'two'), (3,'three'), (4,'four');
create table t2 like t1;
insert t2 select * from t1;
select a from t1 where a in (select a from t2);
a
1
2
3
4
delete from t2;
insert into t2 (a, b)
select a, b from t1 where (a, b) in (select a, b from t1);
select * from t2;
a b
1 one
2 two
3 three
4 four
drop table t1, t2;
...@@ -840,10 +840,13 @@ set autocommit=1; ...@@ -840,10 +840,13 @@ set autocommit=1;
# Bug #4089: subselect and open cursor. # Bug #4089: subselect and open cursor.
# #
#create table t1(a int primary key, b varchar(30)) engine=bdb; create table t1(a int primary key, b varchar(30)) engine=bdb;
#insert into t1 values (1,'one'), (2,'two'), (3,'three'), (4,'four'); insert into t1 values (1,'one'), (2,'two'), (3,'three'), (4,'four');
#create table t2 like t1; create table t2 like t1;
#insert into t2 (a, b) insert t2 select * from t1;
# select a, b from t1 where (a, b) in (select a, b from t1); select a from t1 where a in (select a from t2);
#select * from t2; delete from t2;
#drop table t1, t2; insert into t2 (a, b)
select a, b from t1 where (a, b) in (select a, b from t1);
select * from t2;
drop table t1, t2;
...@@ -81,7 +81,7 @@ class ha_myisam: public handler ...@@ -81,7 +81,7 @@ class ha_myisam: public handler
int index_first(byte * buf); int index_first(byte * buf);
int index_last(byte * buf); int index_last(byte * buf);
int index_next_same(byte *buf, const byte *key, uint keylen); 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() int ft_init()
{ {
if (!ft_handler) if (!ft_handler)
......
...@@ -413,7 +413,8 @@ QUICK_SELECT::~QUICK_SELECT() ...@@ -413,7 +413,8 @@ QUICK_SELECT::~QUICK_SELECT()
{ {
if (!dont_free) if (!dont_free)
{ {
file->ha_index_end(); if (file->inited)
file->ha_index_end();
free_root(&alloc,MYF(0)); free_root(&alloc,MYF(0));
} }
} }
......
...@@ -3851,6 +3851,8 @@ JOIN::join_free(bool full) ...@@ -3851,6 +3851,8 @@ JOIN::join_free(bool full)
JOIN_TAB *tab,*end; JOIN_TAB *tab,*end;
DBUG_ENTER("JOIN::join_free"); DBUG_ENTER("JOIN::join_free");
full= full || !select_lex->uncacheable;
if (table) if (table)
{ {
/* /*
...@@ -3862,7 +3864,18 @@ JOIN::join_free(bool full) ...@@ -3862,7 +3864,18 @@ JOIN::join_free(bool full)
free_io_cache(table[const_tables]); free_io_cache(table[const_tables]);
filesort_free_buffers(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++) for (tab= join_tab, end= tab+tables; tab != end; tab++)
tab->cleanup(); tab->cleanup();
...@@ -3872,22 +3885,27 @@ JOIN::join_free(bool full) ...@@ -3872,22 +3885,27 @@ JOIN::join_free(bool full)
{ {
for (tab= join_tab, end= tab+tables; tab != end; tab++) for (tab= join_tab, end= tab+tables; tab != end; tab++)
{ {
if (tab->table && tab->table->file->inited == handler::RND) if (tab->table)
tab->table->file->ha_rnd_end(); tab->table->file->ha_index_or_rnd_end();
} }
} }
} }
/* /*
We are not using tables anymore We are not using tables anymore
Unlock all tables. We may be in an INSERT .... SELECT statement. Unlock all tables. We may be in an INSERT .... SELECT statement.
*/ */
if ((full || !select_lex->uncacheable) && if (full && lock && thd->lock && !(select_options & SELECT_NO_UNLOCK))
lock && thd->lock &&
!(select_options & SELECT_NO_UNLOCK))
{ {
mysql_unlock_read_tables(thd, lock);// Don't free join->lock // TODO: unlock tables even if the join isn't top level select in the tree
lock=0; 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) if (full)
{ {
group_fields.delete_elements(); group_fields.delete_elements();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment