diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index 94075df57b4..15431c50b45 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -4012,3 +4012,26 @@ WHERE (SELECT COUNT(t0.b) FROM t1 t WHERE t.b>20) GROUP BY a; ERROR HY000: Invalid use of group function SET @@sql_mode=default; DROP TABLE t1; +CREATE TABLE t1 (a INT); +INSERT INTO t1 values (1),(1),(1),(1); +CREATE TABLE t2 (x INT); +INSERT INTO t1 values (1000),(1001),(1002); +SELECT SUM( (SELECT COUNT(a) FROM t2) ) FROM t1; +ERROR HY000: Invalid use of group function +SELECT SUM( (SELECT SUM(COUNT(a)) FROM t2) ) FROM t1; +ERROR HY000: Invalid use of group function +SELECT COUNT(1) FROM DUAL; +COUNT(1) +1 +SELECT SUM( (SELECT AVG( (SELECT t1.a FROM t2) ) FROM DUAL) ) FROM t1; +ERROR HY000: Invalid use of group function +SELECT +SUM( (SELECT AVG( (SELECT COUNT(*) FROM t1 t HAVING t1.a < 12) ) FROM t2) ) +FROM t1; +ERROR HY000: Invalid use of group function +SELECT t1.a as XXA, +SUM( (SELECT AVG( (SELECT COUNT(*) FROM t1 t HAVING XXA < 12) ) FROM t2) ) +FROM t1; +ERROR HY000: Invalid use of group function +DROP TABLE t1,t2; +End of 5.0 tests. diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test index 482b3e883e6..5cd2cd5fa7d 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -2845,3 +2845,33 @@ SELECT a FROM t1 t0 SET @@sql_mode=default; DROP TABLE t1; + +# +# Bug #27363: nested aggregates in outer, subquery / sum(select +# count(outer)) +# +CREATE TABLE t1 (a INT); INSERT INTO t1 values (1),(1),(1),(1); +CREATE TABLE t2 (x INT); INSERT INTO t1 values (1000),(1001),(1002); + +--error ER_INVALID_GROUP_FUNC_USE +SELECT SUM( (SELECT COUNT(a) FROM t2) ) FROM t1; +--error ER_INVALID_GROUP_FUNC_USE +SELECT SUM( (SELECT SUM(COUNT(a)) FROM t2) ) FROM t1; +SELECT COUNT(1) FROM DUAL; + +--error ER_INVALID_GROUP_FUNC_USE +SELECT SUM( (SELECT AVG( (SELECT t1.a FROM t2) ) FROM DUAL) ) FROM t1; + +--error ER_INVALID_GROUP_FUNC_USE +SELECT + SUM( (SELECT AVG( (SELECT COUNT(*) FROM t1 t HAVING t1.a < 12) ) FROM t2) ) +FROM t1; + +--error ER_INVALID_GROUP_FUNC_USE +SELECT t1.a as XXA, + SUM( (SELECT AVG( (SELECT COUNT(*) FROM t1 t HAVING XXA < 12) ) FROM t2) ) +FROM t1; + +DROP TABLE t1,t2; + +--echo End of 5.0 tests. diff --git a/sql/item.cc b/sql/item.cc index ed5bd67d096..5ee98c34d3f 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -3521,9 +3521,13 @@ Item_field::fix_outer_field(THD *thd, Field **from_field, Item **reference) select->inner_refs_list.push_back(rf); rf->in_sum_func= thd->lex->in_sum_func; } + /* + A reference is resolved to a nest level that's outer or the same as + the nest level of the enclosing set function : adjust the value of + max_arg_level for the function if it's needed. + */ if (thd->lex->in_sum_func && - thd->lex->in_sum_func->nest_level == - thd->lex->current_select->nest_level) + thd->lex->in_sum_func->nest_level >= select->nest_level) { Item::Type ref_type= (*reference)->type(); set_if_bigger(thd->lex->in_sum_func->max_arg_level, @@ -5174,6 +5178,16 @@ bool Item_ref::fix_fields(THD *thd, Item **reference) thd->change_item_tree(reference, fld); mark_as_dependent(thd, last_checked_context->select_lex, thd->lex->current_select, this, fld); + /* + A reference is resolved to a nest level that's outer or the same as + the nest level of the enclosing set function : adjust the value of + max_arg_level for the function if it's needed. + */ + if (thd->lex->in_sum_func && + thd->lex->in_sum_func->nest_level >= + last_checked_context->select_lex->nest_level) + set_if_bigger(thd->lex->in_sum_func->max_arg_level, + last_checked_context->select_lex->nest_level); return FALSE; } if (ref == 0) @@ -5187,6 +5201,16 @@ bool Item_ref::fix_fields(THD *thd, Item **reference) DBUG_ASSERT(*ref && (*ref)->fixed); mark_as_dependent(thd, last_checked_context->select_lex, context->select_lex, this, this); + /* + A reference is resolved to a nest level that's outer or the same as + the nest level of the enclosing set function : adjust the value of + max_arg_level for the function if it's needed. + */ + if (thd->lex->in_sum_func && + thd->lex->in_sum_func->nest_level >= + last_checked_context->select_lex->nest_level) + set_if_bigger(thd->lex->in_sum_func->max_arg_level, + last_checked_context->select_lex->nest_level); } } diff --git a/sql/item_sum.cc b/sql/item_sum.cc index 752cefa07d6..4579ecd48ae 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -175,13 +175,25 @@ bool Item_sum::check_sum_func(THD *thd, Item **ref) MYF(0)); return TRUE; } - if (in_sum_func && in_sum_func->nest_level == nest_level) + if (in_sum_func) { /* If the set function is nested adjust the value of max_sum_func_level for the nesting set function. + We take into account only enclosed set functions that are to be + aggregated on the same level or above of the nest level of + the enclosing set function. + But we must always pass up the max_sum_func_level because it is + the maximum nested level of all directly and indirectly enclosed + set functions. We must do that even for set functions that are + aggregated inside of their enclosing set function's nest level + because the enclosing function may contain another enclosing + function that is to be aggregated outside or on the same level + as its parent's nest level. */ - set_if_bigger(in_sum_func->max_sum_func_level, aggr_level); + if (in_sum_func->nest_level >= aggr_level) + set_if_bigger(in_sum_func->max_sum_func_level, aggr_level); + set_if_bigger(in_sum_func->max_sum_func_level, max_sum_func_level); } update_used_tables(); thd->lex->in_sum_func= in_sum_func;