Skip to content

Commit

Permalink
MDEV-11219 main.null fails in buldbot and outside with ps-protocol
Browse files Browse the repository at this point in the history
  • Loading branch information
Alexander Barkov committed Nov 3, 2016
1 parent 82780a7 commit f0d8a4d
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 2 deletions.
42 changes: 41 additions & 1 deletion sql/item_cmpfunc.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2553,7 +2553,7 @@ Item_func_nullif::fix_length_and_dec()
See also class Item_func_nullif declaration.
*/
if (arg_count == 2)
args[arg_count++]= args[0];
args[arg_count++]= m_arg0 ? m_arg0 : args[0];

THD *thd= current_thd;
/*
Expand Down Expand Up @@ -2704,7 +2704,47 @@ Item_func_nullif::fix_length_and_dec()
unsigned_flag= args[2]->unsigned_flag;
fix_char_length(args[2]->max_char_length());
maybe_null=1;
m_arg0= args[0];
setup_args_and_comparator(thd, &cmp);
/*
A special code for EXECUTE..PREPARE.
If args[0] did not change, then we don't remember it, as it can point
to a temporary Item object which will be destroyed between PREPARE
and EXECUTE. EXECUTE time fix_length_and_dec() will correctly set args[2]
from args[0] again.
If args[0] changed, then it can be Item_func_conv_charset() for the
original args[0], which was permanently installed during PREPARE time
into the item tree as a wrapper for args[0], using change_item_tree(), i.e.
NULLIF(latin1_field, 'a' COLLATE utf8_bin)
was "rewritten" to:
CASE WHEN CONVERT(latin1_field USING utf8) = 'a' COLLATE utf8_bin
THEN NULL
ELSE latin1_field
- m_args0 points to Item_field corresponding to latin1_field
- args[0] points to Item_func_conv_charset
- args[0]->args[0] is equal to m_args0
- args[1] points to Item_func_set_collation
- args[2] points is eqial to m_args0
In this case we remember and reuse m_arg0 during EXECUTE time as args[2].
QQ: How to make sure that m_args0 does not point
to something temporary which will be destoyed between PREPARE and EXECUTE.
The condition below should probably be more strict and somehow check that:
- change_item_tree() was called for the new args[0]
- m_args0 is referenced from inside args[0], e.g. as a function argument,
and therefore it is also something that won't be destroyed between
PREPARE and EXECUTE.
Any ideas?
*/
if (args[0] == m_arg0)
m_arg0= NULL;
}


Expand Down
4 changes: 3 additions & 1 deletion sql/item_cmpfunc.h
Original file line number Diff line number Diff line change
Expand Up @@ -1009,6 +1009,7 @@ class Item_func_nullif :public Item_func_hybrid_field_type
*/
Item_cache *m_cache;
int compare();
Item *m_arg0;
public:
/*
Here we pass three arguments to the parent constructor, as NULLIF
Expand All @@ -1020,7 +1021,8 @@ class Item_func_nullif :public Item_func_hybrid_field_type
*/
Item_func_nullif(THD *thd, Item *a, Item *b):
Item_func_hybrid_field_type(thd, a, b, a),
m_cache(NULL)
m_cache(NULL),
m_arg0(NULL)
{ arg_count--; }
void cleanup()
{
Expand Down

0 comments on commit f0d8a4d

Please sign in to comment.