Lars, hej.
Thanks for your notes!
> On Wed, Dec 05, 2007 at 01:08:06PM +0200, Andrei Elkin wrote:
>> > Thanks for a great patch. Some comments/questions:
>> >
>> > 1. Suggestion: Better use error message if wrong mode given instead
>> > of warning.
>>
>> okay, changed. That took me to discuss an issue with Monty who agreed
>> for me to add explanatory notes to set_var::update method.
>
> Thanks.
>
>> > 2. Error message:
>> >
>> > "Last_SQL_Error Error in Write_rows event: error during transaction
>> > execution on table test.t1_nodef. ; handler error (null); the event's
>> > master log and end_log_pos master-bin.000001 2674"
>> >
>> > 1) s/. ; h/. H/
>> > 2) s/null/<something better>/ (fix it somehow...)
>> > 3) s/; the event's master log and end_log_pos/. Event master position:/
>>
>> you must have been looking not to the latest patch. In the latest one
>> the lines are
>>
>> Last_SQL_Errno 1364
>> Last_SQL_Error Could not execute Write_rows event on table test.t1_nodef.
> Error: (handler error <unknown>). The event's master log and end_log_pos
> master-bin.000001 2944
>
> Please remove double-space.
>
> Please remove parenthesis to make the error message look more professional.
>
> Please fix suggestion 2.3 above.
That had been done in the patch committed along with my reply mail:
http://lists.mysql.com/commits/39306
>
>> Here, #define ER_NO_DEFAULT_FOR_FIELD 1364.
>>
>> However, your catch in that former version helped to identify a bug (!) - i
> reported as
>> Bug#32971 No user level error message from slave sql thread when
> ER_NO_DEFAULT_FOR_FIELD.
>>
>> After analysing it I found out unfinished
>> Bug #25597 Extraneous error message displayed for slave SQL thread
>> errors,
>> which was supposed to improve the reporting mechanism, so that mine might be
>> considered as its duplicate.
>> I started fixing mine (and thus bug#25597) right way, hoping yet
>> another patch is easly but got stumbled at some point.
>>
>> Wrt the lines above, I made a simple change in
>> slave_rows_error_report() that allows printing user-level explanatory
>> message if one is available.
>
> Ok, good.
>
>> > 3. For above error msg, is that the starting position of the event?
>> > I think it is the starting position one want...
>>
>> The error says that the stopped event is one that has such end_log_pos.
>> An event carries only its end_pos counter. Hence we have to use that number
>> which uniquely identifies the event in binlog/relaylog.
>
> Ok. Then it is ok to write "Master event end position:
> 'master-bin.0000001 2944'".
>
>> > 4. Why is this construct needed?
>> >
>> > +set @save_binlog_format= @@session.binlog_format;
>> > +set @@session.binlog_format= mixed;
>> > DROP DATABASE mysqltest1;
>> > +set @@session.binlog_format= @save_binlog_format;
>>
>> That's a good question!
>>
>> I forced the statement format in this test because the row format
>> events cause stopping slave due to inconsistency of data - which is
>> part of the test's logics. That was not the case at time of the
>> idemptent default when consistency was out of interest :)
>
> DROP DATABASE must, of course, work in any format. The test should
> not be changed without a good reason.
I was saying that there is the test's specific logics that changes the
slave side unilaterly. After my changes taking the test as it is
causes row-based replication to stop at with error due to
inconsistency. Previously, at time of the idempotent default reign,
that fact was not discovered as the error was ignored.
>
>> It's worth to analyze why REVOKE or DML operations on a table from
>> mysql database are replicated in row-based format.
>> Have not we decided to have only the statement format for mysql db
>> modifications?
>
> Check with Mats.
>
>> > 5. Below seems wrong, why is no error code returned?
>> >
>> > "Error: (handler error <unknown>)."
>>
>> The error must be followed with an explanation (p.2). Nevertheless the
>> handler error can be unknown.
>
> I think an error code should always be expected from the handler, if
> it is handler that indicate failure. Mats?
>
Mats, thanks for confirming that.
>> > 6. I think the best would be to remove the bit macros and replace them
>> > with real functions.
>>
>> There is no objective reason to remove them. They are correct - thanks
>> to Mats' improvement, reliable (look at using compile time assert)
>> and catch their mice perfectly.
>> Besides, converting them into functions kills the idea not to mess
>> with types - any interger type suffies - and still being safe
>> (the out-of-range error plus the compile time assert).
>> After all, the macros are just shortcuts of operations basing on
>> the only << shift.
>> There are similar macros which you might dislike not less.
>> Under my all deepest respect to the object oriented programming I'd
>> never be trying to make classes out of them either :)
>> I hope you will let me generoulsy to stay with them as Mats did.
>
> It is no need to make them general since they are only used in two
> places. And type checking is nice. But, I'm ok with leaving this.
Actually, as discussed with Mats, there are lots of places
when the macros can be deployed. Please check our mail thread.
>
>> With regard to the returning values I think I explained that. Three macros
>> return each 3 values in internally constistent nanner. As there is a
>> macro among them that checks a bit values, and 0 or 1 are obviously
>> both correct results, then for an error case we have to choose something
>> else. A natural choice is -1.
>
> It is not standard,
I doubt there is a standard for the case we are having: the fact of
the matter is a routine returns three values.
> but ok, lets leave it.
thanks.
>
> Best wishes,
> Lars
cheers,
Andrei
>
>
>> > Best wishes,
>> > Lars
>> >
>> >
>> >
>> > On Fri, Nov 30, 2007 at 01:49:43PM +0200, Andrei Elkin wrote:
>> >> Below is the list of changes that have just been committed into a local
>> >> 5.1 repository of elkin. When elkin does a push these changes will
>> >> be propagated to the main repository and, within 24 hours after the
>> >> push, to the public repository.
>> >> For information on how to access the public repository
>> >> see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html
>> >>
>> >> ChangeSet@stripped, 2007-11-30 13:49:33+02:00, aelkin@stripped +35
> -0
>> >> Bug#31552 Replication breaks when deleting rows from out-of-sync
> table
>> >> without PK
>> >> Bug#31609 Not all RBR slave errors reported as errors
>> >> bug#32468 delete rows event on a table with foreign key constraint
> fails
>> >>
>> >> The first two bugs comprise idemptency issues.
>> >> First, there was no error code reported under conditions of the bug
>> >> description although the slave sql thread halted.
>> >> Second, executions were different with and without presence of prim
> key in
>> >> the table.
>> >> Third, there was no way to instruct the slave whether to ignore an
> error
>> >> and skip to the following event or to halt.
>> >> Fourth, there are handler errors which might happen due to idempotant
>> >> applying of binlog but those were not listed among the "idempotent"
> error
>> >> list.
>> >>
>> >> All the named issues are addressed.
>> >> Wrt to the 3rd, there is the new global system variable, changeble at
> run
>> >> time, which controls the slave sql thread behaviour.
>> >> The new variable allows further extensions to mimic the sql_mode
>> >> session/global variable.
>> >> To address the 4th, the new bug#32468 had to be fixed as it was
> staying
>> >> in the way.
>> >>
>> >> include/my_bitmap.h@stripped, 2007-11-30 13:49:21+02:00,
> aelkin@stripped +16 -0
>> >> basic operations with bits of an integer type are added.
>> >>
>> >> mysql-test/extra/rpl_tests/rpl_foreign_key.test@stripped, 2007-11-30
> 13:49:21+02:00, aelkin@stripped +31 -0
>> >> regression test for bug#32468
>> >>
>> >> mysql-test/extra/rpl_tests/rpl_row_basic.test@stripped, 2007-11-30
> 13:49:21+02:00, aelkin@stripped +10 -0
>> >> changes due to bug#31552/31609 idemptency is not default any longer
>> >>
>> >> mysql-test/extra/rpl_tests/rpl_row_tabledefs.test@stripped, 2007-11-30
> 13:49:21+02:00, aelkin@stripped +6 -0
>> >> changes due to bug#31552/31609 idemptency is not default any longer
>> >>
>> >> mysql-test/suite/rpl/r/rpl_foreign_key_innodb.result@stripped, 2007-11-30
> 13:49:21+02:00, aelkin@stripped +13 -0
>> >> results changed
>> >>
>> >> mysql-test/suite/rpl/r/rpl_idempotency.result@stripped, 2007-11-30
> 13:49:22+02:00, aelkin@stripped +159 -0
>> >> results changed
>> >>
>> >> mysql-test/suite/rpl/r/rpl_ignore_table.result@stripped, 2007-11-30
> 13:49:22+02:00, aelkin@stripped +4 -0
>> >> results changed
>> >>
>> >> mysql-test/suite/rpl/r/rpl_row_USER.result@stripped, 2007-11-30
> 13:49:22+02:00, aelkin@stripped +3 -0
>> >> results changed
>> >>
>> >> mysql-test/suite/rpl/r/rpl_row_basic_11bugs.result@stripped, 2007-11-30
> 13:49:22+02:00, aelkin@stripped +2 -0
>> >> results changed
>> >>
>> >> mysql-test/suite/rpl/r/rpl_row_basic_2myisam.result@stripped, 2007-11-30
> 13:49:22+02:00, aelkin@stripped +4 -0
>> >> results changed
>> >>
>> >> mysql-test/suite/rpl/r/rpl_row_basic_3innodb.result@stripped, 2007-11-30
> 13:49:22+02:00, aelkin@stripped +4 -0
>> >> results changed
>> >>
>> >> mysql-test/suite/rpl/r/rpl_row_mystery22.result@stripped, 2007-11-30
> 13:49:23+02:00, aelkin@stripped +2 -0
>> >> results changed
>> >>
>> >> mysql-test/suite/rpl/r/rpl_row_tabledefs_2myisam.result@stripped,
> 2007-11-30 13:49:23+02:00, aelkin@stripped +4 -2
>> >> results changed
>> >>
>> >> mysql-test/suite/rpl/r/rpl_row_tabledefs_3innodb.result@stripped,
> 2007-11-30 13:49:23+02:00, aelkin@stripped +4 -2
>> >> results changed
>> >>
>> >> mysql-test/suite/rpl/r/rpl_temporary_errors.result@stripped, 2007-11-30
> 13:49:23+02:00, aelkin@stripped +2 -0
>> >> results changed
>> >>
>> >> mysql-test/suite/rpl/t/rpl_idempotency-master.opt@stripped, 2007-11-30
> 13:49:28+02:00, aelkin@stripped +2 -0
>> >> innodb is necessary
>> >>
>> >> mysql-test/suite/rpl/t/rpl_idempotency-master.opt@stripped, 2007-11-30
> 13:49:28+02:00, aelkin@stripped +0 -0
>> >>
>> >> mysql-test/suite/rpl/t/rpl_idempotency-slave.opt@stripped, 2007-11-30
> 13:49:28+02:00, aelkin@stripped +2 -0
>> >> innodb is necessary, as well as the tests start with non-default
>> >> IDEMPOTENT slave execution mode.
>> >>
>> >>
>> >> mysql-test/suite/rpl/t/rpl_idempotency-slave.opt@stripped, 2007-11-30
> 13:49:28+02:00, aelkin@stripped +0 -0
>> >>
>> >> mysql-test/suite/rpl/t/rpl_idempotency.test@stripped, 2007-11-30
> 13:49:24+02:00, aelkin@stripped +329 -0
>> >> extenstions to the test providing testing of complements to the
>> >> idempotent error set and checking how slave halts when it faces an
> error
>> >> from the list when the mode is STRICT.
>> >>
>> >> mysql-test/suite/rpl/t/rpl_ignore_table.test@stripped, 2007-11-30
> 13:49:24+02:00, aelkin@stripped +8 -0
>> >> changes due to bug#31552/31609 idemptency is not default any
> longer.
>> >> The fix ensures no row-based events should happen due to DROP
> database.
>> >>
>> >> mysql-test/suite/rpl/t/rpl_row_USER.test@stripped, 2007-11-30
> 13:49:24+02:00, aelkin@stripped +4 -0
>> >> changes due to bug#31552/31609 idemptency is not default any
> longer.
>> >> The fix ensures no row-based events should happen due to DROP
> database.
>> >>
>> >> mysql-test/suite/rpl/t/rpl_row_basic_11bugs.test@stripped, 2007-11-30
> 13:49:24+02:00, aelkin@stripped +3 -0
>> >> changes due to bug#31552/31609 idemptency is not default any
> longer.
>> >>
>> >> mysql-test/suite/rpl/t/rpl_row_mystery22.test@stripped, 2007-11-30
> 13:49:24+02:00, aelkin@stripped +5 -0
>> >> changes due to bug#31552/31609 idemptency is not default any longer
>> >>
>> >> mysql-test/suite/rpl/t/rpl_temporary_errors.test@stripped, 2007-11-30
> 13:49:24+02:00, aelkin@stripped +3 -0
>> >> changes due to bug#31552/31609 idemptency is not default any longer
>> >>
>> >> mysql-test/suite/rpl_ndb/r/rpl_ndb_dd_advance.result@stripped, 2007-11-30
> 13:49:25+02:00, aelkin@stripped +1 -0
>> >> results changed
>> >>
>> >> mysql-test/suite/rpl_ndb/r/rpl_row_basic_7ndb.result@stripped, 2007-11-30
> 13:49:25+02:00, aelkin@stripped +4 -0
>> >> results changed
>> >>
>> >> mysql-test/suite/rpl_ndb/t/rpl_ndb_dd_advance.test@stripped, 2007-11-30
> 13:49:25+02:00, aelkin@stripped +3 -0
>> >> changes due to bug#31552/31609 idemptency is not default any longer
>> >>
>> >> sql/log_event.cc@stripped, 2007-11-30 13:49:25+02:00,
> aelkin@stripped +145 -91
>> >> the fix for bug#32468 delete rows event on a table with foreign key
> constraint fails
>> >> ensures the flags are set at proper time so that their values will
> be caught
>> >> by innodb.
>> >> reseting the flags is done along the common error and errorless
> execution
>> >> path.
>> >> The list of idempotent error is extended with foreign keys related
> items.
>> >> NDB engine write events are designed with the replace sematics in
> mind.
>> >> Therefore the corrsponding ndb handler's flag are (re)set regardless
> of
>> >> the slave's execution mode.
>> >> Rows_log_event::write_row() starts using the bool replace argument
> as its
>> >> caller sets it depending on the event's execution mode.
>> >>
>> >> sql/log_event.h@stripped, 2007-11-30 13:49:26+02:00,
> aelkin@stripped +6 -0
>> >> adding a new member to hold the slave's mode during execution of the
> event.
>> >>
>> >> sql/mysql_priv.h@stripped, 2007-11-30 13:49:26+02:00,
> aelkin@stripped +1 -0
>> >> changes to link the command line option with the new global sys
> var.
>> >>
>> >> sql/mysqld.cc@stripped, 2007-11-30 13:49:26+02:00,
> aelkin@stripped +17 -2
>> >> introduction of the new command line option.
>> >> providing its initialization to a default.
>> >> changes to link the command line option with the new global sys
> var.
>> >>
>> >> sql/rpl_rli.cc@stripped, 2007-11-30 13:49:27+02:00,
> aelkin@stripped +5 -0
>> >> rli post-event-execution cleanup restores the default bits.
>> >>
>> >> sql/set_var.cc@stripped, 2007-11-30 13:49:27+02:00,
> aelkin@stripped +82 -0
>> >> The new "standard" sys_var_set class' and the new global system var
> related
>> >> declarations and definitions.
>> >> fix_slave_exec_mode() is used as with the update method of a new
> class so
>> >> as at time of the command line arguments parsing.
>> >>
>> >> sql/set_var.h@stripped, 2007-11-30 13:49:27+02:00,
> aelkin@stripped +38 -1
>> >> new declarations. The class for the new global sys var is based on
>> >> yet another new "standard" one.
>> >>
>> >> sql/share/errmsg.txt@stripped, 2007-11-30 13:49:28+02:00,
> aelkin@stripped +2 -0
>> >> slave_exec_mode setting error;
>> >> slave inconsistency error which may be not an error when the
> intention
>> >> is "idempotent". I.e consisting of row-based events binlog is being
>> >> applied for the 2nd (more) time.
>> >>
>> >> sql/sql_class.h@stripped, 2007-11-30 13:49:27+02:00,
> aelkin@stripped +3 -0
>> >> The names for the bits of the new sever slave_exec_mode_options.
>> >>
>> >> diff -Nrup a/include/my_bitmap.h b/include/my_bitmap.h
>> >> --- a/include/my_bitmap.h 2007-07-25 16:29:28 +03:00
>> >> +++ b/include/my_bitmap.h 2007-11-30 13:49:21 +02:00
>> >> @@ -159,6 +159,22 @@ static inline my_bool bitmap_cmp(const M
>> >> #define bitmap_set_all(MAP) \
>> >> (memset((MAP)->bitmap, 0xFF, 4*no_words_in_map((MAP))))
>> >>
>> >> +/**
>> >> + check, set and clear a bit of interest of an integer.
>> >> +
>> >> + If the bit is out of range @retval -1. Otherwise
>> >> + bit_is_set @return 0 or 1 reflecting the bit is set or not;
>> >> + bit_do_set @return 1 (bit is set 1)
>> >> + bit_do_clear @return 0 (bit is cleared to 0)
>> >> +*/
>> >> +
>> >> +#define bit_is_set(I,B) (sizeof(I) * CHAR_BIT > (B) ?
> \
>> >> + (((I) & (ULL(1) << (B))) == 0 ? 0
> : 1) : -1)
>> >> +#define bit_do_set(I,B) (sizeof(I) * CHAR_BIT > (B) ? \
>> >> + ((I) |= (ULL(1) << (B)), 1) : -1)
>> >> +#define bit_do_clear(I,B) (sizeof(I) * CHAR_BIT > (B) ? \
>> >> + ((I) &= ~(ULL(1) << (B)), 0) :
> -1)
>> >> +
>> >> #ifdef __cplusplus
>> >> }
>> >> #endif
>> >> diff -Nrup a/mysql-test/extra/rpl_tests/rpl_foreign_key.test
> b/mysql-test/extra/rpl_tests/rpl_foreign_key.test
>> >> --- a/mysql-test/extra/rpl_tests/rpl_foreign_key.test 2007-06-06
> 20:48:52 +03:00
>> >> +++ b/mysql-test/extra/rpl_tests/rpl_foreign_key.test 2007-11-30
> 13:49:21 +02:00
>> >> @@ -32,3 +32,34 @@ SET FOREIGN_KEY_CHECKS=0;
>> >> DROP TABLE IF EXISTS t1,t2,t3;
>> >> SET FOREIGN_KEY_CHECKS=1;
>> >> sync_slave_with_master;
>> >> +
>> >> +#
>> >> +# Bug #32468 delete rows event on a table with foreign key constraint
> fails
>> >> +#
>> >> +
>> >> +connection master;
>> >> +
>> >> +eval create table t1 (b int primary key) engine = $engine_type;
>> >> +eval create table t2 (a int primary key, b int, foreign key (b)
> references t1(b))
>> >> + engine = $engine_type;
>> >> +
>> >> +insert into t1 set b=1;
>> >> +insert into t2 set a=1, b=1;
>> >> +
>> >> +set foreign_key_checks=0;
>> >> +set @@session.binlog_format=row;
>> >> +delete from t1;
>> >> +
>> >> +--echo must sync w/o a problem (could not with the buggy code)
>> >> +sync_slave_with_master;
>> >> +select count(*) from t1 /* must be zero */;
>> >> +
>> >> +
>> >> +# cleanup for bug#32468
>> >> +
>> >> +connection master;
>> >> +drop table t2,t1;
>> >> +
>> >> +sync_slave_with_master;
>> >> +
>> >> +
>> >> diff -Nrup a/mysql-test/extra/rpl_tests/rpl_row_basic.test
> b/mysql-test/extra/rpl_tests/rpl_row_basic.test
>> >> --- a/mysql-test/extra/rpl_tests/rpl_row_basic.test 2007-06-19 00:51:07
> +03:00
>> >> +++ b/mysql-test/extra/rpl_tests/rpl_row_basic.test 2007-11-30 13:49:21
> +02:00
>> >> @@ -174,11 +174,16 @@ sync_slave_with_master;
>> >> INSERT INTO t7 VALUES (1,3), (2,6), (3,9);
>> >> SELECT * FROM t7 ORDER BY C1;
>> >>
>> >> +# bug#31552/31609 idemptency is not default any longer
>> >> +set @@global.slave_exec_mode= 'IDEMPOTENT';
>> >> +
>> >> connection master;
>> >> --echo --- on master: new values inserted ---
>> >> INSERT INTO t7 VALUES (1,2), (2,4), (3,6);
>> >> SELECT * FROM t7 ORDER BY C1;
>> >> sync_slave_with_master;
>> >> +
>> >> +set @@global.slave_exec_mode= 'STRICT';
>> >> --echo --- on slave: old values should be overwritten by replicated
> values ---
>> >> SELECT * FROM t7 ORDER BY C1;
>> >>
>> >> @@ -206,12 +211,17 @@ SELECT * FROM t8 ORDER BY a;
>> >> INSERT INTO t8 VALUES (1,2,3), (2,4,6), (3,6,9);
>> >> SELECT * FROM t8 ORDER BY a;
>> >>
>> >> +# bug#31552/31609 idemptency is not default any longer
>> >> +set @@global.slave_exec_mode= 'IDEMPOTENT';
>> >> +
>> >> connection master;
>> >> --echo --- on master ---
>> >> # We insert a row that will cause conflict on the primary key but not
>> >> # on the other keys.
>> >> INSERT INTO t8 VALUES (2,4,8);
>> >> sync_slave_with_master;
>> >> +set @@global.slave_exec_mode= default;
>> >> +
>> >> --echo --- on slave ---
>> >> SELECT * FROM t8 ORDER BY a;
>> >>
>> >> diff -Nrup a/mysql-test/extra/rpl_tests/rpl_row_tabledefs.test
> b/mysql-test/extra/rpl_tests/rpl_row_tabledefs.test
>> >> --- a/mysql-test/extra/rpl_tests/rpl_row_tabledefs.test 2007-08-21
> 15:32:48 +03:00
>> >> +++ b/mysql-test/extra/rpl_tests/rpl_row_tabledefs.test 2007-11-30
> 13:49:21 +02:00
>> >> @@ -69,6 +69,10 @@ ALTER TABLE t8 ADD e1 INT NOT NULL DEFAU
>> >>
>> >> # Insert some values for tables on slave side. These should not be
>> >> # modified when the row from the master is applied.
>> >> +# before bug#31552/31609 idemptency is not default any longer
>> >> +set @@global.slave_exec_mode= 'IDEMPOTENT';
>> >> +
>> >> +# so the inserts are going to be overriden
>> >> INSERT INTO t1_int VALUES (2, 4, 4711);
>> >> INSERT INTO t1_char VALUES (2, 4, 'Foo is a bar');
>> >> INSERT INTO t1_bit VALUES (2, 4, b'101', b'11100', b'01');
>> >> @@ -86,6 +90,8 @@ SELECT * FROM t1_bit ORDER BY a;
>> >> SELECT * FROM t1_char ORDER BY a;
>> >> --echo **** On Slave ****
>> >> sync_slave_with_master;
>> >> +set @@global.slave_exec_mode= default;
>> >> +
>> >> SELECT a,b,x FROM t1_int ORDER BY a;
>> >> SELECT a,b,HEX(x),HEX(y),HEX(z) FROM t1_bit ORDER BY a;
>> >> SELECT a,b,x FROM t1_char ORDER BY a;
>> >> diff -Nrup a/mysql-test/suite/rpl/r/rpl_foreign_key_innodb.result
> b/mysql-test/suite/rpl/r/rpl_foreign_key_innodb.result
>> >> --- a/mysql-test/suite/rpl/r/rpl_foreign_key_innodb.result 2007-06-27
> 15:27:28 +03:00
>> >> +++ b/mysql-test/suite/rpl/r/rpl_foreign_key_innodb.result 2007-11-30
> 13:49:21 +02:00
>> >> @@ -40,3 +40,16 @@ Got one of the listed errors
>> >> SET FOREIGN_KEY_CHECKS=0;
>> >> DROP TABLE IF EXISTS t1,t2,t3;
>> >> SET FOREIGN_KEY_CHECKS=1;
>> >> +create table t1 (b int primary key) engine = INNODB;
>> >> +create table t2 (a int primary key, b int, foreign key (b) references
> t1(b))
>> >> +engine = INNODB;
>> >> +insert into t1 set b=1;
>> >> +insert into t2 set a=1, b=1;
>> >> +set foreign_key_checks=0;
>> >> +set @@session.binlog_format=row;
>> >> +delete from t1;
>> >> +must sync w/o a problem (could not with the buggy code)
>> >> +select count(*) from t1 /* must be zero */;
>> >> +count(*)
>> >> +0
>> >> +drop table t2,t1;
>> >> diff -Nrup a/mysql-test/suite/rpl/r/rpl_idempotency.result
> b/mysql-test/suite/rpl/r/rpl_idempotency.result
>> >> --- a/mysql-test/suite/rpl/r/rpl_idempotency.result 2007-10-30 22:17:14
> +02:00
>> >> +++ b/mysql-test/suite/rpl/r/rpl_idempotency.result 2007-11-30 13:49:22
> +02:00
>> >> @@ -69,3 +69,162 @@ a
>> >> Last_SQL_Error
>> >> 0
>> >> DROP TABLE t1, t2;
>> >> +select @@global.slave_exec_mode /* must be IDEMPOTENT */;
>> >> +@@global.slave_exec_mode
>> >> +IDEMPOTENT
>> >> +create table ti1 (b int primary key) engine = innodb;
>> >> +create table ti2 (a int primary key, b int, foreign key (b) references
> ti1(b))
>> >> +engine = innodb;
>> >> +set foreign_key_checks=1 /* ensure the check */;
>> >> +insert into ti1 values (1),(2),(3);
>> >> +insert into ti2 set a=2, b=2;
>> >> +select * from ti1 order by b /* must be (1),(2),(3) */;
>> >> +b
>> >> +1
>> >> +2
>> >> +3
>> >> +insert into ti2 set a=1, b=1;
>> >> +select * from ti2 order by b /* must be (1,1) (2,2) */;
>> >> +a b
>> >> +1 1
>> >> +2 2
>> >> +set @save_binlog_format= @@session.binlog_format;
>> >> +set @@session.binlog_format= row;
>> >> +delete from ti1 where b=1;
>> >> +select * from ti1 order by b /* must be (2),(3) */;
>> >> +b
>> >> +2
>> >> +3
>> >> +select * from ti1 order by b /* must stays as were on master
> (1),(2),(3) */;
>> >> +b
>> >> +1
>> >> +2
>> >> +3
>> >> +delete from ti1 where b=3;
>> >> +insert into ti2 set a=3, b=3;
>> >> +select * from ti2 order by b /* must be (1,1),(2,2) - not inserted */;
>> >> +a b
>> >> +1 1
>> >> +2 2
>> >> +set global slave_exec_mode='STRICT';
>> >> +set global slave_exec_mode='IDEMPOTENT';
>> >> +set global slave_exec_mode='IDEMPOTENT,STRICT';
>> >> +Warnings:
>> >> +Warning 1607 Ambiguous slave modes combination. STRICT will be used
>> >> +show warnings /* must be the warning */;
>> >> +Level Code Message
>> >> +Warning 1607 Ambiguous slave modes combination. STRICT will be used
>> >> +select @@global.slave_exec_mode /* must be STRICT */;
>> >> +@@global.slave_exec_mode
>> >> +STRICT
>> >> +*** foreign keys errors as above now forces to stop
>> >> +set foreign_key_checks=0;
>> >> +drop table ti2, ti1;
>> >> +create table ti1 (b int primary key) engine = innodb;
>> >> +create table ti2 (a int primary key, b int, foreign key (b) references
> ti1(b))
>> >> +engine = innodb;
>> >> +set foreign_key_checks=1 /* ensure the check */;
>> >> +insert into ti1 values (1),(2),(3);
>> >> +insert into ti2 set a=2, b=2;
>> >> +select * from ti1 order by b /* must be (1),(2),(3) */;
>> >> +b
>> >> +1
>> >> +2
>> >> +3
>> >> +*** conspire future problem
>> >> +insert into ti2 set a=1, b=1;
>> >> +select * from ti2 order by b /* must be (1,1) (2,2) */;
>> >> +a b
>> >> +1 1
>> >> +2 2
>> >> +delete from ti1 where b=1 /* offending delete event */;
>> >> +select * from ti1 order by b /* must be (2),(3) */;
>> >> +b
>> >> +2
>> >> +3
>> >> +*** slave must stop
>> >> +Last_SQL_Error
>> >> +0
>> >> +select * from ti1 order by b /* must be (1),(2),(3) - not deleted */;
>> >> +b
>> >> +1
>> >> +2
>> >> +3
>> >> +set foreign_key_checks= 0;
>> >> +delete from ti2 where b=1;
>> >> +set foreign_key_checks= 1;
>> >> +set global slave_exec_mode='IDEMPOTENT';
>> >> +start slave sql_thread;
>> >> +set global slave_exec_mode='STRICT';
>> >> +*** conspire the following insert failure
>> >> +*** conspire future problem
>> >> +delete from ti1 where b=3;
>> >> +insert into ti2 set a=3, b=3 /* offending write event */;
>> >> +*** slave must stop
>> >> +Last_SQL_Error
>> >> +1452
>> >> +select * from ti2 order by b /* must be (2,2) */;
>> >> +a b
>> >> +2 2
>> >> +set foreign_key_checks= 0;
>> >> +insert into ti1 set b=3;
>> >> +set foreign_key_checks= 1;
>> >> +set global slave_exec_mode='IDEMPOTENT';
>> >> +start slave sql_thread;
>> >> +set global slave_exec_mode='STRICT';
>> >> +select * from ti2 order by b /* must be (2,2),(3,3) */;
>> >> +a b
>> >> +2 2
>> >> +3 3
>> >> +*** other errors
>> >> +*** conspiring query
>> >> +insert into ti1 set b=1;
>> >> +insert into ti1 set b=1 /* offending write event */;
>> >> +*** slave must stop
>> >> +Last_SQL_Error
>> >> +1062
>> >> +set foreign_key_checks= 0;
>> >> +delete from ti1 where b=1;
>> >> +set foreign_key_checks= 1;
>> >> +set global slave_exec_mode='IDEMPOTENT';
>> >> +start slave sql_thread;
>> >> +set global slave_exec_mode='STRICT';
>> >> +CREATE TABLE t1 (a INT PRIMARY KEY);
>> >> +CREATE TABLE t2 (a INT);
>> >> +INSERT INTO t1 VALUES (-1),(-2),(-3);
>> >> +INSERT INTO t2 VALUES (-1),(-2),(-3);
>> >> +DELETE FROM t1 WHERE a = -2;
>> >> +DELETE FROM t2 WHERE a = -2;
>> >> +DELETE FROM t1 WHERE a = -2;
>> >> +*** slave must stop
>> >> +Last_SQL_Error
>> >> +1032
>> >> +set global slave_exec_mode='IDEMPOTENT';
>> >> +start slave sql_thread;
>> >> +set global slave_exec_mode='STRICT';
>> >> +DELETE FROM t2 WHERE a = -2;
>> >> +*** slave must stop
>> >> +Last_SQL_Error
>> >> +0
>> >> +set global slave_exec_mode='IDEMPOTENT';
>> >> +start slave sql_thread;
>> >> +set global slave_exec_mode='STRICT';
>> >> +UPDATE t1 SET a = 1 WHERE a = -1;
>> >> +UPDATE t2 SET a = 1 WHERE a = -1;
>> >> +UPDATE t1 SET a = 1 WHERE a = -1;
>> >> +*** slave must stop
>> >> +Last_SQL_Error
>> >> +1032
>> >> +set global slave_exec_mode='IDEMPOTENT';
>> >> +start slave sql_thread;
>> >> +set global slave_exec_mode='STRICT';
>> >> +UPDATE t2 SET a = 1 WHERE a = -1;
>> >> +*** slave must stop
>> >> +Last_SQL_Error
>> >> +0
>> >> +set global slave_exec_mode='IDEMPOTENT';
>> >> +start slave sql_thread;
>> >> +set global slave_exec_mode='STRICT';
>> >> +set @@session.binlog_format= @save_binlog_format;
>> >> +drop table t1,t2,ti2,ti1;
>> >> +*** end of tests
>> >> diff -Nrup a/mysql-test/suite/rpl/r/rpl_ignore_table.result
> b/mysql-test/suite/rpl/r/rpl_ignore_table.result
>> >> --- a/mysql-test/suite/rpl/r/rpl_ignore_table.result 2007-06-27 15:27:32
> +03:00
>> >> +++ b/mysql-test/suite/rpl/r/rpl_ignore_table.result 2007-11-30 13:49:22
> +02:00
>> >> @@ -117,10 +117,14 @@ Grants for mysqltest4@localhost
>> >> GRANT USAGE ON *.* TO 'mysqltest4'@'localhost' IDENTIFIED BY PASSWORD
> '*196BDEDE2AE4F84CA44C47D54D78478C7E2BD7B7'
>> >> drop table t1, t4, mysqltest2.t2;
>> >> drop database mysqltest2;
>> >> +set @save_binlog_format= @@session.binlog_format;
>> >> +set @@session.binlog_format= mixed;
>> >> delete from mysql.user where user like "mysqltest%";
>> >> +set @@session.binlog_format= @save_binlog_format;
>> >> delete from mysql.db where user like "mysqltest%";
>> >> delete from mysql.columns_priv where user like "mysqltest%";
>> >> delete from mysql.tables_priv where user like "mysqltest%";
>> >> +set @@global.slave_exec_mode= 'IDEMPOTENT';
>> >> delete from mysql.tables_priv where user like "mysqltest%";
>> >> DROP TABLE IF EXISTS t5;
>> >> CREATE TABLE t5 (
>> >> diff -Nrup a/mysql-test/suite/rpl/r/rpl_row_USER.result
> b/mysql-test/suite/rpl/r/rpl_row_USER.result
>> >> --- a/mysql-test/suite/rpl/r/rpl_row_USER.result 2007-06-27 15:27:30
> +03:00
>> >> +++ b/mysql-test/suite/rpl/r/rpl_row_USER.result 2007-11-30 13:49:22
> +02:00
>> >> @@ -31,7 +31,10 @@ a users
>> >> 2 @localhost%
>> >> 3 tester@localhost
>> >> 4 @localhost%
>> >> +set @save_binlog_format= @@session.binlog_format;
>> >> +set @@session.binlog_format= mixed;
>> >> DROP DATABASE mysqltest1;
>> >> +set @@session.binlog_format= @save_binlog_format;
>> >> REVOKE ALL ON mysqltest1.* FROM 'tester'@'%';
>> >> REVOKE ALL ON mysqltest1.* FROM ''@'localhost%';
>> >> DROP USER tester@'%';
>> >> diff -Nrup a/mysql-test/suite/rpl/r/rpl_row_basic_11bugs.result
> b/mysql-test/suite/rpl/r/rpl_row_basic_11bugs.result
>> >> --- a/mysql-test/suite/rpl/r/rpl_row_basic_11bugs.result 2007-10-24
> 17:02:31 +03:00
>> >> +++ b/mysql-test/suite/rpl/r/rpl_row_basic_11bugs.result 2007-11-30
> 13:49:22 +02:00
>> >> @@ -257,6 +257,7 @@ SELECT * FROM t1 ORDER BY a;
>> >> a b
>> >> 2 master,slave
>> >> 5 slave
>> >> +set @@global.slave_exec_mode= 'IDEMPOTENT';
>> >> **** On Master ****
>> >> UPDATE t1 SET a = 5, b = 'master' WHERE a = 1;
>> >> SELECT * FROM t1 ORDER BY a;
>> >> @@ -264,6 +265,7 @@ a b
>> >> 2 master,slave
>> >> 5 master
>> >> **** On Slave ****
>> >> +set @@global.slave_exec_mode= default;
>> >> Last_SQL_Error
>> >>
>> >> SELECT * FROM t1 ORDER BY a;
>> >> diff -Nrup a/mysql-test/suite/rpl/r/rpl_row_basic_2myisam.result
> b/mysql-test/suite/rpl/r/rpl_row_basic_2myisam.result
>> >> --- a/mysql-test/suite/rpl/r/rpl_row_basic_2myisam.result 2007-06-27
> 15:27:28 +03:00
>> >> +++ b/mysql-test/suite/rpl/r/rpl_row_basic_2myisam.result 2007-11-30
> 13:49:22 +02:00
>> >> @@ -370,6 +370,7 @@ C1 C2
>> >> 1 3
>> >> 2 6
>> >> 3 9
>> >> +set @@global.slave_exec_mode= 'IDEMPOTENT';
>> >> --- on master: new values inserted ---
>> >> INSERT INTO t7 VALUES (1,2), (2,4), (3,6);
>> >> SELECT * FROM t7 ORDER BY C1;
>> >> @@ -377,6 +378,7 @@ C1 C2
>> >> 1 2
>> >> 2 4
>> >> 3 6
>> >> +set @@global.slave_exec_mode= 'STRICT';
>> >> --- on slave: old values should be overwritten by replicated values
> ---
>> >> SELECT * FROM t7 ORDER BY C1;
>> >> C1 C2
>> >> @@ -406,8 +408,10 @@ a b c
>> >> 2 4 6
>> >> 3 6 9
>> >> 99 99 99
>> >> +set @@global.slave_exec_mode= 'IDEMPOTENT';
>> >> --- on master ---
>> >> INSERT INTO t8 VALUES (2,4,8);
>> >> +set @@global.slave_exec_mode= default;
>> >> --- on slave ---
>> >> SELECT * FROM t8 ORDER BY a;
>> >> a b c
>> >> diff -Nrup a/mysql-test/suite/rpl/r/rpl_row_basic_3innodb.result
> b/mysql-test/suite/rpl/r/rpl_row_basic_3innodb.result
>> >> --- a/mysql-test/suite/rpl/r/rpl_row_basic_3innodb.result 2007-06-27
> 15:27:32 +03:00
>> >> +++ b/mysql-test/suite/rpl/r/rpl_row_basic_3innodb.result 2007-11-30
> 13:49:22 +02:00
>> >> @@ -370,6 +370,7 @@ C1 C2
>> >> 1 3
>> >> 2 6
>> >> 3 9
>> >> +set @@global.slave_exec_mode= 'IDEMPOTENT';
>> >> --- on master: new values inserted ---
>> >> INSERT INTO t7 VALUES (1,2), (2,4), (3,6);
>> >> SELECT * FROM t7 ORDER BY C1;
>> >> @@ -377,6 +378,7 @@ C1 C2
>> >> 1 2
>> >> 2 4
>> >> 3 6
>> >> +set @@global.slave_exec_mode= 'STRICT';
>> >> --- on slave: old values should be overwritten by replicated values
> ---
>> >> SELECT * FROM t7 ORDER BY C1;
>> >> C1 C2
>> >> @@ -406,8 +408,10 @@ a b c
>> >> 2 4 6
>> >> 3 6 9
>> >> 99 99 99
>> >> +set @@global.slave_exec_mode= 'IDEMPOTENT';
>> >> --- on master ---
>> >> INSERT INTO t8 VALUES (2,4,8);
>> >> +set @@global.slave_exec_mode= default;
>> >> --- on slave ---
>> >> SELECT * FROM t8 ORDER BY a;
>> >> a b c
>> >> diff -Nrup a/mysql-test/suite/rpl/r/rpl_row_mystery22.result
> b/mysql-test/suite/rpl/r/rpl_row_mystery22.result
>> >> --- a/mysql-test/suite/rpl/r/rpl_row_mystery22.result 2007-06-27
> 15:27:32 +03:00
>> >> +++ b/mysql-test/suite/rpl/r/rpl_row_mystery22.result 2007-11-30
> 13:49:23 +02:00
>> >> @@ -5,6 +5,7 @@ reset slave;
>> >> drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
>> >> start slave;
>> >> create table t1(n int auto_increment primary key, s char(10));
>> >> +set @@global.slave_exec_mode= 'IDEMPOTENT';
>> >> insert into t1 values (2,'old');
>> >> insert into t1 values(NULL,'new');
>> >> insert into t1 values(NULL,'new');
>> >> @@ -28,3 +29,4 @@ n s
>> >> 1 new
>> >> 3 new
>> >> drop table t1;
>> >> +set @@global.slave_exec_mode= default;
>> >> diff -Nrup a/mysql-test/suite/rpl/r/rpl_row_tabledefs_2myisam.result
> b/mysql-test/suite/rpl/r/rpl_row_tabledefs_2myisam.result
>> >> --- a/mysql-test/suite/rpl/r/rpl_row_tabledefs_2myisam.result 2007-09-25
> 18:44:47 +03:00
>> >> +++ b/mysql-test/suite/rpl/r/rpl_row_tabledefs_2myisam.result 2007-11-30
> 13:49:23 +02:00
>> >> @@ -37,6 +37,7 @@ ALTER TABLE t8 ADD e1 INT NOT NULL DEFAU
>> >> ADD e3 INT NOT NULL DEFAULT 0, ADD e4 INT NOT NULL DEFAULT 0,
>> >> ADD e5 INT NOT NULL DEFAULT 0, ADD e6 INT NOT NULL DEFAULT 0,
>> >> ADD e7 INT NOT NULL DEFAULT 0, ADD e8 INT NOT NULL DEFAULT 0;
>> >> +set @@global.slave_exec_mode= 'IDEMPOTENT';
>> >> INSERT INTO t1_int VALUES (2, 4, 4711);
>> >> INSERT INTO t1_char VALUES (2, 4, 'Foo is a bar');
>> >> INSERT INTO t1_bit VALUES (2, 4, b'101', b'11100', b'01');
>> >> @@ -60,6 +61,7 @@ a b
>> >> 1 2
>> >> 2 5
>> >> **** On Slave ****
>> >> +set @@global.slave_exec_mode= default;
>> >> SELECT a,b,x FROM t1_int ORDER BY a;
>> >> a b x
>> >> 1 2 42
>> >> @@ -123,7 +125,7 @@ Replicate_Ignore_Table
>> >> Replicate_Wild_Do_Table
>> >> Replicate_Wild_Ignore_Table
>> >> Last_Errno 1364
>> >> -Last_Error Error in Write_rows event: error during transaction
> execution on table test.t1_nodef.
>> >> +Last_Error Error in Write_rows event: error during transaction
> execution on table test.t1_nodef. ; handler error (null); the event's master log and
> end_log_pos master-bin.000001 2674
>> >> Skip_Counter 0
>> >> Exec_Master_Log_Pos #
>> >> Relay_Log_Space #
>> >> @@ -141,7 +143,7 @@ Master_SSL_Verify_Server_Cert No
>> >> Last_IO_Errno 0
>> >> Last_IO_Error
>> >> Last_SQL_Errno 1364
>> >> -Last_SQL_Error Error in Write_rows event: error during transaction
> execution on table test.t1_nodef.
>> >> +Last_SQL_Error Error in Write_rows event: error during transaction
> execution on table test.t1_nodef. ; handler error (null); the event's master log and
> end_log_pos master-bin.000001 2674
>> >> SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2;
>> >> START SLAVE;
>> >> INSERT INTO t9 VALUES (2);
>> >> diff -Nrup a/mysql-test/suite/rpl/r/rpl_row_tabledefs_3innodb.result
> b/mysql-test/suite/rpl/r/rpl_row_tabledefs_3innodb.result
>> >> --- a/mysql-test/suite/rpl/r/rpl_row_tabledefs_3innodb.result 2007-09-25
> 18:44:47 +03:00
>> >> +++ b/mysql-test/suite/rpl/r/rpl_row_tabledefs_3innodb.result 2007-11-30
> 13:49:23 +02:00
>> >> @@ -37,6 +37,7 @@ ALTER TABLE t8 ADD e1 INT NOT NULL DEFAU
>> >> ADD e3 INT NOT NULL DEFAULT 0, ADD e4 INT NOT NULL DEFAULT 0,
>> >> ADD e5 INT NOT NULL DEFAULT 0, ADD e6 INT NOT NULL DEFAULT 0,
>> >> ADD e7 INT NOT NULL DEFAULT 0, ADD e8 INT NOT NULL DEFAULT 0;
>> >> +set @@global.slave_exec_mode= 'IDEMPOTENT';
>> >> INSERT INTO t1_int VALUES (2, 4, 4711);
>> >> INSERT INTO t1_char VALUES (2, 4, 'Foo is a bar');
>> >> INSERT INTO t1_bit VALUES (2, 4, b'101', b'11100', b'01');
>> >> @@ -60,6 +61,7 @@ a b
>> >> 1 2
>> >> 2 5
>> >> **** On Slave ****
>> >> +set @@global.slave_exec_mode= default;
>> >> SELECT a,b,x FROM t1_int ORDER BY a;
>> >> a b x
>> >> 1 2 42
>> >> @@ -123,7 +125,7 @@ Replicate_Ignore_Table
>> >> Replicate_Wild_Do_Table
>> >> Replicate_Wild_Ignore_Table
>> >> Last_Errno 1364
>> >> -Last_Error Error in Write_rows event: error during transaction
> execution on table test.t1_nodef.
>> >> +Last_Error Could not execute Write_rows event on table test.t1_nodef.
> Error: (handler error <unknown>). The event's master log and end_log_pos
> master-bin.000001 2944
>> >> Skip_Counter 0
>> >> Exec_Master_Log_Pos #
>> >> Relay_Log_Space #
>> >> @@ -141,7 +143,7 @@ Master_SSL_Verify_Server_Cert No
>> >> Last_IO_Errno 0
>> >> Last_IO_Error
>> >> Last_SQL_Errno 1364
>> >> -Last_SQL_Error Error in Write_rows event: error during transaction
> execution on table test.t1_nodef.
>> >> +Last_SQL_Error Could not execute Write_rows event on table
> test.t1_nodef. Error: (handler error <unknown>). The event's master log and
> end_log_pos master-bin.000001 2944
>> >> SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2;
>> >> START SLAVE;
>> >> INSERT INTO t9 VALUES (2);
>> >> diff -Nrup a/mysql-test/suite/rpl/r/rpl_temporary_errors.result
> b/mysql-test/suite/rpl/r/rpl_temporary_errors.result
>> >> --- a/mysql-test/suite/rpl/r/rpl_temporary_errors.result 2007-10-24
> 17:02:32 +03:00
>> >> +++ b/mysql-test/suite/rpl/r/rpl_temporary_errors.result 2007-11-30
> 13:49:23 +02:00
>> >> @@ -12,6 +12,7 @@ INSERT INTO t1 VALUES (1,1), (2,2), (3,3
>> >> SHOW STATUS LIKE 'Slave_retried_transactions';
>> >> Variable_name Value
>> >> Slave_retried_transactions 0
>> >> +set @@global.slave_exec_mode= 'IDEMPOTENT';
>> >> UPDATE t1 SET a = 5, b = 47 WHERE a = 1;
>> >> SELECT * FROM t1;
>> >> a b
>> >> @@ -28,6 +29,7 @@ a b
>> >> 3 3
>> >> 4 4
>> >> **** On Slave ****
>> >> +set @@global.slave_exec_mode= default;
>> >> SHOW STATUS LIKE 'Slave_retried_transactions';
>> >> Variable_name Value
>> >> Slave_retried_transactions 0
>> >> diff -Nrup a/mysql-test/suite/rpl/t/rpl_idempotency-master.opt
> b/mysql-test/suite/rpl/t/rpl_idempotency-master.opt
>> >> --- /dev/null Wed Dec 31 16:00:00 196900
>> >> +++ b/mysql-test/suite/rpl/t/rpl_idempotency-master.opt 2007-11-30
> 13:49:28 +02:00
>> >> @@ -0,0 +1,2 @@
>> >> +--innodb
>> >> +
>> >> diff -Nrup a/mysql-test/suite/rpl/t/rpl_idempotency-slave.opt
> b/mysql-test/suite/rpl/t/rpl_idempotency-slave.opt
>> >> --- /dev/null Wed Dec 31 16:00:00 196900
>> >> +++ b/mysql-test/suite/rpl/t/rpl_idempotency-slave.opt 2007-11-30
> 13:49:28 +02:00
>> >> @@ -0,0 +1,2 @@
>> >> +--slave-exec-mode=IDEMPOTENT --innodb
>> >> +
>> >> diff -Nrup a/mysql-test/suite/rpl/t/rpl_idempotency.test
> b/mysql-test/suite/rpl/t/rpl_idempotency.test
>> >> --- a/mysql-test/suite/rpl/t/rpl_idempotency.test 2007-10-30 22:17:14
> +02:00
>> >> +++ b/mysql-test/suite/rpl/t/rpl_idempotency.test 2007-11-30 13:49:24
> +02:00
>> >> @@ -77,3 +77,332 @@ enable_query_log;
>> >> connection master;
>> >> DROP TABLE t1, t2;
>> >> sync_slave_with_master;
>> >> +
>> >> +# bug#31609 Not all RBR slave errors reported as errors
>> >> +# bug#31552 Replication breaks when deleting rows from out-of-sync
> table
>> >> +# without PK
>> >> +
>> >> +#
>> >> +# Idempotent applying is not default any longer.
>> >> +# The default for slave-exec-mode option and server
>> >> +# variable slave_exec_mode is 'STRICT'.
>> >> +# When 'STRICT' mode is set, the slave SQL thread will stop whenever
>> >> +# the row to change is not found. In 'IDEMPOTENT' mode, the SQL thread
>> >> +# will continue running and apply the row - replace if it's Write_rows
> event -
>> >> +# or skip to the next event.
>> >> +
>> >> +# the previous part of the tests was with IDEMPOTENT slave's mode.
>> >> +
>> >> +
>> >> +#
>> >> +# Other than above idempotent errors dealing with foreign keys
> constraint
>> >> +#
>> >> +
>> >> +select @@global.slave_exec_mode /* must be IDEMPOTENT */;
>> >> +
>> >> +connection master;
>> >> +
>> >> +create table ti1 (b int primary key) engine = innodb;
>> >> +create table ti2 (a int primary key, b int, foreign key (b) references
> ti1(b))
>> >> + engine = innodb;
>> >> +set foreign_key_checks=1 /* ensure the check */;
>> >> +
>> >> +insert into ti1 values (1),(2),(3);
>> >> +insert into ti2 set a=2, b=2;
>> >> +
>> >> +sync_slave_with_master;
>> >> +
>> >> +#connection slave;
>> >> +select * from ti1 order by b /* must be (1),(2),(3) */;
>> >> +insert into ti2 set a=1, b=1;
>> >> +select * from ti2 order by b /* must be (1,1) (2,2) */;
>> >> +
>> >> +connection master;
>> >> +
>> >> +# from now on checking rbr specific idempotent errors
>> >> +set @save_binlog_format= @@session.binlog_format;
>> >> +set @@session.binlog_format= row;
>> >> +delete from ti1 where b=1;
>> >> +
>> >> +select * from ti1 order by b /* must be (2),(3) */;
>> >> +
>> >> +# slave must catch up (expect some warnings in error.log)
>> >> +sync_slave_with_master;
>> >> +
>> >> +#connection slave;
>> >> +select * from ti1 order by b /* must stays as were on master
> (1),(2),(3) */;
>> >> +
>> >> +delete from ti1 where b=3;
>> >> +
>> >> +connection master;
>> >> +insert into ti2 set a=3, b=3;
>> >> +
>> >> +# slave must catch up (expect some warnings in error.log)
>> >> +sync_slave_with_master;
>> >> +
>> >> +#connection slave;
>> >> +select * from ti2 order by b /* must be (1,1),(2,2) - not inserted */;
>> >> +
>> >> +
>> >> +#
>> >> +# Checking the new global sys variable
>> >> +#
>> >> +
>> >> +connection slave;
>> >> +
>> >> +set global slave_exec_mode='STRICT';
>> >> +set global slave_exec_mode='IDEMPOTENT';
>> >> +
>> >> +# checking mutual exclusion for the options
>> >> +set global slave_exec_mode='IDEMPOTENT,STRICT';
>> >> +show warnings /* must be the warning */;
>> >> +
>> >> +select @@global.slave_exec_mode /* must be STRICT */;
>> >> +
>> >> +#
>> >> +# Checking stops
>> >> +#
>> >> +
>> >> +#
>> >> +--echo *** foreign keys errors as above now forces to stop
>> >> +#
>> >> +
>> >> +connection master;
>> >> +
>> >> +set foreign_key_checks=0;
>> >> +drop table ti2, ti1;
>> >> +
>> >> +create table ti1 (b int primary key) engine = innodb;
>> >> +create table ti2 (a int primary key, b int, foreign key (b) references
> ti1(b))
>> >> + engine = innodb;
>> >> +set foreign_key_checks=1 /* ensure the check */;
>> >> +
>> >> +insert into ti1 values (1),(2),(3);
>> >> +insert into ti2 set a=2, b=2;
>> >> +
>> >> +sync_slave_with_master;
>> >> +
>> >> +#connection slave;
>> >> +select * from ti1 order by b /* must be (1),(2),(3) */;
>> >> +--echo *** conspire future problem
>> >> +insert into ti2 set a=1, b=1;
>> >> +select * from ti2 order by b /* must be (1,1) (2,2) */;
>> >> +
>> >> +connection master;
>> >> +
>> >> +delete from ti1 where b=1 /* offending delete event */;
>> >> +select * from ti1 order by b /* must be (2),(3) */;
>> >> +
>> >> +# foreign key: row is referenced
>> >> +
>> >> +--echo *** slave must stop
>> >> +source include/wait_for_slave_sql_to_stop.inc;
>> >> +
>> >> +connection slave;
>> >> +
>> >> +let $last_error = query_get_value("SHOW SLAVE STATUS", Last_SQL_Errno,
> 1);
>> >> +disable_query_log;
>> >> +eval SELECT "$last_error" AS Last_SQL_Error;
>> >> +enable_query_log;
>> >> +
>> >> +select * from ti1 order by b /* must be (1),(2),(3) - not deleted */;
>> >> +set foreign_key_checks= 0;
>> >> +delete from ti2 where b=1;
>> >> +set foreign_key_checks= 1;
>> >> +set global slave_exec_mode='IDEMPOTENT';
>> >> +start slave sql_thread;
>> >> +connection master;
>> >> +sync_slave_with_master;
>> >> +#connection slave;
>> >> +set global slave_exec_mode='STRICT';
>> >> +
>> >> +connection master;
>> >> +
>> >> +sync_slave_with_master;
>> >> +
>> >> +#connection slave;
>> >> +--echo *** conspire the following insert failure
>> >> +# foreign key: no referenced row
>> >> +
>> >> +--echo *** conspire future problem
>> >> +delete from ti1 where b=3;
>> >> +
>> >> +connection master;
>> >> +insert into ti2 set a=3, b=3 /* offending write event */;
>> >> +--echo *** slave must stop
>> >> +
>> >> +source include/wait_for_slave_sql_to_stop.inc;
>> >> +
>> >> +connection slave;
>> >> +
>> >> +let $last_error = query_get_value("SHOW SLAVE STATUS", Last_SQL_Errno,
> 1);
>> >> +disable_query_log;
>> >> +eval SELECT "$last_error" AS Last_SQL_Error;
>> >> +enable_query_log;
>> >> +
>> >> +select * from ti2 order by b /* must be (2,2) */;
>> >> +set foreign_key_checks= 0;
>> >> +insert into ti1 set b=3;
>> >> +set foreign_key_checks= 1;
>> >> +set global slave_exec_mode='IDEMPOTENT';
>> >> +start slave sql_thread;
>> >> +connection master;
>> >> +sync_slave_with_master;
>> >> +#connection slave;
>> >> +set global slave_exec_mode='STRICT';
>> >> +
>> >> +connection master;
>> >> +
>> >> +sync_slave_with_master;
>> >> +
>> >> +select * from ti2 order by b /* must be (2,2),(3,3) */;
>> >> +
>> >> +#
>> >> +--echo *** other errors
>> >> +#
>> >> +
>> >> +# dup key insert
>> >> +
>> >> +#connection slave;
>> >> +--echo *** conspiring query
>> >> +insert into ti1 set b=1;
>> >> +
>> >> +connection master;
>> >> +insert into ti1 set b=1 /* offending write event */;
>> >> +
>> >> +--echo *** slave must stop
>> >> +source include/wait_for_slave_sql_to_stop.inc;
>> >> +
>> >> +connection slave;
>> >> +
>> >> +let $last_error = query_get_value("SHOW SLAVE STATUS", Last_SQL_Errno,
> 1);
>> >> +disable_query_log;
>> >> +eval SELECT "$last_error" AS Last_SQL_Error;
>> >> +enable_query_log;
>> >> +
>> >> +set foreign_key_checks= 0;
>> >> +delete from ti1 where b=1;
>> >> +set foreign_key_checks= 1;
>> >> +set global slave_exec_mode='IDEMPOTENT';
>> >> +start slave sql_thread;
>> >> +connection master;
>> >> +sync_slave_with_master;
>> >> +#connection slave;
>> >> +set global slave_exec_mode='STRICT';
>> >> +
>> >> +# key not found
>> >> +
>> >> +connection master;
>> >> +
>> >> +CREATE TABLE t1 (a INT PRIMARY KEY);
>> >> +CREATE TABLE t2 (a INT);
>> >> +INSERT INTO t1 VALUES (-1),(-2),(-3);
>> >> +INSERT INTO t2 VALUES (-1),(-2),(-3);
>> >> +sync_slave_with_master;
>> >> +
>> >> +#connection slave;
>> >> +DELETE FROM t1 WHERE a = -2;
>> >> +DELETE FROM t2 WHERE a = -2;
>> >> +connection master;
>> >> +DELETE FROM t1 WHERE a = -2;
>> >> +
>> >> +--echo *** slave must stop
>> >> +source include/wait_for_slave_sql_to_stop.inc;
>> >> +
>> >> +connection slave;
>> >> +
>> >> +let $last_error = query_get_value("SHOW SLAVE STATUS", Last_SQL_Errno,
> 1);
>> >> +disable_query_log;
>> >> +eval SELECT "$last_error" AS Last_SQL_Error;
>> >> +enable_query_log;
>> >> +
>> >> +set global slave_exec_mode='IDEMPOTENT';
>> >> +start slave sql_thread;
>> >> +connection master;
>> >> +sync_slave_with_master;
>> >> +#connection slave;
>> >> +set global slave_exec_mode='STRICT';
>> >> +
>> >> +connection master;
>> >> +DELETE FROM t2 WHERE a = -2;
>> >> +--echo *** slave must stop
>> >> +source include/wait_for_slave_sql_to_stop.inc;
>> >> +
>> >> +connection slave;
>> >> +
>> >> +let $last_error = query_get_value("SHOW SLAVE STATUS", Last_SQL_Errno,
> 1);
>> >> +disable_query_log;
>> >> +eval SELECT "$last_error" AS Last_SQL_Error;
>> >> +enable_query_log;
>> >> +
>> >> +set global slave_exec_mode='IDEMPOTENT';
>> >> +start slave sql_thread;
>> >> +connection master;
>> >> +sync_slave_with_master;
>> >> +#connection slave;
>> >> +set global slave_exec_mode='STRICT';
>> >> +
>> >> +UPDATE t1 SET a = 1 WHERE a = -1;
>> >> +UPDATE t2 SET a = 1 WHERE a = -1;
>> >> +
>> >> +connection master;
>> >> +UPDATE t1 SET a = 1 WHERE a = -1;
>> >> +
>> >> +--echo *** slave must stop
>> >> +source include/wait_for_slave_sql_to_stop.inc;
>> >> +
>> >> +connection slave;
>> >> +
>> >> +let $last_error = query_get_value("SHOW SLAVE STATUS", Last_SQL_Errno,
> 1);
>> >> +disable_query_log;
>> >> +eval SELECT "$last_error" AS Last_SQL_Error;
>> >> +enable_query_log;
>> >> +
>> >> +set global slave_exec_mode='IDEMPOTENT';
>> >> +start slave sql_thread;
>> >> +connection master;
>> >> +sync_slave_with_master;
>> >> +#connection slave;
>> >> +set global slave_exec_mode='STRICT';
>> >> +
>> >> +
>> >> +connection master;
>> >> +UPDATE t2 SET a = 1 WHERE a = -1;
>> >> +
>> >> +--echo *** slave must stop
>> >> +source include/wait_for_slave_sql_to_stop.inc;
>> >> +
>> >> +connection slave;
>> >> +
>> >> +let $last_error = query_get_value("SHOW SLAVE STATUS", Last_SQL_Errno,
> 1);
>> >> +disable_query_log;
>> >> +eval SELECT "$last_error" AS Last_SQL_Error;
>> >> +enable_query_log;
>> >> +
>> >> +set global slave_exec_mode='IDEMPOTENT';
>> >> +start slave sql_thread;
>> >> +connection master;
>> >> +sync_slave_with_master;
>> >> +#connection slave;
>> >> +set global slave_exec_mode='STRICT';
>> >> +
>> >> +
>> >> +# cleanup for bug#31609 tests
>> >> +
>> >> +connection master;
>> >> +set @@session.binlog_format= @save_binlog_format;
>> >> +drop table t1,t2,ti2,ti1;
>> >> +
>> >> +sync_slave_with_master;
>> >> +
>> >> +
>> >> +--echo *** end of tests
>> >> +
>> >> +
>> >> +
>> >> +
>> >> +
>> >> +
>> >> +
>> >> +
>> >> +
>> >> diff -Nrup a/mysql-test/suite/rpl/t/rpl_ignore_table.test
> b/mysql-test/suite/rpl/t/rpl_ignore_table.test
>> >> --- a/mysql-test/suite/rpl/t/rpl_ignore_table.test 2007-06-27 15:27:30
> +03:00
>> >> +++ b/mysql-test/suite/rpl/t/rpl_ignore_table.test 2007-11-30 13:49:24
> +02:00
>> >> @@ -122,8 +122,12 @@ show grants for mysqltest4@localhost;
>> >> connection master;
>> >> drop table t1, t4, mysqltest2.t2;
>> >> drop database mysqltest2;
>> >> +set @save_binlog_format= @@session.binlog_format;
>> >> +set @@session.binlog_format= mixed;
>> >> delete from mysql.user where user like "mysqltest%";
>> >> +set @@session.binlog_format= @save_binlog_format;
>> >> delete from mysql.db where user like "mysqltest%";
>> >> +
>> >> #
>> >> # BUG 27606 causes failure to replicate this statement
>> >> # move it to slave instead
>> >> @@ -133,6 +137,10 @@ sync_slave_with_master;
>> >>
>> >> #BUG27606
>> >> delete from mysql.tables_priv where user like "mysqltest%";
>> >> +
>> >> +# bug#31552/31609 idempotency made idempotent non-default so it has to
> be set
>> >> +# because of the inconsistency just have done on slave
>> >> +set @@global.slave_exec_mode= 'IDEMPOTENT';
>> >>
>> >> connection master;
>> >>
>> >> diff -Nrup a/mysql-test/suite/rpl/t/rpl_row_USER.test
> b/mysql-test/suite/rpl/t/rpl_row_USER.test
>> >> --- a/mysql-test/suite/rpl/t/rpl_row_USER.test 2007-06-27 15:27:26
> +03:00
>> >> +++ b/mysql-test/suite/rpl/t/rpl_row_USER.test 2007-11-30 13:49:24
> +02:00
>> >> @@ -49,7 +49,11 @@ connection master;
>> >> # Lets cleanup
>> >> #show binlog events;
>> >>
>> >> +set @save_binlog_format= @@session.binlog_format;
>> >> +set @@session.binlog_format= mixed;
>> >> DROP DATABASE mysqltest1;
>> >> +set @@session.binlog_format= @save_binlog_format;
>> >> +
>> >> REVOKE ALL ON mysqltest1.* FROM 'tester'@'%';
>> >> REVOKE ALL ON mysqltest1.* FROM ''@'localhost%';
>> >> DROP USER tester@'%';
>> >> diff -Nrup a/mysql-test/suite/rpl/t/rpl_row_basic_11bugs.test
> b/mysql-test/suite/rpl/t/rpl_row_basic_11bugs.test
>> >> --- a/mysql-test/suite/rpl/t/rpl_row_basic_11bugs.test 2007-10-24
> 17:02:32 +03:00
>> >> +++ b/mysql-test/suite/rpl/t/rpl_row_basic_11bugs.test 2007-11-30
> 13:49:24 +02:00
>> >> @@ -242,12 +242,15 @@ INSERT INTO t1 VALUES (1,'master,slave')
>> >> sync_slave_with_master;
>> >> UPDATE t1 SET a = 5, b = 'slave' WHERE a = 1;
>> >> SELECT * FROM t1 ORDER BY a;
>> >> +# bug#31552/31609 idemptency is not default any longer
>> >> +set @@global.slave_exec_mode= 'IDEMPOTENT';
>> >> --echo **** On Master ****
>> >> connection master;
>> >> UPDATE t1 SET a = 5, b = 'master' WHERE a = 1;
>> >> SELECT * FROM t1 ORDER BY a;
>> >> --echo **** On Slave ****
>> >> sync_slave_with_master;
>> >> +set @@global.slave_exec_mode= default;
>> >> let $last_error = query_get_value("SHOW SLAVE STATUS", Last_SQL_Error,
> 1);
>> >> disable_query_log;
>> >> eval SELECT "$last_error" AS Last_SQL_Error;
>> >> diff -Nrup a/mysql-test/suite/rpl/t/rpl_row_mystery22.test
> b/mysql-test/suite/rpl/t/rpl_row_mystery22.test
>> >> --- a/mysql-test/suite/rpl/t/rpl_row_mystery22.test 2007-06-27 15:27:25
> +03:00
>> >> +++ b/mysql-test/suite/rpl/t/rpl_row_mystery22.test 2007-11-30 13:49:24
> +02:00
>> >> @@ -9,6 +9,10 @@
>> >> # first, cause a duplicate key problem on the slave
>> >> create table t1(n int auto_increment primary key, s char(10));
>> >> sync_slave_with_master;
>> >> +
>> >> +# bug#31552/31609 idemptency is not default any longer
>> >> +set @@global.slave_exec_mode= 'IDEMPOTENT';
>> >> +
>> >> insert into t1 values (2,'old');
>> >> connection master;
>> >> insert into t1 values(NULL,'new');
>> >> @@ -43,3 +47,4 @@ select * from t1 order by n;
>> >> connection master;
>> >> drop table t1;
>> >> sync_slave_with_master;
>> >> +set @@global.slave_exec_mode= default;
>> >> diff -Nrup a/mysql-test/suite/rpl/t/rpl_temporary_errors.test
> b/mysql-test/suite/rpl/t/rpl_temporary_errors.test
>> >> --- a/mysql-test/suite/rpl/t/rpl_temporary_errors.test 2007-10-24
> 17:02:32 +03:00
>> >> +++ b/mysql-test/suite/rpl/t/rpl_temporary_errors.test 2007-11-30
> 13:49:24 +02:00
>> >> @@ -8,6 +8,8 @@ INSERT INTO t1 VALUES (1,1), (2,2), (3,3
>> >> --echo **** On Slave ****
>> >> sync_slave_with_master;
>> >> SHOW STATUS LIKE 'Slave_retried_transactions';
>> >> +# bug#31552/31609 idemptency is not default any longer
>> >> +set @@global.slave_exec_mode= 'IDEMPOTENT';
>> >> UPDATE t1 SET a = 5, b = 47 WHERE a = 1;
>> >> SELECT * FROM t1;
>> >> --echo **** On Master ****
>> >> @@ -17,6 +19,7 @@ SELECT * FROM t1;
>> >> #SHOW BINLOG EVENTS;
>> >> --echo **** On Slave ****
>> >> sync_slave_with_master;
>> >> +set @@global.slave_exec_mode= default;
>> >> SHOW STATUS LIKE 'Slave_retried_transactions';
>> >> SELECT * FROM t1;
>> >> source include/show_slave_status.inc;
>> >> diff -Nrup a/mysql-test/suite/rpl_ndb/r/rpl_ndb_dd_advance.result
> b/mysql-test/suite/rpl_ndb/r/rpl_ndb_dd_advance.result
>> >> --- a/mysql-test/suite/rpl_ndb/r/rpl_ndb_dd_advance.result 2007-07-04
> 23:06:25 +03:00
>> >> +++ b/mysql-test/suite/rpl_ndb/r/rpl_ndb_dd_advance.result 2007-11-30
> 13:49:25 +02:00
>> >> @@ -301,6 +301,7 @@ SELECT COUNT(*) FROM history;
>> >> COUNT(*)
>> >> 400
>> >> *** DUMP MASTER & SLAVE FOR COMPARE ********
>> >> +set @@global.slave_exec_mode='IDEMPOTENT' /* to ignore missed records
> in mysql.proc */;
>> >> *************** TEST 2 CLEANUP SECTION ********************
>> >> DROP PROCEDURE IF EXISTS tpcb.load;
>> >> DROP PROCEDURE IF EXISTS tpcb.trans;
>> >> diff -Nrup a/mysql-test/suite/rpl_ndb/r/rpl_row_basic_7ndb.result
> b/mysql-test/suite/rpl_ndb/r/rpl_row_basic_7ndb.result
>> >> --- a/mysql-test/suite/rpl_ndb/r/rpl_row_basic_7ndb.result 2007-06-27
> 15:27:31 +03:00
>> >> +++ b/mysql-test/suite/rpl_ndb/r/rpl_row_basic_7ndb.result 2007-11-30
> 13:49:25 +02:00
>> >> @@ -370,6 +370,7 @@ C1 C2
>> >> 1 3
>> >> 2 6
>> >> 3 9
>> >> +set @@global.slave_exec_mode= 'IDEMPOTENT';
>> >> --- on master: new values inserted ---
>> >> INSERT INTO t7 VALUES (1,2), (2,4), (3,6);
>> >> SELECT * FROM t7 ORDER BY C1;
>> >> @@ -377,6 +378,7 @@ C1 C2
>> >> 1 2
>> >> 2 4
>> >> 3 6
>> >> +set @@global.slave_exec_mode= 'STRICT';
>> >> --- on slave: old values should be overwritten by replicated values
> ---
>> >> SELECT * FROM t7 ORDER BY C1;
>> >> C1 C2
>> >> @@ -406,8 +408,10 @@ a b c
>> >> 2 4 6
>> >> 3 6 9
>> >> 99 99 99
>> >> +set @@global.slave_exec_mode= 'IDEMPOTENT';
>> >> --- on master ---
>> >> INSERT INTO t8 VALUES (2,4,8);
>> >> +set @@global.slave_exec_mode= default;
>> >> --- on slave ---
>> >> SELECT * FROM t8 ORDER BY a;
>> >> a b c
>> >> diff -Nrup a/mysql-test/suite/rpl_ndb/t/rpl_ndb_dd_advance.test
> b/mysql-test/suite/rpl_ndb/t/rpl_ndb_dd_advance.test
>> >> --- a/mysql-test/suite/rpl_ndb/t/rpl_ndb_dd_advance.test 2007-07-25
> 16:29:29 +03:00
>> >> +++ b/mysql-test/suite/rpl_ndb/t/rpl_ndb_dd_advance.test 2007-11-30
> 13:49:25 +02:00
>> >> @@ -373,6 +373,7 @@ SELECT COUNT(*) FROM history;
>> >> --echo ****** SLAVE ********
>> >> --sync_slave_with_master
>> >> connection slave;
>> >> +
>> >> USE tpcb;
>> >> SELECT COUNT(*) FROM history;
>> >>
>> >> @@ -381,6 +382,8 @@ SELECT COUNT(*) FROM history;
>> >> --exec $MYSQL_DUMP --compact --order-by-primary --skip-extended-insert
> tpcb account teller branch history > $MYSQLTEST_VARDIR/tmp/RPL_DD_ADV_M.sql
>> >>
>> >> --exec $MYSQL_DUMP_SLAVE --compact --order-by-primary
> --skip-extended-insert tpcb account teller branch history >
> $MYSQLTEST_VARDIR/tmp/RPL_DD_ADV_S.sql
>> >> +
>> >> +set @@global.slave_exec_mode='IDEMPOTENT' /* to ignore missed records
> in mysql.proc */;
>> >>
>> >> --echo *************** TEST 2 CLEANUP SECTION ********************
>> >> connection master;
>> >> diff -Nrup a/sql/log_event.cc b/sql/log_event.cc
>> >> --- a/sql/log_event.cc 2007-10-30 22:23:39 +02:00
>> >> +++ b/sql/log_event.cc 2007-11-30 13:49:25 +02:00
>> >> @@ -90,6 +90,27 @@ static const char *HA_ERR(int i)
>> >> case HA_ERR_LOGGING_IMPOSSIBLE: return "HA_ERR_LOGGING_IMPOSSIBLE";
>> >> case HA_ERR_CORRUPT_EVENT: return "HA_ERR_CORRUPT_EVENT";
>> >> }
>> >> + return 0;
>> >> +}
>> >> +
>> >> +/**
>> >> + macro to call from different branches of
> Rows_log_event::do_apply_event
>> >> +*/
>> >> +static void inline slave_rows_error_report(enum loglevel level, int
> ha_error,
>> >> + Relay_log_info const *rli,
> THD *thd,
>> >> + TABLE *table, const char *
> type,
>> >> + const char *log_name, ulong
> pos)
>> >> +{
>> >> + const char *handler_error= HA_ERR(ha_error);
>> >> + rli->report(level, thd->net.last_errno,
>> >> + "Could not execute %s event on table %s.%s. "
>> >> + "Error: %s (handler error %s). "
>> >> + "The event's master log and end_log_pos %s %lu",
>> >> + type, table->s->db.str,
>> >> + table->s->table_name.str,
>> >> + thd->net.last_error ? thd->net.last_error : "",
>> >> + handler_error == NULL? "<unknown>" :
> handler_error,
>> >> + log_name, pos);
>> >> }
>> >> #endif
>> >>
>> >> @@ -6060,7 +6081,6 @@ int Rows_log_event::do_apply_event(Relay
>> >> {
>> >> DBUG_ENTER("Rows_log_event::do_apply_event(Relay_log_info*)");
>> >> int error= 0;
>> >> -
>> >> /*
>> >> If m_table_id == ~0UL, then we have a dummy event that does not
>> >> contain any data. In that case, we just remove all tables in the
>> >> @@ -6106,6 +6126,24 @@ int Rows_log_event::do_apply_event(Relay
>> >> */
>> >> lex_start(thd);
>> >>
>> >> + /*
>> >> + There are a few flags that are replicated with each row event.
>> >> + Make sure to set/clear them before executing the main body of
>> >> + the event.
>> >> + */
>> >> + if (get_flags(NO_FOREIGN_KEY_CHECKS_F))
>> >> + thd->options|= OPTION_NO_FOREIGN_KEY_CHECKS;
>> >> + else
>> >> + thd->options&= ~OPTION_NO_FOREIGN_KEY_CHECKS;
>> >> +
>> >> + if (get_flags(RELAXED_UNIQUE_CHECKS_F))
>> >> + thd->options|= OPTION_RELAXED_UNIQUE_CHECKS;
>> >> + else
>> >> + thd->options&= ~OPTION_RELAXED_UNIQUE_CHECKS;
>> >> + /* A small test to verify that objects have consistent types */
>> >> + DBUG_ASSERT(sizeof(thd->options) ==
> sizeof(OPTION_RELAXED_UNIQUE_CHECKS));
>> >> +
>> >> +
>> >> while ((error= lock_tables(thd, rli->tables_to_lock,
>> >> rli->tables_to_lock_count,
> &need_reopen)))
>> >> {
>> >> @@ -6240,22 +6278,6 @@ int Rows_log_event::do_apply_event(Relay
>> >> So we call set_time(), like in SBR. Presently it changes
> nothing.
>> >> */
>> >> thd->set_time((time_t)when);
>> >> - /*
>> >> - There are a few flags that are replicated with each row event.
>> >> - Make sure to set/clear them before executing the main body of
>> >> - the event.
>> >> - */
>> >> - if (get_flags(NO_FOREIGN_KEY_CHECKS_F))
>> >> - thd->options|= OPTION_NO_FOREIGN_KEY_CHECKS;
>> >> - else
>> >> - thd->options&= ~OPTION_NO_FOREIGN_KEY_CHECKS;
>> >> -
>> >> - if (get_flags(RELAXED_UNIQUE_CHECKS_F))
>> >> - thd->options|= OPTION_RELAXED_UNIQUE_CHECKS;
>> >> - else
>> >> - thd->options&= ~OPTION_RELAXED_UNIQUE_CHECKS;
>> >> - /* A small test to verify that objects have consistent types */
>> >> - DBUG_ASSERT(sizeof(thd->options) ==
> sizeof(OPTION_RELAXED_UNIQUE_CHECKS));
>> >>
>> >> /*
>> >> Now we are in a statement and will stay in a statement until we
>> >> @@ -6288,8 +6310,9 @@ int Rows_log_event::do_apply_event(Relay
>> >> if (!get_flags(COMPLETE_ROWS_F))
>> >> bitmap_intersect(table->write_set,&m_cols);
>> >>
>> >> + this->slave_exec_mode= slave_exec_mode_options; // fix the mode
>> >> +
>> >> // Do event specific preparations
>> >> -
>> >> error= do_before_row_operations(rli);
>> >>
>> >> // row processing loop
>> >> @@ -6308,22 +6331,41 @@ int Rows_log_event::do_apply_event(Relay
>> >> {
>> >> case 0:
>> >> break;
>> >> + /*
>> >> + The following list of "idempotent" errors
>> >> + means that an error from the list might happen
>> >> + because of idempotent (more than once)
>> >> + applying of a binlog file.
>> >> + Notice, that binlog has a ddl operation its
>> >> + second applying may cause
>> >>
>> >> - /* Some recoverable errors */
>> >> + case HA_ERR_TABLE_DEF_CHANGED:
>> >> + case HA_ERR_CANNOT_ADD_FOREIGN:
>> >> +
>> >> + which are not included into to the list.
>> >> + */
>> >> case HA_ERR_RECORD_CHANGED:
>> >> case HA_ERR_RECORD_DELETED:
>> >> case HA_ERR_KEY_NOT_FOUND:
>> >> case HA_ERR_END_OF_FILE:
>> >> - /* Idempotency support: OK if tuple does not exist */
>> >> + case HA_ERR_FOUND_DUPP_KEY:
>> >> + case HA_ERR_FOUND_DUPP_UNIQUE:
>> >> + case HA_ERR_FOREIGN_DUPLICATE_KEY:
>> >> + case HA_ERR_NO_REFERENCED_ROW:
>> >> + case HA_ERR_ROW_IS_REFERENCED:
>> >> +
>> >> DBUG_PRINT("info", ("error: %s", HA_ERR(error)));
>> >> - error= 0;
>> >> + if (bit_is_set(slave_exec_mode, SLAVE_EXEC_MODE_IDEMPOTENT) ==
> 1)
>> >> + {
>> >> + if (global_system_variables.log_warnings)
>> >> + slave_rows_error_report(WARNING_LEVEL, error, rli, thd,
> table,
>> >> + get_type_str(),
>> >> + RPL_LOG_NAME, (ulong) log_pos);
>> >> + error= 0;
>> >> + }
>> >> break;
>> >> -
>> >> +
>> >> default:
>> >> - rli->report(ERROR_LEVEL, thd->net.last_errno,
>> >> - "Error in %s event: row application failed. %s",
>> >> - get_type_str(),
>> >> - thd->net.last_error ? thd->net.last_error :
> "");
>> >> thd->query_error= 1;
>> >> break;
>> >> }
>> >> @@ -6367,16 +6409,14 @@ int Rows_log_event::do_apply_event(Relay
>> >> */
>> >> if (rli->tables_to_lock && get_flags(STMT_END_F))
>> >> const_cast<Relay_log_info*>(rli)->clear_tables_to_lock();
>> >> -
>> >> +
>> >> if (error)
>> >> { /* error has occured during the transaction */
>> >> - rli->report(ERROR_LEVEL, thd->net.last_errno,
>> >> - "Error in %s event: error during transaction execution
> "
>> >> - "on table %s.%s. %s",
>> >> - get_type_str(), table->s->db.str,
>> >> - table->s->table_name.str,
>> >> - thd->net.last_error ? thd->net.last_error : "");
>> >> -
>> >> + slave_rows_error_report(ERROR_LEVEL, error, rli, thd, table,
>> >> + get_type_str(), RPL_LOG_NAME, (ulong)
> log_pos);
>> >> + }
>> >> + if (error)
>> >> + {
>> >> /*
>> >> If one day we honour --skip-slave-errors in row-based
> replication, and
>> >> the error should be skipped, then we would clear mappings,
> rollback,
>> >> @@ -6488,6 +6528,7 @@ Rows_log_event::do_update_pos(Relay_log_
>> >> */
>> >>
>> >> thd->reset_current_stmt_binlog_row_based();
>> >> +
>> >> rli->cleanup_context(thd, 0);
>> >> if (error == 0)
>> >> {
>> >> @@ -7170,43 +7211,50 @@ Write_rows_log_event::do_before_row_oper
>> >> {
>> >> int error= 0;
>> >>
>> >> - /*
>> >> - We are using REPLACE semantics and not INSERT IGNORE semantics
>> >> - when writing rows, that is: new rows replace old rows. We need to
>> >> - inform the storage engine that it should use this behaviour.
>> >> + /**
>> >> + todo: to introduce a property for handler or event which forces
>> >> + applying the event in idempotent fashion.
>> >> */
>> >> + if (bit_is_set(slave_exec_mode, SLAVE_EXEC_MODE_IDEMPOTENT) == 1 ||
>> >> + m_table->s->db_type()->db_type == DB_TYPE_NDBCLUSTER)
>> >> + {
>> >> + /*
>> >> + We are using REPLACE semantics and not INSERT IGNORE semantics
>> >> + when writing rows, that is: new rows replace old rows. We need
> to
>> >> + inform the storage engine that it should use this behaviour.
>> >> + */
>> >> +
>> >> + /* Tell the storage engine that we are using REPLACE semantics. */
>> >> + thd->lex->duplicates= DUP_REPLACE;
>> >> +
>> >> + /*
>> >> + Pretend we're executing a REPLACE command: this is needed for
>> >> + InnoDB and NDB Cluster since they are not (properly) checking
> the
>> >> + lex->duplicates flag.
>> >> + */
>> >> + thd->lex->sql_command= SQLCOM_REPLACE;
>> >> + /*
>> >> + Do not raise the error flag in case of hitting to an unique
> attribute
>> >> + */
>> >> + m_table->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
>> >> + /*
>> >> + NDB specific: update from ndb master wrapped as Write_rows
>> >> + so that the event should be applied to replace slave's row
>> >> + */
>> >> + m_table->file->extra(HA_EXTRA_WRITE_CAN_REPLACE);
>> >> + /*
>> >> + NDB specific: if update from ndb master wrapped as Write_rows
>> >> + does not find the row it's assumed idempotent binlog applying
>> >> + is taking place; don't raise the error.
>> >> + */
>> >> + m_table->file->extra(HA_EXTRA_IGNORE_NO_KEY);
>> >> + /*
>> >> + TODO: the cluster team (Tomas?) says that it's better if the
> engine knows
>> >> + how many rows are going to be inserted, then it can allocate
> needed memory
>> >> + from the start.
>> >> + */
>> >> + }
>> >>
>> >> - /* Tell the storage engine that we are using REPLACE semantics. */
>> >> - thd->lex->duplicates= DUP_REPLACE;
>> >> -
>> >> - /*
>> >> - Pretend we're executing a REPLACE command: this is needed for
>> >> - InnoDB and NDB Cluster since they are not (properly) checking the
>> >> - lex->duplicates flag.
>> >> - */
>> >> - thd->lex->sql_command= SQLCOM_REPLACE;
>> >> - /*
>> >> - Do not raise the error flag in case of hitting to an unique
> attribute
>> >> - */
>> >> - m_table->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
>> >> - /*
>> >> - NDB specific: update from ndb master wrapped as Write_rows
>> >> - */
>> >> - /*
>> >> - so that the event should be applied to replace slave's row
>> >> - */
>> >> - m_table->file->extra(HA_EXTRA_WRITE_CAN_REPLACE);
>> >> - /*
>> >> - NDB specific: if update from ndb master wrapped as Write_rows
>> >> - does not find the row it's assumed idempotent binlog applying
>> >> - is taking place; don't raise the error.
>> >> - */
>> >> - m_table->file->extra(HA_EXTRA_IGNORE_NO_KEY);
>> >> - /*
>> >> - TODO: the cluster team (Tomas?) says that it's better if the engine
> knows
>> >> - how many rows are going to be inserted, then it can allocate needed
> memory
>> >> - from the start.
>> >> - */
>> >> m_table->file->ha_start_bulk_insert(0);
>> >> /*
>> >> We need TIMESTAMP_NO_AUTO_SET otherwise ha_write_row() will not use
> fill
>> >> @@ -7228,18 +7276,23 @@ Write_rows_log_event::do_before_row_oper
>> >> }
>> >>
>> >> int
>> >> -Write_rows_log_event::do_after_row_operations(const
> Slave_reporting_capability *const,
>> >> +Write_rows_log_event::do_after_row_operations(const
> Slave_reporting_capability *const,
>> >> int error)
>> >> {
>> >> int local_error= 0;
>> >> - m_table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
>> >> - m_table->file->extra(HA_EXTRA_WRITE_CANNOT_REPLACE);
>> >> - /*
>> >> - reseting the extra with
>> >> - table->file->extra(HA_EXTRA_NO_IGNORE_NO_KEY);
>> >> - fires bug#27077
>> >> - todo: explain or fix
>> >> - */
>> >> + if (bit_is_set(slave_exec_mode, SLAVE_EXEC_MODE_IDEMPOTENT) == 1 ||
>> >> + m_table->s->db_type()->db_type == DB_TYPE_NDBCLUSTER)
>> >> + {
>> >> + m_table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
>> >> + m_table->file->extra(HA_EXTRA_WRITE_CANNOT_REPLACE);
>> >> + /*
>> >> + resetting the extra with
>> >> + table->file->extra(HA_EXTRA_NO_IGNORE_NO_KEY);
>> >> + fires bug#27077
>> >> + explanation: file->reset() performs this duty
>> >> + ultimately. Still todo: fix
>> >> + */
>> >> + }
>> >> if ((local_error= m_table->file->ha_end_bulk_insert()))
>> >> {
>> >> m_table->file->print_error(local_error, MYF(0));
>> >> @@ -7358,23 +7411,22 @@ Rows_log_event::write_row(const Relay_lo
>> >>
>> >> while ((error=
> table->file->ha_write_row(table->record[0])))
>> >> {
>> >> - if (error == HA_ERR_LOCK_DEADLOCK || error ==
> HA_ERR_LOCK_WAIT_TIMEOUT)
>> >> - {
>> >> - table->file->print_error(error, MYF(0)); /* to check at
> exec_relay_log_event */
>> >> - DBUG_RETURN(error);
>> >> - }
>> >> - if ((keynum= table->file->get_dup_key(error)) < 0)
>> >> + if (error == HA_ERR_LOCK_DEADLOCK ||
>> >> + error == HA_ERR_LOCK_WAIT_TIMEOUT ||
>> >> + (keynum= table->file->get_dup_key(error)) < 0 ||
>> >> + !overwrite)
>> >> {
>> >> - DBUG_PRINT("info",("Can't locate duplicate key (get_dup_key
> returns %d)",keynum));
>> >> - table->file->print_error(error, MYF(0));
>> >> + DBUG_PRINT("info",("get_dup_key returns %d)", keynum));
>> >> /*
>> >> - We failed to retrieve the duplicate key
>> >> + Deadlock, waiting for lock or just an error from the handler
>> >> + such as HA_ERR_FOUND_DUPP_KEY when overwrite is false.
>> >> + Retrieval of the duplicate key number may fail
>> >> - either because the error was not "duplicate key" error
>> >> - or because the information which key is not available
>> >> */
>> >> + table->file->print_error(error, MYF(0));
>> >> DBUG_RETURN(error);
>> >> }
>> >> -
>> >> /*
>> >> We need to retrieve the old row into record[1] to be able to
>> >> either update or delete the offending record. We either:
>> >> @@ -7512,11 +7564,13 @@ int
>> >> Write_rows_log_event::do_exec_row(const Relay_log_info *const rli)
>> >> {
>> >> DBUG_ASSERT(m_table != NULL);
>> >> - int error= write_row(rli, TRUE /* overwrite */);
>> >> -
>> >> + int error=
>> >> + write_row(rli, /* if 1 then overwrite */
>> >> + bit_is_set(slave_exec_mode, SLAVE_EXEC_MODE_IDEMPOTENT)
> == 1);
>> >> +
>> >> if (error && !thd->net.last_errno)
>> >> thd->net.last_errno= error;
>> >> -
>> >> +
>> >> return error;
>> >> }
>> >>
>> >> diff -Nrup a/sql/log_event.h b/sql/log_event.h
>> >> --- a/sql/log_event.h 2007-10-30 10:51:08 +02:00
>> >> +++ b/sql/log_event.h 2007-11-30 13:49:26 +02:00
>> >> @@ -809,6 +809,12 @@ public:
>> >>
>> >> bool cache_stmt;
>> >>
>> >> + /**
>> >> + A storage to cache the global system variable's value.
>> >> + Handling of a separate event will be governed its member.
>> >> + */
>> >> + ulong slave_exec_mode;
>> >> +
>> >> #ifndef MYSQL_CLIENT
>> >> THD* thd;
>> >>
>> >> diff -Nrup a/sql/mysql_priv.h b/sql/mysql_priv.h
>> >> --- a/sql/mysql_priv.h 2007-10-23 18:10:26 +03:00
>> >> +++ b/sql/mysql_priv.h 2007-11-30 13:49:26 +02:00
>> >> @@ -1813,6 +1813,7 @@ extern uint volatile thread_count, threa
>> >> extern my_bool opt_sql_bin_update, opt_safe_user_create,
> opt_no_mix_types;
>> >> extern my_bool opt_safe_show_db, opt_local_infile,
> opt_myisam_use_mmap;
>> >> extern my_bool opt_slave_compressed_protocol, use_temp_pool;
>> >> +extern ulong slave_exec_mode_options;
>> >> extern my_bool opt_readonly, lower_case_file_system;
>> >> extern my_bool opt_enable_named_pipe, opt_sync_frm,
> opt_allow_suspicious_udfs;
>> >> extern my_bool opt_secure_auth;
>> >> diff -Nrup a/sql/mysqld.cc b/sql/mysqld.cc
>> >> --- a/sql/mysqld.cc 2007-10-30 10:51:08 +02:00
>> >> +++ b/sql/mysqld.cc 2007-11-30 13:49:26 +02:00
>> >> @@ -445,6 +445,8 @@ ulong thread_stack, what_to_log;
>> >> ulong query_buff_size, slow_launch_time, slave_open_temp_tables;
>> >> ulong open_files_limit, max_binlog_size, max_relay_log_size;
>> >> ulong slave_net_timeout, slave_trans_retries;
>> >> +ulong slave_exec_mode_options;
>> >> +const char *slave_exec_mode_str= "STRICT";
>> >> ulong thread_cache_size=0, thread_pool_size= 0;
>> >> ulong binlog_cache_size=0, max_binlog_cache_size=0;
>> >> ulong query_cache_size=0;
>> >> @@ -5101,7 +5103,8 @@ enum options_mysqld
>> >> OPT_SECURE_FILE_PRIV,
>> >> OPT_MIN_EXAMINED_ROW_LIMIT,
>> >> OPT_LOG_SLOW_SLAVE_STATEMENTS,
>> >> - OPT_OLD_MODE
>> >> + OPT_OLD_MODE,
>> >> + OPT_SLAVE_EXEC_MODE
>> >> };
>> >>
>> >>
>> >> @@ -5799,8 +5802,11 @@ replicating a LOAD DATA INFILE command."
>> >> (uchar**) &slave_load_tmpdir, (uchar**) &slave_load_tmpdir,
> 0, GET_STR_ALLOC,
>> >> REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
>> >> {"slave-skip-errors", OPT_SLAVE_SKIP_ERRORS,
>> >> - "Tells the slave thread to continue replication when a query returns
> an error from the provided list.",
>> >> + "Tells the slave thread to continue replication when a query event
> returns an error from the provided list.",
>> >> 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
>> >> + {"slave-exec-mode", OPT_SLAVE_EXEC_MODE,
>> >> + "Modes for how replication events should be executed. Legal values
> are STRICT (default) and IDEMPOTENT. In IDEMPOTENT mode, replication will not stop for
> operations that are idempotent. In STRICT mode, replication will stop on any unexpected
> difference between the master and the slave.",
>> >> + (uchar**) &slave_exec_mode_str, (uchar**)
> &slave_exec_mode_str, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
>> >> #endif
>> >> {"slow-query-log", OPT_SLOW_LOG,
>> >> "Enable|disable slow query log", (uchar**) &opt_slow_log,
>> >> @@ -7109,6 +7115,9 @@ static void mysql_init_variables(void)
>> >>
>> >> /* Things with default values that are not zero */
>> >> delay_key_write_options= (uint) DELAY_KEY_WRITE_ON;
>> >> + slave_exec_mode_options= 0;
>> >> + slave_exec_mode_options= (uint)
>> >> + find_bit_type_or_exit(slave_exec_mode_str,
> &slave_exec_mode_typelib, NULL);
>> >> opt_specialflag= SPECIAL_ENGLISH;
>> >> unix_sock= ip_sock= INVALID_SOCKET;
>> >> mysql_home_ptr= mysql_home;
>> >> @@ -7318,6 +7327,10 @@ mysqld_get_one_option(int optid,
>> >> case OPT_SLAVE_SKIP_ERRORS:
>> >> init_slave_skip_errors(argument);
>> >> break;
>> >> + case OPT_SLAVE_EXEC_MODE:
>> >> + slave_exec_mode_options= (uint)
>> >> + find_bit_type_or_exit(argument, &slave_exec_mode_typelib,
> "");
>> >> + break;
>> >> #endif
>> >> case OPT_SAFEMALLOC_MEM_LIMIT:
>> >> #if !defined(DBUG_OFF) && defined(SAFEMALLOC)
>> >> @@ -7863,6 +7876,8 @@ static void get_options(int *argc,char *
>> >> }
>> >> /* Set global MyISAM variables from delay_key_write_options */
>> >> fix_delay_key_write((THD*) 0, OPT_GLOBAL);
>> >> + /* Set global slave_exec_mode from its option */
>> >> + fix_slave_exec_mode((THD*) 0, OPT_GLOBAL);
>> >>
>> >> #ifndef EMBEDDED_LIBRARY
>> >> if (mysqld_chroot)
>> >> diff -Nrup a/sql/rpl_rli.cc b/sql/rpl_rli.cc
>> >> --- a/sql/rpl_rli.cc 2007-10-13 23:12:47 +03:00
>> >> +++ b/sql/rpl_rli.cc 2007-11-30 13:49:27 +02:00
>> >> @@ -1160,6 +1160,11 @@ void Relay_log_info::cleanup_context(THD
>> >> close_thread_tables(thd);
>> >> clear_tables_to_lock();
>> >> clear_flag(IN_STMT);
>> >> + /*
>> >> + Cleanup for the flags that have been set at do_apply_event.
>> >> + */
>> >> + thd->options&= ~OPTION_NO_FOREIGN_KEY_CHECKS;
>> >> + thd->options&= ~OPTION_RELAXED_UNIQUE_CHECKS;
>> >> last_event_start_time= 0;
>> >> DBUG_VOID_RETURN;
>> >> }
>> >> diff -Nrup a/sql/set_var.cc b/sql/set_var.cc
>> >> --- a/sql/set_var.cc 2007-10-23 18:10:27 +03:00
>> >> +++ b/sql/set_var.cc 2007-11-30 13:49:27 +02:00
>> >> @@ -88,6 +88,16 @@ TYPELIB delay_key_write_typelib=
>> >> delay_key_write_type_names, NULL
>> >> };
>> >>
>> >> +const char *slave_exec_mode_names[]=
>> >> +{ "STRICT", "IDEMPOTENT", NullS };
>> >> +static const unsigned int slave_exec_mode_names_len[]=
>> >> +{ sizeof("STRICT") - 1, sizeof("IDEMPOTENT") - 1, 0 };
>> >> +TYPELIB slave_exec_mode_typelib=
>> >> +{
>> >> + array_elements(slave_exec_mode_names)-1, "",
>> >> + slave_exec_mode_names, (unsigned int *) slave_exec_mode_names_len
>> >> +};
>> >> +
>> >> static int sys_check_ftb_syntax(THD *thd, set_var *var);
>> >> static bool sys_update_ftb_syntax(THD *thd, set_var * var);
>> >> static void sys_default_ftb_syntax(THD *thd, enum_var_type type);
>> >> @@ -408,6 +418,11 @@ static sys_var_const_str_ptr sys_secure_
>> >> static sys_var_long_ptr sys_server_id(&vars, "server_id",
> &server_id, fix_server_id);
>> >> static sys_var_bool_ptr sys_slave_compressed_protocol(&vars,
> "slave_compressed_protocol",
>> >> &opt_slave_compressed_protocol);
>> >> +static sys_var_set_slave_mode slave_exec_mode(&vars,
>> >> + "slave_exec_mode",
>> >> +
> &slave_exec_mode_options,
>> >> +
> &slave_exec_mode_typelib,
>> >> + 0);
>> >> static sys_var_long_ptr sys_slow_launch_time(&vars,
> "slow_launch_time",
>> >> &slow_launch_time);
>> >> static sys_var_thd_ulong sys_sort_buffer(&vars,
> "sort_buffer_size",
>> >> @@ -981,6 +996,73 @@ extern void fix_delay_key_write(THD *thd
>> >> }
>> >> }
>> >>
>> >> +bool sys_var_set::update(THD *thd, set_var *var)
>> >> +{
>> >> + *value= var->save_result.ulong_value;
>> >> + return 0;
>> >> +};
>> >> +
>> >> +uchar *sys_var_set::value_ptr(THD *thd, enum_var_type type,
>> >> + LEX_STRING *base)
>> >> +{
>> >> + char buff[256];
>> >> + String tmp(buff, sizeof(buff), &my_charset_latin1);
>> >> + ulong length;
>> >> + ulong val= *value;
>> >> +
>> >> + tmp.length(0);
>> >> + for (uint i= 0; val; val>>= 1, i++)
>> >> + {
>> >> + if (val & 1)
>> >> + {
>> >> + tmp.append(enum_names->type_names[i],
>> >> + enum_names->type_lengths[i]);
>> >> + tmp.append(',');
>> >> + }
>> >> + }
>> >> +
>> >> + if ((length= tmp.length()))
>> >> + length--;
>> >> + return (uchar*) thd->strmake(tmp.ptr(), length);
>> >> +}
>> >> +
>> >> +void sys_var_set_slave_mode::set_default(THD *thd, enum_var_type type)
>> >> +{
>> >> + slave_exec_mode_options= 0;
>> >> + bit_do_set(slave_exec_mode_options, SLAVE_EXEC_MODE_STRICT);
>> >> +}
>> >> +
>> >> +bool sys_var_set_slave_mode::update(THD *thd, set_var *var)
>> >> +{
>> >> + my_bool rc;
>> >> + pthread_mutex_lock(&LOCK_global_system_variables);
>> >> + rc= sys_var_set::update(thd, var);
>> >> + fix_slave_exec_mode(thd, OPT_GLOBAL);
>> >> + pthread_mutex_unlock(&LOCK_global_system_variables);
>> >> + return rc;
>> >> +}
>> >> +
>> >> +void fix_slave_exec_mode(THD *thd, enum_var_type type)
>> >> +{
>> >> + DBUG_ENTER("fix_slave_exec_mode");
>> >> + compile_time_assert(sizeof(slave_exec_mode_options) * CHAR_BIT
>> >> + > SLAVE_EXEC_MODE_LAST_BIT - 1);
>> >> + if (bit_is_set(slave_exec_mode_options, SLAVE_EXEC_MODE_STRICT) == 1
> &&
>> >> + bit_is_set(slave_exec_mode_options, SLAVE_EXEC_MODE_IDEMPOTENT)
> == 1)
>> >> + {
>> >> + if (thd)
>> >> + push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
>> >> + ER_SLAVE_AMBIGOUS_EXEC_MODE,
> ER(ER_SLAVE_AMBIGOUS_EXEC_MODE),
>> >> + "STRICT will be used");
>> >> + else
>> >> + sql_print_warning("Ambiguous slave modes combination."
>> >> + " STRICT will be used");
>> >> + bit_do_clear(slave_exec_mode_options, SLAVE_EXEC_MODE_IDEMPOTENT);
>> >> + }
>> >> + if (bit_is_set(slave_exec_mode_options, SLAVE_EXEC_MODE_IDEMPOTENT)
> == 0)
>> >> + bit_do_set(slave_exec_mode_options, SLAVE_EXEC_MODE_STRICT);
>> >> + DBUG_VOID_RETURN;
>> >> +}
>> >>
>> >> bool sys_var_thd_binlog_format::is_readonly() const
>> >> {
>> >> diff -Nrup a/sql/set_var.h b/sql/set_var.h
>> >> --- a/sql/set_var.h 2007-08-13 16:11:12 +03:00
>> >> +++ b/sql/set_var.h 2007-11-30 13:49:27 +02:00
>> >> @@ -30,7 +30,8 @@ class sys_var_pluginvar; /* opaque */
>> >> typedef struct system_variables SV;
>> >> typedef struct my_locale_st MY_LOCALE;
>> >>
>> >> -extern TYPELIB bool_typelib, delay_key_write_typelib,
> sql_mode_typelib;
>> >> +extern TYPELIB bool_typelib, delay_key_write_typelib,
> sql_mode_typelib,
>> >> + slave_exec_mode_typelib;
>> >>
>> >> typedef int (*sys_check_func)(THD *, set_var *);
>> >> typedef bool (*sys_update_func)(THD *, set_var *);
>> >> @@ -771,6 +772,41 @@ public:
>> >> };
>> >>
>> >>
>> >> +class sys_var_set :public sys_var
>> >> +{
>> >> +protected:
>> >> + ulong *value;
>> >> + TYPELIB *enum_names;
>> >> +public:
>> >> + sys_var_set(sys_var_chain *chain, const char *name_arg, ulong
> *value_arg,
>> >> + TYPELIB *typelib, sys_after_update_func func)
>> >> + :sys_var(name_arg, func), value(value_arg), enum_names(typelib)
>> >> + { chain_sys_var(chain); }
>> >> + bool check(THD *thd, set_var *var)
>> >> + {
>> >> + return check_set(thd, var, enum_names);
>> >> + }
>> >> + virtual void set_default(THD *thd, enum_var_type type)
>> >> + {
>> >> + *value= 0;
>> >> + }
>> >> + bool update(THD *thd, set_var *var);
>> >> + uchar *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base);
>> >> + bool check_update_type(Item_result type) { return 0; }
>> >> + SHOW_TYPE show_type() { return SHOW_CHAR; }
>> >> +};
>> >> +
>> >> +class sys_var_set_slave_mode :public sys_var_set
>> >> +{
>> >> +public:
>> >> + sys_var_set_slave_mode(sys_var_chain *chain, const char *name_arg,
>> >> + ulong *value_arg,
>> >> + TYPELIB *typelib, sys_after_update_func func)
> :
>> >> + sys_var_set(chain, name_arg, value_arg, typelib, func) {}
>> >> + void set_default(THD *thd, enum_var_type type);
>> >> + bool update(THD *thd, set_var *var);
>> >> +};
>> >> +
>> >> class sys_var_log_output :public sys_var
>> >> {
>> >> ulong *value;
>> >> @@ -1189,6 +1225,7 @@ sys_var *find_sys_var(THD *thd, const ch
>> >> int sql_set_variables(THD *thd, List<set_var_base> *var_list);
>> >> bool not_all_support_one_shot(List<set_var_base> *var_list);
>> >> void fix_delay_key_write(THD *thd, enum_var_type type);
>> >> +void fix_slave_exec_mode(THD *thd, enum_var_type type);
>> >> ulong fix_sql_mode(ulong sql_mode);
>> >> extern sys_var_const_str sys_charset_system;
>> >> extern sys_var_str sys_init_connect;
>> >> diff -Nrup a/sql/share/errmsg.txt b/sql/share/errmsg.txt
>> >> --- a/sql/share/errmsg.txt 2007-10-17 11:13:54 +03:00
>> >> +++ b/sql/share/errmsg.txt 2007-11-30 13:49:28 +02:00
>> >> @@ -6112,3 +6112,5 @@ ER_TRG_CANT_OPEN_TABLE
>> >>
>> >> ER_CANT_CREATE_SROUTINE
>> >> eng "Cannot create stored routine `%-.64s`. Check warnings"
>> >> +ER_SLAVE_AMBIGOUS_EXEC_MODE
>> >> + eng "Ambiguous slave modes combination. %s"
>> >> diff -Nrup a/sql/sql_class.h b/sql/sql_class.h
>> >> --- a/sql/sql_class.h 2007-11-06 14:03:54 +02:00
>> >> +++ b/sql/sql_class.h 2007-11-30 13:49:27 +02:00
>> >> @@ -38,6 +38,9 @@ enum enum_ha_read_modes { RFIRST, RNEXT,
>> >> enum enum_duplicates { DUP_ERROR, DUP_REPLACE, DUP_UPDATE };
>> >> enum enum_delay_key_write { DELAY_KEY_WRITE_NONE, DELAY_KEY_WRITE_ON,
>> >> DELAY_KEY_WRITE_ALL };
>> >> +enum enum_slave_exec_mode { SLAVE_EXEC_MODE_STRICT,
>> >> + SLAVE_EXEC_MODE_IDEMPOTENT,
>> >> + SLAVE_EXEC_MODE_LAST_BIT};
>> >> enum enum_mark_columns
>> >> { MARK_COLUMNS_NONE, MARK_COLUMNS_READ, MARK_COLUMNS_WRITE};
>> >>
>> >>
>> >> --
>> >> MySQL Code Commits Mailing List
>> >> For list archives: http://lists.mysql.com/commits
>> >> To unsubscribe: http://lists.mysql.com/commits?unsub=1
>> >
>> > --
>> > Dr Lars Thalmann, Team Lead, Replication & Backup, www.mysql.com
>>
>>
>> --
>> Andrei Elkin, Software Developer, PhD
>> MySQL Finland Oy, Helsinki, Finland, www.mysql.com
>>
>> Are you MySQL certified? www.mysql.com/certification
>
> --
> Dr Lars Thalmann, Team Lead, Replication & Backup, www.mysql.com