Commit 8c57924a authored by aelkin@mysql.com's avatar aelkin@mysql.com

Bug#19136: Crashing log-bin and uninitialized user variables in a derived table

The reason of the bug is in that `get_var_with_binlog' performs missed
assingment of
the variables as side-effect. Doing that it eventually calls
`free_underlaid_joins' to pass as an argument `thd->lex->select_lex' of the lex
which belongs to the user query, not 
to one which is emulated i.e SET @var1:=NULL.


`get_var_with_binlog' is refined to supply a temporary lex to sql_set_variables's stack.
parent 57ff78b5
...@@ -105,5 +105,6 @@ slave-bin.000001 1370 User var 2 1370 @`a`=5 ...@@ -105,5 +105,6 @@ slave-bin.000001 1370 User var 2 1370 @`a`=5
slave-bin.000001 1412 Query 1 1412 use `test`; insert into t1 values (@a),(@a) slave-bin.000001 1412 Query 1 1412 use `test`; insert into t1 values (@a),(@a)
slave-bin.000001 1478 User var 2 1478 @`a`=NULL slave-bin.000001 1478 User var 2 1478 @`a`=NULL
slave-bin.000001 1503 Query 1 1503 use `test`; insert into t1 values (@a),(@a),(@a*5) slave-bin.000001 1503 Query 1 1503 use `test`; insert into t1 values (@a),(@a),(@a*5)
insert into t1 select * FROM (select @var1 union select @var2) AS t2;
drop table t1; drop table t1;
stop slave; stop slave;
...@@ -47,9 +47,15 @@ connection slave; ...@@ -47,9 +47,15 @@ connection slave;
sync_with_master; sync_with_master;
select * from t1; select * from t1;
show binlog events from 141; show binlog events from 141;
#
# BUG19136: Crashing log-bin and uninitialized user variables in a derived table
# just to check nothing bad happens anymore
connection master; connection master;
insert into t1 select * FROM (select @var1 union select @var2) AS t2;
drop table t1; drop table t1;
save_master_pos; save_master_pos;
connection slave; connection slave;
sync_with_master; sync_with_master;
stop slave; stop slave;
......
...@@ -2733,14 +2733,24 @@ int get_var_with_binlog(THD *thd, LEX_STRING &name, ...@@ -2733,14 +2733,24 @@ int get_var_with_binlog(THD *thd, LEX_STRING &name,
sql_set_variables(), we could instead manually call check() and update(); sql_set_variables(), we could instead manually call check() and update();
this would save memory and time; but calling sql_set_variables() makes this would save memory and time; but calling sql_set_variables() makes
one unique place to maintain (sql_set_variables()). one unique place to maintain (sql_set_variables()).
Manipulation with lex is necessary since free_underlaid_joins
is going to release memory belonging to the main query.
*/ */
List<set_var_base> tmp_var_list; List<set_var_base> tmp_var_list;
LEX *sav_lex= thd->lex, lex_tmp;
thd->lex= &lex_tmp;
lex_start(thd, NULL, 0);
tmp_var_list.push_back(new set_var_user(new Item_func_set_user_var(name, tmp_var_list.push_back(new set_var_user(new Item_func_set_user_var(name,
new Item_null()))); new Item_null())));
/* Create the variable */ /* Create the variable */
if (sql_set_variables(thd, &tmp_var_list)) if (sql_set_variables(thd, &tmp_var_list))
{
thd->lex= sav_lex;
goto err; goto err;
}
thd->lex= sav_lex;
if (!(var_entry= get_variable(&thd->user_vars, name, 0))) if (!(var_entry= get_variable(&thd->user_vars, name, 0)))
goto err; goto err;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment