mirror of
https://github.com/MariaDB/server.git
synced 2025-07-30 16:24:05 +03:00
Bug #30788: Inconsistent retrieval of char/varchar
Index lookup does not always guarantee that we can simply remove the relevant conditions from the WHERE clause. Reasons can be e.g. conversion errors, partial indexes etc. The optimizer was removing these parts of the WHERE condition without any further checking. This leads to "false positives" when using indexes. Fixed by checking the index reference conditions (using WHERE) when using indexes with sub-queries.
This commit is contained in:
@ -217,6 +217,7 @@ static void select_describe(JOIN *join, bool need_tmp_table,bool need_order,
|
||||
bool distinct, const char *message=NullS);
|
||||
static Item *remove_additional_cond(Item* conds);
|
||||
static void add_group_and_distinct_keys(JOIN *join, JOIN_TAB *join_tab);
|
||||
static bool test_if_ref(Item_field *left_item,Item *right_item);
|
||||
|
||||
|
||||
/*
|
||||
@ -673,9 +674,6 @@ err:
|
||||
without "checking NULL", remove the predicates that were pushed down
|
||||
into the subquery.
|
||||
|
||||
We can remove the equalities that will be guaranteed to be true by the
|
||||
fact that subquery engine will be using index lookup.
|
||||
|
||||
If the subquery compares scalar values, we can remove the condition that
|
||||
was wrapped into trig_cond (it will be checked when needed by the subquery
|
||||
engine)
|
||||
@ -685,6 +683,12 @@ err:
|
||||
and non-NULL values, we'll do a full table scan and will rely on the
|
||||
equalities corresponding to non-NULL parts of left tuple to filter out
|
||||
non-matching records.
|
||||
|
||||
TODO: We can remove the equalities that will be guaranteed to be true by the
|
||||
fact that subquery engine will be using index lookup. This must be done only
|
||||
for cases where there are no conversion errors of significance, e.g. 257
|
||||
that is searched in a byte. But this requires homogenization of the return
|
||||
codes of all Field*::store() methods.
|
||||
*/
|
||||
|
||||
void JOIN::remove_subq_pushed_predicates(Item **where)
|
||||
@ -692,17 +696,13 @@ void JOIN::remove_subq_pushed_predicates(Item **where)
|
||||
if (conds->type() == Item::FUNC_ITEM &&
|
||||
((Item_func *)this->conds)->functype() == Item_func::EQ_FUNC &&
|
||||
((Item_func *)conds)->arguments()[0]->type() == Item::REF_ITEM &&
|
||||
((Item_func *)conds)->arguments()[1]->type() == Item::FIELD_ITEM)
|
||||
((Item_func *)conds)->arguments()[1]->type() == Item::FIELD_ITEM &&
|
||||
test_if_ref ((Item_field *)((Item_func *)conds)->arguments()[1],
|
||||
((Item_func *)conds)->arguments()[0]))
|
||||
{
|
||||
*where= 0;
|
||||
return;
|
||||
}
|
||||
if (conds->type() == Item::COND_ITEM &&
|
||||
((class Item_func *)this->conds)->functype() ==
|
||||
Item_func::COND_AND_FUNC)
|
||||
{
|
||||
*where= remove_additional_cond(conds);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1219,7 +1219,7 @@ JOIN::optimize()
|
||||
{
|
||||
if (!having)
|
||||
{
|
||||
Item *where= 0;
|
||||
Item *where= conds;
|
||||
if (join_tab[0].type == JT_EQ_REF &&
|
||||
join_tab[0].ref.items[0]->name == in_left_expr_name)
|
||||
{
|
||||
@ -11862,8 +11862,12 @@ static bool test_if_ref(Item_field *left_item,Item *right_item)
|
||||
Item *ref_item=part_of_refkey(field->table,field);
|
||||
if (ref_item && ref_item->eq(right_item,1))
|
||||
{
|
||||
right_item= right_item->real_item();
|
||||
if (right_item->type() == Item::FIELD_ITEM)
|
||||
return (field->eq_def(((Item_field *) right_item)->field));
|
||||
/* remove equalities injected by IN->EXISTS transformation */
|
||||
else if (right_item->type() == Item::CACHE_ITEM)
|
||||
return ((Item_cache *)right_item)->eq_def (field);
|
||||
if (right_item->const_item() && !(right_item->is_null()))
|
||||
{
|
||||
/*
|
||||
|
Reference in New Issue
Block a user