From 994c0f83083ceee30430f28b8f1ced9b71944dbb Mon Sep 17 00:00:00 2001 From: Gleb Shchepa Date: Sat, 6 Feb 2010 23:54:30 +0400 Subject: 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. mysql-test/r/group_by.result: Test case for bug #45640 mysql-test/t/group_by.test: Test case for bug #45640 sql/item.cc: Bug #45640: optimizer bug produces wrong results Item_field::fix_fields() has been modified to resolve aliases in GROUP BY item trees into aliased items instead of Item_ref items. sql/item.h: Bug #45640: optimizer bug produces wrong results - Item::find_item_processor() has been introduced. - Item_ref::walk() has been modified to apply processors to itself too (not only to referenced item). sql/mysql_priv.h: Bug #45640: optimizer bug produces wrong results fix_inner_refs() has been modified to accept group_list parameter. sql/sql_lex.cc: Bug #45640: optimizer bug produces wrong results Initialization of st_select_lex::group_fix_field has been added. sql/sql_lex.h: Bug #45640: optimizer bug produces wrong results The st_select_lex::group_fix_field field has been introduced to control alias resolution in Itef_fied::fix_fields. sql/sql_select.cc: Bug #45640: optimizer bug produces wrong results - The fix_inner_refs function has been modified to treat subquery outer references like outer fields under aggregate functions, if they are included in GROUP BY item tree. - The find_order_in_list function has been modified to fix Item_field alias fields included in the GROUP BY item trees in a special manner. --- sql/sql_lex.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'sql/sql_lex.h') diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 4e4794ef2cf..459878c03fc 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -647,6 +647,8 @@ public: bool braces; /* SELECT ... UNION (SELECT ... ) <- this braces */ /* TRUE when having fix field called in processing of this SELECT */ bool having_fix_field; + /* TRUE when GROUP BY fix field called in processing of this SELECT */ + bool group_fix_field; /* List of references to fields referenced from inner selects */ List inner_refs_list; /* Number of Item_sum-derived objects in this SELECT */ -- cgit v1.2.1 From 4775601012f81655643667d8635e46de120be7ae Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 28 Mar 2010 16:37:47 +0800 Subject: Bug #50095 Multi statement including CREATE EVENT causes rotten binlog entry The log event of 'CREATE EVENT' was being binlogged with garbage at the end of the query if 'CREATE EVENT' is followed by another SQL statement and they were executed as one command. for example: DELIMITER |; CREATE EVENT e1 ON EVERY DAY DO SELECT 1; SELECT 'a'; DELIMITER ;| When binlogging 'CREATE EVENT', we always create a new statement with definer and write it into the log event. The new statement is made from cpp_buf(preprocessed buffer). which is not a c string(end with '\0'), but it is copied as a c string. In this patch, cpp_buf is copied with its length. --- sql/sql_lex.h | 1 + 1 file changed, 1 insertion(+) (limited to 'sql/sql_lex.h') diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 459878c03fc..54eefa22a59 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -1729,6 +1729,7 @@ typedef struct st_lex : public Query_tables_list - CREATE TRIGGER (points to "TRIGGER"); - CREATE PROCEDURE (points to "PROCEDURE"); - CREATE FUNCTION (points to "FUNCTION" or "AGGREGATE"); + - CREATE EVENT (points to "EVENT") This pointer is required to add possibly omitted DEFINER-clause to the DDL-statement before dumping it to the binlog. -- cgit v1.2.1