Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 67 additions & 0 deletions mysql-test/r/optimizer_reverse_index_range_scan_bug.result
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
#
# Bug#119198 Reverse index range scan give incorrect result.
#
CREATE TABLE temp_table (
id bigint unsigned NOT NULL AUTO_INCREMENT,
col1 tinyint unsigned NOT NULL,
col2 tinyint unsigned NOT NULL,
PRIMARY KEY (id),
KEY temp_table_idx01 (col1)
) ENGINE=InnoDB;
# 2. Insert Data
INSERT INTO temp_table (id, col1, col2)
VALUES (10, 1, 4);
INSERT INTO temp_table (id, col1, col2)
VALUES (20, 1, 4);
# 3. Run Query
SELECT * FROM temp_table;
id col1 col2
10 1 4
20 1 4
# Verify table should contain 2 records id#10, id#20 respectively
#
EXPLAIN
SELECT * FROM temp_table
WHERE col1 >= 1 AND col1 <= 1
ORDER BY col1 DESC, id DESC
LIMIT 1;
id select_type table partitions type possible_keys key key_len ref rows filtered Extra
1 SIMPLE temp_table NULL range temp_table_idx01 temp_table_idx01 1 NULL 2 100.00 Using index condition; Backward index scan
# Query should use reverse index scan range
#
SELECT * FROM temp_table
WHERE col1 >= 1 AND col1 <= 1
ORDER BY col1 DESC, id DESC
LIMIT 1;
id col1 col2
20 1 4
# Query should return valid result with EQ_RANGE ordering by col1 desc limit 1 which is id#20
#
SELECT * FROM temp_table
WHERE col1 >= 1 AND col1 <= 1
ORDER BY col1 DESC, id DESC
LIMIT 2;
id col1 col2
20 1 4
10 1 4
# Query should return valid result with EQ_RANGE ordering by col1 desc limit 2 which are id#20, id#10
#
SELECT * FROM temp_table
WHERE col1 >= 0 AND col1 <= 5
ORDER BY col1 DESC, id DESC
LIMIT 1;
id col1 col2
20 1 4
# Query should return valid result with EQ_RANGE ordering by col1 desc limit 1 which is id#20
#
SELECT * FROM temp_table
WHERE col1 >= 0 AND col1 <= 5
ORDER BY col1 DESC, id DESC
LIMIT 2;
id col1 col2
20 1 4
10 1 4
# Query should return valid result with EQ_RANGE ordering by col1 desc limit 2 which are id#20, id#10
#
# 4. Clean up
DROP TABLE temp_table;
69 changes: 69 additions & 0 deletions mysql-test/t/optimizer_reverse_index_range_scan_bug.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
--source include/have_debug_sync.inc

--echo #
--echo # Bug#119198 Reverse index range scan give incorrect result.
--echo #

CREATE TABLE temp_table (
id bigint unsigned NOT NULL AUTO_INCREMENT,
col1 tinyint unsigned NOT NULL,
col2 tinyint unsigned NOT NULL,
PRIMARY KEY (id),
KEY temp_table_idx01 (col1)
) ENGINE=InnoDB;

--echo # 2. Insert Data

INSERT INTO temp_table (id, col1, col2)
VALUES (10, 1, 4);

INSERT INTO temp_table (id, col1, col2)
VALUES (20, 1, 4);

--echo # 3. Run Query
--disable_warnings
SELECT * FROM temp_table;
--echo # Verify table should contain 2 records id#10, id#20 respectively
--echo #


EXPLAIN
SELECT * FROM temp_table
WHERE col1 >= 1 AND col1 <= 1
ORDER BY col1 DESC, id DESC
LIMIT 1;
--enable_warnings
--echo # Query should use reverse index scan range
--echo #


SELECT * FROM temp_table
WHERE col1 >= 1 AND col1 <= 1
ORDER BY col1 DESC, id DESC
LIMIT 1;
--echo # Query should return valid result with EQ_RANGE ordering by col1 desc limit 1 which is id#20
--echo #

SELECT * FROM temp_table
WHERE col1 >= 1 AND col1 <= 1
ORDER BY col1 DESC, id DESC
LIMIT 2;
--echo # Query should return valid result with EQ_RANGE ordering by col1 desc limit 2 which are id#20, id#10
--echo #

SELECT * FROM temp_table
WHERE col1 >= 0 AND col1 <= 5
ORDER BY col1 DESC, id DESC
LIMIT 1;
--echo # Query should return valid result with EQ_RANGE ordering by col1 desc limit 1 which is id#20
--echo #

SELECT * FROM temp_table
WHERE col1 >= 0 AND col1 <= 5
ORDER BY col1 DESC, id DESC
LIMIT 2;
--echo # Query should return valid result with EQ_RANGE ordering by col1 desc limit 2 which are id#20, id#10
--echo #

--echo # 4. Clean up
DROP TABLE temp_table;
5 changes: 3 additions & 2 deletions sql/sql_optimizer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -9906,8 +9906,9 @@ static bool make_join_query_block(JOIN *join, Item *cond) {
used_index(tab->range_scan()) != MAX_KEY) {
const uint ref_key = used_index(tab->range_scan());
bool skip_quick;
uint used_key_parts = 0;
read_direction = test_if_order_by_key(
&join->order, tab->table(), ref_key, nullptr, &skip_quick);
&join->order, tab->table(), ref_key, &used_key_parts, &skip_quick);
if (skip_quick) read_direction = 0;
/*
If the index provides order there is no need to recheck
Expand All @@ -9921,7 +9922,7 @@ static bool make_join_query_block(JOIN *join, Item *cond) {
if (read_direction == 1 ||
(read_direction == -1 &&
reverse_sort_possible(tab->range_scan()) &&
!make_reverse(get_used_key_parts(tab->range_scan()),
!make_reverse(std::max(used_key_parts, get_used_key_parts(tab->range_scan())),
tab->range_scan()))) {
recheck_reason = DONT_RECHECK;
}
Expand Down