Skip to content

Commit 504802f

Browse files
committed
MDEV-7846: postreview fix
1 parent 54b9981 commit 504802f

File tree

3 files changed

+26
-1
lines changed

3 files changed

+26
-1
lines changed

sql/item_cmpfunc.cc

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1442,6 +1442,12 @@ bool Item_in_optimizer::eval_not_null_tables(uchar *opt_arg)
14421442
bool Item_in_optimizer::fix_left(THD *thd, Item **ref)
14431443
{
14441444
DBUG_ENTER("Item_in_optimizer::fix_left");
1445+
/*
1446+
Here we will store pointer on place of main storage of left expression.
1447+
For usual IN (ALL/ANY) it is subquery left_expr.
1448+
For other cases (MAX/MIN optimization, non-transformed EXISTS (10.0))
1449+
it is args[0].
1450+
*/
14451451
Item **ref0= args;
14461452
if (args[1]->type() == Item::SUBSELECT_ITEM &&
14471453
((Item_subselect *)args[1])->is_in_predicate())
@@ -1455,12 +1461,17 @@ bool Item_in_optimizer::fix_left(THD *thd, Item **ref)
14551461
next execution we need to copy args[1]->left_expr again.
14561462
*/
14571463
ref0= &(((Item_in_subselect *)args[1])->left_expr);
1464+
args[0]= ((Item_in_subselect *)args[1])->left_expr;
14581465
}
14591466
if ((!(*ref0)->fixed && (*ref0)->fix_fields(thd, ref0)) ||
14601467
(!cache && !(cache= Item_cache::get_cache(*ref0))))
14611468
DBUG_RETURN(1);
1469+
/*
1470+
During fix_field() expression could be substituted.
1471+
So we copy changes before use
1472+
*/
14621473
if (args[0] != (*ref0))
1463-
current_thd->change_item_tree(args, (*ref0));
1474+
args[0]= (*ref0);
14641475
DBUG_PRINT("info", ("actual fix fields"));
14651476

14661477
cache->setup(args[0]);

sql/item_subselect.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -449,6 +449,11 @@ class Item_in_subselect :public Item_exists_subselect
449449
Item **having_item);
450450
public:
451451
Item *left_expr;
452+
/*
453+
Important for PS/SP: left_expr_orig is the item that left_expr originally
454+
pointed at. That item is allocated on the statement arena, while
455+
left_expr could later be changed to something on the execution arena.
456+
*/
452457
Item *left_expr_orig;
453458
/* Priority of this predicate in the convert-to-semi-join-nest process. */
454459
int sj_convert_priority;

sql/opt_subselect.cc

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1592,6 +1592,15 @@ static bool convert_subq_to_sj(JOIN *parent_join, Item_in_subselect *subq_pred)
15921592
if (subq_pred->left_expr->cols() == 1)
15931593
{
15941594
nested_join->sj_outer_expr_list.push_back(subq_pred->left_expr);
1595+
/*
1596+
Create Item_func_eq. Note that
1597+
1. this is done on the statement, not execution, arena
1598+
2. if it's a PS then this happens only once - on the first execution.
1599+
On following re-executions, the item will be fix_field-ed normally.
1600+
3. Thus it should be created as if it was fix_field'ed, in particular
1601+
all pointers to items in the execution arena should be protected
1602+
with thd->change_item_tree
1603+
*/
15951604
Item_func_eq *item_eq=
15961605
new Item_func_eq(subq_pred->left_expr_orig, subq_lex->ref_pointer_array[0]);
15971606
if (subq_pred->left_expr_orig != subq_pred->left_expr)

0 commit comments

Comments
 (0)