diff --git a/mysql-test/suite/bugs/r/rpl_bug33029.result b/mysql-test/suite/bugs/r/rpl_bug33029.result new file mode 100644 index 00000000000..d11ae1cc0be --- /dev/null +++ b/mysql-test/suite/bugs/r/rpl_bug33029.result @@ -0,0 +1,15 @@ +stop slave; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +reset master; +reset slave; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +start slave; +create table `t1` (`id` int not null auto_increment primary key); +create trigger `trg` before insert on `t1` for each row begin end; +set @@global.debug="+d,simulate_bug33029"; +stop slave; +start slave; +insert into `t1` values (); +select * from t1; +id +1 diff --git a/mysql-test/suite/bugs/t/rpl_bug33029.test b/mysql-test/suite/bugs/t/rpl_bug33029.test new file mode 100644 index 00000000000..494cef42ce0 --- /dev/null +++ b/mysql-test/suite/bugs/t/rpl_bug33029.test @@ -0,0 +1,25 @@ +# +# Bug #36443 Server crashes when executing insert when insert trigger on table +# +# Emulating the former bug#33029 situation to see that there is no crash anymore. +# + + +source include/master-slave.inc; + +create table `t1` (`id` int not null auto_increment primary key); +create trigger `trg` before insert on `t1` for each row begin end; + +sync_slave_with_master; +set @@global.debug="+d,simulate_bug33029"; + +stop slave; +start slave; + +connection master; + +insert into `t1` values (); + +sync_slave_with_master; +select * from t1; + diff --git a/sql/slave.cc b/sql/slave.cc index dcc808625c0..a6d7758c8de 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -4136,6 +4136,7 @@ bool rpl_master_erroneous_autoinc(THD *thd) if (active_mi && active_mi->rli.sql_thd == thd) { Relay_log_info *rli= &active_mi->rli; + DBUG_EXECUTE_IF("simulate_bug33029", return TRUE;); return rpl_master_has_bug(rli, 33029, FALSE); } return FALSE; diff --git a/sql/sql_class.cc b/sql/sql_class.cc index afa9777e00a..b54aea94424 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -2882,8 +2882,8 @@ void THD::reset_sub_statement_state(Sub_statement_state *backup, */ if (rpl_master_erroneous_autoinc(this)) { - backup->auto_inc_intervals_forced= auto_inc_intervals_forced; - auto_inc_intervals_forced.empty(); + DBUG_ASSERT(backup->auto_inc_intervals_forced.nb_elements() == 0); + auto_inc_intervals_forced.swap(&backup->auto_inc_intervals_forced); } #endif @@ -2931,8 +2931,8 @@ void THD::restore_sub_statement_state(Sub_statement_state *backup) */ if (rpl_master_erroneous_autoinc(this)) { - auto_inc_intervals_forced= backup->auto_inc_intervals_forced; - backup->auto_inc_intervals_forced.empty(); + backup->auto_inc_intervals_forced.swap(&auto_inc_intervals_forced); + DBUG_ASSERT(backup->auto_inc_intervals_forced.nb_elements() == 0); } #endif diff --git a/sql/structs.h b/sql/structs.h index 809175fdde4..0a20eee0e9a 100644 --- a/sql/structs.h +++ b/sql/structs.h @@ -314,31 +314,22 @@ private: */ Discrete_interval *current; uint elements; // number of elements - - /* helper function for copy construct and assignment operator */ - void copy_(const Discrete_intervals_list& from) - { - for (Discrete_interval *i= from.head; i; i= i->next) - { - Discrete_interval j= *i; - append(&j); - } + void set_members(Discrete_interval *h, Discrete_interval *t, + Discrete_interval *c, uint el) + { + head= h; + tail= t; + current= c; + elements= el; } + void operator=(Discrete_intervals_list &); /* prevent use of these */ + Discrete_intervals_list(const Discrete_intervals_list &); + public: Discrete_intervals_list() : head(NULL), current(NULL), elements(0) {}; - Discrete_intervals_list(const Discrete_intervals_list& from) - { - copy_(from); - } - void operator=(const Discrete_intervals_list& from) - { - empty(); - copy_(from); - } void empty_no_free() { - head= current= NULL; - elements= 0; + set_members(NULL, NULL, NULL, 0); } void empty() { @@ -350,7 +341,24 @@ public: } empty_no_free(); } - + void copy_shallow(const Discrete_intervals_list * dli) + { + head= dli->get_head(); + tail= dli->get_tail(); + current= dli->get_current(); + elements= dli->nb_elements(); + } + void swap (Discrete_intervals_list * dli) + { + Discrete_interval *h, *t, *c; + uint el; + h= dli->get_head(); + t= dli->get_tail(); + c= dli->get_current(); + el= dli->nb_elements(); + dli->copy_shallow(this); + set_members(h, t, c, el); + } const Discrete_interval* get_next() { Discrete_interval *tmp= current; @@ -364,4 +372,7 @@ public: ulonglong minimum() const { return (head ? head->minimum() : 0); }; ulonglong maximum() const { return (head ? tail->maximum() : 0); }; uint nb_elements() const { return elements; } + Discrete_interval* get_head() const { return head; }; + Discrete_interval* get_tail() const { return tail; }; + Discrete_interval* get_current() const { return current; }; };