summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrei Elkin <andrei.elkin@oracle.com>2012-07-05 14:37:48 +0300
committerAndrei Elkin <andrei.elkin@oracle.com>2012-07-05 14:37:48 +0300
commite3c8fb4a1cf2984cf1aa1fe31ba828de550f619c (patch)
treefafa0a0b0221db9c8d72bf7fcc51c3d92a103da4
parent91c8e79fcd98bb586f32b22f5d67fcd5ae08ae28 (diff)
downloadmariadb-git-e3c8fb4a1cf2984cf1aa1fe31ba828de550f619c.tar.gz
Bug#14275000
Fixes for BUG11761686 left a flaw that managed to slip away from testing. Only effective filtering branch was actually tested with a regression test added to rpl_filter_tables_not_exist. The reason of the failure is destuction of too early mem-root-allocated memory at the end of the deferred User-var's do_apply_event(). Fixed with bypassing free_root() in the deferred execution branch. Deallocation of created in do_apply_event() items is done by the base code through THD::cleanup_after_query() -> free_items() that the parent Query can't miss. sql/log_event.cc: Do not call free_root() in case the deferred User-var event. Necessary methods to the User-var class are added, do_apply_event() refined. sql/log_event.h: Necessary methods to avoid destoying mem-root-based memory at User-var applying are defined.
-rw-r--r--sql/log_event.cc16
-rw-r--r--sql/log_event.h11
2 files changed, 22 insertions, 5 deletions
diff --git a/sql/log_event.cc b/sql/log_event.cc
index a47b3680d82..1822951cccf 100644
--- a/sql/log_event.cc
+++ b/sql/log_event.cc
@@ -5640,6 +5640,9 @@ User_var_log_event::
User_var_log_event(const char* buf,
const Format_description_log_event* description_event)
:Log_event(buf, description_event)
+#ifndef MYSQL_CLIENT
+ , deferred(false)
+#endif
{
/* The Post-Header is empty. The Variable Data part begins immediately. */
buf+= description_event->common_header_len +
@@ -5848,7 +5851,10 @@ int User_var_log_event::do_apply_event(Relay_log_info const *rli)
CHARSET_INFO *charset;
if (rli->deferred_events_collecting)
+ {
+ set_deferred();
return rli->deferred_events->add(this);
+ }
if (!(charset= get_charset(charset_number, MYF(MY_WME))))
return 1;
@@ -5900,7 +5906,8 @@ int User_var_log_event::do_apply_event(Relay_log_info const *rli)
return 0;
}
}
- Item_func_set_user_var e(user_var_name, it);
+
+ Item_func_set_user_var *e= new Item_func_set_user_var(user_var_name, it);
/*
Item_func_set_user_var can't substitute something else on its place =>
0 can be passed as last argument (reference on item)
@@ -5909,7 +5916,7 @@ int User_var_log_event::do_apply_event(Relay_log_info const *rli)
crash the server, so if fix fields fails, we just return with an
error.
*/
- if (e.fix_fields(thd, 0))
+ if (e->fix_fields(thd, 0))
return 1;
/*
@@ -5917,8 +5924,9 @@ int User_var_log_event::do_apply_event(Relay_log_info const *rli)
a single record and with a single column. Thus, like
a column value, it could always have IMPLICIT derivation.
*/
- e.update_hash(val, val_len, type, charset, DERIVATION_IMPLICIT, 0);
- free_root(thd->mem_root,0);
+ e->update_hash(val, val_len, type, charset, DERIVATION_IMPLICIT, 0);
+ if (!is_deferred())
+ free_root(thd->mem_root,0);
return 0;
}
diff --git a/sql/log_event.h b/sql/log_event.h
index 39cd55f313e..e755b6a5a41 100644
--- a/sql/log_event.h
+++ b/sql/log_event.h
@@ -2483,11 +2483,13 @@ public:
uint charset_number;
bool is_null;
#ifndef MYSQL_CLIENT
+ bool deferred;
User_var_log_event(THD* thd_arg, char *name_arg, uint name_len_arg,
char *val_arg, ulong val_len_arg, Item_result type_arg,
uint charset_number_arg)
:Log_event(), name(name_arg), name_len(name_len_arg), val(val_arg),
- val_len(val_len_arg), type(type_arg), charset_number(charset_number_arg)
+ val_len(val_len_arg), type(type_arg), charset_number(charset_number_arg),
+ deferred(false)
{ is_null= !val; }
void pack_info(Protocol* protocol);
#else
@@ -2500,6 +2502,13 @@ public:
Log_event_type get_type_code() { return USER_VAR_EVENT;}
#ifndef MYSQL_CLIENT
bool write(IO_CACHE* file);
+ /*
+ Getter and setter for deferred User-event.
+ Returns true if the event is not applied directly
+ and which case the applier adjusts execution path.
+ */
+ bool is_deferred() { return deferred; }
+ void set_deferred() { deferred= val; }
#endif
bool is_valid() const { return 1; }