Skip to content

Commit 55efe47

Browse files
MDEV-36118 Fix wrong result with MAX in loose index scan
Loose index scan currently only supports ASC key. When searching for the next MAX value, the search starts from the rightmost range and moves towards the left. If the key has "moved" as the result of a successful ha_index_read_map() call when handling a previous range, we check if the key is to the left of the current range, and if so, we can skip to the next range. The existing check on whether the loop has iterated at least once is not sufficient, as an unsuccessful ha_index_read_map() often (always?) does not "move" the key.
1 parent 652f33e commit 55efe47

File tree

3 files changed

+43
-4
lines changed

3 files changed

+43
-4
lines changed

mysql-test/main/group_min_max.result

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4349,3 +4349,15 @@ drop table t1;
43494349
#
43504350
# End of 10.6 tests
43514351
#
4352+
#
4353+
# MDEV-36118 Wrong result in loose index scan
4354+
#
4355+
CREATE TABLE t1 (a int, b int, KEY (a, b));
4356+
insert into t1 values (1, 3), (1, 1);
4357+
SELECT MAX(b) FROM t1 WHERE (b > 2 AND b < 4) OR (b = 5) GROUP BY a;
4358+
MAX(b)
4359+
3
4360+
drop table t1;
4361+
#
4362+
# End of 10.11 tests
4363+
#

mysql-test/main/group_min_max.test

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2007,3 +2007,29 @@ drop table t1;
20072007
--echo #
20082008
--echo # End of 10.6 tests
20092009
--echo #
2010+
2011+
--echo #
2012+
--echo # MDEV-36118 Wrong result in loose index scan
2013+
--echo #
2014+
2015+
CREATE TABLE t1 (a int, b int, KEY (a, b));
2016+
insert into t1 values (1, 3), (1, 1);
2017+
--source include/maybe_debug.inc
2018+
if ($have_debug) {
2019+
--disable_query_log
2020+
set @old_debug=@@debug;
2021+
set debug="+d,force_group_by";
2022+
--enable_query_log
2023+
}
2024+
SELECT MAX(b) FROM t1 WHERE (b > 2 AND b < 4) OR (b = 5) GROUP BY a;
2025+
if ($have_debug) {
2026+
--disable_query_log
2027+
set debug=@old_debug;
2028+
--enable_query_log
2029+
}
2030+
2031+
drop table t1;
2032+
2033+
--echo #
2034+
--echo # End of 10.11 tests
2035+
--echo #

sql/opt_range.cc

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16090,7 +16090,7 @@ int QUICK_GROUP_MIN_MAX_SELECT::next_max_in_range()
1609016090
ha_rkey_function find_flag;
1609116091
key_part_map keypart_map;
1609216092
QUICK_RANGE *cur_range;
16093-
int result;
16093+
int result= HA_ERR_KEY_NOT_FOUND;
1609416094

1609516095
DBUG_ASSERT(min_max_ranges.elements > 0);
1609616096

@@ -16099,10 +16099,11 @@ int QUICK_GROUP_MIN_MAX_SELECT::next_max_in_range()
1609916099
get_dynamic(&min_max_ranges, (uchar*)&cur_range, range_idx - 1);
1610016100

1610116101
/*
16102-
If the current value for the min/max argument is smaller than the left
16103-
boundary of cur_range, there is no need to check this range.
16102+
If the key has already been "moved" by a successful call to
16103+
ha_index_read_map, and the current value for the max argument
16104+
comes before the range, there is no need to check this range.
1610416105
*/
16105-
if (range_idx != min_max_ranges.elements &&
16106+
if (!result &&
1610616107
!(cur_range->flag & NO_MIN_RANGE) &&
1610716108
(key_cmp(min_max_arg_part, (const uchar*) cur_range->min_key,
1610816109
min_max_arg_len) == -1))

0 commit comments

Comments
 (0)