diff --git a/mysql-test/r/subselect_innodb.result b/mysql-test/r/subselect_innodb.result index 9c1816e295c..bbbc607b6f8 100644 --- a/mysql-test/r/subselect_innodb.result +++ b/mysql-test/r/subselect_innodb.result @@ -96,3 +96,13 @@ id value (select t1.value from t1 where t1.id=t2.id) 1 z a 2 x b drop table t1,t2; +create table t1 (a int, b int) engine=innodb; +insert into t1 values (1,2), (1,3), (2,3), (2,4), (2,5), (3,4), (4,5), (4,100); +create table t2 (a int) engine=innodb; +insert into t2 values (1),(2),(3),(4); +select a, sum(b) as b from t1 group by a having b > (select max(a) from t2); +a b +1 5 +2 12 +4 105 +drop table t1, t2; diff --git a/mysql-test/t/subselect_innodb.test b/mysql-test/t/subselect_innodb.test index 47642832158..8c13171d221 100644 --- a/mysql-test/t/subselect_innodb.test +++ b/mysql-test/t/subselect_innodb.test @@ -101,3 +101,13 @@ insert into t2 values (1,'z'),(2,'x'); select t2.id,t2.value,(select t1.value from t1 where t1.id=t2.id) from t2; select t2.id,t2.value,(select t1.value from t1 where t1.id=t2.id) from t2; drop table t1,t2; + +# +# unlocking tables with subqueries in HAVING +# +create table t1 (a int, b int) engine=innodb; +insert into t1 values (1,2), (1,3), (2,3), (2,4), (2,5), (3,4), (4,5), (4,100); +create table t2 (a int) engine=innodb; +insert into t2 values (1),(2),(3),(4); +select a, sum(b) as b from t1 group by a having b > (select max(a) from t2); +drop table t1, t2; diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index 691ec5f4c7b..082c434f2d9 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -74,6 +74,11 @@ void Item_subselect::init(st_select_lex *select_lex, else engine= new subselect_single_select_engine(select_lex, result, this); } + { + SELECT_LEX *upper= unit->outer_select(); + if (upper->parsing_place == SELECT_LEX_NODE::IN_HAVING) + upper->subquery_in_having= 1; + } DBUG_VOID_RETURN; } diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index b6cb61fe10e..d945eef1425 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -1008,7 +1008,7 @@ void st_select_lex::init_query() ref_pointer_array= 0; select_n_having_items= 0; prep_where= 0; - explicit_limit= 0; + subquery_in_having= explicit_limit= 0; } void st_select_lex::init_select() diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 54d9a09c1f3..328df2f6bb9 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -433,6 +433,11 @@ public: bool having_fix_field; /* explicit LIMIT clause was used */ bool explicit_limit; + /* + there are subquery in HAVING clause => we can't close tables before + query processing end even if we use temporary table + */ + bool subquery_in_having; /* SELECT for SELECT command st_select_lex. Used to privent scaning diff --git a/sql/sql_select.cc b/sql/sql_select.cc index f1f93343a63..946c21bf24f 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -3906,7 +3906,8 @@ JOIN::join_free(bool full) */ if ((full || !select_lex->uncacheable) && lock && thd->lock && - !(select_options & SELECT_NO_UNLOCK)) + !(select_options & SELECT_NO_UNLOCK) && + !select_lex->subquery_in_having) { mysql_unlock_read_tables(thd, lock);// Don't free join->lock lock=0;