summaryrefslogtreecommitdiff
path: root/sql/item_sum.cc
diff options
context:
space:
mode:
authorunknown <evgen@moonbone.local>2008-03-28 18:09:14 +0300
committerunknown <evgen@moonbone.local>2008-03-28 18:09:14 +0300
commitfbbb60ce2f35b93a21229d585b7a27d7c5c50adc (patch)
tree31732e6de3b8d61202db7baddd0a4627816a31ae /sql/item_sum.cc
parent9d0385d62bfb439855ec8de027776ef847f47369 (diff)
parent7c156537cc51c42ae58c61f6bb70a307b8216334 (diff)
downloadmariadb-git-fbbb60ce2f35b93a21229d585b7a27d7c5c50adc.tar.gz
Merge moonbone.local:/work/27219-5.0-opt-mysql
into moonbone.local:/work/27219-bug-5.1 sql/item_subselect.cc: Auto merged sql/item_sum.cc: Auto merged sql/item_sum.h: Auto merged sql/mysql_priv.h: Auto merged sql/sql_lex.cc: Auto merged sql/sql_select.cc: Auto merged mysql-test/r/group_by.result: SCCS merged mysql-test/t/group_by.test: SCCS merged sql/item.cc: SCCS merged sql/sql_lex.h: SCCS merged
Diffstat (limited to 'sql/item_sum.cc')
-rw-r--r--sql/item_sum.cc64
1 files changed, 64 insertions, 0 deletions
diff --git a/sql/item_sum.cc b/sql/item_sum.cc
index ce9e2ad906c..264b53c780a 100644
--- a/sql/item_sum.cc
+++ b/sql/item_sum.cc
@@ -68,6 +68,7 @@ bool Item_sum::init_sum_func_check(THD *thd)
aggr_sel= NULL;
max_arg_level= -1;
max_sum_func_level= -1;
+ outer_fields.empty();
return FALSE;
}
@@ -176,6 +177,7 @@ bool Item_sum::check_sum_func(THD *thd, Item **ref)
MYF(0));
return TRUE;
}
+
if (in_sum_func)
{
/*
@@ -196,6 +198,68 @@ bool Item_sum::check_sum_func(THD *thd, Item **ref)
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);
}
+
+ /*
+ Check that non-aggregated fields and sum functions aren't mixed in the
+ same select in the ONLY_FULL_GROUP_BY mode.
+ */
+ if (outer_fields.elements)
+ {
+ Item_field *field;
+ /*
+ Here we compare the nesting level of the select to which an outer field
+ belongs to with the aggregation level of the sum function. All fields in
+ the outer_fields list are checked.
+
+ If the nesting level is equal to the aggregation level then the field is
+ aggregated by this sum function.
+ If the nesting level is less than the aggregation level then the field
+ belongs to an outer select. In this case if there is an embedding sum
+ function add current field to functions outer_fields list. If there is
+ no embedding function then the current field treated as non aggregated
+ and the select it belongs to is marked accordingly.
+ If the nesting level is greater than the aggregation level then it means
+ that this field was added by an inner sum function.
+ Consider an example:
+
+ select avg ( <-- we are here, checking outer.f1
+ select (
+ select sum(outer.f1 + inner.f1) from inner
+ ) from outer)
+ from most_outer;
+
+ In this case we check that no aggregate functions are used in the
+ select the field belongs to. If there are some then an error is
+ raised.
+ */
+ List_iterator<Item_field> of(outer_fields);
+ while ((field= of++))
+ {
+ SELECT_LEX *sel= field->cached_table->select_lex;
+ if (sel->nest_level < aggr_level)
+ {
+ if (in_sum_func)
+ {
+ /*
+ Let upper function decide whether this field is a non
+ aggregated one.
+ */
+ in_sum_func->outer_fields.push_back(field);
+ }
+ else
+ sel->full_group_by_flag|= NON_AGG_FIELD_USED;
+ }
+ if (sel->nest_level > aggr_level &&
+ (sel->full_group_by_flag & SUM_FUNC_USED) &&
+ !sel->group_list.elements)
+ {
+ my_message(ER_MIX_OF_GROUP_FUNC_AND_FIELDS,
+ ER(ER_MIX_OF_GROUP_FUNC_AND_FIELDS), MYF(0));
+ return TRUE;
+ }
+ }
+ }
+ aggr_sel->full_group_by_flag|= SUM_FUNC_USED;
update_used_tables();
thd->lex->in_sum_func= in_sum_func;
return FALSE;