From: Jorgen Loland Date: March 1 2012 12:58pm Subject: bzr push into mysql-trunk branch (jorgen.loland:3713 to 3714) Bug#12640437 List-Archive: http://lists.mysql.com/commits/143069 X-Bug: 12640437 Message-Id: <20120301125838.CF870777@atum21.no.oracle.com> MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit 3714 Jorgen Loland 2012-03-01 BUG#12640437 - USING SQL_BUFFER_RESULT RESULTS IN A DIFFERENT QUERY OUTPUT For all but simple grouped queries, temporary tables are used to resolve grouping. In these cases, the list of grouping fields is stored in the temporary table and grouping is resolved there (e.g. by adding a unique constraint on the involved fields). Because of this, grouping is already done when the rows are read from the temporary table. In the case where a group clause may be optimized away, grouping does not have to be resolved using a temporary table. However, if a temporary table is explicitly requested (e.g. because the SQL_BUFFER_RESULT hint is used, or the statement is INSERT...SELECT), a temporary table is used anyway. In this case, the temporary table is created with an empty group list (because the group clause was optimized away) and it will therefore not create groups. Since the temporary table does not take care of grouping, JOIN::group shall not be set to false in make_simple_join(). This was fixed in bug 12578908. However, there is an exception where make_simple_join() should set JOIN::group to false even if the query uses a temporary table that was explicitly requested but is not strictly needed. That exception is if the loose index scan access method (explain says "Using index for group-by") is used to read into the temporary table. With loose index scan, grouping is resolved by the access method. This is exactly what happens in this bug. @ mysql-test/r/group_by.result Add test for BUG#12640437 @ mysql-test/t/group_by.test Add test for BUG#12640437 modified: mysql-test/r/group_by.result mysql-test/t/group_by.test sql/sql_executor.cc 3713 brajmohan saxena 2012-03-01 [merge] auto-merge modified: mysql-test/include/print_greedy_search_count.inc mysql-test/r/greedy_search.result sql/mysqld.cc sql/sql_class.h sql/sql_parse.cc sql/sql_planner.cc === modified file 'mysql-test/r/group_by.result' --- a/mysql-test/r/group_by.result 2012-02-29 11:17:52 +0000 +++ b/mysql-test/r/group_by.result 2012-03-01 12:58:27 +0000 @@ -2605,3 +2605,31 @@ xyz 1 DROP TABLE t1; SET @@sql_mode = @old_sql_mode; +# +# BUG#12640437: USING SQL_BUFFER_RESULT RESULTS IN A +# DIFFERENT QUERY OUTPUT +# +CREATE TABLE t1 ( +a int, +b varchar(1), +KEY (b,a) +); +INSERT INTO t1 VALUES (1,NULL),(0,'a'); + +EXPLAIN SELECT SQL_BUFFER_RESULT MIN(a), b FROM t1 WHERE t1.b = 'a' GROUP BY b; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 range b b 9 NULL 2 Using where; Using index for group-by; Using temporary + +SELECT SQL_BUFFER_RESULT MIN(a), b FROM t1 WHERE t1.b = 'a' GROUP BY b; +MIN(a) b +0 a + +EXPLAIN SELECT MIN(a), b FROM t1 WHERE t1.b = 'a' GROUP BY b; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 range b b 9 NULL 2 Using where; Using index for group-by + +SELECT MIN(a), b FROM t1 WHERE t1.b = 'a' GROUP BY b; +MIN(a) b +0 a + +DROP TABLE t1; === modified file 'mysql-test/t/group_by.test' --- a/mysql-test/t/group_by.test 2012-02-29 11:17:52 +0000 +++ b/mysql-test/t/group_by.test 2012-03-01 12:58:27 +0000 @@ -1944,3 +1944,33 @@ select ifnull(a, 'xyz') from t1 group by DROP TABLE t1; SET @@sql_mode = @old_sql_mode; + +--echo # +--echo # BUG#12640437: USING SQL_BUFFER_RESULT RESULTS IN A +--echo # DIFFERENT QUERY OUTPUT +--echo # + +CREATE TABLE t1 ( + a int, + b varchar(1), + KEY (b,a) +); + +INSERT INTO t1 VALUES (1,NULL),(0,'a'); + +let $query= + SELECT SQL_BUFFER_RESULT MIN(a), b FROM t1 WHERE t1.b = 'a' GROUP BY b; + +--echo +--eval EXPLAIN $query +--echo +--eval $query + +let $query= SELECT MIN(a), b FROM t1 WHERE t1.b = 'a' GROUP BY b; +--echo +--eval EXPLAIN $query +--echo +--eval $query + +--echo +DROP TABLE t1; === modified file 'sql/sql_executor.cc' --- a/sql/sql_executor.cc 2012-02-29 11:17:52 +0000 +++ b/sql/sql_executor.cc 2012-03-01 12:58:27 +0000 @@ -1059,11 +1059,7 @@ JOIN::make_simple_join(JOIN *parent, TAB first_record= sort_and_group=0; send_records= (ha_rows) 0; - if (!group_optimized_away) - { - group= false; - } - else + if (group_optimized_away && !tmp_table_param.precomputed_group_by) { /* If grouping has been optimized away, a temporary table is @@ -1074,12 +1070,18 @@ JOIN::make_simple_join(JOIN *parent, TAB created without a grouping expression and JOIN::exec() will not perform the necessary grouping (by the use of end_send_group() or end_write_group()) if JOIN::group is set to false. + + There is one exception: if the loose index scan access method is + used to read into the temporary table, grouping and aggregate + functions are handled. */ // the temporary table was explicitly requested DBUG_ASSERT(test(select_options & OPTION_BUFFER_RESULT)); // the temporary table does not have a grouping expression DBUG_ASSERT(!temp_table->group); } + else + group= false; row_limit= unit->select_limit_cnt; do_send_rows= row_limit ? 1 : 0; No bundle (reason: useless for push emails).