summaryrefslogtreecommitdiff
path: root/sql/mysql_priv.h
diff options
context:
space:
mode:
authorGleb Shchepa <gshchepa@mysql.com>2010-02-06 23:54:30 +0400
committerGleb Shchepa <gshchepa@mysql.com>2010-02-06 23:54:30 +0400
commit57e5f8487f011b5ec7395acd75759d9061439f1b (patch)
treebf8b15b6dfd85b7aed65d198e3d7eda5626b83d8 /sql/mysql_priv.h
parenta26ab94eb27827b3961464b97b50e63d98135c1e (diff)
downloadmariadb-git-57e5f8487f011b5ec7395acd75759d9061439f1b.tar.gz
Bug #45640: optimizer bug produces wrong results
Grouping by a subquery in a query with a distinct aggregate function lead to a wrong result (wrong and unordered grouping values). There are two related problems: 1) The query like this: SELECT (SELECT t1.a) aa, COUNT(DISTINCT b) c FROM t1 GROUP BY aa returned wrong result, because the outer reference "t1.a" in the subquery was substituted with the Item_ref item. The Item_ref item obtains data from the result_field object that refreshes once after the end of each group. This data is not applicable to filesort since filesort() doesn't care about groups (and doesn't update result_field objects with copy_fields() and so on). Also that data is not applicable to group separation algorithm: end_send_group() checks every record with test_if_group_changed() that evaluates Item_ref items, but it refreshes those Item_ref-s only after the end of group, that is a vicious circle and the grouped column values in the output are shifted. Fix: if a) we grouping by a subquery and b) that subquery has outer references to FROM list of the grouping query, then we substitute these outer references with Item_direct_ref like references under aggregate functions: Item_direct_ref obtains data directly from the current record. 2) The query with a non-trivial grouping expression like: SELECT (SELECT t1.a) aa, COUNT(DISTINCT b) c FROM t1 GROUP BY aa+0 also returned wrong result, since JOIN::exec() substitutes references to top-level aliases in SELECT list with Item_copy caching items. Item_copy items have same refreshing policy as Item_ref items, so the whole groping expression with Item_copy inside returns wrong result in filesort() and end_send_group(). Fix: include aliased items into GROUP BY item tree instead of Item_ref references to them.
Diffstat (limited to 'sql/mysql_priv.h')
-rw-r--r--sql/mysql_priv.h2
1 files changed, 1 insertions, 1 deletions
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index 34f29e7c458..1b775e658f1 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -1192,7 +1192,7 @@ int setup_group(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
List<Item> &fields, List<Item> &all_fields, ORDER *order,
bool *hidden_group_fields);
bool fix_inner_refs(THD *thd, List<Item> &all_fields, SELECT_LEX *select,
- Item **ref_pointer_array);
+ Item **ref_pointer_array, ORDER *group_list= NULL);
bool handle_select(THD *thd, LEX *lex, select_result *result,
ulong setup_tables_done_option);