summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorunknown <knielsen@knielsen-hq.org>2011-01-10 14:53:09 +0100
committerunknown <knielsen@knielsen-hq.org>2011-01-10 14:53:09 +0100
commit32379aeba9222d255f151bdea4954932fe784021 (patch)
tree0cd3e1bcd46f1bfcfd44198f3cb01c4d631dc5da
parentd653a80d2a62669243477b82757068a1b7874dbb (diff)
downloadmariadb-git-32379aeba9222d255f151bdea4954932fe784021.tar.gz
Merge Percona patch MWL#47 into mariadb 5.2-percona.
This patch adds options to annotate the binlog (and the mysqlbinlog output) with the original SQL query for queries that are logged using row-based replication.
-rw-r--r--client/client_priv.h1
-rw-r--r--client/mysqlbinlog.cc134
-rw-r--r--mysql-test/extra/binlog_tests/mix_innodb_myisam_binlog.test9
-rw-r--r--mysql-test/extra/rpl_tests/rpl_deadlock.test4
-rw-r--r--mysql-test/extra/rpl_tests/rpl_log.test1
-rw-r--r--mysql-test/extra/rpl_tests/rpl_row_annotate.test155
-rw-r--r--mysql-test/include/binlog_start_pos.inc26
-rw-r--r--mysql-test/include/show_binlog_events.inc2
-rw-r--r--mysql-test/include/show_binlog_events2.inc2
-rw-r--r--mysql-test/r/ctype_cp932_binlog_stm.result2
-rw-r--r--mysql-test/r/mysqlbinlog.result19
-rw-r--r--mysql-test/std_data/words3.dat66
-rw-r--r--mysql-test/suite/binlog/r/binlog_row_annotate.result1219
-rw-r--r--mysql-test/suite/binlog/r/binlog_stm_binlog.result4
-rw-r--r--mysql-test/suite/binlog/t/binlog_incident.test3
-rw-r--r--mysql-test/suite/binlog/t/binlog_killed.test4
-rw-r--r--mysql-test/suite/binlog/t/binlog_killed_simulate.test3
-rw-r--r--mysql-test/suite/binlog/t/binlog_row_annotate-master.opt1
-rw-r--r--mysql-test/suite/binlog/t/binlog_row_annotate.test189
-rw-r--r--mysql-test/suite/maria/r/maria-connect.result8
-rw-r--r--mysql-test/suite/maria/t/maria-connect.test7
-rw-r--r--mysql-test/suite/rpl/r/rpl_deadlock_innodb.result4
-rw-r--r--mysql-test/suite/rpl/r/rpl_row_annotate_do.result144
-rw-r--r--mysql-test/suite/rpl/r/rpl_row_annotate_dont.result126
-rw-r--r--mysql-test/suite/rpl/r/rpl_row_conflicts.result4
-rw-r--r--mysql-test/suite/rpl/t/rpl_row_annotate_do-slave.opt1
-rw-r--r--mysql-test/suite/rpl/t/rpl_row_annotate_do.test16
-rw-r--r--mysql-test/suite/rpl/t/rpl_row_annotate_dont-slave.opt1
-rw-r--r--mysql-test/suite/rpl/t/rpl_row_annotate_dont.test9
-rw-r--r--mysql-test/suite/rpl/t/rpl_row_flsh_tbls.test3
-rw-r--r--mysql-test/suite/rpl/t/rpl_row_mysqlbinlog.test18
-rw-r--r--mysql-test/suite/rpl/t/rpl_stm_flsh_tbls.test3
-rw-r--r--mysql-test/t/ctype_cp932_binlog_stm.test8
-rw-r--r--mysql-test/t/mysqlbinlog-master.opt1
-rw-r--r--mysql-test/t/mysqlbinlog.test99
-rw-r--r--mysql-test/t/mysqlbinlog2.test34
-rw-r--r--sql/handler.cc9
-rw-r--r--sql/log.cc24
-rw-r--r--sql/log.h3
-rw-r--r--sql/log_event.cc164
-rw-r--r--sql/log_event.h62
-rw-r--r--sql/mysql_priv.h4
-rw-r--r--sql/mysqld.cc15
-rw-r--r--sql/rpl_rli.cc4
-rw-r--r--sql/rpl_rli.h38
-rw-r--r--sql/set_var.cc3
-rw-r--r--sql/slave.cc63
-rw-r--r--sql/slave.h1
-rw-r--r--sql/sql_binlog.cc2
-rw-r--r--sql/sql_class.h4
-rw-r--r--sql/sql_insert.cc5
-rw-r--r--sql/sql_repl.cc74
52 files changed, 2649 insertions, 156 deletions
diff --git a/client/client_priv.h b/client/client_priv.h
index f6bde7a594c..0b617c564df 100644
--- a/client/client_priv.h
+++ b/client/client_priv.h
@@ -95,5 +95,6 @@ enum options_client
OPT_REWRITE_DB,
OPT_PLUGIN_DIR,
OPT_DEFAULT_PLUGIN,
+ OPT_SKIP_ANNOTATE_ROWS_EVENTS,
OPT_MAX_CLIENT_OPTION /* should be always the last */
};
diff --git a/client/mysqlbinlog.cc b/client/mysqlbinlog.cc
index 420042e6055..4018cd3908f 100644
--- a/client/mysqlbinlog.cc
+++ b/client/mysqlbinlog.cc
@@ -107,6 +107,7 @@ static ulonglong rec_count= 0;
static short binlog_flags = 0;
static MYSQL* mysql = NULL;
static const char* dirname_for_local_load= 0;
+static bool opt_skip_annotate_rows_events= 0;
/**
Pointer to the Format_description_log_event of the currently active binlog.
@@ -128,6 +129,70 @@ enum Exit_status {
OK_STOP
};
+/**
+ Pointer to the last read Annotate_rows_log_event. Having read an
+ Annotate_rows event, we should not print it immediatedly because all
+ subsequent rbr events can be filtered away, and have to keep it for a while.
+ Also because of that when reading a remote Annotate event we have to keep
+ its binary log representation in a separately allocated buffer.
+*/
+static Annotate_rows_log_event *annotate_event= NULL;
+
+void free_annotate_event()
+{
+ if (annotate_event)
+ {
+ delete annotate_event;
+ annotate_event= 0;
+ }
+}
+
+Log_event* read_remote_annotate_event(uchar* net_buf, ulong event_len,
+ const char **error_msg)
+{
+ uchar *event_buf;
+ Log_event* event;
+
+ if (!(event_buf= (uchar*) my_malloc(event_len + 1, MYF(MY_WME))))
+ {
+ error("Out of memory");
+ return 0;
+ }
+
+ memcpy(event_buf, net_buf, event_len);
+ event_buf[event_len]= 0;
+
+ if (!(event= Log_event::read_log_event((const char*) event_buf, event_len,
+ error_msg, glob_description_event)))
+ {
+ my_free(event_buf, MYF(0));
+ return 0;
+ }
+ /*
+ Ensure the event->temp_buf is pointing to the allocated buffer.
+ (TRUE = free temp_buf on the event deletion)
+ */
+ event->register_temp_buf((char*)event_buf, TRUE);
+
+ return event;
+}
+
+void keep_annotate_event(Annotate_rows_log_event* event)
+{
+ free_annotate_event();
+ annotate_event= event;
+}
+
+void print_annotate_event(PRINT_EVENT_INFO *print_event_info)
+{
+ if (annotate_event)
+ {
+ annotate_event->print(result_file, print_event_info);
+ delete annotate_event; // the event should not be printed more than once
+ annotate_event= 0;
+ }
+}
+
static Exit_status dump_local_log_entries(PRINT_EVENT_INFO *print_event_info,
const char* logname);
static Exit_status dump_remote_log_entries(PRINT_EVENT_INFO *print_event_info,
@@ -927,6 +992,19 @@ Exit_status process_event(PRINT_EVENT_INFO *print_event_info, Log_event *ev,
my_free(fname, MYF(MY_WME));
break;
}
+ case ANNOTATE_ROWS_EVENT:
+ if (!opt_skip_annotate_rows_events)
+ {
+ /*
+ We don't print Annotate event just now because all subsequent
+ rbr-events can be filtered away. Instead we'll keep the event
+ till it will be printed together with the first not filtered
+ away Table map or the last rbr will be processed.
+ */
+ keep_annotate_event((Annotate_rows_log_event*) ev);
+ destroy_evt= FALSE;
+ }
+ break;
case TABLE_MAP_EVENT:
{
Table_map_log_event *map= ((Table_map_log_event *)ev);
@@ -936,6 +1014,13 @@ Exit_status process_event(PRINT_EVENT_INFO *print_event_info, Log_event *ev,
destroy_evt= FALSE;
goto end;
}
+ /*
+ The Table map is to be printed, so it's just the time when we may
+ print the kept Annotate event (if there is any).
+ print_annotate_event() also deletes the kept Annotate event.
+ */
+ print_annotate_event(print_event_info);
+
size_t len_to= 0;
const char* db_to= binlog_filter->get_rewrite_db(map->get_db_name(), &len_to);
if (len_to && map->rewrite_db(db_to, len_to, glob_description_event))
@@ -972,6 +1057,13 @@ Exit_status process_event(PRINT_EVENT_INFO *print_event_info, Log_event *ev,
if (print_event_info->m_table_map_ignored.count() > 0)
print_event_info->m_table_map_ignored.clear_tables();
+ /*
+ If there is a kept Annotate event and all corresponding
+ rbr-events were filtered away, the Annotate event was not
+ freed and it is just the time to do it.
+ */
+ free_annotate_event();
+
/*
One needs to take into account an event that gets
filtered but was last event in the statement. If this is
@@ -1206,6 +1298,11 @@ that may lead to an endless loop.",
"Updates to a database with a different name than the original. \
Example: rewrite-db='from->to'.",
0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ {"skip-annotate-rows-events", OPT_SKIP_ANNOTATE_ROWS_EVENTS,
+ "Don't print Annotate_rows events stored in the binary log.",
+ (uchar**) &opt_skip_annotate_rows_events,
+ (uchar**) &opt_skip_annotate_rows_events,
+ 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
};
@@ -1677,6 +1774,8 @@ static Exit_status dump_remote_log_entries(PRINT_EVENT_INFO *print_event_info,
cast to uint32.
*/
int4store(buf, (uint32)start_position);
+ if (!opt_skip_annotate_rows_events)
+ binlog_flags|= BINLOG_SEND_ANNOTATE_ROWS_EVENT;
int2store(buf + BIN_LOG_HEADER_SIZE, binlog_flags);
size_t tlen = strlen(logname);
@@ -1709,18 +1808,30 @@ static Exit_status dump_remote_log_entries(PRINT_EVENT_INFO *print_event_info,
break; // end of data
DBUG_PRINT("info",( "len: %lu net->read_pos[5]: %d\n",
len, net->read_pos[5]));
- if (!(ev= Log_event::read_log_event((const char*) net->read_pos + 1 ,
- len - 1, &error_msg,
- glob_description_event)))
+ if (net->read_pos[5] == ANNOTATE_ROWS_EVENT)
{
- error("Could not construct log event object: %s", error_msg);
- DBUG_RETURN(ERROR_STOP);
- }
- /*
- If reading from a remote host, ensure the temp_buf for the
- Log_event class is pointing to the incoming stream.
- */
- ev->register_temp_buf((char *) net->read_pos + 1, FALSE);
+ if (!(ev= read_remote_annotate_event(net->read_pos + 1, len - 1,
+ &error_msg)))
+ {
+ error("Could not construct annotate event object: %s", error_msg);
+ DBUG_RETURN(ERROR_STOP);
+ }
+ }
+ else
+ {
+ if (!(ev= Log_event::read_log_event((const char*) net->read_pos + 1 ,
+ len - 1, &error_msg,
+ glob_description_event)))
+ {
+ error("Could not construct log event object: %s", error_msg);
+ DBUG_RETURN(ERROR_STOP);
+ }
+ /*
+ If reading from a remote host, ensure the temp_buf for the
+ Log_event class is pointing to the incoming stream.
+ */
+ ev->register_temp_buf((char *) net->read_pos + 1, FALSE);
+ }
Log_event_type type= ev->get_type_code();
if (glob_description_event->binlog_version >= 3 ||
@@ -2230,6 +2341,7 @@ int main(int argc, char** argv)
if (result_file != stdout)
my_fclose(result_file, MYF(0));
cleanup();
+ free_annotate_event();
delete binlog_filter;
free_root(&s_mem_root, MYF(0));
free_defaults(defaults_argv);
diff --git a/mysql-test/extra/binlog_tests/mix_innodb_myisam_binlog.test b/mysql-test/extra/binlog_tests/mix_innodb_myisam_binlog.test
index 5db79e4f848..96c85e024e9 100644
--- a/mysql-test/extra/binlog_tests/mix_innodb_myisam_binlog.test
+++ b/mysql-test/extra/binlog_tests/mix_innodb_myisam_binlog.test
@@ -321,14 +321,19 @@ let $MYSQLD_DATADIR= `select @@datadir`;
# we check that the error code of the "ROLLBACK" event is 0 and not
# ER_SERVER_SHUTDOWN (i.e. disconnection just rolls back transaction
# and does not make slave to stop)
+
+-- source include/binlog_start_pos.inc
+
if (`select @@binlog_format = 'ROW'`)
{
- --exec $MYSQL_BINLOG --start-position=524 $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/mix_innodb_myisam_binlog.output
+ let $start_pos= `select @binlog_start_pos + 418`;
+ --exec $MYSQL_BINLOG --start-position=$start_pos $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/mix_innodb_myisam_binlog.output
}
if (`select @@binlog_format = 'STATEMENT' || @@binlog_format = 'MIXED'`)
{
- --exec $MYSQL_BINLOG --start-position=555 $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/mix_innodb_myisam_binlog.output
+ let $start_pos= `select @binlog_start_pos + 449`;
+ --exec $MYSQL_BINLOG --start-position=$start_pos $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/mix_innodb_myisam_binlog.output
}
--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
diff --git a/mysql-test/extra/rpl_tests/rpl_deadlock.test b/mysql-test/extra/rpl_tests/rpl_deadlock.test
index 607348ae97b..bf7c1e05b24 100644
--- a/mysql-test/extra/rpl_tests/rpl_deadlock.test
+++ b/mysql-test/extra/rpl_tests/rpl_deadlock.test
@@ -72,7 +72,7 @@ connection slave;
--source include/stop_slave.inc
DELETE FROM t2;
# Set slave position to the BEGIN log event
---replace_result $master_pos_begin MASTER_POS_BEGIN
+--replace_result $master_pos_begin <master_pos_begin>
eval CHANGE MASTER TO MASTER_LOG_POS=$master_pos_begin;
BEGIN;
# Hold lock
@@ -103,7 +103,7 @@ SET global max_relay_log_size=0;
--source include/stop_slave.inc
DELETE FROM t2;
# Set slave position to the BEGIN log event
---replace_result $master_pos_begin MASTER_POS_BEGIN
+--replace_result $master_pos_begin <master_pos_begin>
eval CHANGE MASTER TO MASTER_LOG_POS=$master_pos_begin;
BEGIN;
# Hold lock
diff --git a/mysql-test/extra/rpl_tests/rpl_log.test b/mysql-test/extra/rpl_tests/rpl_log.test
index e714d84a51b..9effeee1292 100644
--- a/mysql-test/extra/rpl_tests/rpl_log.test
+++ b/mysql-test/extra/rpl_tests/rpl_log.test
@@ -14,6 +14,7 @@ source include/stop_slave.inc;
reset master;
reset slave;
source include/start_slave.inc;
+source include/binlog_start_pos.inc;
let $VERSION=`select version()`;
diff --git a/mysql-test/extra/rpl_tests/rpl_row_annotate.test b/mysql-test/extra/rpl_tests/rpl_row_annotate.test
new file mode 100644
index 00000000000..290d0a89b46
--- /dev/null
+++ b/mysql-test/extra/rpl_tests/rpl_row_annotate.test
@@ -0,0 +1,155 @@
+########################################################################
+# WL47: Store in binlog text of statements that caused RBR events
+# new event : ANNOTATE_ROWS_EVENT
+# new master option : --binlog-annotate-rows-events
+# new slave option : --replicate-annotate-rows-events
+########################################################################
+--source include/master-slave.inc
+connect (master2,127.0.0.1,root,,test,$MASTER_MYPORT,);
+
+connection master;
+--disable_query_log
+
+--disable_warnings
+DROP DATABASE IF EXISTS test1;
+--enable_warnings
+
+CREATE DATABASE test1;
+USE test1;
+
+CREATE TABLE t1(a int primary key, b int);
+CREATE TABLE t2(a int, b int);
+CREATE TABLE t3(a int, b int);
+CREATE TABLE t4(a int, b int);
+CREATE TABLE xt1(a int, b int);
+CREATE TABLE xt2(a int, b int);
+
+CREATE TABLE t5 (
+ a INT PRIMARY KEY AUTO_INCREMENT,
+ b VARCHAR(10) CHARACTER SET utf8 COLLATE utf8_bin
+);
+
+SET SESSION binlog_annotate_rows_events = OFF;
+
+INSERT INTO t1 VALUES (0,0), (1,1);
+
+SET SESSION binlog_annotate_rows_events = ON;
+
+UPDATE t1 SET b = b + 1;
+REPLACE t1 VALUES (1,1), (2,2), (3,3);
+
+INSERT INTO t2 VALUES (1,1), (2,2), (3,3);
+INSERT INTO t3 VALUES (1,1), (2,2), (3,3);
+DELETE t1, t2 FROM t1 INNER JOIN t2 INNER JOIN t3 WHERE t1.a=t2.a AND t2.a=t3.a;
+
+INSERT INTO xt1 VALUES (1,1), (2,2), (3,3);
+INSERT INTO t2 VALUES (1,1), (2,2), (3,3);
+DELETE xt1, t2 FROM xt1 INNER JOIN t2 INNER JOIN t3 WHERE xt1.a=t2.a AND t2.a=t3.a;
+
+INSERT INTO xt1 VALUES (1,1), (2,2), (3,3);
+INSERT INTO xt2 VALUES (1,1), (2,2), (3,3);
+DELETE xt1, xt2 FROM xt1 INNER JOIN xt2 INNER JOIN t3 WHERE xt1.a=xt2.a AND xt2.a=t3.a;
+
+INSERT INTO t5(b) VALUES ('foo'), ('bar'), ('baz');
+SET NAMES latin1;
+INSERT INTO t5(b) VALUES ('gås');
+SET NAMES utf8;
+INSERT INTO t5(b) VALUES ('gås');
+SET NAMES latin1;
+
+FLUSH LOGS;
+
+--echo ########################################################################
+--echo # TABLES ON MASTER
+--echo ########################################################################
+--enable_query_log
+
+SELECT * FROM t1 ORDER BY a;
+SELECT * FROM t2 ORDER BY a;
+SELECT * FROM t3 ORDER BY a;
+SELECT * FROM t5 ORDER BY a;
+
+sync_slave_with_master;
+--echo ########################################################################
+--echo # TABLES ON SLAVE: should be the same as on master
+--echo ########################################################################
+--disable_query_log
+USE test1;
+--enable_query_log
+
+SELECT * FROM t1 ORDER BY a;
+SELECT * FROM t2 ORDER BY a;
+SELECT * FROM t3 ORDER BY a;
+SELECT * FROM t5 ORDER BY a;
+
+--echo ########################################################################
+--echo # EVENTS ON SLAVE
+let $annotate= `select @@global.replicate_annotate_rows_events`;
+if ($annotate)
+{
+ --echo # The following Annotate_rows events should appear below:
+ --echo # - UPDATE t1 SET b = b + 1;
+ --echo # - REPLACE t1 VALUES (1,1), (2,2), (3,3);
+ --echo # - INSERT INTO t2 VALUES (1,1), (2,2), (3,3)
+ --echo # - INSERT INTO t3 VALUES (1,1), (2,2), (3,3)
+ --echo # - DELETE t1, t2 FROM <...>
+ --echo # - INSERT INTO t2 VALUES (1,1), (2,2), (3,3)
+ --echo # - DELETE xt1, t2 FROM <...>
+ --echo # - INSERT INTO t5(b) VALUES <...> (3 instances)
+}
+if (!$annotate)
+{
+ --echo # No Annotate_rows events should appear below
+}
+--echo ########################################################################
+FLUSH LOGS;
+
+--source include/binlog_start_pos.inc
+let $start_pos= `select @binlog_start_pos`;
+--replace_column 2 # 5 #
+--replace_result $start_pos <start_pos>
+--replace_regex /table_id: [0-9]+/table_id: #/ /\/\* xid=.* \*\//\/* xid= *\//
+--eval show binlog events in 'slave-bin.000001' from $start_pos
+
+--echo #
+--echo ########################################################################
+--echo # INSERTs DELAYED ON MASTERs
+--echo ########################################################################
+connection master;
+SET SESSION binlog_annotate_rows_events = ON;
+INSERT DELAYED INTO test1.t4 VALUES (1,1);
+FLUSH TABLES;
+SELECT * FROM test1.t4 ORDER BY a;
+
+sync_slave_with_master;
+connection master;
+sync_slave_with_master;
+
+--echo ########################################################################
+--echo # ON SLAVE
+--echo # No Annotate_rows events should appear below
+--echo ########################################################################
+FLUSH LOGS;
+
+--exec $MYSQL --host=127.0.0.1 --port=$SLAVE_MYPORT test -e "show binlog events in 'slave-bin.000002'" > $MYSQLTEST_VARDIR/tmp/annotated_events.txt
+perl;
+ open F, '<', "$ENV{MYSQLTEST_VARDIR}/tmp/annotated_events.txt" or die;
+ binmode STDOUT;
+ while (defined ($_ = <F>)) {
+ if (/Annotate_rows/) {
+ s/[0-9]+\sAnnotate_rows\s[0-9]+\s[0-9]+/# Annotate_rows # #/;
+ print($_);
+ $_ = <F>;
+ s/[0-9]+\sTable_map\s[0-9]+\s[0-9]+\stable_id:\s[0-9]+/# Table_map # # table_id: #/;
+ print($_);
+ }
+ }
+EOF
+
+# Clean-up
+connection master;
+--disable_query_log
+DROP DATABASE test1;
+sync_slave_with_master;
+--enable_query_log
+
diff --git a/mysql-test/include/binlog_start_pos.inc b/mysql-test/include/binlog_start_pos.inc
new file mode 100644
index 00000000000..f6d1c4c68a3
--- /dev/null
+++ b/mysql-test/include/binlog_start_pos.inc
@@ -0,0 +1,26 @@
+##############################################################################
+#
+# binlog_start_pos is the postion of the the first event in the binary log
+# which follows the Format description event. Intended to reduce test suite
+# dependance on the Format description event length changes (e.g. in case
+# of adding new events). Evaluated as:
+#
+# binlog_start_pos = 4 /* binlog header */ +
+# (Format_description_log_event length)
+#
+# Format_description_log_event length =
+# 19 /* event common header */ +
+# 57 /* misc stuff in the Format description header */ +
+# number of events.
+#
+# With current number of events = 160,
+#
+# binlog_start_pos = 4 + 19 + 57 + 160 = 240.
+#
+##############################################################################
+
+let $binlog_start_pos=240;
+--disable_query_log
+SET @binlog_start_pos=240;
+--enable_query_log
+
diff --git a/mysql-test/include/show_binlog_events.inc b/mysql-test/include/show_binlog_events.inc
index 6d8c8196102..a55ac983a52 100644
--- a/mysql-test/include/show_binlog_events.inc
+++ b/mysql-test/include/show_binlog_events.inc
@@ -3,7 +3,7 @@
#
# Useage:
# let $binlog_file= master-bin.000002;
-# let $binlog_start= 106;
+# let $binlog_start= 240;
# let $binlog_limit= 1, 3;
# source include/show_binlog_events.inc;
#
diff --git a/mysql-test/include/show_binlog_events2.inc b/mysql-test/include/show_binlog_events2.inc
index 5dd272c562d..96e42e93f90 100644
--- a/mysql-test/include/show_binlog_events2.inc
+++ b/mysql-test/include/show_binlog_events2.inc
@@ -1,4 +1,4 @@
---let $binlog_start=106
+--let $binlog_start=240
--replace_result $binlog_start <binlog_start>
--replace_column 2 # 5 #
--replace_regex /\/\* xid=.* \*\//\/* XID *\// /table_id: [0-9]+/table_id: #/
diff --git a/mysql-test/r/ctype_cp932_binlog_stm.result b/mysql-test/r/ctype_cp932_binlog_stm.result
index 8854a835e25..20eb73f4c42 100644
--- a/mysql-test/r/ctype_cp932_binlog_stm.result
+++ b/mysql-test/r/ctype_cp932_binlog_stm.result
@@ -44,8 +44,6 @@ master-bin.000001 # Query # # use `test`; INSERT INTO t4 VALUES ( NAME_CONST('in
master-bin.000001 # Query # # use `test`; DROP PROCEDURE bug18293
master-bin.000001 # Query # # use `test`; DROP TABLE t4
End of 5.0 tests
-SHOW BINLOG EVENTS FROM 365;
-ERROR HY000: Error when executing command SHOW BINLOG EVENTS: Wrong offset or I/O error
Bug#44352 UPPER/LOWER function doesn't work correctly on cp932 and sjis environment.
CREATE TABLE t1 (a varchar(16)) character set cp932;
INSERT INTO t1 VALUES (0x8372835E),(0x8352835E);
diff --git a/mysql-test/r/mysqlbinlog.result b/mysql-test/r/mysqlbinlog.result
index 69d19b5e87f..545ef6e8a7e 100644
--- a/mysql-test/r/mysqlbinlog.result
+++ b/mysql-test/r/mysqlbinlog.result
@@ -1,15 +1,17 @@
reset master;
+SET @save_binlog_size= @@global.max_binlog_size;
+SET @@global.max_binlog_size= 4096;
set timestamp=1000000000;
drop table if exists t1,t2,t3,t4,t5,t03,t04;
create table t1 (word varchar(20));
create table t2 (id int auto_increment not null primary key);
insert into t1 values ("abirvalg");
insert into t2 values ();
-load data infile '../../std_data/words.dat' into table t1;
-load data infile '../../std_data/words.dat' into table t1;
-load data infile '../../std_data/words.dat' into table t1;
-load data infile '../../std_data/words.dat' into table t1;
-load data infile '../../std_data/words.dat' into table t1;
+load data infile '../../std_data/words3.dat' into table t1;
+load data infile '../../std_data/words3.dat' into table t1;
+load data infile '../../std_data/words3.dat' into table t1;
+load data infile '../../std_data/words3.dat' into table t1;
+load data infile '../../std_data/words3.dat' into table t1;
insert into t1 values ("Alas");
flush logs;
@@ -255,6 +257,7 @@ DELIMITER ;
ROLLBACK /* added by mysqlbinlog */;
/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
drop table t1,t2;
+SET @@global.max_binlog_size= @save_binlog_size;
flush logs;
flush logs;
select * from t5 /* must be (1),(1) */;
@@ -377,14 +380,14 @@ LOAD DATA LOCAL INFILE 'MYSQLTEST_VARDIR/tmp/SQL_LOAD_MB-#-#' INTO TABLE `t1` FI
/*!*/;
SET TIMESTAMP=1000000000/*!*/;
SET @@session.collation_database=7/*!*/;
-LOAD DATA LOCAL INFILE 'MYSQLTEST_VARDIR/tmp/SQL_LOAD_MB-a-0' INTO TABLE `t1` FIELDS TERMINATED BY '\t' ENCLOSED BY '' ESCAPED BY '\\' LINES TERMINATED BY '\n' (`a`)
+LOAD DATA LOCAL INFILE 'MYSQLTEST_VARDIR/tmp/SQL_LOAD_MB-#-#' INTO TABLE `t1` FIELDS TERMINATED BY '\t' ENCLOSED BY '' ESCAPED BY '\\' LINES TERMINATED BY '\n' (`a`)
/*!*/;
SET TIMESTAMP=1000000000/*!*/;
SET @@session.collation_database=DEFAULT/*!*/;
-LOAD DATA LOCAL INFILE 'MYSQLTEST_VARDIR/tmp/SQL_LOAD_MB-b-0' INTO TABLE `t1` FIELDS TERMINATED BY '\t' ENCLOSED BY '' ESCAPED BY '\\' LINES TERMINATED BY '\n' (`a`)
+LOAD DATA LOCAL INFILE 'MYSQLTEST_VARDIR/tmp/SQL_LOAD_MB-#-#' INTO TABLE `t1` FIELDS TERMINATED BY '\t' ENCLOSED BY '' ESCAPED BY '\\' LINES TERMINATED BY '\n' (`a`)
/*!*/;
SET TIMESTAMP=1000000000/*!*/;
-LOAD DATA LOCAL INFILE 'MYSQLTEST_VARDIR/tmp/SQL_LOAD_MB-c-0' INTO TABLE `t1` CHARACTER SET koi8r FIELDS TERMINATED BY '\t' ENCLOSED BY '' ESCAPED BY '\\' LINES TERMINATED BY '\n' (`a`)
+LOAD DATA LOCAL INFILE 'MYSQLTEST_VARDIR/tmp/SQL_LOAD_MB-#-#' INTO TABLE `t1` CHARACTER SET koi8r FIELDS TERMINATED BY '\t' ENCLOSED BY '' ESCAPED BY '\\' LINES TERMINATED BY '\n' (`a`)
/*!*/;
SET TIMESTAMP=1000000000/*!*/;
drop table t1
diff --git a/mysql-test/std_data/words3.dat b/mysql-test/std_data/words3.dat
new file mode 100644
index 00000000000..dca0819721d
--- /dev/null
+++ b/mysql-test/std_data/words3.dat
@@ -0,0 +1,66 @@
+Aarhus
+Aaron
+Ababa
+aback
+abaft
+abandon
+abandoned
+abandoning
+abandonment
+abandons
+Aarhus
+Aaron
+Ababa
+aback
+abaft
+abandon
+abandoned
+abandoning
+abandonment
+abandons
+abase
+abased
+abasement
+abasements
+abases
+abash
+abashed
+abashes
+abashing
+abasing
+abate
+abated
+abatement
+abatements
+abater
+abates
+abating
+Abba
+abbe
+abbey
+abbeys
+abbot
+abbots
+Abbott
+abbreviate
+abbreviated
+abbreviates
+abbreviating
+abbreviation
+abbreviations
+Abby
+abdomen
+abdomens
+abdominal
+abduct
+abducted
+abduction
+abductions
+abductor
+abductors
+abducts
+Abe
+abed
+Abel
+Abelian
+Abelson
diff --git a/mysql-test/suite/binlog/r/binlog_row_annotate.result b/mysql-test/suite/binlog/r/binlog_row_annotate.result
new file mode 100644
index 00000000000..647c07af2f8
--- /dev/null
+++ b/mysql-test/suite/binlog/r/binlog_row_annotate.result
@@ -0,0 +1,1219 @@
+#####################################################################################
+# The following Annotate_rows events should appear below:
+# - INSERT INTO test2.t2 VALUES (1), (2), (3)
+# - INSERT INTO test3.t3 VALUES (1), (2), (3)
+# - DELETE test1.t1, test2.t2 FROM <...>
+# - INSERT INTO test2.t2 VALUES (1), (2), (3)
+# - DELETE xtest1.xt1, test2.t2 FROM <...>
+#####################################################################################
+show binlog events in 'master-bin.000001' from <start_pos>;
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query 1 # DROP DATABASE IF EXISTS test1
+master-bin.000001 # Query 1 # DROP DATABASE IF EXISTS test2
+master-bin.000001 # Query 1 # DROP DATABASE IF EXISTS test3
+master-bin.000001 # Query 1 # CREATE DATABASE test1
+master-bin.000001 # Query 1 # CREATE DATABASE test2
+master-bin.000001 # Query 1 # CREATE DATABASE test3
+master-bin.000001 # Query 1 # BEGIN
+master-bin.000001 # Table_map 1 # table_id: # (test1.t1)
+master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
+master-bin.000001 # Query 1 # COMMIT
+master-bin.000001 # Query 1 # BEGIN
+master-bin.000001 # Annotate_rows 1 # INSERT INTO test2.t2 VALUES (1), (2), (3)
+master-bin.000001 # Table_map 1 # table_id: # (test2.t2)
+master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
+master-bin.000001 # Query 1 # COMMIT
+master-bin.000001 # Query 1 # BEGIN
+master-bin.000001 # Annotate_rows 1 # INSERT INTO test3.t3 VALUES (1), (2), (3)
+master-bin.000001 # Table_map 1 # table_id: # (test3.t3)
+master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
+master-bin.000001 # Query 1 # COMMIT
+master-bin.000001 # Query 1 # BEGIN
+master-bin.000001 # Annotate_rows 1 # DELETE test1.t1, test2.t2
+FROM test1.t1 INNER JOIN test2.t2 INNER JOIN test3.t3
+WHERE test1.t1.a=test2.t2.a AND test2.t2.a=test3.t3.a
+master-bin.000001 # Table_map 1 # table_id: # (test1.t1)
+master-bin.000001 # Table_map 1 # table_id: # (test2.t2)
+master-bin.000001 # Delete_rows 1 # table_id: #
+master-bin.000001 # Delete_rows 1 # table_id: # flags: STMT_END_F
+master-bin.000001 # Query 1 # COMMIT
+master-bin.000001 # Query 1 # BEGIN
+master-bin.000001 # Annotate_rows 1 # INSERT INTO test2.v2 VALUES (1), (2), (3)
+master-bin.000001 # Table_map 1 # table_id: # (test2.t2)
+master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
+master-bin.000001 # Query 1 # COMMIT
+master-bin.000001 # Query 1 # BEGIN
+master-bin.000001 # Annotate_rows 1 # DELETE xtest1.xt1, test2.t2
+FROM xtest1.xt1 INNER JOIN test2.t2 INNER JOIN test3.t3
+WHERE xtest1.xt1.a=test2.t2.a AND test2.t2.a=test3.t3.a
+master-bin.000001 # Table_map 1 # table_id: # (test2.t2)
+master-bin.000001 # Delete_rows 1 # table_id: # flags: STMT_END_F
+master-bin.000001 # Query 1 # COMMIT
+master-bin.000001 # Rotate 1 # master-bin.000002;pos=4
+#
+#####################################################################################
+# mysqlbinlog
+# The following Annotates should appear in this output:
+# - INSERT INTO test2.t2 VALUES (1), (2), (3)
+# - INSERT INTO test3.t3 VALUES (1), (2), (3)
+# - DELETE test1.t1, test2.t2 FROM <...> (with two subsequent Table maps)
+# - INSERT INTO test2.t2 VALUES (1), (2), (3)
+# - DELETE xtest1.xt1, test2.t2 FROM <...> (with one subsequent Table map)
+#####################################################################################
+/*!40019 SET @@session.max_insert_delayed_threads=0*/;
+/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/;
+DELIMITER /*!*/;
+# at #
+#010909 4:46:40 server id # end_log_pos # Start: binlog v 4, server v #.##.## created 010909 4:46:40 at startup
+ROLLBACK/*!*/;
+# at #
+#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+SET @@session.pseudo_thread_id=#/*!*/;
+SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.unique_checks=1, @@session.autocommit=1/*!*/;
+SET @@session.sql_mode=0/*!*/;
+SET @@session.auto_increment_increment=1, @@session.auto_increment_offset=1/*!*/;
+/*!\C latin1 *//*!*/;
+SET @@session.character_set_client=8,@@session.collation_connection=8,@@session.collation_server=8/*!*/;
+SET @@session.lc_time_names=0/*!*/;
+SET @@session.collation_database=DEFAULT/*!*/;
+DROP DATABASE IF EXISTS test1
+/*!*/;
+# at #
+#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+DROP DATABASE IF EXISTS test2
+/*!*/;
+# at #
+#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+DROP DATABASE IF EXISTS test3
+/*!*/;
+# at #
+#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+CREATE DATABASE test1
+/*!*/;
+# at #
+#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+CREATE DATABASE test2
+/*!*/;
+# at #
+#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+CREATE DATABASE test3
+/*!*/;
+# at #
+#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+BEGIN
+/*!*/;
+# at #
+# at #
+#010909 4:46:40 server id # end_log_pos # Table_map: `test1`.`t1` mapped to number #
+#010909 4:46:40 server id # end_log_pos # Write_rows: table id # flags: STMT_END_F
+### INSERT INTO test1.t1
+### SET
+### @1=1 /* INT meta=0 nullable=1 is_null=0 */
+### INSERT INTO test1.t1
+### SET
+### @1=2 /* INT meta=0 nullable=1 is_null=0 */
+### INSERT INTO test1.t1
+### SET
+### @1=3 /* INT meta=0 nullable=1 is_null=0 */
+# at #
+#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+COMMIT
+/*!*/;
+# at #
+#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+BEGIN
+/*!*/;
+# at #
+# at #
+# at #
+#010909 4:46:40 server id # end_log_pos # Annotate_rows:
+#Q> INSERT INTO test2.t2 VALUES (1), (2), (3)
+#010909 4:46:40 server id # end_log_pos # Table_map: `test2`.`t2` mapped to number #
+#010909 4:46:40 server id # end_log_pos # Write_rows: table id # flags: STMT_END_F
+### INSERT INTO test2.t2
+### SET
+### @1=1 /* INT meta=0 nullable=1 is_null=0 */
+### INSERT INTO test2.t2
+### SET
+### @1=2 /* INT meta=0 nullable=1 is_null=0 */
+### INSERT INTO test2.t2
+### SET
+### @1=3 /* INT meta=0 nullable=1 is_null=0 */
+# at #
+#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+COMMIT
+/*!*/;
+# at #
+#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+BEGIN
+/*!*/;
+# at #
+# at #
+# at #
+#010909 4:46:40 server id # end_log_pos # Annotate_rows:
+#Q> INSERT INTO test3.t3 VALUES (1), (2), (3)
+#010909 4:46:40 server id # end_log_pos # Table_map: `test3`.`t3` mapped to number #
+#010909 4:46:40 server id # end_log_pos # Write_rows: table id # flags: STMT_END_F
+### INSERT INTO test3.t3
+### SET
+### @1=1 /* INT meta=0 nullable=1 is_null=0 */
+### INSERT INTO test3.t3
+### SET
+### @1=2 /* INT meta=0 nullable=1 is_null=0 */
+### INSERT INTO test3.t3
+### SET
+### @1=3 /* INT meta=0 nullable=1 is_null=0 */
+# at #
+#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+COMMIT
+/*!*/;
+# at #
+#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+BEGIN
+/*!*/;
+# at #
+# at #
+# at #
+# at #
+# at #
+#010909 4:46:40 server id # end_log_pos # Annotate_rows:
+#Q> DELETE test1.t1, test2.t2
+#Q> FROM test1.t1 INNER JOIN test2.t2 INNER JOIN test3.t3
+#Q> WHERE test1.t1.a=test2.t2.a AND test2.t2.a=test3.t3
+#010909 4:46:40 server id # end_log_pos # Table_map: `test1`.`t1` mapped to number #
+#010909 4:46:40 server id # end_log_pos # Table_map: `test2`.`t2` mapped to number #
+#010909 4:46:40 server id # end_log_pos # Delete_rows: table id #
+#010909 4:46:40 server id # end_log_pos # Delete_rows: table id # flags: STMT_END_F
+### DELETE FROM test1.t1
+### WHERE
+### @1=1 /* INT meta=0 nullable=1 is_null=0 */
+### DELETE FROM test1.t1
+### WHERE
+### @1=2 /* INT meta=0 nullable=1 is_null=0 */
+### DELETE FROM test1.t1
+### WHERE
+### @1=3 /* INT meta=0 nullable=1 is_null=0 */
+### DELETE FROM test2.t2
+### WHERE
+### @1=1 /* INT meta=0 nullable=1 is_null=0 */
+### DELETE FROM test2.t2
+### WHERE
+### @1=2 /* INT meta=0 nullable=1 is_null=0 */
+### DELETE FROM test2.t2
+### WHERE
+### @1=3 /* INT meta=0 nullable=1 is_null=0 */
+# at #
+#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+COMMIT
+/*!*/;
+# at #
+#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+BEGIN
+/*!*/;
+# at #
+# at #
+# at #
+#010909 4:46:40 server id # end_log_pos # Annotate_rows:
+#Q> INSERT INTO test2.v2 VALUES (1), (2), (3)
+#010909 4:46:40 server id # end_log_pos # Table_map: `test2`.`t2` mapped to number #
+#010909 4:46:40 server id # end_log_pos # Write_rows: table id # flags: STMT_END_F
+### INSERT INTO test2.t2
+### SET
+### @1=1 /* INT meta=0 nullable=1 is_null=0 */
+### INSERT INTO test2.t2
+### SET
+### @1=2 /* INT meta=0 nullable=1 is_null=0 */
+### INSERT INTO test2.t2
+### SET
+### @1=3 /* INT meta=0 nullable=1 is_null=0 */
+# at #
+#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+COMMIT
+/*!*/;
+# at #
+#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+BEGIN
+/*!*/;
+# at #
+# at #
+# at #
+#010909 4:46:40 server id # end_log_pos # Annotate_rows:
+#Q> DELETE xtest1.xt1, test2.t2
+#Q> FROM xtest1.xt1 INNER JOIN test2.t2 INNER JOIN test3.t3
+#Q> WHERE xtest1.xt1.a=test2.t2.a AND test2.t2.a=test3.t3
+#010909 4:46:40 server id # end_log_pos # Table_map: `test2`.`t2` mapped to number #
+#010909 4:46:40 server id # end_log_pos # Delete_rows: table id # flags: STMT_END_F
+### DELETE FROM test2.t2
+### WHERE
+### @1=3 /* INT meta=0 nullable=1 is_null=0 */
+### DELETE FROM test2.t2
+### WHERE
+### @1=2 /* INT meta=0 nullable=1 is_null=0 */
+### DELETE FROM test2.t2
+### WHERE
+### @1=1 /* INT meta=0 nullable=1 is_null=0 */
+# at #
+#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+COMMIT
+/*!*/;
+# at #
+#010909 4:46:40 server id # end_log_pos # Rotate to master-bin.000002 pos: 4
+DELIMITER ;
+# End of log file
+ROLLBACK /* added by mysqlbinlog */;
+/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
+#
+#####################################################################################
+# mysqlbinlog --database=test1
+# The following Annotate should appear in this output:
+# - DELETE test1.t1, test2.t2 FROM <...>
+#####################################################################################
+/*!40019 SET @@session.max_insert_delayed_threads=0*/;
+/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/;
+DELIMITER /*!*/;
+# at #
+#010909 4:46:40 server id # end_log_pos # Start: binlog v 4, server v #.##.## created 010909 4:46:40 at startup
+ROLLBACK/*!*/;
+# at #
+#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+SET @@session.pseudo_thread_id=#/*!*/;
+SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.unique_checks=1, @@session.autocommit=1/*!*/;
+SET @@session.sql_mode=0/*!*/;
+SET @@session.auto_increment_increment=1, @@session.auto_increment_offset=1/*!*/;
+/*!\C latin1 *//*!*/;
+SET @@session.character_set_client=8,@@session.collation_connection=8,@@session.collation_server=8/*!*/;
+SET @@session.lc_time_names=0/*!*/;
+SET @@session.collation_database=DEFAULT/*!*/;
+DROP DATABASE IF EXISTS test1
+/*!*/;
+# at #
+# at #
+# at #
+#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+CREATE DATABASE test1
+/*!*/;
+# at #
+# at #
+# at #
+#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+BEGIN
+/*!*/;
+# at #
+# at #
+#010909 4:46:40 server id # end_log_pos # Table_map: `test1`.`t1` mapped to number #
+#010909 4:46:40 server id # end_log_pos # Write_rows: table id # flags: STMT_END_F
+### INSERT INTO test1.t1
+### SET
+### @1=1 /* INT meta=0 nullable=1 is_null=0 */
+### INSERT INTO test1.t1
+### SET
+### @1=2 /* INT meta=0 nullable=1 is_null=0 */
+### INSERT INTO test1.t1
+### SET
+### @1=3 /* INT meta=0 nullable=1 is_null=0 */
+# at #
+#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+COMMIT
+/*!*/;
+# at #
+#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+BEGIN
+/*!*/;
+# at #
+# at #
+# at #
+# at #
+#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+COMMIT
+/*!*/;
+# at #
+#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+BEGIN
+/*!*/;
+# at #
+# at #
+# at #
+# at #
+#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+COMMIT
+/*!*/;
+# at #
+#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+BEGIN
+/*!*/;
+# at #
+# at #
+# at #
+# at #
+# at #
+#010909 4:46:40 server id # end_log_pos # Annotate_rows:
+#Q> DELETE test1.t1, test2.t2
+#Q> FROM test1.t1 INNER JOIN test2.t2 INNER JOIN test3.t3
+#Q> WHERE test1.t1.a=test2.t2.a AND test2.t2.a=test3.t3
+#010909 4:46:40 server id # end_log_pos # Table_map: `test1`.`t1` mapped to number #
+#010909 4:46:40 server id # end_log_pos # Delete_rows: table id #
+### DELETE FROM test1.t1
+### WHERE
+### @1=1 /* INT meta=0 nullable=1 is_null=0 */
+### DELETE FROM test1.t1
+### WHERE
+### @1=2 /* INT meta=0 nullable=1 is_null=0 */
+### DELETE FROM test1.t1
+### WHERE
+### @1=3 /* INT meta=0 nullable=1 is_null=0 */
+# at #
+#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+COMMIT
+/*!*/;
+# at #
+#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+BEGIN
+/*!*/;
+# at #
+# at #
+# at #
+# at #
+#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+COMMIT
+/*!*/;
+# at #
+#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+BEGIN
+/*!*/;
+# at #
+# at #
+# at #
+# at #
+#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+COMMIT
+/*!*/;
+# at #
+#010909 4:46:40 server id # end_log_pos # Rotate to master-bin.000002 pos: 4
+DELIMITER ;
+# End of log file
+ROLLBACK /* added by mysqlbinlog */;
+/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
+#
+#####################################################################################
+# mysqlbinlog --skip-annotate-rows-events
+# No Annotates should appear in this output
+#####################################################################################
+/*!40019 SET @@session.max_insert_delayed_threads=0*/;
+/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/;
+DELIMITER /*!*/;
+# at #
+#010909 4:46:40 server id # end_log_pos # Start: binlog v 4, server v #.##.## created 010909 4:46:40 at startup
+ROLLBACK/*!*/;
+# at #
+#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+SET @@session.pseudo_thread_id=#/*!*/;
+SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.unique_checks=1, @@session.autocommit=1/*!*/;
+SET @@session.sql_mode=0/*!*/;
+SET @@session.auto_increment_increment=1, @@session.auto_increment_offset=1/*!*/;
+/*!\C latin1 *//*!*/;
+SET @@session.character_set_client=8,@@session.collation_connection=8,@@session.collation_server=8/*!*/;
+SET @@session.lc_time_names=0/*!*/;
+SET @@session.collation_database=DEFAULT/*!*/;
+DROP DATABASE IF EXISTS test1
+/*!*/;
+# at #
+#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+DROP DATABASE IF EXISTS test2
+/*!*/;
+# at #
+#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+DROP DATABASE IF EXISTS test3
+/*!*/;
+# at #
+#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+CREATE DATABASE test1
+/*!*/;
+# at #
+#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+CREATE DATABASE test2
+/*!*/;
+# at #
+#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+CREATE DATABASE test3
+/*!*/;
+# at #
+#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+BEGIN
+/*!*/;
+# at #
+# at #
+#010909 4:46:40 server id # end_log_pos # Table_map: `test1`.`t1` mapped to number #
+#010909 4:46:40 server id # end_log_pos # Write_rows: table id # flags: STMT_END_F
+### INSERT INTO test1.t1
+### SET
+### @1=1 /* INT meta=0 nullable=1 is_null=0 */
+### INSERT INTO test1.t1
+### SET
+### @1=2 /* INT meta=0 nullable=1 is_null=0 */
+### INSERT INTO test1.t1
+### SET
+### @1=3 /* INT meta=0 nullable=1 is_null=0 */
+# at #
+#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+COMMIT
+/*!*/;
+# at #
+#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+BEGIN
+/*!*/;
+# at #
+# at #
+# at #
+#010909 4:46:40 server id # end_log_pos # Table_map: `test2`.`t2` mapped to number #
+#010909 4:46:40 server id # end_log_pos # Write_rows: table id # flags: STMT_END_F
+### INSERT INTO test2.t2
+### SET
+### @1=1 /* INT meta=0 nullable=1 is_null=0 */
+### INSERT INTO test2.t2
+### SET
+### @1=2 /* INT meta=0 nullable=1 is_null=0 */
+### INSERT INTO test2.t2
+### SET
+### @1=3 /* INT meta=0 nullable=1 is_null=0 */
+# at #
+#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+COMMIT
+/*!*/;
+# at #
+#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+BEGIN
+/*!*/;
+# at #
+# at #
+# at #
+#010909 4:46:40 server id # end_log_pos # Table_map: `test3`.`t3` mapped to number #
+#010909 4:46:40 server id # end_log_pos # Write_rows: table id # flags: STMT_END_F
+### INSERT INTO test3.t3
+### SET
+### @1=1 /* INT meta=0 nullable=1 is_null=0 */
+### INSERT INTO test3.t3
+### SET
+### @1=2 /* INT meta=0 nullable=1 is_null=0 */
+### INSERT INTO test3.t3
+### SET
+### @1=3 /* INT meta=0 nullable=1 is_null=0 */
+# at #
+#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+COMMIT
+/*!*/;
+# at #
+#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+BEGIN
+/*!*/;
+# at #
+# at #
+# at #
+# at #
+# at #
+#010909 4:46:40 server id # end_log_pos # Table_map: `test1`.`t1` mapped to number #
+#010909 4:46:40 server id # end_log_pos # Table_map: `test2`.`t2` mapped to number #
+#010909 4:46:40 server id # end_log_pos # Delete_rows: table id #
+#010909 4:46:40 server id # end_log_pos # Delete_rows: table id # flags: STMT_END_F
+### DELETE FROM test1.t1
+### WHERE
+### @1=1 /* INT meta=0 nullable=1 is_null=0 */
+### DELETE FROM test1.t1
+### WHERE
+### @1=2 /* INT meta=0 nullable=1 is_null=0 */
+### DELETE FROM test1.t1
+### WHERE
+### @1=3 /* INT meta=0 nullable=1 is_null=0 */
+### DELETE FROM test2.t2
+### WHERE
+### @1=1 /* INT meta=0 nullable=1 is_null=0 */
+### DELETE FROM test2.t2
+### WHERE
+### @1=2 /* INT meta=0 nullable=1 is_null=0 */
+### DELETE FROM test2.t2
+### WHERE
+### @1=3 /* INT meta=0 nullable=1 is_null=0 */
+# at #
+#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+COMMIT
+/*!*/;
+# at #
+#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+BEGIN
+/*!*/;
+# at #
+# at #
+# at #
+#010909 4:46:40 server id # end_log_pos # Table_map: `test2`.`t2` mapped to number #
+#010909 4:46:40 server id # end_log_pos # Write_rows: table id # flags: STMT_END_F
+### INSERT INTO test2.t2
+### SET
+### @1=1 /* INT meta=0 nullable=1 is_null=0 */
+### INSERT INTO test2.t2
+### SET
+### @1=2 /* INT meta=0 nullable=1 is_null=0 */
+### INSERT INTO test2.t2
+### SET
+### @1=3 /* INT meta=0 nullable=1 is_null=0 */
+# at #
+#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+COMMIT
+/*!*/;
+# at #
+#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+BEGIN
+/*!*/;
+# at #
+# at #
+# at #
+#010909 4:46:40 server id # end_log_pos # Table_map: `test2`.`t2` mapped to number #
+#010909 4:46:40 server id # end_log_pos # Delete_rows: table id # flags: STMT_END_F
+### DELETE FROM test2.t2
+### WHERE
+### @1=3 /* INT meta=0 nullable=1 is_null=0 */
+### DELETE FROM test2.t2
+### WHERE
+### @1=2 /* INT meta=0 nullable=1 is_null=0 */
+### DELETE FROM test2.t2
+### WHERE
+### @1=1 /* INT meta=0 nullable=1 is_null=0 */
+# at #
+#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+COMMIT
+/*!*/;
+# at #
+#010909 4:46:40 server id # end_log_pos # Rotate to master-bin.000002 pos: 4
+DELIMITER ;
+# End of log file
+ROLLBACK /* added by mysqlbinlog */;
+/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
+#
+#####################################################################################
+# mysqlbinlog --read-from-remote-server
+# The following Annotates should appear in this output:
+# - INSERT INTO test2.t2 VALUES (1), (2), (3)
+# - INSERT INTO test3.t3 VALUES (1), (2), (3)
+# - DELETE test1.t1, test2.t2 FROM <...> (with two subsequent Table maps)
+# - INSERT INTO test2.t2 VALUES (1), (2), (3)
+# - DELETE xtest1.xt1, test2.t2 FROM <...> (with one subsequent Table map)
+#####################################################################################
+/*!40019 SET @@session.max_insert_delayed_threads=0*/;
+/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/;
+DELIMITER /*!*/;
+# at #
+#010909 4:46:40 server id # end_log_pos # Start: binlog v 4, server v #.##.## created 010909 4:46:40 at startup
+ROLLBACK/*!*/;
+# at #
+#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+SET @@session.pseudo_thread_id=#/*!*/;
+SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.unique_checks=1, @@session.autocommit=1/*!*/;
+SET @@session.sql_mode=0/*!*/;
+SET @@session.auto_increment_increment=1, @@session.auto_increment_offset=1/*!*/;
+/*!\C latin1 *//*!*/;
+SET @@session.character_set_client=8,@@session.collation_connection=8,@@session.collation_server=8/*!*/;
+SET @@session.lc_time_names=0/*!*/;
+SET @@session.collation_database=DEFAULT/*!*/;
+DROP DATABASE IF EXISTS test1
+/*!*/;
+# at #
+#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+DROP DATABASE IF EXISTS test2
+/*!*/;
+# at #
+#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+DROP DATABASE IF EXISTS test3
+/*!*/;
+# at #
+#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+CREATE DATABASE test1
+/*!*/;
+# at #
+#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+CREATE DATABASE test2
+/*!*/;
+# at #
+#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+CREATE DATABASE test3
+/*!*/;
+# at #
+#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+BEGIN
+/*!*/;
+# at #
+# at #
+#010909 4:46:40 server id # end_log_pos # Table_map: `test1`.`t1` mapped to number #
+#010909 4:46:40 server id # end_log_pos # Write_rows: table id # flags: STMT_END_F
+### INSERT INTO test1.t1
+### SET
+### @1=1 /* INT meta=0 nullable=1 is_null=0 */
+### INSERT INTO test1.t1
+### SET
+### @1=2 /* INT meta=0 nullable=1 is_null=0 */
+### INSERT INTO test1.t1
+### SET
+### @1=3 /* INT meta=0 nullable=1 is_null=0 */
+# at #
+#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+COMMIT
+/*!*/;
+# at #
+#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+BEGIN
+/*!*/;
+# at #
+# at #
+# at #
+#010909 4:46:40 server id # end_log_pos # Annotate_rows:
+#Q> INSERT INTO test2.t2 VALUES (1), (2), (3)
+#010909 4:46:40 server id # end_log_pos # Table_map: `test2`.`t2` mapped to number #
+#010909 4:46:40 server id # end_log_pos # Write_rows: table id # flags: STMT_END_F
+### INSERT INTO test2.t2
+### SET
+### @1=1 /* INT meta=0 nullable=1 is_null=0 */
+### INSERT INTO test2.t2
+### SET
+### @1=2 /* INT meta=0 nullable=1 is_null=0 */
+### INSERT INTO test2.t2
+### SET
+### @1=3 /* INT meta=0 nullable=1 is_null=0 */
+# at #
+#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+COMMIT
+/*!*/;
+# at #
+#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+BEGIN
+/*!*/;
+# at #
+# at #
+# at #
+#010909 4:46:40 server id # end_log_pos # Annotate_rows:
+#Q> INSERT INTO test3.t3 VALUES (1), (2), (3)
+#010909 4:46:40 server id # end_log_pos # Table_map: `test3`.`t3` mapped to number #
+#010909 4:46:40 server id # end_log_pos # Write_rows: table id # flags: STMT_END_F
+### INSERT INTO test3.t3
+### SET
+### @1=1 /* INT meta=0 nullable=1 is_null=0 */
+### INSERT INTO test3.t3
+### SET
+### @1=2 /* INT meta=0 nullable=1 is_null=0 */
+### INSERT INTO test3.t3
+### SET
+### @1=3 /* INT meta=0 nullable=1 is_null=0 */
+# at #
+#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+COMMIT
+/*!*/;
+# at #
+#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+BEGIN
+/*!*/;
+# at #
+# at #
+# at #
+# at #
+# at #
+#010909 4:46:40 server id # end_log_pos # Annotate_rows:
+#Q> DELETE test1.t1, test2.t2
+#Q> FROM test1.t1 INNER JOIN test2.t2 INNER JOIN test3.t3
+#Q> WHERE test1.t1.a=test2.t2.a AND test2.t2.a=test3.t3
+#010909 4:46:40 server id # end_log_pos # Table_map: `test1`.`t1` mapped to number #
+#010909 4:46:40 server id # end_log_pos # Table_map: `test2`.`t2` mapped to number #
+#010909 4:46:40 server id # end_log_pos # Delete_rows: table id #
+#010909 4:46:40 server id # end_log_pos # Delete_rows: table id # flags: STMT_END_F
+### DELETE FROM test1.t1
+### WHERE
+### @1=1 /* INT meta=0 nullable=1 is_null=0 */
+### DELETE FROM test1.t1
+### WHERE
+### @1=2 /* INT meta=0 nullable=1 is_null=0 */
+### DELETE FROM test1.t1
+### WHERE
+### @1=3 /* INT meta=0 nullable=1 is_null=0 */
+### DELETE FROM test2.t2
+### WHERE
+### @1=1 /* INT meta=0 nullable=1 is_null=0 */
+### DELETE FROM test2.t2
+### WHERE
+### @1=2 /* INT meta=0 nullable=1 is_null=0 */
+### DELETE FROM test2.t2
+### WHERE
+### @1=3 /* INT meta=0 nullable=1 is_null=0 */
+# at #
+#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+COMMIT
+/*!*/;
+# at #
+#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+BEGIN
+/*!*/;
+# at #
+# at #
+# at #
+#010909 4:46:40 server id # end_log_pos # Annotate_rows:
+#Q> INSERT INTO test2.v2 VALUES (1), (2), (3)
+#010909 4:46:40 server id # end_log_pos # Table_map: `test2`.`t2` mapped to number #
+#010909 4:46:40 server id # end_log_pos # Write_rows: table id # flags: STMT_END_F
+### INSERT INTO test2.t2
+### SET
+### @1=1 /* INT meta=0 nullable=1 is_null=0 */
+### INSERT INTO test2.t2
+### SET
+### @1=2 /* INT meta=0 nullable=1 is_null=0 */
+### INSERT INTO test2.t2
+### SET
+### @1=3 /* INT meta=0 nullable=1 is_null=0 */
+# at #
+#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+COMMIT
+/*!*/;
+# at #
+#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+BEGIN
+/*!*/;
+# at #
+# at #
+# at #
+#010909 4:46:40 server id # end_log_pos # Annotate_rows:
+#Q> DELETE xtest1.xt1, test2.t2
+#Q> FROM xtest1.xt1 INNER JOIN test2.t2 INNER JOIN test3.t3
+#Q> WHERE xtest1.xt1.a=test2.t2.a AND test2.t2.a=test3.t3
+#010909 4:46:40 server id # end_log_pos # Table_map: `test2`.`t2` mapped to number #
+#010909 4:46:40 server id # end_log_pos # Delete_rows: table id # flags: STMT_END_F
+### DELETE FROM test2.t2
+### WHERE
+### @1=3 /* INT meta=0 nullable=1 is_null=0 */
+### DELETE FROM test2.t2
+### WHERE
+### @1=2 /* INT meta=0 nullable=1 is_null=0 */
+### DELETE FROM test2.t2
+### WHERE
+### @1=1 /* INT meta=0 nullable=1 is_null=0 */
+# at #
+#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+COMMIT
+/*!*/;
+# at #
+#010909 4:46:40 server id # end_log_pos # Rotate to master-bin.000002 pos: 4
+DELIMITER ;
+# End of log file
+ROLLBACK /* added by mysqlbinlog */;
+/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
+#
+#####################################################################################
+# mysqlbinlog --read-from-remote-server --database=test1
+# The following Annotate should appear in this output:
+# - DELETE test1.t1, test2.t2 FROM <...>
+#####################################################################################
+/*!40019 SET @@session.max_insert_delayed_threads=0*/;
+/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/;
+DELIMITER /*!*/;
+# at #
+#010909 4:46:40 server id # end_log_pos # Start: binlog v 4, server v #.##.## created 010909 4:46:40 at startup
+ROLLBACK/*!*/;
+# at #
+#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+SET @@session.pseudo_thread_id=#/*!*/;
+SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.unique_checks=1, @@session.autocommit=1/*!*/;
+SET @@session.sql_mode=0/*!*/;
+SET @@session.auto_increment_increment=1, @@session.auto_increment_offset=1/*!*/;
+/*!\C latin1 *//*!*/;
+SET @@session.character_set_client=8,@@session.collation_connection=8,@@session.collation_server=8/*!*/;
+SET @@session.lc_time_names=0/*!*/;
+SET @@session.collation_database=DEFAULT/*!*/;
+DROP DATABASE IF EXISTS test1
+/*!*/;
+# at #
+# at #
+# at #
+#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+CREATE DATABASE test1
+/*!*/;
+# at #
+# at #
+# at #
+#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+BEGIN
+/*!*/;
+# at #
+# at #
+#010909 4:46:40 server id # end_log_pos # Table_map: `test1`.`t1` mapped to number #
+#010909 4:46:40 server id # end_log_pos # Write_rows: table id # flags: STMT_END_F
+### INSERT INTO test1.t1
+### SET
+### @1=1 /* INT meta=0 nullable=1 is_null=0 */
+### INSERT INTO test1.t1
+### SET
+### @1=2 /* INT meta=0 nullable=1 is_null=0 */
+### INSERT INTO test1.t1
+### SET
+### @1=3 /* INT meta=0 nullable=1 is_null=0 */
+# at #
+#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+COMMIT
+/*!*/;
+# at #
+#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+BEGIN
+/*!*/;
+# at #
+# at #
+# at #
+# at #
+#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+COMMIT
+/*!*/;
+# at #
+#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+BEGIN
+/*!*/;
+# at #
+# at #
+# at #
+# at #
+#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+COMMIT
+/*!*/;
+# at #
+#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+BEGIN
+/*!*/;
+# at #
+# at #
+# at #
+# at #
+# at #
+#010909 4:46:40 server id # end_log_pos # Annotate_rows:
+#Q> DELETE test1.t1, test2.t2
+#Q> FROM test1.t1 INNER JOIN test2.t2 INNER JOIN test3.t3
+#Q> WHERE test1.t1.a=test2.t2.a AND test2.t2.a=test3.t3
+#010909 4:46:40 server id # end_log_pos # Table_map: `test1`.`t1` mapped to number #
+#010909 4:46:40 server id # end_log_pos # Delete_rows: table id #
+### DELETE FROM test1.t1
+### WHERE
+### @1=1 /* INT meta=0 nullable=1 is_null=0 */
+### DELETE FROM test1.t1
+### WHERE
+### @1=2 /* INT meta=0 nullable=1 is_null=0 */
+### DELETE FROM test1.t1
+### WHERE
+### @1=3 /* INT meta=0 nullable=1 is_null=0 */
+# at #
+#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+COMMIT
+/*!*/;
+# at #
+#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+BEGIN
+/*!*/;
+# at #
+# at #
+# at #
+# at #
+#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+COMMIT
+/*!*/;
+# at #
+#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+BEGIN
+/*!*/;
+# at #
+# at #
+# at #
+# at #
+#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+COMMIT
+/*!*/;
+# at #
+#010909 4:46:40 server id # end_log_pos # Rotate to master-bin.000002 pos: 4
+DELIMITER ;
+# End of log file
+ROLLBACK /* added by mysqlbinlog */;
+/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
+#
+#####################################################################################
+# mysqlbinlog --read-from-remote-server --skip-annotate-rows-events
+# No Annotates should appear in this output
+#####################################################################################
+/*!40019 SET @@session.max_insert_delayed_threads=0*/;
+/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/;
+DELIMITER /*!*/;
+# at #
+#010909 4:46:40 server id # end_log_pos # Start: binlog v 4, server v #.##.## created 010909 4:46:40 at startup
+ROLLBACK/*!*/;
+# at #
+#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+SET @@session.pseudo_thread_id=#/*!*/;
+SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.unique_checks=1, @@session.autocommit=1/*!*/;
+SET @@session.sql_mode=0/*!*/;
+SET @@session.auto_increment_increment=1, @@session.auto_increment_offset=1/*!*/;
+/*!\C latin1 *//*!*/;
+SET @@session.character_set_client=8,@@session.collation_connection=8,@@session.collation_server=8/*!*/;
+SET @@session.lc_time_names=0/*!*/;
+SET @@session.collation_database=DEFAULT/*!*/;
+DROP DATABASE IF EXISTS test1
+/*!*/;
+# at #
+#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+DROP DATABASE IF EXISTS test2
+/*!*/;
+# at #
+#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+DROP DATABASE IF EXISTS test3
+/*!*/;
+# at #
+#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+CREATE DATABASE test1
+/*!*/;
+# at #
+#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+CREATE DATABASE test2
+/*!*/;
+# at #
+#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+CREATE DATABASE test3
+/*!*/;
+# at #
+#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+BEGIN
+/*!*/;
+# at #
+# at #
+#010909 4:46:40 server id # end_log_pos # Table_map: `test1`.`t1` mapped to number #
+#010909 4:46:40 server id # end_log_pos # Write_rows: table id # flags: STMT_END_F
+### INSERT INTO test1.t1
+### SET
+### @1=1 /* INT meta=0 nullable=1 is_null=0 */
+### INSERT INTO test1.t1
+### SET
+### @1=2 /* INT meta=0 nullable=1 is_null=0 */
+### INSERT INTO test1.t1
+### SET
+### @1=3 /* INT meta=0 nullable=1 is_null=0 */
+# at #
+#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+COMMIT
+/*!*/;
+# at #
+#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+BEGIN
+/*!*/;
+# at #
+# at #
+#010909 4:46:40 server id # end_log_pos # Table_map: `test2`.`t2` mapped to number #
+#010909 4:46:40 server id # end_log_pos # Write_rows: table id # flags: STMT_END_F
+### INSERT INTO test2.t2
+### SET
+### @1=1 /* INT meta=0 nullable=1 is_null=0 */
+### INSERT INTO test2.t2
+### SET
+### @1=2 /* INT meta=0 nullable=1 is_null=0 */
+### INSERT INTO test2.t2
+### SET
+### @1=3 /* INT meta=0 nullable=1 is_null=0 */
+# at #
+#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+COMMIT
+/*!*/;
+# at #
+#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+BEGIN
+/*!*/;
+# at #
+# at #
+#010909 4:46:40 server id # end_log_pos # Table_map: `test3`.`t3` mapped to number #
+#010909 4:46:40 server id # end_log_pos # Write_rows: table id # flags: STMT_END_F
+### INSERT INTO test3.t3
+### SET
+### @1=1 /* INT meta=0 nullable=1 is_null=0 */
+### INSERT INTO test3.t3
+### SET
+### @1=2 /* INT meta=0 nullable=1 is_null=0 */
+### INSERT INTO test3.t3
+### SET
+### @1=3 /* INT meta=0 nullable=1 is_null=0 */
+# at #
+#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+COMMIT
+/*!*/;
+# at #
+#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+BEGIN
+/*!*/;
+# at #
+# at #
+# at #
+# at #
+#010909 4:46:40 server id # end_log_pos # Table_map: `test1`.`t1` mapped to number #
+#010909 4:46:40 server id # end_log_pos # Table_map: `test2`.`t2` mapped to number #
+#010909 4:46:40 server id # end_log_pos # Delete_rows: table id #
+#010909 4:46:40 server id # end_log_pos # Delete_rows: table id # flags: STMT_END_F
+### DELETE FROM test1.t1
+### WHERE
+### @1=1 /* INT meta=0 nullable=1 is_null=0 */
+### DELETE FROM test1.t1
+### WHERE
+### @1=2 /* INT meta=0 nullable=1 is_null=0 */
+### DELETE FROM test1.t1
+### WHERE
+### @1=3 /* INT meta=0 nullable=1 is_null=0 */
+### DELETE FROM test2.t2
+### WHERE
+### @1=1 /* INT meta=0 nullable=1 is_null=0 */
+### DELETE FROM test2.t2
+### WHERE
+### @1=2 /* INT meta=0 nullable=1 is_null=0 */
+### DELETE FROM test2.t2
+### WHERE
+### @1=3 /* INT meta=0 nullable=1 is_null=0 */
+# at #
+#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+COMMIT
+/*!*/;
+# at #
+#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+BEGIN
+/*!*/;
+# at #
+# at #
+#010909 4:46:40 server id # end_log_pos # Table_map: `test2`.`t2` mapped to number #
+#010909 4:46:40 server id # end_log_pos # Write_rows: table id # flags: STMT_END_F
+### INSERT INTO test2.t2
+### SET
+### @1=1 /* INT meta=0 nullable=1 is_null=0 */
+### INSERT INTO test2.t2
+### SET
+### @1=2 /* INT meta=0 nullable=1 is_null=0 */
+### INSERT INTO test2.t2
+### SET
+### @1=3 /* INT meta=0 nullable=1 is_null=0 */
+# at #
+#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+COMMIT
+/*!*/;
+# at #
+#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+BEGIN
+/*!*/;
+# at #
+# at #
+#010909 4:46:40 server id # end_log_pos # Table_map: `test2`.`t2` mapped to number #
+#010909 4:46:40 server id # end_log_pos # Delete_rows: table id # flags: STMT_END_F
+### DELETE FROM test2.t2
+### WHERE
+### @1=3 /* INT meta=0 nullable=1 is_null=0 */
+### DELETE FROM test2.t2
+### WHERE
+### @1=2 /* INT meta=0 nullable=1 is_null=0 */
+### DELETE FROM test2.t2
+### WHERE
+### @1=1 /* INT meta=0 nullable=1 is_null=0 */
+# at #
+#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+COMMIT
+/*!*/;
+# at #
+#010909 4:46:40 server id # end_log_pos # Rotate to master-bin.000002 pos: 4
+DELIMITER ;
+# End of log file
+ROLLBACK /* added by mysqlbinlog */;
+/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
diff --git a/mysql-test/suite/binlog/r/binlog_stm_binlog.result b/mysql-test/suite/binlog/r/binlog_stm_binlog.result
index abfd6a33a7d..2c8ccf9c846 100644
--- a/mysql-test/suite/binlog/r/binlog_stm_binlog.result
+++ b/mysql-test/suite/binlog/r/binlog_stm_binlog.result
@@ -333,7 +333,7 @@ master-bin.000001 # Query # # use `test`; insert into t1 values( 244 )
master-bin.000001 # Query # # use `test`; insert into t1 values( 243 )
master-bin.000001 # Query # # use `test`; insert into t1 values( 242 )
master-bin.000001 # Query # # use `test`; insert into t1 values( 241 )
-master-bin.000001 # Query # # use `test`; insert into t1 values( 240 )
+master-bin.000001 # Query # # use `test`; insert into t1 values( <binlog_start> )
master-bin.000001 # Query # # use `test`; insert into t1 values( 239 )
master-bin.000001 # Query # # use `test`; insert into t1 values( 238 )
master-bin.000001 # Query # # use `test`; insert into t1 values( 237 )
@@ -467,7 +467,7 @@ master-bin.000001 # Query # # use `test`; insert into t1 values( 110 )
master-bin.000001 # Query # # use `test`; insert into t1 values( 109 )
master-bin.000001 # Query # # use `test`; insert into t1 values( 108 )
master-bin.000001 # Query # # use `test`; insert into t1 values( 107 )
-master-bin.000001 # Query # # use `test`; insert into t1 values( <binlog_start> )
+master-bin.000001 # Query # # use `test`; insert into t1 values( 106 )
master-bin.000001 # Query # # use `test`; insert into t1 values( 105 )
master-bin.000001 # Query # # use `test`; insert into t1 values( 104 )
master-bin.000001 # Query # # use `test`; insert into t1 values( 103 )
diff --git a/mysql-test/suite/binlog/t/binlog_incident.test b/mysql-test/suite/binlog/t/binlog_incident.test
index 901ac49ea24..1c526ca5980 100644
--- a/mysql-test/suite/binlog/t/binlog_incident.test
+++ b/mysql-test/suite/binlog/t/binlog_incident.test
@@ -4,6 +4,7 @@
source include/have_log_bin.inc;
source include/have_debug.inc;
+source include/binlog_start_pos.inc;
let $MYSQLD_DATADIR= `select @@datadir`;
RESET MASTER;
@@ -20,7 +21,7 @@ REPLACE INTO t1 VALUES (4);
DROP TABLE t1;
FLUSH LOGS;
-exec $MYSQL_BINLOG --start-position=106 $MYSQLD_DATADIR/master-bin.000001 >$MYSQLTEST_VARDIR/tmp/binlog_incident-bug44442.sql;
+exec $MYSQL_BINLOG --start-position=$binlog_start_pos $MYSQLD_DATADIR/master-bin.000001 >$MYSQLTEST_VARDIR/tmp/binlog_incident-bug44442.sql;
--disable_query_log
eval SELECT cont LIKE '%RELOAD DATABASE; # Shall generate syntax error%' AS `Contain RELOAD DATABASE` FROM (SELECT load_file('$MYSQLTEST_VARDIR/tmp/binlog_incident-bug44442.sql') AS cont) AS tbl;
--enable_query_log
diff --git a/mysql-test/suite/binlog/t/binlog_killed.test b/mysql-test/suite/binlog/t/binlog_killed.test
index ce6d344af32..a2bd7d8095a 100644
--- a/mysql-test/suite/binlog/t/binlog_killed.test
+++ b/mysql-test/suite/binlog/t/binlog_killed.test
@@ -1,5 +1,6 @@
-- source include/have_innodb.inc
-- source include/have_binlog_format_statement.inc
+-- source include/binlog_start_pos.inc
# You cannot use `KILL' with the Embedded MySQL Server library,
# because the embedded server merely runs inside the threads of the host
@@ -51,7 +52,8 @@ reap;
let $rows= `select count(*) from t2 /* must be 2 or 0 */`;
let $MYSQLD_DATADIR= `select @@datadir`;
---exec $MYSQL_BINLOG --force-if-open --start-position=134 $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/kill_query_calling_sp.binlog
+let $start_pos= `select @binlog_start_pos + 28`;
+--exec $MYSQL_BINLOG --force-if-open --start-position=$start_pos $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/kill_query_calling_sp.binlog
--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
eval select
(@a:=load_file("$MYSQLTEST_VARDIR/tmp/kill_query_calling_sp.binlog"))
diff --git a/mysql-test/suite/binlog/t/binlog_killed_simulate.test b/mysql-test/suite/binlog/t/binlog_killed_simulate.test
index b87d47559fe..c5c14137fbb 100644
--- a/mysql-test/suite/binlog/t/binlog_killed_simulate.test
+++ b/mysql-test/suite/binlog/t/binlog_killed_simulate.test
@@ -1,5 +1,6 @@
-- source include/have_debug.inc
-- source include/have_binlog_format_statement.inc
+-- source include/binlog_start_pos.inc
#
# bug#27571 asynchronous setting mysql_$query()'s local error and
# Query_log_event::error_code
@@ -24,7 +25,7 @@ update t1 set a=2 /* will be "killed" after work has been done */;
# for some constants like the offset of the first real event
# that is different between severs versions.
let $MYSQLD_DATADIR= `select @@datadir`;
---exec $MYSQL_BINLOG --force-if-open --start-position=106 $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/binlog_killed_bug27571.binlog
+--exec $MYSQL_BINLOG --force-if-open --start-position=$binlog_start_pos $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/binlog_killed_bug27571.binlog
--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
eval select
(@a:=load_file("$MYSQLTEST_VARDIR/tmp/binlog_killed_bug27571.binlog"))
diff --git a/mysql-test/suite/binlog/t/binlog_row_annotate-master.opt b/mysql-test/suite/binlog/t/binlog_row_annotate-master.opt
new file mode 100644
index 00000000000..24d88646b3b
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_row_annotate-master.opt
@@ -0,0 +1 @@
+--timezone=GMT-3 --binlog-do-db=test1 --binlog-do-db=test2 --binlog-do-db=test3
diff --git a/mysql-test/suite/binlog/t/binlog_row_annotate.test b/mysql-test/suite/binlog/t/binlog_row_annotate.test
new file mode 100644
index 00000000000..c5db9ef2148
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_row_annotate.test
@@ -0,0 +1,189 @@
+###############################################################################
+# WL47: Store in binlog text of statements that caused RBR events
+# new event: ANNOTATE_ROWS_EVENT
+# new master option: --binlog-annotate-rows-events
+# new mysqlbinlog option: --skip-annotate-rows-events
+#
+# Intended to test that:
+# *** If the --binlog-annotate-rows-events option is switched on on master
+# then Annotate_rows events:
+# - are generated;
+# - are genrated only once for "multi-table-maps" rbr queries;
+# - are not generated when the corresponding queries are filtered away;
+# - are generated when the corresponding queries are filtered away partialy
+# (e.g. in case of multi-delete).
+# *** Annotate_rows events are printed by mysqlbinlog started without
+# --skip-annotate-rows-events options both in remote and local cases.
+# *** Annotate_rows events are not printed by mysqlbinlog started with
+# --skip-annotate-rows-events options both in remote and local cases.
+###############################################################################
+
+--source include/have_log_bin.inc
+--source include/have_binlog_format_row.inc
+--source include/binlog_start_pos.inc
+
+--disable_query_log
+
+# Fix timestamp to avoid varying results
+SET timestamp=1000000000;
+
+# Delete all existing binary logs
+RESET MASTER;
+
+--disable_warnings
+DROP DATABASE IF EXISTS test1;
+DROP DATABASE IF EXISTS test2;
+DROP DATABASE IF EXISTS test3;
+DROP DATABASE IF EXISTS xtest1;
+DROP DATABASE IF EXISTS xtest2;
+--enable_warnings
+
+CREATE DATABASE test1;
+CREATE TABLE test1.t1(a int);
+
+CREATE DATABASE test2;
+CREATE TABLE test2.t2(a int);
+CREATE VIEW test2.v2 AS SELECT * FROM test2.t2;
+
+CREATE DATABASE test3;
+CREATE TABLE test3.t3(a int);
+
+CREATE DATABASE xtest1;
+CREATE TABLE xtest1.xt1(a int);
+
+CREATE DATABASE xtest2;
+CREATE TABLE xtest2.xt2(a int);
+
+# By default SESSION binlog_annotate_rows_events = OFF
+
+INSERT INTO test1.t1 VALUES (1), (2), (3);
+
+SET SESSION binlog_annotate_rows_events = ON;
+
+INSERT INTO test2.t2 VALUES (1), (2), (3);
+INSERT INTO test3.t3 VALUES (1), (2), (3);
+
+# This query generates two Table maps but the Annotate
+# event should appear only once before the first Table map
+DELETE test1.t1, test2.t2
+ FROM test1.t1 INNER JOIN test2.t2 INNER JOIN test3.t3
+ WHERE test1.t1.a=test2.t2.a AND test2.t2.a=test3.t3.a;
+
+# This event should be filtered out together with Annotate event
+INSERT INTO xtest1.xt1 VALUES (1), (2), (3);
+
+# This event should pass the filter
+INSERT INTO test2.v2 VALUES (1), (2), (3);
+
+# This event should pass the filter only for test2.t2 part
+DELETE xtest1.xt1, test2.t2
+ FROM xtest1.xt1 INNER JOIN test2.t2 INNER JOIN test3.t3
+ WHERE xtest1.xt1.a=test2.t2.a AND test2.t2.a=test3.t3.a;
+
+# These events should be filtered out together with Annotate events
+INSERT INTO xtest1.xt1 VALUES (1), (2), (3);
+INSERT INTO xtest2.xt2 VALUES (1), (2), (3);
+DELETE xtest1.xt1, xtest2.xt2
+ FROM xtest1.xt1 INNER JOIN xtest2.xt2 INNER JOIN test3.t3
+ WHERE xtest1.xt1.a=xtest2.xt2.a AND xtest2.xt2.a=test3.t3.a;
+
+FLUSH LOGS;
+--enable_query_log
+
+--echo #####################################################################################
+--echo # The following Annotate_rows events should appear below:
+--echo # - INSERT INTO test2.t2 VALUES (1), (2), (3)
+--echo # - INSERT INTO test3.t3 VALUES (1), (2), (3)
+--echo # - DELETE test1.t1, test2.t2 FROM <...>
+--echo # - INSERT INTO test2.t2 VALUES (1), (2), (3)
+--echo # - DELETE xtest1.xt1, test2.t2 FROM <...>
+--echo #####################################################################################
+
+let $start_pos= `select @binlog_start_pos`;
+--replace_column 2 # 5 #
+--replace_result $start_pos <start_pos>
+--replace_regex /table_id: [0-9]+/table_id: #/ /\/\* xid=.* \*\//\/* xid= *\//
+--eval show binlog events in 'master-bin.000001' from $start_pos
+
+--echo #
+--echo #####################################################################################
+--echo # mysqlbinlog
+--echo # The following Annotates should appear in this output:
+--echo # - INSERT INTO test2.t2 VALUES (1), (2), (3)
+--echo # - INSERT INTO test3.t3 VALUES (1), (2), (3)
+--echo # - DELETE test1.t1, test2.t2 FROM <...> (with two subsequent Table maps)
+--echo # - INSERT INTO test2.t2 VALUES (1), (2), (3)
+--echo # - DELETE xtest1.xt1, test2.t2 FROM <...> (with one subsequent Table map)
+--echo #####################################################################################
+
+let $MYSQLD_DATADIR= `select @@datadir`;
+--replace_regex /server id [0-9]*/server id #/ /server v [^ ]*/server v #.##.##/ /exec_time=[0-9]*/exec_time=#/ /thread_id=[0-9]*/thread_id=#/ /table id [0-9]*/table id #/ /mapped to number [0-9]*/mapped to number #/ /end_log_pos [0-9]*/end_log_pos #/ /# at [0-9]*/# at #/
+--exec $MYSQL_BINLOG --base64-output=decode-rows -v -v $MYSQLD_DATADIR/master-bin.000001
+
+--echo #
+--echo #####################################################################################
+--echo # mysqlbinlog --database=test1
+--echo # The following Annotate should appear in this output:
+--echo # - DELETE test1.t1, test2.t2 FROM <...>
+--echo #####################################################################################
+
+let $MYSQLD_DATADIR= `select @@datadir`;
+--replace_regex /server id [0-9]*/server id #/ /server v [^ ]*/server v #.##.##/ /exec_time=[0-9]*/exec_time=#/ /thread_id=[0-9]*/thread_id=#/ /table id [0-9]*/table id #/ /mapped to number [0-9]*/mapped to number #/ /end_log_pos [0-9]*/end_log_pos #/ /# at [0-9]*/# at #/
+--exec $MYSQL_BINLOG --base64-output=decode-rows --database=test1 -v -v $MYSQLD_DATADIR/master-bin.000001
+
+--echo #
+--echo #####################################################################################
+--echo # mysqlbinlog --skip-annotate-rows-events
+--echo # No Annotates should appear in this output
+--echo #####################################################################################
+
+let $MYSQLD_DATADIR= `select @@datadir`;
+--replace_regex /server id [0-9]*/server id #/ /server v [^ ]*/server v #.##.##/ /exec_time=[0-9]*/exec_time=#/ /thread_id=[0-9]*/thread_id=#/ /table id [0-9]*/table id #/ /mapped to number [0-9]*/mapped to number #/ /end_log_pos [0-9]*/end_log_pos #/ /# at [0-9]*/# at #/
+--exec $MYSQL_BINLOG --base64-output=decode-rows --skip-annotate-rows-events -v -v $MYSQLD_DATADIR/master-bin.000001
+
+--echo #
+--echo #####################################################################################
+--echo # mysqlbinlog --read-from-remote-server
+--echo # The following Annotates should appear in this output:
+--echo # - INSERT INTO test2.t2 VALUES (1), (2), (3)
+--echo # - INSERT INTO test3.t3 VALUES (1), (2), (3)
+--echo # - DELETE test1.t1, test2.t2 FROM <...> (with two subsequent Table maps)
+--echo # - INSERT INTO test2.t2 VALUES (1), (2), (3)
+--echo # - DELETE xtest1.xt1, test2.t2 FROM <...> (with one subsequent Table map)
+--echo #####################################################################################
+
+let $MYSQLD_DATADIR= `select @@datadir`;
+--replace_regex /server id [0-9]*/server id #/ /server v [^ ]*/server v #.##.##/ /exec_time=[0-9]*/exec_time=#/ /thread_id=[0-9]*/thread_id=#/ /table id [0-9]*/table id #/ /mapped to number [0-9]*/mapped to number #/ /end_log_pos [0-9]*/end_log_pos #/ /# at [0-9]*/# at #/
+--exec $MYSQL_BINLOG --base64-output=decode-rows -v -v --read-from-remote-server --user=root --host=localhost --port=$MASTER_MYPORT master-bin.000001
+
+--echo #
+--echo #####################################################################################
+--echo # mysqlbinlog --read-from-remote-server --database=test1
+--echo # The following Annotate should appear in this output:
+--echo # - DELETE test1.t1, test2.t2 FROM <...>
+--echo #####################################################################################
+
+let $MYSQLD_DATADIR= `select @@datadir`;
+--replace_regex /server id [0-9]*/server id #/ /server v [^ ]*/server v #.##.##/ /exec_time=[0-9]*/exec_time=#/ /thread_id=[0-9]*/thread_id=#/ /table id [0-9]*/table id #/ /mapped to number [0-9]*/mapped to number #/ /end_log_pos [0-9]*/end_log_pos #/ /# at [0-9]*/# at #/
+--exec $MYSQL_BINLOG --base64-output=decode-rows --database=test1 -v -v --read-from-remote-server --user=root --host=localhost --port=$MASTER_MYPORT master-bin.000001
+
+--echo #
+--echo #####################################################################################
+--echo # mysqlbinlog --read-from-remote-server --skip-annotate-rows-events
+--echo # No Annotates should appear in this output
+--echo #####################################################################################
+
+let $MYSQLD_DATADIR= `select @@datadir`;
+--replace_regex /server id [0-9]*/server id #/ /server v [^ ]*/server v #.##.##/ /exec_time=[0-9]*/exec_time=#/ /thread_id=[0-9]*/thread_id=#/ /table id [0-9]*/table id #/ /mapped to number [0-9]*/mapped to number #/ /end_log_pos [0-9]*/end_log_pos #/ /# at [0-9]*/# at #/
+--exec $MYSQL_BINLOG --base64-output=decode-rows --skip-annotate-rows-events -v -v --read-from-remote-server --user=root --host=localhost --port=$MASTER_MYPORT master-bin.000001
+
+# Clean-up
+
+--disable_query_log
+DROP DATABASE test1;
+DROP DATABASE test2;
+DROP DATABASE test3;
+DROP DATABASE xtest1;
+DROP DATABASE xtest2;
+--enable_query_log
+
diff --git a/mysql-test/suite/maria/r/maria-connect.result b/mysql-test/suite/maria/r/maria-connect.result
index a02c29f3d5f..45675deb098 100644
--- a/mysql-test/suite/maria/r/maria-connect.result
+++ b/mysql-test/suite/maria/r/maria-connect.result
@@ -14,10 +14,10 @@ a
2
3
4
-SHOW BINLOG EVENTS FROM 106;
+SHOW BINLOG EVENTS FROM <start_pos>;
Log_name Pos Event_type Server_id End_log_pos Info
-master-bin.000001 106 Query 1 204 use `test`; CREATE TABLE t1 (a int primary key)
-master-bin.000001 204 Query 1 295 use `test`; insert t1 values (1),(2),(3)
-master-bin.000001 295 Query 1 386 use `test`; insert t1 values (4),(2),(5)
+master-bin.000001 # Query 1 # use `test`; CREATE TABLE t1 (a int primary key)
+master-bin.000001 # Query 1 # use `test`; insert t1 values (1),(2),(3)
+master-bin.000001 # Query 1 # use `test`; insert t1 values (4),(2),(5)
drop table t1;
set binlog_format=default;
diff --git a/mysql-test/suite/maria/t/maria-connect.test b/mysql-test/suite/maria/t/maria-connect.test
index 9efb5844bc2..a1e9bbce4f2 100644
--- a/mysql-test/suite/maria/t/maria-connect.test
+++ b/mysql-test/suite/maria/t/maria-connect.test
@@ -4,6 +4,9 @@
-- source include/have_maria.inc
-- source include/have_log_bin.inc
+-- source include/binlog_start_pos.inc
+
+let $start_pos= `select @binlog_start_pos`;
let $default=`select @@global.storage_engine`;
set global storage_engine=aria;
@@ -27,7 +30,9 @@ insert t1 values (1),(2),(3);
--error ER_DUP_ENTRY
insert t1 values (4),(2),(5);
select * from t1;
-SHOW BINLOG EVENTS FROM 106;
+--replace_result $start_pos <start_pos>
+--replace_column 2 # 5 #
+eval SHOW BINLOG EVENTS FROM $start_pos;
drop table t1;
set binlog_format=default;
diff --git a/mysql-test/suite/rpl/r/rpl_deadlock_innodb.result b/mysql-test/suite/rpl/r/rpl_deadlock_innodb.result
index 1485389204b..a894e1a4971 100644
--- a/mysql-test/suite/rpl/r/rpl_deadlock_innodb.result
+++ b/mysql-test/suite/rpl/r/rpl_deadlock_innodb.result
@@ -55,7 +55,7 @@ Checking that both slave threads are running.
*** Test lock wait timeout ***
include/stop_slave.inc
DELETE FROM t2;
-CHANGE MASTER TO MASTER_LOG_POS=MASTER_POS_BEGIN;
+CHANGE MASTER TO MASTER_LOG_POS=<master_pos_begin>;
BEGIN;
SELECT * FROM t1 FOR UPDATE;
a
@@ -81,7 +81,7 @@ SET @my_max_relay_log_size= @@global.max_relay_log_size;
SET global max_relay_log_size=0;
include/stop_slave.inc
DELETE FROM t2;
-CHANGE MASTER TO MASTER_LOG_POS=MASTER_POS_BEGIN;
+CHANGE MASTER TO MASTER_LOG_POS=<master_pos_begin>;
BEGIN;
SELECT * FROM t1 FOR UPDATE;
a
diff --git a/mysql-test/suite/rpl/r/rpl_row_annotate_do.result b/mysql-test/suite/rpl/r/rpl_row_annotate_do.result
new file mode 100644
index 00000000000..34405b9cbba
--- /dev/null
+++ b/mysql-test/suite/rpl/r/rpl_row_annotate_do.result
@@ -0,0 +1,144 @@
+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;
+########################################################################
+# TABLES ON MASTER
+########################################################################
+SELECT * FROM t1 ORDER BY a;
+a b
+0 1
+SELECT * FROM t2 ORDER BY a;
+a b
+SELECT * FROM t3 ORDER BY a;
+a b
+1 1
+2 2
+3 3
+SELECT * FROM t5 ORDER BY a;
+a b
+1 foo
+2 bar
+3 baz
+4 gås
+5 gås
+########################################################################
+# TABLES ON SLAVE: should be the same as on master
+########################################################################
+SELECT * FROM t1 ORDER BY a;
+a b
+0 1
+SELECT * FROM t2 ORDER BY a;
+a b
+SELECT * FROM t3 ORDER BY a;
+a b
+1 1
+2 2
+3 3
+SELECT * FROM t5 ORDER BY a;
+a b
+1 foo
+2 bar
+3 baz
+4 gås
+5 gås
+########################################################################
+# EVENTS ON SLAVE
+# The following Annotate_rows events should appear below:
+# - UPDATE t1 SET b = b + 1;
+# - REPLACE t1 VALUES (1,1), (2,2), (3,3);
+# - INSERT INTO t2 VALUES (1,1), (2,2), (3,3)
+# - INSERT INTO t3 VALUES (1,1), (2,2), (3,3)
+# - DELETE t1, t2 FROM <...>
+# - INSERT INTO t2 VALUES (1,1), (2,2), (3,3)
+# - DELETE xt1, t2 FROM <...>
+# - INSERT INTO t5(b) VALUES <...> (3 instances)
+########################################################################
+FLUSH LOGS;
+show binlog events in 'slave-bin.000001' from <start_pos>;
+Log_name Pos Event_type Server_id End_log_pos Info
+slave-bin.000001 # Query 1 # DROP DATABASE IF EXISTS test1
+slave-bin.000001 # Query 1 # CREATE DATABASE test1
+slave-bin.000001 # Query 1 # use `test1`; CREATE TABLE t1(a int primary key, b int)
+slave-bin.000001 # Query 1 # use `test1`; CREATE TABLE t2(a int, b int)
+slave-bin.000001 # Query 1 # use `test1`; CREATE TABLE t3(a int, b int)
+slave-bin.000001 # Query 1 # use `test1`; CREATE TABLE t4(a int, b int)
+slave-bin.000001 # Query 1 # use `test1`; CREATE TABLE t5 (
+a INT PRIMARY KEY AUTO_INCREMENT,
+b VARCHAR(10) CHARACTER SET utf8 COLLATE utf8_bin
+)
+slave-bin.000001 # Query 1 # BEGIN
+slave-bin.000001 # Table_map 1 # table_id: # (test1.t1)
+slave-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
+slave-bin.000001 # Query 1 # COMMIT
+slave-bin.000001 # Query 1 # BEGIN
+slave-bin.000001 # Annotate_rows 1 # UPDATE t1 SET b = b + 1
+slave-bin.000001 # Table_map 1 # table_id: # (test1.t1)
+slave-bin.000001 # Update_rows 1 # table_id: # flags: STMT_END_F
+slave-bin.000001 # Query 1 # COMMIT
+slave-bin.000001 # Query 1 # BEGIN
+slave-bin.000001 # Annotate_rows 1 # REPLACE t1 VALUES (1,1), (2,2), (3,3)
+slave-bin.000001 # Table_map 1 # table_id: # (test1.t1)
+slave-bin.000001 # Update_rows 1 # table_id: #
+slave-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
+slave-bin.000001 # Query 1 # COMMIT
+slave-bin.000001 # Query 1 # BEGIN
+slave-bin.000001 # Annotate_rows 1 # INSERT INTO t2 VALUES (1,1), (2,2), (3,3)
+slave-bin.000001 # Table_map 1 # table_id: # (test1.t2)
+slave-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
+slave-bin.000001 # Query 1 # COMMIT
+slave-bin.000001 # Query 1 # BEGIN
+slave-bin.000001 # Annotate_rows 1 # INSERT INTO t3 VALUES (1,1), (2,2), (3,3)
+slave-bin.000001 # Table_map 1 # table_id: # (test1.t3)
+slave-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
+slave-bin.000001 # Query 1 # COMMIT
+slave-bin.000001 # Query 1 # BEGIN
+slave-bin.000001 # Annotate_rows 1 # DELETE t1, t2 FROM t1 INNER JOIN t2 INNER JOIN t3 WHERE t1.a=t2.a AND t2.a=t3.a
+slave-bin.000001 # Table_map 1 # table_id: # (test1.t2)
+slave-bin.000001 # Table_map 1 # table_id: # (test1.t1)
+slave-bin.000001 # Delete_rows 1 # table_id: #
+slave-bin.000001 # Delete_rows 1 # table_id: # flags: STMT_END_F
+slave-bin.000001 # Query 1 # COMMIT
+slave-bin.000001 # Query 1 # BEGIN
+slave-bin.000001 # Annotate_rows 1 # INSERT INTO t2 VALUES (1,1), (2,2), (3,3)
+slave-bin.000001 # Table_map 1 # table_id: # (test1.t2)
+slave-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
+slave-bin.000001 # Query 1 # COMMIT
+slave-bin.000001 # Query 1 # BEGIN
+slave-bin.000001 # Annotate_rows 1 # DELETE xt1, t2 FROM xt1 INNER JOIN t2 INNER JOIN t3 WHERE xt1.a=t2.a AND t2.a=t3.a
+slave-bin.000001 # Table_map 1 # table_id: # (test1.t2)
+slave-bin.000001 # Delete_rows 1 # table_id: # flags: STMT_END_F
+slave-bin.000001 # Query 1 # COMMIT
+slave-bin.000001 # Query 1 # BEGIN
+slave-bin.000001 # Annotate_rows 1 # INSERT INTO t5(b) VALUES ('foo'), ('bar'), ('baz')
+slave-bin.000001 # Table_map 1 # table_id: # (test1.t5)
+slave-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
+slave-bin.000001 # Query 1 # COMMIT
+slave-bin.000001 # Query 1 # BEGIN
+slave-bin.000001 # Annotate_rows 1 # INSERT INTO t5(b) VALUES ('gås')
+slave-bin.000001 # Table_map 1 # table_id: # (test1.t5)
+slave-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
+slave-bin.000001 # Query 1 # COMMIT
+slave-bin.000001 # Query 1 # BEGIN
+slave-bin.000001 # Annotate_rows 1 # INSERT INTO t5(b) VALUES ('gås')
+slave-bin.000001 # Table_map 1 # table_id: # (test1.t5)
+slave-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
+slave-bin.000001 # Query 1 # COMMIT
+slave-bin.000001 # Rotate 2 # slave-bin.000002;pos=4
+#
+########################################################################
+# INSERTs DELAYED ON MASTERs
+########################################################################
+SET SESSION binlog_annotate_rows_events = ON;
+INSERT DELAYED INTO test1.t4 VALUES (1,1);
+FLUSH TABLES;
+SELECT * FROM test1.t4 ORDER BY a;
+a b
+1 1
+########################################################################
+# ON SLAVE
+# No Annotate_rows events should appear below
+########################################################################
+FLUSH LOGS;
diff --git a/mysql-test/suite/rpl/r/rpl_row_annotate_dont.result b/mysql-test/suite/rpl/r/rpl_row_annotate_dont.result
new file mode 100644
index 00000000000..0c04c6abf61
--- /dev/null
+++ b/mysql-test/suite/rpl/r/rpl_row_annotate_dont.result
@@ -0,0 +1,126 @@
+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;
+########################################################################
+# TABLES ON MASTER
+########################################################################
+SELECT * FROM t1 ORDER BY a;
+a b
+0 1
+SELECT * FROM t2 ORDER BY a;
+a b
+SELECT * FROM t3 ORDER BY a;
+a b
+1 1
+2 2
+3 3
+SELECT * FROM t5 ORDER BY a;
+a b
+1 foo
+2 bar
+3 baz
+4 gås
+5 gås
+########################################################################
+# TABLES ON SLAVE: should be the same as on master
+########################################################################
+SELECT * FROM t1 ORDER BY a;
+a b
+0 1
+SELECT * FROM t2 ORDER BY a;
+a b
+SELECT * FROM t3 ORDER BY a;
+a b
+1 1
+2 2
+3 3
+SELECT * FROM t5 ORDER BY a;
+a b
+1 foo
+2 bar
+3 baz
+4 gås
+5 gås
+########################################################################
+# EVENTS ON SLAVE
+# No Annotate_rows events should appear below
+########################################################################
+FLUSH LOGS;
+show binlog events in 'slave-bin.000001' from <start_pos>;
+Log_name Pos Event_type Server_id End_log_pos Info
+slave-bin.000001 # Query 1 # DROP DATABASE IF EXISTS test1
+slave-bin.000001 # Query 1 # CREATE DATABASE test1
+slave-bin.000001 # Query 1 # use `test1`; CREATE TABLE t1(a int primary key, b int)
+slave-bin.000001 # Query 1 # use `test1`; CREATE TABLE t2(a int, b int)
+slave-bin.000001 # Query 1 # use `test1`; CREATE TABLE t3(a int, b int)
+slave-bin.000001 # Query 1 # use `test1`; CREATE TABLE t4(a int, b int)
+slave-bin.000001 # Query 1 # use `test1`; CREATE TABLE t5 (
+a INT PRIMARY KEY AUTO_INCREMENT,
+b VARCHAR(10) CHARACTER SET utf8 COLLATE utf8_bin
+)
+slave-bin.000001 # Query 1 # BEGIN
+slave-bin.000001 # Table_map 1 # table_id: # (test1.t1)
+slave-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
+slave-bin.000001 # Query 1 # COMMIT
+slave-bin.000001 # Query 1 # BEGIN
+slave-bin.000001 # Table_map 1 # table_id: # (test1.t1)
+slave-bin.000001 # Update_rows 1 # table_id: # flags: STMT_END_F
+slave-bin.000001 # Query 1 # COMMIT
+slave-bin.000001 # Query 1 # BEGIN
+slave-bin.000001 # Table_map 1 # table_id: # (test1.t1)
+slave-bin.000001 # Update_rows 1 # table_id: #
+slave-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
+slave-bin.000001 # Query 1 # COMMIT
+slave-bin.000001 # Query 1 # BEGIN
+slave-bin.000001 # Table_map 1 # table_id: # (test1.t2)
+slave-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
+slave-bin.000001 # Query 1 # COMMIT
+slave-bin.000001 # Query 1 # BEGIN
+slave-bin.000001 # Table_map 1 # table_id: # (test1.t3)
+slave-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
+slave-bin.000001 # Query 1 # COMMIT
+slave-bin.000001 # Query 1 # BEGIN
+slave-bin.000001 # Table_map 1 # table_id: # (test1.t2)
+slave-bin.000001 # Table_map 1 # table_id: # (test1.t1)
+slave-bin.000001 # Delete_rows 1 # table_id: #
+slave-bin.000001 # Delete_rows 1 # table_id: # flags: STMT_END_F
+slave-bin.000001 # Query 1 # COMMIT
+slave-bin.000001 # Query 1 # BEGIN
+slave-bin.000001 # Table_map 1 # table_id: # (test1.t2)
+slave-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
+slave-bin.000001 # Query 1 # COMMIT
+slave-bin.000001 # Query 1 # BEGIN
+slave-bin.000001 # Table_map 1 # table_id: # (test1.t2)
+slave-bin.000001 # Delete_rows 1 # table_id: # flags: STMT_END_F
+slave-bin.000001 # Query 1 # COMMIT
+slave-bin.000001 # Query 1 # BEGIN
+slave-bin.000001 # Table_map 1 # table_id: # (test1.t5)
+slave-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
+slave-bin.000001 # Query 1 # COMMIT
+slave-bin.000001 # Query 1 # BEGIN
+slave-bin.000001 # Table_map 1 # table_id: # (test1.t5)
+slave-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
+slave-bin.000001 # Query 1 # COMMIT
+slave-bin.000001 # Query 1 # BEGIN
+slave-bin.000001 # Table_map 1 # table_id: # (test1.t5)
+slave-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
+slave-bin.000001 # Query 1 # COMMIT
+slave-bin.000001 # Rotate 2 # slave-bin.000002;pos=4
+#
+########################################################################
+# INSERTs DELAYED ON MASTERs
+########################################################################
+SET SESSION binlog_annotate_rows_events = ON;
+INSERT DELAYED INTO test1.t4 VALUES (1,1);
+FLUSH TABLES;
+SELECT * FROM test1.t4 ORDER BY a;
+a b
+1 1
+########################################################################
+# ON SLAVE
+# No Annotate_rows events should appear below
+########################################################################
+FLUSH LOGS;
diff --git a/mysql-test/suite/rpl/r/rpl_row_conflicts.result b/mysql-test/suite/rpl/r/rpl_row_conflicts.result
index 0f15bfc7156..70303bf0159 100644
--- a/mysql-test/suite/rpl/r/rpl_row_conflicts.result
+++ b/mysql-test/suite/rpl/r/rpl_row_conflicts.result
@@ -24,7 +24,7 @@ a
1
[on slave]
---- Wait until slave stops with an error ----
-Last_SQL_Error = Could not execute Write_rows event on table test.t1; Duplicate entry '1' for key 'PRIMARY', Error_code: 1062; handler error HA_ERR_FOUND_DUPP_KEY; the event's master log master-bin.000001, end_log_pos 346 (expected "duplicate key" error)
+Last_SQL_Error = Could not execute Write_rows event on table test.t1; Duplicate entry '1' for key 'PRIMARY', Error_code: 1062; handler error HA_ERR_FOUND_DUPP_KEY; the event's master log master-bin.000001, end_log_pos 480 (expected "duplicate key" error)
SELECT * FROM t1;
a
1
@@ -50,7 +50,7 @@ SELECT * FROM t1;
a
[on slave]
---- Wait until slave stops with an error ----
-Last_SQL_Error = Could not execute Delete_rows event on table test.t1; Can't find record in 't1', Error_code: 1032; handler error HA_ERR_KEY_NOT_FOUND; the event's master log master-bin.000001, end_log_pos 982 (expected "can't find record" error)
+Last_SQL_Error = Could not execute Delete_rows event on table test.t1; Can't find record in 't1', Error_code: 1032; handler error HA_ERR_KEY_NOT_FOUND; the event's master log master-bin.000001, end_log_pos 1116 (expected "can't find record" error)
SELECT * FROM t1;
a
---- Resolve the conflict on the slave and restart SQL thread ----
diff --git a/mysql-test/suite/rpl/t/rpl_row_annotate_do-slave.opt b/mysql-test/suite/rpl/t/rpl_row_annotate_do-slave.opt
new file mode 100644
index 00000000000..aa3af621897
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_row_annotate_do-slave.opt
@@ -0,0 +1 @@
+--log-slave-updates --replicate-annotate-rows-events --replicate-ignore-table=test1.xt1 --replicate-ignore-table=test1.xt2 \ No newline at end of file
diff --git a/mysql-test/suite/rpl/t/rpl_row_annotate_do.test b/mysql-test/suite/rpl/t/rpl_row_annotate_do.test
new file mode 100644
index 00000000000..b61ce0ab6d8
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_row_annotate_do.test
@@ -0,0 +1,16 @@
+###############################################################################
+# WL47: Store in binlog text of statements that caused RBR events
+# Wrapper for extra/rpl/rpl_row_annotate.test.
+# Intended to test that if the --replicate-annotate-rows-events option
+# is switched on on slave then Annotate_events:
+# - are reproduced on slave
+# - are reproduced only once for "multi-table-maps" rbr queries
+# - are not reproduced when the corresponding queries are filtered away
+# on replication
+# - are reproduced when the corresponding queries are filtered away partialy
+# (e.g. in case of multi-delete)
+# - are not generated on slave for queries that are not annotated on master.
+###############################################################################
+
+--source include/have_binlog_format_row.inc
+--source extra/rpl_tests/rpl_row_annotate.test
diff --git a/mysql-test/suite/rpl/t/rpl_row_annotate_dont-slave.opt b/mysql-test/suite/rpl/t/rpl_row_annotate_dont-slave.opt
new file mode 100644
index 00000000000..74ac3bfefcb
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_row_annotate_dont-slave.opt
@@ -0,0 +1 @@
+--log-slave-updates --replicate-ignore-table=test1.xt1 --replicate-ignore-table=test1.xt2 \ No newline at end of file
diff --git a/mysql-test/suite/rpl/t/rpl_row_annotate_dont.test b/mysql-test/suite/rpl/t/rpl_row_annotate_dont.test
new file mode 100644
index 00000000000..56765c591aa
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_row_annotate_dont.test
@@ -0,0 +1,9 @@
+###############################################################################
+# WL47: Store in binlog text of statements that caused RBR events
+# Wrapper for extra/rpl/rpl_row_annotate.test.
+# Intended to test that if the --replicate-annotate-rows-events option
+# is switched off on slave then Annotate_events are not reproduced.
+###############################################################################
+
+--source include/have_binlog_format_row.inc
+--source extra/rpl_tests/rpl_row_annotate.test
diff --git a/mysql-test/suite/rpl/t/rpl_row_flsh_tbls.test b/mysql-test/suite/rpl/t/rpl_row_flsh_tbls.test
index 064a7c89dbe..8764b35a537 100644
--- a/mysql-test/suite/rpl/t/rpl_row_flsh_tbls.test
+++ b/mysql-test/suite/rpl/t/rpl_row_flsh_tbls.test
@@ -1,7 +1,8 @@
# depends on the binlog output
-- source include/have_binlog_format_row.inc
+--source include/binlog_start_pos.inc
-let $rename_event_pos= 925;
+let $rename_event_pos= `select @binlog_start_pos + 819`;
# Bug#18326: Do not lock table for writing during prepare of statement
# The use of the ps protocol causes extra table maps in the binlog, so
diff --git a/mysql-test/suite/rpl/t/rpl_row_mysqlbinlog.test b/mysql-test/suite/rpl/t/rpl_row_mysqlbinlog.test
index 7515249fe0c..ecbca6fc077 100644
--- a/mysql-test/suite/rpl/t/rpl_row_mysqlbinlog.test
+++ b/mysql-test/suite/rpl/t/rpl_row_mysqlbinlog.test
@@ -164,15 +164,18 @@ connection master;
remove_file $MYSQLTEST_VARDIR/tmp/master.sql;
+--source include/binlog_start_pos.inc
# this test for position option
-# By setting this position to 416, we should only get the create of t3
+# By setting this position to start_binlog_pos + 310, we should only get the create of t3
+let $start_pos= `select @binlog_start_pos + 310`;
+let $stop_pos= `select @binlog_start_pos + 463`;
--disable_query_log
select "--- Test 2 position test --" as "";
--enable_query_log
let $MYSQLD_DATADIR= `select @@datadir;`;
--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
---exec $MYSQL_BINLOG --short-form --local-load=$MYSQLTEST_VARDIR/tmp/ --position=416 --stop-position=569 $MYSQLD_DATADIR/master-bin.000001
+--exec $MYSQL_BINLOG --short-form --local-load=$MYSQLTEST_VARDIR/tmp/ --position=$start_pos --stop-position=$stop_pos $MYSQLD_DATADIR/master-bin.000001
# These are tests for remote binlog.
# They should return the same as previous test.
@@ -183,7 +186,7 @@ select "--- Test 3 First Remote test --" as "";
# This is broken now
--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
---exec $MYSQL_BINLOG --short-form --local-load=$MYSQLTEST_VARDIR/tmp/ --stop-position=569 --read-from-remote-server --user=root --host=127.0.0.1 --port=$MASTER_MYPORT master-bin.000001
+--exec $MYSQL_BINLOG --short-form --local-load=$MYSQLTEST_VARDIR/tmp/ --stop-position=$stop_pos --read-from-remote-server --user=root --host=127.0.0.1 --port=$MASTER_MYPORT master-bin.000001
# This part is disabled due to bug #17654
@@ -259,7 +262,7 @@ connection master;
select "--- Test 5 LOAD DATA --" as "";
--enable_query_log
--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
---exec $MYSQL_BINLOG --short-form --local-load=$MYSQLTEST_VARDIR/tmp/ --stop-position=106 --read-from-remote-server --user=root --host=127.0.0.1 --port=$MASTER_MYPORT master-bin.000002
+--exec $MYSQL_BINLOG --short-form --local-load=$MYSQLTEST_VARDIR/tmp/ --stop-position=$binlog_start_pos --read-from-remote-server --user=root --host=127.0.0.1 --port=$MASTER_MYPORT master-bin.000002
# Bug#7853 (mysqlbinlog does not accept input from stdin)
@@ -267,14 +270,17 @@ select "--- Test 5 LOAD DATA --" as "";
select "--- Test 6 reading stdin --" as "";
--enable_query_log
let $MYSQLD_DATADIR= `select @@datadir;`;
+let $stop_pos= `select @binlog_start_pos + 463`;
--replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR
---exec $MYSQL_BINLOG --short-form --stop-position=569 - < $MYSQLD_DATADIR/master-bin.000001
+--exec $MYSQL_BINLOG --short-form --stop-position=$stop_pos - < $MYSQLD_DATADIR/master-bin.000001
--disable_query_log
select "--- Test 7 reading stdin w/position --" as "";
--enable_query_log
+let $start_pos= `select @binlog_start_pos + 310`;
+let $stop_pos= `select @binlog_start_pos + 463`;
--replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR
---exec $MYSQL_BINLOG --short-form --position=416 --stop-position=569 - < $MYSQLD_DATADIR/master-bin.000001
+--exec $MYSQL_BINLOG --short-form --position=$start_pos --stop-position=$stop_pos - < $MYSQLD_DATADIR/master-bin.000001
# Bug#16217 (mysql client did not know how not switch its internal charset)
--disable_query_log
diff --git a/mysql-test/suite/rpl/t/rpl_stm_flsh_tbls.test b/mysql-test/suite/rpl/t/rpl_stm_flsh_tbls.test
index dad61002be4..cffa70ac9ce 100644
--- a/mysql-test/suite/rpl/t/rpl_stm_flsh_tbls.test
+++ b/mysql-test/suite/rpl/t/rpl_stm_flsh_tbls.test
@@ -1,7 +1,8 @@
# depends on the binlog output
--source include/have_binlog_format_mixed_or_statement.inc
+--source include/binlog_start_pos.inc
-let $rename_event_pos= 684;
+let $rename_event_pos= `select @binlog_start_pos + 578`;
-- source extra/rpl_tests/rpl_flsh_tbls.test
# End of 4.1 tests
diff --git a/mysql-test/t/ctype_cp932_binlog_stm.test b/mysql-test/t/ctype_cp932_binlog_stm.test
index f3038ccfa61..b1f34ec22d4 100644
--- a/mysql-test/t/ctype_cp932_binlog_stm.test
+++ b/mysql-test/t/ctype_cp932_binlog_stm.test
@@ -28,14 +28,6 @@ delimiter ;|
--echo End of 5.0 tests
-#
-# #28436: Incorrect position in SHOW BINLOG EVENTS causes server coredump
-# Note: 364 is a magic position (found experimentally, depends on
-# the log's contents) that caused the server crash.
-
---error 1220
-SHOW BINLOG EVENTS FROM 365;
-
--echo Bug#44352 UPPER/LOWER function doesn't work correctly on cp932 and sjis environment.
CREATE TABLE t1 (a varchar(16)) character set cp932;
INSERT INTO t1 VALUES (0x8372835E),(0x8352835E);
diff --git a/mysql-test/t/mysqlbinlog-master.opt b/mysql-test/t/mysqlbinlog-master.opt
deleted file mode 100644
index ac1a87c73b3..00000000000
--- a/mysql-test/t/mysqlbinlog-master.opt
+++ /dev/null
@@ -1 +0,0 @@
---max-binlog-size=4096
diff --git a/mysql-test/t/mysqlbinlog.test b/mysql-test/t/mysqlbinlog.test
index 783708cc3b2..3c58affa0f3 100644
--- a/mysql-test/t/mysqlbinlog.test
+++ b/mysql-test/t/mysqlbinlog.test
@@ -3,10 +3,18 @@
-- source include/have_binlog_format_statement.inc
-- source include/have_log_bin.inc
+-- source include/binlog_start_pos.inc
# Deletes all the binary logs
reset master;
+# We need small binlog size to break the last LOAD DATA INFILE below so that
+# the corresponding Begin_load_query will be written to master-bin.000001
+# while the Execute_load_query will be written to master-bin.000002.
+
+SET @save_binlog_size= @@global.max_binlog_size;
+SET @@global.max_binlog_size= 4096;
+
# we need this for getting fixed timestamps inside of this test
set timestamp=1000000000;
@@ -26,13 +34,15 @@ insert into t2 values ();
# test for load data and load data distributed among the several
# files (we need to fill up first binlog)
-load data infile '../../std_data/words.dat' into table t1;
-load data infile '../../std_data/words.dat' into table t1;
-load data infile '../../std_data/words.dat' into table t1;
-load data infile '../../std_data/words.dat' into table t1;
-load data infile '../../std_data/words.dat' into table t1;
+load data infile '../../std_data/words3.dat' into table t1;
+load data infile '../../std_data/words3.dat' into table t1;
+load data infile '../../std_data/words3.dat' into table t1;
+load data infile '../../std_data/words3.dat' into table t1;
+load data infile '../../std_data/words3.dat' into table t1;
# simple query to show more in second binlog
insert into t1 values ("Alas");
+
+### Starting master-bin.000003
flush logs;
# delimiters are for easier debugging in future
@@ -46,7 +56,7 @@ select "--- Local --" as "";
#
let $MYSQLD_DATADIR= `select @@datadir`;
--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
---replace_regex /SQL_LOAD_MB-[0-9]-[0-9]/SQL_LOAD_MB-#-#/
+--replace_regex /SQL_LOAD_MB-[0-9a-f]+-[0-9a-f]+/SQL_LOAD_MB-#-#/
--exec $MYSQL_BINLOG --short-form --local-load=$MYSQLTEST_VARDIR/tmp/ $MYSQLD_DATADIR/master-bin.000001
# this should not fail but shouldn't produce any working statements
@@ -54,7 +64,7 @@ let $MYSQLD_DATADIR= `select @@datadir`;
select "--- Broken LOAD DATA --" as "";
--enable_query_log
--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
---replace_regex /SQL_LOAD_MB-[0-9]-[0-9]/SQL_LOAD_MB-#-#/
+--replace_regex /SQL_LOAD_MB-[0-9a-f]+-[0-9a-f]+/SQL_LOAD_MB-#-#/
--exec $MYSQL_BINLOG --short-form --local-load=$MYSQLTEST_VARDIR/tmp/ $MYSQLD_DATADIR/master-bin.000002 2> /dev/null
# this should show almost nothing
@@ -62,17 +72,17 @@ select "--- Broken LOAD DATA --" as "";
select "--- --database --" as "";
--enable_query_log
--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
---replace_regex /SQL_LOAD_MB-[0-9]-[0-9]/SQL_LOAD_MB-#-#/
+--replace_regex /SQL_LOAD_MB-[0-9a-f]+-[0-9a-f]+/SQL_LOAD_MB-#-#/
--exec $MYSQL_BINLOG --short-form --local-load=$MYSQLTEST_VARDIR/tmp/ --database=nottest $MYSQLD_DATADIR/master-bin.000001 2> /dev/null
# this test for position option
--disable_query_log
select "--- --position --" as "";
--enable_query_log
+let $start_pos= `select @binlog_start_pos + 227`;
--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
---replace_regex /SQL_LOAD_MB-[0-9]-[0-9]/SQL_LOAD_MB-#-#/
---exec $MYSQL_BINLOG --short-form --local-load=$MYSQLTEST_VARDIR/tmp/ --position=332 $MYSQLD_DATADIR/master-bin.000002
-
+--replace_regex /SQL_LOAD_MB-[0-9a-f]+-[0-9a-f]+/SQL_LOAD_MB-#-#/
+--exec $MYSQL_BINLOG --short-form --local-load=$MYSQLTEST_VARDIR/tmp/ --position=$start_pos $MYSQLD_DATADIR/master-bin.000002
# These are tests for remote binlog.
# They should return the same as previous test.
@@ -83,7 +93,7 @@ select "--- Remote --" as "";
# This is broken now
--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
---replace_regex /SQL_LOAD_MB-[0-9]-[0-9]/SQL_LOAD_MB-#-#/
+--replace_regex /SQL_LOAD_MB-[0-9a-f]+-[0-9a-f]+/SQL_LOAD_MB-#-#/
--exec $MYSQL_BINLOG --short-form --local-load=$MYSQLTEST_VARDIR/tmp/ --read-from-remote-server --user=root --host=127.0.0.1 --port=$MASTER_MYPORT master-bin.000001
# This is broken too
@@ -91,7 +101,7 @@ select "--- Remote --" as "";
select "--- Broken LOAD DATA --" as "";
--enable_query_log
--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
---replace_regex /SQL_LOAD_MB-[0-9]-[0-9]/SQL_LOAD_MB-#-#/
+--replace_regex /SQL_LOAD_MB-[0-9a-f]+-[0-9a-f]+/SQL_LOAD_MB-#-#/
--exec $MYSQL_BINLOG --short-form --local-load=$MYSQLTEST_VARDIR/tmp/ --read-from-remote-server --user=root --host=127.0.0.1 --port=$MASTER_MYPORT master-bin.000002 2> /dev/null
# And this too ! (altough it is documented)
@@ -99,34 +109,39 @@ select "--- Broken LOAD DATA --" as "";
select "--- --database --" as "";
--enable_query_log
--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
---replace_regex /SQL_LOAD_MB-[0-9]-[0-9]/SQL_LOAD_MB-#-#/
+--replace_regex /SQL_LOAD_MB-[0-9a-f]+-[0-9a-f]+/SQL_LOAD_MB-#-#/
--exec $MYSQL_BINLOG --short-form --local-load=$MYSQLTEST_VARDIR/tmp/ --read-from-remote-server --user=root --host=127.0.0.1 --port=$MASTER_MYPORT --database=nottest master-bin.000001 2> /dev/null
# Strangely but this works
--disable_query_log
select "--- --position --" as "";
--enable_query_log
+let $start_pos= `select @binlog_start_pos + 227`;
--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
---replace_regex /SQL_LOAD_MB-[0-9]-[0-9]/SQL_LOAD_MB-#-#/
---exec $MYSQL_BINLOG --short-form --local-load=$MYSQLTEST_VARDIR/tmp/ --read-from-remote-server --position=332 --user=root --host=127.0.0.1 --port=$MASTER_MYPORT master-bin.000002
+--replace_regex /SQL_LOAD_MB-[0-9a-f]+-[0-9a-f]+/SQL_LOAD_MB-#-#/
+--exec $MYSQL_BINLOG --short-form --local-load=$MYSQLTEST_VARDIR/tmp/ --read-from-remote-server --position=$start_pos --user=root --host=127.0.0.1 --port=$MASTER_MYPORT master-bin.000002
# Bug#7853 mysqlbinlog does not accept input from stdin
--disable_query_log
select "--- reading stdin --" as "";
--enable_query_log
--replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR
---replace_regex /SQL_LOAD_MB-[0-9]-[0-9]/SQL_LOAD_MB-#-#/
+--replace_regex /SQL_LOAD_MB-[0-9a-f]+-[0-9a-f]+/SQL_LOAD_MB-#-#/
--exec $MYSQL_BINLOG --short-form - < $MYSQL_TEST_DIR/std_data/trunc_binlog.000001
--replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR
---replace_regex /SQL_LOAD_MB-[0-9]-[0-9]/SQL_LOAD_MB-#-#/
+--replace_regex /SQL_LOAD_MB-[0-9a-f]+-[0-9a-f]+/SQL_LOAD_MB-#-#/
--exec $MYSQL_BINLOG --short-form --position=79 - < $MYSQL_TEST_DIR/std_data/trunc_binlog.000001
drop table t1,t2;
+SET @@global.max_binlog_size= @save_binlog_size;
+
#
# Bug#14157 utf8 encoding in binlog without set character_set_client
#
+### Starting master-bin.000004
flush logs;
+
--write_file $MYSQLTEST_VARDIR/tmp/bug14157.sql
create table if not exists t5 (a int);
set names latin1;
@@ -140,6 +155,8 @@ EOF
# resulted binlog, parly consisting of multi-byte utf8 chars,
# must be digestable for both client and server. In 4.1 the client
# should use default-character-set same as the server.
+
+### Starting master-bin.000005
flush logs;
--exec $MYSQL_BINLOG --short-form $MYSQLD_DATADIR/master-bin.000004 | $MYSQL
select * from t5 /* must be (1),(1) */;
@@ -150,6 +167,8 @@ drop table t5;
# Check that a dump created by mysqlbinlog reproduces
# lc_time_names dependent values correctly
#
+
+### Starting master-bin.000006
flush logs;
create table t5 (c1 int, c2 varchar(128) character set latin1 not null);
insert into t5 values (1, date_format('2001-01-01','%W'));
@@ -158,7 +177,10 @@ insert into t5 values (2, date_format('2001-01-01','%W'));
set lc_time_names=en_US;
insert into t5 values (3, date_format('2001-01-01','%W'));
select * from t5 order by c1;
+
+### Starting master-bin.000007
flush logs;
+
drop table t5;
--exec $MYSQL_BINLOG --short-form $MYSQLD_DATADIR/master-bin.000006 | $MYSQL
select * from t5 order by c1;
@@ -170,7 +192,10 @@ drop table t5;
--disable_warnings
drop procedure if exists p1;
--enable_warnings
+
+### Starting master-bin.000008
flush logs;
+
delimiter //;
create procedure p1()
begin
@@ -178,12 +203,15 @@ select 1;
end;
//
delimiter ;//
+
+### Starting master-bin.000009
flush logs;
+
call p1();
drop procedure p1;
--error ER_SP_DOES_NOT_EXIST
call p1();
---replace_regex /SQL_LOAD_MB-[0-9]-[0-9]/SQL_LOAD_MB-#-#/
+--replace_regex /SQL_LOAD_MB-[0-9a-f]+-[0-9a-f]+/SQL_LOAD_MB-#-#/
--exec $MYSQL_BINLOG --short-form $MYSQLD_DATADIR/master-bin.000008
--exec $MYSQL_BINLOG --short-form $MYSQLD_DATADIR/master-bin.000008 | $MYSQL
call p1();
@@ -202,7 +230,9 @@ drop procedure p1;
# (LOAD DATA INFILE need it)
#
+### Starting master-bin.000010
flush logs;
+
create table t1 (a varchar(64) character set utf8);
load data infile '../../std_data/loaddata6.dat' into table t1;
set character_set_database=koi8r;
@@ -217,9 +247,12 @@ load data infile '../../std_data/loaddata6.dat' into table t1;
load data infile '../../std_data/loaddata6.dat' into table t1 character set koi8r;
select hex(a) from t1;
drop table t1;
+
+### Starting master-bin.000011
flush logs;
+
--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
---replace_regex /SQL_LOAD_MB-[0-9]-[0-9]/SQL_LOAD_MB-#-#/
+--replace_regex /SQL_LOAD_MB-[0-9a-f]+-[0-9a-f]+/SQL_LOAD_MB-#-#/
--exec $MYSQL_BINLOG --short-form --local-load=$MYSQLTEST_VARDIR/tmp/ $MYSQLD_DATADIR/master-bin.000010
#
@@ -229,9 +262,14 @@ flush logs;
CREATE TABLE t1 (c1 CHAR(10));
# we need this for getting fixed timestamps inside of this test
+### Starting master-bin.000012
FLUSH LOGS;
+
INSERT INTO t1 VALUES ('0123456789');
+
+### Starting master-bin.000013
FLUSH LOGS;
+
DROP TABLE t1;
# We create a table, patch, and load the output into it
@@ -257,11 +295,16 @@ DROP TABLE patch;
#
# Bug#29928 incorrect connection_id() restoring from mysqlbinlog out
#
+### Starting master-bin.000014
FLUSH LOGS;
+
CREATE TABLE t1(a INT);
INSERT INTO t1 VALUES(connection_id());
let $a= `SELECT a FROM t1`;
+
+### Starting master-bin.000015
FLUSH LOGS;
+
let $outfile= $MYSQLTEST_VARDIR/tmp/bug29928.sql;
--exec $MYSQL_BINLOG $MYSQLD_DATADIR/master-bin.000014 > $outfile
DROP TABLE t1;
@@ -281,11 +324,12 @@ error 1;
exec $MYSQL_BINLOG $MYSQL_TEST_DIR/std_data/corrupt-relay-bin.000624 > $MYSQLTEST_VARDIR/tmp/bug31793.sql;
--remove_file $MYSQLTEST_VARDIR/tmp/bug31793.sql
-
#
# Test --disable-force-if-open and --force-if-open
#
+### Starting master-bin.000016
FLUSH LOGS;
+
--error 1
--exec $MYSQL_BINLOG $MYSQLD_DATADIR/master-bin.000016 >/dev/null 2>/dev/null
--exec $MYSQL_BINLOG --force-if-open $MYSQLD_DATADIR/master-bin.000016 >/dev/null 2>/dev/null
@@ -300,9 +344,15 @@ GRANT SELECT ON mysqltest1.* TO untrusted@localhost;
SHOW GRANTS FOR untrusted@localhost;
USE mysqltest1;
CREATE TABLE t1 (a INT, b CHAR(64));
+
+### Starting master-bin.000017
flush logs;
+
INSERT INTO t1 VALUES (1,USER());
+
+### Starting master-bin.000018
flush logs;
+
echo mysqlbinlog var/log/master-bin.000017 > var/tmp/bug31611.sql;
exec $MYSQL_BINLOG $MYSQLD_DATADIR/master-bin.000017 > $MYSQLTEST_VARDIR/tmp/bug31611.sql;
connect (unsecure,localhost,untrusted,,mysqltest1);
@@ -326,14 +376,20 @@ DROP USER untrusted@localhost;
connection default;
USE test;
SET BINLOG_FORMAT = STATEMENT;
+
+### Starting master-bin.000019
FLUSH LOGS;
+
CREATE TABLE t1 (a_real FLOAT, an_int INT, a_decimal DECIMAL(5,2), a_string CHAR(32));
SET @a_real = rand(20) * 1000;
SET @an_int = 1000;
SET @a_decimal = CAST(rand(19) * 999 AS DECIMAL(5,2));
SET @a_string = 'Just a test';
INSERT INTO t1 VALUES (@a_real, @an_int, @a_decimal, @a_string);
+
+### Starting master-bin.000020
FLUSH LOGS;
+
query_vertical SELECT * FROM t1;
DROP TABLE t1;
@@ -357,6 +413,7 @@ eval SET @@global.server_id= $s_id_max;
RESET MASTER;
FLUSH LOGS;
+
--exec $MYSQL_BINLOG $MYSQLD_DATADIR/master-bin.000001 > $binlog_file
--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
eval SELECT
diff --git a/mysql-test/t/mysqlbinlog2.test b/mysql-test/t/mysqlbinlog2.test
index d6be029ea56..57adde7b975 100644
--- a/mysql-test/t/mysqlbinlog2.test
+++ b/mysql-test/t/mysqlbinlog2.test
@@ -3,7 +3,7 @@
# TODO: Need to look at making row based version once new binlog client is complete.
-- source include/have_binlog_format_mixed_or_statement.inc
-
+-- source include/binlog_start_pos.inc
--disable_warnings
drop table if exists t1;
@@ -50,15 +50,19 @@ select "--- offset --" as "";
--disable_query_log
select "--- start-position --" as "";
--enable_query_log
---exec $MYSQL_BINLOG --short-form --start-position=608 $MYSQLD_DATADIR/master-bin.000001
+let $start_pos= `select @binlog_start_pos + 502`;
+--exec $MYSQL_BINLOG --short-form --start-position=$start_pos $MYSQLD_DATADIR/master-bin.000001
--disable_query_log
select "--- stop-position --" as "";
--enable_query_log
---exec $MYSQL_BINLOG --short-form --stop-position=608 $MYSQLD_DATADIR/master-bin.000001
+let $stop_pos= `select @binlog_start_pos + 502`;
+--exec $MYSQL_BINLOG --short-form --stop-position=$stop_pos $MYSQLD_DATADIR/master-bin.000001
--disable_query_log
select "--- start and stop positions ---" as "";
--enable_query_log
---exec $MYSQL_BINLOG --short-form --start-position=608 --stop-position 725 $MYSQLD_DATADIR/master-bin.000001
+let $start_pos= `select @binlog_start_pos + 502`;
+let $stop_pos= `select @binlog_start_pos + 619`;
+--exec $MYSQL_BINLOG --short-form --start-position=$start_pos --stop-position $stop_pos $MYSQLD_DATADIR/master-bin.000001
--disable_query_log
select "--- start-datetime --" as "";
--enable_query_log
@@ -84,11 +88,13 @@ select "--- offset --" as "";
--disable_query_log
select "--- start-position --" as "";
--enable_query_log
---exec $MYSQL_BINLOG --short-form --start-position=608 $MYSQLD_DATADIR/master-bin.000001 $MYSQLD_DATADIR/master-bin.000002
+let $start_pos= `select @binlog_start_pos + 502`;
+--exec $MYSQL_BINLOG --short-form --start-position=$start_pos $MYSQLD_DATADIR/master-bin.000001 $MYSQLD_DATADIR/master-bin.000002
--disable_query_log
select "--- stop-position --" as "";
--enable_query_log
---exec $MYSQL_BINLOG --short-form --stop-position=134 $MYSQLD_DATADIR/master-bin.000001 $MYSQLD_DATADIR/master-bin.000002
+let $stop_pos= `select @binlog_start_pos + 28`;
+--exec $MYSQL_BINLOG --short-form --stop-position=$stop_pos $MYSQLD_DATADIR/master-bin.000001 $MYSQLD_DATADIR/master-bin.000002
--disable_query_log
select "--- start-datetime --" as "";
--enable_query_log
@@ -111,15 +117,19 @@ select "--- offset --" as "";
--disable_query_log
select "--- start-position --" as "";
--enable_query_log
---exec $MYSQL_BINLOG --short-form --start-position=608 --read-from-remote-server --user=root --host=127.0.0.1 --port=$MASTER_MYPORT master-bin.000001
+let $start_pos= `select @binlog_start_pos + 502`;
+--exec $MYSQL_BINLOG --short-form --start-position=$start_pos --read-from-remote-server --user=root --host=127.0.0.1 --port=$MASTER_MYPORT master-bin.000001
--disable_query_log
select "--- stop-position --" as "";
--enable_query_log
---exec $MYSQL_BINLOG --short-form --stop-position=608 --read-from-remote-server --user=root --host=127.0.0.1 --port=$MASTER_MYPORT master-bin.000001
+let $stop_pos= `select @binlog_start_pos + 502`;
+--exec $MYSQL_BINLOG --short-form --stop-position=$stop_pos --read-from-remote-server --user=root --host=127.0.0.1 --port=$MASTER_MYPORT master-bin.000001
--disable_query_log
select "--- start and stop positions ---" as "";
--enable_query_log
---exec $MYSQL_BINLOG --short-form --start-position=608 --stop-position 725 --read-from-remote-server --user=root --host=127.0.0.1 --port=$MASTER_MYPORT master-bin.000001
+let $start_pos= `select @binlog_start_pos + 502`;
+let $stop_pos= `select @binlog_start_pos + 619`;
+--exec $MYSQL_BINLOG --short-form --start-position=$start_pos --stop-position $stop_pos --read-from-remote-server --user=root --host=127.0.0.1 --port=$MASTER_MYPORT master-bin.000001
--disable_query_log
select "--- start-datetime --" as "";
--enable_query_log
@@ -142,11 +152,13 @@ select "--- offset --" as "";
--disable_query_log
select "--- start-position --" as "";
--enable_query_log
---exec $MYSQL_BINLOG --short-form --start-position=608 --read-from-remote-server --user=root --host=127.0.0.1 --port=$MASTER_MYPORT master-bin.000001 master-bin.000002
+let $start_pos= `select @binlog_start_pos + 502`;
+--exec $MYSQL_BINLOG --short-form --start-position=$start_pos --read-from-remote-server --user=root --host=127.0.0.1 --port=$MASTER_MYPORT master-bin.000001 master-bin.000002
--disable_query_log
select "--- stop-position --" as "";
--enable_query_log
---exec $MYSQL_BINLOG --short-form --stop-position=134 --read-from-remote-server --user=root --host=127.0.0.1 --port=$MASTER_MYPORT master-bin.000001 master-bin.000002
+let $stop_pos= `select @binlog_start_pos + 28`;
+--exec $MYSQL_BINLOG --short-form --stop-position=$stop_pos --read-from-remote-server --user=root --host=127.0.0.1 --port=$MASTER_MYPORT master-bin.000001 master-bin.000002
--disable_query_log
select "--- start-datetime --" as "";
--enable_query_log
diff --git a/sql/handler.cc b/sql/handler.cc
index e851d9248c2..9bfbc816d3f 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -4699,7 +4699,8 @@ static bool check_table_binlog_row_based(THD *thd, TABLE *table)
/** @brief
Write table maps for all (manually or automatically) locked tables
- to the binary log.
+ to the binary log. Also, if binlog_annotate_rows_events is ON,
+ write Annotate_rows event before the first table map.
SYNOPSIS
write_locked_table_maps()
@@ -4736,6 +4737,9 @@ static int write_locked_table_maps(THD *thd)
locks[0]= thd->extra_lock;
locks[1]= thd->lock;
locks[2]= thd->locked_tables;
+ my_bool with_annotate= thd->variables.binlog_annotate_rows_events &&
+ thd->query() && thd->query_length();
+
for (uint i= 0 ; i < sizeof(locks)/sizeof(*locks) ; ++i )
{
MYSQL_LOCK const *const lock= locks[i];
@@ -4753,7 +4757,8 @@ static int write_locked_table_maps(THD *thd)
check_table_binlog_row_based(thd, table))
{
int const has_trans= table->file->has_transactions();
- int const error= thd->binlog_write_table_map(table, has_trans);
+ int const error= thd->binlog_write_table_map(table, has_trans,
+ &with_annotate);
/*
If an error occurs, it is the responsibility of the caller to
roll back the transaction.
diff --git a/sql/log.cc b/sql/log.cc
index e853fedc3d1..4e07bd76739 100644
--- a/sql/log.cc
+++ b/sql/log.cc
@@ -4175,10 +4175,12 @@ void THD::binlog_set_stmt_begin() {
/*
- Write a table map to the binary log.
+ Write a table map to the binary log. If with_annotate != NULL and
+ *with_annotate = TRUE write also Annotate_rows before the table map.
*/
-int THD::binlog_write_table_map(TABLE *table, bool is_trans)
+int THD::binlog_write_table_map(TABLE *table, bool is_trans,
+ my_bool *with_annotate)
{
int error;
DBUG_ENTER("THD::binlog_write_table_map");
@@ -4196,7 +4198,7 @@ int THD::binlog_write_table_map(TABLE *table, bool is_trans)
if (is_trans && binlog_table_maps == 0)
binlog_start_trans_and_stmt();
- if ((error= mysql_bin_log.write(&the_event)))
+ if ((error= mysql_bin_log.write(&the_event, with_annotate)))
DBUG_RETURN(error);
binlog_table_maps++;
@@ -4326,10 +4328,12 @@ MYSQL_BIN_LOG::flush_and_set_pending_rows_event(THD *thd,
}
/**
- Write an event to the binary log.
+ Write an event to the binary log. If with_annotate != NULL and
+ *with_annotate = TRUE write also Annotate_rows before the event
+ (this should happen only if the event is a Table_map).
*/
-bool MYSQL_BIN_LOG::write(Log_event *event_info)
+bool MYSQL_BIN_LOG::write(Log_event *event_info, my_bool *with_annotate)
{
THD *thd= event_info->thd;
bool error= 1;
@@ -4448,6 +4452,16 @@ bool MYSQL_BIN_LOG::write(Log_event *event_info)
of the SQL command
*/
+ if (with_annotate && *with_annotate)
+ {
+ DBUG_ASSERT(event_info->get_type_code() == TABLE_MAP_EVENT);
+ Annotate_rows_log_event anno(thd);
+ /* Annotate event should be written not more than once */
+ *with_annotate= 0;
+ if (anno.write(file))
+ goto err;
+ }
+
/*
If row-based binlogging, Insert_id, Rand and other kind of "setting
context" events are not needed.
diff --git a/sql/log.h b/sql/log.h
index 8ee94ab5807..491be35bd04 100644
--- a/sql/log.h
+++ b/sql/log.h
@@ -357,7 +357,8 @@ public:
void new_file();
void reset_gathered_updates(THD *thd);
- bool write(Log_event* event_info); // binary log write
+ bool write(Log_event* event_info,
+ my_bool *with_annotate= 0); // binary log write
bool write(THD *thd, IO_CACHE *cache, Log_event *commit_event, bool incident);
bool write_incident(THD *thd, bool lock);
int write_cache(THD *thd, IO_CACHE *cache, bool lock_log,
diff --git a/sql/log_event.cc b/sql/log_event.cc
index fb4fc5b79b3..d4f71194121 100644
--- a/sql/log_event.cc
+++ b/sql/log_event.cc
@@ -649,6 +649,7 @@ const char* Log_event::get_type_str(Log_event_type type)
case BEGIN_LOAD_QUERY_EVENT: return "Begin_load_query";
case EXECUTE_LOAD_QUERY_EVENT: return "Execute_load_query";
case INCIDENT_EVENT: return "Incident";
+ case ANNOTATE_ROWS_EVENT: return "Annotate_rows";
default: return "Unknown"; /* impossible */
}
}
@@ -728,7 +729,7 @@ Log_event::Log_event(const char* buf,
logs are in 4.0 format, until it finds a Format_desc).
*/
if (description_event->binlog_version==3 &&
- buf[EVENT_TYPE_OFFSET]<FORMAT_DESCRIPTION_EVENT && log_pos)
+ (uchar)buf[EVENT_TYPE_OFFSET]<FORMAT_DESCRIPTION_EVENT && log_pos)
{
/*
If log_pos=0, don't change it. log_pos==0 is a marker to mean
@@ -746,8 +747,8 @@ Log_event::Log_event(const char* buf,
DBUG_PRINT("info", ("log_pos: %lu", (ulong) log_pos));
flags= uint2korr(buf + FLAGS_OFFSET);
- if ((buf[EVENT_TYPE_OFFSET] == FORMAT_DESCRIPTION_EVENT) ||
- (buf[EVENT_TYPE_OFFSET] == ROTATE_EVENT))
+ if (((uchar)buf[EVENT_TYPE_OFFSET] == FORMAT_DESCRIPTION_EVENT) ||
+ ((uchar)buf[EVENT_TYPE_OFFSET] == ROTATE_EVENT))
{
/*
These events always have a header which stops here (i.e. their
@@ -1168,14 +1169,14 @@ Log_event* Log_event::read_log_event(const char* buf, uint event_len,
/* Check the integrity */
if (event_len < EVENT_LEN_OFFSET ||
- buf[EVENT_TYPE_OFFSET] >= ENUM_END_EVENT ||
+ (uchar)buf[EVENT_TYPE_OFFSET] >= ENUM_END_EVENT ||
(uint) event_len != uint4korr(buf+EVENT_LEN_OFFSET))
{
*error="Sanity check failed"; // Needed to free buffer
DBUG_RETURN(NULL); // general sanity check - will fail on a partial read
}
- uint event_type= buf[EVENT_TYPE_OFFSET];
+ uint event_type= (uchar)buf[EVENT_TYPE_OFFSET];
if (event_type > description_event->number_of_event_types &&
event_type != FORMAT_DESCRIPTION_EVENT)
{
@@ -1297,6 +1298,9 @@ Log_event* Log_event::read_log_event(const char* buf, uint event_len,
case INCIDENT_EVENT:
ev = new Incident_log_event(buf, event_len, description_event);
break;
+ case ANNOTATE_ROWS_EVENT:
+ ev = new Annotate_rows_log_event(buf, event_len, description_event);
+ break;
default:
DBUG_PRINT("error",("Unknown event code: %d",
(int) buf[EVENT_TYPE_OFFSET]));
@@ -3795,6 +3799,13 @@ Format_description_log_event(uint8 binlog_ver, const char* server_ver)
post_header_len[DELETE_ROWS_EVENT-1]= 6;);
post_header_len[INCIDENT_EVENT-1]= INCIDENT_HEADER_LEN;
+ // Set header length of the reserved events to 0
+ memset(post_header_len + MYSQL_EVENTS_END - 1, 0,
+ (MARIA_EVENTS_BEGIN - MYSQL_EVENTS_END)*sizeof(uint8));
+
+ // Set header lengths of Maria events
+ post_header_len[ANNOTATE_ROWS_EVENT-1]= ANNOTATE_ROWS_HEADER_LEN;
+
// Sanity-check that all post header lengths are initialized.
IF_DBUG({
int i;
@@ -4439,8 +4450,8 @@ Load_log_event::Load_log_event(const char *buf, uint event_len,
*/
if (event_len)
copy_log_event(buf, event_len,
- ((buf[EVENT_TYPE_OFFSET] == LOAD_EVENT) ?
- LOAD_HEADER_LEN +
+ (((uchar)buf[EVENT_TYPE_OFFSET] == LOAD_EVENT) ?
+ LOAD_HEADER_LEN +
description_event->common_header_len :
LOAD_HEADER_LEN + LOG_EVENT_HEADER_LEN),
description_event);
@@ -4477,7 +4488,7 @@ int Load_log_event::copy_log_event(const char *buf, ulong event_len,
*/
if (!(field_lens= (uchar*)sql_ex.init((char*)buf + body_offset,
buf_end,
- buf[EVENT_TYPE_OFFSET] != LOAD_EVENT)))
+ (uchar)buf[EVENT_TYPE_OFFSET] != LOAD_EVENT)))
DBUG_RETURN(1);
data_len = event_len - body_offset;
@@ -6172,7 +6183,7 @@ Create_file_log_event::Create_file_log_event(const char* buf, uint len,
uint8 create_file_header_len= description_event->post_header_len[CREATE_FILE_EVENT-1];
if (!(event_buf= (char*) my_memdup(buf, len, MYF(MY_WME))) ||
copy_log_event(event_buf,len,
- ((buf[EVENT_TYPE_OFFSET] == LOAD_EVENT) ?
+ (((uchar)buf[EVENT_TYPE_OFFSET] == LOAD_EVENT) ?
load_header_len + header_len :
(fake_base ? (header_len+load_header_len) :
(header_len+load_header_len) +
@@ -7925,6 +7936,141 @@ void Rows_log_event::print_helper(FILE *file,
#endif
/**************************************************************************
+ Annotate_rows_log_event member functions
+**************************************************************************/
+
+#ifndef MYSQL_CLIENT
+Annotate_rows_log_event::Annotate_rows_log_event(THD *thd)
+ : Log_event(thd, 0, true),
+ m_save_thd_query_txt(0),
+ m_save_thd_query_len(0)
+{
+ m_query_txt= thd->query();
+ m_query_len= thd->query_length();
+}
+#endif
+
+Annotate_rows_log_event::Annotate_rows_log_event(const char *buf,
+ uint event_len,
+ const Format_description_log_event *desc)
+ : Log_event(buf, desc),
+ m_save_thd_query_txt(0),
+ m_save_thd_query_len(0)
+{
+ m_query_len= event_len - desc->common_header_len;
+ m_query_txt= (char*) buf + desc->common_header_len;
+}
+
+Annotate_rows_log_event::~Annotate_rows_log_event()
+{
+#ifndef MYSQL_CLIENT
+ if (m_save_thd_query_txt)
+ thd->set_query(m_save_thd_query_txt, m_save_thd_query_len);
+#endif
+}
+
+int Annotate_rows_log_event::get_data_size()
+{
+ return m_query_len;
+}
+
+Log_event_type Annotate_rows_log_event::get_type_code()
+{
+ return ANNOTATE_ROWS_EVENT;
+}
+
+bool Annotate_rows_log_event::is_valid() const
+{
+ return (m_query_txt != NULL && m_query_len != 0);
+}
+
+#ifndef MYSQL_CLIENT
+bool Annotate_rows_log_event::write_data_header(IO_CACHE *file)
+{
+ return 0;
+}
+#endif
+
+#ifndef MYSQL_CLIENT
+bool Annotate_rows_log_event::write_data_body(IO_CACHE *file)
+{
+ return my_b_safe_write(file, (uchar*) m_query_txt, m_query_len);
+}
+#endif
+
+#if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION)
+void Annotate_rows_log_event::pack_info(Protocol* protocol)
+{
+ if (m_query_txt && m_query_len)
+ protocol->store(m_query_txt, m_query_len, &my_charset_bin);
+}
+#endif
+
+#ifdef MYSQL_CLIENT
+void Annotate_rows_log_event::print(FILE *file, PRINT_EVENT_INFO *pinfo)
+{
+ if (pinfo->short_form)
+ return;
+
+ print_header(&pinfo->head_cache, pinfo, TRUE);
+ my_b_printf(&pinfo->head_cache, "\tAnnotate_rows:\n");
+
+ char *pbeg; // beginning of the next line
+ char *pend; // end of the next line
+ uint cnt= 0; // characters counter
+
+ for (pbeg= m_query_txt; ; pbeg= pend)
+ {
+ // skip all \r's and \n's at the beginning of the next line
+ for (;; pbeg++)
+ {
+ if (++cnt > m_query_len)
+ return;
+
+ if (*pbeg != '\r' && *pbeg != '\n')
+ break;
+ }
+
+ // find end of the next line
+ for (pend= pbeg + 1;
+ ++cnt <= m_query_len && *pend != '\r' && *pend != '\n';
+ pend++);
+
+ // print next line
+ my_b_write(&pinfo->head_cache, (const uchar*) "#Q> ", 4);
+ my_b_write(&pinfo->head_cache, (const uchar*) pbeg, pend - pbeg);
+ my_b_write(&pinfo->head_cache, (const uchar*) "\n", 1);
+ }
+}
+#endif
+
+#if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION)
+int Annotate_rows_log_event::do_apply_event(Relay_log_info const *rli)
+{
+ m_save_thd_query_txt= thd->query();
+ m_save_thd_query_len= thd->query_length();
+ thd->set_query(m_query_txt, m_query_len);
+ return 0;
+}
+#endif
+
+#if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION)
+int Annotate_rows_log_event::do_update_pos(Relay_log_info *rli)
+{
+ rli->inc_event_relay_log_pos();
+ return 0;
+}
+#endif
+
+#if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION)
+Log_event::enum_skip_reason
+Annotate_rows_log_event::do_shall_skip(Relay_log_info *rli)
+{
+ return continue_group(rli);
+}
+#endif
+
+/**************************************************************************
Table_map_log_event member functions and support functions
**************************************************************************/
diff --git a/sql/log_event.h b/sql/log_event.h
index 770fb29301b..6593929eb91 100644
--- a/sql/log_event.h
+++ b/sql/log_event.h
@@ -250,6 +250,7 @@ struct sql_ex_info
#define EXECUTE_LOAD_QUERY_EXTRA_HEADER_LEN (4 + 4 + 4 + 1)
#define EXECUTE_LOAD_QUERY_HEADER_LEN (QUERY_HEADER_LEN + EXECUTE_LOAD_QUERY_EXTRA_HEADER_LEN)
#define INCIDENT_HEADER_LEN 2
+#define ANNOTATE_ROWS_HEADER_LEN 0
/*
Max number of possible extra bytes in a replication event compared to a
packet (i.e. a query) sent from client to master;
@@ -582,8 +583,14 @@ enum Log_event_type
*/
INCIDENT_EVENT= 26,
+ /* New MySQL/Sun events are to be added right above this comment */
+ MYSQL_EVENTS_END,
+
+ MARIA_EVENTS_BEGIN= 160,
+ /* New Maria event numbers start from here */
+ ANNOTATE_ROWS_EVENT= 160,
+
/*
- Add new events here - right above this comment!
Existing events (except ENUM_END_EVENT) should never change their numbers
*/
@@ -2988,6 +2995,59 @@ public:
char *str_to_hex(char *to, const char *from, uint len);
/**
+ @class Annotate_rows_log_event
+
+ In row-based mode, if binlog_annotate_rows_events = ON, each group of
+ Table_map_log_events is preceded by an Annotate_rows_log_event which
+ contains the query which caused the subsequent rows operations.
+
+ The Annotate_rows_log_event has no post-header and its body contains
+ the corresponding query (without trailing zero). Note. The query length
+ is to be calculated as a difference between the whole event length and
+ the common header length.
+*/
+class Annotate_rows_log_event: public Log_event
+{
+public:
+#ifndef MYSQL_CLIENT
+ Annotate_rows_log_event(THD*);
+#endif
+ Annotate_rows_log_event(const char *buf, uint event_len,
+ const Format_description_log_event*);
+ ~Annotate_rows_log_event();
+
+ virtual int get_data_size();
+ virtual Log_event_type get_type_code();
+ virtual bool is_valid() const;
+
+#ifndef MYSQL_CLIENT
+ virtual bool write_data_header(IO_CACHE*);
+ virtual bool write_data_body(IO_CACHE*);
+#endif
+
+#if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION)
+ virtual void pack_info(Protocol*);
+#endif
+
+#ifdef MYSQL_CLIENT
+ virtual void print(FILE*, PRINT_EVENT_INFO*);
+#endif
+
+#if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION)
+private:
+ virtual int do_apply_event(Relay_log_info const*);
+ virtual int do_update_pos(Relay_log_info*);
+ virtual enum_skip_reason do_shall_skip(Relay_log_info*);
+#endif
+
+private:
+ char *m_query_txt;
+ uint m_query_len;
+ char *m_save_thd_query_txt;
+ uint m_save_thd_query_len;
+};
+
+/**
@class Table_map_log_event
In row-based mode, every row operation event is preceded by a
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index 3f836a5ab1f..1b3c56ceae4 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -611,7 +611,11 @@ protected:
/* BINLOG_DUMP options */
#define BINLOG_DUMP_NON_BLOCK 1
+#endif /* !MYSQL_CLIENT */
+#define BINLOG_SEND_ANNOTATE_ROWS_EVENT 2
+
+#ifndef MYSQL_CLIENT
/* sql_show.cc:show_log_files() */
#define SHOW_LOG_STATUS_FREE "FREE"
#define SHOW_LOG_STATUS_INUSE "IN USE"
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index 3d6879e5b23..bc03beaf46d 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -512,6 +512,7 @@ my_bool opt_local_infile, opt_slave_compressed_protocol;
my_bool opt_safe_user_create = 0, opt_no_mix_types = 0;
my_bool opt_show_slave_auth_info, opt_sql_bin_update = 0;
my_bool opt_log_slave_updates= 0;
+my_bool opt_replicate_annotate_rows_events= 0;
bool slave_warning_issued = false;
/*
@@ -5870,6 +5871,8 @@ enum options_mysqld
OPT_REPLICATE_IGNORE_DB, OPT_LOG_SLAVE_UPDATES,
OPT_BINLOG_DO_DB, OPT_BINLOG_IGNORE_DB,
OPT_BINLOG_FORMAT,
+ OPT_BINLOG_ANNOTATE_ROWS_EVENTS,
+ OPT_REPLICATE_ANNOTATE_ROWS_EVENTS,
#ifndef DBUG_OFF
OPT_BINLOG_SHOW_XID,
#endif
@@ -6096,6 +6099,18 @@ struct my_option my_long_options[] =
#endif
, &opt_binlog_format, &opt_binlog_format,
0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ {"binlog-annotate-rows-events", OPT_BINLOG_ANNOTATE_ROWS_EVENTS,
+ "Tells the master to annotate RBR events with the statement that "
+ "caused these events.",
+ (uchar**) &global_system_variables.binlog_annotate_rows_events,
+ (uchar**) &max_system_variables.binlog_annotate_rows_events,
+ 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
+ {"replicate-annotate-rows-events", OPT_REPLICATE_ANNOTATE_ROWS_EVENTS,
+ "Tells the slave to write annotate rows events recieved from the master "
+ "to its own binary log. Sensible only in pair with log-slave-updates option.",
+ (uchar**) &opt_replicate_annotate_rows_events,
+ (uchar**) &opt_replicate_annotate_rows_events,
+ 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
{"binlog-do-db", OPT_BINLOG_DO_DB,
"Tells the master it should log updates for the specified database, "
"and exclude all others not explicitly mentioned.",
diff --git a/sql/rpl_rli.cc b/sql/rpl_rli.cc
index c37c4735e37..a2d0b1e4904 100644
--- a/sql/rpl_rli.cc
+++ b/sql/rpl_rli.cc
@@ -38,7 +38,8 @@ Relay_log_info::Relay_log_info()
inited(0), abort_slave(0), slave_running(0), until_condition(UNTIL_NONE),
until_log_pos(0), retried_trans(0),
tables_to_lock(0), tables_to_lock_count(0),
- last_event_start_time(0), m_flags(0)
+ last_event_start_time(0), m_flags(0),
+ m_annotate_event(0)
{
DBUG_ENTER("Relay_log_info::Relay_log_info");
@@ -72,6 +73,7 @@ Relay_log_info::~Relay_log_info()
pthread_cond_destroy(&stop_cond);
pthread_cond_destroy(&log_space_cond);
relay_log.cleanup();
+ free_annotate_event();
DBUG_VOID_RETURN;
}
diff --git a/sql/rpl_rli.h b/sql/rpl_rli.h
index 5cafcf47086..0ea3c23bfd8 100644
--- a/sql/rpl_rli.h
+++ b/sql/rpl_rli.h
@@ -423,8 +423,46 @@ public:
(m_flags & (1UL << IN_STMT));
}
+ /**
+ Save pointer to Annotate_rows event and switch on the
+ binlog_annotate_rows_events for this sql thread.
+ To be called when sql thread recieves an Annotate_rows event.
+ */
+ inline void set_annotate_event(Annotate_rows_log_event *event)
+ {
+ free_annotate_event();
+ m_annotate_event= event;
+ sql_thd->variables.binlog_annotate_rows_events= 1;
+ }
+
+ /**
+ Returns pointer to the saved Annotate_rows event or NULL if there is
+ no saved event.
+ */
+ inline Annotate_rows_log_event* get_annotate_event()
+ {
+ return m_annotate_event;
+ }
+
+ /**
+ Delete saved Annotate_rows event (if any) and switch off the
+ binlog_annotate_rows_events for this sql thread.
+ To be called when sql thread has applied the last (i.e. with
+ STMT_END_F flag) rbr event.
+ */
+ inline void free_annotate_event()
+ {
+ if (m_annotate_event)
+ {
+ sql_thd->variables.binlog_annotate_rows_events= 0;
+ delete m_annotate_event;
+ m_annotate_event= 0;
+ }
+ }
+
private:
uint32 m_flags;
+ Annotate_rows_log_event *m_annotate_event;
};
diff --git a/sql/set_var.cc b/sql/set_var.cc
index 910deafc432..894b6519127 100644
--- a/sql/set_var.cc
+++ b/sql/set_var.cc
@@ -182,6 +182,9 @@ static sys_var_const sys_back_log(&vars, "back_log",
OPT_GLOBAL, SHOW_LONG,
(uchar*) &back_log);
static sys_var_const_os_str sys_basedir(&vars, "basedir", mysql_home);
+static sys_var_thd_bool
+sys_binlog_annotate_rows_events(&vars, "binlog_annotate_rows_events",
+ &SV::binlog_annotate_rows_events);
static sys_var_long_ptr sys_binlog_cache_size(&vars, "binlog_cache_size",
&binlog_cache_size);
static sys_var_thd_binlog_format sys_binlog_format(&vars, "binlog_format",
diff --git a/sql/slave.cc b/sql/slave.cc
index 0e41d897dd4..e159645db38 100644
--- a/sql/slave.cc
+++ b/sql/slave.cc
@@ -1867,6 +1867,9 @@ static int request_dump(MYSQL* mysql, Master_info* mi,
*suppress_warnings= FALSE;
+ if (opt_log_slave_updates && opt_replicate_annotate_rows_events)
+ binlog_flags|= BINLOG_SEND_ANNOTATE_ROWS_EVENT;
+
// TODO if big log files: Change next to int8store()
int4store(buf, (ulong) mi->master_log_pos);
int2store(buf + 4, binlog_flags);
@@ -2261,17 +2264,41 @@ static int exec_relay_log_event(THD* thd, Relay_log_info* rli)
}
exec_res= apply_event_and_update_pos(ev, thd, rli);
- /*
- Format_description_log_event should not be deleted because it will be
- used to read info about the relay log's format; it will be deleted when
- the SQL thread does not need it, i.e. when this thread terminates.
- */
- if (ev->get_type_code() != FORMAT_DESCRIPTION_EVENT)
- {
- DBUG_PRINT("info", ("Deleting the event after it has been executed"));
- delete ev;
+ switch (ev->get_type_code()) {
+ case FORMAT_DESCRIPTION_EVENT:
+ /*
+ Format_description_log_event should not be deleted because it
+ will be used to read info about the relay log's format;
+ it will be deleted when the SQL thread does not need it,
+ i.e. when this thread terminates.
+ */
+ break;
+ case ANNOTATE_ROWS_EVENT:
+ /*
+ Annotate_rows event should not be deleted because after it has
+ been applied, thd->query points to the string inside this event.
+ The thd->query will be used to generate new Annotate_rows event
+ during applying the subsequent Rows events.
+ */
+ rli->set_annotate_event((Annotate_rows_log_event*) ev);
+ break;
+ case DELETE_ROWS_EVENT:
+ case UPDATE_ROWS_EVENT:
+ case WRITE_ROWS_EVENT:
+ /*
+ After the last Rows event has been applied, the saved Annotate_rows
+ event (if any) is not needed anymore and can be deleted.
+ */
+ if (((Rows_log_event*)ev)->get_flags(Rows_log_event::STMT_END_F))
+ rli->free_annotate_event();
+ /* fall through */
+ default:
+ DBUG_PRINT("info", ("Deleting the event after it has been executed"));
+ delete ev;
+ break;
}
+
/*
update_log_pos failed: this should not happen, so we don't
retry.
@@ -2899,6 +2926,12 @@ pthread_handler_t handle_slave_sql(void *arg)
thd->init_for_queries();
thd->temporary_tables = rli->save_temporary_tables; // restore temp tables
set_thd_in_use_temporary_tables(rli); // (re)set sql_thd in use for saved temp tables
+ /*
+ binlog_annotate_rows_events must be TRUE only after an Annotate_rows event
+ has been recieved and only till the last corresponding rbr event has been
+ applied. In all other cases it must be FALSE.
+ */
+ thd->variables.binlog_annotate_rows_events= 0;
pthread_mutex_lock(&LOCK_thread_count);
threads.append(thd);
pthread_mutex_unlock(&LOCK_thread_count);
@@ -3382,7 +3415,7 @@ static int queue_binlog_ver_1_event(Master_info *mi, const char *buf,
If we get Load event, we need to pass a non-reusable buffer
to read_log_event, so we do a trick
*/
- if (buf[EVENT_TYPE_OFFSET] == LOAD_EVENT)
+ if ((uchar)buf[EVENT_TYPE_OFFSET] == LOAD_EVENT)
{
if (unlikely(!(tmp_buf=(char*)my_malloc(event_len+1,MYF(MY_WME)))))
{
@@ -3589,13 +3622,13 @@ static int queue_event(Master_info* mi,const char* buf, ulong event_len)
LINT_INIT(inc_pos);
if (mi->rli.relay_log.description_event_for_queue->binlog_version<4 &&
- buf[EVENT_TYPE_OFFSET] != FORMAT_DESCRIPTION_EVENT /* a way to escape */)
+ (uchar)buf[EVENT_TYPE_OFFSET] != FORMAT_DESCRIPTION_EVENT /* a way to escape */)
DBUG_RETURN(queue_old_event(mi,buf,event_len));
LINT_INIT(inc_pos);
pthread_mutex_lock(&mi->data_lock);
- switch (buf[EVENT_TYPE_OFFSET]) {
+ switch ((uchar)buf[EVENT_TYPE_OFFSET]) {
case STOP_EVENT:
/*
We needn't write this event to the relay log. Indeed, it just indicates a
@@ -3698,9 +3731,9 @@ static int queue_event(Master_info* mi,const char* buf, ulong event_len)
the master's binlog (i.e. Format_desc, Rotate & Stop) should not increment
mi->master_log_pos.
*/
- if (buf[EVENT_TYPE_OFFSET]!=FORMAT_DESCRIPTION_EVENT &&
- buf[EVENT_TYPE_OFFSET]!=ROTATE_EVENT &&
- buf[EVENT_TYPE_OFFSET]!=STOP_EVENT)
+ if ((uchar)buf[EVENT_TYPE_OFFSET]!=FORMAT_DESCRIPTION_EVENT &&
+ (uchar)buf[EVENT_TYPE_OFFSET]!=ROTATE_EVENT &&
+ (uchar)buf[EVENT_TYPE_OFFSET]!=STOP_EVENT)
{
mi->master_log_pos+= inc_pos;
memcpy(rli->ign_master_log_name_end, mi->master_log_name, FN_REFLEN);
diff --git a/sql/slave.h b/sql/slave.h
index 1a1cfcebd9b..63dd3afc6b8 100644
--- a/sql/slave.h
+++ b/sql/slave.h
@@ -106,6 +106,7 @@ extern MYSQL_PLUGIN_IMPORT char *relay_log_info_file;
extern char *opt_relay_logname, *opt_relaylog_index_name;
extern my_bool opt_skip_slave_start, opt_reckless_slave;
extern my_bool opt_log_slave_updates;
+extern my_bool opt_replicate_annotate_rows_events;
extern ulonglong relay_log_space_limit;
/*
diff --git a/sql/sql_binlog.cc b/sql/sql_binlog.cc
index da582c37ae9..9a7aac5774b 100644
--- a/sql/sql_binlog.cc
+++ b/sql/sql_binlog.cc
@@ -167,7 +167,7 @@ void mysql_client_binlog_statement(THD* thd)
*/
if (!have_fd_event)
{
- int type = bufptr[EVENT_TYPE_OFFSET];
+ int type = (uchar)bufptr[EVENT_TYPE_OFFSET];
if (type == FORMAT_DESCRIPTION_EVENT || type == START_EVENT_V3)
have_fd_event= TRUE;
else
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 2fe579713e1..ae7994c65c9 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -367,6 +367,7 @@ struct system_variables
ulong ndb_index_stat_cache_entries;
ulong ndb_index_stat_update_freq;
ulong binlog_format; // binlog format for this thd (see enum_binlog_format)
+ my_bool binlog_annotate_rows_events;
my_bool binlog_direct_non_trans_update;
/*
In slave thread we need to know in behalf of which
@@ -1478,7 +1479,8 @@ public:
*/
void binlog_start_trans_and_stmt();
void binlog_set_stmt_begin();
- int binlog_write_table_map(TABLE *table, bool is_transactional);
+ int binlog_write_table_map(TABLE *table, bool is_transactional,
+ my_bool *with_annotate= 0);
int binlog_write_row(TABLE* table, bool is_transactional,
MY_BITMAP const* cols, size_t colcnt,
const uchar *buf);
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index 72ca7310ee1..48105cf9f3c 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -1966,6 +1966,11 @@ bool delayed_get_table(THD *thd, TABLE_LIST *table_list)
pthread_mutex_lock(&LOCK_thread_count);
thread_count++;
pthread_mutex_unlock(&LOCK_thread_count);
+ /*
+ Annotating delayed inserts is not supported.
+ */
+ di->thd.variables.binlog_annotate_rows_events= 0;
+
di->thd.set_db(table_list->db, (uint) strlen(table_list->db));
di->thd.set_query(my_strdup(table_list->table_name, MYF(MY_WME)), 0);
if (di->thd.db == NULL || di->thd.query() == NULL)
diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc
index 95e48c531be..51361fdf6e4 100644
--- a/sql/sql_repl.cc
+++ b/sql/sql_repl.cc
@@ -489,7 +489,7 @@ impossible position";
DBUG_PRINT("info",
("Looked for a Format_description_log_event, found event type %d",
(*packet)[EVENT_TYPE_OFFSET+1]));
- if ((*packet)[EVENT_TYPE_OFFSET+1] == FORMAT_DESCRIPTION_EVENT)
+ if ((uchar)(*packet)[EVENT_TYPE_OFFSET+1] == FORMAT_DESCRIPTION_EVENT)
{
binlog_can_be_corrupted= test((*packet)[FLAGS_OFFSET+1] &
LOG_EVENT_BINLOG_IN_USE_F);
@@ -557,31 +557,36 @@ impossible position";
#endif
if ((*packet)[EVENT_TYPE_OFFSET+1] == FORMAT_DESCRIPTION_EVENT)
+ if ((uchar)(*packet)[EVENT_TYPE_OFFSET+1] == FORMAT_DESCRIPTION_EVENT)
{
binlog_can_be_corrupted= test((*packet)[FLAGS_OFFSET+1] &
LOG_EVENT_BINLOG_IN_USE_F);
(*packet)[FLAGS_OFFSET+1] &= ~LOG_EVENT_BINLOG_IN_USE_F;
}
- else if ((*packet)[EVENT_TYPE_OFFSET+1] == STOP_EVENT)
+ else if ((uchar)(*packet)[EVENT_TYPE_OFFSET+1] == STOP_EVENT)
binlog_can_be_corrupted= FALSE;
- if (my_net_write(net, (uchar*) packet->ptr(), packet->length()))
+ if ((uchar)(*packet)[EVENT_TYPE_OFFSET+1] != ANNOTATE_ROWS_EVENT ||
+ (flags & BINLOG_SEND_ANNOTATE_ROWS_EVENT))
{
- errmsg = "Failed on my_net_write()";
- my_errno= ER_UNKNOWN_ERROR;
- goto err;
- }
+ if (my_net_write(net, (uchar*) packet->ptr(), packet->length()))
+ {
+ errmsg = "Failed on my_net_write()";
+ my_errno= ER_UNKNOWN_ERROR;
+ goto err;
+ }
- DBUG_PRINT("info", ("log event code %d",
- (*packet)[LOG_EVENT_OFFSET+1] ));
- if ((*packet)[LOG_EVENT_OFFSET+1] == LOAD_EVENT)
- {
- if (send_file(thd))
- {
- errmsg = "failed in send_file()";
- my_errno= ER_UNKNOWN_ERROR;
- goto err;
- }
+ DBUG_PRINT("info", ("log event code %d",
+ (*packet)[LOG_EVENT_OFFSET+1] ));
+ if ((uchar)(*packet)[LOG_EVENT_OFFSET+1] == LOAD_EVENT)
+ {
+ if (send_file(thd))
+ {
+ errmsg = "failed in send_file()";
+ my_errno= ER_UNKNOWN_ERROR;
+ goto err;
+ }
+ }
}
packet->set("\0", 1, &my_charset_bin);
}
@@ -677,23 +682,27 @@ impossible position";
if (read_packet)
{
- thd_proc_info(thd, "Sending binlog event to slave");
- if (my_net_write(net, (uchar*) packet->ptr(), packet->length()) )
- {
- errmsg = "Failed on my_net_write()";
- my_errno= ER_UNKNOWN_ERROR;
- goto err;
- }
-
- if ((*packet)[LOG_EVENT_OFFSET+1] == LOAD_EVENT)
- {
- if (send_file(thd))
+ if ((uchar)(*packet)[EVENT_TYPE_OFFSET+1] != ANNOTATE_ROWS_EVENT ||
+ (flags & BINLOG_SEND_ANNOTATE_ROWS_EVENT))
+ {
+ thd_proc_info(thd, "Sending binlog event to slave");
+ if (my_net_write(net, (uchar*) packet->ptr(), packet->length()) )
{
- errmsg = "failed in send_file()";
+ errmsg = "Failed on my_net_write()";
my_errno= ER_UNKNOWN_ERROR;
goto err;
}
- }
+
+ if ((uchar)(*packet)[LOG_EVENT_OFFSET+1] == LOAD_EVENT)
+ {
+ if (send_file(thd))
+ {
+ errmsg = "failed in send_file()";
+ my_errno= ER_UNKNOWN_ERROR;
+ goto err;
+ }
+ }
+ }
packet->set("\0", 1, &my_charset_bin);
/*
No need to net_flush because we will get to flush later when
@@ -1774,6 +1783,11 @@ static sys_var_chain vars = { NULL, NULL };
static sys_var_const sys_log_slave_updates(&vars, "log_slave_updates",
OPT_GLOBAL, SHOW_MY_BOOL,
(uchar*) &opt_log_slave_updates);
+static sys_var_const
+sys_replicate_annotate_rows_events(&vars,
+ "replicate_annotate_rows_events",
+ OPT_GLOBAL, SHOW_MY_BOOL,
+ (uchar*) &opt_replicate_annotate_rows_events);
static sys_var_const sys_relay_log(&vars, "relay_log",
OPT_GLOBAL, SHOW_CHAR_PTR,
(uchar*) &opt_relay_logname);