@@ -1442,9 +1442,25 @@ bool Item_in_optimizer::eval_not_null_tables(uchar *opt_arg)
14421442bool Item_in_optimizer::fix_left (THD *thd, Item **ref)
14431443{
14441444 DBUG_ENTER (" Item_in_optimizer::fix_left" );
1445- if ((!args[0 ]->fixed && args[0 ]->fix_fields (thd, args)) ||
1446- (!cache && !(cache= Item_cache::get_cache (args[0 ]))))
1445+ Item **ref0= args;
1446+ if (args[1 ]->type () == Item::SUBSELECT_ITEM &&
1447+ ((Item_subselect *)args[1 ])->is_in_predicate ())
1448+ {
1449+ /*
1450+ left_expr->fix_fields() may cause left_expr to be substituted for
1451+ another item. (e.g. an Item_field may be changed into Item_ref). This
1452+ transformation is undone at the end of statement execution (e.g. the
1453+ Item_ref is deleted). However, Item_in_optimizer::args[0] may keep
1454+ the pointer to the post-transformation item. Because of that, on the
1455+ next execution we need to copy args[1]->left_expr again.
1456+ */
1457+ ref0= &(((Item_in_subselect *)args[1 ])->left_expr );
1458+ args[0 ]= ref0[0 ];
1459+ }
1460+ if ((!args[0 ]->fixed && args[0 ]->fix_fields (thd, ref0)) ||
1461+ (!cache && !(cache= Item_cache::get_cache (ref0[0 ]))))
14471462 DBUG_RETURN (1 );
1463+ args[0 ]= ref0[0 ];
14481464 DBUG_PRINT (" info" , (" actual fix fields" ));
14491465
14501466 cache->setup (args[0 ]);
@@ -1500,17 +1516,27 @@ bool Item_in_optimizer::fix_left(THD *thd, Item **ref)
15001516bool Item_in_optimizer::fix_fields (THD *thd, Item **ref)
15011517{
15021518 DBUG_ASSERT (fixed == 0 );
1519+ Item_subselect *sub= 0 ;
1520+ uint col;
1521+
1522+ /*
1523+ MAX/MIN optimization can convert the subquery into
1524+ expr + Item_singlerow_subselect
1525+ */
1526+ if (args[1 ]->type () == Item::SUBSELECT_ITEM)
1527+ sub= (Item_subselect *)args[1 ];
1528+
15031529 if (fix_left (thd, ref))
15041530 return TRUE ;
15051531 if (args[0 ]->maybe_null )
15061532 maybe_null=1 ;
15071533
15081534 if (!args[1 ]->fixed && args[1 ]->fix_fields (thd, args+1 ))
15091535 return TRUE ;
1510- Item_in_subselect * sub= (Item_in_subselect *) args[1 ];
1511- if ( args[0 ]->cols () != sub-> engine -> cols ( ))
1536+ if (( sub && ((col= args[0 ]-> cols ()) != sub-> engine -> cols ())) ||
1537+ (!sub && ( args[1 ]->cols () != (col= 1 )) ))
15121538 {
1513- my_error (ER_OPERAND_COLUMNS, MYF (0 ), args[ 0 ]-> cols () );
1539+ my_error (ER_OPERAND_COLUMNS, MYF (0 ), col );
15141540 return TRUE ;
15151541 }
15161542 if (args[1 ]->maybe_null )
0 commit comments