diff options
author | unknown <gkodinov/kgeorge@magare.gmz> | 2007-04-26 11:12:17 +0300 |
---|---|---|
committer | unknown <gkodinov/kgeorge@magare.gmz> | 2007-04-26 11:12:17 +0300 |
commit | e14fd2b6516ae54a16ebd4cb0a92702fd8d4a315 (patch) | |
tree | 798a9ba14582610866bd4b5a9003c9d6ced82566 /sql | |
parent | 4430048ee8084e0fcef144e64ab89b59f8e31a71 (diff) | |
download | mariadb-git-e14fd2b6516ae54a16ebd4cb0a92702fd8d4a315.tar.gz |
Bug #27363:
Validity checks for nested set functions
were not taking into account that the enclosed
set function may be on a nest level that is
lower than the nest level of the enclosing set
function.
Fixed by :
- propagating max_sum_func_level
up the enclosing set functions chain.
- updating the max_sum_func_level of the
enclosing set function when the enclosed set
function is aggregated above or on the same
nest level of as the level of the enclosing
set function.
- updating the max_arg_level of the enclosing
set function on a reference that refers to
an item above or on the same nest level
as the level of the enclosing set function.
- Treating both Item_field and Item_ref as possibly
referencing items from outer nest levels.
mysql-test/r/subselect.result:
Bug #27363: test cases
mysql-test/t/subselect.test:
Bug #27363: test cases
sql/item.cc:
Bug #27363:
Treat the reference as an outer reference for the
enclosing set function even if it's referencing
an item that is above the nest level of the
enclosing set function.
Consider both Item_field and Item_ref.
sql/item_sum.cc:
Bug #27363: Use the enclosed set function aggregation
level to mark the enclosing set function even
if it's aggregated on a level that is above the
nest level of the enclosing set function.
Pass max_sum_func_level up the accending branch of the
recursion because it must take into account each
directly or indirectly nested set function.
Diffstat (limited to 'sql')
-rw-r--r-- | sql/item.cc | 28 | ||||
-rw-r--r-- | sql/item_sum.cc | 16 |
2 files changed, 40 insertions, 4 deletions
diff --git a/sql/item.cc b/sql/item.cc index 8568a44c547..05067cf16dc 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -3538,9 +3538,13 @@ Item_field::fix_outer_field(THD *thd, Field **from_field, Item **reference) thd->restore_active_arena(arena, &backup); fixed_as_field= 1; } + /* + 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, @@ -5182,6 +5186,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) @@ -5195,6 +5209,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 359b4516c3c..ca8aa2f06e7 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; |