Commit 067d6fdf authored by igor@rurik.mysql.com's avatar igor@rurik.mysql.com

Fixed bug #18165.

Made [NOT]BETWEEN predicates SARGable in respect to the second and 
the third arguments.
parent 7c73d0b2
......@@ -860,3 +860,39 @@ a
13
15
drop table t1, t2;
CREATE TABLE t1 (
id int NOT NULL DEFAULT '0',
b int NOT NULL DEFAULT '0',
c int NOT NULL DEFAULT '0',
INDEX idx1(b,c), INDEX idx2(c));
INSERT INTO t1(id) VALUES (1), (2), (3), (4), (5), (6), (7), (8);
INSERT INTO t1(b,c) VALUES (3,4), (3,4);
SELECT * FROM t1 WHERE b<=3 AND 3<=c;
id b c
0 3 4
0 3 4
SELECT * FROM t1 WHERE 3 BETWEEN b AND c;
id b c
0 3 4
0 3 4
EXPLAIN SELECT * FROM t1 WHERE b<=3 AND 3<=c;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range idx1,idx2 idx2 4 NULL 3 Using where
EXPLAIN SELECT * FROM t1 WHERE 3 BETWEEN b AND c;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range idx1,idx2 idx2 4 NULL 3 Using where
SELECT * FROM t1 WHERE 0 < b OR 0 > c;
id b c
0 3 4
0 3 4
SELECT * FROM t1 WHERE 0 NOT BETWEEN b AND c;
id b c
0 3 4
0 3 4
EXPLAIN SELECT * FROM t1 WHERE 0 < b OR 0 > c;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index_merge idx1,idx2 idx1,idx2 4,4 NULL 4 Using sort_union(idx1,idx2); Using where
EXPLAIN SELECT * FROM t1 WHERE 0 NOT BETWEEN b AND c;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index_merge idx1,idx2 idx1,idx2 4,4 NULL 4 Using sort_union(idx1,idx2); Using where
DROP TABLE t1;
......@@ -680,4 +680,34 @@ prepare stmt1 from @a;
execute stmt1;
drop table t1, t2;
#
# Bug #18165: range access for BETWEEN with a constant for the first argument
#
CREATE TABLE t1 (
id int NOT NULL DEFAULT '0',
b int NOT NULL DEFAULT '0',
c int NOT NULL DEFAULT '0',
INDEX idx1(b,c), INDEX idx2(c));
INSERT INTO t1(id) VALUES (1), (2), (3), (4), (5), (6), (7), (8);
INSERT INTO t1(b,c) VALUES (3,4), (3,4);
SELECT * FROM t1 WHERE b<=3 AND 3<=c;
SELECT * FROM t1 WHERE 3 BETWEEN b AND c;
EXPLAIN SELECT * FROM t1 WHERE b<=3 AND 3<=c;
EXPLAIN SELECT * FROM t1 WHERE 3 BETWEEN b AND c;
SELECT * FROM t1 WHERE 0 < b OR 0 > c;
SELECT * FROM t1 WHERE 0 NOT BETWEEN b AND c;
EXPLAIN SELECT * FROM t1 WHERE 0 < b OR 0 > c;
EXPLAIN SELECT * FROM t1 WHERE 0 NOT BETWEEN b AND c;
DROP TABLE t1;
# End of 5.0 tests
This diff is collapsed.
......@@ -2796,11 +2796,12 @@ add_key_fields(KEY_FIELD **key_fields,uint *and_level,
break;
case Item_func::OPTIMIZE_KEY:
{
Item **values;
// BETWEEN, IN, NE
if (cond_func->key_item()->real_item()->type() == Item::FIELD_ITEM &&
!(cond_func->used_tables() & OUTER_REF_TABLE_BIT))
{
Item **values= cond_func->arguments()+1;
values= cond_func->arguments()+1;
if (cond_func->functype() == Item_func::NE_FUNC &&
cond_func->arguments()[1]->real_item()->type() == Item::FIELD_ITEM &&
!(cond_func->arguments()[0]->used_tables() & OUTER_REF_TABLE_BIT))
......@@ -2813,6 +2814,22 @@ add_key_fields(KEY_FIELD **key_fields,uint *and_level,
cond_func->argument_count()-1,
usable_tables);
}
if (cond_func->functype() == Item_func::BETWEEN)
{
values= cond_func->arguments();
for (uint i= 1 ; i < cond_func->argument_count() ; i++)
{
Item_field *field_item;
if (cond_func->arguments()[i]->real_item()->type() == Item::FIELD_ITEM
&&
!(cond_func->arguments()[i]->used_tables() & OUTER_REF_TABLE_BIT))
{
field_item= (Item_field *) (cond_func->arguments()[i]->real_item());
add_key_equal_fields(key_fields, *and_level, cond_func,
field_item, 0, values, 1, usable_tables);
}
}
}
break;
}
case Item_func::OPTIMIZE_OP:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment