Skip to content

Commit b5f40f3

Browse files
author
Evgeny Potemkin
committed
Bug#50539: Wrong result when loose index scan is used for an aggregate
function with distinct. Loose index scan is used to find MIN/MAX values using appropriate index and thus allow to avoid grouping. For each found row it updates non-aggregated fields with values from row with found MIN/MAX value. Without loose index scan non-aggregated fields are copied by end_send_group function. With loose index scan there is no need in end_send_group and end_send is used instead. Non-aggregated fields still need to be copied and this was wrongly implemented in QUICK_GROUP_MIN_MAX_SELECT::get_next. WL#3220 added a case when loose index scan can be used with end_send_group to optimize calculation of aggregate functions with distinct. In this case the row found by QUICK_GROUP_MIN_MAX_SELECT::get_next might belong to a next group and copying it will produce wrong result. Update of non-aggregated fields is moved to the end_send function from QUICK_GROUP_MIN_MAX_SELECT::get_next.
1 parent 6bad457 commit b5f40f3

File tree

4 files changed

+50
-14
lines changed

4 files changed

+50
-14
lines changed

mysql-test/r/group_min_max.result

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2686,7 +2686,7 @@ a c COUNT(DISTINCT c, a, b)
26862686
1 1 1
26872687
1 1 1
26882688
1 1 1
2689-
2 1 1
2689+
1 1 1
26902690
2 1 1
26912691
2 1 1
26922692
2 1 1
@@ -2714,7 +2714,7 @@ id select_type table type possible_keys key key_len ref rows Extra
27142714
1 SIMPLE t2 range NULL a 10 NULL 9 Using index for group-by
27152715
SELECT a, COUNT(DISTINCT b), SUM(DISTINCT b) FROM t2 GROUP BY a;
27162716
a COUNT(DISTINCT b) SUM(DISTINCT b)
2717-
2 8 36
2717+
1 8 36
27182718
2 8 36
27192719
EXPLAIN SELECT COUNT(DISTINCT b), SUM(DISTINCT b) FROM t2 GROUP BY a;
27202720
id select_type table type possible_keys key key_len ref rows Extra
@@ -2761,7 +2761,7 @@ SELECT 42 * (a + c + COUNT(DISTINCT c, a, b)) FROM t2 GROUP BY a, b, c;
27612761
126
27622762
126
27632763
126
2764-
168
2764+
126
27652765
168
27662766
168
27672767
168
@@ -2779,3 +2779,24 @@ SELECT (SUM(DISTINCT a) + MAX(b)) FROM t2 GROUP BY a;
27792779
10
27802780
DROP TABLE t1,t2;
27812781
# end of WL#3220 tests
2782+
#
2783+
# Bug#50539: Wrong result when loose index scan is used for an aggregate
2784+
# function with distinct
2785+
#
2786+
CREATE TABLE t1 (
2787+
f1 int(11) NOT NULL DEFAULT '0',
2788+
f2 char(1) NOT NULL DEFAULT '',
2789+
PRIMARY KEY (f1,f2)
2790+
) ;
2791+
insert into t1 values(1,'A'),(1 , 'B'), (1, 'C'), (2, 'A'),
2792+
(3, 'A'), (3, 'B'), (3, 'C'), (3, 'D');
2793+
SELECT f1, COUNT(DISTINCT f2) FROM t1 GROUP BY f1;
2794+
f1 COUNT(DISTINCT f2)
2795+
1 3
2796+
2 1
2797+
3 4
2798+
explain SELECT f1, COUNT(DISTINCT f2) FROM t1 GROUP BY f1;
2799+
id select_type table type possible_keys key key_len ref rows Extra
2800+
1 SIMPLE t1 range NULL PRIMARY 5 NULL 9 Using index for group-by (scanning)
2801+
drop table t1;
2802+
# End of test#50539.

mysql-test/t/group_min_max.test

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1166,3 +1166,22 @@ SELECT (SUM(DISTINCT a) + MAX(b)) FROM t2 GROUP BY a;
11661166
DROP TABLE t1,t2;
11671167

11681168
--echo # end of WL#3220 tests
1169+
1170+
--echo #
1171+
--echo # Bug#50539: Wrong result when loose index scan is used for an aggregate
1172+
--echo # function with distinct
1173+
--echo #
1174+
CREATE TABLE t1 (
1175+
f1 int(11) NOT NULL DEFAULT '0',
1176+
f2 char(1) NOT NULL DEFAULT '',
1177+
PRIMARY KEY (f1,f2)
1178+
) ;
1179+
insert into t1 values(1,'A'),(1 , 'B'), (1, 'C'), (2, 'A'),
1180+
(3, 'A'), (3, 'B'), (3, 'C'), (3, 'D');
1181+
1182+
SELECT f1, COUNT(DISTINCT f2) FROM t1 GROUP BY f1;
1183+
explain SELECT f1, COUNT(DISTINCT f2) FROM t1 GROUP BY f1;
1184+
1185+
drop table t1;
1186+
--echo # End of test#50539.
1187+

sql/opt_range.cc

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10959,17 +10959,7 @@ int QUICK_GROUP_MIN_MAX_SELECT::get_next()
1095910959
} while ((result == HA_ERR_KEY_NOT_FOUND || result == HA_ERR_END_OF_FILE) &&
1096010960
is_last_prefix != 0);
1096110961

10962-
if (result == 0)
10963-
{
10964-
/*
10965-
Partially mimic the behavior of end_select_send. Copy the
10966-
field data from Item_field::field into Item_field::result_field
10967-
of each non-aggregated field (the group fields, and optionally
10968-
other fields in non-ANSI SQL mode).
10969-
*/
10970-
copy_fields(&join->tmp_table_param);
10971-
}
10972-
else if (result == HA_ERR_KEY_NOT_FOUND)
10962+
if (result == HA_ERR_KEY_NOT_FOUND)
1097310963
result= HA_ERR_END_OF_FILE;
1097410964

1097510965
DBUG_RETURN(result);

sql/sql_select.cc

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12255,6 +12255,12 @@ end_send(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
1225512255
if (!end_of_records)
1225612256
{
1225712257
int error;
12258+
if (join->tables &&
12259+
join->join_tab->is_using_loose_index_scan())
12260+
{
12261+
/* Copy non-aggregated fields when loose index scan is used. */
12262+
copy_fields(&join->tmp_table_param);
12263+
}
1225812264
if (join->having && join->having->val_int() == 0)
1225912265
DBUG_RETURN(NESTED_LOOP_OK); // Didn't match having
1226012266
error=0;

0 commit comments

Comments
 (0)