Commit c8cafde7 authored by unknown's avatar unknown

Fixed bug #18165.

Made [NOT]BETWEEN predicates SARGable in respect to the second and 
the third arguments.


mysql-test/r/range.result:
  Added a test case to bug #18165.
mysql-test/t/range.test:
  Added a test case to bug #18165.
sql/opt_range.cc:
  Fixed bug #18165.
  Made [NOT]BETWEEN predicates SARGable in respect to the second and 
  the third arguments.
  Put in a separate function called get_full_func_mm_tree the functionality
  that builds a conjunction of all SEL_TREEs for a simple predicate of the
  form (f op c), where f was a field and c was a constant, applying different
  equalities f=f' with f' being another field.
parent 85ac350c
...@@ -860,3 +860,39 @@ a ...@@ -860,3 +860,39 @@ a
13 13
15 15
drop table t1, t2; 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; ...@@ -680,4 +680,34 @@ prepare stmt1 from @a;
execute stmt1; execute stmt1;
drop table t1, t2; 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 # End of 5.0 tests
This diff is collapsed.
...@@ -2796,11 +2796,12 @@ add_key_fields(KEY_FIELD **key_fields,uint *and_level, ...@@ -2796,11 +2796,12 @@ add_key_fields(KEY_FIELD **key_fields,uint *and_level,
break; break;
case Item_func::OPTIMIZE_KEY: case Item_func::OPTIMIZE_KEY:
{ {
Item **values;
// BETWEEN, IN, NE // BETWEEN, IN, NE
if (cond_func->key_item()->real_item()->type() == Item::FIELD_ITEM && if (cond_func->key_item()->real_item()->type() == Item::FIELD_ITEM &&
!(cond_func->used_tables() & OUTER_REF_TABLE_BIT)) !(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 && if (cond_func->functype() == Item_func::NE_FUNC &&
cond_func->arguments()[1]->real_item()->type() == Item::FIELD_ITEM && cond_func->arguments()[1]->real_item()->type() == Item::FIELD_ITEM &&
!(cond_func->arguments()[0]->used_tables() & OUTER_REF_TABLE_BIT)) !(cond_func->arguments()[0]->used_tables() & OUTER_REF_TABLE_BIT))
...@@ -2813,6 +2814,22 @@ add_key_fields(KEY_FIELD **key_fields,uint *and_level, ...@@ -2813,6 +2814,22 @@ add_key_fields(KEY_FIELD **key_fields,uint *and_level,
cond_func->argument_count()-1, cond_func->argument_count()-1,
usable_tables); 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; break;
} }
case Item_func::OPTIMIZE_OP: 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