mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03:00
MDEV-5606: range optimizer: "x < y" is sargable, while "y > x" is not
Port to mariadb-1.0 the following fix from mysql-5.6: Revision ID: jorgen.loland@oracle.com-20120314131055-ml54x9deueqfsff4 BUG#13701206: WHERE A>=B DOES NOT GIVE SAME EXECUTION PLAN AS WHERE B<=A (RANGE OPTIMIZER) that fix didn't have a public testcase, so I created one.
This commit is contained in:
@ -7684,7 +7684,8 @@ static SEL_TREE *get_func_mm_tree(RANGE_OPT_PARAM *param, Item_func *cond_func,
|
||||
param PARAM from SQL_SELECT::test_quick_select
|
||||
cond_func item for the predicate
|
||||
field_item field in the predicate
|
||||
value constant in the predicate
|
||||
value constant in the predicate (or a field already read from
|
||||
a table in the case of dynamic range access)
|
||||
(for BETWEEN it contains the number of the field argument,
|
||||
for IN it's always 0)
|
||||
inv TRUE <> NOT cond_func is considered
|
||||
@ -7953,24 +7954,41 @@ static SEL_TREE *get_mm_tree(RANGE_OPT_PARAM *param,COND *cond)
|
||||
DBUG_RETURN(ftree);
|
||||
}
|
||||
default:
|
||||
|
||||
DBUG_ASSERT (!ftree);
|
||||
if (cond_func->arguments()[0]->real_item()->type() == Item::FIELD_ITEM)
|
||||
{
|
||||
field_item= (Item_field*) (cond_func->arguments()[0]->real_item());
|
||||
value= cond_func->arg_count > 1 ? cond_func->arguments()[1] : 0;
|
||||
value= cond_func->arg_count > 1 ? cond_func->arguments()[1] : NULL;
|
||||
if (value && value->is_expensive())
|
||||
DBUG_RETURN(0);
|
||||
ftree= get_full_func_mm_tree(param, cond_func, field_item, value, inv);
|
||||
}
|
||||
else if (cond_func->have_rev_func() &&
|
||||
cond_func->arguments()[1]->real_item()->type() ==
|
||||
Item::FIELD_ITEM)
|
||||
/*
|
||||
Even if get_full_func_mm_tree() was executed above and did not
|
||||
return a range predicate it may still be possible to create one
|
||||
by reversing the order of the operands. Note that this only
|
||||
applies to predicates where both operands are fields. Example: A
|
||||
query of the form
|
||||
|
||||
WHERE t1.a OP t2.b
|
||||
|
||||
In this case, arguments()[0] == t1.a and arguments()[1] == t2.b.
|
||||
When creating range predicates for t2, get_full_func_mm_tree()
|
||||
above will return NULL because 'field' belongs to t1 and only
|
||||
predicates that applies to t2 are of interest. In this case a
|
||||
call to get_full_func_mm_tree() with reversed operands (see
|
||||
below) may succeed.
|
||||
*/
|
||||
if (!ftree && cond_func->have_rev_func() &&
|
||||
cond_func->arguments()[1]->real_item()->type() == Item::FIELD_ITEM)
|
||||
{
|
||||
field_item= (Item_field*) (cond_func->arguments()[1]->real_item());
|
||||
value= cond_func->arguments()[0];
|
||||
if (value && value->is_expensive())
|
||||
DBUG_RETURN(0);
|
||||
ftree= get_full_func_mm_tree(param, cond_func, field_item, value, inv);
|
||||
}
|
||||
else
|
||||
DBUG_RETURN(0);
|
||||
if (value && value->is_expensive())
|
||||
DBUG_RETURN(0);
|
||||
|
||||
ftree= get_full_func_mm_tree(param, cond_func, field_item, value, inv);
|
||||
}
|
||||
|
||||
DBUG_RETURN(ftree);
|
||||
|
Reference in New Issue
Block a user