diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index 6e35b6e78c1..a2460b8f11a 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -1438,4 +1438,11 @@ explain select * from t3 where a > all (select max(b) from t2 group by a); id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t3 ALL NULL NULL NULL NULL 3 Using where 2 SUBQUERY t2 ALL NULL NULL NULL NULL 4 Using temporary; Using filesort -drop table if exists t2, t3; +drop table t2, t3; +create table t1 (E1 INTEGER UNSIGNED NOT NULL, E2 INTEGER UNSIGNED NOT NULL, E3 INTEGER UNSIGNED NOT NULL, PRIMARY KEY(E1) +); +insert into t1 VALUES(1,1,1), (2,2,1); +select count(*) from t1 INNER JOIN (SELECT A.E1, A.E2, A.E3 FROM t1 AS A WHERE A.E3 = (SELECT MAX(B.E3) FROM t1 AS B WHERE A.E2 = B.E2)) AS THEMAX ON t1.E1 = THEMAX.E2 AND t1.E1 = t1.E2; +count(*) +2 +drop table t1; diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test index 9ba91c7e0a6..afc2d1a9328 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -964,4 +964,13 @@ explain select * from t3 where a >= all (select b from t2); insert into t2 values (2,2), (2,1), (3,3), (3,1); select * from t3 where a > all (select max(b) from t2 group by a); explain select * from t3 where a > all (select max(b) from t2 group by a); -drop table if exists t2, t3; +drop table t2, t3; + +# +# deived tables with subquery inside all by one table +# +create table t1 (E1 INTEGER UNSIGNED NOT NULL, E2 INTEGER UNSIGNED NOT NULL, E3 INTEGER UNSIGNED NOT NULL, PRIMARY KEY(E1) +); +insert into t1 VALUES(1,1,1), (2,2,1); +select count(*) from t1 INNER JOIN (SELECT A.E1, A.E2, A.E3 FROM t1 AS A WHERE A.E3 = (SELECT MAX(B.E3) FROM t1 AS B WHERE A.E2 = B.E2)) AS THEMAX ON t1.E1 = THEMAX.E2 AND t1.E1 = t1.E2; +drop table t1; diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc index 13d3cc27376..7fd2b751c1d 100644 --- a/sql/sql_derived.cc +++ b/sql/sql_derived.cc @@ -220,7 +220,7 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, } } else - unit->exclude_level(); + unit->exclude_tree(); org_table_list->db= (char *)""; #ifndef DBUG_OFF /* Try to catch errors if this is accessed */ diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 80d698dfc26..5b05bf096cb 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -1097,6 +1097,16 @@ void st_select_lex_node::exclude() */ } + +/* + Exclude level of current unit from tree of SELECTs + + SYNOPSYS + st_select_lex_unit::exclude_level() + + NOTE: units which belong to current will be brought up on level of + currernt unit +*/ void st_select_lex_unit::exclude_level() { SELECT_LEX_UNIT *units= 0, **units_last= &units; @@ -1125,6 +1135,30 @@ void st_select_lex_unit::exclude_level() (*prev)= next; } + +/* + Exclude subtree of current unit from tree of SELECTs + + SYNOPSYS + st_select_lex_unit::exclude_tree() +*/ +void st_select_lex_unit::exclude_tree() +{ + SELECT_LEX_UNIT *units= 0, **units_last= &units; + for (SELECT_LEX *sl= first_select(); sl; sl= sl->next_select()) + { + if (sl->link_prev && (*sl->link_prev= sl->link_next)) + sl->link_next->link_prev= sl->link_prev; + + for (SELECT_LEX_UNIT *u= sl->first_inner_unit(); u; u= u->next_unit()) + { + u->exclude_level(); + } + } + (*prev)= next; +} + + /* st_select_lex_node::mark_as_dependent mark all st_select_lex struct from this to 'last' as dependent @@ -1135,7 +1169,6 @@ void st_select_lex_unit::exclude_level() NOTE 'last' should be reachable from this st_select_lex_node - */ void st_select_lex::mark_as_dependent(SELECT_LEX *last) diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 0166951ab9d..7545f525082 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -321,6 +321,7 @@ public: st_select_lex_unit* next_unit() { return (st_select_lex_unit*) next; } st_select_lex* return_after_parsing() { return return_to; } void exclude_level(); + void exclude_tree(); /* UNION methods */ int prepare(THD *thd, select_result *result, bool tables_and_fields_initied);