summaryrefslogtreecommitdiff
path: root/sql/sql_select.cc
diff options
context:
space:
mode:
authorJorgen Loland <jorgen.loland@sun.com>2009-10-14 10:46:50 +0200
committerJorgen Loland <jorgen.loland@sun.com>2009-10-14 10:46:50 +0200
commit6da93b223b4b929402b432f90b2585d38f2f1e5a (patch)
tree67e6d2d27354e1926e9f6de44eb1349e9586241a /sql/sql_select.cc
parentf9c6730258a9f5776608967fcc1f10183710c76f (diff)
downloadmariadb-git-6da93b223b4b929402b432f90b2585d38f2f1e5a.tar.gz
Bug#47280 - strange results from count(*) with order by multiple
columns without where/group Simple SELECT with implicit grouping used to return many rows if the query was ordered by the aggregated column in the SELECT list. This was incorrect because queries with implicit grouping should only return a single record. The problem was that when JOIN:exec() decided if execution needed to handle grouping, it was assumed that sum_func_count==0 meant that there were no aggregate functions in the query. This assumption was not correct in JOIN::exec() because the aggregate functions might have been optimized away during JOIN::optimize(). The reason why queries without ordering behaved correctly was that sum_func_count is only recalculated if the optimizer chooses to use temporary tables (which it does in the ordered case). Hence, non-ordered queries were correctly treated as grouped. The fix for this bug was to remove the assumption that sum_func_count==0 means that there is no need for grouping. This was done by introducing variable "bool implicit_grouping" in the JOIN object. mysql-test/r/func_group.result: Add test for BUG#47280 mysql-test/t/func_group.test: Add test for BUG#47280 sql/opt_sum.cc: Improve comment for opt_sum_query() sql/sql_class.h: Add comment for variables in TMP_TABLE_PARAM sql/sql_select.cc: Introduce and use variable implicit_grouping instead of (!group_list && sum_func_count) in places that need to test if grouping is required. Also added comments for: optimization of aggregate fields for implicitly grouped queries (JOIN::optimize) and choice of end_select method (JOIN::execute) sql/sql_select.h: Add variable implicit_grouping, which will be TRUE for queries that contain aggregate functions but no GROUP BY clause. Also added comment to sort_and_group variable.
Diffstat (limited to 'sql/sql_select.cc')
-rw-r--r--sql/sql_select.cc27
1 files changed, 22 insertions, 5 deletions
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 9dacb2c2ce4..02e52e0c518 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -644,8 +644,11 @@ JOIN::prepare(Item ***rref_pointer_array,
this->group= group_list != 0;
unit= unit_arg;
+ if (tmp_table_param.sum_func_count && !group_list)
+ implicit_grouping= TRUE;
+
#ifdef RESTRICTED_GROUP
- if (sum_func_count && !group_list && (func_count || field_count))
+ if (implicit_grouping)
{
my_message(ER_WRONG_SUM_SELECT,ER(ER_WRONG_SUM_SELECT),MYF(0));
goto err;
@@ -881,15 +884,23 @@ JOIN::optimize()
}
#endif
- /* Optimize count(*), min() and max() */
- if (tables_list && tmp_table_param.sum_func_count && ! group_list)
+ /*
+ Try to optimize count(*), min() and max() to const fields if
+ there is implicit grouping (aggregate functions but no
+ group_list). In this case, the result set shall only contain one
+ row.
+ */
+ if (tables_list && implicit_grouping)
{
int res;
/*
opt_sum_query() returns HA_ERR_KEY_NOT_FOUND if no rows match
to the WHERE conditions,
- or 1 if all items were resolved,
+ or 1 if all items were resolved (optimized away),
or 0, or an error number HA_ERR_...
+
+ If all items were resolved by opt_sum_query, there is no need to
+ open any tables.
*/
if ((res=opt_sum_query(select_lex->leaf_tables, all_fields, conds)))
{
@@ -2024,7 +2035,7 @@ JOIN::exec()
count_field_types(select_lex, &curr_join->tmp_table_param,
*curr_all_fields, 0);
- if (curr_join->group || curr_join->tmp_table_param.sum_func_count ||
+ if (curr_join->group || curr_join->implicit_grouping ||
(procedure && (procedure->flags & PROC_GROUP)))
{
if (make_group_fields(this, curr_join))
@@ -10811,6 +10822,12 @@ Next_select_func setup_end_select_func(JOIN *join)
}
else
{
+ /*
+ Choose method for presenting result to user. Use end_send_group
+ if the query requires grouping (has a GROUP BY clause and/or one or
+ more aggregate functions). Use end_send if the query should not
+ be grouped.
+ */
if ((join->sort_and_group ||
(join->procedure && join->procedure->flags & PROC_GROUP)) &&
!tmp_tbl->precomputed_group_by)