Commit 4236b120 authored by Yuchen Pei's avatar Yuchen Pei Committed by Sergei Petrunia

MDEV-22534: Decorrelation for IN: workaround for MDEV-31269

Skip the decorrelation of IN subquery if
- we are running in a prepared statement
- any of trivial correlation expressions uses an Item_ref-derived object.
parent f393ecea
......@@ -399,7 +399,7 @@ select
json_extract(trace, '$**.join_optimization.steps[*].transformation.to') as JS
from information_schema.OPTIMIZER_TRACE;
JS
["decorrelation", "materialization", "semijoin"]
["materialization", "semijoin"]
EXECUTE st2;
a b c
1 r r
......
......@@ -2354,6 +2354,8 @@ class Item :public Value_source,
If there is some, sets a bit for this key in the proper key map.
*/
virtual bool check_index_dependence(void *arg) { return 0; }
virtual bool uses_item_ref_processor(void *arg) { return false; }
/*============== End of Item processor list ======================*/
/*
......@@ -5801,6 +5803,10 @@ class Item_ref :public Item_ident
return 0;
return cleanup_processor(arg);
}
bool uses_item_ref_processor(void *arg) override
{
return true;
}
Item *field_transformer_for_having_pushdown(THD *thd, uchar *arg) override
{ return (*ref)->field_transformer_for_having_pushdown(thd, arg); }
Item *remove_item_direct_ref() override
......
......@@ -3096,17 +3096,6 @@ static bool find_inner_outer_equalities(Item **conds,
return TRUE;
}
/* Check whether item tree intersects with the free list */
static bool intersects_free_list(Item *item, THD *thd)
{
for (const Item *to_find= thd->free_list; to_find; to_find= to_find->next)
if (item->walk(&Item::find_item_processor, 1, (void *) to_find))
return true;
return false;
}
/*
Prepare exists2in / decorrelation transformation
......@@ -3134,15 +3123,17 @@ bool Item_exists_subselect::exists2in_prepare(
DBUG_ASSERT(eqs.elements() != 0);
/*
If we are in a ps/sp execution, check for and skip on
intersection with the temporary free list to avoid 2nd ps execution
segfault
A workaround to avoid 2nd ps execution segfault (MDEV-31269):
The transformation we're doing is permanent. Don't apply it if
the involved conditions use Item_ref-based items (which are not
permanent).
*/
if (!thd->stmt_arena->is_conventional())
if (!thd->stmt_arena->is_conventional() && substype()==IN_SUBS)
{
for (uint i= 0; i < (uint) eqs.elements(); i++)
{
if (intersects_free_list(*eqs.at(i).eq_ref, thd))
Item *item= *eqs.at(i).eq_ref;
if (item->walk(&Item::uses_item_ref_processor, TRUE, NULL))
DBUG_RETURN(TRUE);
}
}
......
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