Evgeny,
The patch looks OK. See few minor comments below.
Timour
> #At file:///work/bzr_trees/38195-bug-5.0-opt/
>
> 2611 Evgeny Potemkin 2008-08-06
> Bug#38195: Incorrect handling of aggregate functions when loose index scan is
> used causes server crash.
>
> When the loose index scan access method is used values of aggregated functions
> are precomputed by it. Aggregation of such functions shouldn't be performed
> in this case and functions should be treated as normal ones.
> The create_tmp_table function wasn't taking this into account and this led to
> a crash.
>
> Now the JOIN::exec and the create_tmp_table functions treat aggregate
> functions as normal ones when the loose index scan is used.
This comment implies that MIN/MAX functions were always treated as
aggregate with loose scan, which is not the case. What the fix is correcting
is a special case when the result of these functions is materialized in a
temp table.
> modified:
> mysql-test/r/group_min_max.result
> mysql-test/t/group_min_max.test
> sql/sql_select.cc
>
> per-file messages:
> mysql-test/r/group_min_max.result
> Added a test case for the bug#38195.
> mysql-test/t/group_min_max.test
> Added a test case for the bug#38195.
> sql/sql_select.cc
> Bug#38195: Incorrect handling of aggregate functions when loose index scan is
> used causes server crash.
> The JOIN::exec and the create_tmp_table functions treat aggregate
> functions as normal ones when the loose index scan is used.
> === modified file 'mysql-test/r/group_min_max.result'
> --- a/mysql-test/r/group_min_max.result 2007-11-20 14:07:24 +0000
> +++ b/mysql-test/r/group_min_max.result 2008-08-06 14:15:55 +0000
> @@ -2353,3 +2353,44 @@ a MIN(b) MAX(b) AVG(b)
> 2 1 3 2.0000
> 1 1 3 2.0000
> DROP TABLE t1;
> +create table t1 (a int, b int, primary key (a,b), key `index` (a,b)) engine=MyISAM;
> +insert into t1 (a,b) values (0,0),(0,1),(0,2),(0,3),(0,4),(0,5),(0,6),(0,7),
> +(0,8),(0,9),(0,10),(0,11),(0,12),(0,13);
> +insert into t1 (a,b) select a, max(b)+1 from t1 where a = 0 group by a;
> +select * from t1;
> +a b
> +0 0
> +0 1
> +0 2
> +0 3
> +0 4
> +0 5
> +0 6
> +0 7
> +0 8
> +0 9
> +0 10
> +0 11
> +0 12
> +0 13
> +0 14
> +insert into t1 (a,b) select a, max(b+1)+1 from t1 where a = 0 group by a;
> +select * from t1;
> +a b
> +0 0
> +0 1
> +0 2
> +0 3
> +0 4
> +0 5
> +0 6
> +0 7
> +0 8
> +0 9
> +0 10
> +0 11
> +0 12
> +0 13
> +0 14
> +0 16
> +drop table t1;
>
> === modified file 'mysql-test/t/group_min_max.test'
> --- a/mysql-test/t/group_min_max.test 2007-11-20 14:07:24 +0000
> +++ b/mysql-test/t/group_min_max.test 2008-08-06 14:15:55 +0000
> @@ -916,3 +916,16 @@ SELECT a, MIN(b), MAX(b), AVG(b) FROM t1
> SELECT a, MIN(b), MAX(b), AVG(b) FROM t1 GROUP BY a ORDER BY a DESC;
>
> DROP TABLE t1;
> +
> +#
> +# Bug#38195: Incorrect handling of aggregate functions when loose index scan is
> +# used causes server crash.
> +#
> +create table t1 (a int, b int, primary key (a,b), key `index` (a,b)) engine=MyISAM;
> +insert into t1 (a,b) values (0,0),(0,1),(0,2),(0,3),(0,4),(0,5),(0,6),(0,7),
> +(0,8),(0,9),(0,10),(0,11),(0,12),(0,13);
Please add EXPLAIN statements for the SELECT parts of both INSERT statements.
> +insert into t1 (a,b) select a, max(b)+1 from t1 where a = 0 group by a;
> +select * from t1;
> +insert into t1 (a,b) select a, max(b+1)+1 from t1 where a = 0 group by a;
> +select * from t1;
> +drop table t1;
>
> === modified file 'sql/sql_select.cc'
> --- a/sql/sql_select.cc 2008-07-26 20:44:07 +0000
> +++ b/sql/sql_select.cc 2008-08-06 14:15:55 +0000
> @@ -1724,7 +1724,8 @@ JOIN::exec()
> if (!items1)
> {
> items1= items0 + all_fields.elements;
> - if (sort_and_group || curr_tmp_table->group)
> + if (sort_and_group || curr_tmp_table->group ||
> + tmp_table_param.precomputed_group_by)
> {
> if (change_to_use_tmp_fields(thd, items1,
> tmp_fields_list1, tmp_all_fields1,
> @@ -9259,6 +9260,8 @@ create_tmp_table(THD *thd,TMP_TABLE_PARA
> MI_COLUMNDEF *recinfo;
> uint total_uneven_bit_length= 0;
> bool force_copy_fields= param->force_copy_fields;
> + /* Treat sum functions as normal ones when loose index scan is used. */
> + save_sum_fields|= param->precomputed_group_by;
> DBUG_ENTER("create_tmp_table");
> DBUG_PRINT("enter",("distinct: %d save_sum_fields: %d rows_limit: %lu group:
> %d",
> (int) distinct, (int) save_sum_fields,
>
>