diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index d745dd8ff73..f3196c55873 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -2507,6 +2507,23 @@ void Item_func_nullif::split_sum_func(THD *thd, Item **ref_pointer_array, } +bool Item_func_nullif::walk(Item_processor processor, + bool walk_subquery, uchar *arg) +{ + /* + No needs to iterate through args[2] when it's just a copy of args[0]. + See MDEV-9712 Performance degradation of nested NULLIF + */ + uint tmp_count= arg_count == 2 || args[0] == args[2] ? 2 : 3; + for (uint i= 0; i < tmp_count; i++) + { + if (args[i]->walk(processor, walk_subquery, arg)) + return true; + } + return (this->*processor)(arg); +} + + void Item_func_nullif::update_used_tables() { if (m_cache) @@ -2517,7 +2534,14 @@ void Item_func_nullif::update_used_tables() } else { - Item_func::update_used_tables(); + /* + MDEV-9712 Performance degradation of nested NULLIF + No needs to iterate through args[2] when it's just a copy of args[0]. + */ + DBUG_ASSERT(arg_count == 3); + used_tables_and_const_cache_init(); + used_tables_and_const_cache_update_and_join(args[0] == args[2] ? 2 : 3, + args); } } diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index 39f2cf5590d..2f66382941d 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -1026,6 +1026,7 @@ public: String *str_op(String *str); my_decimal *decimal_op(my_decimal *); void fix_length_and_dec(); + bool walk(Item_processor processor, bool walk_subquery, uchar *arg); uint decimal_precision() const { return args[2]->decimal_precision(); } const char *func_name() const { return "nullif"; } void print(String *str, enum_query_type query_type); @@ -1037,13 +1038,21 @@ public: Item* propagate_equal_fields(THD *thd, const Context &ctx, COND_EQUAL *cond) { Context cmpctx(ANY_SUBST, cmp.compare_type(), cmp.compare_collation()); + const Item *old0= args[0]; args[0]->propagate_equal_fields_and_change_item_tree(thd, cmpctx, cond, &args[0]); args[1]->propagate_equal_fields_and_change_item_tree(thd, cmpctx, cond, &args[1]); - args[2]->propagate_equal_fields_and_change_item_tree(thd, - Context_identity(), - cond, &args[2]); + /* + MDEV-9712 Performance degradation of nested NULLIF + ANY_SUBST is more relaxed than IDENTITY_SUBST. + If ANY_SUBST did not change args[0], + then we can skip propagation for args[2]. + */ + if (old0 != args[0]) + args[2]->propagate_equal_fields_and_change_item_tree(thd, + Context_identity(), + cond, &args[2]); return this; } };