Skip to content

Commit 82395df

Browse files
srmppnsomrak.mon
authored andcommitted
Bug#119198 fix bug optimizer reverse index scan give incorrect result
1 parent b79ac11 commit 82395df

File tree

3 files changed

+139
-2
lines changed

3 files changed

+139
-2
lines changed
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
#
2+
# Bug#119198 Reverse index range scan give incorrect result.
3+
#
4+
CREATE TABLE temp_table (
5+
id bigint unsigned NOT NULL AUTO_INCREMENT,
6+
col1 tinyint unsigned NOT NULL,
7+
col2 tinyint unsigned NOT NULL,
8+
PRIMARY KEY (id),
9+
KEY temp_table_idx01 (col1)
10+
) ENGINE=InnoDB;
11+
# 2. Insert Data
12+
INSERT INTO temp_table (id, col1, col2)
13+
VALUES (10, 1, 4);
14+
INSERT INTO temp_table (id, col1, col2)
15+
VALUES (20, 1, 4);
16+
# 3. Run Query
17+
SELECT * FROM temp_table;
18+
id col1 col2
19+
10 1 4
20+
20 1 4
21+
# Verify table should contain 2 records id#10, id#20 respectively
22+
#
23+
EXPLAIN
24+
SELECT * FROM temp_table
25+
WHERE col1 >= 1 AND col1 <= 1
26+
ORDER BY col1 DESC, id DESC
27+
LIMIT 1;
28+
id select_type table partitions type possible_keys key key_len ref rows filtered Extra
29+
1 SIMPLE temp_table NULL range temp_table_idx01 temp_table_idx01 1 NULL 2 100.00 Using index condition; Backward index scan
30+
# Query should use reverse index scan range
31+
#
32+
SELECT * FROM temp_table
33+
WHERE col1 >= 1 AND col1 <= 1
34+
ORDER BY col1 DESC, id DESC
35+
LIMIT 1;
36+
id col1 col2
37+
20 1 4
38+
# Query should return valid result with EQ_RANGE ordering by col1 desc limit 1 which is id#20
39+
#
40+
SELECT * FROM temp_table
41+
WHERE col1 >= 1 AND col1 <= 1
42+
ORDER BY col1 DESC, id DESC
43+
LIMIT 2;
44+
id col1 col2
45+
20 1 4
46+
10 1 4
47+
# Query should return valid result with EQ_RANGE ordering by col1 desc limit 2 which are id#20, id#10
48+
#
49+
SELECT * FROM temp_table
50+
WHERE col1 >= 0 AND col1 <= 5
51+
ORDER BY col1 DESC, id DESC
52+
LIMIT 1;
53+
id col1 col2
54+
20 1 4
55+
# Query should return valid result with EQ_RANGE ordering by col1 desc limit 1 which is id#20
56+
#
57+
SELECT * FROM temp_table
58+
WHERE col1 >= 0 AND col1 <= 5
59+
ORDER BY col1 DESC, id DESC
60+
LIMIT 2;
61+
id col1 col2
62+
20 1 4
63+
10 1 4
64+
# Query should return valid result with EQ_RANGE ordering by col1 desc limit 2 which are id#20, id#10
65+
#
66+
# 4. Clean up
67+
DROP TABLE temp_table;
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
--source include/have_debug_sync.inc
2+
3+
--echo #
4+
--echo # Bug#119198 Reverse index range scan give incorrect result.
5+
--echo #
6+
7+
CREATE TABLE temp_table (
8+
id bigint unsigned NOT NULL AUTO_INCREMENT,
9+
col1 tinyint unsigned NOT NULL,
10+
col2 tinyint unsigned NOT NULL,
11+
PRIMARY KEY (id),
12+
KEY temp_table_idx01 (col1)
13+
) ENGINE=InnoDB;
14+
15+
--echo # 2. Insert Data
16+
17+
INSERT INTO temp_table (id, col1, col2)
18+
VALUES (10, 1, 4);
19+
20+
INSERT INTO temp_table (id, col1, col2)
21+
VALUES (20, 1, 4);
22+
23+
--echo # 3. Run Query
24+
--disable_warnings
25+
SELECT * FROM temp_table;
26+
--echo # Verify table should contain 2 records id#10, id#20 respectively
27+
--echo #
28+
29+
30+
EXPLAIN
31+
SELECT * FROM temp_table
32+
WHERE col1 >= 1 AND col1 <= 1
33+
ORDER BY col1 DESC, id DESC
34+
LIMIT 1;
35+
--enable_warnings
36+
--echo # Query should use reverse index scan range
37+
--echo #
38+
39+
40+
SELECT * FROM temp_table
41+
WHERE col1 >= 1 AND col1 <= 1
42+
ORDER BY col1 DESC, id DESC
43+
LIMIT 1;
44+
--echo # Query should return valid result with EQ_RANGE ordering by col1 desc limit 1 which is id#20
45+
--echo #
46+
47+
SELECT * FROM temp_table
48+
WHERE col1 >= 1 AND col1 <= 1
49+
ORDER BY col1 DESC, id DESC
50+
LIMIT 2;
51+
--echo # Query should return valid result with EQ_RANGE ordering by col1 desc limit 2 which are id#20, id#10
52+
--echo #
53+
54+
SELECT * FROM temp_table
55+
WHERE col1 >= 0 AND col1 <= 5
56+
ORDER BY col1 DESC, id DESC
57+
LIMIT 1;
58+
--echo # Query should return valid result with EQ_RANGE ordering by col1 desc limit 1 which is id#20
59+
--echo #
60+
61+
SELECT * FROM temp_table
62+
WHERE col1 >= 0 AND col1 <= 5
63+
ORDER BY col1 DESC, id DESC
64+
LIMIT 2;
65+
--echo # Query should return valid result with EQ_RANGE ordering by col1 desc limit 2 which are id#20, id#10
66+
--echo #
67+
68+
--echo # 4. Clean up
69+
DROP TABLE temp_table;

sql/sql_optimizer.cc

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9906,8 +9906,9 @@ static bool make_join_query_block(JOIN *join, Item *cond) {
99069906
used_index(tab->range_scan()) != MAX_KEY) {
99079907
const uint ref_key = used_index(tab->range_scan());
99089908
bool skip_quick;
9909+
uint used_key_parts = 0;
99099910
read_direction = test_if_order_by_key(
9910-
&join->order, tab->table(), ref_key, nullptr, &skip_quick);
9911+
&join->order, tab->table(), ref_key, &used_key_parts, &skip_quick);
99119912
if (skip_quick) read_direction = 0;
99129913
/*
99139914
If the index provides order there is no need to recheck
@@ -9921,7 +9922,7 @@ static bool make_join_query_block(JOIN *join, Item *cond) {
99219922
if (read_direction == 1 ||
99229923
(read_direction == -1 &&
99239924
reverse_sort_possible(tab->range_scan()) &&
9924-
!make_reverse(get_used_key_parts(tab->range_scan()),
9925+
!make_reverse(std::max(used_key_parts, get_used_key_parts(tab->range_scan())),
99259926
tab->range_scan()))) {
99269927
recheck_reason = DONT_RECHECK;
99279928
}

0 commit comments

Comments
 (0)