Now if I put the same expression into WHERE:
it erroneously returns one row:
The expected result is to have the expression evaluate into the same result in the SELECT list and in WHERE.
The problem is that Item_func_nullif::const_item() returns true and its val_real() is called from eval_const_cond().
In fact, it has constant items in args and args:
but the returned value referenced by m_args0_copy is not a constant item:
The return argument should probably be stored in arg instead, so the standard Item_func methods can see it and update Used_tables_cache taking into account the return value (not only the compared values).