Zhixuan Zhu wrote:
> Our custom storage engine does DML completely internally. I.e., we get the execution
> plan from thd->lex->select_lex.where in rnd_init() and take over from there.
> It’s been working well until recently we found a corner case that probably confused
> the Optimizer. The following DML statement has two conditions with one being the const
> condition:
>
> Delete from test where 4>2 and test.c1=1;
>
> When we call traverse_cond on the structure “thd->lex->select_lex.where
> (icp)”, we got nothing but an empty “AND” item. So the above where
> clause give us no conditions to push and of course we end up deleting all rows from the
> table ☹.
>
> (gdb) p icp
> $8 = (class Item_cond *) 0x8978ce0
> (gdb) p icp->func_name()
> $9 = 0x846df2e "and"
> (gdb) p icp->argument_list().elements
> $10 = 0
>
> We found the function that does the trick is in remove_eq_conds() in sql_select.cc.
> The following code removes the whole list:
>
> if (((Item_cond*) cond)->argument_list()->elements == 1)
> { // Remove list
> item= ((Item_cond*) cond)->argument_list()->head();
> ((Item_cond*) cond)->argument_list()->empty();
> return item;
> }
>
> When we comment out that part everything seems to work. SELECT works fine although
> its lex->select_lex.where has the same empty “AND” item,
> lex->select_lex.join has the entire complete condition list though. Is this an error or
> what is the trick behind that code?
>
You have to push the condition returned by remove_eq_conds, not the one
you have originally, or, you have to save the original condition as
Item_cond somewhere.
Regards,
Igor.
> Thanks,
> Zhixuan