mirror of
https://github.com/MariaDB/server.git
synced 2025-07-27 18:02:13 +03:00
MDEV-25969: Condition pushdown into derived table doesn't work if select list uses SP
Consider a query of the form: select ... from (select item2 as COL1) as T where COL1=123 Condition pushdown into derived table will try to push "COL1=123" condition down into table T. The process of pushdown involves "substituting" the item, that is, replacing Item_field("T.COL1") with its "producing item" item2. In order to use item2, one needs to clone it (call Item::build_clone). If the item is not cloneable (e.g. Item_func_sp is not), the pushdown process will fail and nothing at all will be pushed. Fixed by introducing transform_condition_or_part() which will try to apply the transformation for as many parts of condition as possible. The parts of condition that couldn't be transformed are dropped.
This commit is contained in:
@ -1192,6 +1192,68 @@ bool mysql_derived_reinit(THD *thd, LEX *lex, TABLE_LIST *derived)
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
@brief
|
||||
Given condition cond and transformer+argument, try transforming as many
|
||||
conjuncts as possible.
|
||||
|
||||
@detail
|
||||
The motivation of this function is to convert the condition that's being
|
||||
pushed into a WHERE clause with derived_field_transformer_for_where or
|
||||
with derived_grouping_field_transformer_for_where.
|
||||
The transformer may fail for some sub-condition, in this case we want to
|
||||
convert the most restrictive part of the condition that can be pushed.
|
||||
|
||||
This function only does it for top-level AND: conjuncts that could not be
|
||||
converted are dropped.
|
||||
|
||||
@return
|
||||
Converted condition, or NULL if nothing could be converted
|
||||
*/
|
||||
|
||||
static
|
||||
Item *transform_condition_or_part(THD *thd,
|
||||
Item *cond,
|
||||
Item_transformer transformer,
|
||||
uchar *arg)
|
||||
{
|
||||
if (cond->type() != Item::COND_ITEM ||
|
||||
((Item_cond*) cond)->functype() != Item_func::COND_AND_FUNC)
|
||||
{
|
||||
Item *new_item= cond->transform(thd, transformer, arg);
|
||||
// Indicate that the condition is not pushable
|
||||
if (!new_item)
|
||||
cond->clear_extraction_flag();
|
||||
return new_item;
|
||||
}
|
||||
|
||||
List_iterator<Item> li(*((Item_cond*) cond)->argument_list());
|
||||
Item *item;
|
||||
while ((item=li++))
|
||||
{
|
||||
Item *new_item= item->transform(thd, transformer, arg);
|
||||
if (!new_item)
|
||||
{
|
||||
// Indicate that the condition is not pushable
|
||||
item->clear_extraction_flag();
|
||||
li.remove();
|
||||
}
|
||||
else
|
||||
li.replace(new_item);
|
||||
}
|
||||
|
||||
switch (((Item_cond*) cond)->argument_list()->elements)
|
||||
{
|
||||
case 0:
|
||||
return NULL;
|
||||
case 1:
|
||||
return ((Item_cond*) cond)->argument_list()->head();
|
||||
default:
|
||||
return cond;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
@brief
|
||||
Extract the condition depended on derived table/view and pushed it there
|
||||
@ -1287,9 +1349,11 @@ bool pushdown_cond_for_derived(THD *thd, Item *cond, TABLE_LIST *derived)
|
||||
if (!sl->join->group_list && !sl->with_sum_func)
|
||||
{
|
||||
/* extracted_cond_copy is pushed into where of sl */
|
||||
extracted_cond_copy= extracted_cond_copy->transform(thd,
|
||||
&Item::derived_field_transformer_for_where,
|
||||
(uchar*) sl);
|
||||
extracted_cond_copy=
|
||||
transform_condition_or_part(thd,
|
||||
extracted_cond_copy,
|
||||
&Item::derived_field_transformer_for_where,
|
||||
(uchar*)sl);
|
||||
if (extracted_cond_copy)
|
||||
{
|
||||
extracted_cond_copy->walk(
|
||||
@ -1316,9 +1380,12 @@ bool pushdown_cond_for_derived(THD *thd, Item *cond, TABLE_LIST *derived)
|
||||
pushed into the where clause of sl to make them usable in the new context
|
||||
*/
|
||||
if (cond_over_grouping_fields)
|
||||
cond_over_grouping_fields= cond_over_grouping_fields->transform(thd,
|
||||
&Item::derived_grouping_field_transformer_for_where,
|
||||
(uchar*) sl);
|
||||
{
|
||||
cond_over_grouping_fields=
|
||||
transform_condition_or_part(thd, cond_over_grouping_fields,
|
||||
&Item::derived_grouping_field_transformer_for_where,
|
||||
(uchar*) sl);
|
||||
}
|
||||
|
||||
if (cond_over_grouping_fields)
|
||||
{
|
||||
|
Reference in New Issue
Block a user