summaryrefslogtreecommitdiffstats
path: root/mysql-test/suite/binlog/t
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-13 12:24:36 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-13 12:24:36 +0000
commit06eaf7232e9a920468c0f8d74dcf2fe8b555501c (patch)
treee2c7b5777f728320e5b5542b6213fd3591ba51e2 /mysql-test/suite/binlog/t
parentInitial commit. (diff)
downloadmariadb-06eaf7232e9a920468c0f8d74dcf2fe8b555501c.tar.xz
mariadb-06eaf7232e9a920468c0f8d74dcf2fe8b555501c.zip
Adding upstream version 1:10.11.6.upstream/1%10.11.6
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'mysql-test/suite/binlog/t')
-rw-r--r--mysql-test/suite/binlog/t/backup.test19
-rw-r--r--mysql-test/suite/binlog/t/binlog_1pc.test39
-rw-r--r--mysql-test/suite/binlog/t/binlog_admin_cmd_kill.test98
-rw-r--r--mysql-test/suite/binlog/t/binlog_autocommit_off_no_hang-master.opt1
-rw-r--r--mysql-test/suite/binlog/t/binlog_autocommit_off_no_hang.test45
-rw-r--r--mysql-test/suite/binlog/t/binlog_base64_flag.test190
-rw-r--r--mysql-test/suite/binlog/t/binlog_bug23533.test50
-rw-r--r--mysql-test/suite/binlog/t/binlog_bug36391-master.opt1
-rw-r--r--mysql-test/suite/binlog/t/binlog_bug36391.test30
-rw-r--r--mysql-test/suite/binlog/t/binlog_checkpoint.test236
-rw-r--r--mysql-test/suite/binlog/t/binlog_checkpoint_flush_logs.test79
-rw-r--r--mysql-test/suite/binlog/t/binlog_checksum.test37
-rw-r--r--mysql-test/suite/binlog/t/binlog_commit_wait.test229
-rw-r--r--mysql-test/suite/binlog/t/binlog_database.test15
-rw-r--r--mysql-test/suite/binlog/t/binlog_delete_and_flush_index-master.opt1
-rw-r--r--mysql-test/suite/binlog/t/binlog_delete_and_flush_index.test114
-rw-r--r--mysql-test/suite/binlog/t/binlog_dmls_on_tmp_tables_readonly.test92
-rw-r--r--mysql-test/suite/binlog/t/binlog_drop_if_exists.test162
-rw-r--r--mysql-test/suite/binlog/t/binlog_empty_xa_prepared.test148
-rw-r--r--mysql-test/suite/binlog/t/binlog_expire_logs_seconds.test122
-rw-r--r--mysql-test/suite/binlog/t/binlog_expire_warnings.test200
-rw-r--r--mysql-test/suite/binlog/t/binlog_flush_binlogs_delete_domain.test167
-rw-r--r--mysql-test/suite/binlog/t/binlog_format_switch_in_tmp_table.test76
-rw-r--r--mysql-test/suite/binlog/t/binlog_grant.test216
-rw-r--r--mysql-test/suite/binlog/t/binlog_gtid_delete_domain_debug.test11
-rw-r--r--mysql-test/suite/binlog/t/binlog_implicit_commit.test63
-rw-r--r--mysql-test/suite/binlog/t/binlog_incident.test1
-rw-r--r--mysql-test/suite/binlog/t/binlog_index-master.opt1
-rw-r--r--mysql-test/suite/binlog/t/binlog_index.test1
-rw-r--r--mysql-test/suite/binlog/t/binlog_innodb.opt1
-rw-r--r--mysql-test/suite/binlog/t/binlog_innodb.test204
-rw-r--r--mysql-test/suite/binlog/t/binlog_innodb_row.test105
-rw-r--r--mysql-test/suite/binlog/t/binlog_innodb_stm.test26
-rw-r--r--mysql-test/suite/binlog/t/binlog_invalid_read_in_rotate.combinations5
-rw-r--r--mysql-test/suite/binlog/t/binlog_invalid_read_in_rotate.test48
-rw-r--r--mysql-test/suite/binlog/t/binlog_ioerr.test1
-rw-r--r--mysql-test/suite/binlog/t/binlog_killed.test457
-rw-r--r--mysql-test/suite/binlog/t/binlog_killed_simulate-master.opt1
-rw-r--r--mysql-test/suite/binlog/t/binlog_killed_simulate.test61
-rw-r--r--mysql-test/suite/binlog/t/binlog_max_binlog_stmt_cache_size.opt1
-rw-r--r--mysql-test/suite/binlog/t/binlog_max_binlog_stmt_cache_size.test36
-rw-r--r--mysql-test/suite/binlog/t/binlog_max_extension.test87
-rw-r--r--mysql-test/suite/binlog/t/binlog_mdev342-master.opt1
-rw-r--r--mysql-test/suite/binlog/t/binlog_mdev342.test67
-rw-r--r--mysql-test/suite/binlog/t/binlog_mdev717.test46
-rw-r--r--mysql-test/suite/binlog/t/binlog_mixed.test23
-rw-r--r--mysql-test/suite/binlog/t/binlog_mixed_cache_stat.opt1
-rw-r--r--mysql-test/suite/binlog/t/binlog_mixed_cache_stat.test5
-rw-r--r--mysql-test/suite/binlog/t/binlog_mixed_load_data.test15
-rw-r--r--mysql-test/suite/binlog/t/binlog_mysqlbinlog-cp932-master.opt1
-rw-r--r--mysql-test/suite/binlog/t/binlog_mysqlbinlog-cp932.test1
-rw-r--r--mysql-test/suite/binlog/t/binlog_mysqlbinlog2-master.opt1
-rw-r--r--mysql-test/suite/binlog/t/binlog_mysqlbinlog2.test217
-rw-r--r--mysql-test/suite/binlog/t/binlog_mysqlbinlog_base64.test102
-rw-r--r--mysql-test/suite/binlog/t/binlog_mysqlbinlog_do_server_ids.test477
-rw-r--r--mysql-test/suite/binlog/t/binlog_mysqlbinlog_glle_ordered.test43
-rw-r--r--mysql-test/suite/binlog/t/binlog_mysqlbinlog_gtid_strict_mode.test105
-rw-r--r--mysql-test/suite/binlog/t/binlog_mysqlbinlog_gtid_window.test151
-rw-r--r--mysql-test/suite/binlog/t/binlog_mysqlbinlog_raw_flush.test54
-rw-r--r--mysql-test/suite/binlog/t/binlog_mysqlbinlog_row-master.opt1
-rw-r--r--mysql-test/suite/binlog/t/binlog_mysqlbinlog_row.test491
-rw-r--r--mysql-test/suite/binlog/t/binlog_mysqlbinlog_row_frag.test50
-rw-r--r--mysql-test/suite/binlog/t/binlog_mysqlbinlog_row_innodb-master.opt1
-rw-r--r--mysql-test/suite/binlog/t/binlog_mysqlbinlog_row_innodb.test28
-rw-r--r--mysql-test/suite/binlog/t/binlog_mysqlbinlog_row_myisam-master.opt1
-rw-r--r--mysql-test/suite/binlog/t/binlog_mysqlbinlog_row_myisam.test23
-rw-r--r--mysql-test/suite/binlog/t/binlog_mysqlbinlog_row_trans-master.opt1
-rw-r--r--mysql-test/suite/binlog/t/binlog_mysqlbinlog_row_trans.test159
-rw-r--r--mysql-test/suite/binlog/t/binlog_mysqlbinlog_start_alter_verbose.test58
-rw-r--r--mysql-test/suite/binlog/t/binlog_mysqlbinlog_stop_never.test61
-rw-r--r--mysql-test/suite/binlog/t/binlog_mysqlbinlog_suppress_O_TMPFILE.test51
-rw-r--r--mysql-test/suite/binlog/t/binlog_no_uniqfile_crash.test83
-rw-r--r--mysql-test/suite/binlog/t/binlog_old_versions.test153
-rw-r--r--mysql-test/suite/binlog/t/binlog_parallel_replication_ddl.test30
-rw-r--r--mysql-test/suite/binlog/t/binlog_parallel_replication_marks_row.test3
-rw-r--r--mysql-test/suite/binlog/t/binlog_parallel_replication_marks_stm_mix.test3
-rw-r--r--mysql-test/suite/binlog/t/binlog_query_filter_rules-master.opt1
-rw-r--r--mysql-test/suite/binlog/t/binlog_query_filter_rules.test32
-rw-r--r--mysql-test/suite/binlog/t/binlog_recover_checksum_error.test37
-rw-r--r--mysql-test/suite/binlog/t/binlog_rotate_perf.test102
-rw-r--r--mysql-test/suite/binlog/t/binlog_row_annotate-master.opt1
-rw-r--r--mysql-test/suite/binlog/t/binlog_row_annotate.test1
-rw-r--r--mysql-test/suite/binlog/t/binlog_row_binlog-master.opt1
-rw-r--r--mysql-test/suite/binlog/t/binlog_row_binlog.test7
-rw-r--r--mysql-test/suite/binlog/t/binlog_row_cache_stat.test5
-rw-r--r--mysql-test/suite/binlog/t/binlog_row_ctype_cp932.test5
-rw-r--r--mysql-test/suite/binlog/t/binlog_row_ctype_ucs.test6
-rw-r--r--mysql-test/suite/binlog/t/binlog_row_drop_tbl.test5
-rw-r--r--mysql-test/suite/binlog/t/binlog_row_drop_tmp_tbl.test5
-rw-r--r--mysql-test/suite/binlog/t/binlog_row_innodb_stat-master.opt1
-rw-r--r--mysql-test/suite/binlog/t/binlog_row_insert_select.test10
-rw-r--r--mysql-test/suite/binlog/t/binlog_row_mix_innodb_myisam-master.opt1
-rw-r--r--mysql-test/suite/binlog/t/binlog_row_mix_innodb_myisam.test15
-rw-r--r--mysql-test/suite/binlog/t/binlog_row_mysqlbinlog_db_filter.test148
-rw-r--r--mysql-test/suite/binlog/t/binlog_row_mysqlbinlog_options-master.opt1
-rw-r--r--mysql-test/suite/binlog/t/binlog_row_mysqlbinlog_options.test78
-rw-r--r--mysql-test/suite/binlog/t/binlog_row_mysqlbinlog_verbose.test69
-rw-r--r--mysql-test/suite/binlog/t/binlog_server_id.test29
-rw-r--r--mysql-test/suite/binlog/t/binlog_sf.test187
-rw-r--r--mysql-test/suite/binlog/t/binlog_show_binlog_event_random_pos.combinations5
-rw-r--r--mysql-test/suite/binlog/t/binlog_show_binlog_event_random_pos.test42
-rw-r--r--mysql-test/suite/binlog/t/binlog_spurious_ddl_errors.test95
-rw-r--r--mysql-test/suite/binlog/t/binlog_sql_mode.test171
-rw-r--r--mysql-test/suite/binlog/t/binlog_start_comment.test25
-rw-r--r--mysql-test/suite/binlog/t/binlog_statement_insert_delayed.test13
-rw-r--r--mysql-test/suite/binlog/t/binlog_stm_binlog-master.opt1
-rw-r--r--mysql-test/suite/binlog/t/binlog_stm_binlog.test20
-rw-r--r--mysql-test/suite/binlog/t/binlog_stm_blackhole.test6
-rw-r--r--mysql-test/suite/binlog/t/binlog_stm_cache_stat.test5
-rw-r--r--mysql-test/suite/binlog/t/binlog_stm_ctype_cp932.test6
-rw-r--r--mysql-test/suite/binlog/t/binlog_stm_ctype_ucs.test6
-rw-r--r--mysql-test/suite/binlog/t/binlog_stm_datetime_ranges_mdev15289.test7
-rw-r--r--mysql-test/suite/binlog/t/binlog_stm_do_db-master.opt1
-rw-r--r--mysql-test/suite/binlog/t/binlog_stm_do_db.test90
-rw-r--r--mysql-test/suite/binlog/t/binlog_stm_drop_tbl.test5
-rw-r--r--mysql-test/suite/binlog/t/binlog_stm_drop_tmp_tbl.test5
-rw-r--r--mysql-test/suite/binlog/t/binlog_stm_innodb_stat-master.opt1
-rw-r--r--mysql-test/suite/binlog/t/binlog_stm_insert_select.test5
-rw-r--r--mysql-test/suite/binlog/t/binlog_stm_mix_innodb_myisam-master.opt1
-rw-r--r--mysql-test/suite/binlog/t/binlog_stm_mix_innodb_myisam.test15
-rw-r--r--mysql-test/suite/binlog/t/binlog_stm_ps.test117
-rw-r--r--mysql-test/suite/binlog/t/binlog_stm_row.test103
-rw-r--r--mysql-test/suite/binlog/t/binlog_stm_sp.test82
-rw-r--r--mysql-test/suite/binlog/t/binlog_stm_sp_type_row.test108
-rw-r--r--mysql-test/suite/binlog/t/binlog_stm_unsafe_warning-master.opt1
-rw-r--r--mysql-test/suite/binlog/t/binlog_stm_unsafe_warning.test208
-rw-r--r--mysql-test/suite/binlog/t/binlog_stm_user_variables.test87
-rw-r--r--mysql-test/suite/binlog/t/binlog_switch_inside_trans.test200
-rw-r--r--mysql-test/suite/binlog/t/binlog_table_map_optional_metadata.test334
-rw-r--r--mysql-test/suite/binlog/t/binlog_table_map_optional_metadata_binary.test74
-rw-r--r--mysql-test/suite/binlog/t/binlog_table_map_optional_metadata_ucs2.test75
-rw-r--r--mysql-test/suite/binlog/t/binlog_table_map_optional_metadata_utf32.test75
-rw-r--r--mysql-test/suite/binlog/t/binlog_tmp_table.test159
-rw-r--r--mysql-test/suite/binlog/t/binlog_tmp_table_row.test30
-rw-r--r--mysql-test/suite/binlog/t/binlog_trigger.test51
-rw-r--r--mysql-test/suite/binlog/t/binlog_truncate_active_log.inc70
-rw-r--r--mysql-test/suite/binlog/t/binlog_truncate_active_log.test104
-rw-r--r--mysql-test/suite/binlog/t/binlog_truncate_innodb.test45
-rw-r--r--mysql-test/suite/binlog/t/binlog_truncate_kill.test55
-rw-r--r--mysql-test/suite/binlog/t/binlog_truncate_multi_engine.inc75
-rw-r--r--mysql-test/suite/binlog/t/binlog_truncate_multi_engine.opt1
-rw-r--r--mysql-test/suite/binlog/t/binlog_truncate_multi_engine.test59
-rw-r--r--mysql-test/suite/binlog/t/binlog_truncate_multi_log.test87
-rw-r--r--mysql-test/suite/binlog/t/binlog_truncate_multi_log_unsafe.test120
-rw-r--r--mysql-test/suite/binlog/t/binlog_truncate_myisam.test17
-rw-r--r--mysql-test/suite/binlog/t/binlog_unsafe-master.opt1
-rw-r--r--mysql-test/suite/binlog/t/binlog_unsafe.test762
-rw-r--r--mysql-test/suite/binlog/t/binlog_variables_log_bin-master.opt1
-rw-r--r--mysql-test/suite/binlog/t/binlog_variables_log_bin.test5
-rw-r--r--mysql-test/suite/binlog/t/binlog_variables_log_bin_index-master.opt2
-rw-r--r--mysql-test/suite/binlog/t/binlog_variables_log_bin_index.test4
-rw-r--r--mysql-test/suite/binlog/t/binlog_variables_relay_log-master.opt1
-rw-r--r--mysql-test/suite/binlog/t/binlog_variables_relay_log.test5
-rw-r--r--mysql-test/suite/binlog/t/binlog_variables_relay_log_index-master.opt2
-rw-r--r--mysql-test/suite/binlog/t/binlog_variables_relay_log_index.test4
-rw-r--r--mysql-test/suite/binlog/t/binlog_verbose_compressed_fields.test70
-rw-r--r--mysql-test/suite/binlog/t/binlog_write_error.test84
-rw-r--r--mysql-test/suite/binlog/t/binlog_xa_checkpoint.test57
-rw-r--r--mysql-test/suite/binlog/t/binlog_xa_handling.test28
-rw-r--r--mysql-test/suite/binlog/t/binlog_xa_prepared.inc106
-rw-r--r--mysql-test/suite/binlog/t/binlog_xa_prepared_disconnect.test11
-rw-r--r--mysql-test/suite/binlog/t/binlog_xa_recover.opt1
-rw-r--r--mysql-test/suite/binlog/t/binlog_xa_recover.test277
-rw-r--r--mysql-test/suite/binlog/t/binlog_xa_recover_using_new_server_id.test44
-rw-r--r--mysql-test/suite/binlog/t/flashback-largebinlog.test114
-rw-r--r--mysql-test/suite/binlog/t/flashback-master.opt2
-rw-r--r--mysql-test/suite/binlog/t/flashback.test378
-rw-r--r--mysql-test/suite/binlog/t/foreign_key.test22
-rw-r--r--mysql-test/suite/binlog/t/innodb_autoinc_lock_mode_binlog.opt1
-rw-r--r--mysql-test/suite/binlog/t/innodb_autoinc_lock_mode_binlog.test21
-rw-r--r--mysql-test/suite/binlog/t/innodb_rc_insert_before_delete.test92
-rw-r--r--mysql-test/suite/binlog/t/load_data_stm_view.test24
-rw-r--r--mysql-test/suite/binlog/t/mysqladmin.test12
-rw-r--r--mysql-test/suite/binlog/t/read_only.inc79
-rw-r--r--mysql-test/suite/binlog/t/read_only.test2
-rw-r--r--mysql-test/suite/binlog/t/read_only_statement.test2
-rw-r--r--mysql-test/suite/binlog/t/show_concurrent_rotate.test29
-rw-r--r--mysql-test/suite/binlog/t/start_alter_mysqlbinlog_replay.test61
-rw-r--r--mysql-test/suite/binlog/t/temptable_uservar_disconnect-7938.test17
179 files changed, 11914 insertions, 0 deletions
diff --git a/mysql-test/suite/binlog/t/backup.test b/mysql-test/suite/binlog/t/backup.test
new file mode 100644
index 00000000..e1d921c7
--- /dev/null
+++ b/mysql-test/suite/binlog/t/backup.test
@@ -0,0 +1,19 @@
+--source include/have_log_bin.inc
+--source include/have_binlog_format_mixed.inc
+
+--echo #
+--echo # Test BACKUP STAGES BLOCK_COMMIT with binary logging on
+--echo #
+
+SET BINLOG_FORMAT=MIXED;
+RESET MASTER;
+
+create table t1 (a int) engine=aria;
+insert into t1 values (1);
+
+BACKUP STAGE START;
+BACKUP STAGE BLOCK_COMMIT;
+SELECT @@gtid_binlog_pos;
+BACKUP STAGE END;
+source include/show_binlog_events.inc;
+drop table t1;
diff --git a/mysql-test/suite/binlog/t/binlog_1pc.test b/mysql-test/suite/binlog/t/binlog_1pc.test
new file mode 100644
index 00000000..8465ff17
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_1pc.test
@@ -0,0 +1,39 @@
+# The test file contains tests specific to one phase commit
+# execution and binlogging.
+#
+# MDEV-26031 unnessary xid logging in one phase commit case
+#
+--source include/have_innodb.inc
+--source include/have_aria.inc
+--source include/have_binlog_format_mixed.inc
+
+RESET MASTER;
+
+CREATE TABLE t (f INT) ENGINE=INNODB;
+CREATE TABLE ta (f INT) ENGINE=Aria;
+
+--let $binlog_start = query_get_value(SHOW MASTER STATUS, Position, 1)
+BEGIN;
+ INSERT INTO t SET f = 1;
+ INSERT INTO ta SET f = 1;
+COMMIT;
+--let $binlog_file = query_get_value(SHOW MASTER STATUS, File, 1)
+--source include/show_binlog_events.inc
+
+--echo # Prove that binlog is resettable. Under the bug condition it was not.
+RESET MASTER;
+
+--let $binlog_start = query_get_value(SHOW MASTER STATUS, Position, 1)
+--let $binlog_file = query_get_value(SHOW MASTER STATUS, File, 1)
+SET @@binlog_format = ROW;
+CREATE TABLE ta2 ENGINE = Aria SELECT * from t;
+--source include/show_binlog_events.inc
+
+--echo # Prove that binlog is resettable. Under the bug condition it was not.
+RESET MASTER;
+
+
+--echo # Cleanup
+DROP TABLE ta2, ta, t;
+
+--echo # End of the tests
diff --git a/mysql-test/suite/binlog/t/binlog_admin_cmd_kill.test b/mysql-test/suite/binlog/t/binlog_admin_cmd_kill.test
new file mode 100644
index 00000000..e2397f0e
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_admin_cmd_kill.test
@@ -0,0 +1,98 @@
+# ==== Purpose ====
+#
+# Test verifies that when an admin command execution is interrupted by KILL
+# command it should stop its execution. The admin command in binary log should
+# contain only the list of tables which have successfully executed admin
+# command prior to kill.
+#
+# ==== Implementation ====
+#
+# Steps:
+# 0 - Create two table t1,t2.
+# 1 - Execute OPTIMIZE TABLE t1,t2 command.
+# 2 - Using debug sync mechanism kill OPTIMIZE TABLE command at a stage
+# where it has not optimized any table.
+# 3 - Check that OPTIMIZE TABLE command is not written to binary log.
+# 4 - Using debug sync mechanism hold the execution of OPTIMIZE TABLE after
+# t1 table optimization. Now kill the OPTIMIZE TABLE command.
+# 5 - Observe the binlog output, the OPTIMIZE TABLE command should display `t1,t2`.
+# 6 - Please note that, we binlog the entire query even if at least one
+# table is modified as admin commands are safe to replicate and they will
+# not make the slave to diverge.
+#
+# ==== References ====
+#
+# MDEV-22530: Aborting OPTIMIZE TABLE still logs in binary log and replicates to the Slave server.
+#
+--source include/have_log_bin.inc
+--source include/have_debug.inc
+--source include/have_debug_sync.inc
+--source include/have_innodb.inc
+
+--echo #
+--echo # Kill OPTIMIZE command prior to table modification
+--echo #
+RESET MASTER;
+
+CREATE TABLE t1 (f INT) ENGINE=INNODB;
+CREATE TABLE t2 (f INT) ENGINE=INNODB;
+
+--connect(con1,127.0.0.1,root,,test,$MASTER_MYPORT,)
+--connection con1
+SET debug_sync='admin_command_kill_before_modify SIGNAL ready_to_be_killed WAIT_FOR master_cont';
+--send OPTIMIZE TABLE t1,t2
+
+--connection default
+SET debug_sync='now WAIT_FOR ready_to_be_killed';
+--let $thd_id= `SELECT ID FROM INFORMATION_SCHEMA.PROCESSLIST WHERE INFO LIKE '%OPTIMIZE TABLE %'`
+
+# Now kill.
+--replace_result $thd_id THD_ID
+eval KILL $thd_id;
+
+SET debug_sync = 'reset';
+--disconnect con1
+
+--source include/show_binlog_events.inc
+DROP TABLE t1,t2;
+
+RESET MASTER;
+
+--echo #
+--echo # Kill OPTIMIZE command after table modification
+--echo #
+
+CREATE TABLE t1 (f INT) ENGINE=INNODB;
+CREATE TABLE t2 (f INT) ENGINE=INNODB;
+
+--connect(con1,127.0.0.1,root,,test,$MASTER_MYPORT,)
+--connection con1
+SET debug_sync='admin_command_kill_after_modify SIGNAL ready_to_be_killed WAIT_FOR master_cont';
+--send OPTIMIZE TABLE t1,t2
+
+--connection default
+SET debug_sync='now WAIT_FOR ready_to_be_killed';
+--let $thd_id= `SELECT ID FROM INFORMATION_SCHEMA.PROCESSLIST WHERE INFO LIKE '%OPTIMIZE TABLE %'`
+
+# Now kill.
+--replace_result $thd_id THD_ID
+eval KILL $thd_id;
+
+SET debug_sync = 'reset';
+--disconnect con1
+
+--let $wait_binlog_event= OPTIMIZE
+--source include/wait_for_binlog_event.inc
+
+DROP TABLE t1,t2;
+let $binlog_file= query_get_value(SHOW MASTER STATUS, File, 1);
+FLUSH LOGS;
+
+--let $MYSQLD_DATADIR= `select @@datadir`
+--exec $MYSQL_BINLOG $MYSQLD_DATADIR/$binlog_file > $MYSQLTEST_VARDIR/tmp/mysqlbinlog.out
+
+--let SEARCH_PATTERN= OPTIMIZE TABLE t1,t2
+--let SEARCH_FILE= $MYSQLTEST_VARDIR/tmp/mysqlbinlog.out
+--source include/search_pattern_in_file.inc
+
+--remove_file $MYSQLTEST_VARDIR/tmp/mysqlbinlog.out
diff --git a/mysql-test/suite/binlog/t/binlog_autocommit_off_no_hang-master.opt b/mysql-test/suite/binlog/t/binlog_autocommit_off_no_hang-master.opt
new file mode 100644
index 00000000..e0fa81e6
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_autocommit_off_no_hang-master.opt
@@ -0,0 +1 @@
+--autocommit=0
diff --git a/mysql-test/suite/binlog/t/binlog_autocommit_off_no_hang.test b/mysql-test/suite/binlog/t/binlog_autocommit_off_no_hang.test
new file mode 100644
index 00000000..8f1dbb2a
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_autocommit_off_no_hang.test
@@ -0,0 +1,45 @@
+#
+# Purpose:
+# When the mysql.gtid_slave_pos table uses the InnoDB engine, and mysqld
+# starts, it reads the table and begins a transaction. After mysqld reads the
+# value, it should end the transaction and release all associated locks.
+# The bug reported in DBAAS-7828 shows that when autocommit is off, the locks
+# are not released, resulting in indefinite hangs on future attempts to change
+# gtid_slave_pos. This test ensures its fix such that the locks are properly
+# released.
+#
+# References:
+# DBAAS-7828: Primary/replica: configuration change of "autocommit=0" can
+# not be applied
+#
+
+--source include/have_innodb.inc
+--source include/have_log_bin.inc
+
+# Reading gtid_slave_pos table is format independent so just use one for
+# reduced test time
+--source include/have_binlog_format_row.inc
+
+--let old_slave_pos_engine= query_get_value(SHOW TABLE STATUS FROM mysql LIKE 'gtid_slave_pos', Engine, 1)
+
+# Use a transactional engine
+ALTER TABLE mysql.gtid_slave_pos ENGINE=innodb;
+
+--echo # Restart the server so mysqld reads the gtid_slave_pos using innodb
+--exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
+--shutdown_server
+--source include/wait_until_disconnected.inc
+--exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
+--enable_reconnect
+--source include/wait_until_connected_again.inc
+
+--echo # Set gtid_slave_pos should not hang
+SET GLOBAL gtid_slave_pos=@@gtid_binlog_pos;
+COMMIT;
+
+# Revert table type
+--disable_query_log
+--eval ALTER TABLE mysql.gtid_slave_pos ENGINE=$old_slave_pos_engine
+--enable_query_log
+
+RESET MASTER;
diff --git a/mysql-test/suite/binlog/t/binlog_base64_flag.test b/mysql-test/suite/binlog/t/binlog_base64_flag.test
new file mode 100644
index 00000000..5311da54
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_base64_flag.test
@@ -0,0 +1,190 @@
+# This test case verifies that the mysqlbinlog --base64-output=X flags
+# work as expected, and that BINLOG statements with row events fail if
+# they are not preceded by BINLOG statements with Format description
+# events.
+#
+# See also BUG#32407.
+
+
+# BINLOG statement does not work in embedded mode.
+source include/not_embedded.inc;
+
+call mtr.add_suppression("BINLOG_BASE64_EVENT: According to the master's version");
+call mtr.add_suppression("BINLOG_BASE64_EVENT: Column 1 of table 'test.char128_utf8' cannot be converted");
+
+disable_warnings;
+DROP TABLE IF EXISTS t1;
+enable_warnings;
+# Test to show BUG#32407. This reads a binlog created with the
+# mysql-5.1-telco-6.1 tree, specifically at the tag
+# mysql-5.1.15-ndb-6.1.23, and applies it to the database. The test
+# should fail before BUG#32407 was fixed and succeed afterwards.
+--echo ==== Test BUG#32407 ====
+
+# The binlog contains row events equivalent to:
+# CREATE TABLE t1 (a int) engine = myisam
+# INSERT INTO t1 VALUES (1), (1)
+exec $MYSQL_BINLOG suite/binlog/std_data/bug32407.001 | $MYSQL;
+# The above line should succeed and t1 should contain two ones
+select * from t1;
+
+
+# Test that a BINLOG statement encoding a row event fails unless a
+# Format_description_event as been supplied with an earlier BINLOG
+# statement.
+--echo ==== Test BINLOG statement w/o FD event ====
+
+# This is a binlog statement consisting of one Table_map_log_event and
+# one Write_rows_log_event. Together, they correspond to the
+# following query:
+# INSERT INTO TABLE test.t1 VALUES (2)
+
+error ER_NO_FORMAT_DESCRIPTION_EVENT_BEFORE_BINLOG_STATEMENT;
+BINLOG '
+SVtYRxMBAAAAKQAAADQBAAAAABAAAAAAAAAABHRlc3QAAnQxAAEDAAE=
+SVtYRxcBAAAAIgAAAFYBAAAQABAAAAAAAAEAAf/+AgAAAA==
+';
+# The above line should fail and 2 should not be in the table
+select * from t1;
+
+
+# Test that it works to read a Format_description_log_event with a
+# BINLOG statement, followed by a row-event in base64 from the same
+# version.
+--echo ==== Test BINLOG statement with FD event ====
+
+# This is a binlog statement containing a Format_description_log_event
+# from the same version as the Table_map and Write_rows_log_event.
+BINLOG '
+ODdYRw8BAAAAZgAAAGoAAAABAAQANS4xLjIzLXJjLWRlYnVnLWxvZwAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAA4N1hHEzgNAAgAEgAEBAQEEgAAUwAEGggAAAAICAgC
+';
+
+# This is a Table_map_log_event+Write_rows_log_event corresponding to:
+# INSERT INTO TABLE test.t1 VALUES (3)
+BINLOG '
+TFtYRxMBAAAAKQAAAH8BAAAAABAAAAAAAAAABHRlc3QAAnQxAAEDAAE=
+TFtYRxcBAAAAIgAAAKEBAAAQABAAAAAAAAEAAf/+AwAAAA==
+';
+# The above line should succeed and 3 should be in the table
+select * from t1;
+
+# The same as above with one-fragment BINLOG to prove
+# equivalency with the fragmented BINLOG @frag_0, @frag_1.
+DELETE FROM t1 WHERE a=3;
+# This is a binlog statement containing a Format_description_log_event
+# from the same version as the Table_map and Write_rows_log_event.
+BINLOG '
+ODdYRw8BAAAAZgAAAGoAAAABAAQANS4xLjIzLXJjLWRlYnVnLWxvZwAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAA4N1hHEzgNAAgAEgAEBAQEEgAAUwAEGggAAAAICAgC
+';
+
+# This is a Table_map_log_event+Write_rows_log_event corresponding to:
+# INSERT INTO TABLE test.t1 VALUES (3)
+SET @binlog_fragment_0='
+TFtYRxMBAAAAKQAAAH8BAAAAABAAAAAAAAAABHRlc3QAAnQxAAEDAAE=
+TFtYRxcBAAAAIgAAAKEBAAAQABAAAAAAAAEAAf/+AwAAAA==
+';
+SET @binlog_fragment_1='';
+BINLOG @binlog_fragment_0, @binlog_fragment_1;
+# The above line should succeed and 3 should be in the table:
+select * from t1;
+# show "one-shot" feature of binlog_fragment variables
+SELECT @binlog_fragment_0, @binlog_fragment_1 as 'NULL','NULL';
+
+# New mysqlbinlog supports --base64-output=never
+--echo ==== Test --base64-output=never on a binlog with row events ====
+
+# mysqlbinlog should fail
+--replace_regex /#[0-9][0-9][0-9][0-9][0-9][0-9] \N*/<#>/ /SET \@\@session.pseudo_thread_id.*/<#>/
+exec $MYSQL_BINLOG --base64-output=never --print-row-count=0 --print-row-event-positions=0 suite/binlog/std_data/bug32407.001;
+
+
+# Test that the following fails cleanly: "First, read a
+# Format_description event which has N event types. Then, read an
+# event of type M>N"
+--echo ==== Test non-matching FD event and Row event ====
+
+# This is the Format_description_log_event from
+# bug32407.001, encoded in base64. It contains only the old
+# row events (number of event types is 22)
+BINLOG '
+4CdYRw8BAAAAYgAAAGYAAAAAAAQANS4xLjE1LW5kYi02LjEuMjQtZGVidWctbG9nAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAADgJ1hHEzgNAAgAEgAEBAQEEgAATwAEGggICAg=
+';
+
+# The following is a Write_rows_log_event with event type 23, i.e.,
+# not supported by the Format_description_log_event above. It
+# corresponds to the following query:
+# INSERT INTO t1 VALUES (5)
+error 1149;
+BINLOG '
+Dl1YRxMBAAAAKQAAADQBAAAAABAAAAAAAAAABHRlc3QAAnQxAAEDAAE=
+Dl1YRxcBAAAAIgAAAFYBAAAQABAAAAAAAAEAAf/+BQAAAA==
+';
+# the above line should fail and 5 should not be in the binlog.
+select * from t1;
+
+# Test that BUG#37426 is triggered.
+
+CREATE TABLE char128_utf8 (
+ i1 INT NOT NULL,
+ c CHAR(128) CHARACTER SET utf8 NOT NULL,
+ i2 INT NOT NULL);
+CREATE TABLE char63_utf8 (
+ i1 INT NOT NULL,
+ c CHAR(63) CHARACTER SET utf8 NOT NULL,
+ i2 INT NOT NULL);
+
+#
+# This is the format description log event
+#
+
+BINLOG '
+MuNkSA8BAAAAZgAAAGoAAAAAAAQANS4xLjI1LXJjLWRlYnVnLWxvZwAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAy42RIEzgNAAgAEgAEBAQEEgAAUwAEGggAAAAICAgC
+';
+
+# ... this event corresponding to
+#
+# INSERT INTO char63_utf8 VALUES ( 1, "123", 1 )
+#
+# The binlog event below shall not trigger the bug check
+
+BINLOG '
+3u9kSBMBAAAANgAAAJYBAAAAABAAAAAAAAAABHRlc3QAC2NoYXI2M191dGY4AAMD/gMC/r0A
+3u9kSBcBAAAAKgAAAMABAAAQABAAAAAAAAEAA//4AQAAAAMxMjMBAAAA
+';
+SELECT * FROM char63_utf8;
+
+# ... and this is an event corresponding to
+#
+# INSERT INTO char128_utf8 VALUES ( 1, "123", 1 )
+#
+# The binlog event below shall trigger the bug check and produce an error
+#
+
+error ER_UNKNOWN_ERROR;
+BINLOG '
+iONkSBMBAAAANwAAAJkBAAAAABAAAAAAAAAABHRlc3QADGNoYXIxMjhfdXRmOAADA/4DAv6AAA==
+iONkSBcBAAAAKwAAAMQBAAAQABAAAAAAAAEAA//4AQAAAAMAMTIzAQAAAA==
+';
+
+drop table t1, char63_utf8, char128_utf8;
+
+call mtr.add_suppression("Slave SQL.*master suffers from this bug: http:..bugs.mysql.com.bug.php.id=37426.* error.* 1105");
+call mtr.add_suppression("Slave SQL.*Table definition on master and slave does not match: Column 1 size mismatch.* error.* 1535");
+call mtr.add_suppression("Slave SQL.*Column 1 of table .test.char128_utf8. cannot be converted.* error.* 1677");
+
+--echo #
+--echo # Bug #54393: crash and/or valgrind errors in
+--echo # mysql_client_binlog_statement
+--echo #
+--error ER_SYNTAX_ERROR
+BINLOG '';
+--error ER_BASE64_DECODE_ERROR
+BINLOG '123';
+--error ER_BASE64_DECODE_ERROR
+BINLOG '-2079193929';
+--error ER_BASE64_DECODE_ERROR
+BINLOG 'xç↓%~∙D╒ƒ╡';
diff --git a/mysql-test/suite/binlog/t/binlog_bug23533.test b/mysql-test/suite/binlog/t/binlog_bug23533.test
new file mode 100644
index 00000000..a7749711
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_bug23533.test
@@ -0,0 +1,50 @@
+#############################################################
+# Bug#23533: CREATE SELECT max_binlog_cache_size test
+# case needed
+#############################################################
+
+--source include/have_innodb.inc
+--source include/have_log_bin.inc
+--source include/have_binlog_format_row.inc
+call mtr.add_suppression("Write to binary log failed: Multi-statement transaction required more than .max_binlog_cache_size.*");
+SET AUTOCOMMIT=0;
+
+# Create 1st table
+CREATE TABLE t1 (a INT NOT NULL AUTO_INCREMENT, b TEXT, PRIMARY KEY(a)) ENGINE=InnoDB;
+--disable_query_log
+let $i= 1000;
+while ($i)
+{
+ BEGIN;
+ eval INSERT INTO t1 VALUES($i, REPEAT('x', 4096));
+ COMMIT;
+ dec $i;
+}
+--enable_query_log
+SELECT COUNT(*) FROM t1;
+
+# Set small value for max_binlog_cache_size
+let $saved_binlog_cache_size= query_get_value(SELECT @@binlog_cache_size AS Value, Value, 1);
+let $saved_max_binlog_cache_size= query_get_value(SELECT @@max_binlog_cache_size AS Value, Value, 1);
+SET GLOBAL binlog_cache_size=4096;
+SET GLOBAL max_binlog_cache_size=4096;
+
+# New value of max_binlog_cache_size will apply to new session
+disconnect default;
+connect(default,localhost,root,,test);
+
+# Copied data from t1 into t2 large than max_binlog_cache_size
+START TRANSACTION;
+--error ER_TRANS_CACHE_FULL
+CREATE TABLE t2 SELECT * FROM t1;
+COMMIT;
+SHOW TABLES LIKE 't%';
+
+# 5.1 End of Test
+--disable_query_log
+eval SET GLOBAL max_binlog_cache_size=$saved_max_binlog_cache_size;
+eval SET GLOBAL binlog_cache_size=$saved_binlog_cache_size;
+--enable_query_log
+DROP TABLE t1;
+disconnect default;
+connect(default,localhost,root,,test);
diff --git a/mysql-test/suite/binlog/t/binlog_bug36391-master.opt b/mysql-test/suite/binlog/t/binlog_bug36391-master.opt
new file mode 100644
index 00000000..56273241
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_bug36391-master.opt
@@ -0,0 +1 @@
+--sql_mode=NO_BACKSLASH_ESCAPES
diff --git a/mysql-test/suite/binlog/t/binlog_bug36391.test b/mysql-test/suite/binlog/t/binlog_bug36391.test
new file mode 100644
index 00000000..64d91dfa
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_bug36391.test
@@ -0,0 +1,30 @@
+#
+# BUG#36391 and BUG#38731
+#
+# The fix for BUG#20103 "Escaping with backslash does not work as expected"
+# was implemented too greedy though in that it not only changes the behavior
+# of backslashes within strings but in general, so disabling command shortcuts
+# like \G or \C (which in turn leads to BUG#36391: "mysqlbinlog creates invalid charset statements".
+#
+# The test executes simple commands that are stored in the binary log and
+# re-execute them through the mysql client which should have to process
+# some command shortcuts. The backslashes within strings is disabled in the file
+# rpl_bug36391-master.opt by the option --sql_mode=NO_BACKSLASH_ESCAPES.
+#
+#
+
+--source include/have_log_bin.inc
+--source include/have_binlog_format_mixed.inc
+
+CREATE TABLE t1(id INT);
+let $binlog= query_get_value(SHOW MASTER STATUS, File, 1);
+let $binlog_path= `SELECT CONCAT(@@DATADIR, '$binlog')`;
+SHOW TABLES;
+FLUSH LOGS;
+DROP TABLE t1;
+
+--exec $MYSQL_BINLOG $binlog_path | $MYSQL test
+SHOW TABLES;
+
+# Clean up
+DROP TABLE t1;
diff --git a/mysql-test/suite/binlog/t/binlog_checkpoint.test b/mysql-test/suite/binlog/t/binlog_checkpoint.test
new file mode 100644
index 00000000..4237f33c
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_checkpoint.test
@@ -0,0 +1,236 @@
+--source include/have_innodb.inc
+--source include/have_debug.inc
+--source include/have_debug_sync.inc
+--source include/have_binlog_format_row.inc
+
+SET @old_max_binlog_size= @@global.max_binlog_size;
+SET GLOBAL max_binlog_size= 4096;
+SET @old_innodb_flush_log_at_trx_commit= @@global.innodb_flush_log_at_trx_commit;
+SET GLOBAL innodb_flush_log_at_trx_commit= 1;
+RESET MASTER;
+
+CREATE TABLE t1 (a INT PRIMARY KEY, b MEDIUMTEXT) ENGINE=Innodb;
+CREATE TABLE t2 (a INT PRIMARY KEY, b MEDIUMTEXT) ENGINE=Myisam;
+
+--echo *** Test that RESET MASTER waits for pending commit checkpoints to complete.
+
+# con1 will hang before doing commit checkpoint, blocking RESET MASTER.
+connect(con1,localhost,root,,);
+SET DEBUG_SYNC= "commit_after_group_release_commit_ordered SIGNAL con1_ready WAIT_FOR con1_go";
+send INSERT INTO t1 VALUES (1, REPEAT("x", 4100));
+
+connection default;
+SET DEBUG_SYNC= "now WAIT_FOR con1_ready";
+# Let's add a few binlog rotations just for good measure.
+INSERT INTO t2 VALUES (1, REPEAT("x", 4100));
+INSERT INTO t2 VALUES (2, REPEAT("x", 4100));
+--source include/show_binary_logs.inc
+--let $binlog_file= master-bin.000004
+--let $binlog_start= 4
+--source include/show_binlog_events.inc
+SET DEBUG_SYNC= "execute_command_after_close_tables SIGNAL reset_master_done";
+send RESET MASTER;
+
+connect(con2,localhost,root,,);
+--echo This will timeout, as RESET MASTER is blocked
+SET DEBUG_SYNC= "now WAIT_FOR reset_master_done TIMEOUT 1";
+# Wake up transaction to allow RESET MASTER to complete.
+SET DEBUG_SYNC= "now SIGNAL con1_go";
+
+connection con1;
+reap;
+
+connection default;
+reap;
+--source include/show_binary_logs.inc
+--let $binlog_file= master-bin.000001
+--let $binlog_start= 4
+--source include/show_binlog_events.inc
+
+--echo *** Test that binlog N is active, and commit checkpoint for (N-1) is
+--echo *** done while there is still a pending commit checkpoint for (N-2).
+
+connection con1;
+SET DEBUG_SYNC= "commit_after_group_release_commit_ordered SIGNAL con1_ready WAIT_FOR con1_continue";
+send INSERT INTO t1 VALUES (20, REPEAT("x", 4100));
+
+connection default;
+SET DEBUG_SYNC= "now WAIT_FOR con1_ready";
+
+connection con2;
+SET DEBUG_SYNC= "commit_after_group_release_commit_ordered SIGNAL con2_ready WAIT_FOR con2_continue";
+send INSERT INTO t1 VALUES (21, REPEAT("x", 4100));
+
+connection default;
+SET DEBUG_SYNC= "now WAIT_FOR con2_ready";
+--source include/show_binary_logs.inc
+--let $binlog_file= master-bin.000001
+--source include/show_binlog_events.inc
+--let $binlog_file= master-bin.000002
+--source include/show_binlog_events.inc
+--let $binlog_file= master-bin.000003
+--source include/show_binlog_events.inc
+
+# We need to sync the test case with the background processing of the
+# commit checkpoint, otherwise we get nondeterministic results.
+SET DEBUG_SYNC= "RESET";
+SET @old_dbug= @@global.DEBUG_DBUG;
+SET GLOBAL debug_dbug="+d,binlog_background_checkpoint_processed";
+
+SET DEBUG_SYNC= "now SIGNAL con2_continue";
+
+connection con2;
+reap;
+
+connection default;
+--echo con1 is still pending, no new binlog checkpoint should have been logged.
+# Make sure commit checkpoint is processed before we check that no checkpoint
+# event has been binlogged.
+SET DEBUG_SYNC= "now WAIT_FOR binlog_background_checkpoint_processed";
+SET GLOBAL debug_dbug= @old_dbug;
+SET DEBUG_SYNC= "RESET";
+
+--let $binlog_file= master-bin.000003
+--source include/show_binlog_events.inc
+
+SET DEBUG_SYNC= "now SIGNAL con1_continue";
+
+connection con1;
+reap;
+
+connection default;
+
+--echo No commit checkpoints are pending, a new binlog checkpoint should have been logged.
+--let $binlog_file= master-bin.000003
+
+# Wait for the master-bin.000003 binlog checkpoint to appear.
+--let $wait_for_all= 0
+--let $show_statement= SHOW BINLOG EVENTS IN "$binlog_file"
+--let $field= Info
+--let $condition= = "master-bin.000003"
+--source include/wait_show_condition.inc
+
+--source include/show_binlog_events.inc
+
+
+--echo *** MDEV-4322: Broken XID counting during binlog rotation ***
+
+# Test that binlog shutdown waits for any pending binlog checkpoints to have time to complete.
+
+connection default;
+# We will use debug_sync to setup a wait inside the background processing
+# of binlog checkpoints. The wait is newer resumed, and will eventually
+# time out. If server shutdown does not wait for checkpoint processing to
+# complete, we will get an assert.
+#
+# It is a bit tricky to inject the wait properly as it has to happen in a
+# background thread during shutdown. So we first inject a DBUG to set the
+# debug_sync wait in the correct thread, then wait to be signalled that
+# the inject happened so that we can remove it again from DBUG (else
+# check_testcase will complain).
+
+SET @old_dbug= @@global.DEBUG_DBUG;
+SET GLOBAL debug_dbug="+d,inject_binlog_background_thread_before_mark_xid_done";
+
+FLUSH LOGS;
+INSERT INTO t1 VALUES (30, REPEAT("x", 4100));
+SET DEBUG_SYNC= "now WAIT_FOR injected_binlog_background_thread";
+SET GLOBAL debug_dbug= @old_dbug;
+INSERT INTO t1 VALUES (31, REPEAT("x", 4100));
+--source include/show_binary_logs.inc
+SET debug_sync = 'reset';
+
+SET GLOBAL max_binlog_size= @old_max_binlog_size;
+SET GLOBAL innodb_flush_log_at_trx_commit= @old_innodb_flush_log_at_trx_commit;
+
+--source include/shutdown_mysqld.inc
+--source include/start_mysqld.inc
+
+
+--echo *** MDEV-7402: 'reset master' hangs, waits for signalled COND_xid_list ***
+
+
+connect(con3,localhost,root,,);
+# Make the binlog background thread wait before clearing the pending checkpoint.
+# The bug was that one RESET MASTER would clear the reset_master_pending
+# flag set by another RESET MASTER; this could cause the wakeup from the
+# binlog background thread not to be sent, and thus the second RESET MASTER
+# to wait infinitely.
+SET debug_sync="reset_logs_after_set_reset_master_pending SIGNAL reset_master_ready WAIT_FOR reset_master_cont";
+send RESET MASTER;
+
+--connection default
+SET @old_dbug= @@global.DEBUG_DBUG;
+SET GLOBAL debug_dbug="+d,inject_binlog_background_thread_before_mark_xid_done";
+SET debug_sync="now WAIT_FOR reset_master_ready";
+RESET MASTER;
+SET debug_sync="now WAIT_FOR injected_binlog_background_thread";
+SET GLOBAL debug_dbug=@old_dbug;
+SET debug_sync="now SIGNAL reset_master_cont";
+
+--connection con3
+REAP;
+
+--connection default
+SET debug_sync = 'reset';
+
+--echo *** MDEV-24660: MYSQL_BIN_LOG::cleanup(): Assertion `b->xid_count == 0' failed in MYSQL_BIN_LOG::cleanup
+# Test a scenario of forcibly rolled back mixed engine "unsafe" transaction
+# at shutdown. That should not let to the assert.
+
+SET @old_max_binlog_size= @@global.max_binlog_size;
+SET GLOBAL max_binlog_size= 4096;
+
+--connect(con_24660,localhost,root,,)
+
+# Construct an unsafe xa transaction that is rolled back
+# in binlog at the shutdown time. That requires STATEMENT binlog format.
+FLUSH LOGS;
+--let $binlog_file = query_get_value(SHOW MASTER STATUS, File, 1)
+SET @@session.binlog_format = STATEMENT;
+CREATE TABLE tm (a INT) ENGINE = myisam;
+
+call mtr.add_suppression("Table './test/tm' is marked as crashed");
+call mtr.add_suppression("Checking table");
+
+XA START 'xa1';
+ --let $a = `SELECT a + 1 FROM t1`
+ --eval INSERT INTO t1 VALUES ($a, 1)
+ INSERT INTO tm SET a = 1;
+ --inc $a
+ --let $repeat_x = `SELECT REPEAT("x", 4100)`
+--disable_query_log
+ --eval INSERT INTO t1 VALUES ($a, "$repeat_x")
+--enable_query_log
+XA END 'xa1';
+
+--connection default
+ # In the patch's base BBT would exit first to win the race against
+ # the XA transaction's binloging.
+ SET GLOBAL debug_dbug="+d,only_kill_system_threads_no_loop";
+--source include/shutdown_mysqld.inc
+--source include/start_mysqld.inc
+
+--echo ** Proof of shutdown caused ROLLBACK-completed transaction
+
+--let assert_file=$MYSQLTEST_VARDIR/tmp/binlog_decoded.out
+--let datadir=`select @@datadir`
+
+--echo # MYSQL_BINLOG datadir/binlog_file --result-file=assert_file
+--exec $MYSQL_BINLOG $datadir/$binlog_file --result-file=$assert_file
+
+--let $assert_text= No XA statements should be written into the binary log
+--let $assert_count= 0
+--let assert_select= XA START|XA END|XA PREPARE|XA COMMIT|XA ROLLBACK
+--source include/assert_grep.inc
+
+--let $assert_text= The transaction should be rolled back
+--let $assert_count= 1
+--let assert_select= ^ROLLBACK\$
+--source include/assert_grep.inc
+
+SELECT * FROM tm;
+--eval SELECT * FROM t1 WHERE a = $a
+
+# Clean up.
+DROP TABLE t1, t2, tm;
diff --git a/mysql-test/suite/binlog/t/binlog_checkpoint_flush_logs.test b/mysql-test/suite/binlog/t/binlog_checkpoint_flush_logs.test
new file mode 100644
index 00000000..e21f1eb3
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_checkpoint_flush_logs.test
@@ -0,0 +1,79 @@
+--source include/have_innodb.inc
+--source include/have_debug.inc
+--source include/have_debug_sync.inc
+--source include/have_binlog_format_row.inc
+
+# References:
+#
+# MDEV-24526 binlog rotate via FLUSH LOGS may obsolate binlog file too eary
+#
+# The test for MDEV-24526 proves the fixes correct observed race condition
+# between a commiting transaction and FLUSH-LOGS.
+# The plot.
+# Trx_1 (con1) transaction binlogs first
+# to yield its turn acquiring LOCK_commit_ordered to Trx_2 and stand
+# still waiting of a signal that will never arrive.
+# Trx_2 can't acquire it in the fixed version even though
+# Trx_3 makes sure Trx_2 has reached a post-rotation execution point
+# to signal it to proceed.
+# Then the server gets crashed and Trx_1 must recover unlike
+# in the OLD buggy version.
+#
+SET GLOBAL innodb_flush_log_at_trx_commit= 1;
+RESET MASTER;
+
+CREATE TABLE t1 (a INT PRIMARY KEY, b MEDIUMTEXT) ENGINE=Innodb;
+
+--echo *** Test that FLUSH LOGS waits if a transaction ordered commit is in progress.
+
+connect(con1,localhost,root,,); # Trx_1
+# hang before doing acquiring Commit Ordered mutex
+SET DEBUG_SYNC= "commit_before_get_LOCK_commit_ordered SIGNAL con1_ready WAIT_FOR con1_go";
+
+--send INSERT INTO t1 VALUES (1, REPEAT("x", 1))
+
+connection default; # Trx_2
+
+SET DEBUG_SYNC= "now WAIT_FOR con1_ready";
+SET DEBUG_SYNC= "rotate_after_rotate SIGNAL con_flush_ready WAIT_FOR default_go";
+--send FLUSH LOGS
+
+connect(con2,localhost,root,,); # Trx_3
+--echo Trx_1 is not yet committed:
+SELECT count(*) as 'ZERO' from t1;
+
+--echo Wait for Trx_2 has rotated binlog:
+SET DEBUG_SYNC= "now WAIT_FOR con_flush_ready";
+# Useless signal to prove Trx_2 cannot race Trx_1's commit
+# even though Trx_1 never received the being waited 'con1_go'.
+SET DEBUG_SYNC= "now SIGNAL default_go";
+
+--let $shutdown_timeout=0
+--source include/restart_mysqld.inc
+
+connection default;
+--enable_reconnect
+--error 0,2013
+--reap
+
+--echo Must be tree logs in the list:
+--source include/show_binary_logs.inc
+--let $binlog_file= master-bin.000001
+--let $binlog_start= 4
+--source include/show_binlog_events.inc
+
+--echo Only one Binlog checkpoint must exist and point to master-bin.000001
+--let $binlog_file= master-bin.000002
+--let $binlog_start= 4
+--source include/show_binlog_events.inc
+
+
+# In the buggy server version the following select may have
+# resulted with ZERO:
+SELECT count(*) as 'ONE' from t1;
+
+# Clean up.
+connection default;
+
+DROP TABLE t1;
+SET debug_sync = 'reset';
diff --git a/mysql-test/suite/binlog/t/binlog_checksum.test b/mysql-test/suite/binlog/t/binlog_checksum.test
new file mode 100644
index 00000000..7ecb9308
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_checksum.test
@@ -0,0 +1,37 @@
+source include/have_innodb.inc;
+source include/have_log_bin.inc;
+
+#
+# WL#2540 replication event checksum
+#
+# Objectives of the test are:
+# to demo binlog events with CRC32 checksum in them and
+# to prove show binlog events and mysqlbinlog are capable to handle
+# the checksum.
+#
+
+set @save_binlog_checksum = @@global.binlog_checksum;
+set @save_master_verify_checksum = @@global.master_verify_checksum;
+set @@global.binlog_checksum = CRC32;
+set @@global.master_verify_checksum = 1;
+let $MYSQLD_DATADIR= `select @@datadir`;
+
+reset master;
+--echo must be master-bin.000001
+--source include/show_binary_logs.inc
+
+create table t1 (a int);
+flush logs;
+drop table t1;
+
+--source include/show_binlog_events.inc
+--exec $MYSQL_BINLOG -c $MYSQLD_DATADIR/master-bin.000001 | $MYSQL
+show tables;
+
+# clean-up
+
+drop table t1;
+set @@global.binlog_checksum = @save_binlog_checksum;
+set @@global.master_verify_checksum = @save_master_verify_checksum;
+
+--echo End of the tests
diff --git a/mysql-test/suite/binlog/t/binlog_commit_wait.test b/mysql-test/suite/binlog/t/binlog_commit_wait.test
new file mode 100644
index 00000000..7d7af2a9
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_commit_wait.test
@@ -0,0 +1,229 @@
+--source include/have_innodb.inc
+--source include/have_log_bin.inc
+
+ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
+CREATE TABLE t1 (a INT PRIMARY KEY, b INT) ENGINE=InnoDB;
+
+SET @old_count= @@GLOBAL.binlog_commit_wait_count;
+SET GLOBAL binlog_commit_wait_count= 3;
+SET @old_usec= @@GLOBAL.binlog_commit_wait_usec;
+SET GLOBAL binlog_commit_wait_usec= 20000000;
+
+connect(con1,localhost,root,,test);
+connect(con2,localhost,root,,test);
+connect(con3,localhost,root,,test);
+
+# Get Initial status measurements
+--connection default
+SELECT variable_value INTO @group_commits FROM information_schema.global_status
+ WHERE variable_name = 'binlog_group_commits';
+SELECT variable_value INTO @group_commit_trigger_count FROM information_schema.global_status
+ WHERE variable_name = 'binlog_group_commit_trigger_count';
+SELECT variable_value INTO @group_commit_trigger_timeout FROM information_schema.global_status
+ WHERE variable_name = 'binlog_group_commit_trigger_timeout';
+SELECT variable_value INTO @group_commit_trigger_lock_wait FROM information_schema.global_status
+ WHERE variable_name = 'binlog_group_commit_trigger_lock_wait';
+
+# Note: binlog_group_commits is counted at the start of the group and group_commit_trigger_* is
+# counted near when the groups its finalised.
+
+# Check that if T2 goes to wait for a row lock of T1 while T1 is waiting for
+# more transactions to arrive for group commit, the commit of T1 will complete
+# immediately.
+# We test this by setting a very high timeout (20 seconds), and testing that
+# that much time does not elapse.
+
+--connection default
+SET @a= current_timestamp();
+
+--connection con1
+BEGIN;
+INSERT INTO t1 VALUES (1,0);
+send COMMIT;
+
+--connection con2
+send INSERT INTO t1 VALUES (1,1);
+
+--connection con1
+reap;
+
+--connection default
+SET @b= unix_timestamp(current_timestamp()) - unix_timestamp(@a);
+SELECT IF(@b < 20, "Ok", CONCAT("Error: too much time elapsed: ", @b, " seconds >= 20"));
+
+# All connections are to the same server. One transaction occurs on con1. It is
+# commited before con2 is started. con2 transaction violates the unique key contraint. This
+# type of group commit is binlog_group_commit_trigger_lock_wait so that further con2
+# transactions will occur afterwards as they may be as result of the ER_DUP_ENTRY on the
+# application side.
+# before: binlog_group_commit=0, binlog_group_commit_trigger_count=0
+# before: binlog_group_commit_trigger_timeout=0, binlog_group_commit_trigger_lock_wait=0
+# after: binlog_group_commit+1 by reason of binlog_group_commit_trigger_lock_wait+1
+SELECT variable_value - @group_commits FROM information_schema.global_status
+ WHERE variable_name = 'binlog_group_commits';
+SELECT variable_value - @group_commit_trigger_count FROM information_schema.global_status
+ WHERE variable_name = 'binlog_group_commit_trigger_count';
+SELECT variable_value - @group_commit_trigger_timeout FROM information_schema.global_status
+ WHERE variable_name = 'binlog_group_commit_trigger_timeout';
+SELECT variable_value - @group_commit_trigger_lock_wait FROM information_schema.global_status
+ WHERE variable_name = 'binlog_group_commit_trigger_lock_wait';
+
+--connection con2
+--error ER_DUP_ENTRY
+reap;
+
+
+# Test that the commit triggers when sufficient commits have queued up.
+--connection default
+SET @a= current_timestamp();
+
+--connection con1
+send INSERT INTO t1 VALUES (2,0);
+
+--connection con2
+send INSERT INTO t1 VALUES (3,0);
+
+--connection con3
+INSERT INTO t1 VALUES (4,0);
+
+--connection con1
+reap;
+--connection con2
+reap;
+
+--connection default
+SET @b= unix_timestamp(current_timestamp()) - unix_timestamp(@a);
+SELECT IF(@b < 20, "Ok", CONCAT("Error: too much time elapsed: ", @b, " seconds >= 20"));
+
+# All connections are to the same server. 3 non-conflicting transaction occur
+# on each connection. The binlog_commit_wait_count=3 at the start therefore 1
+# group is committed by virtue of reaching 3 transactions. Hence
+# binlog_group_commit_trigger_count is incremented.
+# before: binlog_group_commit=1, binlog_group_commit_trigger_count=0
+# before: binlog_group_commit_trigger_timeout=0, binlog_group_commit_trigger_lock_wait=1
+# after: binlog_group_commit+1 by reason of binlog_group_commit_trigger_count+1
+SELECT variable_value - @group_commits FROM information_schema.global_status
+ WHERE variable_name = 'binlog_group_commits';
+SELECT variable_value - @group_commit_trigger_count FROM information_schema.global_status
+ WHERE variable_name = 'binlog_group_commit_trigger_count';
+SELECT variable_value - @group_commit_trigger_timeout FROM information_schema.global_status
+ WHERE variable_name = 'binlog_group_commit_trigger_timeout';
+SELECT variable_value - @group_commit_trigger_lock_wait FROM information_schema.global_status
+ WHERE variable_name = 'binlog_group_commit_trigger_lock_wait';
+
+# Test that commit triggers immediately if there is already a transaction
+# waiting on another transaction that reaches its commit.
+
+--connection default
+SET @a= current_timestamp();
+
+--connection con1
+send INSERT INTO t1 VALUES (6,0);
+
+--connection con2
+BEGIN;
+UPDATE t1 SET b=b+1 WHERE a=1;
+
+--connection con3
+send UPDATE t1 SET b=b+10 WHERE a=1;
+
+--connection con2
+# A small sleep to let con3 have time to wait on con2.
+# The sleep might be too small on loaded host, but that is not a big problem;
+# it only means we will trigger a different code path (con3 waits after con2
+# is ready to commit rather than before); and either path should work the same.
+# So we will not get false positive in case of different timing; at worst false
+# negative.
+SELECT SLEEP(0.25);
+UPDATE t1 SET b=b+1 WHERE a=3;
+COMMIT;
+
+--connection con1
+reap;
+
+--connection default
+SET @b= unix_timestamp(current_timestamp()) - unix_timestamp(@a);
+SELECT IF(@b < 20, "Ok", CONCAT("Error: too much time elapsed: ", @b, " seconds >= 20"));
+
+# All connections are to the same server. con2 and con3 updates are aquiring
+# the same row lock for a=1. Either con2 or con3 will be in a lock wait
+# thefore the binlog_group_commit_trigger_lock_wait is incremented.
+# before: binlog_group_commit=2, binlog_group_commit_trigger_count=1
+# before: binlog_group_commit_trigger_timeout=0, binlog_group_commit_trigger_lock_wait=1
+# after: binlog_group_commit+1 by reason of binlog_group_commit_trigger_lock_wait+1
+SELECT variable_value - @group_commits FROM information_schema.global_status
+ WHERE variable_name = 'binlog_group_commits';
+SELECT variable_value - @group_commit_trigger_count FROM information_schema.global_status
+ WHERE variable_name = 'binlog_group_commit_trigger_count';
+SELECT variable_value - @group_commit_trigger_timeout FROM information_schema.global_status
+ WHERE variable_name = 'binlog_group_commit_trigger_timeout';
+SELECT variable_value - @group_commit_trigger_lock_wait FROM information_schema.global_status
+ WHERE variable_name = 'binlog_group_commit_trigger_lock_wait';
+
+--connection default
+SET @a= current_timestamp();
+
+# Now con3 will be waiting for a following group commit to trigger.
+--connection con1
+send INSERT INTO t1 VALUES (7,0);
+--connection con2
+INSERT INTO t1 VALUES (8,0);
+--connection con3
+reap;
+
+--connection default
+SET @b= unix_timestamp(current_timestamp()) - unix_timestamp(@a);
+SELECT IF(@b < 20, "Ok", CONCAT("Error: too much time elapsed: ", @b, " seconds >= 20"));
+
+# The con1 and con2 transactions above are combined with the 'send UPDATE t1 SET b=b+10 WHERE a=1;'
+# on con3 from the previous block. So we have 3 so this is a count based group.
+# before: binlog_group_commit=3, binlog_group_commit_trigger_count=1
+# before: binlog_group_commit_trigger_timeout=0, binlog_group_commit_trigger_lock_wait=2
+# after: binlog_group_commit+1 by reason of binlog_group_commit_trigger_count+1
+SELECT variable_value - @group_commits FROM information_schema.global_status
+ WHERE variable_name = 'binlog_group_commits';
+SELECT variable_value - @group_commit_trigger_count FROM information_schema.global_status
+ WHERE variable_name = 'binlog_group_commit_trigger_count';
+SELECT variable_value - @group_commit_trigger_timeout FROM information_schema.global_status
+ WHERE variable_name = 'binlog_group_commit_trigger_timeout';
+SELECT variable_value - @group_commit_trigger_lock_wait FROM information_schema.global_status
+ WHERE variable_name = 'binlog_group_commit_trigger_lock_wait';
+
+# Test that when the binlog_commit_wait_usec is reached the tranction gets a group commit
+
+--connection default
+SET @a= current_timestamp();
+SET GLOBAL binlog_commit_wait_usec= 5*1000*1000;
+
+--connection con1
+reap;
+INSERT INTO t1 VALUES (9,0);
+
+--connection default
+SET @b= unix_timestamp(current_timestamp()) - unix_timestamp(@a);
+SELECT IF(@b < 4, CONCAT("Error: too little time elapsed: ", @b, " seconds < 4"),
+ IF(@b < 20, "Ok", CONCAT("Error: too much time elapsed: ", @b, " seconds >= 20")));
+
+# con1 pushes 1 transaction. The count was for 3 to occur before a group commit.
+# The timeout is 5 seconds but we allow between 4 and 20 because of the fragile nature
+# of time in test. This is a timeout causing the commit so binlog_group_commit_trigger_timeout
+# is incremented.
+# before: binlog_group_commit=4, binlog_group_commit_trigger_count=2
+# before: binlog_group_commit_trigger_timeout=0, binlog_group_commit_trigger_lock_wait=2
+# after: binlog_group_commit+1 by reason of binlog_group_commit_trigger_timeout+1
+SELECT variable_value - @group_commits FROM information_schema.global_status
+ WHERE variable_name = 'binlog_group_commits';
+SELECT variable_value - @group_commit_trigger_count FROM information_schema.global_status
+ WHERE variable_name = 'binlog_group_commit_trigger_count';
+SELECT variable_value - @group_commit_trigger_timeout FROM information_schema.global_status
+ WHERE variable_name = 'binlog_group_commit_trigger_timeout';
+SELECT variable_value - @group_commit_trigger_lock_wait FROM information_schema.global_status
+ WHERE variable_name = 'binlog_group_commit_trigger_lock_wait';
+
+--connection default
+SELECT * FROM t1 ORDER BY a;
+
+--connection default
+DROP TABLE t1;
+SET GLOBAL binlog_commit_wait_count= @old_count;
+SET GLOBAL binlog_commit_wait_usec= @old_usec;
diff --git a/mysql-test/suite/binlog/t/binlog_database.test b/mysql-test/suite/binlog/t/binlog_database.test
new file mode 100644
index 00000000..8d298b8a
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_database.test
@@ -0,0 +1,15 @@
+# A wrapper to test that dropping a database is binlogged
+# correctly. We test all three modes in the same file to avoid
+# unecessary server restarts.
+
+--source include/have_innodb.inc
+--source include/have_binlog_format_statement.inc
+
+set binlog_format=statement;
+source include/database.test;
+set binlog_format=mixed;
+source include/database.test;
+set binlog_format=row;
+source include/database.test;
+
+show databases;
diff --git a/mysql-test/suite/binlog/t/binlog_delete_and_flush_index-master.opt b/mysql-test/suite/binlog/t/binlog_delete_and_flush_index-master.opt
new file mode 100644
index 00000000..434bd66d
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_delete_and_flush_index-master.opt
@@ -0,0 +1 @@
+--log-bin=master-bin --log-bin-index=master-bin
diff --git a/mysql-test/suite/binlog/t/binlog_delete_and_flush_index.test b/mysql-test/suite/binlog/t/binlog_delete_and_flush_index.test
new file mode 100644
index 00000000..84c83687
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_delete_and_flush_index.test
@@ -0,0 +1,114 @@
+# BUG#34582: FLUSH LOGS does not close and reopen the binlog index
+# file
+#
+# WHAT
+# ====
+#
+# We want to test that FLUSH LOGS closes and reopens binlog index
+# file.
+#
+# HOW
+# ===
+#
+# PREPARE:
+# 1. create some binlog events
+# 2. show index content, binlog events and binlog contents
+# for mysql-bin.000001
+# 3. copy the mysql-bin.000001 to mysql-bin-b34582.000001
+# 4. change the index file so that mysql-bin.000001 is replaced
+# with mysql-bin-b34582.000001
+# 5. FLUSH the logs so that new index is closed and reopened
+#
+# ASSERTIONS:
+# 1. index file contents shows mysql-bin-b34582.000001 and
+# mysql-bin.000002
+# 1. show binary logs shows current index entries
+# 2. binlog contents for mysql-bin-b34582.000001 are displayed
+# 3. Purge binlogs up to the latest one succeeds
+# 4. SHOW BINARY LOGS presents the latest one only after purging
+# 5. Purged binlogs files don't exist in the filesystem
+# 6. Not purged binlog file exists in the filesystem
+#
+# CLEAN UP:
+# 1. RESET MASTER
+#
+
+-- source include/have_log_bin.inc
+
+RESET MASTER;
+
+-- let $datadir= `SELECT @@datadir`
+-- let $index=$datadir/master-bin.index
+-- chmod 0644 $index
+
+# action: issue one command so that binlog gets some event
+CREATE TABLE t1 (a int);
+
+-- echo ### assertion: index file contains regular entries
+-- replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
+-- eval SET @index=LOAD_FILE('$index')
+-- replace_regex /\.[\\\/]master/master/
+SELECT @index;
+
+--echo ### assertion: show original binlogs
+-- source include/show_binary_logs.inc
+
+--echo ### assertion: binlog contents from regular entries
+-- source include/show_binlog_events.inc
+
+# action: copy binlogs to other names and change entries in index file
+-- copy_file $datadir/master-bin.000001 $datadir/master-bin-b34582.000001
+let INDEX_FILE=$index;
+perl;
+$file= $ENV{'INDEX_FILE'};
+open(FILE, ">$file") || die "Unable to open $file.";
+truncate(FILE,0);
+close ($file);
+EOF
+
+-- append_file $index
+master-bin-b34582.000001
+EOF
+
+# action: should cause rotation, and creation of new binlogs
+FLUSH LOGS;
+
+# file is not used anymore - remove it (mysql closed on flush logs).
+-- remove_file $datadir/master-bin.000001
+
+-- echo ### assertion: index file contains renamed binlog and the new one
+-- replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
+-- eval SET @index=LOAD_FILE('$index')
+-- replace_regex /\.[\\\/]master/master/
+SELECT @index;
+
+-- echo ### assertion: original binlog content still exists, despite we
+-- echo ### renamed and changed the index file
+-- source include/show_binlog_events.inc
+
+-- echo ### assertion: user changed binlog index shows correct entries
+-- source include/show_binary_logs.inc
+
+DROP TABLE t1;
+
+-- echo ### assertion: purging binlogs up to binlog created after instrumenting index file should work
+-- let $current_binlog= query_get_value(SHOW MASTER STATUS, File, 1)
+-- eval PURGE BINARY LOGS TO '$current_binlog'
+
+-- echo ### assertion: show binary logs should only contain latest binlog
+-- source include/show_binary_logs.inc
+
+-- echo ### assertion: assert that binlog files were indeed purged (using file_exists calls)
+-- error 1
+-- file_exists $datadir/master-bin-b34852.000001
+
+-- echo ### assertion: assert that not purged binlog file exists
+-- file_exists $datadir/$current_binlog
+
+-- echo ### assertion: show index file contents and these should match show binary logs issued above
+-- replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
+-- eval SET @index=LOAD_FILE('$index')
+-- replace_regex /\.[\\\/]master/master/
+SELECT @index;
+
+RESET MASTER;
diff --git a/mysql-test/suite/binlog/t/binlog_dmls_on_tmp_tables_readonly.test b/mysql-test/suite/binlog/t/binlog_dmls_on_tmp_tables_readonly.test
new file mode 100644
index 00000000..dd0cdd0f
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_dmls_on_tmp_tables_readonly.test
@@ -0,0 +1,92 @@
+# ==== Purpose ====
+#
+# Check that DMLs are allowed on temporary tables, when server is in read only
+# mode and binary log is enabled with binlog-format being stmt/mixed mode.
+#
+# ==== Implementation ====
+#
+# Start the server with binary log being enabled. Mark the server as read only.
+# Create a non-SUPER user and let the user to create a temporary table and
+# perform DML operations on that temporary table. DMLs should not be blocked
+# with a 'server read-only mode' error.
+#
+# ==== References ====
+#
+# Bug#12818255: READ-ONLY OPTION DOES NOT ALLOW INSERTS/UPDATES ON TEMPORARY
+# TABLES
+# Bug#14294223: CHANGES NOT ALLOWED TO TEMPORARY TABLES ON READ-ONLY SERVERS
+###############################################################################
+--source include/have_log_bin.inc
+--source include/have_innodb.inc
+--disable_warnings
+DROP TABLE IF EXISTS t1 ;
+--enable_warnings
+
+--enable_connect_log
+--echo # READ_ONLY does nothing to SUPER users
+--echo # so we use a non-SUPER one:
+CREATE USER test@localhost;
+GRANT CREATE TEMPORARY TABLES, SELECT, DROP ON *.* TO test@localhost;
+
+connect (con1,localhost,test,,test);
+
+connection default;
+SET GLOBAL READ_ONLY=1;
+
+connection con1;
+CREATE TEMPORARY TABLE t1 (a INT) ENGINE=INNODB;
+
+--echo # Test INSERTS with autocommit being off and on.
+BEGIN;
+INSERT INTO t1 VALUES (10);
+COMMIT;
+INSERT INTO t1 VALUES (20);
+
+--echo # Test UPDATES with autocommit being off and on.
+BEGIN;
+UPDATE t1 SET a=30 WHERE a=10;
+COMMIT;
+UPDATE t1 SET a=40 WHERE a=20;
+
+connection default;
+SET GLOBAL READ_ONLY=0;
+
+--echo # Test scenario where global read_only is enabled in the middle of transaction.
+--echo # Test INSERT operations on temporary tables, INSERTs should be successful even
+--echo # when global read_only is enabled.
+connection con1;
+BEGIN;
+INSERT INTO t1 VALUES(50);
+
+connection default;
+SET GLOBAL READ_ONLY=1;
+
+connection con1;
+SELECT @@GLOBAL.READ_ONLY;
+COMMIT;
+
+connection default;
+SET GLOBAL READ_ONLY=0;
+
+--echo # Test UPDATE operations on temporary tables, UPDATEs should be successful even
+--echo # when global read_only is enabled.
+connection con1;
+BEGIN;
+UPDATE t1 SET a=60 WHERE a=50;
+
+connection default;
+SET GLOBAL READ_ONLY=1;
+
+connection con1;
+SELECT @@GLOBAL.READ_ONLY;
+COMMIT;
+
+SELECT * FROM t1;
+
+--echo # Clean up
+connection default;
+SET GLOBAL READ_ONLY=0;
+
+disconnect con1;
+DROP USER test@localhost;
+--disable_connect_log
diff --git a/mysql-test/suite/binlog/t/binlog_drop_if_exists.test b/mysql-test/suite/binlog/t/binlog_drop_if_exists.test
new file mode 100644
index 00000000..b565104c
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_drop_if_exists.test
@@ -0,0 +1,162 @@
+--source include/have_innodb.inc
+
+# BUG#13684:
+# SP: DROP PROCEDURE|FUNCTION IF EXISTS not binlogged if routine
+# does not exist
+#
+# There is an inconsistency with DROP DATABASE IF EXISTS, DROP
+# TABLE IF EXISTS and DROP VIEW IF EXISTS: those are binlogged even
+# if the DB or TABLE does not exist, whereas DROP PROCEDURE IF
+# EXISTS does not. It would be nice or at least consistent if DROP
+# PROCEDURE/STATEMENT worked the same too.
+#
+# Description:
+# DROP PROCEDURE|FUNCTION IF EXISTS does not get binlogged whereas DROP
+# DATABASE|TABLE|TRIGGER|... IF EXISTS do.
+#
+# Fixed DROP PROCEDURE|FUNCTION IF EXISTS by adding a call to
+# write_bin_log in mysql_execute_command. Checked also if all
+# documented "DROP (...) IF EXISTS" get binlogged. Left out DROP
+# SERVER IF EXISTS because it seems that it only gets binlogged when
+# using row event (see BUG#25705).
+#
+# TODO: add DROP SERVER IF EXISTS to the test case when its
+# binlogging procedure gets fixed (BUG#25705). Furthermore, when
+# logging in RBR format the events that get logged are effectively in
+# RBR format and not in STATEMENT format meaning that one must needs
+# to be extra careful when writing a test for it, or change the CREATE
+# SERVER logging to always log as STATEMENT. You can quickly check this
+# by enabling the flag below $fixed_bug_25705=1 and watch the diff on
+# the STDOUT. More detail may be found on the generated reject file.
+#
+# Test is implemented as follows:
+#
+# i) test each "drop if exists" (DDL), found in MySQL 5.1 manual,
+# on inexistent objects (except for DROP SERVER);
+# ii) show binlog events;
+# iii) create an object for each drop if exists statement;
+# iv) issue "drop if exists" in existent objects.
+# v) show binlog events;
+#
+# References:
+# http://dev.mysql.com/doc/refman/5.1/en/sql-syntax-data-definition.html
+#
+--source include/have_log_bin.inc
+RESET MASTER;
+
+disable_warnings;
+
+# test all "drop if exists" in manual with inexistent objects
+DROP PROCEDURE IF EXISTS db_bug_13684.p;
+DROP FUNCTION IF EXISTS db_bug_13684.f;
+DROP TRIGGER IF EXISTS db_bug_13684.tr;
+DROP VIEW IF EXISTS db_bug_13684.v;
+DROP EVENT IF EXISTS db_bug_13684.e;
+DROP TABLE IF EXISTS db_bug_13684.t;
+DROP DATABASE IF EXISTS db_bug_13684;
+
+let $fixed_bug_25705 = 0;
+
+if($fixed_bug_25705)
+{
+ DROP SERVER IF EXISTS s_bug_13684;
+}
+--source include/show_binlog_events.inc
+
+# test drop with existing values
+
+# create
+CREATE DATABASE db_bug_13684;
+
+CREATE TABLE db_bug_13684.t (a int);
+
+CREATE EVENT db_bug_13684.e
+ ON SCHEDULE AT CURRENT_TIMESTAMP + INTERVAL 1 HOUR
+ DO
+ UPDATE db_bug_13684.t SET a = a + 1;
+
+CREATE VIEW db_bug_13684.v
+ AS SELECT * FROM db_bug_13684.t;
+
+CREATE TRIGGER db_bug_13684.tr BEFORE INSERT ON db_bug_13684.t
+ FOR EACH ROW BEGIN
+ END;
+
+CREATE PROCEDURE db_bug_13684.p (OUT p1 INT)
+ BEGIN
+ END;
+
+CREATE FUNCTION db_bug_13684.f (s CHAR(20))
+ RETURNS CHAR(50) DETERMINISTIC
+ RETURN s;
+
+if($fixed_bug_25705)
+{
+ CREATE SERVER s_bug_13684
+ FOREIGN DATA WRAPPER mysql
+ OPTIONS (USER 'Remote', HOST '192.168.1.106', DATABASE 'test');
+}
+
+--source include/show_binlog_events.inc
+
+# drop existing
+DROP PROCEDURE IF EXISTS db_bug_13684.p;
+DROP FUNCTION IF EXISTS db_bug_13684.f;
+DROP TRIGGER IF EXISTS db_bug_13684.tr;
+DROP VIEW IF EXISTS db_bug_13684.v;
+DROP EVENT IF EXISTS db_bug_13684.e;
+DROP TABLE IF EXISTS db_bug_13684.t;
+DROP DATABASE IF EXISTS db_bug_13684;
+if($fixed_bug_25705)
+{
+ DROP SERVER IF EXISTS s_bug_13684;
+}
+
+--source include/show_binlog_events.inc
+
+enable_warnings;
+
+# Drop comments in binlog
+let $binlog_start= query_get_value(SHOW MASTER STATUS, Position, 1);
+CREATE TABLE t1(id int);
+DROP TABLE /* comment */ t1;
+CREATE TABLE t1(id int);
+DROP TABLE IF EXISTS /* comment */ t1;
+
+CREATE TABLE t1(id int);
+DROP TABLE /**/ t1;
+CREATE TABLE t1(id int);
+DROP TABLE IF EXISTS /* */ t1;
+
+--source include/show_binlog_events.inc
+
+--echo #
+--echo # MDEV-22820 Bogus "Unknown table" warnings produced upon attempt to
+--echo # drop parent table referenced by FK
+--echo #
+
+let $binlog_start= query_get_value(SHOW MASTER STATUS, Position, 1);
+
+create table t1 (a int, key(a)) engine=InnoDB;
+create table t2 (b int, foreign key(b) references t1(a)) engine=InnoDB;
+--error ER_ROW_IS_REFERENCED_2
+drop table if exists t1;
+--error ER_ROW_IS_REFERENCED_2
+drop table if exists t1,t0;
+show warnings;
+drop table t2,t1;
+
+create table t3 (a int) engine=aria;
+
+# This is not logged
+--error ER_BAD_TABLE_ERROR
+drop table t10,t20;
+# This is logged
+--error ER_BAD_TABLE_ERROR
+drop table t10,t20,t3;
+
+# These are both logged
+drop table if exists t10,t20;
+drop table if exists t10,t20,t3;
+
+--source include/show_binlog_events.inc
diff --git a/mysql-test/suite/binlog/t/binlog_empty_xa_prepared.test b/mysql-test/suite/binlog/t/binlog_empty_xa_prepared.test
new file mode 100644
index 00000000..501403f4
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_empty_xa_prepared.test
@@ -0,0 +1,148 @@
+# The test verifies execution and binary logging of user XA that produce empty
+# XA-PREPARE group of events.
+
+--source include/have_binlog_format_mixed.inc
+--source include/have_innodb.inc
+
+RESET MASTER; # clear binlogs
+# MDEV-22420 DDL on temporary object is prohibited when XA is in prepare state
+
+# Temporary sequnce may not be created within a transaction
+CREATE TEMPORARY SEQUENCE seq_1;
+
+XA START '3';
+CREATE TEMPORARY TABLE tmp_1(c INT);
+XA END '3';
+XA PREPARE '3';
+--error ER_XAER_RMFAIL
+DROP TEMPORARY TABLE tmp_1;
+--error ER_XAER_RMFAIL
+ALTER TABLE tmp_1 DROP COLUMN c;
+--error ER_XAER_RMFAIL
+DROP TEMPORARY SEQUENCE seq_1;
+--error ER_XAER_RMFAIL
+ALTER SEQUENCE seq_1 INCREMENT BY 1;
+
+--error ER_XAER_RMFAIL
+CREATE TEMPORARY TABLE tmp_2(c INT);
+--error ER_XAER_RMFAIL
+CREATE TEMPORARY SEQUENCE seq_2;
+
+# Cleanup
+XA ROLLBACK '3';
+
+--echo # Proof of correct logging incl empty XA-PREPARE
+--source include/show_binlog_events.inc
+
+# The test verifies execution and binary logging of user XA that produce empty
+# XA-PREPARE group of events.
+#
+# MDEV-22757 Assertion `!binlog || exist_hton_without_prepare'
+# in MYSQL_BIN_LOG::unlog_xa_prepare
+
+RESET MASTER;
+CREATE TABLE t1 (a INT) ENGINE=MyISAM;
+CREATE TABLE t2 (id INT PRIMARY KEY) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1),(2);
+INSERT INTO t2 VALUES (1),(2);
+
+XA START '1';
+REPLACE INTO t1 SELECT * FROM t1;
+REPLACE INTO t2 SELECT * FROM t2;
+XA END '1';
+XA PREPARE '1';
+
+# Cleanup
+XA ROLLBACK '1';
+DROP TABLE t1, t2;
+
+--echo # Proof of correct logging incl empty XA-PREPARE
+--source include/show_binlog_events.inc
+
+
+# MDEV-22430 Assertion ... in MYSQL_BIN_LOG::unlog_xa_prepare
+
+RESET MASTER;
+CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1);
+CREATE SEQUENCE s ENGINE=InnoDB;
+
+XA START '2';
+--disable_ps2_protocol
+SELECT NEXT VALUE FOR s;
+--enable_ps2_protocol
+REPLACE INTO t1 SELECT * FROM t1;
+XA END '2';
+XA PREPARE '2';
+
+# Cleanup
+XA ROLLBACK '2';
+DROP SEQUENCE s;
+DROP TABLE t1;
+
+--echo # Proof of correct logging incl empty XA-PREPARE
+--source include/show_binlog_events.inc
+
+
+# MDEV-25616 Binlog event for XA COMMIT is generated without matching XA START
+
+CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1);
+
+--source include/count_sessions.inc
+--connect(con1,localhost,root,,)
+
+XA START '1';
+ --error ER_DUP_ENTRY
+ INSERT INTO t1 VALUES (2),(1);
+ SELECT * FROM t1 WHERE a = 2;
+XA END '1';
+XA PREPARE '1';
+
+--disconnect con1
+
+--connection default
+--source include/wait_until_count_sessions.inc
+XA RECOVER;
+
+--error ER_XA_RBROLLBACK
+XA COMMIT '1';
+--echo Must be no XA PREPARE group nor XA completion one:
+--source include/show_binlog_events.inc
+DROP TABLE t1;
+
+--source include/count_sessions.inc
+
+--connect(con2,localhost,root,,)
+CREATE TABLE tm (a INT PRIMARY KEY) ENGINE=MyISAM;
+XA START '1';
+ --error ER_DUP_ENTRY
+ INSERT INTO tm VALUES (1),(1);
+ SELECT * FROM tm WHERE a = 2;
+XA END '1';
+XA PREPARE '1';
+
+--disconnect con2
+
+--connection default
+--source include/wait_until_count_sessions.inc
+XA RECOVER;
+
+--error ER_XA_RBROLLBACK
+XA ROLLBACK '1';
+--echo Must be no XA PREPARE group nor XA completion one:
+--source include/show_binlog_events.inc
+DROP TABLE tm;
+
+
+# MDEV-32257 dangling XA-rollback in binlog from emtpy XA
+--connection default
+--let $binlog_start = query_get_value(SHOW MASTER STATUS, Position, 1)
+--let $binlog_file = query_get_value(SHOW MASTER STATUS, File, 1)
+SET pseudo_slave_mode=1;
+XA START 'a';
+XA END 'a';
+XA PREPARE 'a';
+--error ER_XA_RBROLLBACK
+XA ROLLBACK 'a';
+--source include/show_binlog_events.inc
diff --git a/mysql-test/suite/binlog/t/binlog_expire_logs_seconds.test b/mysql-test/suite/binlog/t/binlog_expire_logs_seconds.test
new file mode 100644
index 00000000..bb53f2c4
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_expire_logs_seconds.test
@@ -0,0 +1,122 @@
+#
+# WL#9236: Add a new variable binlog_expire_logs_seconds
+#
+# ==== Purpose ====
+# The test case test the following:
+#
+# 1. If binlog_expire_logs_seconds = 0 and expire_logs_days = 0, no purge happens.
+#
+# 2. In all the below listed cases it purges the binary logs older than the timeout
+# and keeps the binary logs newer than the timeout.
+#
+# 2.1. binlog_expire_logs_seconds > 0 and expire_logs_days > 0
+# 2.2. binlog_expire_logs_seconds > 0 and expire_logs_days = 0
+# 2.3. binlog_expire_logs_seconds = 0 and expire_logs_days > 0
+# 2.4. binlog_expire_logs_seconds = 1, testing smallest value
+# 2.5. binlog_expire_logs_seconds = 8553600, testing max value 99days
+#
+# Additional tests for the boundaries of expire_logs_days already
+# exist on the sys_vars.expire_logs_days_basic test case.
+
+# Test in this file is binlog format agnostic, thus no need
+# to rerun it for every format.
+--source include/have_binlog_format_row.inc
+--source include/not_windows.inc
+
+--let $saved_expire_logs_days= `SELECT @@GLOBAL.expire_logs_days`
+--let $saved_binlog_expire_logs_seconds= `SELECT @@GLOBAL.binlog_expire_logs_seconds`
+# Set the datadir
+--let $MYSQLD_DATADIR= `SELECT @@datadir`
+
+--echo ####
+--echo #### 1. When binlog_expire_logs_seconds == 0 and expire_logs_days == 0
+--echo #### no purge should happen
+
+SET GLOBAL binlog_expire_logs_seconds= 0;
+SET GLOBAL expire_logs_days= 0;
+
+# This will test the expire period for three scenarios, described in the .inc file.
+--source suite/binlog/include/binlog_expire_logs_seconds.inc
+
+--echo ####
+--echo #### 2.1: binlog_expire_logs_seconds > 0 and expire_logs_days > 0
+--echo #### expire_logs_days=1.5 and binlog_expire_logs_seconds=86400
+--echo #### Since binlog_expire_logs_seconds is set later
+--echo #### expire_logs_days value will be overridden should be
+--echo #### '0.000347222'
+--echo ####
+
+# Here we will test both with smaller values and larger values
+
+--echo Testing with smaller values of binlog_expire_logs_seconds
+
+SET GLOBAL expire_logs_days= 1.5;
+SET GLOBAL binlog_expire_logs_seconds= 30 ;
+SELECT @@expire_logs_days as 'Expected_0.000347222';
+SELECT @@binlog_expire_logs_seconds as Expected_30;
+
+--let $expire_logs_seconds= `SELECT @@global.binlog_expire_logs_seconds`
+
+--let $first_binlog_file= query_get_value(SHOW MASTER STATUS, File, 1)
+FLUSH LOGS;
+
+--sleep $expire_logs_seconds
+
+--let $second_binlog_file= query_get_value(SHOW MASTER STATUS, File, 1)
+FLUSH LOGS;
+
+# The sleep is in two parts to ensure a time gap between first_binlog_file
+# and second_binlog_file, by doing that we can check that one is purged and
+# another isn't.
+# sleep for n seconds here, n < $expire_logs_seconds
+--sleep 3
+FLUSH LOGS;
+
+--error 1
+--file_exists $MYSQLD_DATADIR/$first_binlog_file
+
+--file_exists $MYSQLD_DATADIR/$second_binlog_file
+
+RESET MASTER;
+--echo ####
+--echo #### 2.2: binlog_expire_logs_seconds = 43200 and expire_logs_days = 0
+--echo ####
+
+SET GLOBAL expire_logs_days=0;
+SET GLOBAL binlog_expire_logs_seconds=43200;
+SELECT @@expire_logs_days as 'Expected_0.5';
+SELECT @@binlog_expire_logs_seconds as Expected_43200;
+
+# This will test the expire period for three scenarios, described in the .inc file.
+
+--source suite/binlog/include/binlog_expire_logs_seconds.inc
+
+--echo ####
+--echo #### 2.3: binlog_expire_logs_seconds == 0 and expire_logs_days > 0
+--echo ####
+
+SET GLOBAL binlog_expire_logs_seconds= 0;
+SET GLOBAL expire_logs_days= 1;
+SELECT @@expire_logs_days as Expected_1;
+SELECT @@binlog_expire_logs_seconds as Expected_86400;
+
+# This will test the expire period for three scenarios, described in the .inc file.
+--source suite/binlog/include/binlog_expire_logs_seconds.inc
+
+--echo ####
+--echo #### 2.4: binlog_expire_logs_seconds = 1
+--echo ####
+SET GLOBAL binlog_expire_logs_seconds= 1;
+SELECT @@expire_logs_days;
+SELECT @@binlog_expire_logs_seconds as Expected_1;
+
+--echo ####
+--echo #### 2.5. binlog_expire_logs_seconds = 8553600, testing max value 99days
+--echo ####
+SET GLOBAL binlog_expire_logs_seconds= 8553600;
+SELECT @@expire_logs_days;
+SELECT @@binlog_expire_logs_seconds as Expected_8553600;
+
+# reset the variables
+--eval SET GLOBAL binlog_expire_logs_seconds= $saved_binlog_expire_logs_seconds
+--eval SET GLOBAL expire_logs_days= $saved_expire_logs_days
diff --git a/mysql-test/suite/binlog/t/binlog_expire_warnings.test b/mysql-test/suite/binlog/t/binlog_expire_warnings.test
new file mode 100644
index 00000000..2e0831ad
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_expire_warnings.test
@@ -0,0 +1,200 @@
+# ==== Requirements ====
+#
+# Verify the logic for warnings related to expire-logs-days and
+# binlog-expire-logs-seconds on server start:
+#
+# R0. All the following shall hold with binlog disabled and binlog enabled.
+#
+# R1. Binlog off warnings:
+#
+# R1.1. If the binary log is disabled, using any of
+# binlog-expire-logs-seconds or expire_logs_days shall
+# generate a warning.
+#
+# R1.2. If the binary log is enabled, or if
+# binlog-expire-logs-seconds / expire_logs_days is not used,
+# there shall be no warning for this case.
+#
+# R2. Values:
+#
+# R2.1. None of expire-logs-days or binlog-expire-logs-seconds is
+# set: both shall use their default values (days=0, seconds=0)
+#
+# R2.2. Exactly one of expire-logs-days or binlog-expire-logs-seconds
+# is set: that value is propogated to other variable.
+#
+# R2.3. Both expire-logs-days or binlog-expire-logs-seconds are
+# set, and at least one of them is set to zero: the last set value
+# should be effective and its value will be propogated to other
+# variable.
+#
+# R2.4. Both expire-logs-days and binlog-expire-logs-seconds are
+# set, and both are non-zero: the last set value
+# should be effective and its value will be propogated to other
+# variable.
+#
+# ==== Implementation ====
+#
+# Test all combinations of:
+#
+# - log-bin: on, off
+# - expire-logs-days: not set, set to 0, set to nonzero
+# - binlog-expire-logs-seconds: not set, set to 0, set to nonzero
+# - Verify option value propogation, by varying the order, in which options
+# are set
+# --expire_logs_days --binlog_expire_logs_seconds
+# --binlog_expire_logs_seconds --expire_logs_days
+# For each such scenario, state the expected warnings and values, and
+# use extra/binlog_tests/binlog_expire_warnings.inc to execute the
+# scenario.
+#
+# ==== References ====
+#
+# MDEV-19371: Implement binlog_expire_logs_seconds for purging of binary
+# logs
+#
+--source include/have_binlog_format_row.inc
+
+# Restarts the server with new options.
+--source include/force_restart.inc
+
+# A bit slow, since it restarts the server many times. Also, this is
+# unlikely to break in the future, so not important to run frequently.
+--source include/big_test.inc
+
+
+--let $ofile = $MYSQLTEST_VARDIR/tmp/binlog_expire_warnings-output.err
+
+--let $i = 0
+while ($i < 2) {
+
+if ($i == 0) {
+ --echo #### Binary log ENABLED ####
+ --let $options =
+ --let $binlog_off = 0
+ }
+ if ($i == 1) {
+ --echo #### Binary log DISABLED ####
+ --let $options = --skip-log-bin
+ --let $binlog_off = 1
+ }
+
+ --echo ==== Don't set any option ====
+
+ --let $days =
+ --let $seconds =
+ --let $expect_binlog_off_days_and_seconds_warning = 0
+ --let $expect_days = 0
+ --let $expect_seconds = 0
+ --source suite/binlog/include/binlog_expire_warnings.inc
+
+ --echo ==== Set one option to zero ====
+
+ --echo ---- days=0 ----
+ --let $days = 0
+ --let $seconds =
+ --let $expect_binlog_off_days_and_seconds_warning = 0
+ --let $expect_days = 0
+ --let $expect_seconds = 0
+ --let $option_invoke_order= days_then_seconds
+ --source suite/binlog/include/binlog_expire_warnings.inc
+
+ --echo ---- seconds=0 ----
+ --let $days =
+ --let $seconds = 0
+ --let $expect_binlog_off_days_and_seconds_warning = 0
+ --let $expect_days = 0
+ --let $expect_seconds = 0
+ --let $option_invoke_order= seconds_then_days
+ --source suite/binlog/include/binlog_expire_warnings.inc
+
+ --echo ==== Set one option to non-zero ====
+
+ --echo ---- days=2 ----
+ --let $days = 2
+ --let $seconds =
+ --let $expect_binlog_off_days_and_seconds_warning = $binlog_off
+ --let $expect_days = 2
+ --let $expect_seconds = `SELECT $days * 24 * 60 * 60`
+ --let $option_invoke_order= days_then_seconds
+ --source suite/binlog/include/binlog_expire_warnings.inc
+
+ --echo ---- seconds=86400 ----
+ --let $days =
+ --let $seconds = 86400
+ --let $expect_binlog_off_days_and_seconds_warning = $binlog_off
+ --let $expect_days = 1
+ --let $expect_seconds = 86400
+ --let $option_invoke_order= days_then_seconds
+ --source suite/binlog/include/binlog_expire_warnings.inc
+
+ --echo ==== Set both options to zero ====
+
+ --let $days = 0
+ --let $seconds = 0
+ --let $expect_binlog_off_days_and_seconds_warning = 0
+ --let $expect_days = 0
+ --let $expect_seconds = 0
+ --let $option_invoke_order= days_then_seconds
+ --source suite/binlog/include/binlog_expire_warnings.inc
+
+ --echo ==== Set both options: one to zero and one to non-zero ====
+ --echo ---- days=1 seconds=0 ----
+ --echo ---- The later seconds=0 will override days.
+ --let $days = 1
+ --let $seconds = 0
+ --let $expect_binlog_off_days_and_seconds_warning = 0
+ --let $expect_days = 0
+ --let $expect_seconds = 0
+ --let $option_invoke_order= days_then_seconds
+ --source suite/binlog/include/binlog_expire_warnings.inc
+
+ --echo ---- seconds=0 days=1 ----
+ --echo ---- The later days=1 will override seconds.
+ --let $days = 1
+ --let $seconds = 0
+ --let $expect_binlog_off_days_and_seconds_warning = $binlog_off
+ --let $expect_days = 1
+ --let $expect_seconds = 86400
+ --let $option_invoke_order= seconds_then_days
+ --source suite/binlog/include/binlog_expire_warnings.inc
+
+ --echo ---- days=0 seconds=86400 ----
+ --echo ---- The later seconds=86400 will override days.
+ --let $days = 0
+ --let $seconds = 86400
+ --let $expect_binlog_off_days_and_seconds_warning = $binlog_off
+ --let $expect_days = 1
+ --let $expect_seconds = 86400
+ --let $option_invoke_order= days_then_seconds
+ --source suite/binlog/include/binlog_expire_warnings.inc
+
+ --echo ==== Set both options to non-zero ====
+
+ --echo ---- days=1 and seconds=172800 ----
+ --echo ---- Since binlog_expire_logs_seconds is set later expire_log_days
+ --echo ---- becomes 2
+ --let $days = 1
+ --let $seconds = 172800
+ --let $expect_binlog_off_days_and_seconds_warning = $binlog_off
+ --let $expect_days = 2
+ --let $expect_seconds = 172800
+ --let $option_invoke_order= days_then_seconds
+ --source suite/binlog/include/binlog_expire_warnings.inc
+
+ --echo ---- days=1 and seconds=172800 ----
+ --echo ---- Since expire_logs_days is set later binlog_expire_logs_seconds
+ --echo ---- becomes 86400
+ --let $days = 1
+ --let $seconds = 172800
+ --let $expect_binlog_off_days_and_seconds_warning = $binlog_off
+ --let $expect_days = 1
+ --let $expect_seconds = 86400
+ --let $option_invoke_order= seconds_then_days
+ --source suite/binlog/include/binlog_expire_warnings.inc
+
+ --inc $i
+}
+
+# cleanup
+--remove_file $ofile
diff --git a/mysql-test/suite/binlog/t/binlog_flush_binlogs_delete_domain.test b/mysql-test/suite/binlog/t/binlog_flush_binlogs_delete_domain.test
new file mode 100644
index 00000000..1643ecff
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_flush_binlogs_delete_domain.test
@@ -0,0 +1,167 @@
+# Prove basic properties of
+#
+# FLUSH BINARY LOGS DELETE_DOMAIN_ID = (...)
+#
+# The command removes the supplied list of domains from the current
+# @@global.gtid_binlog_state provided the binlog files do not contain
+# events from such domains.
+
+# The test is not format specific. One format is chosen to run it.
+--source include/have_binlog_format_mixed.inc
+
+# Reset binlog state
+RESET MASTER;
+
+# Empty list is accepted
+FLUSH BINARY LOGS DELETE_DOMAIN_ID = ();
+--echo and the command execution is effective thence rotates binlog as usual
+--source include/show_binary_logs.inc
+
+--echo Non-existed domain is warned, the command completes without rotation
+--echo but with a warning
+--let $binlog_pre_flush=query_get_value(SHOW MASTER STATUS, Position, 1)
+FLUSH BINARY LOGS DELETE_DOMAIN_ID = (99);
+--source include/show_binary_logs.inc
+
+# Log one event in a specified domain and try to delete the domain
+SET @@SESSION.gtid_domain_id=1;
+SET @@SESSION.server_id=1;
+CREATE TABLE t (a int);
+SELECT @@GLOBAL.gtid_binlog_state, @@GLOBAL.gtid_binlog_pos;
+--let $binlog_start=
+--source include/show_binlog_events.inc
+
+--error ER_BINLOG_CANT_DELETE_GTID_DOMAIN
+FLUSH BINARY LOGS DELETE_DOMAIN_ID = (1);
+
+# the same error after log rotation
+FLUSH BINARY LOGS;
+--error ER_BINLOG_CANT_DELETE_GTID_DOMAIN
+FLUSH BINARY LOGS DELETE_DOMAIN_ID = (1);
+
+# the latest binlog does not really contain any events incl ones from 1-domain
+--let $purge_to_binlog= query_get_value(SHOW MASTER STATUS, File, 1)
+--eval PURGE BINARY LOGS TO '$purge_to_binlog';
+# So now it's safe to delete
+--error 0
+FLUSH BINARY LOGS DELETE_DOMAIN_ID = (1);
+--echo Gtid_list of the current binlog does not contain '1':
+--let $binlog_file=query_get_value(SHOW MASTER STATUS, File, 1)
+--source include/show_gtid_list.inc
+--echo But the previous log's Gtid_list may have it which explains a warning from the following command
+--let $binlog_file=$purge_to_binlog
+--source include/show_gtid_list.inc
+
+--echo Already deleted domain in Gtid_list of the earliest log is benign
+--echo but may cause a warning
+--error 0
+FLUSH BINARY LOGS DELETE_DOMAIN_ID = (1);
+
+# Few domains delete. The chosen number verifies among others how
+# expected overrun of the static buffers of underlying dynamic arrays is doing.
+--let $domain_cnt=17
+--let $server_in_domain_cnt=3
+--let $err_domain_id=`SELECT FLOOR($domain_cnt/2)`
+--let $err_server_id=`SELECT FLOOR($server_in_domain_cnt/2)`
+--let $domain_list=
+--disable_query_log
+while ($domain_cnt)
+{
+ --let servers=$server_in_domain_cnt
+ --eval SET @@SESSION.gtid_domain_id=$domain_cnt
+ while ($servers)
+ {
+ --eval SET @@SESSION.server_id=10*$domain_cnt + $servers
+ --eval INSERT INTO t SET a=@@SESSION.server_id
+
+ --dec $servers
+ }
+ --let $domain_list= $domain_cnt, $domain_list
+
+ --dec $domain_cnt
+}
+--enable_query_log
+--let $zero=0
+--let $domain_list= $domain_list$zero
+
+--error ER_BINLOG_CANT_DELETE_GTID_DOMAIN
+--eval FLUSH BINARY LOGS DELETE_DOMAIN_ID = ($domain_list)
+
+--echo MDEV-31140: Missing error from DELETE_DOMAIN_ID when gtid_binlog_state partially matches GTID_LIST.
+FLUSH BINARY LOGS;
+--let $purge_to_binlog= query_get_value(SHOW MASTER STATUS, File, 1)
+--eval PURGE BINARY LOGS TO '$purge_to_binlog'
+--eval SET @@SESSION.gtid_domain_id=$err_domain_id
+--eval SET @@SESSION.server_id=10*$err_domain_id + $err_server_id
+eval INSERT INTO t SELECT 1+MAX(a) FROM t;
+--error ER_BINLOG_CANT_DELETE_GTID_DOMAIN
+--eval FLUSH BINARY LOGS DELETE_DOMAIN_ID = ($domain_list)
+
+# Now satisfy the safety condtion to purge log files containing $domain list
+FLUSH BINARY LOGS;
+--let $purge_to_binlog= query_get_value(SHOW MASTER STATUS, File, 1)
+--eval PURGE BINARY LOGS TO '$purge_to_binlog'
+--error 0
+--eval FLUSH BINARY LOGS DELETE_DOMAIN_ID = ($domain_list)
+--echo Gtid_list of the current binlog does not contain $domain_list:
+--let $binlog_file=query_get_value(SHOW MASTER STATUS, File, 1)
+--source include/show_gtid_list.inc
+
+# Show reaction on @@global.gtid_binlog_state not succeeding
+# earlier state as described by the 1st binlog' Gtid_list.
+# Now let it be out-order gtid logged to a domain unrelated to deletion.
+
+--let $del_d_id=1
+--eval SET @@SESSION.gtid_domain_id=$del_d_id;
+SET @@SESSION.server_id=1;
+SET @@SESSION.gtid_seq_no=1;
+INSERT INTO t SET a=1;
+SET @@SESSION.server_id=2;
+SET @@SESSION.gtid_seq_no=2;
+INSERT INTO t SET a=2;
+
+SET @@SESSION.gtid_domain_id=11;
+SET @@SESSION.server_id=11;
+SET @@SESSION.gtid_seq_no=11;
+INSERT INTO t SET a=11;
+
+SET @gtid_binlog_state_saved=@@GLOBAL.gtid_binlog_state;
+FLUSH BINARY LOGS;
+
+# Inject out of order for domain '11' before
+SET @@SESSION.gtid_domain_id=11;
+SET @@SESSION.server_id=11;
+SET @@SESSION.gtid_seq_no=1;
+INSERT INTO t SET a=1;
+
+SELECT @gtid_binlog_state_saved "as original state", @@GLOBAL.gtid_binlog_state as "out of order for 11 domain state";
+
+# to delete '1', first to purge logs containing its events
+--let $purge_to_binlog= query_get_value(SHOW MASTER STATUS, File, 1)
+--eval PURGE BINARY LOGS TO '$purge_to_binlog'
+
+--echo the following command succeeds with warnings
+--eval FLUSH BINARY LOGS DELETE_DOMAIN_ID = ($del_d_id)
+
+# cleanup: forget the out-of-order
+RESET MASTER;
+
+#
+# MDEV-14431
+# Check rejection to delete a domain with value exceeding its range's maximum
+#
+--let $d_max_plus_1=`SELECT 1 << 32`
+--error ER_BINLOG_CANT_DELETE_GTID_DOMAIN
+--eval FLUSH BINARY LOGS DELETE_DOMAIN_ID = ($d_max_plus_1)
+
+# accepted maximum:
+--let $d_max=`SELECT (1 << 32) - 1`
+--error 0
+--eval FLUSH BINARY LOGS DELETE_DOMAIN_ID = ($d_max)
+
+#
+# Cleanup
+#
+
+DROP TABLE t;
+RESET MASTER;
diff --git a/mysql-test/suite/binlog/t/binlog_format_switch_in_tmp_table.test b/mysql-test/suite/binlog/t/binlog_format_switch_in_tmp_table.test
new file mode 100644
index 00000000..68685060
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_format_switch_in_tmp_table.test
@@ -0,0 +1,76 @@
+#
+# Bug #45855 row events in binlog after switch from binlog_fmt=mix to stmt with open tmp tbl
+# Bug #45856 can't switch from binlog_format=row to mix with open tmp tbl
+# This test verfies if the program will generate ER_TEMP_TABLE_PREVENTS_SWITCH_OUT_OF_RBR
+# error and forbid switching @@SESSION.binlog_format from MIXED or ROW to
+# STATEMENT when there are open temp tables and we are logging in row format.
+# There is no error in any other case.
+#
+
+source include/have_binlog_format_mixed.inc;
+
+SELECT @@SESSION.binlog_format;
+CREATE TABLE t1 (a VARCHAR(100));
+CREATE TEMPORARY TABLE t2 (a VARCHAR(100));
+
+--echo # Test allow switching @@SESSION.binlog_format from MIXED to STATEMENT
+--echo # when there are open temp tables and we are logging in statement based format.
+SET SESSION binlog_format = STATEMENT;
+SELECT @@SESSION.binlog_format;
+
+--echo # Test allow switching @@SESSION.binlog_format from STATEMENT to
+--echo # STATEMENT when there are open temp tables.
+SET SESSION binlog_format = STATEMENT;
+SELECT @@SESSION.binlog_format;
+
+INSERT INTO t1 VALUES ('statement based');
+SELECT @@SESSION.binlog_format;
+--echo # Test allow switching @@SESSION.binlog_format from STATEMENT to
+--echo # MIXED when there are open temp tables.
+SET SESSION binlog_format = MIXED;
+SELECT @@SESSION.binlog_format;
+
+--echo # Test allow switching @@SESSION.binlog_format from MIXED to MIXED
+--echo # when there are open temp tables.
+SET SESSION binlog_format = MIXED;
+SELECT @@SESSION.binlog_format;
+
+INSERT INTO t2 VALUES (UUID());
+SELECT @@SESSION.binlog_format;
+
+--echo # Test forbit switching @@SESSION.binlog_format from MIXED to STATEMENT
+--echo # when there are open temp tables and we are logging in row based format.
+--ERROR ER_TEMP_TABLE_PREVENTS_SWITCH_OUT_OF_RBR
+SET SESSION binlog_format = STATEMENT;
+SELECT @@SESSION.binlog_format;
+
+SET SESSION binlog_format = ROW;
+SELECT @@SESSION.binlog_format;
+
+INSERT INTO t1 VALUES ('row based');
+--echo # Test allow switching @@SESSION.binlog_format from ROW to MIXED
+--echo # when there are open temp tables.
+SET SESSION binlog_format = MIXED;
+SELECT @@SESSION.binlog_format;
+
+INSERT INTO t1 VALUES ('row based');
+--echo # Test allow switching @@SESSION.binlog_format from MIXED to ROW
+--echo # when there are open temp tables.
+SET SESSION binlog_format = ROW;
+SELECT @@SESSION.binlog_format;
+
+--echo # Test allow switching @@SESSION.binlog_format from ROW to ROW
+--echo # when there are open temp tables.
+SET SESSION binlog_format = ROW;
+SELECT @@SESSION.binlog_format;
+
+INSERT INTO t1 VALUES ('row based');
+--echo # Test forbit switching @@SESSION.binlog_format from ROW to STATEMENT
+--echo # when there are open temp tables.
+--ERROR ER_TEMP_TABLE_PREVENTS_SWITCH_OUT_OF_RBR
+SET SESSION binlog_format = STATEMENT;
+SELECT @@SESSION.binlog_format;
+
+DROP TEMPORARY TABLE t2;
+DROP TABLE t1;
+
diff --git a/mysql-test/suite/binlog/t/binlog_grant.test b/mysql-test/suite/binlog/t/binlog_grant.test
new file mode 100644
index 00000000..d573281f
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_grant.test
@@ -0,0 +1,216 @@
+# Test grants for various objects (especially variables) related to
+# the binary log
+
+source include/have_log_bin.inc;
+
+connection default;
+--disable_warnings
+reset master;
+--enable_warnings
+
+set @saved_binlog_format = @@global.binlog_format;
+create user mysqltest_1@localhost;
+GRANT SELECT on test.* to mysqltest_1@localhost;
+show grants for mysqltest_1@localhost;
+
+connect (plain,localhost,mysqltest_1,,test);
+connect (root,localhost,root,,test);
+
+# Testing setting session SQL_LOG_BIN variable both as
+# root and as plain user.
+
+--echo **** Variable SQL_LOG_BIN ****
+
+connection root;
+--echo [root]
+set session sql_log_bin = 1;
+
+connection plain;
+--echo [plain]
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
+set session sql_log_bin = 1;
+
+
+# Testing setting both session and global BINLOG_FORMAT variable both
+# as root and as plain user.
+
+--echo **** Variable BINLOG_FORMAT ****
+
+connection root;
+--echo [root]
+set global binlog_format = row;
+set session binlog_format = row;
+
+connection plain;
+--echo [plain]
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
+set global binlog_format = row;
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
+set session binlog_format = row;
+
+--echo **** Clean up ****
+disconnect plain;
+disconnect root;
+
+connection default;
+set global binlog_format = @saved_binlog_format;
+drop user mysqltest_1@localhost;
+
+
+# Testing if REPLICATION CLIENT privilege is enough to execute
+# SHOW MASTER LOGS and SHOW BINARY.
+CREATE USER 'mysqltest_1'@'localhost';
+GRANT REPLICATION CLIENT ON *.* TO 'mysqltest_1'@'localhost';
+--connect(rpl,localhost,mysqltest_1,,"*NO-ONE*")
+
+--connection rpl
+# We are only interested if the following commands succeed and not on
+# their output.
+--disable_result_log
+SHOW MASTER LOGS;
+SHOW BINARY LOGS;
+SHOW BINLOG STATUS;
+--enable_result_log
+
+# clean up
+--disconnect rpl
+connection default;
+DROP USER 'mysqltest_1'@'localhost';
+
+
+--echo #
+--echo # Start of 10.5 test
+--echo #
+
+--echo #
+--echo # MDEV-21743 Split up SUPER privilege to smaller privileges
+--echo #
+
+--echo # Test that REPLICATION CLIENT is an alias for BINLOG MONITOR
+
+CREATE USER user1@localhost;
+GRANT REPLICATION CLIENT ON *.* TO user1@localhost;
+SHOW GRANTS FOR user1@localhost;
+REVOKE REPLICATION CLIENT ON *.* FROM user1@localhost;
+SHOW GRANTS FOR user1@localhost;
+DROP USER user1@localhost;
+
+
+--echo # Test if SHOW BINARY LOGS and SHOW BINGLOG STATUS are not allowed without REPLICATION CLIENT or SUPER
+CREATE USER user1@localhost;
+GRANT ALL PRIVILEGES ON *.* TO user1@localhost;
+REVOKE REPLICATION CLIENT, SUPER ON *.* FROM user1@localhost;
+--connect(user1,localhost,user1,,)
+--connection user1
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
+SHOW MASTER LOGS;
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
+SHOW BINARY LOGS;
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
+SHOW BINLOG STATUS;
+--disconnect user1
+--connection default
+DROP USER user1@localhost;
+
+
+--echo # Test if PURGE BINARY LOGS is not allowed without BINLOG ADMIN or SUPER
+CREATE USER user1@localhost;
+GRANT ALL PRIVILEGES ON *.* TO user1@localhost;
+REVOKE BINLOG ADMIN, SUPER ON *.* FROM user1@localhost;
+--connect(user1,localhost,user1,,)
+--connection user1
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
+PURGE BINARY LOGS BEFORE '2001-01-01 00:00:00';
+--disconnect user1
+--connection default
+DROP USER user1@localhost;
+
+
+--echo # Test if PURGE BINLOG is allowed with BINLOG ADMIN
+CREATE USER user1@localhost;
+GRANT BINLOG ADMIN ON *.* TO user1@localhost;
+--connect(user1,localhost,user1,,"*NO-ONE*")
+--connection user1
+PURGE BINARY LOGS BEFORE '2001-01-01 00:00:00';
+--disconnect user1
+connection default;
+DROP USER user1@localhost;
+
+
+--echo # Test if PURGE BINLOG is allowed with SUPER
+CREATE USER user1@localhost;
+GRANT SUPER ON *.* TO user1@localhost;
+--connect(user1,localhost,user1,,"*NO-ONE*")
+--connection user1
+PURGE BINARY LOGS BEFORE '2001-01-01 00:00:00';
+--disconnect user1
+connection default;
+DROP USER user1@localhost;
+
+
+--echo # Test if SHOW BINLOG EVENTS is not allowed without BINLOG MONITOR
+CREATE USER user1@localhost;
+GRANT ALL PRIVILEGES ON *.* TO user1@localhost;
+REVOKE BINLOG MONITOR ON *.* FROM user1@localhost;
+--connect(user1,localhost,user1,,)
+--connection user1
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
+SHOW BINLOG EVENTS;
+--disconnect user1
+--connection default
+DROP USER user1@localhost;
+
+
+--echo # Test if SHOW BINLOG EVENTS is allowed with BINLOG MONITOR
+CREATE USER user1@localhost;
+GRANT BINLOG MONITOR ON *.* TO user1@localhost;
+--connect(user1,localhost,user1,,"*NO-ONE*")
+--connection user1
+--disable_result_log
+SHOW BINLOG EVENTS;
+--enable_result_log
+--disconnect user1
+connection default;
+DROP USER user1@localhost;
+
+--echo #
+--echo # MDEV-21975 Add BINLOG REPLAY privilege and bind new privileges to
+--echo # gtid_seq_no, preudo_thread_id, server_id, gtid_domain_id
+--echo #
+--echo # Test combinations of BINLOG REPLAY guarded features which typically
+--echo # arise in mysqlbinlog output replay on server.
+--echo #
+
+CREATE USER user1@localhost;
+GRANT BINLOG REPLAY ON *.* TO user1@localhost;
+GRANT ALL ON test.* TO user1@localhost;
+RESET MASTER;
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (1),(2),(3);
+--connect(user1,localhost,user1,,)
+# Genuine mysqlbinlog output
+--exec $MYSQL_BINLOG --read-from-remote-server --user=root --host=127.0.0.1 --port=$MASTER_MYPORT master-bin.000001 > $MYSQLTEST_VARDIR/tmp/mysqlbinlog.sql
+RENAME TABLE t1 to t2;
+
+--exec $MYSQL --user=user1 test < $MYSQLTEST_VARDIR/tmp/mysqlbinlog.sql
+
+--connection default
+REVOKE BINLOG REPLAY ON *.* FROM user1@localhost;
+call mtr.add_suppression("Access denied; you need (at least one of) the SUPER, BINLOG REPLAY privilege(s) for this operation");
+--echo # Privilege errors are expected now:
+--connection user1
+--error 1
+--exec $MYSQL --user=user1 test < $MYSQLTEST_VARDIR/tmp/mysqlbinlog.sql
+
+--connection default
+--let $diff_tables=t1,t2
+--source include/diff_tables.inc
+
+--echo # Test cleanup
+--remove_file $MYSQLTEST_VARDIR/tmp/mysqlbinlog.sql
+DROP TABLE t2,t1;
+DROP USER user1@localhost;
+
+--echo #
+--echo # End of 10.5 test
+--echo #
diff --git a/mysql-test/suite/binlog/t/binlog_gtid_delete_domain_debug.test b/mysql-test/suite/binlog/t/binlog_gtid_delete_domain_debug.test
new file mode 100644
index 00000000..5de549c4
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_gtid_delete_domain_debug.test
@@ -0,0 +1,11 @@
+# Check "internal" error branches of
+# FLUSH BINARY LOGS DELETE_DOMAIN_ID = (...)
+# handler.
+--source include/have_debug.inc
+--source include/have_binlog_format_mixed.inc
+
+SET @@SESSION.debug_dbug='+d,inject_binlog_delete_domain_init_error';
+--error ER_BINLOG_CANT_DELETE_GTID_DOMAIN
+FLUSH BINARY LOGS DELETE_DOMAIN_ID = (99);
+
+SHOW WARNINGS;
diff --git a/mysql-test/suite/binlog/t/binlog_implicit_commit.test b/mysql-test/suite/binlog/t/binlog_implicit_commit.test
new file mode 100644
index 00000000..11ceae5f
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_implicit_commit.test
@@ -0,0 +1,63 @@
+# The purpose of this test is to test that setting autocommit does a
+# commit of outstanding transactions and nothing is left pending in
+# the transaction cache.
+
+source include/have_log_bin.inc;
+source include/have_innodb.inc;
+
+# We need a transactional engine, so let's use InnoDB
+CREATE TABLE t1 (id INT) ENGINE = InnoDB;
+
+# Testing SET AUTOCOMMIT
+SET BINLOG_FORMAT = STATEMENT;
+
+let $cleanup = COMMIT;
+
+let $prepare = SET AUTOCOMMIT = 0;
+let $statement = SET AUTOCOMMIT = 1;
+source include/implicit.test;
+
+let $prepare = SET AUTOCOMMIT = 1;
+let $statement = SET AUTOCOMMIT = 1;
+source include/implicit.test;
+
+let $prepare = SET AUTOCOMMIT = 0;
+let $statement = SET AUTOCOMMIT = 0;
+source include/implicit.test;
+
+let $prepare = SET AUTOCOMMIT = 1;
+let $statement = SET AUTOCOMMIT = 0;
+source include/implicit.test;
+
+SET BINLOG_FORMAT = ROW;
+let $prepare = SET AUTOCOMMIT = 0;
+let $statement = SET AUTOCOMMIT = 1;
+source include/implicit.test;
+
+let $prepare = SET AUTOCOMMIT = 1;
+let $statement = SET AUTOCOMMIT = 1;
+source include/implicit.test;
+
+let $prepare = SET AUTOCOMMIT = 0;
+let $statement = SET AUTOCOMMIT = 0;
+source include/implicit.test;
+
+let $prepare = SET AUTOCOMMIT = 1;
+let $statement = SET AUTOCOMMIT = 0;
+source include/implicit.test;
+
+RESET MASTER;
+SET AUTOCOMMIT = 0;
+INSERT INTO t1 VALUES (1);
+source include/show_binlog_events.inc;
+LOCK TABLES t1 WRITE;
+source include/show_binlog_events.inc;
+INSERT INTO t1 VALUES (2);
+source include/show_binlog_events.inc;
+UNLOCK TABLES;
+source include/show_binlog_events.inc;
+COMMIT;
+source include/show_binlog_events.inc;
+
+# Cleaning up
+DROP TABLE t1;
diff --git a/mysql-test/suite/binlog/t/binlog_incident.test b/mysql-test/suite/binlog/t/binlog_incident.test
new file mode 100644
index 00000000..de7abf20
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_incident.test
@@ -0,0 +1 @@
+--source include/binlog_incident.inc
diff --git a/mysql-test/suite/binlog/t/binlog_index-master.opt b/mysql-test/suite/binlog/t/binlog_index-master.opt
new file mode 100644
index 00000000..c3754b4d
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_index-master.opt
@@ -0,0 +1 @@
+--loose-skip-stack-trace --log-warnings=0 --log-bin=master-bin --log-bin-index=master-bin
diff --git a/mysql-test/suite/binlog/t/binlog_index.test b/mysql-test/suite/binlog/t/binlog_index.test
new file mode 100644
index 00000000..a7c4ce8f
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_index.test
@@ -0,0 +1 @@
+--source include/binlog_index.inc
diff --git a/mysql-test/suite/binlog/t/binlog_innodb.opt b/mysql-test/suite/binlog/t/binlog_innodb.opt
new file mode 100644
index 00000000..2d4e658e
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_innodb.opt
@@ -0,0 +1 @@
+--binlog_cache_size=32768 --binlog_stmt_cache_size=32768
diff --git a/mysql-test/suite/binlog/t/binlog_innodb.test b/mysql-test/suite/binlog/t/binlog_innodb.test
new file mode 100644
index 00000000..5f372e6d
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_innodb.test
@@ -0,0 +1,204 @@
+source include/have_innodb.inc;
+source include/have_log_bin.inc;
+
+SET BINLOG_FORMAT=MIXED;
+
+RESET MASTER;
+
+CREATE TABLE t1 (a INT PRIMARY KEY, b INT) ENGINE=INNODB;
+INSERT INTO t1 VALUES (1,1),(2,2),(3,3),(4,4),(5,5),(6,6);
+
+SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;
+BEGIN;
+# Should be logged as statement
+UPDATE t1 SET b = 2*a WHERE a > 1;
+COMMIT;
+
+SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
+BEGIN;
+# Should be logged as rows
+UPDATE t1 SET b = a * a WHERE a > 3;
+COMMIT;
+
+# Check that errors are generated when trying to use READ COMMITTED
+# transaction isolation level in STATEMENT binlog mode.
+
+SET BINLOG_FORMAT=STATEMENT;
+
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+BEGIN;
+error ER_BINLOG_STMT_MODE_AND_ROW_ENGINE;
+UPDATE t1 SET b = 1*a WHERE a > 1;
+COMMIT;
+
+SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
+BEGIN;
+error ER_BINLOG_STMT_MODE_AND_ROW_ENGINE;
+UPDATE t1 SET b = 2*a WHERE a > 2;
+COMMIT;
+
+SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;
+BEGIN;
+UPDATE t1 SET b = 3*a WHERE a > 3;
+COMMIT;
+
+SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE;
+BEGIN;
+UPDATE t1 SET b = 4*a WHERE a > 4;
+COMMIT;
+
+SET BINLOG_FORMAT=MIXED;
+
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+BEGIN;
+UPDATE t1 SET b = 1*a WHERE a > 1;
+COMMIT;
+
+SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
+BEGIN;
+UPDATE t1 SET b = 2*a WHERE a > 2;
+COMMIT;
+
+SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;
+BEGIN;
+UPDATE t1 SET b = 3*a WHERE a > 3;
+COMMIT;
+
+SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE;
+BEGIN;
+UPDATE t1 SET b = 4*a WHERE a > 4;
+COMMIT;
+
+SET BINLOG_FORMAT=ROW;
+
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+BEGIN;
+UPDATE t1 SET b = 1*a WHERE a > 1;
+COMMIT;
+
+SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
+BEGIN;
+UPDATE t1 SET b = 2*a WHERE a > 2;
+COMMIT;
+
+SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;
+BEGIN;
+UPDATE t1 SET b = 3*a WHERE a > 3;
+COMMIT;
+
+SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE;
+BEGIN;
+UPDATE t1 SET b = 4*a WHERE a > 4;
+COMMIT;
+
+source include/show_binlog_events.inc;
+
+DROP TABLE t1;
+
+
+#
+# Let us test binlog_cache_use and binlog_cache_disk_use status vars.
+# Actually this test has nothing to do with innodb per se, it just requires
+# transactional table.
+#
+flush status;
+show status like "binlog_cache_use";
+show status like "binlog_cache_disk_use";
+
+create table t1 (a int) engine=innodb;
+
+# Now we are going to create transaction which is long enough so its
+# transaction binlog will be flushed to disk...
+let $1=2000;
+disable_query_log;
+begin;
+while ($1)
+{
+ eval insert into t1 values( $1 );
+ dec $1;
+}
+commit;
+enable_query_log;
+show status like "binlog_cache_use";
+show status like "binlog_cache_disk_use";
+
+# Transaction which should not be flushed to disk and so should not
+# increase binlog_cache_disk_use.
+begin;
+delete from t1;
+commit;
+show status like "binlog_cache_use";
+show status like "binlog_cache_disk_use";
+drop table t1;
+
+#
+# Bug#27716 multi-update did partially and has not binlogged
+#
+
+CREATE TABLE `t1` (
+ `a` int(11) NOT NULL auto_increment,
+ `b` int(11) default NULL,
+ PRIMARY KEY (`a`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 ;
+
+CREATE TABLE `t2` (
+ `a` int(11) NOT NULL auto_increment,
+ `b` int(11) default NULL,
+ PRIMARY KEY (`a`)
+) ENGINE=INNODB DEFAULT CHARSET=latin1 ;
+
+# A. testing multi_update::send_eof() execution branch
+insert into t1 values (1,1),(2,2);
+insert into t2 values (1,1),(4,4);
+reset master;
+--error ER_DUP_ENTRY
+UPDATE t2,t1 SET t2.a=t1.a+2;
+# check
+select * from t2 /* must be (3,1), (4,4) */;
+--echo # There must no UPDATE in binlog;
+source include/show_binlog_events.inc;
+
+# B. testing multi_update::send_error() execution branch
+delete from t1;
+delete from t2;
+insert into t1 values (1,2),(3,4),(4,4);
+insert into t2 values (1,2),(3,4),(4,4);
+reset master;
+--error ER_DUP_ENTRY
+UPDATE t2,t1 SET t2.a=t2.b where t2.a=t1.a;
+--echo # There must be no UPDATE query event;
+source include/show_binlog_events.inc;
+
+# cleanup bug#27716
+drop table t1, t2;
+
+--echo *** MDEV-11937: InnoDB flushes redo log too often ***
+
+# Count number of log fsyncs reported by InnoDB per commit.
+CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=InnoDB;
+
+SET @old_flush = @@GLOBAL.innodb_flush_log_at_trx_commit;
+SET GLOBAL innodb_flush_log_at_trx_commit=1;
+
+--let $syncs1 = query_get_value(SHOW STATUS LIKE 'Innodb_data_fsyncs', Value, 1)
+--let $ROWS = 100
+--disable_query_log
+let $count = $ROWS;
+while ($count) {
+ eval INSERT INTO t1 VALUES ($count);
+ dec $count;
+}
+--let $syncs2 = query_get_value(SHOW STATUS LIKE 'Innodb_data_fsyncs', Value, 1)
+eval SET @num_sync = $syncs2 - $syncs1;
+--enable_query_log
+
+# Allow a bit of slack, in case some background process or something
+# is introducing a few more syncs.
+eval SELECT IF(@num_sync < $ROWS*1.5, "OK",
+ CONCAT("ERROR: More than 1 fsync per commit (saw ", @num_sync/$ROWS, ")")) AS status;
+
+DROP TABLE t1;
+SET GLOBAL innodb_flush_log_at_trx_commit=@old_flush;
+
+
+--echo End of tests
diff --git a/mysql-test/suite/binlog/t/binlog_innodb_row.test b/mysql-test/suite/binlog/t/binlog_innodb_row.test
new file mode 100644
index 00000000..f4ad1058
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_innodb_row.test
@@ -0,0 +1,105 @@
+#
+# Tests of innodb/binlog with the row binlog format
+#
+source include/have_innodb.inc;
+source include/have_log_bin.inc;
+source include/have_binlog_format_row.inc;
+
+#
+# Bug #40221 Replication failure on RBR + UPDATE the primary key
+#
+
+CREATE TABLE t1 (i int unique) ENGINE=innodb;
+reset master;
+
+# part 1: update can cause the dup key
+
+begin;
+insert into t1 values (1),(2);
+--echo *** the following UPDATE query wont generate any updates for the binlog ***
+--error ER_DUP_ENTRY
+update t1 set i = 3 where i < 3;
+commit;
+
+--echo *** Results of the test: the binlog must have only Write_rows events not any Update_rows ***
+source include/show_binlog_events.inc;
+
+# part 2: insert can cause the dup key
+
+delete from t1;
+reset master;
+
+begin;
+insert into t1 values (1),(2);
+--echo *** the following UPDATE query wont generate any updates for the binlog ***
+--error ER_DUP_ENTRY
+insert into t1 values (3),(4),(1),(2);
+commit;
+
+--echo *** Results of the test: the binlog must have only one Write_rows event not two ***
+source include/show_binlog_events.inc;
+
+drop table t1;
+
+#
+# BUG#51251
+#
+# The test case checks if truncating a temporary table created with
+# engine InnoDB will not cause the truncate statement to be binlogged.
+
+# Before patch for BUG#51251, the TRUNCATE statements below would be
+# binlogged, which would cause the slave to fail with "table does not
+# exist".
+
+RESET MASTER;
+
+CREATE TABLE t1 ( c1 int , primary key (c1)) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1), (2), (3);
+CREATE TEMPORARY TABLE IF NOT EXISTS t2 LIKE t1;
+TRUNCATE TABLE t2;
+DROP TABLE t1;
+
+-- echo ###############################################
+-- echo ### assertion: No event for 'TRUNCATE TABLE t2'
+-- echo ###############################################
+-- source include/show_binlog_events.inc
+-- echo ###############################################
+
+RESET MASTER;
+
+CREATE TEMPORARY TABLE t1 (c1 int) Engine=InnoDB;
+INSERT INTO t1 VALUES (1), (2), (3);
+TRUNCATE t1;
+DROP TEMPORARY TABLE t1;
+
+-- echo ###############################################
+-- echo ### assertion: No event for 'TRUNCATE TABLE t1'
+-- echo ###############################################
+-- source include/show_binlog_events.inc
+-- echo ###############################################
+
+
+--echo #
+--echo # Bug#12346411 SQL/LOG.CC:6509: ASSERTION `PREPARED_XIDS > 0' FAILED
+--echo #
+
+--disable_warnings
+DROP TABLE IF EXISTS t1, t2;
+--enable_warnings
+
+CREATE TABLE t1(a INT PRIMARY KEY) engine=innodb;
+CREATE TABLE t2(a INT) engine=myisam;
+
+INSERT INTO t1 VALUES (1);
+START TRANSACTION;
+INSERT INTO t2 VALUES (1);
+INSERT IGNORE INTO t1 VALUES (1);
+COMMIT;
+
+INSERT INTO t1 VALUES (2);
+START TRANSACTION;
+INSERT INTO t2 VALUES (2);
+UPDATE IGNORE t1 SET a=1 WHERE a=2;
+COMMIT;
+
+DROP TABLE t1, t2;
diff --git a/mysql-test/suite/binlog/t/binlog_innodb_stm.test b/mysql-test/suite/binlog/t/binlog_innodb_stm.test
new file mode 100644
index 00000000..4dfa7a76
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_innodb_stm.test
@@ -0,0 +1,26 @@
+source include/have_innodb.inc;
+source include/have_binlog_format_statement.inc;
+
+#
+# MDEV-18466 Unsafe to log updates on tables referenced by foreign keys with triggers in statement format
+#
+
+create table categories(
+ cat_id int not null primary key,
+ cat_name varchar(255) not null,
+ cat_description text
+) engine=innodb;
+
+create table products(
+ prd_id int not null auto_increment primary key,
+ prd_name varchar(355) not null,
+ prd_price decimal,
+ cat_id int not null,
+ foreign key fk_cat(cat_id)
+ references categories(cat_id)
+ on update cascade
+) engine=innodb;
+
+insert into categories values (1, 'drinks', 'drinks');
+update categories set cat_description=2 where cat_id=1;
+drop table products, categories;
diff --git a/mysql-test/suite/binlog/t/binlog_invalid_read_in_rotate.combinations b/mysql-test/suite/binlog/t/binlog_invalid_read_in_rotate.combinations
new file mode 100644
index 00000000..72076e12
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_invalid_read_in_rotate.combinations
@@ -0,0 +1,5 @@
+[enable_checksum]
+binlog_checksum=1
+
+[disable_checksum]
+binlog_checksum=0
diff --git a/mysql-test/suite/binlog/t/binlog_invalid_read_in_rotate.test b/mysql-test/suite/binlog/t/binlog_invalid_read_in_rotate.test
new file mode 100644
index 00000000..36bb56c8
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_invalid_read_in_rotate.test
@@ -0,0 +1,48 @@
+# ==== Purpose ====
+#
+# Test verifies that reading binary log by using "SHOW BINLOG EVENTS" command
+# from various random positions doesn't lead to crash. It should exit
+# gracefully with appropriate error.
+#
+# ==== References ====
+#
+# MDEV-18046:Assortment of crashes, assertion failures and ASAN errors in mysql_show_binlog_events
+
+--source include/have_log_bin.inc
+--source include/have_innodb.inc
+
+RESET MASTER;
+
+call mtr.add_suppression("Error in Log_event::read_log_event*");
+call mtr.add_suppression("Replication event checksum verification failed while reading from a log file*");
+
+DROP TABLE /*! IF EXISTS*/ t1;
+CREATE TABLE `t1` (
+`col_int` int,
+pk integer auto_increment,
+`col_char_12_key` char(12),
+`col_int_key` int,
+`col_char_12` char(12),
+primary key (pk),
+key (`col_char_12_key` ),
+key (`col_int_key` )) ENGINE=InnoDB;
+
+INSERT /*! IGNORE */ INTO t1 VALUES (183173120, NULL, 'abcd', 1, 'efghijk'), (1, NULL, 'lmno', 2, 'p');
+
+--disable_warnings
+ALTER TABLE `t1` ENABLE KEYS;
+--enable_warnings
+
+--let $max_pos= query_get_value(SHOW MASTER STATUS,Position,1)
+--let $pos= 1
+while ($pos <= $max_pos)
+{
+ --disable_query_log
+ --disable_result_log
+ --error 0,1220
+ eval SHOW BINLOG EVENTS FROM $pos;
+ --inc $pos
+ --enable_result_log
+ --enable_query_log
+}
+DROP TABLE t1;
diff --git a/mysql-test/suite/binlog/t/binlog_ioerr.test b/mysql-test/suite/binlog/t/binlog_ioerr.test
new file mode 100644
index 00000000..e75adb19
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_ioerr.test
@@ -0,0 +1 @@
+--source include/binlog_ioerr.inc
diff --git a/mysql-test/suite/binlog/t/binlog_killed.test b/mysql-test/suite/binlog/t/binlog_killed.test
new file mode 100644
index 00000000..7c3a262d
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_killed.test
@@ -0,0 +1,457 @@
+-- source include/have_innodb.inc
+-- source include/have_binlog_format_statement.inc
+-- source include/binlog_start_pos.inc
+
+call mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT");
+
+# You cannot use `KILL' with the Embedded MySQL Server library,
+# because the embedded server merely runs inside the threads of the host
+# application. -- the docs
+
+-- source include/not_embedded.inc
+
+#
+# Avoid printing binlog checkpoints
+#
+
+--let $skip_checkpoint_events=1
+
+
+###
+### bug#22725 : incorrect killed error in binlogged query
+###
+
+connect (con1, localhost, root,,);
+connect (con2, localhost, root,,);
+
+create table t1 (a int auto_increment, b int, PRIMARY KEY (a)) ENGINE=InnoDB;
+create table t2 (a int auto_increment, b int, PRIMARY KEY (a)) ENGINE=MyISAM;
+create table t3 (a int auto_increment, b int, PRIMARY KEY (a)) ENGINE=InnoDB;
+
+#
+# effective test for bug#22725
+#
+
+connection con1;
+select get_lock("a", 20);
+
+connection con2;
+let $ID= `select connection_id()`;
+
+#
+# reset master does not reset binlogging on the embedded server.
+# the test is not run on the embedded for reason of using KILL query.
+# `reset master' problem is to be addressed by bug#15580 fixes.
+#
+reset master;
+send insert into t2 values (null, null), (null, get_lock("a", 10));
+
+
+connection con1;
+
+--disable_abort_on_error
+--disable_warnings
+
+let $wait_condition=
+ select count(*) = 1 from information_schema.processlist
+ where info like "%insert into t2 values%" and state like 'User lock';
+--source include/wait_condition.inc
+
+--replace_regex /[0-9]+/ID/
+eval kill query $ID;
+
+connection con2;
+--error 0,ER_QUERY_INTERRUPTED
+reap;
+let $rows= `select count(*) from t2 /* must be 2 or 0 */`;
+
+let $MYSQLD_DATADIR= `select @@datadir`;
+--let $binlog_killed_pos=query_get_value(SHOW BINLOG EVENTS, Pos, 6)
+--let $binlog_killed_end_log_pos=query_get_value(SHOW BINLOG EVENTS, End_log_pos, 6)
+--exec $MYSQL_BINLOG --force-if-open --start-position=$binlog_killed_pos --stop-position=$binlog_killed_end_log_pos $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/kill_query_calling_sp.binlog
+--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
+--disable_result_log
+eval select
+(@a:=load_file("$MYSQLTEST_VARDIR/tmp/kill_query_calling_sp.binlog"))
+is not null;
+--enable_result_log
+--replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR
+let $error_code= `select @a like "%#%error_code=0%" /* must return 1 or 0*/`;
+let $insert_binlogged= `select @a like "%insert into%" /* must return 1 or 0 */`;
+eval set @result= $rows - $error_code - $insert_binlogged;
+
+--enable_warnings
+--enable_abort_on_error
+
+select @result /* must be zero either way */;
+
+
+--remove_file $MYSQLTEST_VARDIR/tmp/kill_query_calling_sp.binlog
+connection con1;
+select RELEASE_LOCK("a");
+
+#
+# bug#27571 asynchronous setting mysql_`query`::error and Query_log_e::error_code
+#
+
+# checking that killing inside of select loops is safe as before
+# killing after the loop can be only simulated - another test
+
+delete from t1;
+delete from t2;
+insert into t1 values (1,1),(2,2);
+
+#
+# simple update
+#
+connection con1;
+begin; update t1 set b=11 where a=2;
+
+connection con2;
+let $ID= `select connection_id()`;
+begin;
+send update t1 set b=b+10;
+
+connection con1;
+--replace_result $ID ID
+eval kill query $ID;
+rollback;
+
+# Bug #32148 killi query may be ineffective
+# forced to comment out the test's outcome
+# and mask out ineffective ER_QUERY_INTERRUPTED
+# todo1: revert back upon fixing bug#32148
+# todo2: the tests need refining in that
+# killing should wait till the victim requested
+# its lock (wait_condition available in 5.1 tests)
+
+connection con2;
+--error 0,ER_QUERY_INTERRUPTED
+reap;
+rollback;
+select * from t1 order by a /* must be the same as before (1,1),(2,2) */;
+
+#
+# multi update
+# commented out as Bug #31807 multi-update,delete killing does not report with ER_QUERY_INTERRUPTED
+# in the way
+#
+# connection con1;
+# begin; update t1 set b=b+10;
+
+# connection con2;
+# send update t1 as t_1,t1 as t_2 set t_1.b=11 where t_2.a=2;
+
+# connection con1;
+# --replace_result $ID ID
+# eval kill query $ID;
+# rollback;
+
+# disable_abort_on_error;
+
+# connection con2;
+# --error HY000,ER_QUERY_INTERRUPTED
+# reap;
+# select * from t1 /* must be the same as before (1,1),(2,2) */;
+
+# enable_abort_on_error;
+#
+# simple delete
+#
+connection con1;
+begin; delete from t1 where a=2;
+
+connection con2;
+let $ID= `select connection_id()`;
+begin;
+send delete from t1 where a=2;
+
+connection con1;
+--replace_result $ID ID
+eval kill query $ID;
+rollback;
+
+connection con2;
+--error 0,ER_QUERY_INTERRUPTED
+reap;
+rollback;
+# todo1,2 above
+select * from t1 order by a /* must be the same as before (1,1),(2,2) */;
+
+
+#
+# multi delete
+# the same as for multi-update
+#
+# connection con1;
+# begin; delete from t1 where a=2;
+
+# connection con2;
+# send delete t1 from t1 where t1.a=2;
+
+# connection con1;
+# --replace_result $ID ID
+# eval kill query $ID;
+# rollback;
+
+# connection con2;
+# --error 0,ER_QUERY_INTERRUPTED
+# reap;
+# select * from t1 /* must be the same as before (1,1),(2,2) */;
+#
+# insert select
+#
+connection con1;
+--disable_warnings
+drop table if exists t4;
+--enable_warnings
+create table t4 (a int, b int) engine=innodb;
+insert into t4 values (3, 3);
+begin; insert into t1 values (3, 3);
+
+connection con2;
+let $ID= `select connection_id()`;
+begin;
+send insert into t1 select * from t4 for update;
+
+connection con1;
+--replace_result $ID ID
+eval kill query $ID;
+rollback;
+
+connection con2;
+--error 0,ER_QUERY_INTERRUPTED,ER_LOCK_WAIT_TIMEOUT
+reap;
+# todo 1,2 above
+rollback;
+select * from t1 /* must be the same as before (1,1),(2,2) */;
+
+drop table t4; # cleanup for the sub-case
+
+###
+## non-ta table case: killing must be recorded in binlog
+###
+create table t4 (a int, b int) ENGINE=MyISAM /* for killing update and delete */;
+
+delimiter |;
+create function bug27563(n int)
+RETURNS int(11)
+NOT DETERMINISTIC
+begin
+ if @b > 0 then
+ select get_lock("a", 20) into @a;
+ else
+ set @b= 1;
+ end if;
+ return n;
+end|
+delimiter ;|
+
+#
+# update
+#
+
+delete from t4;
+insert into t4 values (1,1), (1,1);
+reset master;
+connection con1;
+select get_lock("a", 20);
+
+connection con2;
+let $ID= `select connection_id()`;
+set @b= 0;
+send update t4 set b=b + bug27563(b);
+
+connection con1;
+let $wait_condition= select count(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST where state='User lock';
+source include/wait_condition.inc;
+select count(*) FROM INFORMATION_SCHEMA.PROCESSLIST where state='User lock';
+
+--replace_result $ID ID
+eval kill query $ID;
+
+connection con2;
+--error ER_QUERY_INTERRUPTED
+reap;
+select * from t4 order by b /* must be (1,1), (1,2) */;
+select @b /* must be 1 at the end of a stmt calling bug27563() */;
+--echo must have the update query event on the 4th line
+source include/show_binlog_events.inc;
+--let $binlog_killed_pos= query_get_value(SHOW BINLOG EVENTS, Pos, 5)
+--let $binlog_killed_end_log_pos= query_get_value(SHOW BINLOG EVENTS, End_log_pos, 5)
+
+--echo *** a proof the query is binlogged with an error ***
+
+--exec $MYSQL_BINLOG --force-if-open --start-position=$binlog_killed_pos --stop-position=$binlog_killed_end_log_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"))
+is not null;
+--replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR
+let $error_code= `select @a like "%#%error_code=0%" /* must return 0*/`;
+eval select $error_code /* must return 0 to mean the killed update is in */;
+
+# cleanup for the sub-case
+connection con1;
+select RELEASE_LOCK("a");
+--remove_file $MYSQLTEST_VARDIR/tmp/binlog_killed_bug27571.binlog
+
+#
+# delete
+#
+
+delete from t4;
+insert into t4 values (1,1), (2,2);
+reset master;
+connection con1;
+select get_lock("a", 20);
+
+connection con2;
+let $ID= `select connection_id()`;
+set @b= 0;
+send delete from t4 where b=bug27563(1) or b=bug27563(2);
+
+connection con1;
+let $wait_condition= select count(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST where state='User lock';
+source include/wait_condition.inc;
+select count(*) FROM INFORMATION_SCHEMA.PROCESSLIST where state='User lock';
+--replace_result $ID ID
+eval kill query $ID;
+
+connection con2;
+--error ER_QUERY_INTERRUPTED
+reap;
+select count(*) from t4 /* must be 1 */;
+select @b /* must be 1 at the end of a stmt calling bug27563() */;
+--echo must have the delete query event on the 4th line
+source include/show_binlog_events.inc;
+--let $binlog_killed_pos= query_get_value(SHOW BINLOG EVENTS, Pos, 5)
+--let $binlog_killed_end_log_pos= query_get_value(SHOW BINLOG EVENTS, End_log_pos, 5)
+
+# a proof the query is binlogged with an error
+
+--exec $MYSQL_BINLOG --force-if-open --start-position=$binlog_killed_pos --stop-position=$binlog_killed_end_log_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"))
+is not null;
+--replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR
+let $error_code= `select @a like "%#%error_code=0%" /* must return 0*/`;
+eval select $error_code /* must return 0 to mean the killed delete is in */;
+
+# cleanup for the sub-case
+connection con1;
+select RELEASE_LOCK("a");
+--remove_file $MYSQLTEST_VARDIR/tmp/binlog_killed_bug27571.binlog
+
+drop table t4;
+
+#
+# load data - see simulation tests
+#
+
+
+# bug#27571 cleanup
+
+drop function bug27563;
+
+
+# Prove that killing connection in the middle
+# of mixed engine transactions affect binlogging
+# as specified.
+
+# keep binlogging for this piece of test in a new file
+FLUSH LOGS;
+
+# Connection con3 as transaction generator thoughout the test
+connect (con3, localhost, root,,);
+
+connection con3;
+let $ID= `select connection_id()`;
+
+--let $threads_connected=`select variable_value from information_schema.global_status where variable_name="threads_connected"`
+--let wait_condition=select variable_value < $threads_connected from information_schema.global_status where variable_name="threads_connected"
+
+--echo MI: MyISAM, INNODB
+BEGIN;
+INSERT INTO t2 VALUES (NULL, 1);
+INSERT INTO t1 VALUES (NULL, 2);
+
+#Connection con1 as killer throughout the test
+connection con1;
+--replace_result $ID ID
+--eval KILL $ID
+let $binlog_file= query_get_value(SHOW MASTER STATUS, File, 1);
+--source include/wait_condition.inc
+--let $binlog_start= 4
+--source include/show_binlog_events.inc
+--let $binlog_killed_pos=query_get_value(SHOW MASTER STATUS, Position, 1)
+
+disconnect con3;
+connect (con3, localhost, root,,);
+connection con3;
+let $ID= `select connection_id()`;
+
+--echo IM: INNODB, MyISAM
+BEGIN;
+INSERT INTO t1 VALUES (NULL, 3);
+INSERT INTO t2 VALUES (NULL, 4);
+
+connection con1;
+--replace_result $ID ID
+--eval KILL $ID
+--source include/wait_condition.inc
+--let $binlog_start= $binlog_killed_pos
+--source include/show_binlog_events.inc
+--let $binlog_killed_pos=query_get_value(SHOW MASTER STATUS, Position, 1)
+
+disconnect con3;
+connect (con3, localhost, root,,);
+connection con3;
+let $ID= `select connection_id()`;
+
+--echo IMI: INNODB, MyISAM, INNODB
+BEGIN;
+INSERT INTO t1 VALUES (NULL, 5);
+INSERT INTO t2 VALUES (NULL, 6);
+INSERT INTO t1 VALUES (NULL, 7);
+
+connection con1;
+--replace_result $ID ID
+--eval KILL $ID
+--source include/wait_condition.inc
+--let $binlog_start= $binlog_killed_pos
+--source include/show_binlog_events.inc
+--let $binlog_killed_pos=query_get_value(SHOW MASTER STATUS, Position, 1)
+
+disconnect con3;
+connect (con3, localhost, root,,);
+connection con3;
+let $ID= `select connection_id()`;
+
+--echo MI2: MyISAM, INNODB, MyISAM, INNODB
+BEGIN;
+INSERT INTO t2 VALUES (NULL, 8);
+INSERT INTO t1 VALUES (NULL, 9);
+INSERT INTO t2 VALUES (NULL, 10);
+INSERT INTO t1 VALUES (NULL, 11);
+
+connection con1;
+--replace_result $ID ID
+--eval KILL $ID
+--source include/wait_condition.inc
+--let $binlog_start= $binlog_killed_pos
+--source include/show_binlog_events.inc
+
+
+#
+# common cleanup
+#
+
+connection default;
+disconnect con1;
+disconnect con2;
+
+drop table t1,t2,t3;
+
+--echo end of the tests
diff --git a/mysql-test/suite/binlog/t/binlog_killed_simulate-master.opt b/mysql-test/suite/binlog/t/binlog_killed_simulate-master.opt
new file mode 100644
index 00000000..90c70ece
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_killed_simulate-master.opt
@@ -0,0 +1 @@
+--loose-debug=d,simulate_kill_bug27571
diff --git a/mysql-test/suite/binlog/t/binlog_killed_simulate.test b/mysql-test/suite/binlog/t/binlog_killed_simulate.test
new file mode 100644
index 00000000..20f51721
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_killed_simulate.test
@@ -0,0 +1,61 @@
+-- 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
+#
+
+#
+# Checking that killing upon successful row-loop does not affect binlogging
+#
+
+create table t1 (a int) engine=MyISAM;
+insert into t1 set a=1;
+reset master;
+
+update t1 set a=2 /* will be "killed" after work has been done */;
+
+# a proof the query is binlogged with no error
+let datadir= `select @@datadir`;
+--exec $MYSQL_BINLOG --force-if-open --start-position=$binlog_start_pos $datadir/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/binlog_killed_bug27571.binlog
+--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
+eval set @a:=load_file("$MYSQLTEST_VARDIR/tmp/binlog_killed_bug27571.binlog");
+--replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR
+select @a like '%#%error_code=0%' /* must return 1 as query completed before got killed*/;
+
+# cleanup for the sub-case
+remove_file $MYSQLTEST_VARDIR/tmp/binlog_killed_bug27571.binlog;
+
+#
+# Checking that killing inside of row-loop for LOAD DATA into
+# non-transactional table affects binlogging
+#
+
+create table t2 (a int, b int) ENGINE=MyISAM;
+reset master;
+--error ER_QUERY_INTERRUPTED
+load data infile '../../std_data/rpl_loaddata.dat' into table t2 /* will be "killed" in the middle */;
+
+# a proof the query is binlogged with an error
+--let binlog_load_data= query_get_value(SHOW BINLOG EVENTS, Pos, 5)
+--let binlog_end= query_get_value(SHOW BINLOG EVENTS, Pos, 6)
+source include/show_binlog_events.inc;
+
+--mkdir $MYSQLTEST_VARDIR/tmp/binlog_killed_bug27571
+--exec $MYSQL_BINLOG --local-load=$MYSQLTEST_VARDIR/tmp/binlog_killed_bug27571 --force-if-open --start-position=$binlog_load_data --stop-position=$binlog_end $datadir/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/binlog_killed_bug27571.binlog
+
+--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
+eval set @a:=load_file("$MYSQLTEST_VARDIR/tmp/binlog_killed_bug27571.binlog");
+--replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR
+select @a like '%#%error_code=0%' /* must return 0 to mean the killed query is in */;
+
+# cleanup for the sub-case
+remove_file $MYSQLTEST_VARDIR/tmp/binlog_killed_bug27571.binlog;
+
+--remove_files_wildcard $MYSQLTEST_VARDIR/tmp/binlog_killed_bug27571 *
+--rmdir $MYSQLTEST_VARDIR/tmp/binlog_killed_bug27571
+
+drop table t1,t2;
+
+--echo end of the tests
diff --git a/mysql-test/suite/binlog/t/binlog_max_binlog_stmt_cache_size.opt b/mysql-test/suite/binlog/t/binlog_max_binlog_stmt_cache_size.opt
new file mode 100644
index 00000000..c52ef14d
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_max_binlog_stmt_cache_size.opt
@@ -0,0 +1 @@
+--max_binlog_stmt_cache_size=18446744073709547520
diff --git a/mysql-test/suite/binlog/t/binlog_max_binlog_stmt_cache_size.test b/mysql-test/suite/binlog/t/binlog_max_binlog_stmt_cache_size.test
new file mode 100644
index 00000000..ca3f45c1
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_max_binlog_stmt_cache_size.test
@@ -0,0 +1,36 @@
+
+--echo #
+--echo # MDEV-4774: Strangeness with max_binlog_stmt_cache_size Settings
+--echo #
+
+CALL mtr.add_suppression("unsigned value 18446744073709547520 adjusted to 4294963200");
+
+--replace_result 18446744073709547520 MAX_BINLOG_STMT_CACHE_SIZE 4294963200 MAX_BINLOG_STMT_CACHE_SIZE
+SELECT @@global.max_binlog_stmt_cache_size;
+
+# Save the initial value of @@global.max_binlog_stmt_cache_size.
+--replace_result 18446744073709547520 MAX_BINLOG_STMT_CACHE_SIZE 4294963200 MAX_BINLOG_STMT_CACHE_SIZE
+SET @cache_size= @@max_binlog_stmt_cache_size;
+
+--disable_warnings
+SET @@global.max_binlog_stmt_cache_size= @cache_size+1;
+--enable_warnings
+--replace_result 18446744073709547520 MAX_BINLOG_STMT_CACHE_SIZE 4294963200 MAX_BINLOG_STMT_CACHE_SIZE
+SELECT @@global.max_binlog_stmt_cache_size;
+
+--disable_warnings
+SET @@global.max_binlog_stmt_cache_size = @cache_size+4095;
+--enable_warnings
+--replace_result 4294963200 MAX_BINLOG_STMT_CACHE_SIZE 18446744073709547520 MAX_BINLOG_STMT_CACHE_SIZE
+SELECT @@global.max_binlog_stmt_cache_size;
+
+--disable_warnings
+SET @@global.max_binlog_stmt_cache_size= @cache_size-1;
+--enable_warnings
+SELECT @@global.max_binlog_stmt_cache_size = @cache_size-4096;
+
+# Restore @@global.max_binlog_stmt_cache_size to its initial value.
+SET @@global.max_binlog_stmt_cache_size= @cache_size;
+
+--echo # End of test
+
diff --git a/mysql-test/suite/binlog/t/binlog_max_extension.test b/mysql-test/suite/binlog/t/binlog_max_extension.test
new file mode 100644
index 00000000..81e35744
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_max_extension.test
@@ -0,0 +1,87 @@
+# BUG#40611: MySQL cannot make a binary log after sequential number beyond
+# unsigned long.
+#
+# Problem statement
+# =================
+#
+# Extension for log file names might be created with negative
+# numbers (when counter used would wrap around), causing server
+# failure when incrementing -00001 (reaching number 000000
+# extension).
+#
+# Test
+# ====
+# This tests aims at testing the a patch that removes negatives
+# numbers from log name extensions and checks that the server
+# reports gracefully that the limit has been reached.
+#
+# It instruments index file to point to a log file close to
+# the new maximum and calls flush logs to get warning.
+#
+
+call mtr.add_suppression("Next log extension: 2147483647. Remaining log filename extensions: 0.");
+call mtr.add_suppression("Log filename extension number exhausted:");
+call mtr.add_suppression("Can't generate a unique log-filename");
+
+
+-- source include/have_log_bin.inc
+RESET MASTER;
+
+-- let $MYSQLD_DATADIR= `select @@datadir`
+-- let $log_bin_index=`select substring_index(@@log_bin_index,'/',-1)`
+-- let $log_bin_basename=`select substring_index(@@log_bin_basename,'/',-1)`
+
+###############################################
+# check hitting maximum file name extension:
+###############################################
+
+##########
+# Prepare
+##########
+
+# 1. Stop master server
+-- exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
+-- shutdown_server
+-- source include/wait_until_disconnected.inc
+
+# 2. Prepare log and index file
+-- copy_file $MYSQLD_DATADIR/$log_bin_index $MYSQLD_DATADIR/$log_bin_index.orig
+-- copy_file $MYSQLD_DATADIR/$log_bin_basename.000001 $MYSQLD_DATADIR/$log_bin_basename.2147483646
+-- append_file $MYSQLD_DATADIR/$log_bin_index
+master-bin.2147483646
+EOF
+
+# 3. Restart the server
+-- exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
+-- enable_reconnect
+-- source include/wait_until_connected_again.inc
+
+###########
+# Assertion
+###########
+
+# assertion: should raise error
+-- error ER_NO_UNIQUE_LOGFILE
+FLUSH LOGS;
+
+##############
+# Clean up
+##############
+
+# 1. Stop the server
+-- exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
+-- shutdown_server
+-- source include/wait_until_disconnected.inc
+
+# 2. Undo changes to index and log files
+-- remove_file $MYSQLD_DATADIR/$log_bin_index
+-- copy_file $MYSQLD_DATADIR/$log_bin_index.orig $MYSQLD_DATADIR/$log_bin_index
+-- remove_file $MYSQLD_DATADIR/$log_bin_index.orig
+
+-- remove_file $MYSQLD_DATADIR/$log_bin_basename.2147483646
+-- remove_file $MYSQLD_DATADIR/$log_bin_basename.2147483647
+
+# 3. Restart the server
+-- exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
+-- enable_reconnect
+-- source include/wait_until_connected_again.inc
diff --git a/mysql-test/suite/binlog/t/binlog_mdev342-master.opt b/mysql-test/suite/binlog/t/binlog_mdev342-master.opt
new file mode 100644
index 00000000..590d44a6
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_mdev342-master.opt
@@ -0,0 +1 @@
+--loose-skip-stack-trace --skip-core-file
diff --git a/mysql-test/suite/binlog/t/binlog_mdev342.test b/mysql-test/suite/binlog/t/binlog_mdev342.test
new file mode 100644
index 00000000..6d48ea12
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_mdev342.test
@@ -0,0 +1,67 @@
+--source include/have_innodb.inc
+--source include/have_debug.inc
+--source include/have_debug_sync.inc
+--source include/have_binlog_format_row.inc
+# Valgrind does not work well with test that crashes the server
+--source include/not_valgrind.inc
+
+# (We do not need to restore these settings, as we crash the server).
+SET GLOBAL max_binlog_size= 4096;
+SET GLOBAL innodb_flush_log_at_trx_commit= 1;
+RESET MASTER;
+
+CREATE TABLE t1 (a INT PRIMARY KEY, b MEDIUMTEXT) ENGINE=Innodb;
+# MDEV-515 takes X-lock on the table for the first insert
+# In that case, Concurrent DML will get blocked
+INSERT INTO t1 VALUES(100, "MDEV-515");
+# One connection does an insert that causes a binlog rotate.
+# The rotate is paused after writing new file but before updating index.
+connect(con1,localhost,root,,);
+SET DEBUG_SYNC= "binlog_open_before_update_index SIGNAL con1_ready WAIT_FOR con1_cont";
+SET SESSION debug_dbug="+d,crash_create_critical_before_update_index";
+send INSERT INTO t1 VALUES (1, REPEAT("x", 4100));
+
+connection default;
+SET DEBUG_SYNC= "now WAIT_FOR con1_ready";
+
+# Another connection creates a prepared transaction.
+# After the transaction is prepared, it will hang waiting for LOCK_log.
+connect(con2,localhost,root,,);
+SET DEBUG_SYNC= "ha_commit_trans_after_prepare SIGNAL con2_ready";
+send INSERT INTO t1 VALUES (2, NULL);
+
+connection default;
+SET DEBUG_SYNC= "now WAIT_FOR con2_ready";
+
+# Now crash the server in con1, with old binlog closed, new binlog not yet in
+# index, and one transaction in prepared-but-not-committed state.
+--write_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
+wait-binlog_mdev342.test
+EOF
+# If con1 manages to race ahead and crash, we can see the crash already in the
+# SET DEBUG_SYNC statement, so need --error here also.
+--error 0,2006,2013
+SET DEBUG_SYNC= "now SIGNAL con1_cont";
+connection con1;
+--error 2006,2013
+reap;
+
+--append_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
+restart-binlog_mdev342.test
+EOF
+
+connection default;
+--enable_reconnect
+--source include/wait_until_connected_again.inc
+
+# Check that all transactions are recovered.
+SELECT a FROM t1 ORDER BY a;
+
+--source include/show_binary_logs.inc
+--let $binlog_file= master-bin.000001
+--let $binlog_start= 4
+--source include/show_binlog_events.inc
+
+# Cleanup
+connection default;
+DROP TABLE t1;
diff --git a/mysql-test/suite/binlog/t/binlog_mdev717.test b/mysql-test/suite/binlog/t/binlog_mdev717.test
new file mode 100644
index 00000000..61d3aa71
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_mdev717.test
@@ -0,0 +1,46 @@
+# MDEV-717 LP:1003679 - Wrong binlog order on concurrent DROP schema and CREATE function.
+
+--source include/have_debug_sync.inc
+--source include/have_log_bin.inc
+RESET MASTER;
+
+connect(con1,localhost,root);
+connection default;
+
+CREATE DATABASE mysqltest;
+SET DEBUG_SYNC= "after_wait_locked_schema_name SIGNAL locked WAIT_FOR release";
+--send DROP DATABASE mysqltest;
+connection con1;
+SET DEBUG_SYNC= "now WAIT_FOR locked";
+SET DEBUG_SYNC= "before_wait_locked_pname SIGNAL release";
+--error ER_BAD_DB_ERROR
+CREATE FUNCTION mysqltest.f1() RETURNS INT RETURN 1;
+connection default;
+--reap
+
+CREATE DATABASE mysqltest;
+SET DEBUG_SYNC= "after_wait_locked_schema_name SIGNAL locked WAIT_FOR release";
+--send DROP DATABASE mysqltest;
+connection con1;
+SET DEBUG_SYNC= "now WAIT_FOR locked";
+SET DEBUG_SYNC= "before_wait_locked_pname SIGNAL release";
+--error ER_BAD_DB_ERROR
+CREATE EVENT mysqltest.e1 ON SCHEDULE EVERY 15 MINUTE DO BEGIN END;
+connection default;
+--reap
+
+CREATE DATABASE mysqltest;
+CREATE EVENT mysqltest.e1 ON SCHEDULE EVERY 15 MINUTE DO BEGIN END;
+SET DEBUG_SYNC= "after_wait_locked_schema_name SIGNAL locked WAIT_FOR release";
+--send DROP DATABASE mysqltest;
+connection con1;
+SET DEBUG_SYNC= "now WAIT_FOR locked";
+SET DEBUG_SYNC= "before_wait_locked_pname SIGNAL release";
+--error ER_BAD_DB_ERROR
+ALTER EVENT mysqltest.e1 ON SCHEDULE EVERY 20 MINUTE DO BEGIN END;
+connection default;
+--reap
+
+SET DEBUG_SYNC= "RESET";
+--source include/show_binlog_events.inc
+
diff --git a/mysql-test/suite/binlog/t/binlog_mixed.test b/mysql-test/suite/binlog/t/binlog_mixed.test
new file mode 100644
index 00000000..fa1b2ca3
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_mixed.test
@@ -0,0 +1,23 @@
+--source include/have_innodb.inc
+--source include/have_binlog_format_mixed_or_row.inc
+
+#
+# MDEV-22048 Assertion `binlog_table_maps == 0 ||
+# locked_tables_mode == LTM_LOCK_TABLES' failed in
+# THD::reset_for_next_command
+#
+
+CREATE TABLE t1 (a INT) ENGINE=InnoDB;
+INSERT INTO t1 (a) VALUES (1),(2);
+
+CREATE TABLE t2 (b INT) ENGINE=InnoDB;
+
+CREATE TRIGGER tr1 BEFORE UPDATE ON t1 FOR EACH ROW SET @a = 0;
+CREATE TRIGGER tr2 BEFORE INSERT ON t2 FOR EACH ROW DELETE FROM t1 LIMIT 1;
+
+SET AUTOCOMMIT= OFF;
+LOCK TABLES t2 WRITE;
+DELETE FROM t1 LIMIT 1;
+SAVEPOINT A;
+UNLOCK TABLES;
+DROP TABLE t1, t2;
diff --git a/mysql-test/suite/binlog/t/binlog_mixed_cache_stat.opt b/mysql-test/suite/binlog/t/binlog_mixed_cache_stat.opt
new file mode 100644
index 00000000..2d4e658e
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_mixed_cache_stat.opt
@@ -0,0 +1 @@
+--binlog_cache_size=32768 --binlog_stmt_cache_size=32768
diff --git a/mysql-test/suite/binlog/t/binlog_mixed_cache_stat.test b/mysql-test/suite/binlog/t/binlog_mixed_cache_stat.test
new file mode 100644
index 00000000..f22ea65d
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_mixed_cache_stat.test
@@ -0,0 +1,5 @@
+# This is a wrapper for binlog.test so that the same test case can be used
+# For both statement and row based bin logs 9/19/2005 [jbm]
+
+-- source include/have_binlog_format_mixed.inc
+-- source include/binlog_cache_stat.test
diff --git a/mysql-test/suite/binlog/t/binlog_mixed_load_data.test b/mysql-test/suite/binlog/t/binlog_mixed_load_data.test
new file mode 100644
index 00000000..7e7cb973
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_mixed_load_data.test
@@ -0,0 +1,15 @@
+#
+# Bug #34283 mysqlbinlog leaves tmpfile after termination
+# if binlog contains load data infile, so in mixed mode we
+# go to row-based for avoiding the problem.
+#
+
+--source include/have_binlog_format_mixed.inc
+--source include/have_log_bin.inc
+
+RESET MASTER;
+CREATE TABLE t1 (word CHAR(20) NOT NULL) ENGINE=MYISAM;
+let $binlog_start= query_get_value(SHOW MASTER STATUS, Position, 1);
+LOAD DATA INFILE '../../std_data/words.dat' INTO TABLE t1;
+--source include/show_binlog_events.inc
+DROP TABLE t1;
diff --git a/mysql-test/suite/binlog/t/binlog_mysqlbinlog-cp932-master.opt b/mysql-test/suite/binlog/t/binlog_mysqlbinlog-cp932-master.opt
new file mode 100644
index 00000000..bb0cda45
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_mysqlbinlog-cp932-master.opt
@@ -0,0 +1 @@
+--max-binlog-size=8192
diff --git a/mysql-test/suite/binlog/t/binlog_mysqlbinlog-cp932.test b/mysql-test/suite/binlog/t/binlog_mysqlbinlog-cp932.test
new file mode 100644
index 00000000..80710261
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_mysqlbinlog-cp932.test
@@ -0,0 +1 @@
+--source include/binlog_mysqlbinlog-cp932.inc
diff --git a/mysql-test/suite/binlog/t/binlog_mysqlbinlog2-master.opt b/mysql-test/suite/binlog/t/binlog_mysqlbinlog2-master.opt
new file mode 100644
index 00000000..4d69f335
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_mysqlbinlog2-master.opt
@@ -0,0 +1 @@
+--timezone=GMT-3
diff --git a/mysql-test/suite/binlog/t/binlog_mysqlbinlog2.test b/mysql-test/suite/binlog/t/binlog_mysqlbinlog2.test
new file mode 100644
index 00000000..53bf932e
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_mysqlbinlog2.test
@@ -0,0 +1,217 @@
+# Test for the new options --start-datetime, stop-datetime,
+# and a few others.
+
+# 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
+
+set sql_mode="";
+set global binlog_checksum=NONE;
+--disable_warnings
+drop table if exists t1;
+--enable_warnings
+
+# We need this for getting fixed timestamps inside of this test.
+# I use a date in the past to keep a growing timestamp along the
+# binlog (including the Start_log_event). This test will work
+# unchanged everywhere, because mysql-test-run has fixed TZ, which it
+# exports (so mysqlbinlog has same fixed TZ).
+set @a=UNIX_TIMESTAMP("1970-01-21 15:32:22");
+set timestamp=@a;
+reset master;
+create table t1 (a int auto_increment not null primary key, b char(3));
+insert into t1 values(null, "a");
+insert into t1 values(null, "b");
+set timestamp=@a+2;
+--let $binlog_pos_760=query_get_value(SHOW MASTER STATUS, Position, 1)
+insert into t1 values(null, "c");
+--let $binlog_pos_951=query_get_value(SHOW BINLOG EVENTS in 'master-bin.000001' from $binlog_pos_760, Pos, 5)
+set timestamp=@a+4;
+insert into t1 values(null, "d");
+insert into t1 values(null, "e");
+
+flush logs;
+set timestamp=@a+1; # this could happen on a slave
+insert into t1 values(null, "f");
+--let $binlog_pos_135=query_get_value(SHOW BINLOG EVENTS in 'master-bin.000002', Pos, 4)
+--let $binlog_pos_203=query_get_value(SHOW BINLOG EVENTS in 'master-bin.000002', Pos, 5)
+
+# delimiters are for easier debugging in future
+
+--disable_query_log
+select "--- Local --" as "";
+--enable_query_log
+
+#
+# We should use --short-form everywhere because in other case output will
+# be time dependent (the Start events). Better than nothing.
+#
+let $MYSQLD_DATADIR= `select @@datadir`;
+--replace_regex /collation_server=[0-9]+/collation_server=X/ /character_set_client=[a-zA-Z0-9]+/character_set_client=X/ /collation_connection=[0-9]+/collation_connection=X/
+--exec $MYSQL_BINLOG --short-form --base64-output=never $MYSQLD_DATADIR/master-bin.000001
+
+--disable_query_log
+select "--- offset --" as "";
+--enable_query_log
+--replace_regex /collation_server=[0-9]+/collation_server=X/ /character_set_client=[a-zA-Z0-9]+/character_set_client=X/ /collation_connection=[0-9]+/collation_connection=X/
+--exec $MYSQL_BINLOG --short-form --offset=5 $MYSQLD_DATADIR/master-bin.000001
+--disable_query_log
+select "--- start-position --" as "";
+--enable_query_log
+let $start_pos= `select @binlog_start_pos + 705`;
+--replace_regex /collation_server=[0-9]+/collation_server=X/ /character_set_client=[a-zA-Z0-9]+/character_set_client=X/ /collation_connection=[0-9]+/collation_connection=X/
+--exec $MYSQL_BINLOG --short-form --start-position=$start_pos $MYSQLD_DATADIR/master-bin.000001
+--disable_query_log
+select "--- stop-position --" as "";
+--enable_query_log
+let $stop_pos= `select @binlog_start_pos + 705`;
+--replace_regex /collation_server=[0-9]+/collation_server=X/ /character_set_client=[a-zA-Z0-9]+/character_set_client=X/ /collation_connection=[0-9]+/collation_connection=X/
+--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
+let $start_pos= `select @binlog_start_pos + 705`;
+let $stop_pos= `select @binlog_start_pos + 866`;
+--replace_regex /collation_server=[0-9]+/collation_server=X/ /character_set_client=[a-zA-Z0-9]+/character_set_client=X/ /collation_connection=[0-9]+/collation_connection=X/
+--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
+--replace_regex /collation_server=[0-9]+/collation_server=X/ /character_set_client=[a-zA-Z0-9]+/character_set_client=X/ /collation_connection=[0-9]+/collation_connection=X/
+--exec $MYSQL_BINLOG --short-form "--start-datetime=1970-01-21 15:32:24" $MYSQLD_DATADIR/master-bin.000001
+--disable_query_log
+select "--- stop-datetime --" as "";
+--enable_query_log
+--replace_regex /collation_server=[0-9]+/collation_server=X/ /character_set_client=[a-zA-Z0-9]+/character_set_client=X/ /collation_connection=[0-9]+/collation_connection=X/
+--exec $MYSQL_BINLOG --short-form "--stop-datetime=1970-01-21 15:32:24" $MYSQLD_DATADIR/master-bin.000001
+
+--disable_query_log
+select "--- Local with 2 binlogs on command line --" as "";
+--enable_query_log
+
+# This is to verify that some options apply only to first, or last binlog
+
+flush logs;
+--replace_regex /collation_server=[0-9]+/collation_server=X/ /character_set_client=[a-zA-Z0-9]+/character_set_client=X/ /collation_connection=[0-9]+/collation_connection=X/
+--exec $MYSQL_BINLOG --short-form $MYSQLD_DATADIR/master-bin.000001 $MYSQLD_DATADIR/master-bin.000002
+
+--disable_query_log
+select "--- offset --" as "";
+--enable_query_log
+--replace_regex /collation_server=[0-9]+/collation_server=X/ /character_set_client=[a-zA-Z0-9]+/character_set_client=X/ /collation_connection=[0-9]+/collation_connection=X/
+--exec $MYSQL_BINLOG --short-form --offset=5 $MYSQLD_DATADIR/master-bin.000001 $MYSQLD_DATADIR/master-bin.000002
+--disable_query_log
+select "--- start-position --" as "";
+--enable_query_log
+let $start_pos= `select @binlog_start_pos + 705`;
+--replace_regex /collation_server=[0-9]+/collation_server=X/ /character_set_client=[a-zA-Z0-9]+/character_set_client=X/ /collation_connection=[0-9]+/collation_connection=X/
+--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
+let $stop_pos= `select @binlog_start_pos + 134`;
+--replace_regex /collation_server=[0-9]+/collation_server=X/ /character_set_client=[a-zA-Z0-9]+/character_set_client=X/ /collation_connection=[0-9]+/collation_connection=X/
+--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
+--replace_regex /collation_server=[0-9]+/collation_server=X/ /character_set_client=[a-zA-Z0-9]+/character_set_client=X/ /collation_connection=[0-9]+/collation_connection=X/
+--exec $MYSQL_BINLOG --short-form "--start-datetime=1970-01-21 15:32:24" $MYSQLD_DATADIR/master-bin.000001 $MYSQLD_DATADIR/master-bin.000002
+--disable_query_log
+select "--- stop-datetime --" as "";
+--enable_query_log
+--replace_regex /collation_server=[0-9]+/collation_server=X/ /character_set_client=[a-zA-Z0-9]+/character_set_client=X/ /collation_connection=[0-9]+/collation_connection=X/
+--exec $MYSQL_BINLOG --short-form "--stop-datetime=1970-01-21 15:32:24" $MYSQLD_DATADIR/master-bin.000001 $MYSQLD_DATADIR/master-bin.000002
+
+--disable_query_log
+select "--- Remote --" as "";
+--enable_query_log
+
+--replace_regex /collation_server=[0-9]+/collation_server=X/ /character_set_client=[a-zA-Z0-9]+/character_set_client=X/ /collation_connection=[0-9]+/collation_connection=X/
+--exec $MYSQL_BINLOG --short-form --read-from-remote-server --user=root --host=127.0.0.1 --port=$MASTER_MYPORT master-bin.000001
+
+--disable_query_log
+select "--- offset --" as "";
+--enable_query_log
+--replace_regex /collation_server=[0-9]+/collation_server=X/ /character_set_client=[a-zA-Z0-9]+/character_set_client=X/ /collation_connection=[0-9]+/collation_connection=X/
+--exec $MYSQL_BINLOG --short-form --offset=5 --read-from-remote-server --user=root --host=127.0.0.1 --port=$MASTER_MYPORT master-bin.000001
+--disable_query_log
+select "--- start-position --" as "";
+--enable_query_log
+let $start_pos= `select @binlog_start_pos + 705`;
+--replace_regex /collation_server=[0-9]+/collation_server=X/ /character_set_client=[a-zA-Z0-9]+/character_set_client=X/ /collation_connection=[0-9]+/collation_connection=X/
+--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
+let $stop_pos= `select @binlog_start_pos + 705`;
+--replace_regex /collation_server=[0-9]+/collation_server=X/ /character_set_client=[a-zA-Z0-9]+/character_set_client=X/ /collation_connection=[0-9]+/collation_connection=X/
+--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
+let $start_pos= `select @binlog_start_pos + 705`;
+let $stop_pos= `select @binlog_start_pos + 812`;
+--replace_regex /collation_server=[0-9]+/collation_server=X/ /character_set_client=[a-zA-Z0-9]+/character_set_client=X/ /collation_connection=[0-9]+/collation_connection=X/
+--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
+--replace_regex /collation_server=[0-9]+/collation_server=X/ /character_set_client=[a-zA-Z0-9]+/character_set_client=X/ /collation_connection=[0-9]+/collation_connection=X/
+--exec $MYSQL_BINLOG --short-form "--start-datetime=1970-01-21 15:32:24" --read-from-remote-server --user=root --host=127.0.0.1 --port=$MASTER_MYPORT master-bin.000001
+--disable_query_log
+select "--- stop-datetime --" as "";
+--enable_query_log
+--replace_regex /collation_server=[0-9]+/collation_server=X/ /character_set_client=[a-zA-Z0-9]+/character_set_client=X/ /collation_connection=[0-9]+/collation_connection=X/
+--exec $MYSQL_BINLOG --short-form "--stop-datetime=1970-01-21 15:32:24" --read-from-remote-server --user=root --host=127.0.0.1 --port=$MASTER_MYPORT master-bin.000001
+
+--disable_query_log
+select "--- Remote with 2 binlogs on command line --" as "";
+--enable_query_log
+
+--replace_regex /collation_server=[0-9]+/collation_server=X/ /character_set_client=[a-zA-Z0-9]+/character_set_client=X/ /collation_connection=[0-9]+/collation_connection=X/
+--exec $MYSQL_BINLOG --short-form --read-from-remote-server --user=root --host=127.0.0.1 --port=$MASTER_MYPORT master-bin.000001 master-bin.000002
+
+--disable_query_log
+select "--- offset --" as "";
+--enable_query_log
+--replace_regex /collation_server=[0-9]+/collation_server=X/ /character_set_client=[a-zA-Z0-9]+/character_set_client=X/ /collation_connection=[0-9]+/collation_connection=X/
+--exec $MYSQL_BINLOG --short-form --offset=5 --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-position --" as "";
+--enable_query_log
+let $start_pos= `select @binlog_start_pos + 705`;
+--replace_regex /collation_server=[0-9]+/collation_server=X/ /character_set_client=[a-zA-Z0-9]+/character_set_client=X/ /collation_connection=[0-9]+/collation_connection=X/
+--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
+let $stop_pos= `select @binlog_start_pos + 109`;
+--replace_regex /collation_server=[0-9]+/collation_server=X/ /character_set_client=[a-zA-Z0-9]+/character_set_client=X/ /collation_connection=[0-9]+/collation_connection=X/
+--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
+--replace_regex /collation_server=[0-9]+/collation_server=X/ /character_set_client=[a-zA-Z0-9]+/character_set_client=X/ /collation_connection=[0-9]+/collation_connection=X/
+--exec $MYSQL_BINLOG --short-form "--start-datetime=19700121153224" --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-datetime --" as "";
+--enable_query_log
+--replace_regex /collation_server=[0-9]+/collation_server=X/ /character_set_client=[a-zA-Z0-9]+/character_set_client=X/ /collation_connection=[0-9]+/collation_connection=X/
+--exec $MYSQL_BINLOG --short-form "--stop-datetime=1970/01/21 15@32@24" --read-from-remote-server --user=root --host=127.0.0.1 --port=$MASTER_MYPORT master-bin.000001 master-bin.000002
+
+--disable_query_log
+select "--- to-last-log --" as "";
+--enable_query_log
+
+--replace_regex /collation_server=[0-9]+/collation_server=X/ /character_set_client=[a-zA-Z0-9]+/character_set_client=X/ /collation_connection=[0-9]+/collation_connection=X/
+--exec $MYSQL_BINLOG --short-form --read-from-remote-server --user=root --host=127.0.0.1 --port=$MASTER_MYPORT --to-last-log master-bin.000001
+
+# clean up
+--disable_query_log
+select "--- end of test --" as "";
+--enable_query_log
+drop table t1;
+
+set global binlog_checksum=default;
+# End of 4.1 tests
diff --git a/mysql-test/suite/binlog/t/binlog_mysqlbinlog_base64.test b/mysql-test/suite/binlog/t/binlog_mysqlbinlog_base64.test
new file mode 100644
index 00000000..3d3444ce
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_mysqlbinlog_base64.test
@@ -0,0 +1,102 @@
+-- source include/have_binlog_format_row.inc
+#
+# Reset master to cleanup binlog
+#
+reset master;
+
+#
+# Write different events to binlog
+#
+create table t1 (a int);
+insert into t1 values (1);
+insert into t1 values (2);
+insert into t1 values (3);
+update t1 set a=a+2 where a=2;
+update t1 set a=a+2 where a=3;
+
+create table t2 (word varchar(20));
+load data infile '../../std_data/words.dat' into table t2;
+
+#
+# Save binlog
+#
+let $MYSQLD_DATADIR=`select @@datadir`;
+flush logs;
+--exec $MYSQL_BINLOG --hexdump $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/mysqlbinlog_base64.sql
+
+#
+# Clear database and restore from binlog
+#
+drop table t1;
+drop table t2;
+--exec $MYSQL test < $MYSQLTEST_VARDIR/tmp/mysqlbinlog_base64.sql
+
+#
+# Verify that all binlog events have been executed
+#
+select * from t1;
+select * from t2;
+
+#
+# Verify that events larger than the default IO_CACHE buffer
+# are handled correctly (BUG#25628).
+#
+flush logs;
+drop table t2;
+create table t2 (word varchar(20));
+load data infile '../../std_data/words.dat' into table t2;
+insert into t2 select * from t2;
+insert into t2 select * from t2;
+insert into t2 select * from t2;
+insert into t2 select * from t2;
+insert into t2 select * from t2;
+insert into t2 select * from t2;
+insert into t2 select * from t2;
+insert into t2 select * from t2;
+insert into t2 select * from t2;
+select count(*) from t2;
+
+flush logs;
+--exec $MYSQL_BINLOG --hexdump $MYSQLD_DATADIR/master-bin.000003 > $MYSQLTEST_VARDIR/tmp/mysqlbinlog_base64.sql
+--exec $MYSQL test < $MYSQLTEST_VARDIR/tmp/mysqlbinlog_base64.sql
+
+#
+# Verify that all binlog events have been executed
+#
+select count(*) from t2;
+
+#
+# Test cleanup
+#
+--remove_file $MYSQLTEST_VARDIR/tmp/mysqlbinlog_base64.sql
+drop table t1;
+drop table t2;
+
+#
+# BUG#12354268
+#
+# This test verifies that using --start-position with DECODE-ROWS
+# does not make mysqlbinlog to output an error stating that it
+# does not contain any FD event.
+#
+
+RESET MASTER;
+USE test;
+SET @old_binlog_format= @@binlog_format;
+SET SESSION binlog_format=ROW;
+CREATE TABLE t1(c1 INT);
+--let $master_binlog= query_get_value(SHOW MASTER STATUS, File, 1)
+--let $master_pos= query_get_value(SHOW MASTER STATUS, Position, 1)
+--let $MYSQLD_DATADIR= `SELECT @@datadir`
+
+INSERT INTO t1 VALUES (1);
+
+FLUSH LOGS;
+
+--disable_result_log
+--exec $MYSQL_BINLOG --base64-output=DECODE-ROWS --start-position=$master_pos -v $MYSQLD_DATADIR/$master_binlog
+--enable_result_log
+
+DROP TABLE t1;
+SET SESSION binlog_format= @old_binlog_format;
+RESET MASTER;
diff --git a/mysql-test/suite/binlog/t/binlog_mysqlbinlog_do_server_ids.test b/mysql-test/suite/binlog/t/binlog_mysqlbinlog_do_server_ids.test
new file mode 100644
index 00000000..9f32e2db
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_mysqlbinlog_do_server_ids.test
@@ -0,0 +1,477 @@
+#
+# Purpose:
+#
+# This test validates that the option --do-server-ids for the mariadb-binlog
+# command line tool correctly filters events by server id.
+#
+#
+# Methodology:
+#
+# This test invokes mariadb-binlog using combinations of --do-server-ids with
+# various combinations of other parameters to ensure it correctly filters by
+# server id. Specifically, the following test cases are validated:
+# Test Case 1) --do-server-ids with a single server id limits output to that
+# single server
+# Test Case 2) --do-server-ids with multiple server ids limits output to the
+# provided servers
+# Test Case 3) --do-server-ids when combined with --do-domain-ids should
+# intersect the results
+# Test Case 4) --do-server-ids when combined with --ignore-domain-ids should
+# intersect the results
+# Test Case 5) --do-server-ids when combined with a GTID range should
+# intersect the results
+# Test Case 6) --do-server-ids when combined with both --ignore-domain-ids
+# and a GTID range should intersect all results
+# Test Case 7) --do-server-ids when combined with both --do-domain-ids and
+# a GTID range should intersect all results
+# Test Case 8) --do-server-ids and --offset=<n> skips n events after the
+# first GTID is found
+# Test Case 9) --do-server-ids with --start-datetime=<T> where T occurs
+# after the first GTID is found results in no events before T
+# Test Case 10) --do-server-ids works with --read-from-remote-server
+# Test Case 11) --do-server-ids works over multiple binary log input files
+# Test Case 12) --do-server-ids re-specifications should override previous
+# ones
+# Test Case 13) --do-server-ids and --server-id should be aliases and a
+# re-specification of one should override the former
+# Test Case 14) --ignore-server-ids re-specifications should override
+# previous ones
+# Test Case 15) --do-domain-ids re-specifications should override previous
+# ones
+# Test Case 16) --ignore-domain-ids re-specifications should override
+# previous ones
+#
+# Additionally, this test validates the following error scenarios:
+# Error Case 1) --do-server-ids and --ignore-server-ids cannot be specified
+# together
+# Error Case 2) Invalid server ID number provided
+#
+#
+# References:
+#
+# MDEV-20119: Implement the --do-domain-ids, --ignore-domain-ids, and
+# --ignore-server-ids options for mysqlbinlog
+#
+
+--source include/have_log_bin.inc
+
+--echo ###############################
+--echo # Test Setup
+--echo ###############################
+
+
+# Save old state
+let $ORIG_GTID_DOMAIN_ID = `select @@session.gtid_domain_id`;
+let $ORIG_SERVER_ID = `select @@session.server_id`;
+
+# Configure test variables
+--let $MYSQLD_DATADIR=`select @@datadir`
+
+--let table_inconsistent_err= "table data is inconsistent after replaying binlog events";
+--let table_exists_error= "table exists but binlog playback should have excluded its creation";
+
+# Initialize test data
+set @a=UNIX_TIMESTAMP("1970-01-21 15:32:22");
+SET timestamp=@a;
+RESET MASTER;
+
+SET @@session.gtid_domain_id= 0;
+SET @@session.server_id= 1;
+CREATE TABLE t1 (a int);
+
+SET @@session.server_id= 2;
+CREATE TABLE t2 (a int);
+INSERT INTO t2 values (3);
+--let t2_checksum= `CHECKSUM TABLE t2`
+
+SET @@session.gtid_domain_id= 1;
+SET @@session.server_id= 1;
+CREATE TABLE t3 (a int);
+INSERT INTO t3 values (4);
+--let t3_checksum= `CHECKSUM TABLE t3`
+
+SET @@session.server_id= 3;
+SET timestamp=@a+1;
+CREATE TABLE t4 (a int);
+SET timestamp=@a+2;
+INSERT INTO t4 values (5);
+--let t4_checksum= `CHECKSUM TABLE t4`
+
+SET @@session.gtid_domain_id= 0;
+SET @@session.server_id= 1;
+INSERT INTO t1 values (1);
+--let t1_partial_checksum= `CHECKSUM TABLE t1`
+
+SET @@session.gtid_domain_id= 2;
+SET @@session.server_id= 1;
+CREATE TABLE t5 (a int);
+INSERT INTO t5 values (6);
+--let t5_checksum= `CHECKSUM TABLE t5`
+
+SET @@session.gtid_domain_id= 0;
+SET @@session.server_id= 1;
+INSERT INTO t1 values (2);
+--let t1_checksum= `CHECKSUM TABLE t1`
+
+FLUSH LOGS;
+
+SET @@session.gtid_domain_id= 0;
+SET @@session.server_id= 2;
+CREATE TABLE t6 (a int);
+INSERT INTO t6 values (1);
+--let t6_checksum= `CHECKSUM TABLE t6`
+FLUSH LOGS;
+
+--let BINLOG_FILENAME= query_get_value(SHOW BINARY LOGS, Log_name, 1)
+--let BINLOG_FILENAME2= query_get_value(SHOW BINARY LOGS, Log_name, 2)
+--let BINLOG_FILE_PARAM= $MYSQLD_DATADIR/$BINLOG_FILENAME.orig
+--let BINLOG_FILE_PARAM2= $MYSQLD_DATADIR/$BINLOG_FILENAME2.orig
+--copy_file $MYSQLD_DATADIR/$BINLOG_FILENAME $BINLOG_FILE_PARAM
+--copy_file $MYSQLD_DATADIR/$BINLOG_FILENAME2 $BINLOG_FILE_PARAM2
+
+DROP TABLE t1;
+DROP TABLE t2;
+DROP TABLE t3;
+DROP TABLE t4;
+DROP TABLE t5;
+DROP TABLE t6;
+RESET MASTER;
+
+--echo ###############################
+--echo # Test Cases
+--echo ###############################
+
+--echo #
+--echo # Test Case 1) --do-server-ids with a single server id limits output
+--echo # to that single server
+--echo # MYSQL_BINLOG BINLOG_FILE_PARAM --do-server-ids=2 | MYSQL
+--exec $MYSQL_BINLOG $BINLOG_FILE_PARAM --do-server-ids=2 | $MYSQL
+if ($t2_checksum != `CHECKSUM TABLE t2`)
+{
+ die $table_inconsistent_err;
+}
+if (`SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = 'test' AND table_name IN ('t1','t3','t4','t5','t6')`)
+{
+ die $table_exists_error;
+}
+DROP TABLE t2;
+
+
+--echo #
+--echo # Test Case 2) --do-server-ids with multiple server ids limits output
+--echo # to the provided servers
+--echo # MYSQL_BINLOG BINLOG_FILE_PARAM --do-server-ids=2,3 | MYSQL
+--exec $MYSQL_BINLOG $BINLOG_FILE_PARAM --do-server-ids=2,3 | $MYSQL
+if ($t2_checksum != `CHECKSUM TABLE t2`)
+{
+ die $table_inconsistent_err;
+}
+if ($t4_checksum != `CHECKSUM TABLE t4`)
+{
+ die $table_inconsistent_err;
+}
+if (`SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = 'test' AND table_name IN ('t1','t3','t5','t6')`)
+{
+ die $table_exists_error;
+}
+DROP TABLE t2;
+DROP TABLE t4;
+
+
+--echo #
+--echo # Test Case 3) --do-server-ids when combined with --do-domain-ids should
+--echo # intersect the results
+--echo # MYSQL_BINLOG BINLOG_FILE_PARAM --do-server-ids=1 --do-domain-ids=0 | MYSQL
+--exec $MYSQL_BINLOG $BINLOG_FILE_PARAM --do-server-ids=1 --do-domain-ids=0 | $MYSQL
+if ($t1_checksum != `CHECKSUM TABLE t1`)
+{
+ die $table_inconsistent_err;
+}
+if (`SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = 'test' AND table_name IN ('t2','t3','t4','t5','t6')`)
+{
+ die $table_exists_error;
+}
+DROP TABLE t1;
+
+
+--echo #
+--echo # Test Case 4) --do-server-ids when combined with --ignore-domain-ids should
+--echo # intersect the results
+--echo # MYSQL_BINLOG BINLOG_FILE_PARAM --do-server-ids=1 --ignore-domain-ids=0 | MYSQL
+--exec $MYSQL_BINLOG $BINLOG_FILE_PARAM --do-server-ids=1 --ignore-domain-ids=0 | $MYSQL
+if ($t3_checksum != `CHECKSUM TABLE t3`)
+{
+ die $table_inconsistent_err;
+}
+if ($t5_checksum != `CHECKSUM TABLE t5`)
+{
+ die $table_inconsistent_err;
+}
+if (`SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = 'test' AND table_name IN ('t1','t2','t4','t6')`)
+{
+ die $table_exists_error;
+}
+DROP TABLE t3;
+DROP TABLE t5;
+
+
+--echo #
+--echo # Test Case 5) --do-server-ids when combined with a GTID range should
+--echo # intersect the results
+--echo # MYSQL_BINLOG BINLOG_FILE_PARAM --do-server-ids=1 --stop-position=0-1-4 | MYSQL
+--exec $MYSQL_BINLOG $BINLOG_FILE_PARAM --do-server-ids=1 --stop-position=0-1-4 | $MYSQL
+if ($t1_partial_checksum != `CHECKSUM TABLE t1`)
+{
+ die $table_inconsistent_err;
+}
+if (`SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = 'test' AND table_name IN ('t2','t3','t4','t5','t6')`)
+{
+ die $table_exists_error;
+}
+DROP TABLE t1;
+
+
+--echo #
+--echo # Test Case 6) --do-server-ids when combined with both --ignore-domain-ids
+--echo # and a GTID range should intersect all results
+--echo # MYSQL_BINLOG BINLOG_FILE_PARAM --do-server-ids=1 --ignore-domain-ids=0 --start-position=1-1-0 | MYSQL
+--exec $MYSQL_BINLOG $BINLOG_FILE_PARAM --do-server-ids=1 --ignore-domain-ids=0 --start-position=1-1-0 | $MYSQL
+if ($t3_checksum != `CHECKSUM TABLE t3`)
+{
+ die $table_inconsistent_err;
+}
+if ($t5_checksum != `CHECKSUM TABLE t5`)
+{
+ die $table_inconsistent_err;
+}
+if (`SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = 'test' AND table_name IN ('t1','t2','t4','t6')`)
+{
+ die $table_exists_error;
+}
+DROP TABLE t3;
+DROP TABLE t5;
+
+
+--echo #
+--echo # Test Case 7) --do-server-ids when combined with both --do-domain-ids and
+--echo # a GTID range should intersect all results
+--echo # MYSQL_BINLOG BINLOG_FILE_PARAM --do-server-ids=2 --do-domain-ids=0 --start-position=0-1-0 | MYSQL
+--exec $MYSQL_BINLOG $BINLOG_FILE_PARAM --do-server-ids=2 --do-domain-ids=0 --start-position=0-1-0 | $MYSQL
+if ($t2_checksum != `CHECKSUM TABLE t2`)
+{
+ die $table_inconsistent_err;
+}
+if (`SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = 'test' AND table_name IN ('t1','t3','t4','t5','t6')`)
+{
+ die $table_exists_error;
+}
+DROP TABLE t2;
+
+
+
+--echo #
+--echo # Test Case 8) --do-server-ids and --offset=<n> skips n events after the
+--echo # first GTID is found
+
+# t4 needs to be specified because its creation should be skipped from
+# --offset specification
+CREATE TABLE t4 (a int);
+
+--echo # MYSQL_BINLOG BINLOG_FILE_PARAM --offset=5 --do-server-ids=3 --do-domain-ids=1 | MYSQL
+--exec $MYSQL_BINLOG $BINLOG_FILE_PARAM --offset=5 --do-server-ids=3 --do-domain-ids=1 | $MYSQL
+if ($t4_checksum != `CHECKSUM TABLE t4`)
+{
+ die $table_inconsistent_err;
+}
+if (`SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = 'test' AND table_name IN ('t1','t2','t3','t5','t6')`)
+{
+ die $table_exists_error;
+}
+DROP TABLE t4;
+
+
+--echo #
+--echo # Test Case 9) --do-server-ids with --start-datetime=<T> where T occurs
+--echo # after the first GTID is found results in no events before T
+
+# t4 needs to be specified because its creation should be skipped from
+# --start-datetime specification
+CREATE TABLE t4 (a int);
+
+--echo # MYSQL_BINLOG BINLOG_FILE_PARAM --start-datetime="1970-01-21 15:32:24" --do-server-ids=3 --do-domain-ids=1 | MYSQL
+--exec $MYSQL_BINLOG $BINLOG_FILE_PARAM --start-datetime="1970-01-21 15:32:24" --do-server-ids=3 --do-domain-ids=1 | $MYSQL
+if ($t4_checksum != `CHECKSUM TABLE t4`)
+{
+ die $table_inconsistent_err;
+}
+if (`SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = 'test' AND table_name IN ('t1','t2','t3','t5','t6')`)
+{
+ die $table_exists_error;
+}
+DROP TABLE t4;
+
+
+--echo #
+--echo # Test Case 10) --do-server-ids works with --read-from-remote-server
+
+--echo # Setup test specific data
+RESET MASTER;
+
+SET @@session.gtid_domain_id= 0;
+SET @@session.server_id= 1;
+CREATE TABLE t1 (a int);
+INSERT INTO t1 VALUES (1);
+
+SET @@session.server_id= 2;
+CREATE TABLE t2 (a int);
+INSERT INTO t2 VALUES (1);
+--let t11_t2_checksum= `CHECKSUM TABLE t2`
+
+SET @@session.server_id= 1;
+DROP TABLE t1;
+DROP TABLE t2;
+
+--echo # MYSQL_BINLOG BINLOG_FILENAME --read-from-remote-server --do-server-ids=2 | MYSQL
+--exec $MYSQL_BINLOG $BINLOG_FILENAME --read-from-remote-server --do-server-ids=2 | $MYSQL
+if ($t11_t2_checksum != `CHECKSUM TABLE t2`)
+{
+ die $table_inconsistent_err;
+}
+if (`SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = 'test' AND table_name IN ('t1','t3','t4','t5','t6')`)
+{
+ die $table_exists_error;
+}
+DROP TABLE t2;
+
+
+--echo #
+--echo # Test Case 11) --do-server-ids works over multiple binary log input
+--echo # files
+--echo # MYSQL_BINLOG BINLOG_FILE_PARAM BINLOG_FILE_PARAM2 --do-server-ids=2 | MYSQL
+--exec $MYSQL_BINLOG $BINLOG_FILE_PARAM $BINLOG_FILE_PARAM2 --do-server-ids=2 | $MYSQL
+if ($t2_checksum != `CHECKSUM TABLE t2`)
+{
+ die $table_inconsistent_err;
+}
+if ($t6_checksum != `CHECKSUM TABLE t6`)
+{
+ die $table_inconsistent_err;
+}
+if (`SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = 'test' AND table_name IN ('t1','t3','t4','t5')`)
+{
+ die $table_exists_error;
+}
+DROP TABLE t2;
+DROP TABLE t6;
+
+--echo #
+--echo # Test Case 12) --do-server-ids re-specifications should override
+--echo # previous ones
+--echo # MYSQL_BINLOG BINLOG_FILE_PARAM --do-server-ids=1 --do-server-ids=2 | MYSQL
+--exec $MYSQL_BINLOG $BINLOG_FILE_PARAM --do-server-ids=1 --do-server-ids=2 | $MYSQL
+if ($t2_checksum != `CHECKSUM TABLE t2`)
+{
+ die $table_inconsistent_err;
+}
+if (`SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = 'test' AND table_name IN ('t1','t3','t4','t5','t6')`)
+{
+ die $table_exists_error;
+}
+DROP TABLE t2;
+
+--echo #
+--echo # Test Case 13) --do-server-ids and --server-id should be aliases and
+--echo # a re-specification of one should override the former
+--echo # MYSQL_BINLOG BINLOG_FILE_PARAM --do-server-ids=1 --server-id=2 | MYSQL
+--exec $MYSQL_BINLOG $BINLOG_FILE_PARAM --do-server-ids=1 --server-id=2 | $MYSQL
+if ($t2_checksum != `CHECKSUM TABLE t2`)
+{
+ die $table_inconsistent_err;
+}
+if (`SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = 'test' AND table_name IN ('t1','t3','t4','t5','t6')`)
+{
+ die $table_exists_error;
+}
+DROP TABLE t2;
+
+--echo #
+--echo # Test Case 14) --ignore-server-ids re-specifications should override
+--echo # previous ones
+--echo # MYSQL_BINLOG BINLOG_FILE_PARAM --ignore-server-ids=2 --ignore-server-ids=1,3 | MYSQL
+--exec $MYSQL_BINLOG $BINLOG_FILE_PARAM --ignore-server-ids=2 --ignore-server-ids=1,3 | $MYSQL
+if ($t2_checksum != `CHECKSUM TABLE t2`)
+{
+ die $table_inconsistent_err;
+}
+if (`SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = 'test' AND table_name IN ('t1','t3','t4','t5','t6')`)
+{
+ die $table_exists_error;
+}
+DROP TABLE t2;
+
+--echo #
+--echo # Test Case 15) --do-domain-ids re-specifications should override
+--echo # previous ones
+--echo # MYSQL_BINLOG BINLOG_FILE_PARAM --do-domain-ids=1 --do-domain-ids=0 | MYSQL
+--exec $MYSQL_BINLOG $BINLOG_FILE_PARAM --do-domain-ids=1 --do-domain-ids=0 | $MYSQL
+if ($t1_checksum != `CHECKSUM TABLE t1`)
+{
+ die $table_inconsistent_err;
+}
+if ($t2_checksum != `CHECKSUM TABLE t2`)
+{
+ die $table_inconsistent_err;
+}
+if (`SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = 'test' AND table_name IN ('t3','t4','t5','t6')`)
+{
+ die $table_exists_error;
+}
+DROP TABLE t1,t2;
+
+--echo #
+--echo # Test Case 16) --ignore-domain-ids re-specifications should override
+--echo # previous ones
+--echo # MYSQL_BINLOG BINLOG_FILE_PARAM --ignore-domain-ids=0 --ignore-domain-ids=1,2 | MYSQL
+--exec $MYSQL_BINLOG $BINLOG_FILE_PARAM --ignore-domain-ids=0 --ignore-domain-ids=1,2 | $MYSQL
+if ($t1_checksum != `CHECKSUM TABLE t1`)
+{
+ die $table_inconsistent_err;
+}
+if ($t2_checksum != `CHECKSUM TABLE t2`)
+{
+ die $table_inconsistent_err;
+}
+if (`SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = 'test' AND table_name IN ('t3','t4','t5','t6')`)
+{
+ die $table_exists_error;
+}
+DROP TABLE t1,t2;
+
+--echo ##############################
+--echo # Error Cases
+--echo ##############################
+
+--echo #
+--echo # Error Case 1:
+--echo # --ignore-server-ids and --do-server-ids both specified
+--echo # MYSQL_BINLOG BINLOG_FILE_PARAM --do-server-ids=1 --ignore-server-ids=2
+--error 1
+--exec $MYSQL_BINLOG $BINLOG_FILE_PARAM --do-server-ids=1 --ignore-server-ids=2
+
+--echo #
+--echo # Error Case 2:
+--echo # Invalid server ID number provided
+--echo # MYSQL_BINLOG BINLOG_FILE_PARAM --do-server-ids=-1
+--error 1
+--exec $MYSQL_BINLOG $BINLOG_FILE_PARAM --do-server-ids=-1
+
+--echo ##############################
+--echo # Cleanup
+--echo ##############################
+--eval SET @@global.gtid_domain_id= $ORIG_GTID_DOMAIN_ID
+--eval SET @@global.server_id= $ORIG_SERVER_ID
+
+--remove_file $BINLOG_FILE_PARAM
+--remove_file $BINLOG_FILE_PARAM2
+
+--echo # End of tests
diff --git a/mysql-test/suite/binlog/t/binlog_mysqlbinlog_glle_ordered.test b/mysql-test/suite/binlog/t/binlog_mysqlbinlog_glle_ordered.test
new file mode 100644
index 00000000..9c79925b
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_mysqlbinlog_glle_ordered.test
@@ -0,0 +1,43 @@
+#
+# Purpose:
+# This test validates that GTIDs are ordered when mysqlbinlog outputs
+# Gtid_list events.
+#
+# Methodology:
+# Write multiple events to the binlog with different domain ids and server
+# ids, and ensure that the Gtid_list event GTIDs are ordered first by domain id
+# (ascending), and then sequence number (ascending).
+#
+# References:
+# MDEV-4989: Support for GTID in mysqlbinlog
+#
+--source include/have_log_bin.inc
+
+RESET MASTER;
+SET @@session.gtid_domain_id= 0;
+SET @@session.server_id= 1;
+CREATE TABLE t1 (a int);
+SET @@session.gtid_domain_id= 1;
+SET @@session.server_id= 2;
+CREATE TABLE t2 (a int);
+SET @@session.server_id= 1;
+INSERT INTO t2 VALUES (1);
+SET @@session.gtid_domain_id= 2;
+SET @@session.server_id= 3;
+CREATE TABLE t3 (a int);
+FLUSH LOGS;
+FLUSH LOGS;
+
+--let $binlog_file= query_get_value(SHOW BINARY LOGS, Log_name, 2)
+--let $MYSQLD_DATADIR=`select @@datadir`
+--let SEARCH_FILE=$MYSQLTEST_VARDIR/tmp/tmp_binlog.out
+
+--echo # MYSQL_BINLOG MYSQLD_DATADIR/binlog_file > SEARCH_FILE
+--exec $MYSQL_BINLOG $MYSQLD_DATADIR/$binlog_file > $SEARCH_FILE
+
+--let SEARCH_PATTERN= Gtid list \[0-1-1,\n# 1-2-1,\n# 1-1-2,\n# 2-3-1\]
+--source include/search_pattern_in_file.inc
+
+DROP TABLE t1;
+DROP TABLE t2;
+DROP TABLE t3;
diff --git a/mysql-test/suite/binlog/t/binlog_mysqlbinlog_gtid_strict_mode.test b/mysql-test/suite/binlog/t/binlog_mysqlbinlog_gtid_strict_mode.test
new file mode 100644
index 00000000..16682640
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_mysqlbinlog_gtid_strict_mode.test
@@ -0,0 +1,105 @@
+#
+# Purpose:
+#
+# This test ensures that the mariadb-binlog CLI tool properly displays errors
+# and warnings for out of order GTIDs.
+#
+#
+# Methodology:
+#
+# We simulate invalid sequence numberings by manually changing gtid_seq_no to
+# differ from its expected linear sequence. Specifically, we test the following
+# cases:
+# Test Case 1) Sequential sequence numbers results in no warnings
+# Test Case 2) A skipped sequence number results in no warnings if all numbers
+# are monotonic (i.e. gaps in sequence number are allowed
+# provided they never decrease)
+# Test Case 3) A sequence number lower than the last processed value results
+# in a warning
+# Test Case 4) Skipping a GTID and later receiving it results in a warning
+# Test Case 5) Repeat sequence numbers result in a warning
+# Test Case 6) Warnings from different domains are all displayed
+# Test Case 7) A decreasing seq_no before a start-position is ignored
+# Test Case 8) A decreasing seq_no inside of a --start/--stop position window
+# is displayed
+# Test Case 9) Error if --stop-position is not greater than or equal to
+# --start-position
+# Test Case 10) Strict mode warnings should be independent of --offset option
+# specification
+# Test Case 11) Strict mode warnings should be independent of
+# --start-timestamp option specification
+# Test Case 12) Specifying multiple binary logs with a log-position start
+# should skip GTID state verification
+# Test Case 13) If multiple binary logs should be specified but a middle log
+# is missing, we should detect that and warn when using -vvv
+# Test Case 14) If a --stop-position GTID occurs before the first specified
+# binlog's GLLE, error
+#
+# Note that test cases are tested under three scenarios:
+# 1) --gtid-strict-mode should error and immediately quit with error on out of
+# order GTIDs
+# 2) --skip-gtid-strict-mode -vvv should not quit early or with error when
+# encountering out of order GTIDs; however should produce warnings after
+# binlog processing
+# 3) --skip-gtid-strict-mode should neither produce errors nor warnings when
+# encountering out of order GTIDs
+#
+# References:
+# MDEV-4989: Support for GTID in mysqlbinlog
+#
+
+--source include/have_log_bin.inc
+
+--echo ###############################
+--echo # Test Setup
+--echo ###############################
+
+## Save old state
+#
+let orig_gtid_domain_id = `select @@session.gtid_domain_id`;
+let orig_server_id = `select @@session.server_id`;
+RESET MASTER;
+
+--echo ####################################################
+--echo # Test Case Group 1
+--echo #
+--echo # Tests with --gtid-strict-mode should error and
+--echo # immediately quit with error on out of order GTIDs
+--echo ####################################################
+--let is_strict_mode= 1
+--let is_verbose= 0
+--let DEFAULT_ERROR_PREFIX=ERROR
+--source include/mysqlbinlog_gtid_strict_mode.inc
+
+--echo ####################################################
+--echo # Test Case Group 2
+--echo #
+--echo # Test cases with --skip-gtid-strict-mode -vvv
+--echo # should not quit early or with error when
+--echo # encountering out of order GTIDs; however should
+--echo # produce warnings after binlog processing
+--echo ####################################################
+--let is_strict_mode= 0
+--let is_verbose= 1
+--let DEFAULT_ERROR_PREFIX=WARNING
+--source include/mysqlbinlog_gtid_strict_mode.inc
+
+--echo ####################################################
+--echo # Test Case Group 3
+--echo #
+--echo # Run test cases with --skip-gtid-strict-mode should
+--echo # neither produce errors nor warnings when
+--echo # encountering out of order GTIDs
+--echo ####################################################
+--let is_strict_mode= 0
+--let is_verbose= 0
+--let DEFAULT_ERROR_PREFIX=(ERROR|WARNING)
+--source include/mysqlbinlog_gtid_strict_mode.inc
+
+--echo ##############################
+--echo # Cleanup
+--echo ##############################
+--eval SET @@global.gtid_domain_id= $orig_gtid_domain_id
+--eval SET @@global.server_id= $orig_server_id
+
+--echo End of the tests
diff --git a/mysql-test/suite/binlog/t/binlog_mysqlbinlog_gtid_window.test b/mysql-test/suite/binlog/t/binlog_mysqlbinlog_gtid_window.test
new file mode 100644
index 00000000..3efb8d02
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_mysqlbinlog_gtid_window.test
@@ -0,0 +1,151 @@
+#
+# Purpose:
+#
+# This test ensures that the mariadb-binlog CLI tool can filter log events
+# using GTID ranges. More specifically, this test ensures the following
+# capabilities:
+# 1) GTIDs can be used to filter results on local binlog files
+# 2) GTIDs can be used to filter results from remote servers
+# 3) For a given GTID range, its start-position is exclusive and its
+# stop-position is inclusive. This allows users to receive events strictly
+# after what they already have.
+# 4) After the events have been written, the session server id and domain id
+# are reset to their former values
+#
+#
+# Methodology:
+#
+# This test validates the expected capabilities using the following test cases
+# on both a local binlog file and remote server for all binlog formats.
+# Test Case 1) The end of the binlog file resets the server and domain id of
+# the session
+# Test Case 2) Single GTID range specified
+# Test Case 3) Single GTID range with different server_ids
+# Test Case 4) Multiple GTID ranges specified
+# Test Case 5) Multiple GTID ranges specified where the domain ids are
+# listed in different orders between start/stop position
+# Test Case 6) Only start position specified
+# Test Case 7) Only stop position specified
+# Test Case 8) Seq_no=0 in --start-position includes all events for a domain
+# Test Case 9) Seq_no=0 in --stop-position excludes all events for a domain
+# Test Case 10) Output stops for all domain ids when all --stop-position GTID
+# values have been hit.
+# Test Case 11) All GTID events from other domains are printed until
+# the --stop-position values are hit
+# Test Case 12) Scalar and GTID values can be used together for stop or start
+# position
+# Test Case 13) If the start position is delayed within the binlog, events
+# occurring before that position are ignored
+# Test Case 14) If start position is repeated, the last specification
+# overrides all previous ones
+# Test Case 15) If stop position is repeated, the last specification
+# overrides all previous ones
+# Test Case 16) Start position with --offset=<n> skips n events after the
+# first GTID is found
+# Test Case 17) Start position with --start-datetime=<T> where T occurs
+# after the specified GTID results in no events before T
+# Test Case 18) If --stop-position is specified, domains which are not present
+# in its list should be excluded from output
+# Test Case 19) If the start and stop GTIDs in any domain are equal, the
+# domain should not have any output
+# Test Case 20) If --start-position and --stop-position have different domain
+# ids, only events from GTIDs in the --stop-position list are
+# output
+# Test Case 21) Successive binary logs (e.g. logs with previous logs that
+# have been purged) will write events when the --start-position
+# matches their Gtid_list_log_event state
+# Test Case 22) Successive binary logs can be called with --stop-position and
+# without --start-position
+#
+# To validate for data consistency, each test case compares a checksum of
+# correct data against a variant created after replaying the binlog using
+# --(start|stop)-position. If the checksums are identical, the test passes.
+# If the checksums differ, data has been changed and the test fails.
+#
+# Additionally, this test validates the following error scenarios:
+# Error Case 1) A GTID --start-position that does not mention all domains
+# that make up the binary log state should error
+# Error Case 2) A GTID --start-position with any sequence numbers which
+# occur before the binary log state should result in error
+# Error Case 3) A GTID --start-position with any sequence numbers that are not
+# eventually processed results in error
+# Error Case 4) User provides invalid positions
+# Error Case 5) User provides GTID ranges with repeated domain ids
+#
+# References:
+# MDEV-4989: Support for GTID in mysqlbinlog
+#
+
+--source include/have_log_bin.inc
+
+--echo ###############################
+--echo # Test Setup
+--echo ###############################
+
+## Save old state
+#
+let orig_gtid_domain_id = `select @@session.gtid_domain_id`;
+let orig_server_id = `select @@session.server_id`;
+RESET MASTER;
+
+
+--echo ######################################
+--echo # Test Group 1
+--echo # Run test cases on local log file
+--echo ######################################
+--let is_remote= 0
+--source include/mysqlbinlog_gtid_window_test_cases.inc
+
+--echo ######################################
+--echo # Test Group 2
+--echo # Run test cases on remote host
+--echo ######################################
+--let is_remote= 1
+--source include/mysqlbinlog_gtid_window_test_cases.inc
+
+# Note that error cases 1-3 are in mysqlbinlog_gtid_window_test_cases.inc
+# because we validate for error consistency of GTID state between
+# mariadb-binlog working on local files and receiving errors from a server
+
+--let err_out_= $MYSQLTEST_VARDIR/tmp/err.out
+--let tmp_out_= $MYSQLTEST_VARDIR/tmp/std.out
+
+--let $MYSQLD_DATADIR=`select @@datadir`
+--echo #
+--echo # Error Case 4:
+--echo # User provides invalid positions
+--echo # MYSQL_BINLOG MYSQLD_DATADIR/master-bin.000001 --start-position=z
+--error 1
+--exec $MYSQL_BINLOG $MYSQLD_DATADIR/master-bin.000001 --start-position=z
+
+--echo # MYSQL_BINLOG MYSQLD_DATADIR/master-bin.000001 --start-position=1-
+--error 1
+--exec $MYSQL_BINLOG $MYSQLD_DATADIR/master-bin.000001 --start-position=1-
+
+--echo # MYSQL_BINLOG MYSQLD_DATADIR/master-bin.000001 --start-position=1-2
+--error 1
+--exec $MYSQL_BINLOG $MYSQLD_DATADIR/master-bin.000001 --start-position=1-2
+
+--echo # MYSQL_BINLOG MYSQLD_DATADIR/master-bin.000001 --start-position=1-2-
+--error 1
+--exec $MYSQL_BINLOG $MYSQLD_DATADIR/master-bin.000001 --start-position=1-2-
+
+--echo # MYSQL_BINLOG MYSQLD_DATADIR/master-bin.000001 --start-position=-1
+--error 1
+--exec $MYSQL_BINLOG $MYSQLD_DATADIR/master-bin.000001 --start-position=-1
+
+--echo #
+--echo # Error Case 5:
+--echo # User provides GTID ranges with repeated domain ids
+--echo # MYSQL_BINLOG MYSQLD_DATADIR/master-bin.000001 --start-position=0-1-1,0-1-8 --stop-position=0-1-4,0-1-12
+--error 1
+--exec $MYSQL_BINLOG $MYSQLD_DATADIR/master-bin.000001 --start-position=0-1-1,0-1-8 --stop-position=0-1-4,0-1-12
+
+
+--echo ##############################
+--echo # Cleanup
+--echo ##############################
+--eval SET @@global.gtid_domain_id= $orig_gtid_domain_id
+--eval SET @@global.server_id= $orig_server_id
+
+--echo # End of the tests
diff --git a/mysql-test/suite/binlog/t/binlog_mysqlbinlog_raw_flush.test b/mysql-test/suite/binlog/t/binlog_mysqlbinlog_raw_flush.test
new file mode 100644
index 00000000..252a8577
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_mysqlbinlog_raw_flush.test
@@ -0,0 +1,54 @@
+#
+# Purpose:
+# When using mariadb-binlog with options for --raw and --stop-never, events
+# from the master's currently active log file should be written to their
+# respective log file specified by --result-file, and shown on-disk. This test
+# ensures that the log files on disk, created by mariadb-binlog, have the most
+# up-to-date events from the master.
+# Option --raw works only with --read-from-remote-server, otherwise returns error.
+#
+# Methodology:
+# On the master, rotate to a newly active binlog file and write an event to
+# it. Read the master's binlog using mariadb-binlog with --raw and --stop-never
+# and write the data to an intermediary binlog file (a timeout is used on this
+# command to ensure it exits). Read the local intermediary binlog file to ensure
+# that the master's most recent event exists in the local file.
+#
+# References:
+# MDEV-14608: mysqlbinlog lastest backupfile size is 0
+#
+
+--source include/linux.inc
+--source include/have_log_bin.inc
+
+--echo #
+--echo # MDEV-30698 Cover missing test cases for mariadb-binlog options
+--echo # --raw [and] --flashback
+--echo #
+# Test --raw format without -R (--read-from-remote-server)
+--error 1 # Error 1 operation not permitted
+--exec $MYSQL_BINLOG --raw --user=root --host=127.0.0.1 --port=$MASTER_MYPORT --stop-never --result-file=$MYSQLTEST_VARDIR/tmp/ master-bin.000001
+
+# Create newly active log
+CREATE TABLE t1 (a int);
+FLUSH LOGS;
+INSERT INTO t1 VALUES (1);
+
+# Read binlog data from master to intermediary result file
+--let TIMEOUT=1
+--echo # timeout TIMEOUT MYSQL_BINLOG --raw --read-from-remote-server --user=root --host=127.0.0.1 --port=MASTER_MYPORT --stop-never --result-file=MYSQLTEST_VARDIR/tmp/ master-bin.000001
+--error 124 # Error 124 means timeout was reached
+--exec timeout $TIMEOUT $MYSQL_BINLOG --raw --read-from-remote-server --user=root --host=127.0.0.1 --port=$MASTER_MYPORT --stop-never --result-file=$MYSQLTEST_VARDIR/tmp/ master-bin.000001
+
+# Ensure the binlog output has the most recent events from the master
+--echo # MYSQL_BINLOG MYSQLTEST_VARDIR/tmp/master-bin.000002 > MYSQLTEST_VARDIR/tmp/local-bin.000002.out
+--exec $MYSQL_BINLOG $MYSQLTEST_VARDIR/tmp/master-bin.000002 > $MYSQLTEST_VARDIR/tmp/local-bin.000002.out
+--let SEARCH_PATTERN= GTID 0-1-2
+--let SEARCH_FILE= $MYSQLTEST_VARDIR/tmp/local-bin.000002.out
+--source include/search_pattern_in_file.inc
+
+# Cleanup
+DROP TABLE t1;
+--remove_file $MYSQLTEST_VARDIR/tmp/master-bin.000001
+--remove_file $MYSQLTEST_VARDIR/tmp/master-bin.000002
+--remove_file $MYSQLTEST_VARDIR/tmp/local-bin.000002.out
diff --git a/mysql-test/suite/binlog/t/binlog_mysqlbinlog_row-master.opt b/mysql-test/suite/binlog/t/binlog_mysqlbinlog_row-master.opt
new file mode 100644
index 00000000..4d69f335
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_mysqlbinlog_row-master.opt
@@ -0,0 +1 @@
+--timezone=GMT-3
diff --git a/mysql-test/suite/binlog/t/binlog_mysqlbinlog_row.test b/mysql-test/suite/binlog/t/binlog_mysqlbinlog_row.test
new file mode 100644
index 00000000..113e4ed7
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_mysqlbinlog_row.test
@@ -0,0 +1,491 @@
+--source include/have_log_bin.inc
+--source include/have_binlog_format_row.inc
+--source include/have_ucs2.inc
+
+--echo #
+--echo # Preparatory cleanup.
+--echo #
+--disable_warnings
+DROP TABLE IF EXISTS t1;
+--enable_warnings
+
+--echo #
+--echo # We need a fixed timestamp to avoid varying results.
+--echo #
+SET timestamp=1000000000;
+
+--echo #
+--echo # Delete all existing binary logs.
+--echo #
+RESET MASTER;
+
+
+CREATE TABLE t1 (c01 BIT);
+INSERT INTO t1 VALUES (0);
+INSERT INTO t1 VALUES (1);
+DROP TABLE t1;
+
+CREATE TABLE t1 (c01 BIT(7));
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (8);
+INSERT INTO t1 VALUES (16);
+INSERT INTO t1 VALUES (32);
+INSERT INTO t1 VALUES (64);
+INSERT INTO t1 VALUES (127);
+DELETE FROM t1 WHERE c01=127;
+UPDATE t1 SET c01=15 WHERE c01=16;
+DROP TABLE t1;
+
+CREATE TABLE t1 (a BIT(20), b CHAR(2));
+INSERT INTO t1 VALUES (b'00010010010010001001', 'ab');
+DROP TABLE t1;
+
+CREATE TABLE t1 (c02 BIT(64));
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (128);
+INSERT INTO t1 VALUES (b'1111111111111111111111111111111111111111111111111111111111111111');
+DROP TABLE t1;
+
+
+CREATE TABLE t1 (c03 TINYINT);
+INSERT INTO t1 VALUES (1),(2),(3);
+INSERT INTO t1 VALUES (-128);
+UPDATE t1 SET c03=2 WHERE c03=1;
+DELETE FROM t1 WHERE c03=-128;
+DROP TABLE t1;
+
+CREATE TABLE t1 (c04 TINYINT UNSIGNED);
+INSERT INTO t1 VALUES (128), (255);
+UPDATE t1 SET c04=2 WHERE c04=1;
+DELETE FROM t1 WHERE c04=255;
+DROP TABLE t1;
+
+CREATE TABLE t1 (c06 BOOL);
+INSERT INTO t1 VALUES (TRUE);
+DELETE FROM t1 WHERE c06=TRUE;
+DROP TABLE t1;
+
+CREATE TABLE t1 (c07 SMALLINT);
+INSERT INTO t1 VALUES (1234);
+DELETE FROM t1 WHERE c07=1234;
+DROP TABLE t1;
+
+CREATE TABLE t1 (c08 SMALLINT UNSIGNED);
+INSERT INTO t1 VALUES (32768), (65535);
+UPDATE t1 SET c08=2 WHERE c08=32768;
+DELETE FROM t1 WHERE c08=65535;
+DROP TABLE t1;
+
+CREATE TABLE t1 (c10 MEDIUMINT);
+INSERT INTO t1 VALUES (12345);
+DELETE FROM t1 WHERE c10=12345;
+DROP TABLE t1;
+
+CREATE TABLE t1 (c11 MEDIUMINT UNSIGNED);
+INSERT INTO t1 VALUES (8388608), (16777215);
+UPDATE t1 SET c11=2 WHERE c11=8388608;
+DELETE FROM t1 WHERE c11=16777215;
+DROP TABLE t1;
+
+CREATE TABLE t1 (c13 INT);
+INSERT INTO t1 VALUES (123456);
+DELETE FROM t1 WHERE c13=123456;
+DROP TABLE t1;
+
+CREATE TABLE t1 (c14 INT UNSIGNED);
+INSERT INTO t1 VALUES (2147483648), (4294967295);
+UPDATE t1 SET c14=2 WHERE c14=2147483648;
+DELETE FROM t1 WHERE c14=4294967295;
+DROP TABLE t1;
+
+CREATE TABLE t1 (c16 BIGINT);
+INSERT INTO t1 VALUES (1234567890);
+DELETE FROM t1 WHERE c16=1234567890;
+DROP TABLE t1;
+
+CREATE TABLE t1 (c17 BIGINT UNSIGNED);
+INSERT INTO t1 VALUES (9223372036854775808), (18446744073709551615);
+UPDATE t1 SET c17=2 WHERE c17=9223372036854775808;
+DELETE FROM t1 WHERE c17=18446744073709551615;
+DROP TABLE t1;
+
+CREATE TABLE t1 (c19 FLOAT);
+INSERT INTO t1 VALUES (123.2234);
+DELETE FROM t1 WHERE c19>123;
+DROP TABLE t1;
+
+CREATE TABLE t1 (c22 DOUBLE);
+INSERT INTO t1 VALUES (123434.22344545);
+DELETE FROM t1 WHERE c22>123434;
+DROP TABLE t1;
+
+#
+
+CREATE TABLE t1 (c25 DECIMAL(10,5));
+INSERT INTO t1 VALUES (124.45);
+INSERT INTO t1 VALUES (-543.21);
+DELETE FROM t1 WHERE c25=124.45;
+DROP TABLE t1;
+
+#
+
+CREATE TABLE t1 (c28 DATE);
+INSERT INTO t1 VALUES ('2001-02-03');
+DELETE FROM t1 WHERE c28='2001-02-03';
+DROP TABLE t1;
+
+CREATE TABLE t1 (c29 DATETIME);
+INSERT INTO t1 VALUES ('2001-02-03 10:20:30');
+DELETE FROM t1 WHERE c29='2001-02-03 10:20:30';
+DROP TABLE t1;
+
+CREATE TABLE t1 (c30 TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP);
+INSERT INTO t1 VALUES ('2001-02-03 10:20:30');
+DELETE FROM t1 WHERE c30='2001-02-03 10:20:30';
+DROP TABLE t1;
+
+CREATE TABLE t1 (c31 TIME);
+INSERT INTO t1 VALUES ('11:22:33');
+DELETE FROM t1 WHERE c31='11:22:33';
+DROP TABLE t1;
+
+CREATE TABLE t1 (c32 YEAR);
+INSERT INTO t1 VALUES ('2001');
+DELETE FROM t1 WHERE c32=2001;
+DROP TABLE t1;
+
+#
+
+CREATE TABLE t1 (c33 CHAR);
+INSERT INTO t1 VALUES ('a');
+DELETE FROM t1 WHERE c33='a';
+DROP TABLE t1;
+
+CREATE TABLE t1 (c34 CHAR(0));
+INSERT INTO t1 VALUES ('');
+DELETE FROM t1 WHERE c34='';
+DROP TABLE t1;
+
+CREATE TABLE t1 (c35 CHAR(1));
+INSERT INTO t1 VALUES ('b');
+DELETE FROM t1 WHERE c35='b';
+DROP TABLE t1;
+
+CREATE TABLE t1 (c36 CHAR(255));
+INSERT INTO t1 VALUES (repeat('c',255));
+DELETE FROM t1 WHERE c36>'c';
+DROP TABLE t1;
+
+#
+
+CREATE TABLE t1 (c37 NATIONAL CHAR);
+INSERT INTO t1 VALUES ('a');
+DELETE FROM t1 WHERE c37='a';
+DROP TABLE t1;
+
+CREATE TABLE t1 (c38 NATIONAL CHAR(0));
+INSERT INTO t1 VALUES ('');
+DELETE FROM t1 WHERE c38='';
+DROP TABLE t1;
+
+CREATE TABLE t1 (c39 NATIONAL CHAR(1));
+INSERT INTO t1 VALUES ('a');
+DELETE FROM t1 WHERE c39='a';
+DROP TABLE t1;
+
+CREATE TABLE t1 (c40 NATIONAL CHAR(255));
+INSERT INTO t1 VALUES (repeat('a', 255));
+INSERT INTO t1 VALUES (repeat(_latin1 0xDF, 255));
+DELETE FROM t1 WHERE c40>'a';
+DROP TABLE t1;
+
+#
+
+CREATE TABLE t1 (c41 CHAR CHARACTER SET UCS2);
+INSERT INTO t1 VALUES ('a');
+DELETE FROM t1 WHERE c41='a';
+DROP TABLE t1;
+
+CREATE TABLE t1 (c42 CHAR(0) CHARACTER SET UCS2);
+INSERT INTO t1 VALUES ('');
+DELETE FROM t1 WHERE c42='';
+DROP TABLE t1;
+
+CREATE TABLE t1 (c43 CHAR(1) CHARACTER SET UCS2);
+INSERT INTO t1 VALUES ('a');
+DELETE FROM t1 WHERE c43='a';
+DROP TABLE t1;
+
+CREATE TABLE t1 (c44 CHAR(255) CHARACTER SET UCS2);
+INSERT INTO t1 VALUES (repeat('a', 255));
+INSERT INTO t1 VALUES (repeat(_latin1 0xDF, 255));
+DELETE FROM t1 WHERE c44>'a';
+DROP TABLE t1;
+
+#
+
+CREATE TABLE t1 (c45 VARCHAR(0));
+INSERT INTO t1 VALUES ('');
+DELETE FROM t1 WHERE c45='';
+DROP TABLE t1;
+
+CREATE TABLE t1 (c46 VARCHAR(1));
+INSERT INTO t1 VALUES ('a');
+DELETE FROM t1 WHERE c46='a';
+DROP TABLE t1;
+
+CREATE TABLE t1 (c47 VARCHAR(255));
+INSERT INTO t1 VALUES (repeat('a',255));
+DELETE FROM t1 WHERE c47>'a';
+DROP TABLE t1;
+
+CREATE TABLE t1 (c48 VARCHAR(261));
+INSERT INTO t1 VALUES (repeat('a',261));
+DELETE FROM t1 WHERE c48>'a';
+DROP TABLE t1;
+
+#
+
+CREATE TABLE t1 (c49 NATIONAL VARCHAR(0));
+INSERT INTO t1 VALUES ('');
+DELETE FROM t1 WHERE c49='';
+DROP TABLE t1;
+
+CREATE TABLE t1 (c50 NATIONAL VARCHAR(1));
+INSERT INTO t1 VALUES ('a');
+DELETE FROM t1 WHERE c50='a';
+DROP TABLE t1;
+
+CREATE TABLE t1 (c51 NATIONAL VARCHAR(255));
+INSERT INTO t1 VALUES (repeat('a',255));
+INSERT INTO t1 VALUES (repeat(_latin1 0xDF, 255));
+DELETE FROM t1 WHERE c51>'a';
+DROP TABLE t1;
+
+CREATE TABLE t1 (c52 NATIONAL VARCHAR(261));
+INSERT INTO t1 VALUES (repeat('a',261));
+INSERT INTO t1 VALUES (repeat(_latin1 0xDF, 261));
+DELETE FROM t1 WHERE c52>'a';
+DROP TABLE t1;
+
+#
+
+CREATE TABLE t1 (c53 VARCHAR(0) CHARACTER SET ucs2);
+INSERT INTO t1 VALUES ('');
+DELETE FROM t1 WHERE c53='';
+DROP TABLE t1;
+
+CREATE TABLE t1 (c54 VARCHAR(1) CHARACTER SET ucs2);
+INSERT INTO t1 VALUES ('a');
+DELETE FROM t1 WHERE c54='a';
+DROP TABLE t1;
+
+CREATE TABLE t1 (c55 VARCHAR(255) CHARACTER SET ucs2);
+INSERT INTO t1 VALUES (repeat('ab', 127));
+DELETE FROM t1 WHERE c55>'a';
+DROP TABLE t1;
+
+CREATE TABLE t1 (c56 VARCHAR(261) CHARACTER SET ucs2);
+INSERT INTO t1 VALUES (repeat('ab', 130));
+DELETE FROM t1 WHERE c56>'a';
+DROP TABLE t1;
+
+#
+
+CREATE TABLE t1 (c57 BINARY);
+INSERT INTO t1 VALUES (0x00);
+INSERT INTO t1 VALUES (0x02);
+INSERT INTO t1 VALUES ('a');
+DELETE FROM t1 WHERE c57='a';
+DROP TABLE t1;
+
+CREATE TABLE t1 (c58 BINARY(0));
+INSERT INTO t1 VALUES ('');
+DELETE FROM t1 WHERE c58='';
+DROP TABLE t1;
+
+CREATE TABLE t1 (c59 BINARY(1));
+INSERT INTO t1 VALUES (0x00);
+INSERT INTO t1 VALUES (0x02);
+INSERT INTO t1 VALUES ('a');
+DELETE FROM t1 WHERE c59='a';
+DROP TABLE t1;
+
+CREATE TABLE t1 (c60 BINARY(255));
+INSERT INTO t1 VALUES (0x00);
+INSERT INTO t1 VALUES (0x02);
+INSERT INTO t1 VALUES (repeat('a\0',120));
+DELETE FROM t1 WHERE c60<0x02;
+DROP TABLE t1;
+
+#
+
+CREATE TABLE t1 (c61 VARBINARY(0));
+INSERT INTO t1 VALUES ('');
+DELETE FROM t1 WHERE c61='';
+DROP TABLE t1;
+
+CREATE TABLE t1 (c62 VARBINARY(1));
+INSERT INTO t1 VALUES (0x00);
+INSERT INTO t1 VALUES (0x02);
+INSERT INTO t1 VALUES ('a');
+DELETE FROM t1 WHERE c62=0x02;
+DROP TABLE t1;
+
+CREATE TABLE t1 (c63 VARBINARY(255));
+INSERT INTO t1 VALUES (0x00);
+INSERT INTO t1 VALUES (0x02);
+INSERT INTO t1 VALUES (repeat('a\0',120));
+DELETE FROM t1 WHERE c63=0x02;
+DROP TABLE t1;
+
+#
+
+CREATE TABLE t1 (c65 TINYBLOB);
+INSERT INTO t1 VALUES ('tinyblob1');
+DELETE FROM t1 WHERE c65='tinyblob1';
+DROP TABLE t1;
+
+CREATE TABLE t1 (c68 BLOB);
+INSERT INTO t1 VALUES ('blob1');
+DELETE FROM t1 WHERE c68='blob1';
+DROP TABLE t1;
+
+CREATE TABLE t1 (c71 MEDIUMBLOB);
+INSERT INTO t1 VALUES ('mediumblob1');
+DELETE FROM t1 WHERE c71='mediumblob1';
+DROP TABLE t1;
+
+CREATE TABLE t1 (c74 LONGBLOB);
+INSERT INTO t1 VALUES ('longblob1');
+DELETE FROM t1 WHERE c74='longblob1';
+DROP TABLE t1;
+
+CREATE TABLE t1 (c66 TINYTEXT);
+INSERT INTO t1 VALUES ('tinytext1');
+DELETE FROM t1 WHERE c66='tinytext1';
+DROP TABLE t1;
+
+CREATE TABLE t1 (c69 TEXT);
+INSERT INTO t1 VALUES ('text1');
+DELETE FROM t1 WHERE c69='text1';
+DROP TABLE t1;
+
+CREATE TABLE t1 (c72 MEDIUMTEXT);
+INSERT INTO t1 VALUES ('mediumtext1');
+DELETE FROM t1 WHERE c72='mediumtext1';
+DROP TABLE t1;
+
+CREATE TABLE t1 (c75 LONGTEXT);
+INSERT INTO t1 VALUES ('longtext1');
+DELETE FROM t1 WHERE c75='longtext1';
+DROP TABLE t1;
+
+#
+
+CREATE TABLE t1 (c67 TINYTEXT CHARACTER SET UCS2);
+INSERT INTO t1 VALUES ('tinytext1');
+DELETE FROM t1 WHERE c67='tinytext1';
+DROP TABLE t1;
+
+CREATE TABLE t1 (c70 TEXT CHARACTER SET UCS2);
+INSERT INTO t1 VALUES ('text1');
+DELETE FROM t1 WHERE c70='text1';
+DROP TABLE t1;
+
+CREATE TABLE t1 (c73 MEDIUMTEXT CHARACTER SET UCS2);
+INSERT INTO t1 VALUES ('mediumtext1');
+DELETE FROM t1 WHERE c73='mediumtext1';
+DROP TABLE t1;
+
+CREATE TABLE t1 (c76 LONGTEXT CHARACTER SET UCS2);
+INSERT INTO t1 VALUES ('longtext1');
+DELETE FROM t1 WHERE c76='longtext1';
+DROP TABLE t1;
+
+#
+
+CREATE TABLE t1 (c77 ENUM('a','b','c'));
+INSERT INTO t1 VALUES ('b');
+DELETE FROM t1 WHERE c77='b';
+DROP TABLE t1;
+
+#
+
+CREATE TABLE t1 (c78 SET('a','b','c','d','e','f'));
+INSERT INTO t1 VALUES ('a,b');
+INSERT INTO t1 VALUES ('a,c');
+INSERT INTO t1 VALUES ('b,c');
+INSERT INTO t1 VALUES ('a,b,c');
+INSERT INTO t1 VALUES ('a,b,c,d');
+INSERT INTO t1 VALUES ('a,b,c,d,e');
+INSERT INTO t1 VALUES ('a,b,c,d,e,f');
+DELETE FROM t1 WHERE c78='a,b';
+DROP TABLE t1;
+
+#
+# Check multi-table update
+#
+CREATE TABLE t1 (a int NOT NULL DEFAULT 0, b int NOT NULL DEFAULT 0);
+CREATE TABLE t2 (a int NOT NULL DEFAULT 0, b int NOT NULL DEFAULT 0);
+INSERT INTO t1 SET a=1;
+INSERT INTO t1 SET b=1;
+INSERT INTO t2 SET a=1;
+INSERT INTO t2 SET b=1;
+UPDATE t1, t2 SET t1.a=10, t2.a=20;
+DROP TABLE t1,t2;
+
+--echo #
+--echo # MDEV-20591 Wrong Number of rows in mysqlbinlog output.
+--echo #
+
+CREATE TABLE t1(c_char_utf8 CHAR(10) ,
+ c_varchar_utf8 char(10) ,
+ c_text_utf8 blob );
+
+INSERT into t1 values("B", "B", REPEAT("#", 2000));
+
+drop table t1;
+
+flush logs;
+
+let $MYSQLD_DATADIR= `select @@datadir`;
+
+--copy_file std_data/old_decimal/t1dec102.frm $MYSQLD_DATADIR/test/t1dec102.frm
+--copy_file std_data/old_decimal/t1dec102.MYD $MYSQLD_DATADIR/test/t1dec102.MYD
+--copy_file std_data/old_decimal/t1dec102.MYI $MYSQLD_DATADIR/test/t1dec102.MYI
+
+INSERT INTO t1dec102 VALUES (-999.99);
+INSERT INTO t1dec102 VALUES (0);
+INSERT INTO t1dec102 VALUES (999.99);
+SELECT * FROM t1dec102 ORDER BY a;
+DROP TABLE t1dec102;
+
+flush logs;
+#
+# MDEV-22330: mysqlbinlog stops with an error Don't know how to handle column
+# type: 255 meta: 4 (0004)
+# Check support for GEOMETRY type with verbose mode.
+#
+CREATE TABLE t1 (a GEOMETRY DEFAULT NULL);
+
+INSERT INTO t1 VALUES (NULL);
+INSERT INTO t1 VALUES (POINT(10,10));
+DROP TABLE t1;
+FLUSH LOGS;
+
+--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
+--replace_regex /SQL_LOAD_MB-[0-9]-[0-9]/SQL_LOAD_MB-#-#/ /exec_time=[0-9]*/exec_time=#/ /end_log_pos [0-9]*/end_log_pos #/ /# at [0-9]*/# at #/ /thread_id=[0-9]*/thread_id=#/ /table id [0-9]*/table id #/ /mapped to number [0-9]*/mapped to number #/ /server v [^ ]*/server v #.##.##/ /(@[0-9]*=[0-9]*[.][0-9]{1,3})[0-9e+-]*[^ ]*(.*(FLOAT|DOUBLE).*[*].)/\1...\2/ /CRC32 0x[0-9a-f]*/CRC32 XXX/ /collation_server=[0-9]+/collation_server=X/ /character_set_client=[a-zA-Z0-9]+/character_set_client=X/ /collation_connection=[0-9]+/collation_connection=X/ /xid=\d*/xid=<xid>/
+--exec $MYSQL_BINLOG --base64-output=decode-rows -v -v $MYSQLD_DATADIR/master-bin.000001
+
+--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
+--replace_regex /SQL_LOAD_MB-[0-9]-[0-9]/SQL_LOAD_MB-#-#/ /exec_time=[0-9]*/exec_time=#/ /end_log_pos [0-9]*/end_log_pos #/ /# at [0-9]*/# at #/ /thread_id=[0-9]*/thread_id=#/ /table id [0-9]*/table id #/ /mapped to number [0-9]*/mapped to number #/ /server v [^ ]*/server v #.##.##/ /(@[0-9]*=[0-9]*[.][0-9]{1,3})[0-9e+-]*[^ ]*(.*(FLOAT|DOUBLE).*[*].)/\1...\2/ /CRC32 0x[0-9a-f]*/CRC32 XXX/ /xid=\d*/xid=<xid>/
+--error 1
+--exec $MYSQL_BINLOG --base64-output=decode-rows -v -v $MYSQLD_DATADIR/master-bin.000002 2>&1
+
+--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
+--replace_regex /SQL_LOAD_MB-[0-9]-[0-9]/SQL_LOAD_MB-#-#/ /exec_time=[0-9]*/exec_time=#/ /end_log_pos [0-9]*/end_log_pos #/ /# at [0-9]*/# at #/ /thread_id=[0-9]*/thread_id=#/ /table id [0-9]*/table id #/ /mapped to number [0-9]*/mapped to number #/ /server v [^ ]*/server v #.##.##/ /(@[0-9]*=[0-9]*[.][0-9]{1,3})[0-9e+-]*[^ ]*(.*(FLOAT|DOUBLE).*[*].)/\1...\2/ /CRC32 0x[0-9a-f]*/CRC32 XXX/ /collation_server=[0-9]+/collation_server=X/ /character_set_client=[a-zA-Z0-9]+/character_set_client=X/ /collation_connection=[0-9]+/collation_connection=X/ /xid=\d*/xid=<xid>/
+--exec $MYSQL_BINLOG --base64-output=decode-rows -v -v $MYSQLD_DATADIR/master-bin.000003
diff --git a/mysql-test/suite/binlog/t/binlog_mysqlbinlog_row_frag.test b/mysql-test/suite/binlog/t/binlog_mysqlbinlog_row_frag.test
new file mode 100644
index 00000000..3e18ef1e
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_mysqlbinlog_row_frag.test
@@ -0,0 +1,50 @@
+--source include/have_debug.inc
+--source include/have_binlog_format_row.inc
+
+--let $MYSQLD_DATADIR= `select @@datadir`
+
+CREATE TABLE t (a TEXT);
+# events of interest are guaranteed to stay in 000001 log
+RESET MASTER;
+--eval INSERT INTO t SET a=repeat('a', 1024)
+SELECT a into @a from t;
+FLUSH LOGS;
+DELETE FROM t;
+
+--exec $MYSQL_BINLOG --verbose --debug-binlog-row-event-max-encoded-size=256 $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/mysqlbinlog.sql
+
+--let SEARCH_PATTERN= BINLOG @binlog_fragment_0, @binlog_fragment_1
+--let SEARCH_FILE= $MYSQLTEST_VARDIR/tmp/mysqlbinlog.sql
+--source include/search_pattern_in_file.inc
+
+--exec $MYSQL test < $MYSQLTEST_VARDIR/tmp/mysqlbinlog.sql
+
+SELECT a LIKE @a as 'true' FROM t;
+
+# improper syntax error
+--echo BINLOG number-of-fragments must be exactly two
+--error ER_PARSE_ERROR
+BINLOG @binlog_fragment;
+--error ER_PARSE_ERROR
+BINLOG @binlog_fragment, @binlog_fragment, @binlog_fragment;
+
+# corrupted fragments error check (to the expected error code notice,
+# the same error code occurs in a similar unfragmented case)
+SET @binlog_fragment_0='012345';
+SET @binlog_fragment_1='012345';
+--error ER_SYNTAX_ERROR
+BINLOG @binlog_fragment_0, @binlog_fragment_1;
+
+# Not existing fragment is not allowed
+SET @binlog_fragment_0='012345';
+--error ER_WRONG_TYPE_FOR_VAR
+BINLOG @binlog_fragment_0, @binlog_fragment_not_exist;
+
+# MDEV-22520
+SET @a= '42';
+--error ER_SYNTAX_ERROR
+BINLOG @a, @a;
+
+--echo # Cleanup
+--remove_file $MYSQLTEST_VARDIR/tmp/mysqlbinlog.sql
+DROP TABLE t;
diff --git a/mysql-test/suite/binlog/t/binlog_mysqlbinlog_row_innodb-master.opt b/mysql-test/suite/binlog/t/binlog_mysqlbinlog_row_innodb-master.opt
new file mode 100644
index 00000000..4d69f335
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_mysqlbinlog_row_innodb-master.opt
@@ -0,0 +1 @@
+--timezone=GMT-3
diff --git a/mysql-test/suite/binlog/t/binlog_mysqlbinlog_row_innodb.test b/mysql-test/suite/binlog/t/binlog_mysqlbinlog_row_innodb.test
new file mode 100644
index 00000000..7bd72657
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_mysqlbinlog_row_innodb.test
@@ -0,0 +1,28 @@
+# mysqlbinlog_row_innodb.test
+#
+# Show that mysqlbinlog displays human readable comments to
+# row-based log events.
+#
+# Main module for the InnoDB storage engine.
+#
+# Calls include/mysqlbinlog_row.inc
+# See there for more informaton.
+#
+
+--source include/have_innodb.inc
+let $engine_type=InnoDB;
+
+SET @save_stats_auto_recalc=@@GLOBAL.innodb_stats_auto_recalc;
+SET GLOBAL innodb_stats_auto_recalc=OFF;
+
+#
+# The test case would also work with statement based or mixed mode logging.
+# But this would require different result files. To handle this with the
+# current test suite, new main test cases are required.
+#
+--source include/have_binlog_format_row.inc
+--source include/have_ucs2.inc
+
+--source include/mysqlbinlog_row_engine.inc
+
+SET GLOBAL innodb_stats_auto_recalc=@save_stats_auto_recalc;
diff --git a/mysql-test/suite/binlog/t/binlog_mysqlbinlog_row_myisam-master.opt b/mysql-test/suite/binlog/t/binlog_mysqlbinlog_row_myisam-master.opt
new file mode 100644
index 00000000..4d69f335
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_mysqlbinlog_row_myisam-master.opt
@@ -0,0 +1 @@
+--timezone=GMT-3
diff --git a/mysql-test/suite/binlog/t/binlog_mysqlbinlog_row_myisam.test b/mysql-test/suite/binlog/t/binlog_mysqlbinlog_row_myisam.test
new file mode 100644
index 00000000..e7b03358
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_mysqlbinlog_row_myisam.test
@@ -0,0 +1,23 @@
+# mysqlbinlog_row.test
+#
+# Show that mysqlbinlog displays human readable comments to
+# row-based log events.
+#
+# Main module for the MyISAM storage engine.
+#
+# Calls include/mysqlbinlog_row.inc
+# See there for more informaton.
+#
+
+#--source include/have_myisam.inc
+let $engine_type=MyISAM;
+
+#
+# The test case would also work with statement based or mixed mode logging.
+# But this would require different result files. To handle this with the
+# current test suite, new main test cases are required.
+#
+--source include/have_binlog_format_row.inc
+--source include/have_ucs2.inc
+
+--source include/mysqlbinlog_row_engine.inc
diff --git a/mysql-test/suite/binlog/t/binlog_mysqlbinlog_row_trans-master.opt b/mysql-test/suite/binlog/t/binlog_mysqlbinlog_row_trans-master.opt
new file mode 100644
index 00000000..4d69f335
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_mysqlbinlog_row_trans-master.opt
@@ -0,0 +1 @@
+--timezone=GMT-3
diff --git a/mysql-test/suite/binlog/t/binlog_mysqlbinlog_row_trans.test b/mysql-test/suite/binlog/t/binlog_mysqlbinlog_row_trans.test
new file mode 100644
index 00000000..3b054884
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_mysqlbinlog_row_trans.test
@@ -0,0 +1,159 @@
+# mysqlbinlog_trans.test
+#
+# Show that mysqlbinlog work correctly with transactions.
+#
+
+#--source include/have_myisam.inc
+--let $engine_type_nontrans= MyISAM
+--source include/have_innodb.inc
+--let $engine_type= InnoDB
+
+#
+# The test case would also work with statement based or mixed mode logging.
+# But this would require different result files. To handle this with the
+# current test suite, new main test cases are required.
+#
+--source include/have_binlog_format_row.inc
+
+--source include/have_log_bin.inc
+
+--echo #
+--echo # Preparatory cleanup.
+--echo #
+--disable_warnings
+DROP TABLE IF EXISTS t1, t2;
+--enable_warnings
+
+--echo #
+--echo # We need a fixed timestamp to avoid varying results.
+--echo #
+SET timestamp=1000000000;
+
+--echo #
+--echo # Delete all existing binary logs.
+--echo #
+RESET MASTER;
+
+--echo #
+--echo # Create test tables.
+--echo #
+eval CREATE TABLE t1 (
+ c1 INT,
+ c2 VARCHAR(20)
+ ) ENGINE=$engine_type DEFAULT CHARSET latin1;
+eval CREATE TABLE t2 (
+ c1 INT,
+ c2 VARCHAR(20)
+ ) ENGINE=$engine_type_nontrans DEFAULT CHARSET latin1;
+
+--echo #
+--echo # Start transaction #1, transactional table only, commit.
+--echo #
+START TRANSACTION;
+
+--echo #
+--echo # Do some statements.
+--echo #
+INSERT INTO t1 VALUES (1,'varchar-1'), (2,'varchar-2'), (3,'varchar-3');
+UPDATE t1 SET c1 = c1 + 10;
+DELETE FROM t1 WHERE c1 = 12;
+
+--echo #
+--echo # Commit transaction.
+--echo #
+COMMIT;
+SELECT * FROM t1;
+TRUNCATE TABLE t1;
+
+--echo #
+--echo # Start transaction #2, transactional table only, rollback.
+--echo #
+START TRANSACTION;
+
+--echo #
+--echo # Do some statements.
+--echo #
+INSERT INTO t1 VALUES (1,'varchar-1'), (2,'varchar-2'), (3,'varchar-3');
+UPDATE t1 SET c1 = c1 + 10;
+DELETE FROM t1 WHERE c1 = 12;
+
+--echo #
+--echo # Rollback transaction.
+--echo #
+ROLLBACK;
+SELECT * FROM t1;
+TRUNCATE TABLE t1;
+
+--echo #
+--echo # Start transaction #3, both tables, commit.
+--echo #
+START TRANSACTION;
+
+--echo #
+--echo # Do some statements on the transactional table.
+--echo #
+INSERT INTO t1 VALUES (1,'varchar-1'), (2,'varchar-2'), (3,'varchar-3');
+UPDATE t1 SET c1 = c1 + 10;
+DELETE FROM t1 WHERE c1 = 12;
+
+--echo #
+--echo # Do some statements on the non-transactional table.
+--echo #
+INSERT INTO t2 VALUES (1,'varchar-1'), (2,'varchar-2'), (3,'varchar-3');
+UPDATE t2 SET c1 = c1 + 10;
+DELETE FROM t2 WHERE c1 = 12;
+
+--echo #
+--echo # Commit transaction.
+--echo #
+COMMIT;
+SELECT * FROM t1;
+SELECT * FROM t2;
+TRUNCATE TABLE t1;
+TRUNCATE TABLE t2;
+
+--echo #
+--echo # Start transaction #4, both tables, rollback.
+--echo #
+START TRANSACTION;
+
+--echo #
+--echo # Do some statements on the transactional table.
+--echo #
+INSERT INTO t1 VALUES (1,'varchar-1'), (2,'varchar-2'), (3,'varchar-3');
+UPDATE t1 SET c1 = c1 + 10;
+DELETE FROM t1 WHERE c1 = 12;
+
+--echo #
+--echo # Do some statements on the non-transactional table.
+--echo #
+INSERT INTO t2 VALUES (1,'varchar-1'), (2,'varchar-2'), (3,'varchar-3');
+UPDATE t2 SET c1 = c1 + 10;
+DELETE FROM t2 WHERE c1 = 12;
+
+--echo #
+--echo # Rollback transaction.
+--echo #
+ROLLBACK;
+SELECT * FROM t1;
+SELECT * FROM t2;
+TRUNCATE TABLE t1;
+TRUNCATE TABLE t2;
+
+--echo #
+--echo # Flush all log buffers to the log file.
+--echo #
+FLUSH LOGS;
+
+--echo #
+--echo # Call mysqlbinlog to display the log file contents.
+--echo #
+let $MYSQLD_DATADIR= `select @@datadir`;
+--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
+--replace_regex /SQL_LOAD_MB-[0-9]-[0-9]/SQL_LOAD_MB-#-#/ /exec_time=[0-9]*/exec_time=#/ /end_log_pos [0-9]*/end_log_pos #/ /# at [0-9]*/# at #/ /Xid = [0-9]*/Xid = #/ /thread_id=[0-9]*/thread_id=#/ /table id [0-9]*/table id #/ /mapped to number [0-9]*/mapped to number #/ /server v [^ ]*/server v #.##.##/ /CRC32 0x[0-9a-f]*/CRC32 XXX/ /collation_server=[0-9]+/collation_server=X/ /character_set_client=[a-zA-Z0-9]+/character_set_client=X/ /collation_connection=[0-9]+/collation_connection=X/ /xid=\d*/xid=<xid>/
+--exec $MYSQL_BINLOG --base64-output=decode-rows -v -v $MYSQLD_DATADIR/master-bin.000001
+
+--echo #
+--echo # Cleanup.
+--echo #
+DROP TABLE t1, t2;
diff --git a/mysql-test/suite/binlog/t/binlog_mysqlbinlog_start_alter_verbose.test b/mysql-test/suite/binlog/t/binlog_mysqlbinlog_start_alter_verbose.test
new file mode 100644
index 00000000..338326d1
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_mysqlbinlog_start_alter_verbose.test
@@ -0,0 +1,58 @@
+#
+# Purpose:
+#
+# This test ensures that mysqlbinlog prints a comment when two-phase alter
+# is enabled which shows the original alter query issued.
+#
+#
+# References:
+# MENT-662: Finalize MDEV-11675 "Lag Free Alter On Slave"
+#
+
+# Just row format for faster testing
+--source include/have_binlog_format_row.inc
+--source include/have_innodb.inc
+
+#---
+# Setup
+#---
+--let $binlog_alter_two_phase= `select @@binlog_alter_two_phase`
+set global binlog_alter_two_phase = ON;
+set binlog_alter_two_phase = ON;
+
+RESET MASTER;
+create table myt (a int) engine=InnoDB;
+
+
+#---
+# Issue ALTER
+#---
+alter table myt add column (b int);
+
+
+#---
+# Check binlog output
+#---
+FLUSH LOGS;
+
+--disable_query_log
+--let $MYSQLD_DATADIR= `select @@datadir`
+--let $BINLOG_FILENAME= query_get_value(SHOW BINARY LOGS, Log_name, 1)
+
+--echo # Exec MYSQL_BINLOG --base64-output=decode-rows -v MYSQLD_DATADIR/BINLOG_FILENAME > MYSQLTEST_VARDIR/tmp/mysqlbinlog_verbose.sql
+--exec $MYSQL_BINLOG --base64-output=decode-rows -v $MYSQLD_DATADIR/$BINLOG_FILENAME > $MYSQLTEST_VARDIR/tmp/mysqlbinlog_verbose.sql
+
+create table raw_binlog_rows (txt varchar(1000));
+--eval load data local infile '$MYSQLTEST_VARDIR/tmp/mysqlbinlog_verbose.sql' into table raw_binlog_rows columns terminated by '\n'
+--remove_file $MYSQLTEST_VARDIR/tmp/mysqlbinlog_verbose.sql
+--enable_query_log
+--echo Verbose statements from : $BINLOG_FILENAME
+# Output --verbose lines, with extra Windows CR's trimmed
+select replace(txt,'\r', '') as stmt from raw_binlog_rows where txt like '###%';
+
+#---
+# Cleanup
+#---
+drop table raw_binlog_rows;
+drop table myt;
+--eval set global binlog_alter_two_phase=$binlog_alter_two_phase
diff --git a/mysql-test/suite/binlog/t/binlog_mysqlbinlog_stop_never.test b/mysql-test/suite/binlog/t/binlog_mysqlbinlog_stop_never.test
new file mode 100644
index 00000000..b6a95c2c
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_mysqlbinlog_stop_never.test
@@ -0,0 +1,61 @@
+# ==== Purpose ====
+#
+# Test verifies that continuous streaming of binary log content using the
+# "mysqlbinlog --stop-never" option and sourcing it to mysql client works
+# fine.
+#
+# ==== Implementation ====
+#
+# Steps:
+# 1 - Create a table on a server on which binary log is enabled and insert
+# a row.
+# 2 - Disable the binary log on the server and drop the table.
+# 3 - Capture the binary log output using "mysqlbinlog --stop_never" option
+# and source it to mysql client.
+# 4 - Query the PROCESSLIST table to ensure that the dump thread which is
+# serving "stop_never" option has read entire binlog.
+# 5 - Verify that the table is populated on the server.
+# 6 - Cleanup.
+#
+# ==== References ====
+#
+# MDEV-11154: Write_on_release_cache(log_event.cc) function will not write
+# "COMMIT", if use "mysqlbinlog ... | mysql ..."
+
+--source include/not_windows.inc
+
+# Test is not specific to any binlog format. Hence Running only for 'row'.
+--source include/have_binlog_format_row.inc
+
+# binlog file name is needed in the test. To use master-bin.000001,
+# RESET MASTER is needed.
+RESET MASTER;
+# kill the dump threads if there any dump threads (may be from previous test)
+--source include/stop_dump_threads.inc
+
+--echo # Step-1: Execute some dummy statements.
+CREATE TABLE t1(i int);
+INSERT INTO t1 values (1);
+
+--echo # Step-2: Disable binary log temporarily and drop the table 't1'.
+set @@SESSION.SQL_LOG_BIN = 0;
+DROP TABLE t1;
+set @@SESSION.SQL_LOG_BIN = 1;
+
+--echo # Step-3: Execute MYSQL_BINLOG with --stop-never and source it to mysql client.
+--exec ($MYSQL_BINLOG --read-from-remote-server --stop-never --user=root --host=127.0.0.1 --port=$MASTER_MYPORT master-bin.000001 | $MYSQL --user=root --protocol=tcp --host=127.0.0.1 --port=$MASTER_MYPORT) < /dev/null > /dev/null 2>&1 &
+
+--echo # Step-4: Wait till dump thread transfer is completed.
+let $wait_condition= SELECT id from information_schema.processlist where processlist.command like '%Binlog%' and state like '%Master has sent%';
+--source include/wait_condition.inc
+
+--echo # Step-5: Check that the data is there.
+let $count= 1;
+let $table= test.t1;
+source include/wait_until_rows_count.inc;
+
+--echo # Step-6: Cleanup
+--echo # kill the dump thread serving the mysqlbinlog --stop-never process
+--source include/stop_dump_threads.inc
+
+DROP TABLE t1;
diff --git a/mysql-test/suite/binlog/t/binlog_mysqlbinlog_suppress_O_TMPFILE.test b/mysql-test/suite/binlog/t/binlog_mysqlbinlog_suppress_O_TMPFILE.test
new file mode 100644
index 00000000..c97269a8
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_mysqlbinlog_suppress_O_TMPFILE.test
@@ -0,0 +1,51 @@
+# ==== Purpose ====
+#
+# Suppress the following informational note that gets printed to standard
+# error when O_TMPFILE flag is not supported by underlying operating system.
+#
+# Note: ../client/mysqlbinlog: O_TMPFILE is not supported on /tmp (disabling
+# future attempts)
+#
+# Step 1: Generate a binarylog file with a size greater than 1MB.
+# Step 2: Use mysqlbinlog tool to generate sql file and redirect the standard
+# error to standard output (2>&1)
+# Step 3: Source the generated sql file as inpurt to mysql client, observe no
+# syntax error is reported.
+#
+# ==== References ====
+#
+# MDEV-23846: O_TMPFILE error in mysqlbinlog stream output breaks restore
+#
+--source include/have_binlog_format_row.inc
+
+RESET MASTER;
+CREATE TABLE t(f text);
+INSERT INTO t VALUES (repeat('x',4096));
+INSERT INTO t SELECT * FROM t;
+INSERT INTO t SELECT * FROM t;
+INSERT INTO t SELECT * FROM t;
+INSERT INTO t SELECT * FROM t;
+INSERT INTO t SELECT * FROM t;
+INSERT INTO t SELECT * FROM t;
+INSERT INTO t SELECT * FROM t;
+INSERT INTO t SELECT * FROM t;
+INSERT INTO t SELECT * FROM t;
+SELECT COUNT(*) FROM t;
+FLUSH LOGS;
+let $MYSQLD_DATADIR= `select @@datadir`;
+
+--exec $MYSQL_BINLOG $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/mysqlbinlog_base64.sql 2>&1
+#
+# Clear database and restore from binlog
+#
+DROP TABLE t;
+
+--exec $MYSQL test < $MYSQLTEST_VARDIR/tmp/mysqlbinlog_base64.sql
+
+--echo # 512- Rows must be present
+--let $assert_cond= COUNT(*) = 512 FROM t
+--let $assert_text= Table t should have 512 rows.
+--source include/assert.inc
+
+DROP TABLE t;
+RESET MASTER;
diff --git a/mysql-test/suite/binlog/t/binlog_no_uniqfile_crash.test b/mysql-test/suite/binlog/t/binlog_no_uniqfile_crash.test
new file mode 100644
index 00000000..cb8b1078
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_no_uniqfile_crash.test
@@ -0,0 +1,83 @@
+# ==== Purpose ====
+#
+# Test verifies that when RESET MASTER TO # command is supplied with binlog
+# extension number greater than 2147483647 the command should report
+# appropriate error and binary log should be disabled. It should not result in
+# a crash.
+#
+# ==== Implementation ====
+#
+# Steps:
+# 0 - Verify case with max binary log extension. Max value is '2147483647'
+# 1 - Confirm that SHOW BINARY LOGS displays a binary log with '2147483647'
+# 2 - Verify that events are successfully written into max extension file.
+# 3 - Try to create a binary log with extension greater than max allowed
+# value '2147483648', verify ER_NO_UNIQUE_LOGFILE error is reported.
+# 4 - Execute CREATE DATABASE db2 statement and verify server dosn't crash.
+# 5 - Execute SHOW BINARY LOG command and verify that it reports
+# ER_NO_BINARY_LOGGING error.
+# 6 - Restart the server and verify that databse 'db2' exists and it it not
+# present in the binary log.
+#
+# ==== References ====
+#
+# MDEV-22451: SIGSEGV in __memmove_avx_unaligned_erms/memcpy from
+# _my_b_write on CREATE after RESET MASTER
+#
+--source include/have_log_bin.inc
+
+call mtr.add_suppression("Next log extension: 2147483647. Remaining log filename extensions: 0");
+call mtr.add_suppression("Log filename extension number exhausted:.");
+call mtr.add_suppression("Can't generate a unique log-filename");
+call mtr.add_suppression("MYSQL_BIN_LOG::open failed to generate new file name.");
+call mtr.add_suppression("Could not use master-bin for logging");
+
+
+--echo "Test case verifies creation of binary log with max entension value."
+RESET MASTER TO 2147483647;
+--source include/show_binary_logs.inc
+
+# Check error log for correct messages.
+let $log_error_= `SELECT @@GLOBAL.log_error`;
+if(!$log_error_)
+{
+ # MySQL Server on windows is started with --console and thus
+ # does not know the location of its .err log, use default location
+ let $log_error_ = $MYSQLTEST_VARDIR/log/mysqld.1.err;
+}
+
+--let SEARCH_FILE=$log_error_
+--let SEARCH_PATTERN=Next log extension: 2147483647. Remaining log filename extensions: 0.
+--source include/search_pattern_in_file.inc
+
+CREATE DATABASE db1;
+--source include/show_binlog_events.inc
+
+--error ER_NO_UNIQUE_LOGFILE
+RESET MASTER TO 2147483648;
+
+--let SEARCH_FILE=$log_error_
+--let SEARCH_PATTERN=Turning logging off for the whole duration of the MariaDB server process
+--source include/search_pattern_in_file.inc
+
+--echo "Following CREATE DATABSE db2 command will not be present in binary log"
+--echo "as binary log got closed due to ER_NO_UNIQUE_LOGFILE error."
+CREATE DATABASE db2;
+
+
+--echo "RESET MASTER command fails to generate a new binary log"
+--echo "log-bin will be disabled and server needs to be restarted to"
+--echo "re-enable the binary log."
+--error ER_NO_BINARY_LOGGING
+SHOW BINARY LOGS;
+
+--source include/restart_mysqld.inc
+
+--source include/show_binary_logs.inc
+SHOW DATABASES LIKE 'db%';
+--source include/show_binlog_events.inc
+
+# Cleanup
+DROP DATABASE db1;
+DROP DATABASE db2;
+--source include/show_binlog_events.inc
diff --git a/mysql-test/suite/binlog/t/binlog_old_versions.test b/mysql-test/suite/binlog/t/binlog_old_versions.test
new file mode 100644
index 00000000..13010154
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_old_versions.test
@@ -0,0 +1,153 @@
+# Test that old binlog formats can be read.
+
+# Some previous versions of MySQL use their own binlog format,
+# especially in row-based replication. This test uses saved binlogs
+# from those old versions to test that we can replicate from old
+# versions to the present version.
+
+# Replicating from old versions to new versions is necessary in an
+# online upgrade scenario, where the .
+
+# The previous versions we currently test are:
+# - version 5.1.17 and earlier trees
+# - mysql-5.1-wl2325-xxx trees (AKA alcatel trees)
+# - mysql-5.1-telco-6.1 trees
+# For completeness, we also test mysql-5.1-new_rpl, which is supposed
+# to be the "correct" version.
+
+# All binlogs were generated with the same commands (listed at the end
+# of this test for reference). The binlogs contain the following
+# events: Table_map, Write_rows, Update_rows, Delete_rows Query, Xid,
+# User_var, Int_var, Rand, Begin_load, Append_file, Execute_load.
+
+# Related bugs: BUG#27779, BUG#31581, BUG#31582, BUG#31583, BUG#32407
+
+source include/not_embedded.inc;
+
+--echo ==== Read binlog with v2 row events ====
+
+# Read binlog.
+--exec $MYSQL_BINLOG --local-load=$MYSQLTEST_VARDIR/tmp/ suite/binlog/std_data/ver_trunk_row_v2.001 | $MYSQL --local-infile=1
+# Show result.
+SELECT * FROM t1 ORDER BY a;
+SELECT * FROM t2 ORDER BY a;
+SELECT COUNT(*) FROM t3;
+# Reset.
+DROP TABLE t1, t2, t3;
+
+
+--echo ==== Read modern binlog (version 5.1.23) ====
+
+# Read binlog.
+--exec $MYSQL_BINLOG --local-load=$MYSQLTEST_VARDIR/tmp/ suite/binlog/std_data/ver_5_1_23.001 | $MYSQL --local-infile=1
+# Show result.
+SELECT * FROM t1 ORDER BY a;
+SELECT * FROM t2 ORDER BY a;
+SELECT COUNT(*) FROM t3;
+# Reset.
+DROP TABLE t1, t2, t3;
+
+
+--echo ==== Read binlog from version 5.1.17 ====
+
+# Read binlog.
+--exec $MYSQL_BINLOG --local-load=$MYSQLTEST_VARDIR/tmp/ suite/binlog/std_data/ver_5_1_17.001 | $MYSQL --local-infile=1
+# Show result.
+SELECT * FROM t1 ORDER BY a;
+SELECT * FROM t2 ORDER BY a;
+SELECT COUNT(*) FROM t3;
+# Reset.
+DROP TABLE t1, t2, t3;
+
+
+--echo ==== Read binlog from version 4.1 ====
+
+# In this version, neither row-based binlogging nor Xid events
+# existed, so the binlog was generated without the "row-based tests"
+# part and the "get xid event" part, and it does not create table t2.
+
+# Read binlog.
+--exec $MYSQL_BINLOG --local-load=$MYSQLTEST_VARDIR/tmp/ suite/binlog/std_data/binlog_old_version_4_1.000001 | $MYSQL --local-infile=1
+# Show result.
+SELECT * FROM t1 ORDER BY a;
+SELECT COUNT(*) FROM t3;
+# Reset.
+DROP TABLE t1, t3;
+
+
+--echo ==== Read binlog from telco tree (mysql-5.1-telco-6.1) ====
+
+# Read binlog.
+--exec $MYSQL_BINLOG --local-load=$MYSQLTEST_VARDIR/tmp/ suite/binlog/std_data/ver_5_1-telco.001 | $MYSQL --local-infile=1
+# Show resulting tablea.
+SELECT * FROM t1 ORDER BY a;
+SELECT * FROM t2 ORDER BY a;
+SELECT COUNT(*) FROM t3;
+# Reset.
+DROP TABLE t1, t2, t3;
+
+
+#### The following commands were used to generate the binlogs ####
+#
+#source include/master-slave.inc;
+#
+## ==== initialize ====
+#USE test;
+#CREATE TABLE t1 (a int, b char(50)) ENGINE = MyISAM;
+#CREATE TABLE t2 (a int, b char(50)) ENGINE = InnoDB;
+#CREATE TABLE t3 (a char(20));
+#
+#
+## ==== row based tests ====
+#SET BINLOG_FORMAT='row';
+#
+## ---- get write, update, and delete rows events ----
+#INSERT INTO t1 VALUES (0, 'one'), (1, 'two');
+#UPDATE t1 SET a=a+1;
+#DELETE FROM t1 WHERE a=2;
+#
+#
+## ==== statement based tests ====
+#SET BINLOG_FORMAT = 'statement';
+#
+## ---- get xid events ----
+#BEGIN;
+#INSERT INTO t2 VALUES (3, 'first stm in trx');
+#INSERT INTO t1 VALUES (3, 'last stm in trx: next event should be xid');
+#COMMIT;
+#
+## ---- get user var events ----
+#SET @x = 4;
+#INSERT INTO t1 VALUES (@x, 'four');
+#
+## ---- get rand event ----
+#INSERT INTO t1 VALUES (RAND() * 1000000, 'random');
+#
+## ---- get intvar event ----
+#INSERT INTO t1 VALUES (LAST_INSERT_ID(), 'last_insert_id');
+#
+## ---- get begin, append and execute load events ----
+## double the file until we have more than 2^17 bytes, so that the
+## event has to be split and we can use Append_file_log_event.
+#
+#SET SQL_LOG_BIN=0;
+#CREATE TABLE temp (a char(20));
+#LOAD DATA INFILE '../std_data_ln/words.dat' INTO TABLE temp;
+#INSERT INTO temp SELECT * FROM temp;
+#INSERT INTO temp SELECT * FROM temp;
+#INSERT INTO temp SELECT * FROM temp;
+#INSERT INTO temp SELECT * FROM temp;
+#INSERT INTO temp SELECT * FROM temp;
+#INSERT INTO temp SELECT * FROM temp;
+#INSERT INTO temp SELECT * FROM temp;
+#INSERT INTO temp SELECT * FROM temp;
+#SELECT a FROM temp INTO OUTFILE 'big_file.dat';
+#DROP TABLE temp;
+#SET SQL_LOG_BIN=1;
+#
+#LOAD DATA INFILE 'big_file.dat' INTO TABLE t3;
+#
+#SELECT * FROM t1 ORDER BY a;
+#SELECT * FROM t2 ORDER BY a;
+#SELECT COUNT(*) FROM t3;
+#--source include/rpl_end.inc
diff --git a/mysql-test/suite/binlog/t/binlog_parallel_replication_ddl.test b/mysql-test/suite/binlog/t/binlog_parallel_replication_ddl.test
new file mode 100644
index 00000000..d861ecc9
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_parallel_replication_ddl.test
@@ -0,0 +1,30 @@
+# Check binlog properties of various DDL:s.
+# Motivated by MDEV-27365.
+#
+--source include/have_log_bin.inc
+--source include/have_binlog_format_mixed.inc
+
+RESET MASTER;
+
+# MDEV-27365 CREATE-or-REPLACE SEQUENCE bilogged without DDL flag
+# Prove it is logged with the DDL flag.
+CREATE OR REPLACE SEQUENCE s1;
+
+# This one has been always correct.
+DROP SEQUENCE s1;
+FLUSH LOGS;
+
+--let $MYSQLD_DATADIR= `select @@datadir`
+--exec $MYSQL_BINLOG --base64-output=decode-rows $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/mysqlbinlog.sql
+
+--let SEARCH_PATTERN= GTID [0-9]+-[0-9]+-[0-9]+
+--let SEARCH_FILE= $MYSQLTEST_VARDIR/tmp/mysqlbinlog.sql
+--source include/search_pattern_in_file.inc
+
+--echo The same as above number of samples must be found:
+--let SEARCH_PATTERN= GTID [0-9]+-[0-9]+-[0-9]+ ddl
+--let SEARCH_FILE= $MYSQLTEST_VARDIR/tmp/mysqlbinlog.sql
+--source include/search_pattern_in_file.inc
+--remove_file $MYSQLTEST_VARDIR/tmp/mysqlbinlog.sql
+
+--echo End of the tests
diff --git a/mysql-test/suite/binlog/t/binlog_parallel_replication_marks_row.test b/mysql-test/suite/binlog/t/binlog_parallel_replication_marks_row.test
new file mode 100644
index 00000000..82898486
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_parallel_replication_marks_row.test
@@ -0,0 +1,3 @@
+--source include/have_log_bin.inc
+--source include/have_binlog_format_row.inc
+--source include/binlog_parallel_replication_marks.test
diff --git a/mysql-test/suite/binlog/t/binlog_parallel_replication_marks_stm_mix.test b/mysql-test/suite/binlog/t/binlog_parallel_replication_marks_stm_mix.test
new file mode 100644
index 00000000..15042b3a
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_parallel_replication_marks_stm_mix.test
@@ -0,0 +1,3 @@
+--source include/have_log_bin.inc
+--source include/have_binlog_format_mixed_or_statement.inc
+--source include/binlog_parallel_replication_marks.test
diff --git a/mysql-test/suite/binlog/t/binlog_query_filter_rules-master.opt b/mysql-test/suite/binlog/t/binlog_query_filter_rules-master.opt
new file mode 100644
index 00000000..33632bf9
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_query_filter_rules-master.opt
@@ -0,0 +1 @@
+--replicate-do-db='impossible_database'
diff --git a/mysql-test/suite/binlog/t/binlog_query_filter_rules.test b/mysql-test/suite/binlog/t/binlog_query_filter_rules.test
new file mode 100644
index 00000000..d56a32ce
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_query_filter_rules.test
@@ -0,0 +1,32 @@
+# regression test for
+# Bug#36099 replicate-do-db affects replaying RBR events with mysqlbinlog
+# The test verifies that the slave side filtering rule does not affect
+# applying of row-events on master via mysqlbinlog
+
+-- source include/have_log_bin.inc
+-- source include/not_embedded.inc
+-- source include/have_binlog_format_row.inc
+
+--disable_warnings
+drop table if exists t1;
+--enable_warnings
+
+reset master;
+
+create table t1 (a int);
+insert into t1 values (1);
+
+let $MYSQLD_DATADIR= `select @@datadir`;
+flush logs;
+--exec $MYSQL_BINLOG $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/bug36099.sql
+
+drop table t1;
+--exec $MYSQL -e "source $MYSQLTEST_VARDIR/tmp/bug36099.sql"
+
+--echo *** must be 1 ***
+select * from t1;
+
+# cleanup
+
+drop table t1;
+remove_file $MYSQLTEST_VARDIR/tmp/bug36099.sql;
diff --git a/mysql-test/suite/binlog/t/binlog_recover_checksum_error.test b/mysql-test/suite/binlog/t/binlog_recover_checksum_error.test
new file mode 100644
index 00000000..12c9f3d9
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_recover_checksum_error.test
@@ -0,0 +1,37 @@
+# The test verifies server binlog-based recovery.
+#
+# MDEV-23832 checksum error at server binlog recovery should not crash
+
+# The test logic really requires --log-bin.
+--source include/have_binlog_format_mixed.inc
+--source include/have_debug.inc
+
+--let $do_checksum = `SELECT @@global.master_verify_checksum`
+--let $debug_dbug_saved = `SELECT @@global.debug_dbug`
+--let $binlog_checksum = `SELECT @@global.binlog_checksum`
+set @@global.binlog_checksum = CRC32;
+
+call mtr.add_suppression("Replication event checksum verification failed");
+call mtr.add_suppression("Error in Log_event::read_log_event");
+
+# Proof of no crash follows.
+# There's no need for actual bin-loggable queries to the server
+--let $restart_parameters= --master_verify_checksum=ON --debug_dbug="+d,corrupt_read_log_event_char"
+--let $shutdown_timeout=0
+--source include/restart_mysqld.inc
+--let $restart_parameters=
+--let $shutdown_timeout=
+
+#
+# Cleanup
+
+--replace_regex /= .*/= VALUE/
+--eval set @@global.debug_dbug = "$debug_dbug_saved"
+
+--replace_result $do_checksum DO_CHECKSUM
+--eval set @@global.master_verify_checksum = $do_checksum
+--replace_result $binlog_checksum BINLOG_CHECKSUM
+--eval set @@global.binlog_checksum = $binlog_checksum
+#
+--echo # EOF the test
+#
diff --git a/mysql-test/suite/binlog/t/binlog_rotate_perf.test b/mysql-test/suite/binlog/t/binlog_rotate_perf.test
new file mode 100644
index 00000000..74c91fec
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_rotate_perf.test
@@ -0,0 +1,102 @@
+# ==== Purpose ====
+#
+# functional test for open_binlog call using when
+#
+# flush log reset master/slave called
+#
+# ==== Related ====
+#
+# TXSQL feature 67 binlog rotate perf optimization
+
+let $engine= myisam;
+
+--source include/have_binlog_format_row.inc
+--connect(conn1,localhost,root,,test)
+
+reset master;
+create database test_rotate_db;
+use test_rotate_db;
+--echo #currrent engine=$engine
+# Create a new table
+--replace_column 2 #
+show binary logs;
+--eval CREATE TABLE t1_$engine (c1 INT) ENGINE=$engine
+--eval insert into t1_$engine values(0),(1)
+
+# do batch flush and show
+let $loop_times= 100;
+--source include/show_master_status.inc
+while ($loop_times) {
+ flush logs;
+ flush logs;
+ if ($loop_times < 5)
+ {
+ --source include/show_master_status.inc
+ if ($loop_times == 4)
+ {
+ --source include/show_binary_logs.inc
+ }
+ reset master;
+ }
+ if ($loop_times >= 5)
+ {
+ flush logs;
+ }
+
+ #
+ dec $loop_times;
+ --echo # left times= $loop_times
+}
+--echo # [engine=$engine] after first loop_times=$loop_times, show master logs results
+--source include/show_binary_logs.inc
+
+# do batch flush and show with restart mysql
+--source include/show_master_status.inc
+let $loop_times= 10;
+while ($loop_times) {
+ flush logs;
+ flush logs;
+ --echo #begin to restart mysqld current loop_times=$loop_times
+ --source include/restart_mysqld.inc
+ #
+ dec $loop_times;
+ --echo # left restart times= $loop_times
+}
+--echo # [engine=$engine] after second loop_times=$loop_times, show master logs results
+--source include/show_binary_logs.inc
+
+
+# try to change the log-bin configs and restart
+--echo # ======= now try to change the log-bin config for mysqld =======
+--let $restart_parameters="--log-bin=new_log_bin"
+--echo #begin to restart mysqld
+--source include/restart_mysqld.inc
+--let $restart_parameters= ""
+
+--source include/show_binary_logs.inc
+let $loop_times= 10;
+while ($loop_times) {
+ flush logs;
+ flush logs;
+ if ($loop_times < 5)
+ {
+ if ($loop_times == 4)
+ {
+ --source include/show_binary_logs.inc
+ }
+ reset master;
+ }
+ if ($loop_times >= 5)
+ {
+ flush logs;
+ }
+
+ #
+ dec $loop_times;
+ --echo # left times= $loop_times
+}
+--echo # [engine=$engine] after third loop_times=$loop_times, show master logs results
+--source include/show_binary_logs.inc
+
+##cleanup
+drop database test_rotate_db;
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 00000000..24d88646
--- /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 00000000..a6e5f828
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_row_annotate.test
@@ -0,0 +1 @@
+--source include/binlog_row_annotate.inc
diff --git a/mysql-test/suite/binlog/t/binlog_row_binlog-master.opt b/mysql-test/suite/binlog/t/binlog_row_binlog-master.opt
new file mode 100644
index 00000000..e4c44226
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_row_binlog-master.opt
@@ -0,0 +1 @@
+--max_binlog_size=8192 --default-storage-engine=MyISAM
diff --git a/mysql-test/suite/binlog/t/binlog_row_binlog.test b/mysql-test/suite/binlog/t/binlog_row_binlog.test
new file mode 100644
index 00000000..7fa6a2ce
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_row_binlog.test
@@ -0,0 +1,7 @@
+# This is a wrapper for binlog.test so that the same test case can be used
+# For both statement and row based bin logs 9/19/2005 [jbm]
+
+-- source include/have_binlog_format_row.inc
+let collation=utf8mb3_unicode_ci;
+--source include/have_collation.inc
+--source include/binlog.test
diff --git a/mysql-test/suite/binlog/t/binlog_row_cache_stat.test b/mysql-test/suite/binlog/t/binlog_row_cache_stat.test
new file mode 100644
index 00000000..6f406119
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_row_cache_stat.test
@@ -0,0 +1,5 @@
+# This is a wrapper for binlog.test so that the same test case can be used
+# For both statement and row based bin logs 9/19/2005 [jbm]
+
+-- source include/have_binlog_format_row.inc
+-- source include/binlog_cache_stat.test
diff --git a/mysql-test/suite/binlog/t/binlog_row_ctype_cp932.test b/mysql-test/suite/binlog/t/binlog_row_ctype_cp932.test
new file mode 100644
index 00000000..b99afb6c
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_row_ctype_cp932.test
@@ -0,0 +1,5 @@
+# This is a wrapper for binlog.test so that the same test case can be used
+# For both statement and row based bin logs 9/19/2005 [jbm]
+
+-- source include/have_binlog_format_row.inc
+-- source include/ctype_cp932.test
diff --git a/mysql-test/suite/binlog/t/binlog_row_ctype_ucs.test b/mysql-test/suite/binlog/t/binlog_row_ctype_ucs.test
new file mode 100644
index 00000000..02a9b647
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_row_ctype_ucs.test
@@ -0,0 +1,6 @@
+# This is a wrapper for binlog.test so that the same test case can be used
+# For both statement and row based bin logs 9/19/2005 [jbm]
+
+-- source include/have_binlog_format_row.inc
+-- source include/ctype_ucs_binlog.test
+
diff --git a/mysql-test/suite/binlog/t/binlog_row_drop_tbl.test b/mysql-test/suite/binlog/t/binlog_row_drop_tbl.test
new file mode 100644
index 00000000..82853065
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_row_drop_tbl.test
@@ -0,0 +1,5 @@
+# This is a wrapper for drop_table.test so that the same test case can be used
+# For both statement and row based bin logs
+
+-- source include/have_binlog_format_row.inc
+-- source include/drop_table.test
diff --git a/mysql-test/suite/binlog/t/binlog_row_drop_tmp_tbl.test b/mysql-test/suite/binlog/t/binlog_row_drop_tmp_tbl.test
new file mode 100644
index 00000000..e45e659c
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_row_drop_tmp_tbl.test
@@ -0,0 +1,5 @@
+# This is a wrapper for binlog.test so that the same test case can be used
+# For both statement and row based bin logs 9/19/2005 [jbm]
+
+-- source include/have_binlog_format_row.inc
+-- source include/drop_temp_table.test
diff --git a/mysql-test/suite/binlog/t/binlog_row_innodb_stat-master.opt b/mysql-test/suite/binlog/t/binlog_row_innodb_stat-master.opt
new file mode 100644
index 00000000..4cb92754
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_row_innodb_stat-master.opt
@@ -0,0 +1 @@
+--binlog_cache_size=32768
diff --git a/mysql-test/suite/binlog/t/binlog_row_insert_select.test b/mysql-test/suite/binlog/t/binlog_row_insert_select.test
new file mode 100644
index 00000000..e2a08536
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_row_insert_select.test
@@ -0,0 +1,10 @@
+# This is a wrapper for binlog.test so that the same test case can be used
+# For both statement and row based bin logs 9/19/2005 [jbm]
+
+-- source include/have_binlog_format_row.inc
+# 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
+# we disable the ps-protocol for this statement.
+--disable_ps_protocol
+-- source include/insert_select-binlog.test
+--enable_ps_protocol
diff --git a/mysql-test/suite/binlog/t/binlog_row_mix_innodb_myisam-master.opt b/mysql-test/suite/binlog/t/binlog_row_mix_innodb_myisam-master.opt
new file mode 100644
index 00000000..a177f285
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_row_mix_innodb_myisam-master.opt
@@ -0,0 +1 @@
+--loose-innodb-lock-wait-timeout=2 --default-storage-engine=MyISAM
diff --git a/mysql-test/suite/binlog/t/binlog_row_mix_innodb_myisam.test b/mysql-test/suite/binlog/t/binlog_row_mix_innodb_myisam.test
new file mode 100644
index 00000000..9692c6ee
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_row_mix_innodb_myisam.test
@@ -0,0 +1,15 @@
+# This is a wrapper for binlog.test so that the same test case can be used
+# For both statement and row based bin logs 9/19/2005 [jbm]
+
+-- source include/have_binlog_format_row.inc
+
+# 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
+# we disable the ps-protocol for this statement.
+--disable_ps_protocol
+
+-- source include/mix_innodb_myisam_binlog.test
+
+--enable_ps_protocol
+
+-- source include/mix_innodb_myisam_side_effects.test
diff --git a/mysql-test/suite/binlog/t/binlog_row_mysqlbinlog_db_filter.test b/mysql-test/suite/binlog/t/binlog_row_mysqlbinlog_db_filter.test
new file mode 100644
index 00000000..2e3e53b8
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_row_mysqlbinlog_db_filter.test
@@ -0,0 +1,148 @@
+# BUG#42941: --database parameter to mysqlbinlog fails with RBR
+#
+# WHAT
+# ====
+#
+# This test aims at checking whether a rows log event is printed or
+# not when --database parameter is used to filter events from one
+# given database.
+#
+# HOW
+# ===
+#
+# The test is implemented as follows:
+#
+# i) Some operations are done in two different databases:
+# 'test' and 'b42941';
+# ii) mysqlbinlog is used to dump the contents of the binlog file
+# filtering only events from 'b42941'. The result of the dump is
+# stored in a temporary file. (This is done with and without
+# --verbose/hexdump flag);
+# iii) The contents of the dump are loaded into a session variable;
+# iv) The variable contents are searched for 'test' and 'b42941';
+# v) Should 'test' be found, an ERROR is reported. Should 'b42941' be
+# absent, an ERROR is reported.
+
+-- source include/have_log_bin.inc
+-- source include/have_binlog_format_row.inc
+-- source include/have_innodb.inc
+
+RESET MASTER;
+-- let $MYSQLD_DATADIR= `select @@datadir`
+
+CREATE TABLE t1 (id int);
+CREATE TABLE t2 (id int);
+CREATE TABLE t3 (txt TEXT);
+CREATE TABLE t4 (a int) ENGINE= InnoDB;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t2 VALUES (1);
+INSERT INTO t2 VALUES (2);
+INSERT INTO t1 VALUES (3);
+-- replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
+-- eval LOAD DATA INFILE '$MYSQLTEST_VARDIR/std_data/words.dat' INTO TABLE t3
+INSERT INTO t1 VALUES (4);
+
+CREATE DATABASE b42941;
+use b42941;
+CREATE TABLE t1 (id int);
+CREATE TABLE t2 (id int);
+CREATE TABLE t3 (txt TEXT);
+CREATE TABLE t4 (a int) ENGINE= InnoDB;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t2 VALUES (1);
+INSERT INTO t2 VALUES (2);
+INSERT INTO t1 VALUES (3);
+-- replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
+-- eval LOAD DATA INFILE '$MYSQLTEST_VARDIR/std_data/words.dat' INTO TABLE t3
+INSERT INTO t1 VALUES (4);
+
+INSERT INTO test.t1 VALUES (5);
+
+FLUSH LOGS;
+
+UPDATE test.t1 t11, b42941.t1 t12 SET t11.id=10, t12.id=100;
+
+BEGIN;
+INSERT INTO test.t4 VALUES (1);
+INSERT INTO b42941.t4 VALUES (1);
+UPDATE test.t4 tn4, b42941.t4 tt4 SET tn4.a= 10, tt4.a= 100;
+COMMIT;
+
+FLUSH LOGS;
+
+-- let $log_file1= $MYSQLD_DATADIR/master-bin.000001
+-- let $log_file2= $MYSQLD_DATADIR/master-bin.000002
+-- let $outfile= $MYSQLTEST_VARDIR/tmp/b42941-mysqlbinlog
+-- let $cmd= $MYSQL_BINLOG
+
+let $i= 3;
+while($i)
+{
+ -- let $flags=--database=b42941
+
+ # construct CLI for mysqlbinlog
+ if($i==3)
+ {
+ -- let $flags= $flags --verbose --hexdump
+ }
+
+ if($i==2)
+ {
+ -- let $flags= $flags --verbose
+ }
+
+# if($i==1)
+# {
+ # do nothing $flags is already set as it should be
+# }
+
+ # execute mysqlbinlog on the two available master binlog files
+ -- exec $cmd $flags $log_file1 > $outfile.1
+ -- exec $cmd $flags $log_file2 > $outfile.2
+
+ # load outputs into a variable
+ -- replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
+ -- eval SET @b42941_output.1= LOAD_FILE('$outfile.1')
+
+ -- replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
+ -- eval SET @b42941_output.2= LOAD_FILE('$outfile.2')
+
+ # remove unecessary files
+ -- remove_file $outfile.1
+ -- remove_file $outfile.2
+
+ #
+ # The two tests are canceled since we introduced the patch of bug#46998,
+ # which will make mydsqlbinlog output the 'BEGIN', 'COMMIT' and 'ROLLBACK'
+ # in regardless of database filtering
+ #
+ # assertion: events for database test are filtered
+ #if (`SELECT INSTR(@b42941_output.1, 'test')`)
+ #{
+ #-- echo **** ERROR **** Database name 'test' FOUND in mysqlbinlog output ($flags $outfile.1).
+ #}
+
+ #if (`SELECT INSTR(@b42941_output.2, 'test')`)
+ #{
+ #-- echo **** ERROR **** Database name 'test' FOUND in mysqlbinlog output ($flags $outfile.2).
+ #}
+
+ # assertion: events for database b42941 are not filtered
+ if (!`SELECT INSTR(@b42941_output.1, 'b42941')`)
+ {
+ -- echo **** ERROR **** Database name 'b42941' NOT FOUND in mysqlbinlog output ($flags $outfile.1).
+ }
+
+ if (!`SELECT INSTR(@b42941_output.2, 'b42941')`)
+ {
+ -- echo **** ERROR **** Database name 'b42941' NOT FOUND in mysqlbinlog output ($flags $outfile.2).
+ }
+
+ dec $i;
+}
+
+DROP DATABASE b42941;
+use test;
+DROP TABLE t1, t2, t3, t4;
diff --git a/mysql-test/suite/binlog/t/binlog_row_mysqlbinlog_options-master.opt b/mysql-test/suite/binlog/t/binlog_row_mysqlbinlog_options-master.opt
new file mode 100644
index 00000000..4d69f335
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_row_mysqlbinlog_options-master.opt
@@ -0,0 +1 @@
+--timezone=GMT-3
diff --git a/mysql-test/suite/binlog/t/binlog_row_mysqlbinlog_options.test b/mysql-test/suite/binlog/t/binlog_row_mysqlbinlog_options.test
new file mode 100644
index 00000000..159b0186
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_row_mysqlbinlog_options.test
@@ -0,0 +1,78 @@
+--source include/have_log_bin.inc
+--source include/have_binlog_format_row.inc
+
+#
+# MWL36: Add a mysqlbinlog option to change the used database
+# (Adding --rewrite-db option)
+#
+--disable_warnings
+DROP DATABASE IF EXISTS test1;
+DROP DATABASE IF EXISTS test2;
+DROP DATABASE IF EXISTS test3;
+--enable_warnings
+
+# For SBR --rewrite-db affects only default database and doesn't affect
+# a query (specifically CREATE DATABASE) itself. Hence (for testing
+# purpose) we start binary logging after all databases have been created.
+
+CREATE DATABASE test1;
+CREATE DATABASE test2;
+CREATE DATABASE test3;
+
+# Fix timestamp to avoid varying results.
+SET timestamp=1000000000;
+
+# Delete all existing binary logs.
+RESET MASTER;
+
+# We'll call mysqlbinlog with two rewrite rules:
+# --rewrite-db="test1->new_test1"
+# --rewrite-db="test3->new_test3"
+
+USE test1;
+CREATE TABLE t1 (a INT, b INT);
+INSERT INTO t1 VALUES (1,1),(2,2);
+
+USE test2;
+CREATE TABLE t2 (a INT);
+INSERT INTO t2 VALUES (1),(2);
+
+DELETE FROM test1.t1 WHERE a=1;
+
+USE test3;
+CREATE TABLE t3 (a INT);
+INSERT INTO t3 VALUES (1),(2);
+INSERT INTO test1.t1 VALUES (3,3);
+
+USE test1;
+LOAD DATA INFILE '../../std_data/loaddata7.dat' INTO TABLE t1
+ FIELDS TERMINATED BY ',' LINES TERMINATED BY '\r\n';
+DELETE FROM test3.t3 WHERE a=1;
+
+flush logs;
+
+--echo #
+--echo # mysqlbinlog output
+--echo # --base64-output = decode-rows
+--echo # --rewrite-db = test1->new_test1
+--echo # --rewrite-db = test3->new_test3
+--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 #/ /CRC32 0x[0-9a-f]*/CRC32 XXX/ /collation_server=[0-9]+/collation_server=X/ /character_set_client=[a-zA-Z0-9]+/character_set_client=X/ /collation_connection=[0-9]+/collation_connection=X/ /xid=\d*/xid=<xid>/
+--exec $MYSQL_BINLOG --base64-output=decode-rows --rewrite-db="test1->new_test1" --rewrite-db="test3->new_test3" -v -v $MYSQLD_DATADIR/master-bin.000001
+
+--echo #
+--echo # mysqlbinlog output
+--echo # --base64-output = decode-rows
+--echo # --rewrite-db = test1->new_test1
+--echo # --rewrite-db = test3->new_test3
+--echo # --read-from-remote-server
+--echo #
+
+--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 #/ /CRC32 0x[0-9a-f]*/CRC32 XXX/ /collation_server=[0-9]+/collation_server=X/ /character_set_client=[a-zA-Z0-9]+/character_set_client=X/ /collation_connection=[0-9]+/collation_connection=X/ /xid=\d*/xid=<xid>/
+--exec $MYSQL_BINLOG --base64-output=decode-rows --rewrite-db="test1->new_test1" --rewrite-db="test3->new_test3" -v -v --read-from-remote-server --user=root --host=localhost --port=$MASTER_MYPORT master-bin.000001
+
+DROP DATABASE test1;
+DROP DATABASE test2;
+DROP DATABASE test3;
diff --git a/mysql-test/suite/binlog/t/binlog_row_mysqlbinlog_verbose.test b/mysql-test/suite/binlog/t/binlog_row_mysqlbinlog_verbose.test
new file mode 100644
index 00000000..98aa7635
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_row_mysqlbinlog_verbose.test
@@ -0,0 +1,69 @@
+########################################################
+# WHAT
+# ====
+# This test aims to check that the mysqlbinlog --verbose
+# command can output binlogs in 4 format variants.
+#
+# 1) Updates logged as write_row events
+# Only primary key and updated columns included in the
+# event
+# 2) Updates logged as write_row_events
+# All columns included in the event
+# 3) Updates logged as update_row events
+# Only primary key and updated columns included in the
+# event
+# 4) Updates logged as update_row events
+# All columns included in the event
+########################################################
+
+# We require binlog_format_row as we're independent of binlog format
+# and there's no point running the same test 3 times
+-- source include/have_binlog_format_row.inc
+
+--disable_query_log
+--let $binlog_file=write-partial-row.binlog
+--exec $MYSQL_BINLOG --verbose suite/binlog/std_data/$binlog_file > $MYSQLTEST_VARDIR/tmp/mysqlbinlog_verbose.sql
+create table raw_binlog_rows (txt varchar(1000));
+--eval load data local infile '$MYSQLTEST_VARDIR/tmp/mysqlbinlog_verbose.sql' into table raw_binlog_rows columns terminated by '\n';
+--remove_file $MYSQLTEST_VARDIR/tmp/mysqlbinlog_verbose.sql
+--enable_query_log
+--echo Verbose statements from : $binlog_file
+# Output --verbose lines, with extra Windows CR's trimmed
+select replace(txt,'\r', '') as stmt from raw_binlog_rows where txt like '###%';
+drop table raw_binlog_rows;
+
+--disable_query_log
+--let $binlog_file=write-full-row.binlog
+--exec $MYSQL_BINLOG --verbose suite/binlog/std_data/$binlog_file > $MYSQLTEST_VARDIR/tmp/mysqlbinlog_verbose.sql
+create table raw_binlog_rows (txt varchar(1000));
+--eval load data local infile '$MYSQLTEST_VARDIR/tmp/mysqlbinlog_verbose.sql' into table raw_binlog_rows columns terminated by '\n';
+--remove_file $MYSQLTEST_VARDIR/tmp/mysqlbinlog_verbose.sql
+--enable_query_log
+--echo Verbose statements from : $binlog_file
+# Output --verbose lines, with extra Windows CR's trimmed
+select replace(txt,'\r', '') as stmt from raw_binlog_rows where txt like '###%';
+drop table raw_binlog_rows;
+
+--disable_query_log
+--let $binlog_file=update-partial-row.binlog
+--exec $MYSQL_BINLOG --verbose suite/binlog/std_data/$binlog_file > $MYSQLTEST_VARDIR/tmp/mysqlbinlog_verbose.sql
+create table raw_binlog_rows (txt varchar(1000));
+--eval load data local infile '$MYSQLTEST_VARDIR/tmp/mysqlbinlog_verbose.sql' into table raw_binlog_rows columns terminated by '\n';
+--remove_file $MYSQLTEST_VARDIR/tmp/mysqlbinlog_verbose.sql
+--enable_query_log
+--echo Verbose statements from : $binlog_file
+# Output --verbose lines, with extra Windows CR's trimmed
+select replace(txt,'\r', '') as stmt from raw_binlog_rows where txt like '###%';
+drop table raw_binlog_rows;
+
+--disable_query_log
+--let $binlog_file=update-full-row.binlog
+--exec $MYSQL_BINLOG --verbose suite/binlog/std_data/$binlog_file > $MYSQLTEST_VARDIR/tmp/mysqlbinlog_verbose.sql
+create table raw_binlog_rows (txt varchar(1000));
+--eval load data local infile '$MYSQLTEST_VARDIR/tmp/mysqlbinlog_verbose.sql' into table raw_binlog_rows columns terminated by '\n';
+--remove_file $MYSQLTEST_VARDIR/tmp/mysqlbinlog_verbose.sql
+--enable_query_log
+--echo Verbose statements from : $binlog_file
+# Output --verbose lines, with extra Windows CR's trimmed
+select replace(txt,'\r', '') as stmt from raw_binlog_rows where txt like '###%';
+drop table raw_binlog_rows;
diff --git a/mysql-test/suite/binlog/t/binlog_server_id.test b/mysql-test/suite/binlog/t/binlog_server_id.test
new file mode 100644
index 00000000..6e98ec6e
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_server_id.test
@@ -0,0 +1,29 @@
+# Test for BUG#28908 Replication: set global server_id is not setting the session server_id
+
+-- source include/have_log_bin.inc
+
+let $saved_server_id=`select @@server_id`;
+set global server_id=1;
+reset master;
+
+-- disable_warnings
+drop table if exists t1,t2,t3;
+-- enable_warnings
+
+create table t1 (a int);
+select @@server_id;
+source include/show_binlog_events2.inc;
+
+set global server_id=2;
+create table t2 (b int);
+select @@server_id;
+source include/show_binlog_events2.inc;
+
+set global server_id=3;
+create table t3 (c int);
+select @@server_id;
+source include/show_binlog_events2.inc;
+
+# cleanup
+eval set global server_id=$saved_server_id;
+drop table t1,t2,t3;
diff --git a/mysql-test/suite/binlog/t/binlog_sf.test b/mysql-test/suite/binlog/t/binlog_sf.test
new file mode 100644
index 00000000..fecc4736
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_sf.test
@@ -0,0 +1,187 @@
+
+# We change binlog format inside the test, so no need to re-run with
+# more than one binlog_format.
+-- source include/have_binlog_format_statement.inc
+
+# Bug#16456 RBR: rpl_sp.test expects query to fail, but passes in RBR
+# BUG#41166 stored function requires "deterministic" if binlog_format is "statement"
+
+# save status
+
+let $otfc=`select @@log_bin_trust_function_creators`;
+set global log_bin_trust_function_creators=0;
+
+# fail *on definition*
+
+set binlog_format=STATEMENT;
+
+delimiter |;
+--error ER_BINLOG_UNSAFE_ROUTINE
+create function fn16456()
+ returns int
+begin
+ return unix_timestamp();
+end|
+delimiter ;|
+
+
+
+# force in definition, so we can see whether we fail on call
+
+set global log_bin_trust_function_creators=1;
+
+delimiter |;
+create function fn16456()
+ returns int
+begin
+ return unix_timestamp();
+end|
+delimiter ;|
+
+set global log_bin_trust_function_creators=0;
+
+
+
+# allow funcall in RBR
+
+set binlog_format=ROW;
+
+--replace_column 1 timestamp
+select fn16456();
+
+
+
+# fail funcall in SBR
+
+set binlog_format=STATEMENT;
+
+--error ER_BINLOG_UNSAFE_ROUTINE
+select fn16456();
+
+
+
+# clean
+
+drop function fn16456;
+
+
+
+# success in definition with deterministic
+
+set global log_bin_trust_function_creators=0;
+
+delimiter |;
+create function fn16456()
+ returns int deterministic
+begin
+ return unix_timestamp();
+end|
+delimiter ;|
+
+
+
+# allow funcall in RBR
+
+set binlog_format=ROW;
+
+--replace_column 1 timestamp
+select fn16456();
+
+
+
+# allow funcall in SBR
+
+set binlog_format=STATEMENT;
+
+--replace_column 1 timestamp
+select fn16456();
+
+
+
+# clean
+
+drop function fn16456;
+
+
+# success in definition with NO SQL
+
+set global log_bin_trust_function_creators=0;
+
+delimiter |;
+create function fn16456()
+ returns int no sql
+begin
+ return unix_timestamp();
+end|
+delimiter ;|
+
+
+
+# allow funcall in RBR
+
+set binlog_format=ROW;
+
+--replace_column 1 timestamp
+select fn16456();
+
+
+
+# allow funcall in SBR
+
+set binlog_format=STATEMENT;
+
+--replace_column 1 timestamp
+select fn16456();
+
+
+# clean
+
+drop function fn16456;
+
+
+
+# success in definition with reads sql data
+
+set global log_bin_trust_function_creators=0;
+
+delimiter |;
+create function fn16456()
+ returns int reads sql data
+begin
+ return unix_timestamp();
+end|
+delimiter ;|
+
+
+
+# allow funcall in RBR
+
+set binlog_format=ROW;
+
+--replace_column 1 timestamp
+select fn16456();
+
+
+
+# allow funcall in SBR
+
+set binlog_format=STATEMENT;
+
+--replace_column 1 timestamp
+select fn16456();
+
+
+
+# clean
+
+drop function fn16456;
+
+
+
+# restore status
+
+--disable_query_log
+set binlog_format=STATEMENT;
+eval set global log_bin_trust_function_creators=$otfc;
+reset master;
+--enable_query_log
diff --git a/mysql-test/suite/binlog/t/binlog_show_binlog_event_random_pos.combinations b/mysql-test/suite/binlog/t/binlog_show_binlog_event_random_pos.combinations
new file mode 100644
index 00000000..72076e12
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_show_binlog_event_random_pos.combinations
@@ -0,0 +1,5 @@
+[enable_checksum]
+binlog_checksum=1
+
+[disable_checksum]
+binlog_checksum=0
diff --git a/mysql-test/suite/binlog/t/binlog_show_binlog_event_random_pos.test b/mysql-test/suite/binlog/t/binlog_show_binlog_event_random_pos.test
new file mode 100644
index 00000000..05e6967c
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_show_binlog_event_random_pos.test
@@ -0,0 +1,42 @@
+# ==== Purpose ====
+#
+# Test verifies that reading binary log by using "SHOW BINLOG EVENTS" command
+# from various random positions doesn't lead to crash. It should exit
+# gracefully with appropriate error.
+#
+# ==== References ====
+#
+# MDEV-18046:Assortment of crashes, assertion failures and ASAN errors in mysql_show_binlog_events
+
+--source include/have_log_bin.inc
+--source include/have_innodb.inc
+
+RESET MASTER;
+call mtr.add_suppression("Error in Log_event::read_log_event*");
+call mtr.add_suppression("Replication event checksum verification failed while reading from a log file*");
+
+DROP TABLE IF EXISTS t1;
+CREATE TABLE t1 (c1 CHAR(255), c2 CHAR(255), c3 CHAR(255), c4 CHAR(255), c5 CHAR(255));
+INSERT INTO t1 VALUES (repeat('a', 255), repeat('a', 255),repeat('a', 255),repeat('a', 255),repeat('a', 255));
+INSERT INTO t1 VALUES (repeat('a', 255), repeat('a', 255),repeat('a', 255),repeat('a', 255),repeat('a', 255));
+UPDATE t1 SET c1=repeat('b',255);
+INSERT INTO t1 VALUES (repeat('a', 255), repeat('a', 255),repeat('a', 255),repeat('a', 255),repeat('a', 255));
+--let $max_pos= query_get_value(SHOW MASTER STATUS,Position,1)
+--let $pos= 1
+while ($pos <= $max_pos)
+{
+ --disable_query_log
+ --disable_result_log
+ --error 0,1220
+ eval SHOW BINLOG EVENTS FROM $pos LIMIT 100;
+ --inc $pos
+ --enable_result_log
+ --enable_query_log
+}
+
+# Testing a case where input position is greater than actual binlog file size.
+--replace_result $pos POS $max_pos MAX_POS
+--error 1220
+eval SHOW BINLOG EVENTS FROM $pos;
+
+DROP TABLE t1;
diff --git a/mysql-test/suite/binlog/t/binlog_spurious_ddl_errors.test b/mysql-test/suite/binlog/t/binlog_spurious_ddl_errors.test
new file mode 100644
index 00000000..29a86076
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_spurious_ddl_errors.test
@@ -0,0 +1,95 @@
+################################################################################
+# BUG#50479 DDL stmt on row-only/stmt-only tables generate spurious
+# binlog_format errors
+#
+# In the fix of BUG#39934 in 5.1-rep+3, errors are generated when
+# binlog_format=row and a statement modifies a table restricted to
+# statement-logging (ER_BINLOG_ROW_MODE_AND_STMT_ENGINE); or if
+# binlog_format=statement and a statement modifies a table limited to
+# row-logging (ER_BINLOG_STMT_MODE_AND_ROW_ENGINE).
+#
+# In this test case, we check if some DDL statements that lock tables do not
+# trigger errors as they do not generate rows events and as such are harmless
+# from the point of view of conflicts between the engine's supported logging
+# format and the value of binlog_format.
+#
+# In particular, we check if:
+# 1 - ALTER TABLE, CREATE INDEX and CREATE TRIGGER do not generate either
+# ER_BINLOG_STMT_MODE_AND_ROW_ENGINE or ER_BINLOG_STMT_MODE_AND_ROW_ENGINE
+#
+# 2 - CREATE TABLE ... SELECT generates an error because the command can
+# generate row events but CREATE TABLE without SELECT does not generate
+# an error.
+################################################################################
+--source include/have_innodb.inc
+--source include/have_example_plugin.inc
+--source include/have_log_bin.inc
+
+SET @old_binlog_format= @@global.binlog_format;
+INSTALL PLUGIN example SONAME 'ha_example';
+
+--echo ################################################################################
+--echo # Verifies if ER_BINLOG_STMT_MODE_AND_ROW_ENGINE happens by setting the binlog
+--echo # format to STATEMENT and the transaction isolation level to READ COMMITTED as
+--echo # such changes force Innodb to accept changes in the row format.
+--echo #
+--echo # When CREATE TABLE, ALTER TABLE, CREATE INDEX and CREATE TRIGGER are executed
+--echo # any error should be triggered.
+--echo #
+--echo # In contrast, CREATE TABLE ... SELECT should trigger the following error:
+--echo # ER_BINLOG_STMT_MODE_AND_ROW_ENGINE.
+--echo ################################################################################
+SET binlog_format = STATEMENT;
+SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
+CREATE TABLE t_row (a VARCHAR(100)) ENGINE = InnoDB;
+
+ALTER TABLE t_row ADD COLUMN b INT;
+
+CREATE TRIGGER trig_row BEFORE INSERT ON t_row FOR EACH ROW INSERT INTO t_stmt VALUES (1);
+
+CREATE INDEX i ON t_row(a);
+
+--error ER_BINLOG_STMT_MODE_AND_ROW_ENGINE
+CREATE TABLE t_row_new ENGINE = InnoDB SELECT * FROM t_row;
+
+DROP TABLE t_row;
+
+--echo
+--echo
+
+--echo ################################################################################
+--echo # Verifies if ER_BINLOG_ROW_MODE_AND_STMT_ENGINE happens by setting the binlog
+--echo # format to ROW and using a engine, i.e. EXAMPLE, that only supports STATEMENT.
+--echo #
+--echo # When CREATE TABLE, ALTER TABLE, CREATE INDEX and CREATE TRIGGER are executed
+--echo # the error ER_BINLOG_ROW_MODE_AND_STMT_ENGINE is not triggered. Note that other
+--echo # errors are triggered due to restrictions in the engine.
+--echo #
+--echo # In contrast, CREATE TABLE ... SELECT should trigger the following error:
+--echo # ER_BINLOG_ROW_MODE_AND_STMT_ENGINE.
+--echo ################################################################################
+SET binlog_format = ROW;
+CREATE TABLE t_stmt (a VARCHAR(100)) ENGINE = EXAMPLE;
+
+ALTER TABLE t_stmt ADD COLUMN b INT;
+
+CREATE TRIGGER trig_stmt BEFORE INSERT ON t_stmt FOR EACH ROW INSERT INTO t_stmt VALUES (1);
+
+--error ER_TOO_MANY_KEY_PARTS
+CREATE INDEX i ON t_stmt(a);
+
+--error ER_BINLOG_ROW_MODE_AND_STMT_ENGINE
+CREATE TABLE t_stmt_new ENGINE = EXAMPLE SELECT * FROM t_stmt;
+
+DROP TABLE t_stmt;
+
+--echo
+--echo
+
+--echo ################################################################################
+--echo # CLEAN UP #
+--echo ################################################################################
+flush tables;
+UNINSTALL PLUGIN example;
+SET @@global.binlog_format = @old_binlog_format;
+SET @@session.binlog_format = @old_binlog_format;
diff --git a/mysql-test/suite/binlog/t/binlog_sql_mode.test b/mysql-test/suite/binlog/t/binlog_sql_mode.test
new file mode 100644
index 00000000..167c8f5a
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_sql_mode.test
@@ -0,0 +1,171 @@
+# ==== Purpose ====
+#
+# Test that sql_mode can correct restore before generating the binlog event
+# when creating CREATEable objects.
+#
+# ==== Method ====
+#
+# Scan binlog file to check if the sql_mode is still set to 0 before generating binlog event
+#
+
+-- source include/have_log_bin.inc
+
+# BUG#39526 sql_mode not retained in binary log for CREATE PROCEDURE
+
+SET @old_sql_mode= @@global.sql_mode;
+SET @old_binlog_format=@@session.binlog_format;
+let $MYSQLD_DATADIR= `select @@datadir`;
+SET SESSION sql_mode=8;
+
+--echo Initialization
+
+RESET MASTER;
+CREATE TABLE t1 (id INT);
+
+CREATE PROCEDURE testProc() SELECT * FROM t1;
+CREATE VIEW testView as SELECT * from t1;
+
+DELIMITER |;
+CREATE FUNCTION testFunc()
+ RETURNS INT
+ BEGIN
+ return 1;
+ END;|
+DELIMITER ;|
+
+DELIMITER |;
+CREATE TRIGGER testTrig BEFORE INSERT ON t1
+ FOR EACH ROW BEGIN
+ UPDATE t1 SET id = id +1;
+ END;|
+DELIMITER ;|
+
+DELIMITER |;
+CREATE EVENT testEvent ON SCHEDULE
+ EVERY 1 DAY
+ DO
+ BEGIN
+ UPDATE t1 SET id = id +1;
+ END;|
+DELIMITER ;|
+
+--echo Check Result
+
+let $MYSQLD_DATADIR= `select @@datadir`;
+--exec $MYSQL_BINLOG --force-if-open $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/mysqlbinlog_bug39526.binlog
+--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
+eval select
+(@a:=load_file("$MYSQLTEST_VARDIR/tmp/mysqlbinlog_bug39526.binlog"))
+is not null;
+let $s_mode_unsigned= `select @a like "%@@session.sql_mode=0%" /* must return 0 */`;
+echo *** String sql_mode=0 is found: $s_mode_unsigned ***;
+
+--remove_file $MYSQLTEST_VARDIR/tmp/mysqlbinlog_bug39526.binlog
+
+--echo Clean Up
+
+DROP PROCEDURE testProc;
+DROP FUNCTION testFunc;
+DROP TRIGGER testTrig;
+DROP EVENT testEvent;
+DROP VIEW testView;
+DROP TABLE t1;
+
+SET @@global.sql_mode= @old_sql_mode;
+SET @@session.binlog_format=@old_binlog_format;
+
+--echo
+--echo #
+--echo # Test for Bug#12601974 - STORED PROCEDURE SQL_MODE=NO_BACKSLASH_ESCAPES
+--echo # IGNORED AND BREAKS REPLICATION
+--echo #
+
+--disable_warnings
+DROP DATABASE IF EXISTS mysqltest_db;
+DROP TABLE IF EXISTS test_table;
+--enable_warnings
+
+CREATE DATABASE mysqltest_db;
+USE mysqltest_db;
+CREATE TABLE test_table (c1 CHAR(50));
+
+SET @org_mode=@@sql_mode;
+
+SET @@sql_mode='';
+DELIMITER $;
+CREATE PROCEDURE proc_without_sql_mode (IN param1 CHAR(50), IN param2 CHAR(50))
+BEGIN
+ DECLARE var1 CHAR(50) DEFAULT param1;
+ DECLARE var2 CHAR(50) DEFAULT param2;
+ DECLARE var3 CHAR(50) DEFAULT 'abcd\bef';
+ DECLARE var4 CHAR(50) DEFAULT 'abcd\nef';
+ DECLARE var5 CHAR(50) DEFAULT 'abcd\ref';
+ DECLARE var6 CHAR(50) DEFAULT 'abcd\tef';
+ DECLARE var7 CHAR(50) DEFAULT 'abcd\\ef';
+ DECLARE var8 CHAR(50) DEFAULT 'abcd\%ef';
+ DECLARE var9 CHAR(50) DEFAULT 'abcd\_ef';
+
+ INSERT INTO test_table VALUES (var1);
+ INSERT INTO test_table VALUES (var2);
+ INSERT INTO test_table VALUES (var3);
+ INSERT INTO test_table VALUES (var4);
+ INSERT INTO test_table VALUES (var5);
+ INSERT INTO test_table VALUES (var6);
+ INSERT INTO test_table VALUES (var7);
+ INSERT INTO test_table VALUES (var8);
+ INSERT INTO test_table VALUES (var9);
+END
+$
+
+SET @@sql_mode='NO_BACKSLASH_ESCAPES'$
+CREATE PROCEDURE proc_with_sql_mode (IN param1 CHAR(50), IN param2 CHAR(50))
+BEGIN
+ DECLARE var1 CHAR(50) DEFAULT param1;
+ DECLARE var2 CHAR(50) DEFAULT param2;
+ DECLARE var3 CHAR(50) DEFAULT 'wxyz\bef';
+ DECLARE var4 CHAR(50) DEFAULT 'wxyz\nef';
+ DECLARE var5 CHAR(50) DEFAULT 'wxyz\ref';
+ DECLARE var6 CHAR(50) DEFAULT 'wxyz\tef';
+ DECLARE var7 CHAR(50) DEFAULT 'wxyz\\ef';
+ DECLARE var8 CHAR(50) DEFAULT 'wxyz\%ef';
+ DECLARE var9 CHAR(50) DEFAULT 'wxyz\_ef';
+
+ INSERT INTO test_table VALUES (var1);
+ INSERT INTO test_table VALUES (var2);
+ INSERT INTO test_table VALUES (var3);
+ INSERT INTO test_table VALUES (var4);
+ INSERT INTO test_table VALUES (var5);
+ INSERT INTO test_table VALUES (var6);
+ INSERT INTO test_table VALUES (var7);
+ INSERT INTO test_table VALUES (var8);
+ INSERT INTO test_table VALUES (var9);
+END
+$
+
+DELIMITER ;$
+SET @@sql_mode='';
+CALL proc_without_sql_mode('abcd\'ef', 'abcd\"ef');
+CALL proc_with_sql_mode('wxyz\'ef', 'wxyz\"ef');
+SELECT * FROM test_table;
+
+let $MYSQLD_DATADIR= `select @@datadir`;
+--exec $MYSQL_BINLOG --force-if-open -d mysqltest_db $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/mysqlbinlog_bug12601974.binlog
+
+--echo "Dropping table test_table"
+DROP TABLE test_table;
+
+--exec $MYSQL -e "source $MYSQLTEST_VARDIR/tmp/mysqlbinlog_bug12601974.binlog"
+
+--echo #"test_table" content after replaying the binlog
+SELECT * FROM test_table;
+
+--echo #Clean up
+--remove_file $MYSQLTEST_VARDIR/tmp/mysqlbinlog_bug12601974.binlog
+DROP DATABASE mysqltest_db;
+SET @@sql_mode= @org_mode;
+use test;
+
+--echo
+--echo #End of Test for Bug#12601974
+
+
diff --git a/mysql-test/suite/binlog/t/binlog_start_comment.test b/mysql-test/suite/binlog/t/binlog_start_comment.test
new file mode 100644
index 00000000..98f2ca05
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_start_comment.test
@@ -0,0 +1,25 @@
+# Test case for bug#32205 Replaying statements from mysqlbinlog fails
+# with a syntax error, replicates fine
+
+source include/have_log_bin.inc;
+source include/have_local_infile.inc;
+
+reset master;
+--disable_warnings
+drop table if exists t1,t2;
+--enable_warnings
+create table t1 (word varchar(20)) -- create table t1;
+create table t2 (word varchar(20)) -- create table t2;
+load data infile '../../std_data/words.dat' into table t1 -- load data to t1;
+insert into t2 values ("Ada");
+flush logs;
+select * from t2;
+let $MYSQLD_DATADIR= `select @@datadir`;
+--exec $MYSQL_BINLOG --local-load=$MYSQLTEST_VARDIR/tmp/ $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/binlog_start_comment.binlog
+--exec $MYSQL --local-infile=1 < $MYSQLTEST_VARDIR/tmp/binlog_start_comment.binlog
+flush logs;
+select * from t2;
+
+# clean up
+drop table t1,t2;
+remove_file $MYSQLTEST_VARDIR/tmp/binlog_start_comment.binlog;
diff --git a/mysql-test/suite/binlog/t/binlog_statement_insert_delayed.test b/mysql-test/suite/binlog/t/binlog_statement_insert_delayed.test
new file mode 100644
index 00000000..9145afc0
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_statement_insert_delayed.test
@@ -0,0 +1,13 @@
+# This test is to verify replication with INSERT DELAY through
+# unrecommended STATEMENT binlog format
+
+-- source include/not_embedded.inc
+-- source include/have_binlog_format_statement.inc
+-- disable_query_log
+reset master; # get rid of previous tests binlog
+-- enable_query_log
+disable_query_log;
+call mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT");
+enable_query_log;
+-- source include/binlog_insert_delayed.test
+reset master;
diff --git a/mysql-test/suite/binlog/t/binlog_stm_binlog-master.opt b/mysql-test/suite/binlog/t/binlog_stm_binlog-master.opt
new file mode 100644
index 00000000..099f07e5
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_stm_binlog-master.opt
@@ -0,0 +1 @@
+--max_binlog_size=4096 --default-storage-engine=MyISAM
diff --git a/mysql-test/suite/binlog/t/binlog_stm_binlog.test b/mysql-test/suite/binlog/t/binlog_stm_binlog.test
new file mode 100644
index 00000000..045be97d
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_stm_binlog.test
@@ -0,0 +1,20 @@
+-- source include/not_embedded.inc
+-- source include/have_binlog_format_mixed.inc
+let collation=utf8mb3_unicode_ci;
+--source include/have_collation.inc
+
+reset master; # clear up binlogs
+# REQUIREMENT
+# replace_regex should replace output of SHOW BINLOG EVENTS
+
+create table t1 (a int, b int) engine=innodb;
+begin;
+insert into t1 values (1,2);
+commit;
+source include/show_binlog_events.inc;
+drop table t1;
+
+# This is a wrapper for binlog.test so that the same test case can be used
+# For both statement and row based bin logs 9/19/2005 [jbm]
+
+-- source include/binlog.test
diff --git a/mysql-test/suite/binlog/t/binlog_stm_blackhole.test b/mysql-test/suite/binlog/t/binlog_stm_blackhole.test
new file mode 100644
index 00000000..9dea4d1b
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_stm_blackhole.test
@@ -0,0 +1,6 @@
+# This is a wrapper for binlog.test so that the same test case can be used
+# For both statement and row based bin logs 9/19/2005 [jbm]
+
+-- source include/not_embedded.inc
+-- source include/have_binlog_format_statement.inc
+-- source include/blackhole.test
diff --git a/mysql-test/suite/binlog/t/binlog_stm_cache_stat.test b/mysql-test/suite/binlog/t/binlog_stm_cache_stat.test
new file mode 100644
index 00000000..a03f4c54
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_stm_cache_stat.test
@@ -0,0 +1,5 @@
+# This is a wrapper for binlog.test so that the same test case can be used
+# For both statement and row based bin logs 9/19/2005 [jbm]
+
+-- source include/have_binlog_format_statement.inc
+-- source include/binlog_cache_stat.test
diff --git a/mysql-test/suite/binlog/t/binlog_stm_ctype_cp932.test b/mysql-test/suite/binlog/t/binlog_stm_ctype_cp932.test
new file mode 100644
index 00000000..33378b28
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_stm_ctype_cp932.test
@@ -0,0 +1,6 @@
+# This is a wrapper for binlog.test so that the same test case can be used
+# For both statement and row based bin logs 9/19/2005 [jbm]
+
+-- source include/not_embedded.inc
+-- source include/have_binlog_format_mixed_or_statement.inc
+-- source include/ctype_cp932.test
diff --git a/mysql-test/suite/binlog/t/binlog_stm_ctype_ucs.test b/mysql-test/suite/binlog/t/binlog_stm_ctype_ucs.test
new file mode 100644
index 00000000..ed5b899c
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_stm_ctype_ucs.test
@@ -0,0 +1,6 @@
+# This is a wrapper for binlog.test so that the same test case can be used
+# For both statement and row based bin logs 9/19/2005 [jbm]
+
+-- source include/have_binlog_format_mixed_or_statement.inc
+-- source include/ctype_ucs_binlog.test
+
diff --git a/mysql-test/suite/binlog/t/binlog_stm_datetime_ranges_mdev15289.test b/mysql-test/suite/binlog/t/binlog_stm_datetime_ranges_mdev15289.test
new file mode 100644
index 00000000..d277db97
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_stm_datetime_ranges_mdev15289.test
@@ -0,0 +1,7 @@
+--source include/not_embedded.inc
+--source include/have_binlog_format_statement.inc
+reset master; # clear up binlogs
+--exec $MYSQL_CLIENT_TEST test_datetime_ranges_mdev15289 > $MYSQLTEST_VARDIR/log/binlog_stm_datetime_ranges_mysql_client_test.out.log 2>&1
+
+--let $binlog_file = LAST
+source include/show_binlog_events.inc;
diff --git a/mysql-test/suite/binlog/t/binlog_stm_do_db-master.opt b/mysql-test/suite/binlog/t/binlog_stm_do_db-master.opt
new file mode 100644
index 00000000..e2cfcb29
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_stm_do_db-master.opt
@@ -0,0 +1 @@
+--binlog-do-db=b42829
diff --git a/mysql-test/suite/binlog/t/binlog_stm_do_db.test b/mysql-test/suite/binlog/t/binlog_stm_do_db.test
new file mode 100644
index 00000000..3ed1734f
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_stm_do_db.test
@@ -0,0 +1,90 @@
+# BUG#42829: binlogging enabled for all schemas regardless of
+# binlog-db-db / binlog-ignore-db
+#
+# WHAT
+# ====
+#
+# We want to test whether filtered events from binlog will cause
+# raising an error mentioning that statement is unable to be logged or
+# not, when:
+#
+# 1. isolation level READ-COMMITTED; AND
+#
+# 2. using InnoDB engine; AND
+#
+# 3. using SBL (in which case InnoDB will only allow RBL).
+#
+# HOW
+# ===
+#
+# The test is implemented as follows:
+#
+# i) set tx_isolation to read-committed.
+#
+# ii) create two databases (one filtered other not - using
+# binlog-do-db)
+#
+# iii) Create statements that are to be filtered on filtered db
+#
+# - At this point, before fix, an error would be raised
+#
+# iv) do the same thing for not the filtered database and check
+# that events throw an error:
+#
+# - Error: ER_BINLOG_STMT_MODE_AND_ROW_ENGINE
+#
+
+-- source include/have_log_bin.inc
+-- source include/have_innodb.inc
+-- source include/have_binlog_format_statement.inc
+RESET MASTER; # clear up binlogs
+SET @old_isolation_level= @@session.tx_isolation;
+SET @@session.tx_isolation= 'READ-COMMITTED';
+
+-- let $engine= InnoDB
+-- let $filtered= b42829_filtered
+-- let $not_filtered= b42829
+
+-- eval CREATE DATABASE $not_filtered
+-- eval use $not_filtered
+-- eval CREATE TABLE t1 (x int, y int) engine=$engine
+-- eval CREATE TABLE t2 (x int, y int) engine=$engine
+
+-- eval CREATE DATABASE $filtered
+-- eval use $filtered
+-- eval CREATE TABLE t1 (x int, y int) engine=$engine
+-- eval CREATE TABLE t2 (x int, y int) engine=$engine
+
+SET @@session.sql_log_bin= 0;
+-- eval INSERT INTO $filtered.t1 VALUES (100,100)
+-- eval INSERT INTO $not_filtered.t1 VALUES (100,100)
+SET @@session.sql_log_bin= 1;
+
+-- echo ### assertion: the inserts will not raise log error because
+-- echo ### binlog-do-db is filtering used database
+INSERT INTO t2 VALUES (1,2), (1,3), (1,4);
+INSERT INTO t1 SELECT * FROM t2;
+
+-- echo ### assertion: assert that despite updating a not filtered
+-- echo ### database this wont trigger an error as the
+-- echo ### used database is the filtered one.
+-- eval UPDATE $filtered.t1 ft1, $not_filtered.t1 nft1 SET ft1.x=1, nft1.x=2
+
+-- eval use $not_filtered
+-- echo ### assertion: the statements *will* raise log error because
+-- echo ### binlog-do-db is not filtering used database
+BEGIN;
+-- error ER_BINLOG_STMT_MODE_AND_ROW_ENGINE
+INSERT INTO t2 VALUES (1,2), (1,3), (1,4);
+-- error ER_BINLOG_STMT_MODE_AND_ROW_ENGINE
+-- eval UPDATE $filtered.t1 ft1, $not_filtered.t1 nft1 SET ft1.x=1, nft1.x=2
+-- error ER_BINLOG_STMT_MODE_AND_ROW_ENGINE
+INSERT INTO t1 SELECT * FROM t2;
+COMMIT;
+
+-- echo ### assertion: filtered events did not make into the binlog
+source include/show_binlog_events.inc;
+
+-- eval DROP DATABASE $not_filtered
+-- eval DROP DATABASE $filtered
+SET @@session.tx_isolation= @old_isolation_level;
diff --git a/mysql-test/suite/binlog/t/binlog_stm_drop_tbl.test b/mysql-test/suite/binlog/t/binlog_stm_drop_tbl.test
new file mode 100644
index 00000000..fb8b290a
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_stm_drop_tbl.test
@@ -0,0 +1,5 @@
+# This is a wrapper for drop_table.test so that the same test case can be used
+# For both statement and row based bin logs
+
+-- source include/have_binlog_format_mixed_or_statement.inc
+-- source include/drop_table.test
diff --git a/mysql-test/suite/binlog/t/binlog_stm_drop_tmp_tbl.test b/mysql-test/suite/binlog/t/binlog_stm_drop_tmp_tbl.test
new file mode 100644
index 00000000..201aa45b
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_stm_drop_tmp_tbl.test
@@ -0,0 +1,5 @@
+# This is a wrapper for binlog.test so that the same test case can be used
+# For both statement and row based bin logs 9/19/2005 [jbm]
+
+-- source include/have_binlog_format_mixed_or_statement.inc
+-- source include/drop_temp_table.test
diff --git a/mysql-test/suite/binlog/t/binlog_stm_innodb_stat-master.opt b/mysql-test/suite/binlog/t/binlog_stm_innodb_stat-master.opt
new file mode 100644
index 00000000..4cb92754
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_stm_innodb_stat-master.opt
@@ -0,0 +1 @@
+--binlog_cache_size=32768
diff --git a/mysql-test/suite/binlog/t/binlog_stm_insert_select.test b/mysql-test/suite/binlog/t/binlog_stm_insert_select.test
new file mode 100644
index 00000000..d0782c70
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_stm_insert_select.test
@@ -0,0 +1,5 @@
+# This is a wrapper for binlog.test so that the same test case can be used
+# For both statement and row based bin logs 9/19/2005 [jbm]
+
+-- source include/have_binlog_format_mixed_or_statement.inc
+-- source include/insert_select-binlog.test
diff --git a/mysql-test/suite/binlog/t/binlog_stm_mix_innodb_myisam-master.opt b/mysql-test/suite/binlog/t/binlog_stm_mix_innodb_myisam-master.opt
new file mode 100644
index 00000000..0fa355b4
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_stm_mix_innodb_myisam-master.opt
@@ -0,0 +1 @@
+--loose-innodb-lock-wait-timeout=2 --binlog-direct-non-transactional-updates=FALSE --default-storage-engine=MyISAM
diff --git a/mysql-test/suite/binlog/t/binlog_stm_mix_innodb_myisam.test b/mysql-test/suite/binlog/t/binlog_stm_mix_innodb_myisam.test
new file mode 100644
index 00000000..911c90b5
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_stm_mix_innodb_myisam.test
@@ -0,0 +1,15 @@
+# This is a wrapper for binlog.test so that the same test case can be used
+# For both statement and row based bin logs 9/19/2005 [jbm]
+
+-- source include/have_binlog_format_statement.inc
+
+CALL mtr.add_suppression("Statement may not be safe to log in statement format.");
+
+-- source include/mix_innodb_myisam_binlog.test
+
+set @@session.binlog_format=statement;
+-- source include/mix_innodb_myisam_side_effects.test
+set @@session.binlog_format=@@global.binlog_format;
+
+
+--echo end of tests
diff --git a/mysql-test/suite/binlog/t/binlog_stm_ps.test b/mysql-test/suite/binlog/t/binlog_stm_ps.test
new file mode 100644
index 00000000..b83991b1
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_stm_ps.test
@@ -0,0 +1,117 @@
+# This test is to verify replication with PS
+
+-- source include/not_embedded.inc
+-- source include/have_binlog_format_statement.inc
+
+disable_query_log;
+call mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT");
+enable_query_log;
+
+-- disable_query_log
+reset master; # get rid of previous tests binlog
+-- enable_query_log
+
+--disable_warnings
+drop table if exists t1;
+--enable_warnings
+reset master;
+
+#
+# Bug #26842: master binary log contains invalid queries - replication fails
+#
+create table t1 (a int);
+prepare s from "insert into t1 values (@a),(?)";
+set @a=98; execute s using @a;
+prepare s from "insert into t1 values (?)";
+set @a=99; execute s using @a;
+prepare s from "insert into t1 select 100 limit ?";
+set @a=100; execute s using @a;
+source include/show_binlog_events.inc;
+drop table t1;
+
+--echo #
+--echo # MDEV-10709 Expressions as parameters to Dynamic SQL
+--echo #
+
+FLUSH LOGS;
+SET TIMESTAMP=UNIX_TIMESTAMP('2001-01-02 10:20:30.123456');
+CREATE TABLE t1 (a DECIMAL(30,8));
+PREPARE stmt FROM 'INSERT INTO t1 VALUES (?)';
+EXECUTE stmt USING 10;
+EXECUTE stmt USING 11e0;
+EXECUTE stmt USING 12.1;
+EXECUTE stmt USING '13';
+EXECUTE stmt USING CURRENT_DATE;
+EXECUTE stmt USING MAKETIME(10,20,30);
+EXECUTE stmt USING CURRENT_TIME;
+EXECUTE stmt USING CURRENT_TIME(3);
+EXECUTE stmt USING CURRENT_TIME(6);
+EXECUTE stmt USING CURRENT_TIMESTAMP;
+EXECUTE stmt USING CURRENT_TIMESTAMP(3);
+EXECUTE stmt USING CURRENT_TIMESTAMP(6);
+SELECT * FROM t1;
+--let $binlog_file = LAST
+source include/show_binlog_events.inc;
+DROP TABLE t1;
+SET TIMESTAMP=DEFAULT;
+
+--echo #
+--echo # MDEV-10585 EXECUTE IMMEDIATE statement
+--echo #
+
+FLUSH LOGS;
+CREATE TABLE t1 (a INT);
+EXECUTE IMMEDIATE 'INSERT INTO t1 VALUES (101)';
+SET @a=102;
+EXECUTE IMMEDIATE 'INSERT INTO t1 VALUES (?)' USING @a;
+SET @a=103;
+SET @stmt='INSERT INTO t1 VALUES (?)';
+EXECUTE IMMEDIATE @stmt USING @a;
+--let $binlog_file = LAST
+source include/show_binlog_events.inc;
+DROP TABLE t1;
+
+--echo #
+--echo # MDEV-11360 Dynamic SQL: DEFAULT as a bind parameter
+--echo #
+
+FLUSH LOGS;
+CREATE TABLE t1 (a INT DEFAULT 10);
+EXECUTE IMMEDIATE 'INSERT INTO t1 VALUES (Default)';
+--echo # The output of this query in 'Note' is a syntactically incorrect query.
+--echo # But as it's never logged, it's ok. It should be human readable only.
+EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT ?' USING Default;
+EXECUTE IMMEDIATE 'INSERT INTO t1 VALUES (?)' USING Default;
+
+DELIMITER $$;
+CREATE PROCEDURE p1 ()
+BEGIN
+ INSERT INTO t1 VALUES (Default);
+ # EXPLAIN should not be logged
+ EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT ?' USING Default;
+ EXECUTE IMMEDIATE 'INSERT INTO t1 VALUES (?)' USING Default;
+END;
+$$
+DELIMITER ;$$
+CALL p1;
+DROP PROCEDURE p1;
+DROP TABLE t1;
+
+--let $binlog_file = LAST
+source include/show_binlog_events.inc;
+
+--echo #
+--echo #MDEV-14467 Item_param: replace {INT|DECIMAL|REAL|STRING|TIME}_VALUE with Type_handler
+--echo #
+
+FLUSH LOGS;
+CREATE TABLE t1 (a INT);
+EXECUTE IMMEDIATE 'INSERT INTO t1 SELECT 1 LIMIT ?' USING 10;
+EXECUTE IMMEDIATE 'INSERT INTO t1 SELECT 1 LIMIT ?' USING 10.1;
+EXECUTE IMMEDIATE 'INSERT INTO t1 SELECT 1 LIMIT ?' USING 10.1e0;
+EXECUTE IMMEDIATE 'INSERT INTO t1 SELECT 1 LIMIT ?' USING '10';
+EXECUTE IMMEDIATE 'INSERT INTO t1 SELECT 1 LIMIT ?' USING TIME'10:10:10';
+DROP TABLE t1;
+
+--let $binlog_file = LAST
+source include/show_binlog_events.inc;
diff --git a/mysql-test/suite/binlog/t/binlog_stm_row.test b/mysql-test/suite/binlog/t/binlog_stm_row.test
new file mode 100644
index 00000000..bef6b6e6
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_stm_row.test
@@ -0,0 +1,103 @@
+--source include/have_log_bin.inc
+# Test sets its own binlog_format, so we restrict it to run only once
+--source include/have_binlog_format_row.inc
+
+CALL mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT");
+
+# Get rid of previous tests binlog
+--disable_query_log
+reset master;
+--enable_query_log
+
+#
+# Bug#34306: Can't make copy of log tables when server binary log is enabled
+#
+# This is an additional test for Bug#34306 in order to ensure that INSERT INTO
+# .. SELECT FROM is properly replicated under SBR and RBR and that the proper
+# read lock type are acquired.
+#
+
+--disable_warnings
+DROP TABLE IF EXISTS t1;
+DROP TABLE IF EXISTS t2;
+--enable_warnings
+
+set @saved_global_binlog_format = @@global.binlog_format;
+set @saved_local_binlog_format = @@session.binlog_format;
+SET GLOBAL BINLOG_FORMAT = STATEMENT;
+SET SESSION BINLOG_FORMAT = STATEMENT;
+
+CREATE TABLE t1 (a INT);
+CREATE TABLE t2 LIKE t1;
+select @@SESSION.BINLOG_FORMAT;
+INSERT INTO t1 VALUES(1);
+INSERT INTO t2 VALUES(2);
+
+--connect(con1,localhost,root,,)
+--connect(con2,localhost,root,,)
+
+--echo #
+--echo # Ensure that INSERT INTO .. SELECT FROM under SBR takes a read
+--echo # lock that will prevent the source table from being modified.
+--echo #
+
+--disable_ps2_protocol
+--connection con1
+SELECT GET_LOCK('Bug#34306', 120);
+--connection con2
+PREPARE stmt FROM "INSERT INTO t1 SELECT * FROM t2 WHERE GET_LOCK('Bug#34306', 120)";
+--send EXECUTE stmt;
+--connection default
+let $wait_condition=
+ SELECT COUNT(*) = 1 FROM information_schema.processlist WHERE
+ state = "User lock" AND
+ info = "INSERT INTO t1 SELECT * FROM t2 WHERE GET_LOCK('Bug#34306', 120)";
+--source include/wait_condition.inc
+--send INSERT INTO t2 VALUES (3);
+--connection con1
+let $wait_condition=
+ SELECT COUNT(*) = 1 FROM information_schema.processlist WHERE
+ state = "Waiting for table level lock" and info = "INSERT INTO t2 VALUES (3)";
+--source include/wait_condition.inc
+SELECT RELEASE_LOCK('Bug#34306');
+--connection con2
+--reap
+SELECT RELEASE_LOCK('Bug#34306');
+--connection default
+--reap
+
+--echo #
+--echo # Ensure that INSERT INTO .. SELECT FROM prepared under SBR does
+--echo # not prevent the source table from being modified if under RBR.
+--echo #
+
+--connection con2
+SET SESSION BINLOG_FORMAT = ROW;
+--connection con1
+SELECT GET_LOCK('Bug#34306', 120);
+--connection con2
+--send EXECUTE stmt;
+--connection default
+let $wait_condition=
+ SELECT COUNT(*) = 1 FROM information_schema.processlist WHERE
+ state = "User lock" AND
+ info = "INSERT INTO t1 SELECT * FROM t2 WHERE GET_LOCK('Bug#34306', 120)";
+--source include/wait_condition.inc
+--connection con1
+INSERT INTO t2 VALUES (4);
+SELECT RELEASE_LOCK('Bug#34306');
+--connection con2
+--reap
+--enable_ps2_protocol
+
+--disconnect con1
+--disconnect con2
+--connection default
+
+--echo # Show binlog events
+source include/show_binlog_events.inc;
+
+DROP TABLE t1;
+DROP TABLE t2;
+SET GLOBAL BINLOG_FORMAT = @saved_global_binlog_format;
+SET SESSION BINLOG_FORMAT = @saved_local_binlog_format;
diff --git a/mysql-test/suite/binlog/t/binlog_stm_sp.test b/mysql-test/suite/binlog/t/binlog_stm_sp.test
new file mode 100644
index 00000000..047cab74
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_stm_sp.test
@@ -0,0 +1,82 @@
+--source include/have_binlog_format_statement.inc
+
+--disable_query_log
+reset master; # get rid of previous tests binlog
+--enable_query_log
+
+--echo #
+--echo # MDEV-11815 SP variables of temporal data types do not replicate correctly
+--echo #
+
+CREATE TABLE t1(a INT);
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE i INT DEFAULT 123;
+ DECLARE b8 BIT(8) DEFAULT 0x61;
+ DECLARE t0 TIME DEFAULT '01:01:01';
+ DECLARE t6 TIME(6) DEFAULT '01:01:01.123456';
+ DECLARE d DATE DEFAULT '2001-01-01';
+ DECLARE dt0 DATETIME DEFAULT '2001-01-01 01:01:01';
+ DECLARE dt6 DATETIME(6) DEFAULT '2001-01-01 01:01:01.123456';
+ DECLARE ts0 TIMESTAMP DEFAULT '2001-01-01 01:01:01';
+ DECLARE ts6 TIMESTAMP(6) DEFAULT '2001-01-01 01:01:01.123456';
+ INSERT INTO t1 VALUES (i=0x61);
+ INSERT INTO t1 VALUES (b8=0x61);
+ INSERT INTO t1 VALUES (t0=10101);
+ INSERT INTO t1 VALUES (t6=10101);
+ INSERT INTO t1 VALUES (d=20010101);
+ INSERT INTO t1 VALUES (dt0=20010101010101);
+ INSERT INTO t1 VALUES (dt6=20010101010101);
+ INSERT INTO t1 VALUES (ts0=20010101010101);
+ INSERT INTO t1 VALUES (ts6=20010101010101);
+END;
+$$
+DELIMITER ;$$
+CALL p1;
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+--let $binlog_file = LAST
+source include/show_binlog_events.inc;
+
+--echo #
+--echo # MDEV-16020 SP variables inside GROUP BY..WITH ROLLUP break replication
+--echo #
+
+FLUSH LOGS;
+CREATE TABLE t1 (d DATE);
+INSERT INTO t1 VALUES ('1985-05-13'),('1989-12-24');
+CREATE TABLE t2 (d DATE, c BIGINT);
+DELIMITER $$;
+BEGIN NOT ATOMIC
+ BEGIN
+ DECLARE var INT DEFAULT 10;
+ INSERT INTO t2 SELECT d, COUNT(*) FROM t1 GROUP BY d, var;
+ INSERT INTO t2 SELECT d, COUNT(*) FROM t1 GROUP BY d, var WITH ROLLUP;
+ END;
+ BEGIN
+ DECLARE atomic INT DEFAULT 20;
+ INSERT INTO t2 SELECT d, COUNT(*) FROM t1 GROUP BY d, atomic;
+ INSERT INTO t2 SELECT d, COUNT(*) FROM t1 GROUP BY d, atomic WITH ROLLUP;
+ INSERT INTO t2 SELECT d, COUNT(*) FROM t1 GROUP BY d, `atomic`;
+ INSERT INTO t2 SELECT d, COUNT(*) FROM t1 GROUP BY d, `atomic` WITH ROLLUP;
+ END;
+ BEGIN
+ DECLARE atomic ROW (atomic INT, xxx INT) DEFAULT (31,32);
+ INSERT INTO t2 SELECT d, COUNT(*) FROM t1 GROUP BY d, atomic.atomic;
+ INSERT INTO t2 SELECT d, COUNT(*) FROM t1 GROUP BY d, atomic.atomic WITH ROLLUP;
+ INSERT INTO t2 SELECT d, COUNT(*) FROM t1 GROUP BY d, `atomic`.`atomic`;
+ INSERT INTO t2 SELECT d, COUNT(*) FROM t1 GROUP BY d, `atomic`.`atomic` WITH ROLLUP;
+ INSERT INTO t2 SELECT d, COUNT(*) FROM t1 GROUP BY d, atomic.xxx;
+ INSERT INTO t2 SELECT d, COUNT(*) FROM t1 GROUP BY d, atomic.xxx WITH ROLLUP;
+ INSERT INTO t2 SELECT d, COUNT(*) FROM t1 GROUP BY d, `atomic`.`xxx`;
+ INSERT INTO t2 SELECT d, COUNT(*) FROM t1 GROUP BY d, `atomic`.`xxx` WITH ROLLUP;
+ END;
+END;
+$$
+DELIMITER ;$$
+DROP TABLE t1,t2;
+
+--let $binlog_file = LAST
+source include/show_binlog_events.inc;
diff --git a/mysql-test/suite/binlog/t/binlog_stm_sp_type_row.test b/mysql-test/suite/binlog/t/binlog_stm_sp_type_row.test
new file mode 100644
index 00000000..a7e21ee5
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_stm_sp_type_row.test
@@ -0,0 +1,108 @@
+--source include/not_embedded.inc
+--source include/have_binlog_format_statement.inc
+
+--disable_query_log
+call mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT");
+reset master; # get rid of previous tests binlog
+--enable_query_log
+
+
+SET sql_mode=ORACLE;
+
+--echo #
+--echo # MDEV-10914 ROW data type for stored routine variables
+--echo #
+
+CREATE TABLE t1 (a INT, b INT);
+DELIMITER $$;
+CREATE PROCEDURE p1
+AS
+ rec ROW(a INT,b INT);
+BEGIN
+ rec.a:=100;
+ rec.b:=200;
+ INSERT INTO t1 VALUES (rec.a,rec.b);
+ INSERT INTO t1 VALUES (10, rec=ROW(100,200));
+ INSERT INTO t1 VALUES (10, ROW(100,200)=rec);
+ INSERT INTO t1 SELECT 10, 20 FROM DUAL WHERE rec=ROW(100,200);
+ INSERT INTO t1 SELECT 10, 21 FROM DUAL WHERE ROW(100,200)=rec;
+ rec.a:=NULL;
+ INSERT INTO t1 VALUES (11, rec=ROW(100,200));
+ INSERT INTO t1 VALUES (11, rec=ROW(100,201));
+ INSERT INTO t1 VALUES (11, ROW(100,200)=rec);
+ INSERT INTO t1 VALUES (11, ROW(100,201)=rec);
+ INSERT INTO t1 SELECT 11, 20 FROM DUAL WHERE rec=ROW(100,200);
+ INSERT INTO t1 SELECT 11, 21 FROM DUAL WHERE ROW(100,200)=rec;
+ rec.b:=NULL;
+ INSERT INTO t1 VALUES (12, rec=ROW(100,200));
+ INSERT INTO t1 VALUES (12, ROW(100,200)=rec);
+ INSERT INTO t1 SELECT 12, 20 FROM DUAL WHERE rec=ROW(100,200);
+ INSERT INTO t1 SELECT 12, 21 FROM DUAL WHERE ROW(100,200)=rec;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+SELECT * FROM t1;
+DROP TABLE t1;
+DROP PROCEDURE p1;
+--let $binlog_file = LAST
+source include/show_binlog_events.inc;
+
+
+--echo #
+--echo # Testing ROW fields in LIMIT
+--echo #
+
+FLUSH LOGS;
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (10),(10);
+CREATE TABLE t2 (a INT);
+DELIMITER $$;
+CREATE PROCEDURE p1()
+AS
+ a INT:= 1;
+ rec ROW(a INT);
+BEGIN
+ rec.a:= 1;
+ INSERT INTO t2 SELECT 1 FROM t1 LIMIT a;
+ INSERT INTO t2 SELECT 2 FROM t1 LIMIT rec.a;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP TABLE t1,t2;
+DROP PROCEDURE p1;
+--let $binlog_file = LAST
+source include/show_binlog_events.inc;
+
+
+--echo #
+--echo # End of MDEV-10914 ROW data type for stored routine variables
+--echo #
+
+
+--echo #
+--echo # MDEV-12291 Allow ROW variables as SELECT INTO targets
+--echo #
+
+FLUSH LOGS;
+SET sql_mode=DEFAULT;
+CREATE TABLE t1 (a INT, b VARCHAR(32));
+INSERT INTO t1 VALUES (10, 'b10');
+CREATE TABLE t2 LIKE t1;
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE rec1 ROW(a INT, b VARCHAR(32));
+ SELECT * INTO rec1 FROM t1;
+ INSERT INTO t2 VALUES (rec1.a, rec1.b);
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+SELECT * FROM t1;
+DROP TABLE t1;
+DROP TABLE t2;
+DROP PROCEDURE p1;
+--let $binlog_file = LAST
+source include/show_binlog_events.inc;
diff --git a/mysql-test/suite/binlog/t/binlog_stm_unsafe_warning-master.opt b/mysql-test/suite/binlog/t/binlog_stm_unsafe_warning-master.opt
new file mode 100644
index 00000000..2dda40e6
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_stm_unsafe_warning-master.opt
@@ -0,0 +1 @@
+--binlog-ignore-db=b42851 --log-error --log-bin=master-bin --log-bin-index=master-bin
diff --git a/mysql-test/suite/binlog/t/binlog_stm_unsafe_warning.test b/mysql-test/suite/binlog/t/binlog_stm_unsafe_warning.test
new file mode 100644
index 00000000..578f0ff5
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_stm_unsafe_warning.test
@@ -0,0 +1,208 @@
+# BUG#42851: Spurious "Statement is not safe to log in statement
+# format." warnings
+#
+# WHY
+# ===
+#
+# This test aims at checking that the fix that removes spurious
+# entries in the error log when the statement is filtered out from
+# binlog, is working.
+#
+# HOW
+# ===
+#
+# The test case is split into three assertions when issuing statements
+# containing LIMIT and ORDER BY:
+#
+# i) issue statements in database that is not filtered => check
+# that warnings ARE shown;
+#
+# ii) issue statements in database that is not filtered, but with
+# binlog disabled => check that warnings ARE NOT shown;
+#
+# iii) issue statements in database that is filtered => check that
+# warnings ARE NOT shown.
+
+-- source include/have_log_bin.inc
+-- source include/have_binlog_format_statement.inc
+call mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT.");
+
+-- echo ### NOT filtered database => assertion: warnings ARE shown
+
+-- disable_warnings
+DROP TABLE IF EXISTS t1;
+-- enable_warnings
+
+CREATE TABLE t1 (a int, b int, primary key (a));
+INSERT INTO t1 VALUES (1,2), (2,3);
+UPDATE t1 SET b='4' WHERE a=1 LIMIT 1;
+UPDATE t1 SET b='5' WHERE a=2 ORDER BY a LIMIT 1;
+DROP TABLE t1;
+
+-- echo ### NOT filtered database => assertion: binlog disabled and warnings ARE NOT shown
+
+SET SQL_LOG_BIN= 0;
+
+-- disable_warnings
+DROP TABLE IF EXISTS t1;
+-- enable_warnings
+
+CREATE TABLE t1 (a int, b int, primary key (a));
+INSERT INTO t1 VALUES (1,2), (2,3);
+UPDATE t1 SET b='4' WHERE a=1 LIMIT 1;
+UPDATE t1 SET b='5' WHERE a=2 ORDER BY a LIMIT 1;
+DROP TABLE t1;
+
+SET SQL_LOG_BIN= 1;
+
+-- echo ### FILTERED database => assertion: warnings ARE NOT shown
+
+let $old_db= `SELECT DATABASE()`;
+
+CREATE DATABASE b42851;
+USE b42851;
+
+-- disable_warnings
+DROP TABLE IF EXISTS t1;
+-- enable_warnings
+
+CREATE TABLE t1 (a int, b int, primary key (a));
+INSERT INTO t1 VALUES (1,2), (2,3);
+UPDATE t1 SET b='4' WHERE a=1 LIMIT 1;
+UPDATE t1 SET b='5' WHERE a=2 ORDER BY a LIMIT 1;
+DROP TABLE t1;
+
+CREATE TABLE t1 (a VARCHAR(1000));
+INSERT INTO t1 VALUES (CURRENT_USER()); #marked unsafe before BUG#47995
+INSERT INTO t1 VALUES (FOUND_ROWS()); #marked unsafe before BUG#47995
+INSERT INTO t1 VALUES (GET_LOCK('tmp', 1)); #marked unsafe in BUG#47995
+INSERT INTO t1 VALUES (IS_FREE_LOCK('tmp')); #marked unsafe in BUG#47995
+INSERT INTO t1 VALUES (IS_USED_LOCK('tmp')); #marked unsafe in BUG#47995
+INSERT INTO t1 VALUES (LOAD_FILE('../../std_data/words2.dat')); #marked unsafe in BUG#39701
+INSERT INTO t1 VALUES (MASTER_POS_WAIT('dummy arg', 4711, 1));
+INSERT INTO t1 VALUES (RELEASE_LOCK('tmp')); #marked unsafe in BUG#47995
+INSERT INTO t1 VALUES (ROW_COUNT()); #marked unsafe before BUG#47995
+INSERT INTO t1 VALUES (SESSION_USER()); #marked unsafe before BUG#47995
+INSERT INTO t1 VALUES (SLEEP(1)); #marked unsafe in BUG#47995
+INSERT INTO t1 VALUES (SYSDATE()); #marked unsafe in BUG#47995
+INSERT INTO t1 VALUES (SYSTEM_USER()); #marked unsafe before BUG#47995
+INSERT INTO t1 VALUES (USER()); #marked unsafe before BUG#47995
+INSERT INTO t1 VALUES (UUID()); #marked unsafe before BUG#47995
+INSERT INTO t1 VALUES (UUID_SHORT()); #marked unsafe before BUG#47995
+INSERT INTO t1 VALUES (VERSION()); #marked unsafe in BUG#47995
+INSERT INTO t1 VALUES (RAND()); #marked unsafe in BUG#49222
+
+# clean up
+DROP DATABASE b42851;
+
+eval USE $old_db;
+
+--echo #
+--echo # Bug#46265: Can not disable warning about unsafe statements for binary logging
+--echo #
+
+let BINLOG_COUNTER1= `select CONVERT(NOW(),UNSIGNED) as timestmap from dual`;
+
+SET @old_log_warnings = @@log_warnings;
+
+--disable_warnings
+DROP TABLE IF EXISTS t1;
+--enable_warnings
+CREATE TABLE t1 (a VARCHAR(36), b VARCHAR(15));
+
+SET GLOBAL LOG_WARNINGS = 0;
+# Replacing the result file content here.
+# Instead of writing $BINLOG_COUNTER1 value to result file,
+# writing a fixed string timestamp to it.
+--replace_result $BINLOG_COUNTER1 timestamp
+eval INSERT INTO t1 VALUES(UUID(), '$BINLOG_COUNTER1');
+SET GLOBAL LOG_WARNINGS = 1;
+--replace_result $BINLOG_COUNTER1 timestamp
+eval INSERT INTO t1 VALUES(UUID(), '$BINLOG_COUNTER1');
+DROP TABLE t1;
+
+SET GLOBAL log_warnings = @old_log_warnings;
+
+let $log_error_= `SELECT @@GLOBAL.log_error`;
+if(!$log_error_)
+{
+ # MySQL Server on windows is started with --console and thus
+ # does not know the location of its .err log, use default location
+ let $log_error_ = $MYSQLTEST_VARDIR/log/mysqld.1.err;
+}
+
+# Assign env variable LOG_ERROR
+let LOG_ERROR=$log_error_;
+
+--echo # Count the number of times the "Unsafe" message was printed
+--echo # to the error log.
+
+perl;
+ use strict;
+ use Cwd;
+ my $log_error= $ENV{'LOG_ERROR'} or die "LOG_ERROR not set";
+ open(FILE, "$log_error") or die("Unable to open '$log_error' from directory " . cwd() . " :$! \n");
+ my $binlog_counter= $ENV{'BINLOG_COUNTER1'} or die "BINLOG_COUNTER1 not set";
+ my $count = () = grep(/$binlog_counter/g,<FILE>);
+ # Grep the timestamp value from the error file.
+ print "Occurrences: $count\n";
+ close(FILE);
+EOF
+
+#
+# Check how RAND() can be used with replication
+#
+
+create table t1 (n1 int, n2 int, n3 int,
+ key (n1, n2, n3),
+ key (n2, n3, n1),
+ key (n3, n1, n2));
+insert into t1 values (1,1,1);
+# This should work fine
+insert into t1 values (RAND()*1000+10, RAND()*1000+10, RAND()*1000+10);
+# This should need row based logging.
+update t1 set n1=rand() where n1=1;
+delete from t1 where n2=1 + rand()*0;
+drop table t1;
+
+# bug#50192: diplaying the unsafe warning comes out to the user warning stack
+-- disable_warnings
+DROP TABLE IF EXISTS t1, t2;
+-- enable_warnings
+
+CREATE TABLE t1 (a int);
+CREATE TABLE t2 (a int auto_increment primary key, b int);
+CREATE TRIGGER tr_bug50192 AFTER INSERT ON t1 FOR EACH ROW INSERT INTO t2 (b) VALUES (1);
+
+DELIMITER |;
+
+CREATE FUNCTION sf_bug50192() RETURNS INTEGER
+BEGIN
+ INSERT INTO t2(b) VALUES(2);
+ RETURN 1;
+END |
+
+DELIMITER ;|
+
+INSERT INTO t1 VALUES (0);
+SHOW WARNINGS;
+SELECT sf_bug50192();
+SHOW WARNINGS;
+
+# The test proves MDEV-24617 fixes leave in force
+# unsafe warnings in non-deterministic CREATE..SELECT cases.
+# Below an inserted default value to `b` of the target table is replication
+# unsafe. A warning must be out.
+CREATE TABLE t3 (a INT(11) DEFAULT NULL);
+INSERT INTO t3 VALUES (1);
+CREATE TABLE t4 (a INT(11) DEFAULT NULL, b BIGINT(20) DEFAULT uuid_short()) SELECT * FROM t3;
+SHOW WARNINGS;
+# no warning out of a deterministic "rhs" of SELECT
+CREATE OR REPLACE TABLE t4 (a INT(11) DEFAULT NULL) SELECT * FROM t3;
+SHOW WARNINGS;
+
+# cleanup
+
+DROP FUNCTION sf_bug50192;
+DROP TRIGGER tr_bug50192;
+DROP TABLE t1, t2, t3, t4;
diff --git a/mysql-test/suite/binlog/t/binlog_stm_user_variables.test b/mysql-test/suite/binlog/t/binlog_stm_user_variables.test
new file mode 100644
index 00000000..85bf511a
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_stm_user_variables.test
@@ -0,0 +1,87 @@
+-- source include/have_binlog_format_statement.inc
+RESET MASTER;
+#
+# BUG#49562: SBR out of sync when using numeric data types + user variable
+#
+
+-- let $max_unsigned_long= 18446744073709551615
+-- let $min_signed_long= -9223372036854775808
+-- eval SET @positive= $max_unsigned_long
+-- eval SET @negative= $min_signed_long
+
+CREATE TABLE t1 (`tinyint` TINYINT,
+ `smallint` SMALLINT,
+ `mediumint` MEDIUMINT,
+ `integer` INTEGER,
+ `bigint` BIGINT,
+ `utinyint` TINYINT UNSIGNED,
+ `usmallint` SMALLINT UNSIGNED,
+ `umediumint` MEDIUMINT UNSIGNED,
+ `uinteger` INTEGER UNSIGNED,
+ `ubigint` BIGINT UNSIGNED,
+ `double` DOUBLE,
+ `float` FLOAT,
+ `real` REAL(30,2),
+ `decimal` DECIMAL(30,2)) ENGINE = MyISAM;
+
+-- echo ### insert max unsigned
+-- echo ### a) declarative
+-- disable_warnings
+-- eval INSERT IGNORE INTO t1 VALUES ($max_unsigned_long, $max_unsigned_long, $max_unsigned_long, $max_unsigned_long, $max_unsigned_long, $max_unsigned_long, $max_unsigned_long,$max_unsigned_long, $max_unsigned_long, $max_unsigned_long, $max_unsigned_long, $max_unsigned_long, $max_unsigned_long, $max_unsigned_long);
+-- enable_warnings
+TRUNCATE t1;
+
+-- echo ### b) user var
+-- disable_warnings
+INSERT IGNORE INTO t1 VALUES (@positive,
+ @positive,
+ @positive,
+ @positive,
+ @positive,
+ @positive,
+ @positive,
+ @positive,
+ @positive,
+ @positive,
+ @positive,
+ @positive,
+ @positive,
+ @positive);
+-- enable_warnings
+
+-- echo ## assertion: checks that User_var_log_event::pack_info
+-- echo ## correctly displays the binlog content by taking into
+-- echo ## account the unsigned_flag
+-- source include/show_binlog_events.inc
+
+-- echo ### insert min signed
+-- echo ### a) declarative
+-- disable_warnings
+-- eval INSERT IGNORE INTO t1 VALUES ($min_signed_long, $min_signed_long, $min_signed_long, $min_signed_long, $min_signed_long, $min_signed_long, $min_signed_long,$min_signed_long, $min_signed_long, $min_signed_long, $min_signed_long, $min_signed_long, $min_signed_long, $min_signed_long);
+-- enable_warnings
+TRUNCATE t1;
+
+-- echo ### b) user var
+-- disable_warnings
+INSERT IGNORE INTO t1 VALUES (@negative,
+ @negative,
+ @negative,
+ @negative,
+ @negative,
+ @negative,
+ @negative,
+ @negative,
+ @negative,
+ @negative,
+ @negative,
+ @negative,
+ @negative,
+ @negative);
+-- enable_warnings
+
+-- echo ## assertion: checks that User_var_log_event::pack_info
+-- echo ## correctly displays the binlog content by taking into
+-- echo ## account the unsigned_flag
+-- source include/show_binlog_events.inc
+
+DROP TABLE t1;
diff --git a/mysql-test/suite/binlog/t/binlog_switch_inside_trans.test b/mysql-test/suite/binlog/t/binlog_switch_inside_trans.test
new file mode 100644
index 00000000..a93cd44f
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_switch_inside_trans.test
@@ -0,0 +1,200 @@
+#
+# BUG#47863
+# This test verifies if the session variable 'binlog_format' and
+# 'binlog_direct_non_transactional_updates' are read-only inside
+# a transaction and in sub-statements.
+#
+
+source include/have_innodb.inc;
+source include/have_binlog_format_row.inc;
+
+set @save_binlog_format= @@global.binlog_format;
+set @save_binlog_dirct= @@global.binlog_direct_non_transactional_updates;
+create table t1 (a int) engine= myisam;
+create table t2 (a int) engine= innodb;
+
+SELECT @@session.binlog_format;
+SELECT @@session.binlog_direct_non_transactional_updates;
+SELECT @@session.sql_log_bin;
+SET AUTOCOMMIT=1;
+--echo # Test that the session variable 'binlog_format',
+--echo # 'binlog_direct_non_transactional_updates' and 'sql_log_bin'
+--echo # are writable outside a transaction.
+--echo # Current session values are ROW, FALSE, TRUE, respectively.
+set @@session.binlog_format= statement;
+set @@session.binlog_direct_non_transactional_updates= TRUE;
+set @@session.sql_log_bin= FALSE;
+SELECT @@session.binlog_format;
+SELECT @@session.binlog_direct_non_transactional_updates;
+SELECT @@session.sql_log_bin;
+
+begin;
+--echo # Test that the session variable 'binlog_format',
+--echo # 'binlog_direct_non_transactional_updates' and 'sql_log_bin' are
+--echo # read-only inside a transaction with no preceding updates.
+--echo # Current session values are STATEMENT, TRUE, FALSE, respectively.
+--error ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_BINLOG_FORMAT
+ set @@session.binlog_format= mixed;
+--error ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_BINLOG_DIRECT
+ set @@session.binlog_direct_non_transactional_updates= FALSE;
+--error ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_SQL_LOG_BIN
+set @@session.sql_log_bin= FALSE;
+
+ insert into t2 values (1);
+--echo # Test that the session variable 'binlog_format',
+--echo # 'binlog_direct_non_transactional_updates' and 'sql_log_bin' are
+--echo # read-only inside a transaction with preceding transactional updates.
+--echo # Current session values are STATEMENT, TRUE and FALSE, respectively.
+--error ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_BINLOG_FORMAT
+ set @@session.binlog_format= row;
+--error ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_BINLOG_DIRECT
+ set @@session.binlog_direct_non_transactional_updates= FALSE;
+--error ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_SQL_LOG_BIN
+set @@session.sql_log_bin= FALSE;
+commit;
+
+begin;
+ insert into t1 values (2);
+--echo # Test that the session variable 'binlog_format'
+--echo # 'binlog_direct_non_transactional_updates' and 'sql_log_bin' are
+--echo # read-only inside a transaction with preceding non-transactional updates.
+--echo # Current session values are STATEMENT, TRUE, FALSE, respectively.
+--error ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_BINLOG_FORMAT
+ set @@session.binlog_format= mixed;
+--error ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_BINLOG_DIRECT
+ set @@session.binlog_direct_non_transactional_updates= FALSE;
+--error ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_SQL_LOG_BIN
+set @@session.sql_log_bin= FALSE;
+commit;
+
+--echo # Test that the session variable 'binlog_format',
+--echo # 'binlog_direct_non_transactional_updates' and 'sql_log_bin' are
+--echo # writable when AUTOCOMMIT=0, before a transaction has started.
+--echo # Current session values are STATEMENT, TRUE, FALSE, respectively.
+set AUTOCOMMIT=0;
+set @@session.binlog_format= row;
+set @@session.binlog_direct_non_transactional_updates= FALSE;
+set @@session.sql_log_bin= TRUE;
+SELECT @@session.binlog_format;
+SELECT @@session.binlog_direct_non_transactional_updates;
+SELECT @@session.sql_log_bin;
+
+insert into t1 values (3);
+--echo # Test that the session variable 'binlog_format',
+--echo # 'binlog_direct_non_transactional_updates' and 'sql_log_bin' are
+--echo # read-only inside an AUTOCOMMIT=0 transaction
+--echo # with preceding non-transactional updates.
+--echo # Current session values are ROW, FALSE, TRUE, respectively.
+--error ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_BINLOG_FORMAT
+set @@session.binlog_format= statement;
+--error ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_BINLOG_DIRECT
+set @@session.binlog_direct_non_transactional_updates= TRUE;
+--error ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_SQL_LOG_BIN
+set @@session.sql_log_bin= FALSE;
+SELECT @@session.binlog_format;
+SELECT @@session.binlog_direct_non_transactional_updates;
+SELECT @@session.sql_log_bin;
+commit;
+
+insert into t2 values (4);
+--echo # Test that the session variable 'binlog_format',
+--echo # 'binlog_direct_non_transactional_updates' and 'sql_log_bin' are
+--echo # read-only inside an AUTOCOMMIT=0 transaction with
+--echo # preceding transactional updates.
+--echo # Current session values are ROW, FALSE, TRUE, respectively.
+--error ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_BINLOG_FORMAT
+set @@session.binlog_format= statement;
+--error ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_BINLOG_DIRECT
+set @@session.binlog_direct_non_transactional_updates= TRUE;
+--error ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_SQL_LOG_BIN
+set @@session.sql_log_bin= FALSE;
+SELECT @@session.binlog_format;
+SELECT @@session.binlog_direct_non_transactional_updates;
+SELECT @@session.sql_log_bin;
+commit;
+
+begin;
+ insert into t2 values (5);
+--echo # Test that the global variable 'binlog_format' and
+--echo # 'binlog_direct_non_transactional_updates' are
+--echo # writable inside a transaction.
+--echo # Current session values are ROW, FALSE, TRUE respectively.
+ SELECT @@global.binlog_format;
+ set @@global.binlog_format= statement;
+ set @@global.binlog_direct_non_transactional_updates= TRUE;
+ SELECT @@global.binlog_format;
+ SELECT @@global.binlog_direct_non_transactional_updates;
+commit;
+
+set @@global.binlog_format= @save_binlog_format;
+set @@global.binlog_direct_non_transactional_updates= @save_binlog_dirct;
+
+create table t3(a int, b int) engine= innodb;
+create table t4(a int) engine= innodb;
+create table t5(a int) engine= innodb;
+delimiter |;
+eval create trigger tr1 after insert on t3 for each row begin
+ insert into t4(a) values(1);
+ set @@session.binlog_format= statement;
+ insert into t4(a) values(2);
+ insert into t5(a) values(3);
+end |
+delimiter ;|
+
+--echo # Test that the session variable 'binlog_format' is read-only
+--echo # in sub-statements.
+--echo # Current session value is ROW.
+--error ER_STORED_FUNCTION_PREVENTS_SWITCH_BINLOG_FORMAT
+insert into t3(a,b) values(1,1);
+SELECT @@session.binlog_format;
+
+create table t6(a int, b int) engine= innodb;
+create table t7(a int) engine= innodb;
+create table t8(a int) engine= innodb;
+delimiter |;
+eval create trigger tr2 after insert on t6 for each row begin
+ insert into t7(a) values(1);
+ set @@session.binlog_direct_non_transactional_updates= TRUE;
+ insert into t7(a) values(2);
+ insert into t8(a) values(3);
+end |
+delimiter ;|
+
+--echo # Test that the session variable
+--echo # 'binlog_direct_non_transactional_updates' is
+--echo # read-only in sub-statements.
+--echo # Current session value is FALSE.
+--error ER_STORED_FUNCTION_PREVENTS_SWITCH_BINLOG_DIRECT
+insert into t6(a,b) values(1,1);
+SELECT @@session.binlog_direct_non_transactional_updates;
+
+create table t9(a int, b int) engine= innodb;
+create table t10(a int) engine= innodb;
+create table t11(a int) engine= innodb;
+delimiter |;
+eval create trigger tr3 after insert on t9 for each row begin
+ insert into t10(a) values(1);
+ set @@session.sql_log_bin= TRUE;
+ insert into t10(a) values(2);
+ insert into t11(a) values(3);
+end |
+delimiter ;|
+
+--echo # Test that the session variable 'sql_log_bin' is
+--echo # read-only in sub-statements.
+--echo # Current session value is FALSE.
+--error ER_STORED_FUNCTION_PREVENTS_SWITCH_SQL_LOG_BIN
+insert into t9(a,b) values(1,1);
+SELECT @@session.sql_log_bin;
+
+drop table t1;
+drop table t2;
+drop table t3;
+drop table t4;
+drop table t5;
+drop table t6;
+drop table t7;
+drop table t8;
+drop table t9;
+drop table t10;
+drop table t11;
diff --git a/mysql-test/suite/binlog/t/binlog_table_map_optional_metadata.test b/mysql-test/suite/binlog/t/binlog_table_map_optional_metadata.test
new file mode 100644
index 00000000..4577c6c1
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_table_map_optional_metadata.test
@@ -0,0 +1,334 @@
+################################################################################
+# WL#4618 RBR: extended table metadata in the binary log
+#
+# Below metadata is logged into Table_map_log_event
+# - signedness of numeric columns
+# - charsets of character columns
+# - column names
+# - set/enum character sets and string values
+# - primary key
+#
+# The first two are always logged. The others are controlled by system
+# variable --binlog-row-metadata
+#
+# The test will verify if the metadata can be logged and printed by mysqlbinlog
+# correctly.
+# mysqlbinlog --print-table-metadata will print the extra metadata
+################################################################################
+--source include/have_debug.inc
+--source include/have_binlog_format_row.inc
+
+RESET MASTER;
+SET GLOBAL binlog_row_metadata = MINIMAL;
+
+--let $MYSQLD_DATADIR= `select @@datadir`
+--let $binlog_file= $MYSQLD_DATADIR/master-bin.000001
+
+--echo #
+--echo # Temporal types can be printed correctly
+--echo #
+CREATE TABLE t1(c_year YEAR, c_date DATE, c_time TIME, c_time_f TIME(3),
+ c_datetime DATETIME, c_datetime_f DATETIME(3),
+ c_timestamp TIMESTAMP NOT NULL DEFAULT NOW(),
+ c_timestamp_f TIMESTAMP(3) DEFAULT "2017-1-1 10:10:10");
+
+INSERT INTO t1(c_year) VALUES(2017);
+--source include/print_optional_metadata.inc
+
+DROP TABLE t1;
+RESET MASTER;
+
+--echo #
+--echo # Geometry types can be printed correctly
+--echo #
+CREATE TABLE t1 (c_geo GEOMETRY, c_point POINT, c_linestring LINESTRING,
+ c_polygon POLYGON, c_multi_point MULTIPOINT,
+ c_multi_linestring MULTILINESTRING, c_multi_polygon MULTIPOLYGON,
+ c_geometrycollection GEOMETRYCOLLECTION, c_char CHAR(100));
+
+INSERT INTO t1(c_point) VALUES(ST_PointFromText('POINT(10 10)'));
+--source include/print_optional_metadata.inc
+
+RESET MASTER;
+SET GLOBAL binlog_row_metadata = FULL;
+
+# geometry type is binlogged, the real geometry types are printed
+INSERT INTO t1(c_point) VALUES(ST_PointFromText('POINT(10 10)'));
+--source include/print_optional_metadata.inc
+
+DROP TABLE t1;
+RESET MASTER;
+
+--echo #
+--echo # Numeric types can be printed correctly
+--echo #
+CREATE TABLE t1(c_bit BIT(10), c_bool BOOL, c_smallint SMALLINT,
+ c_mediumint MEDIUMINT, c_int INT UNSIGNED, c_bigint BIGINT,
+ c_float FLOAT UNSIGNED, c_double DOUBLE, c_decimal DECIMAL(10, 2));
+
+SET GLOBAL binlog_row_metadata = MINIMAL;
+INSERT INTO t1(c_bool) VALUES(1);
+
+--echo # UNSIGNED flag should be printed
+--source include/print_optional_metadata.inc
+
+RESET MASTER;
+SET GLOBAL binlog_row_metadata = FULL;
+INSERT INTO t1(c_bool) VALUES(1);
+
+--source include/print_optional_metadata.inc
+
+DROP TABLE t1;
+RESET MASTER;
+
+--echo #
+--echo # Character types can be printed correctly
+--echo #
+CREATE TABLE t1(c_char CHAR(10), c_varchar VARCHAR(500),
+ c_tinytext TINYTEXT, c_text TEXT,
+ c_mediumtext MEDIUMTEXT, c_longtext LONGTEXT CHARSET utf8);
+
+SET GLOBAL binlog_row_metadata = MINIMAL;
+INSERT INTO t1(c_char) VALUES("1");
+
+# Charset set is printed with default charset
+--source include/print_optional_metadata.inc
+
+RESET MASTER;
+SET GLOBAL binlog_row_metadata = FULL;
+INSERT INTO t1(c_char) VALUES("1");
+
+--source include/print_optional_metadata.inc
+
+DROP TABLE t1;
+RESET MASTER;
+
+--echo #
+--echo # Column names with non-ascii characters and escape characters can be printed correctly
+--echo #
+set names utf8;
+CREATE TABLE t1(`åäö表\a'``"` INT);
+
+SHOW CREATE TABLE t1;
+
+INSERT INTO t1 VALUES(1);
+--source include/print_optional_metadata.inc
+DROP TABLE t1;
+RESET MASTER;
+--echo #
+--echo # Charsets can be printed correctly
+--echo #
+CREATE TABLE t1(c_char_utf8 CHAR(10) CHARSET utf8,
+ c_varchar_utf8 VARCHAR(10) CHARSET utf8,
+ c_text_utf8 TEXT CHARSET utf8);
+
+INSERT INTO t1 VALUES("1", "2", "3");
+
+# Charset set is printed with Default charset
+--source include/print_optional_metadata.inc
+
+DROP TABLE t1;
+RESET MASTER;
+
+# Test collation number less than 250 and collation number greater than 250
+CREATE TABLE t1(c_utf8mb4_520 CHAR(10) CHARSET utf8mb4 COLLATE utf8mb4_unicode_ci,
+ c_utf8mb4_0900 VARCHAR(10) CHARSET utf8mb4 COLLATE utf8mb4_polish_ci,
+ c_utf8mb4_def TEXT CHARSET utf8mb4);
+
+INSERT INTO t1 VALUES("1", "2", "3");
+
+# Charset set is printed without default charset
+--source include/print_optional_metadata.inc
+
+DROP TABLE t1;
+RESET MASTER;
+
+--echo #
+--echo # Blob and binary columns can be printed correctly
+--echo #
+CREATE TABLE t1(c_binary BINARY(10), c_varbinary VARBINARY(10),
+ c_tinyblob TINYBLOB, c_blob BLOB,
+ c_mediumblob MEDIUMBLOB, c_longblob LONGBLOB);
+
+INSERT INTO t1 VALUES("1", "2", "3", "4", "5", "6");
+--source include/print_optional_metadata.inc
+
+DROP TABLE t1;
+RESET MASTER;
+
+--echo #
+--echo # Verify that SET string values and character sets can be printed correctly
+--echo #
+
+set names utf8;
+CREATE TABLE t1(
+ c_set_1 SET("set1_v1_å", "set1_v2_ä", "set1_v3_ö"),
+ c_set_2 SET("set2_v1_å", "set2_v2_ä", "set2_v3_ö") CHARACTER SET latin1,
+ c_set_4 SET("set3_v1_å", "set3_v2_ä", "set3_v3_ö") CHARACTER SET swe7 COLLATE swe7_bin);
+
+SET GLOBAL binlog_row_metadata = MINIMAL;
+INSERT INTO t1 VALUES("set1_v1_å", "set2_v3_ö", "set3_v1_å");
+--source include/print_optional_metadata.inc
+
+RESET MASTER;
+SET GLOBAL binlog_row_metadata = FULL;
+INSERT INTO t1 VALUES("set1_v1_å", "set2_v3_ö", "set3_v1_å");
+--source include/print_optional_metadata.inc
+
+DROP TABLE t1;
+RESET MASTER;
+
+--echo #
+--echo # Verify that ENUM string values and character sets can be printed correctly
+--echo #
+
+CREATE TABLE t1(
+ c_enum_1 ENUM("enum1_v1_å", "enum1_v2_ä", "enum1_v3_ö"),
+ c_enum_3 ENUM("enum2_v1_å", "enum2_v2_ä", "enum2_v3_ö") CHARACTER SET latin1,
+ c_enum_4 ENUM("enum3_v1_å", "enum3_v2_ä", "enum3_v3_ö") CHARACTER SET swe7 COLLATE swe7_bin);
+
+SET GLOBAL binlog_row_metadata = MINIMAL;
+INSERT INTO t1 VALUES("enum1_v1_å", "enum2_v3_ö", "enum3_v1_å");
+--source include/print_optional_metadata.inc
+
+RESET MASTER;
+SET GLOBAL binlog_row_metadata = FULL;
+INSERT INTO t1 VALUES("enum1_v1_å", "enum2_v3_ö", "enum3_v1_å");
+--source include/print_optional_metadata.inc
+
+DROP TABLE t1;
+RESET MASTER;
+
+--echo #
+--echo # Verify that explicit NOT NULL can be printed correctly
+--echo #
+CREATE TABLE t1(c_not_null1 INT NOT NULL, c_null1 INT, c_not_null2 INT NOT NULL,
+ c_null2 INT);
+
+INSERT INTO t1 VALUES(1, 2, 3, 4);
+--source include/print_optional_metadata.inc
+
+DROP TABLE t1;
+RESET MASTER;
+
+--echo #
+--echo # Verify that primary key can be printed correctly
+--echo #
+CREATE TABLE t1(c_key1 INT, c_key3 INT, c_not_key INT, c_key2 INT,
+PRIMARY KEY(c_key1, c_key2, c_key3));
+
+INSERT INTO t1 VALUES(1, 2, 3, 4);
+--let $print_primary_key= 1
+--source include/print_optional_metadata.inc
+
+DROP TABLE t1;
+RESET MASTER;
+
+# Key has prefix
+CREATE TABLE t1(c_key1 CHAR(100), c_key3 CHAR(100), c_not_key INT, c_key2 CHAR(10),
+PRIMARY KEY(c_key1(5), c_key2, c_key3(10)));
+
+INSERT INTO t1 VALUES("1", "2", 3, "4");
+--source include/print_optional_metadata.inc
+
+RESET MASTER;
+# Primary key should not be printed
+SET GLOBAL binlog_row_metadata = MINIMAL;
+
+INSERT INTO t1 VALUES("2", "2", 3, "4");
+--source include/print_optional_metadata.inc
+
+RESET MASTER;
+--echo #
+--echo # Coverage test: Print column index instead of column name if column name
+--echo # is not binlogged.
+--echo #
+SET GLOBAL binlog_row_metadata = FULL;
+
+SET SESSION debug_dbug = 'd, dont_log_column_name';
+INSERT INTO t1 VALUES("3", "2", 3, "4");
+--source include/print_optional_metadata.inc
+
+--let $print_primary_key=
+DROP TABLE t1;
+RESET MASTER;
+
+--echo #
+--echo # Coverage test: Inject an invalid column type
+--echo #
+CREATE TABLE t1(c1 int, c2 BLOB);
+
+SET SESSION debug_dbug = 'd,inject_invalid_column_type';
+INSERT INTO t1 VALUES(1, "a");
+# It prints an error
+--source include/print_optional_metadata.inc
+
+RESET MASTER;
+
+--echo #
+--echo # Coverage test: Inject an invalid BLOB metadata
+--echo #
+--let $start_pos= query_get_value(SHOW MASTER STATUS, Position, 1)
+
+SET SESSION debug_dbug = 'd,inject_invalid_blob_size';
+INSERT INTO t1 VALUES(2, "b");
+
+# The invalid metadata will case assertion failure on Write_rows_log_event
+# So we need to stop mysqlbinlog before reading Write_rows_log_event.
+--let $stop_position= query_get_value(SHOW BINLOG EVENTS FROM $start_pos LIMIT 3, End_log_pos, 3)
+--source include/print_optional_metadata.inc
+
+--echo #
+--echo # Coverage test: Inject an invalid Geometry type
+--echo #
+DROP TABLE t1;
+CREATE TABLE t1(c_geometry GEOMETRY, c_point POINT, c_multilinestring MULTILINESTRING);
+RESET MASTER;
+--let $start_pos= query_get_value(SHOW MASTER STATUS, Position, 1)
+
+SET SESSION debug_dbug = 'd,inject_invalid_geometry_type';
+INSERT INTO t1(c_point) VALUES(ST_PointFromText('POINT(10 10)'));
+
+# The invalid metadata will case assertion failure on Write_rows_log_event
+# So we need to stop mysqlbinlog before reading Write_rows_log_event.
+--let $stop_position= query_get_value(SHOW BINLOG EVENTS FROM $start_pos LIMIT 3, End_log_pos, 3)
+--source include/print_optional_metadata.inc
+
+DROP TABLE t1;
+RESET MASTER;
+--echo #
+--echo # Comptibility Test: Verify mysqlbinlog can print OLD table_map_log_event
+--echo # without any optional metadata
+--echo #
+CREATE TABLE t1(c_int INT, c_tiny_int_unsigned TINYINT UNSIGNED,
+ c_binary BINARY(10), c_text TEXT, c_point POINT);
+
+SET session debug_dbug='d,simulate_no_optional_metadata';
+INSERT INTO t1(c_int) VALUES(1);
+# TINYINT will be printed without UNSIGNED flag,
+# CHAR will be printed as BINARY(10)
+# POINT will be printed as GEOMETRY
+--let $stop_position=
+--source include/print_optional_metadata.inc
+
+DROP TABLE t1;
+RESET MASTER;
+--echo #
+--echo # Simulate error on initializing charset and primary key metadata
+--echo #
+CREATE TABLE t1(c1 char(10) PRIMARY KEY);
+
+SET session debug_dbug='d,simulate_init_charset_field_error';
+INSERT INTO t1 VALUES("a");
+
+SET GLOBAL binlog_row_metadata = FULL;
+SET session debug_dbug='d,simulate_init_primary_key_field_error';
+INSERT INTO t1 VALUES("b");
+
+--let $print_primary_key= 1
+--source include/print_optional_metadata.inc
+
+SET SESSION debug_dbug = '';
+SET GLOBAL binlog_row_metadata = NO_LOG;
+DROP TABLE t1;
+RESET MASTER;
diff --git a/mysql-test/suite/binlog/t/binlog_table_map_optional_metadata_binary.test b/mysql-test/suite/binlog/t/binlog_table_map_optional_metadata_binary.test
new file mode 100644
index 00000000..29e10ede
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_table_map_optional_metadata_binary.test
@@ -0,0 +1,74 @@
+################################################################################
+# WL#4618 RBR: extended table metadata in the binary log
+#
+# Below metadata is logged into Table_map_log_event
+# - signedness of numeric columns
+# - charsets of character columns
+# - column names
+# - set/enum character sets and string values
+# - primary key
+#
+# The first two are always logged. The others are controlled by system
+# variable --binlog-row-metadata
+#
+# The test will verify if the metadata can be logged and printed by mysqlbinlog
+# correctly.
+# mysqlbinlog --print-table-metadata will print the extra metadata
+################################################################################
+--source include/have_debug.inc
+--source include/have_binlog_format_row.inc
+--let $MYSQLD_DATADIR= `select @@datadir`
+--let $binlog_file= $MYSQLD_DATADIR/master-bin.000001
+
+RESET MASTER;
+--echo #
+--echo # Verify that SET string values and character sets can be printed correctly
+--echo #
+
+SET NAMES utf8;
+CREATE TABLE t1(
+ c_set_1 SET("set1_v1_å", "set1_v2_ä", "set1_v3_ö"),
+ c_set_2 SET("set2_v1_å", "set2_v2_ä", "set2_v3_ö") CHARACTER SET binary);
+
+SET GLOBAL binlog_row_metadata = MINIMAL;
+INSERT INTO t1 VALUES("set1_v1_å", "set2_v2_ä");
+--source include/print_optional_metadata.inc
+
+RESET MASTER;
+SET GLOBAL binlog_row_metadata = FULL;
+INSERT INTO t1 VALUES("set1_v1_å", "set2_v2_ä");
+--source include/print_optional_metadata.inc
+INSERT INTO t1 VALUES("set1_v3_ö", "set2_v3_ö");
+INSERT INTO t1 VALUES("set1_v1_Ã¥", "set2_v1_Ã¥");
+SELECT c_set_1, HEX(c_set_1) FROM t1;
+SELECT c_set_2, HEX(c_set_2) FROM t1;
+
+DROP TABLE t1;
+RESET MASTER;
+
+--echo #
+--echo # Verify that ENUM string values and character sets can be printed correctly
+--echo #
+
+CREATE TABLE t1(
+ c_enum_1 ENUM("enum1_v1_å", "enum1_v2_ä", "enum1_v3_ö"),
+ c_enum_2 ENUM("enum2_v1_å", "enum2_v2_ä", "enum2_v3_ö") CHARACTER SET binary);
+
+SET GLOBAL binlog_row_metadata = MINIMAL;
+INSERT INTO t1 VALUES("enum1_v1_å", "enum2_v2_ä");
+--source include/print_optional_metadata.inc
+
+
+RESET MASTER;
+SET GLOBAL binlog_row_metadata = FULL;
+INSERT INTO t1 VALUES("enum1_v1_å", "enum2_v2_ä");
+--source include/print_optional_metadata.inc
+INSERT INTO t1 VALUES("enum1_v3_ö", "enum2_v3_ö");
+INSERT INTO t1 VALUES("enum1_v1_Ã¥", "enum2_v1_Ã¥");
+SELECT c_enum_1, HEX(c_enum_1) FROM t1;
+SELECT c_enum_2, HEX(c_enum_2) FROM t1;
+
+DROP TABLE t1;
+RESET MASTER;
+
+SET GLOBAL binlog_row_metadata = NO_LOG;
diff --git a/mysql-test/suite/binlog/t/binlog_table_map_optional_metadata_ucs2.test b/mysql-test/suite/binlog/t/binlog_table_map_optional_metadata_ucs2.test
new file mode 100644
index 00000000..8c9e2242
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_table_map_optional_metadata_ucs2.test
@@ -0,0 +1,75 @@
+################################################################################
+# WL#4618 RBR: extended table metadata in the binary log
+#
+# Below metadata is logged into Table_map_log_event
+# - signedness of numeric columns
+# - charsets of character columns
+# - column names
+# - set/enum character sets and string values
+# - primary key
+#
+# The first two are always logged. The others are controlled by system
+# variable --binlog-row-metadata
+#
+# The test will verify if the metadata can be logged and printed by mysqlbinlog
+# correctly.
+# mysqlbinlog --print-table-metadata will print the extra metadata
+################################################################################
+--source include/have_debug.inc
+--source include/have_binlog_format_row.inc
+--source include/have_ucs2.inc
+--let $MYSQLD_DATADIR= `select @@datadir`
+--let $binlog_file= $MYSQLD_DATADIR/master-bin.000001
+
+RESET MASTER;
+--echo #
+--echo # Verify that SET string values and character sets can be printed correctly
+--echo #
+
+SET NAMES utf8;
+CREATE TABLE t1(
+ c_set_1 SET("set1_v1_å", "set1_v2_ä", "set1_v3_ö"),
+ c_set_2 SET("set2_v1_å", "set2_v2_ä", "set2_v3_ö") CHARACTER SET ucs2);
+
+SET GLOBAL binlog_row_metadata = MINIMAL;
+INSERT INTO t1 VALUES("set1_v1_å", "set2_v2_ä");
+--source include/print_optional_metadata.inc
+
+RESET MASTER;
+SET GLOBAL binlog_row_metadata = FULL;
+INSERT INTO t1 VALUES("set1_v1_å", "set2_v2_ä");
+--source include/print_optional_metadata.inc
+INSERT INTO t1 VALUES("set1_v3_ö", "set2_v3_ö");
+INSERT INTO t1 VALUES("set1_v1_Ã¥", "set2_v1_Ã¥");
+SELECT c_set_1, HEX(c_set_1) FROM t1;
+SELECT c_set_2, HEX(c_set_2) FROM t1;
+
+DROP TABLE t1;
+RESET MASTER;
+
+--echo #
+--echo # Verify that ENUM string values and character sets can be printed correctly
+--echo #
+
+CREATE TABLE t1(
+ c_enum_1 ENUM("enum1_v1_å", "enum1_v2_ä", "enum1_v3_ö"),
+ c_enum_2 ENUM("enum2_v1_å", "enum2_v2_ä", "enum2_v3_ö") CHARACTER SET ucs2);
+
+SET GLOBAL binlog_row_metadata = MINIMAL;
+INSERT INTO t1 VALUES("enum1_v1_å", "enum2_v2_ä");
+--source include/print_optional_metadata.inc
+
+
+RESET MASTER;
+SET GLOBAL binlog_row_metadata = FULL;
+INSERT INTO t1 VALUES("enum1_v1_å", "enum2_v2_ä");
+--source include/print_optional_metadata.inc
+INSERT INTO t1 VALUES("enum1_v3_ö", "enum2_v3_ö");
+INSERT INTO t1 VALUES("enum1_v1_Ã¥", "enum2_v1_Ã¥");
+SELECT c_enum_1, HEX(c_enum_1) FROM t1;
+SELECT c_enum_2, HEX(c_enum_2) FROM t1;
+
+DROP TABLE t1;
+RESET MASTER;
+
+SET GLOBAL binlog_row_metadata = NO_LOG;
diff --git a/mysql-test/suite/binlog/t/binlog_table_map_optional_metadata_utf32.test b/mysql-test/suite/binlog/t/binlog_table_map_optional_metadata_utf32.test
new file mode 100644
index 00000000..094de058
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_table_map_optional_metadata_utf32.test
@@ -0,0 +1,75 @@
+################################################################################
+# WL#4618 RBR: extended table metadata in the binary log
+#
+# Below metadata is logged into Table_map_log_event
+# - signedness of numeric columns
+# - charsets of character columns
+# - column names
+# - set/enum character sets and string values
+# - primary key
+#
+# The first two are always logged. The others are controlled by system
+# variable --binlog-row-metadata
+#
+# The test will verify if the metadata can be logged and printed by mysqlbinlog
+# correctly.
+# mysqlbinlog --print-table-metadata will print the extra metadata
+################################################################################
+--source include/have_debug.inc
+--source include/have_binlog_format_row.inc
+--source include/have_utf32.inc
+--let $MYSQLD_DATADIR= `select @@datadir`
+--let $binlog_file= $MYSQLD_DATADIR/master-bin.000001
+
+RESET MASTER;
+--echo #
+--echo # Verify that SET string values and character sets can be printed correctly
+--echo #
+
+SET NAMES utf8;
+CREATE TABLE t1(
+ c_set_1 SET("set1_v1_å", "set1_v2_ä", "set1_v3_ö"),
+ c_set_2 SET("set2_v1_å", "set2_v2_ä", "set2_v3_ö") CHARACTER SET utf32);
+
+SET GLOBAL binlog_row_metadata = MINIMAL;
+INSERT INTO t1 VALUES("set1_v1_å", "set2_v2_ä");
+--source include/print_optional_metadata.inc
+
+RESET MASTER;
+SET GLOBAL binlog_row_metadata = FULL;
+INSERT INTO t1 VALUES("set1_v1_å", "set2_v2_ä");
+--source include/print_optional_metadata.inc
+INSERT INTO t1 VALUES("set1_v3_ö", "set2_v3_ö");
+INSERT INTO t1 VALUES("set1_v1_Ã¥", "set2_v1_Ã¥");
+SELECT c_set_1, HEX(c_set_1) FROM t1;
+SELECT c_set_2, HEX(c_set_2) FROM t1;
+
+DROP TABLE t1;
+RESET MASTER;
+
+--echo #
+--echo # Verify that ENUM string values and character sets can be printed correctly
+--echo #
+
+CREATE TABLE t1(
+ c_enum_1 ENUM("enum1_v1_å", "enum1_v2_ä", "enum1_v3_ö"),
+ c_enum_2 ENUM("enum2_v1_å", "enum2_v2_ä", "enum2_v3_ö") CHARACTER SET utf32);
+
+SET GLOBAL binlog_row_metadata = MINIMAL;
+INSERT INTO t1 VALUES("enum1_v1_å", "enum2_v2_ä");
+--source include/print_optional_metadata.inc
+
+
+RESET MASTER;
+SET GLOBAL binlog_row_metadata = FULL;
+INSERT INTO t1 VALUES("enum1_v1_å", "enum2_v2_ä");
+--source include/print_optional_metadata.inc
+INSERT INTO t1 VALUES("enum1_v3_ö", "enum2_v3_ö");
+INSERT INTO t1 VALUES("enum1_v1_Ã¥", "enum2_v1_Ã¥");
+SELECT c_enum_1, HEX(c_enum_1) FROM t1;
+SELECT c_enum_2, HEX(c_enum_2) FROM t1;
+
+DROP TABLE t1;
+RESET MASTER;
+
+SET GLOBAL binlog_row_metadata = NO_LOG;
diff --git a/mysql-test/suite/binlog/t/binlog_tmp_table.test b/mysql-test/suite/binlog/t/binlog_tmp_table.test
new file mode 100644
index 00000000..45428530
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_tmp_table.test
@@ -0,0 +1,159 @@
+# ==== Purpose ====
+#
+# Test if statements used temporary tables are binlogged correctly
+#
+# ==== Method ====
+#
+# Use two connections, use temporary tables on both of them, and by
+# switching connections between statements, the test can check if the
+# statements are logged with the correct thread id.
+#
+# The statements current tested include:
+# CREATE TEMPORARY TABLE
+# CREATE TEMPORARY TABLE LIKE
+# INSERT
+# REPLACE
+# UPDATE
+# INSERT SELECT
+# TRUNCATE
+#
+# Note: When adding new query statements, please add them between the
+# two 'flush logs'. And aslo please make sure the connection is
+# switched between each statement.
+#
+# ==== Related bugs ====
+#
+# BUG#35583 mysqlbinlog replay fails with ERROR 1146 when temp tables are used
+#
+source include/have_log_bin.inc;
+source include/have_binlog_format_mixed_or_statement.inc;
+
+RESET MASTER;
+
+--disable_query_log
+CALL mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT");
+--enable_query_log
+
+connect (master,127.0.0.1,root,,test,$MASTER_MYPORT,);
+connect (master1,127.0.0.1,root,,test,$MASTER_MYPORT,);
+
+create table foo (a int);
+
+flush logs;
+
+connection master;
+create temporary table tmp1_foo like foo;
+connection master1;
+create temporary table tmp2_foo (a int);
+
+connection master;
+insert into tmp1_foo values (1), (2), (3), (4);
+connection master1;
+replace into tmp2_foo values (1), (2), (3), (4);
+
+connection master;
+update tmp1_foo set a=2*a-1;
+connection master1;
+update tmp2_foo set a=2*a;
+
+connection master;
+delete from tmp1_foo where a < 5;
+connection master1;
+delete from tmp2_foo where a < 5;
+
+--disable_warnings
+connection master;
+insert into foo select * from tmp1_foo;
+connection master1;
+insert into foo select * from tmp2_foo;
+--enable_warnings
+
+connection master;
+truncate table tmp1_foo;
+connection master1;
+truncate table tmp2_foo;
+
+let $binlog_file= query_get_value(SHOW MASTER STATUS, File, 1);
+
+flush logs;
+
+connection default;
+select * from foo;
+
+# prepare for the replay
+drop table foo;
+create table foo (a int);
+
+# replay from binary log
+let $MYSQLD_DATADIR= `select @@datadir`;
+exec $MYSQL_BINLOG $MYSQLD_DATADIR/$binlog_file | $MYSQL;
+select * from foo;
+
+# clean up
+drop table foo;
+
+#################################################################
+# BUG#51226
+#################################################################
+
+RESET MASTER;
+
+-- let $dbname=b51226
+
+connect (con1,localhost,root,,test,$MASTER_MYPORT,$MASTER_MYSOCK);
+connect (con2,localhost,root,,test,$MASTER_MYPORT,$MASTER_MYSOCK);
+
+#
+# action: on con1 create the database and the tmp table
+#
+-- connection con1
+-- eval create database $dbname
+-- eval use $dbname
+create temporary table t1(i int);
+
+#
+# action: on con1 create the tmp table
+#
+-- connection con2
+-- eval use $dbname
+create temporary table t1(i int);
+
+# action: at this point, the last event binlogged contains the
+# pseudo_thread_id from con2. So now we switch to con1, issue
+# a statement that fails and close the connection (which logs
+# implicitely a DROP TEMPORARY TABLE).
+#
+# Before the patch this would not log con1's pseudo_thread_id
+# because the failing statement would reset THD context
+# (unsetting the thread_specific_used flag, and consequently,
+# causing the DROP event to be logged without pseudo_thread_id
+# in its header).
+
+-- connection con1
+-- error 1050
+create temporary table t1(i int);
+-- disconnect con1
+
+-- connection default
+-- let $wait_binlog_event= DROP
+-- source include/wait_for_binlog_event.inc
+
+# action: insert in the t1. This would cause the the test to fail,
+# because when replaying the binlog the previous implicit drop
+# temp table would have been executed under the wrong
+# pseudo_thread_id, dropping the tmp table on con2.
+-- connection con2
+insert into t1 values(1);
+-- disconnect con2
+
+-- connection default
+-- let $wait_binlog_event= DROP
+-- source include/wait_for_binlog_event.inc
+
+-- eval DROP DATABASE $dbname
+FLUSH LOGS;
+
+# assertion: assert that when replaying the binary log will succeed,
+# instead of failing with "Table 'XXX.YYY' doesn't exist"
+-- let $MYSQLD_DATADIR= `select @@datadir`
+-- exec $MYSQL_BINLOG $MYSQLD_DATADIR/master-bin.000001 | $MYSQL
diff --git a/mysql-test/suite/binlog/t/binlog_tmp_table_row.test b/mysql-test/suite/binlog/t/binlog_tmp_table_row.test
new file mode 100644
index 00000000..ce11c880
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_tmp_table_row.test
@@ -0,0 +1,30 @@
+# ==== Purpose ====
+#
+# Test if statements used temporary tables are not binlogged in the case of
+# binlog_format=row
+#
+# ==== Method ====
+#
+# We will see if binlog file size is increased or not, It should be constant for the
+# entire period of test.
+#
+# ==== Related bugs ====
+#
+# Mdev-9266
+#
+source include/have_log_bin.inc;
+source include/have_binlog_format_row.inc;
+
+RESET MASTER;
+
+--echo #Create table test
+--let $sql_query= create temporary table t1(a int, b int)
+--source suite/binlog/include/check_binlog_size.inc
+
+--echo #Add index test
+--let $sql_query= create index index_a on t1(a)
+--source suite/binlog/include/check_binlog_size.inc
+
+--echo #drop index test
+--let $sql_query= drop index index_a on t1
+--source suite/binlog/include/check_binlog_size.inc
diff --git a/mysql-test/suite/binlog/t/binlog_trigger.test b/mysql-test/suite/binlog/t/binlog_trigger.test
new file mode 100644
index 00000000..3f93d6e8
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_trigger.test
@@ -0,0 +1,51 @@
+--source include/not_embedded.inc
+--source include/have_binlog_format_statement.inc
+
+--disable_query_log
+reset master; # get rid of previous tests binlog
+--enable_query_log
+
+--echo #
+--echo # WL#3253: multiple triggers per table
+--echo #
+
+--echo # Testing that the FOLLOWS and PRECEDES clauses get logged
+
+CREATE TABLE t1 (a INT, b INT);
+CREATE TRIGGER tr1_bi BEFORE INSERT ON t1 FOR EACH ROW INSERT INTO t2 (a) VALUES (NEW.a + 100);
+CREATE TRIGGER tr4_bi BEFORE INSERT ON t1 FOR EACH ROW INSERT INTO t2 (a) VALUES (NEW.a + 300);
+CREATE TRIGGER tr2_bi BEFORE INSERT ON t1 FOR EACH ROW FOLLOWS tr1_bi INSERT INTO t2 (a) VALUES (NEW.a + 200);
+CREATE TRIGGER tr3_bi BEFORE INSERT ON t1 FOR EACH ROW precedes tr4_bi INSERT INTO t2 (a) VALUES (NEW.a + 400);
+DROP TABLE t1;
+
+
+--let $binlog_file = LAST
+source include/show_binlog_events.inc;
+
+--echo #
+--echo # MDEV-25517 Atomic DDL: Assertion `query_arg' in THD::binlog_query
+--echo # upon DROP TRIGGER
+--echo #
+
+# This test case is 'random' by design. For most cases the second DROP TRIGGER
+# will generate a warning "Dropped orphan trigger...", but if there is a timing
+# issue, we may get another error or warning later. This is ok as it enables
+# us to have more code paths tested over time.
+
+CREATE TABLE t1 (a INT);
+CREATE TRIGGER trg AFTER INSERT ON t1 FOR EACH ROW SET @x = 1;
+--disable_warnings
+--connect (con1,localhost,root,,test)
+--send
+ DROP TRIGGER trg;
+--connection default
+--error 0,ER_TRG_DOES_NOT_EXIST
+DROP TRIGGER trg;
+# Cleanup
+--connection con1
+--error 0,ER_TRG_DOES_NOT_EXIST
+--reap
+--disconnect con1
+--connection default
+--enable_warnings
+DROP TABLE t1;
diff --git a/mysql-test/suite/binlog/t/binlog_truncate_active_log.inc b/mysql-test/suite/binlog/t/binlog_truncate_active_log.inc
new file mode 100644
index 00000000..68ac7527
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_truncate_active_log.inc
@@ -0,0 +1,70 @@
+connect(master1,localhost,root,,);
+connect(master2,localhost,root,,);
+connect(master3,localhost,root,,);
+connect(master4,localhost,root,,);
+
+--connection default
+
+# First to commit few transactions
+INSERT INTO t VALUES (10);
+INSERT INTO tm VALUES (10);
+
+--connection master1
+# Hold insert after write to binlog and before "run_commit_ordered" in engine
+SET DEBUG_SYNC= "commit_before_get_LOCK_commit_ordered SIGNAL master1_ready WAIT_FOR signal_never_arrives";
+--send_eval $query1
+
+--connection master2
+SET DEBUG_SYNC= "now WAIT_FOR master1_ready";
+SET DEBUG_SYNC= "commit_before_get_LOCK_after_binlog_sync SIGNAL master2_ready";
+--send_eval $query2
+
+--connection master3
+SET DEBUG_SYNC= "now WAIT_FOR master2_ready";
+SELECT @@global.gtid_binlog_pos as 'Before the crash';
+
+--connection master4
+# Simulate prepared & not-logged trx; it will never recover.
+SET DEBUG_SYNC= "ha_commit_trans_before_log_and_order SIGNAL master4_ready WAIT_FOR signal_never_arrives";
+--send INSERT INTO t4 VALUES (13)
+
+--connection master3
+SET DEBUG_SYNC= "now WAIT_FOR master4_ready";
+SELECT @@global.gtid_binlog_pos as 'Before the crash and never logged trx';
+
+--connection default
+--source include/kill_mysqld.inc
+--disconnect master1
+--disconnect master2
+--disconnect master3
+--disconnect master4
+
+#
+# Server restart
+#
+--let $restart_parameters= --rpl-semi-sync-slave-enabled=1 --sync-binlog=1 --log-warnings=3
+--source include/start_mysqld.inc
+
+# Check error log for a successful truncate message.
+--let $log_error_ = $MYSQLTEST_VARDIR/log/mysqld.1.err
+
+--let SEARCH_FILE=$log_error_
+--let SEARCH_PATTERN=Successfully truncated.*to remove transactions starting from GTID $truncate_gtid_pos
+
+--source include/search_pattern_in_file.inc
+
+--echo Pre-crash binlog file content:
+--let $binlog_file= query_get_value(show binary logs, Log_name, $binlog_file_index)
+--source include/show_binlog_events.inc
+
+SELECT @@global.gtid_binlog_pos as 'After the crash';
+--echo "One row should be present in table 't'"
+SELECT * FROM t;
+--echo "No row should be present in table 't4'"
+SELECT * FROM t4;
+
+# prepare binlog file index for the next test
+--inc $binlog_file_index
+
+# Local cleanup
+DELETE FROM t;
diff --git a/mysql-test/suite/binlog/t/binlog_truncate_active_log.test b/mysql-test/suite/binlog/t/binlog_truncate_active_log.test
new file mode 100644
index 00000000..7c63a853
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_truncate_active_log.test
@@ -0,0 +1,104 @@
+# ==== Purpose ====
+#
+# Test verifies the truncation of single binary log file.
+#
+# ==== References ====
+#
+# MDEV-21117: recovery for --rpl-semi-sync-slave-enabled server
+
+--source include/have_innodb.inc
+--source include/have_aria.inc
+# File: binlog_truncate_active_log.inc included in test makes use of
+# 'debug_sync' facility.
+--source include/have_debug_sync.inc
+--source include/have_binlog_format_statement.inc
+
+call mtr.add_suppression("Can.t init tc log");
+call mtr.add_suppression("Aborting");
+
+# The following cases are tested:
+# A. 2pc transaction is followed by a blank "zero-engines" one
+# B. 2pc transaction follows the blank one
+# C. Similarly to A, with the XA blank transaction
+
+RESET MASTER;
+SET @@global.sync_binlog=1;
+CREATE TABLE t (f INT) ENGINE=INNODB;
+CREATE TABLE t2 (f INT) ENGINE=INNODB;
+CREATE TABLE t4 (f INT) ENGINE=INNODB;
+CREATE TABLE tm (f INT) ENGINE=Aria;
+
+# Old (pre-crash) binlog file index initial value.
+# It keeps incremented at the end of each case.
+--let $binlog_file_index=1
+
+--echo # Case A.
+# Using 'debug_sync' hold 'query1' execution after 'query1' is flushed and
+# synced to binary log but not yet committed. In an another connection hold
+# 'query2' execution after 'query2' is flushed and synced to binlog.
+# Crash and restart server with --rpl-semi-sync-slave-enabled=1
+#
+# During recovery of binary log 'query1' status is checked with InnoDB engine,
+# it will be in prepared but not yet commited. All transactions starting from
+# 'query1' onwards will be removed from the binary log.
+# Show-binlog-events is to prove that.
+
+--let $truncate_gtid_pos = 0-1-7
+--let $query1 = INSERT INTO t VALUES (20)
+--let $query2 = DELETE FROM t2 WHERE f = 0 /* no such record */
+--source binlog_truncate_active_log.inc
+
+--echo # Case B.
+# The inverted sequence ends up to truncate starting from $query2
+--let $truncate_gtid_pos = 0-1-11
+--let $query1 = DELETE FROM t2 WHERE f = 0
+--let $query2 = INSERT INTO t VALUES (20)
+--source binlog_truncate_active_log.inc
+
+
+--echo # Case C.
+delimiter |;
+CREATE PROCEDURE sp_blank_xa()
+BEGIN
+ XA START 'blank';
+ DELETE FROM t2 WHERE f = 0 /* no such record */;
+ XA END 'blank';
+ XA PREPARE 'blank';
+END|
+delimiter ;|
+
+# The same as in A with $query2 being the zero-engine XA transaction.
+# Both $query1 and $query2 are going to be truncated.
+--let $truncate_gtid_pos = 0-1-15
+--let $query1 = INSERT INTO t VALUES (20)
+--let $query2 = CALL sp_blank_xa
+--source binlog_truncate_active_log.inc
+
+DROP PROCEDURE sp_blank_xa;
+
+
+--echo # Case D.
+delimiter |;
+CREATE PROCEDURE sp_xa()
+BEGIN
+ XA START 'xid';
+ DELETE FROM t WHERE f = 10;
+ XA END 'xid';
+ XA PREPARE 'xid';
+END|
+delimiter ;|
+
+# The same as in B with $query1 being the prepared XA transaction.
+# Truncation must occurs at $query2.
+--let $truncate_gtid_pos = 0-1-21
+--let $query1 = CALL sp_xa
+--let $query2 = INSERT INTO t2 VALUES (20)
+--source binlog_truncate_active_log.inc
+
+DROP PROCEDURE sp_xa;
+
+
+--echo # Cleanup
+DROP TABLE t,t2,tm;
+SET @@global.sync_binlog= default;
+--echo # End of the tests
diff --git a/mysql-test/suite/binlog/t/binlog_truncate_innodb.test b/mysql-test/suite/binlog/t/binlog_truncate_innodb.test
new file mode 100644
index 00000000..511b82bd
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_truncate_innodb.test
@@ -0,0 +1,45 @@
+source include/have_log_bin.inc;
+source include/have_innodb.inc;
+
+let $engine = InnoDB;
+
+SET @old_binlog_format=@@binlog_format;
+
+SET BINLOG_FORMAT=ROW;
+RESET MASTER;
+
+source include/binlog_truncate.test;
+
+--echo # Even though the isolation level might be permissive, truncate
+--echo # table follows a stricter isolation as its locking is based on
+--echo # (exclusive) metadata locks.
+
+let $before_truncate = SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+source include/binlog_truncate.test;
+
+let $before_truncate = SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
+source include/binlog_truncate.test;
+
+let $before_truncate = SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;
+source include/binlog_truncate.test;
+
+let $before_truncate = SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
+source include/binlog_truncate.test;
+
+SET BINLOG_FORMAT=STATEMENT;
+RESET MASTER;
+
+source include/binlog_truncate.test;
+
+--echo # Truncate is not supported for SBR if the isolation level is
+--echo # READ UNCOMMITTED or READ COMMITTED. These specific isolation
+--echo # levels are tested elsewhere.
+
+let $before_truncate = SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;
+source include/binlog_truncate.test;
+
+let $before_truncate = SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
+source include/binlog_truncate.test;
+
+SET @@global.binlog_format = @old_binlog_format;
+SET @@session.binlog_format = @old_binlog_format; \ No newline at end of file
diff --git a/mysql-test/suite/binlog/t/binlog_truncate_kill.test b/mysql-test/suite/binlog/t/binlog_truncate_kill.test
new file mode 100644
index 00000000..0b9e873d
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_truncate_kill.test
@@ -0,0 +1,55 @@
+###############################################################################
+# Bug#17942050:KILL OF TRUNCATE TABLE WILL LEAD TO BINARY LOG WRITTEN WHILE
+# ROWS REMAINS
+#
+# Problem:
+# ========
+# When truncate table fails while using transactional based engines even
+# though the operation errors out we still continue and log it to binlog.
+# Because of this master has data but the truncate will be written to binary
+# log which will cause inconsistency.
+#
+# Test:
+# =====
+# Make master to wait in "open_table" call during the execution of truncate
+# table command and kill the truncate table from other connection. This causes
+# open table to return an error saying truncate failed during open table. This
+# statement should not be binlogged.
+###############################################################################
+--source include/have_innodb.inc
+--source include/have_debug_sync.inc
+--source include/have_binlog_format_statement.inc
+RESET MASTER;
+--connection default
+CREATE TABLE t1(id INT AUTO_INCREMENT PRIMARY KEY, a INT, b INT) ENGINE=INNODB;
+INSERT INTO t1(a, b) VALUES(1,2),(2,4),(3,6),(4,8),(5,10);
+SET DEBUG_SYNC = "open_and_process_table signal truncate_before_lock wait_for forever";
+--send TRUNCATE t1
+
+connect(con1,localhost,root,,);
+SET DEBUG_SYNC = "now wait_for truncate_before_lock";
+# Wait for one connection to reach open_and_process_table.
+--let $show_statement= SHOW PROCESSLIST
+--let $field= State
+--let $condition= 'debug sync point: open_and_process_table';
+--source include/wait_show_condition.inc
+
+SELECT ((@id := id) - id) FROM information_schema.processlist WHERE processlist.info LIKE '%TRUNCATE t1%' AND state LIKE '%open_and_process_table%';
+# Test killing from mysql server
+KILL QUERY @id;
+
+connection default;
+--ERROR ER_QUERY_INTERRUPTED
+--reap
+
+connection con1;
+--source include/show_binlog_events.inc
+
+disconnect con1;
+--source include/wait_until_disconnected.inc
+connection default;
+
+SELECT * FROM t1;
+
+DROP TABLE t1;
+SET DEBUG_SYNC= 'RESET';
diff --git a/mysql-test/suite/binlog/t/binlog_truncate_multi_engine.inc b/mysql-test/suite/binlog/t/binlog_truncate_multi_engine.inc
new file mode 100644
index 00000000..f3801070
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_truncate_multi_engine.inc
@@ -0,0 +1,75 @@
+#
+# Invoked by binlog_truncate_multi_engine.test
+# Parameters:
+# $debug_sync_action describes debug-sync actions
+# $kill_server 1 when to crash, 0 for regular restart
+# $restart_parameters the caller may simulate partial commit at recovery
+# $test_outcome summary of extected results
+# $MYSQLD_DATADIR
+
+--echo #
+--echo #
+--echo # Case $case : $description
+--echo #
+RESET MASTER;
+FLUSH LOGS;
+SET GLOBAL max_binlog_size= 4096;
+
+connect(con1,localhost,root,,);
+--echo List of binary logs before rotation
+--source include/show_binary_logs.inc
+INSERT INTO t1 VALUES (1, REPEAT("x", 1));
+INSERT INTO t2 VALUES (1, REPEAT("x", 1));
+--let $is_case_B=`SELECT $case = "B"`
+
+if ($is_case_B)
+{
+ --write_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
+wait-binlog_truncate_multi_engine.test
+EOF
+
+ SET GLOBAL debug_dbug="d,enable_log_write_upto_crash";
+}
+BEGIN;
+ INSERT INTO t2 VALUES (2, REPEAT("x", 4100));
+ INSERT INTO t1 VALUES (2, REPEAT("x", 4100));
+
+if (`SELECT $debug_sync_action != ""`)
+{
+ --eval SET DEBUG_SYNC= $debug_sync_action
+}
+send COMMIT;
+
+--connection default
+if ($is_case_B)
+{
+ --source include/wait_until_disconnected.inc
+ --source include/start_mysqld.inc
+}
+if (!$is_case_B)
+{
+ SET DEBUG_SYNC= "now WAIT_FOR con1_ready";
+ --echo List of binary logs after rotation
+ --source include/show_binary_logs.inc
+
+ --echo # restart the server with $restart_parameters
+ --echo # the server is restarted
+ --source include/restart_mysqld.inc
+}
+
+--connection default
+--echo #
+--echo # *** Summary: $test_outcome:
+--echo #
+SELECT COUNT(*) FROM t1;
+SELECT COUNT(*) FROM t2;
+SELECT @@GLOBAL.gtid_binlog_state;
+SELECT @@GLOBAL.gtid_binlog_pos;
+--echo List of binary logs at the end of the tests
+--source include/show_binary_logs.inc
+--echo # ***
+# cleanup
+DELETE FROM t1;
+DELETE FROM t2;
+--disconnect con1
+--echo #
diff --git a/mysql-test/suite/binlog/t/binlog_truncate_multi_engine.opt b/mysql-test/suite/binlog/t/binlog_truncate_multi_engine.opt
new file mode 100644
index 00000000..03e7d74f
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_truncate_multi_engine.opt
@@ -0,0 +1 @@
+--plugin-load=$HA_ROCKSDB_SO
diff --git a/mysql-test/suite/binlog/t/binlog_truncate_multi_engine.test b/mysql-test/suite/binlog/t/binlog_truncate_multi_engine.test
new file mode 100644
index 00000000..12b0a743
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_truncate_multi_engine.test
@@ -0,0 +1,59 @@
+# ==== Purpose ====
+#
+# Test verifies truncation of multiple binary logs with multiple transactional
+# storage engines
+#
+# ==== References ====
+#
+# MDEV-21117: recovery for --rpl-semi-sync-slave-enabled server
+
+--source include/have_rocksdb.inc
+--source include/have_innodb.inc
+--source include/have_debug.inc
+--source include/have_debug_sync.inc
+--source include/have_binlog_format_row.inc
+
+--let $old_max_binlog_size= `select @@global.max_binlog_size`
+call mtr.add_suppression("Can.t init tc log");
+call mtr.add_suppression("Aborting");
+--let $MYSQLD_DATADIR= `SELECT @@datadir`
+
+SET @@global.sync_binlog= 1;
+CREATE TABLE t1 (a INT PRIMARY KEY, b MEDIUMTEXT) ENGINE=Innodb;
+CREATE TABLE t2 (a INT PRIMARY KEY, b MEDIUMTEXT) ENGINE=rocksdb;
+
+--let $case = "A"
+--let $description = "neither engine committed => rollback & binlog truncate"
+# Hold off engine commits after write to binlog and its rotation.
+# The transaction is killed along with the server after that.
+--let $shutdown_timeout=0
+--let $debug_sync_action = "commit_after_release_LOCK_log SIGNAL con1_ready WAIT_FOR signal_no_signal"
+--let $restart_parameters = --rpl-semi-sync-slave-enabled=1 --sync-binlog=1
+--let $test_outcome= 1 row should be present in both tables; binlog is truncated; number of binlogs at reconnect - 3
+--source binlog_truncate_multi_engine.inc
+--echo Proof of the truncated binlog file is readable (two transactions must be seen):
+--exec $MYSQL_BINLOG --short-form --skip-annotate-row-events $MYSQLD_DATADIR/master-bin.000002
+
+--let $case = "B"
+--let $description = "one engine has committed its transaction branch"
+# Hold off after one engine has committed.
+--let $shutdown_timeout=0
+--let $debug_sync_action = ""
+# Both debug_sync and debug-dbug are required to make sure Engines remember the commit state
+# debug_sync alone will not help.
+--let $restart_parameters = --rpl-semi-sync-slave-enabled=1 --sync-binlog=1
+--let $test_outcome= 2 rows should be present in both tables; no binlog truncation; one extra binlog file compare with A; number of binlogs at reconnect - 4
+--source binlog_truncate_multi_engine.inc
+
+--let $case = "C"
+--let $description= "both engines have committed its transaction branch"
+--let $debug_sync_action = "commit_after_run_commit_ordered SIGNAL con1_ready"
+# Hold off after both engines have committed. The server is shut down.
+--let $shutdown_timeout=
+--let $restart_parameters = --rpl-semi-sync-slave-enabled=1 --sync-binlog=1
+--let $test_outcome= 2 rows should be present in both tables; no binlog truncation; the same # of binlog files as in B; number of binlogs at reconnect - 4
+--source binlog_truncate_multi_engine.inc
+
+DROP TABLE t1, t2;
+SET @@global.sync_binlog= default;
+--echo # End of the tests
diff --git a/mysql-test/suite/binlog/t/binlog_truncate_multi_log.test b/mysql-test/suite/binlog/t/binlog_truncate_multi_log.test
new file mode 100644
index 00000000..079c79b2
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_truncate_multi_log.test
@@ -0,0 +1,87 @@
+# ==== Purpose ====
+#
+# Test verifies truncation of multiple binary logs.
+#
+# ==== References ====
+# MDEV-21117: recovery for --rpl-semi-sync-slave-enabled server
+
+--source include/have_innodb.inc
+--source include/have_debug_sync.inc
+--source include/have_binlog_format_row.inc
+
+call mtr.add_suppression("Can.t init tc log");
+call mtr.add_suppression("Aborting");
+
+SET @@global.max_binlog_size= 4096;
+SET @@global.sync_binlog= 1;
+RESET MASTER;
+FLUSH LOGS;
+CREATE TABLE ti (a INT PRIMARY KEY, b MEDIUMTEXT) ENGINE=Innodb;
+CREATE TABLE tm (a INT PRIMARY KEY, b MEDIUMTEXT) ENGINE=MyISAM;
+
+connect(master1,localhost,root,,);
+--echo "List of binary logs before rotation"
+--source include/show_binary_logs.inc
+
+# Some load to either non- and transactional egines
+# that should not affect the following recovery:
+INSERT INTO ti VALUES(1,"I am gonna survive");
+INSERT INTO tm VALUES(1,"me too!");
+
+# hold on near engine commit
+SET DEBUG_SYNC= "commit_after_release_LOCK_after_binlog_sync SIGNAL master1_ready WAIT_FOR master1_go_never_arrives";
+--send INSERT INTO ti VALUES (2, REPEAT("x", 4100))
+
+connect(master2,localhost,root,,);
+# The 2nd trx for recovery, it does not rotate binlog
+SET DEBUG_SYNC= "now WAIT_FOR master1_ready";
+SET DEBUG_SYNC= "commit_before_get_LOCK_commit_ordered SIGNAL master2_ready WAIT_FOR master2_go_never_arrives";
+--send INSERT INTO ti VALUES (3, "not gonna survive")
+
+--connection default
+SET DEBUG_SYNC= "now WAIT_FOR master2_ready";
+
+connect(master3,localhost,root,,);
+# The 3nd trx for recovery, it won't get into binlog nor therefore recover
+SET DEBUG_SYNC= "ha_commit_trans_before_log_and_order SIGNAL master3_ready WAIT_FOR master3_go_never_arrives";
+--send INSERT INTO ti VALUES (4, "not gonna be log therefore survive"),(5, "ditto")
+
+--connection default
+SET DEBUG_SYNC= "now WAIT_FOR master3_ready";
+
+--echo "List of binary logs before crash"
+--source include/show_binary_logs.inc
+--echo # The gtid binlog state prior the crash will be truncated at the end of the test
+SELECT @@global.gtid_binlog_state;
+
+--connection default
+--source include/kill_mysqld.inc
+--disconnect master1
+--disconnect master2
+--disconnect master3
+
+#
+# Server restart
+#
+--let $restart_parameters= --rpl-semi-sync-slave-enabled=1 --sync-binlog=1 --log-warnings=3
+--source include/start_mysqld.inc
+
+# Check error log for a successful truncate message.
+let $log_error_ = $MYSQLTEST_VARDIR/log/mysqld.1.err;
+
+--let SEARCH_FILE=$log_error_
+--let SEARCH_PATTERN=truncated binlog file:.*master.*000002
+--source include/search_pattern_in_file.inc
+
+
+--echo "One record should be present in table"
+SELECT * FROM ti;
+
+--echo # The truncated gtid binlog state
+SELECT @@global.gtid_binlog_state;
+SELECT @@global.gtid_binlog_pos;
+
+--echo # Cleanup
+DROP TABLE ti;
+SET @@global.sync_binlog= default;
+--echo # End of the tests
diff --git a/mysql-test/suite/binlog/t/binlog_truncate_multi_log_unsafe.test b/mysql-test/suite/binlog/t/binlog_truncate_multi_log_unsafe.test
new file mode 100644
index 00000000..5a5cc667
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_truncate_multi_log_unsafe.test
@@ -0,0 +1,120 @@
+# ==== Purpose ====
+# The test verifies attempt to recover by the semisync slave server whose
+# binlog is unsafe for truncation.
+#
+# ==== Implementation ====
+# 2 binlog files are created with the 1st one destined to be the binlog
+# checkpoint file for recovery.
+# The final group of events is replication unsafe (myisam INSERT).
+# Therefore the semisync slave recovery may not.
+#
+# Steps:
+# 0 - Set max_binlog_size= 4096, to help an insert into a
+# transaction table 'ti' get binlog rotated while the
+# transaction won't be committed, being stopped at
+# a prior to commit debug_sync point
+# 1 - insert into a non-transactional 'tm' table completes with
+# binary logging as well
+# 2 - kill and attempt to restart the server as semisync slave that
+# must produce an expected unsafe-to-recover error
+# 3 - complete the test with a normal restart that successfully finds and
+# commits the transaction in doubt.
+#
+# ==== References ====
+#
+# MDEV-21117: recovery for --rpl-semi-sync-slave-enabled server
+#
+
+--source include/have_innodb.inc
+--source include/have_debug_sync.inc
+--source include/have_binlog_format_row.inc
+
+SET @@global.max_binlog_size= 4096;
+
+call mtr.add_suppression("Table '.*tm' is marked as crashed and should be repaired");
+call mtr.add_suppression("Got an error from unknown thread");
+call mtr.add_suppression("Checking table: '.*tm'");
+call mtr.add_suppression("Recovering table: '.*tm'");
+call mtr.add_suppression("Cannot truncate the binary log to file");
+call mtr.add_suppression("Crash recovery failed");
+call mtr.add_suppression("Can.t init tc log");
+call mtr.add_suppression("Aborting");
+call mtr.add_suppression("Found 1 prepared transactions");
+call mtr.add_suppression("mysqld: Table.*tm.*is marked as crashed");
+call mtr.add_suppression("Checking table.*tm");
+
+RESET MASTER;
+FLUSH LOGS;
+SET @@global.sync_binlog=1;
+CREATE TABLE ti (a INT PRIMARY KEY, b MEDIUMTEXT) ENGINE=Innodb;
+CREATE TABLE tm (f INT) ENGINE=MYISAM;
+
+--let $row_count = 5
+--let $i = `select $row_count-2`
+--disable_query_log
+while ($i)
+{
+ --eval INSERT INTO ti VALUES ($i, REPEAT("x", 1))
+ --dec $i
+}
+--enable_query_log
+INSERT INTO tm VALUES(1);
+
+connect(master1,localhost,root,,);
+connect(master2,localhost,root,,);
+connect(master3,localhost,root,,);
+
+--connection master1
+
+# The 1st trx binlogs, rotate binlog and hold on before committing at engine
+SET DEBUG_SYNC= "commit_after_release_LOCK_after_binlog_sync SIGNAL master1_ready WAIT_FOR master1_go_never_arrives";
+--send_eval INSERT INTO ti VALUES ($row_count - 1, REPEAT("x", 4100))
+
+--connection master2
+SET DEBUG_SYNC= "now WAIT_FOR master1_ready";
+# The 2nd trx for recovery, it does not rotate binlog
+SET DEBUG_SYNC= "commit_before_get_LOCK_commit_ordered SIGNAL master2_ready WAIT_FOR master2_go_never_arrives";
+--send_eval INSERT INTO ti VALUES ($row_count, REPEAT("x", 1))
+
+--connection master3
+SET DEBUG_SYNC= "now WAIT_FOR master2_ready";
+SET DEBUG_SYNC= "commit_before_get_LOCK_after_binlog_sync SIGNAL master3_ready";
+--send INSERT INTO tm VALUES (2)
+
+--connection default
+SET DEBUG_SYNC= "now WAIT_FOR master3_ready";
+--echo # The gtid binlog state prior the crash must be restored at the end of the test;
+SELECT @@global.gtid_binlog_state;
+--source include/kill_mysqld.inc
+
+#
+# Server restarts
+#
+--echo # Failed restart as the semisync slave
+--error 1
+--exec $MYSQLD_LAST_CMD --rpl-semi-sync-slave-enabled=1 >> $MYSQLTEST_VARDIR/log/mysqld.1.err 2>&1
+
+--echo # Normal restart
+--source include/start_mysqld.inc
+
+# Check error log for correct messages.
+let $log_error_ = $MYSQLTEST_VARDIR/log/mysqld.1.err;
+
+--let SEARCH_FILE=$log_error_
+--let SEARCH_PATTERN=Cannot truncate the binary log to file
+--source include/search_pattern_in_file.inc
+
+--echo # Proof that the in-doubt transactions are recovered by the 2nd normal server restart
+--eval SELECT COUNT(*) = $row_count as 'True' FROM ti
+# myisam table may require repair (which is not tested here)
+--disable_warnings
+SELECT COUNT(*) <= 1 FROM tm;
+--enable_warnings
+
+--echo # The gtid binlog state prior the crash is restored now
+SELECT @@GLOBAL.gtid_binlog_state;
+SELECT @@GLOBAL.gtid_binlog_pos;
+
+--echo # Cleanup
+DROP TABLE ti, tm;
+--echo End of test
diff --git a/mysql-test/suite/binlog/t/binlog_truncate_myisam.test b/mysql-test/suite/binlog/t/binlog_truncate_myisam.test
new file mode 100644
index 00000000..864e9c63
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_truncate_myisam.test
@@ -0,0 +1,17 @@
+source include/have_log_bin.inc;
+
+SET @old_binlog_format=@@binlog_format;
+
+let $engine = MyISAM;
+
+SET BINLOG_FORMAT=ROW;
+RESET MASTER;
+
+source include/binlog_truncate.test;
+
+SET BINLOG_FORMAT=STATEMENT;
+RESET MASTER;
+
+source include/binlog_truncate.test;
+
+SET BINLOG_FORMAT=@old_binlog_format;
diff --git a/mysql-test/suite/binlog/t/binlog_unsafe-master.opt b/mysql-test/suite/binlog/t/binlog_unsafe-master.opt
new file mode 100644
index 00000000..50fc48d2
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_unsafe-master.opt
@@ -0,0 +1 @@
+--log-output=file,table
diff --git a/mysql-test/suite/binlog/t/binlog_unsafe.test b/mysql-test/suite/binlog/t/binlog_unsafe.test
new file mode 100644
index 00000000..b637a980
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_unsafe.test
@@ -0,0 +1,762 @@
+# ==== Background ====
+#
+# Some statements may execute differently on master and slave when
+# logged in statement format. Such statements are called unsafe.
+# Unsafe statements include:
+#
+# - statements using @@variables (with a small number of exceptions;
+# see below);
+# - statements using certain functions, e.g., UUID();
+# - statements using LIMIT;
+# - INSERT DELAYED;
+# - insert into two autoinc columns;
+# - statements using UDF's.
+# - statements reading from log tables in the mysql database.
+# - INSERT ... SELECT ... ON DUPLICATE KEY UPDATE
+# - REPLACE ... SELECT
+# - CREATE TABLE [IGNORE/REPLACE] SELECT
+# - INSERT IGNORE...SELECT
+# - UPDATE IGNORE
+# - INSERT... ON DUPLICATE KEY UPDATE on a table with two UNIQUE KEYS
+#
+# Note that statements that use stored functions, stored procedures,
+# triggers, views, or prepared statements that invoke unsafe
+# statements shall also be unsafe.
+#
+# Unsafeness of a statement shall have the following consequences:
+#
+# 1. If the binlogging is on and the unsafe statement is logged:
+# - If binlog_format=STATEMENT, the statement shall give a warning.
+# - If binlog_format=MIXED or binlog_format=ROW, the statement shall
+# be logged in row format.
+#
+# 2. If binlogging is off or the statement is not logged (e.g. SELECT
+# UUID()), no warning shall be issued and the statement shall not
+# be logged.
+#
+# Moreover, when a sub-statement of a recursive construct (i.e.,
+# stored function, stored procedure, trigger, view, or prepared
+# statement) is unsafe and binlog_format=STATEMENT, then a warning
+# shall be issued for every recursive construct. In effect, this
+# creates a stack trace from the top-level statement to the unsafe
+# statement.
+#
+#
+# ==== Purpose ====
+#
+# This test verifies that a warning is generated when it should,
+# according to the rules above.
+#
+# All @@variables should be unsafe, with some exceptions. Therefore,
+# this test also verifies that the exceptions do *not* generate a
+# warning.
+#
+#
+# ==== Method ====
+#
+# 1. Each type of statements listed above is executed.
+#
+# 2. Each unsafe statement is wrapped in each type of recursive
+# construct (stored function, stored procedure, trigger, view, or
+# prepared statement).
+#
+# 3. Each unsafe statement is wrapped in two levels of recursive
+# constructs (function invoking trigger invoking UUID(), etc).
+#
+# We try to insert the variables that should not be unsafe into a
+# table, and verify that *no* warning is issued.
+#
+# Execute a unsafe statement calling a trigger or stored function
+# or neither when SQL_LOG_BIN is turned ON, a warning/error should be issued
+# Execute a unsafe statement calling a trigger or stored function
+# or neither when @@SQL_LOG_BIN is turned OFF,
+# no warning/error is issued
+#
+#
+# ==== Related bugs and worklogs ====
+#
+# WL#3339: Issue warnings when statement-based replication may fail
+# BUG#31168: @@hostname does not replicate
+# BUG#34732: mysqlbinlog does not print default values for auto_increment variables
+# BUG#34768: nondeterministic INSERT using LIMIT logged in stmt mode if binlog_format=mixed
+# BUG#41980, SBL, INSERT .. SELECT .. LIMIT = ERROR, even when @@SQL_LOG_BIN is 0
+# BUG#42640: mysqld crashes when unsafe statements are executed (STRICT_TRANS_TABLES mode)
+# BUG#45825: INSERT DELAYED is not unsafe: logged in statement format
+# BUG#45785: LIMIT in SP does not cause RBL if binlog_format=MIXED
+# BUG#47995: Mark user functions as unsafe
+# BUG#49222: Mark RAND() unsafe
+# BUG#11758262: MARK INSERT...SEL...ON DUP KEY UPD,REPLACE...SEL,CREATE...[IGN|REPL] SEL
+#
+# ==== Related test cases ====
+#
+# rpl.rpl_variables verifies that variables which cannot be replicated
+# safely in statement mode are replicated correctly in mixed or row
+# mode.
+#
+# rpl.rpl_variables_stm tests the small subset of variables that
+# actually can be replicated safely in statement mode.
+#
+--source include/have_udf.inc
+--source include/have_log_bin.inc
+--source include/have_binlog_format_statement.inc
+
+--disable_query_log
+call mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT");
+--enable_query_log
+
+--echo #### Setup tables ####
+
+CREATE TABLE t0 (a CHAR(200));
+CREATE TABLE t1 (a CHAR(200));
+CREATE TABLE t2 (a CHAR(200));
+CREATE TABLE t3 (a CHAR(200));
+CREATE TABLE ta0 (a CHAR(200));
+CREATE TABLE ta1 (a CHAR(200));
+CREATE TABLE ta2 (a CHAR(200));
+CREATE TABLE ta3 (a CHAR(200));
+CREATE TABLE autoinc_table (a INT PRIMARY KEY AUTO_INCREMENT);
+CREATE TABLE data_table (a CHAR(200));
+INSERT INTO data_table VALUES ('foo');
+CREATE TABLE trigger_table_1 (a INT);
+CREATE TABLE trigger_table_2 (a INT);
+CREATE TABLE trigger_table_3 (a INT);
+CREATE TABLE double_autoinc_table (a INT PRIMARY KEY AUTO_INCREMENT);
+
+--DELIMITER |
+CREATE TRIGGER double_autoinc_trig
+BEFORE INSERT ON double_autoinc_table FOR EACH ROW
+BEGIN
+ INSERT INTO autoinc_table VALUES (NULL);
+END|
+
+CREATE FUNCTION multi_unsafe_func() RETURNS INT
+BEGIN
+ INSERT INTO t0 VALUES(CONCAT(@@hostname, @@hostname));
+ INSERT INTO t0 VALUES(0);
+ INSERT INTO t0 VALUES(CONCAT(UUID(), @@hostname));
+ RETURN 1;
+END|
+--DELIMITER ;
+
+--replace_result $UDF_EXAMPLE_SO UDF_EXAMPLE_LIB
+--eval CREATE FUNCTION myfunc_int RETURNS INTEGER SONAME "$UDF_EXAMPLE_SO"
+
+# In each iteration of this loop, we select one method to make the
+# statement unsafe.
+--let $unsafe_type= 0
+while ($unsafe_type < 9) {
+
+ --echo
+
+ if ($unsafe_type == 0) {
+ --echo ==== Testing UUID() unsafeness ====
+ --let $desc_0= unsafe UUID() function
+ --let $stmt_sidef_0= INSERT INTO t0 VALUES (UUID())
+ --let $value_0= UUID()
+ --let $sel_sidef_0=
+ --let $sel_retval_0= SELECT UUID()
+ --let $CRC_ARG_expected_number_of_warnings= 1
+ }
+
+ if ($unsafe_type == 1) {
+ --echo ==== Testing @@hostname unsafeness ====
+ --let $desc_0= unsafe @@hostname variable
+ --let $stmt_sidef_0= INSERT INTO t0 VALUES (@@hostname)
+ --let $value_0= @@hostname
+ --let $sel_sidef_0=
+ # $sel_retval is going to be used in views. Views cannot execute
+ # statements that refer to @@variables. Hence, we set $set_retval
+ # to empty instead of SELECT @@hostname.
+ --let $sel_retval_0=
+ --let $CRC_ARG_expected_number_of_warnings= 1
+ }
+
+ if ($unsafe_type == 2) {
+ --echo ==== Testing SELECT...LIMIT unsafeness ====
+ --let $desc_0= unsafe SELECT...LIMIT statement
+ --let $stmt_sidef_0= INSERT INTO t0 SELECT * FROM data_table LIMIT 1
+ --let $value_0=
+ --let $sel_sidef_0=
+ --let $sel_retval_0= SELECT * FROM data_table LIMIT 1
+ --let $CRC_ARG_expected_number_of_warnings= 1
+ }
+
+ if ($unsafe_type == 3) {
+ --echo ==== Testing INSERT DELAYED safeness after BUG#54579 is fixed ====
+ --let $desc_0= unsafe INSERT DELAYED statement
+ --let $stmt_sidef_0= INSERT DELAYED INTO t0 VALUES (1), (2)
+ --let $value_0=
+ --let $sel_sidef_0=
+ --let $sel_retval_0=
+ --let $CRC_ARG_expected_number_of_warnings= 0
+ }
+
+ if ($unsafe_type == 4) {
+ --echo ==== Testing unsafeness of insert of two autoinc values ====
+ --let $desc_0= unsafe update of two autoinc columns
+ --let $stmt_sidef_0= INSERT INTO double_autoinc_table VALUES (NULL)
+ --let $value_0=
+ --let $sel_sidef_0=
+ --let $sel_retval_0=
+ --let $CRC_ARG_expected_number_of_warnings= 1
+ }
+
+ if ($unsafe_type == 5) {
+ --echo ==== Testing unsafeness of UDF's ====
+ --let $desc_0= unsafe UDF
+ --let $stmt_sidef_0= INSERT INTO t0 VALUES (myfunc_int(10))
+ --let $value_0= myfunc_int(10)
+ --let $sel_sidef_0= SELECT myfunc_int(10)
+ --let $sel_retval_0=
+ --let $CRC_ARG_expected_number_of_warnings= 1
+ }
+
+ if ($unsafe_type == 6) {
+ --echo ==== Testing unsafeness of access to mysql.general_log ====
+ --let $desc_0= unsafe use of mysql.general_log
+ --let $stmt_sidef_0= INSERT INTO t0 SELECT COUNT(*) FROM mysql.general_log
+ --let $value_0=
+ --let $sel_sidef_0=
+ --let $sel_retval_0= SELECT COUNT(*) FROM mysql.general_log
+ --let $CRC_ARG_expected_number_of_warnings= 1
+ }
+
+ if ($unsafe_type == 7) {
+ --echo ==== Testing a statement that is unsafe in many ways ====
+ --let $desc_0= statement that is unsafe in many ways
+ # Concatenate three unsafe values, and then concatenate NULL to
+ # that so that the result is NULL and we instead use autoinc.
+ --let $stmt_sidef_0= INSERT DELAYED INTO double_autoinc_table SELECT CONCAT(UUID(), @@hostname, myfunc_int(), NULL) FROM mysql.general_log LIMIT 1
+ --let $value_0=
+ --let $sel_sidef_0=
+ --let $sel_retval_0=
+ --let $CRC_ARG_expected_number_of_warnings= 7
+ }
+
+ if ($unsafe_type == 8) {
+ --echo ==== Testing a statement that is unsafe several times ====
+ --let $desc_0= statement that is unsafe several times
+ --let $stmt_sidef_0= INSERT INTO ta0 VALUES (multi_unsafe_func())
+ --let $value_0=
+ --let $sel_sidef_0= SELECT multi_unsafe_func()
+ --let $sel_retval_0=
+ --let $CRC_ARG_expected_number_of_warnings= 2
+ }
+
+ # In each iteration of the following loop, we select one way to
+ # enclose the unsafe statement as a sub-statement of a recursive
+ # construct (i.e., a function, procedure, trigger, view, or prepared
+ # statement).
+ #
+ # In the last iteration, $call_type_1=7, we don't create a recursive
+ # construct. Instead, we just invoke the unsafe statement directly.
+
+ --let $call_type_1= 0
+ while ($call_type_1 < 8) {
+ #--echo debug: level 1, types $call_type_1 -> $unsafe_type
+ --let $CRC_ARG_level= 1
+ --let $CRC_ARG_type= $call_type_1
+ --let $CRC_ARG_stmt_sidef= $stmt_sidef_0
+ --let $CRC_ARG_value= $value_0
+ --let $CRC_ARG_sel_sidef= $sel_sidef_0
+ --let $CRC_ARG_sel_retval= $sel_retval_0
+ --let $CRC_ARG_desc= $desc_0
+ --source suite/rpl/include/create_recursive_construct.inc
+ --let $stmt_sidef_1= $CRC_RET_stmt_sidef
+ --let $value_1= $CRC_RET_value
+ --let $sel_sidef_1= $CRC_RET_sel_sidef
+ --let $sel_retval_1= $CRC_RET_sel_retval
+ --let $is_toplevel_1= $CRC_RET_is_toplevel
+ --let $drop_1= $CRC_RET_drop
+ --let $desc_1= $CRC_RET_desc
+
+ # Some statements must be top-level statements, i.e., cannot be
+ # called as a sub-statement of any recursive construct. (One
+ # example is 'EXECUTE prepared_stmt'). When
+ # create_recursive_construct.inc creates a top-level statement, it
+ # sets $CRC_RET_is_toplevel=1.
+
+ if (!$is_toplevel_1) {
+
+ # In each iteration of this loop, we select one way to enclose
+ # the previous recursive construct in another recursive
+ # construct.
+
+ --let $call_type_2= 0
+ while ($call_type_2 < 7) {
+ #--echo debug: level 2, types $call_type_2 -> $call_type_1 -> $unsafe_type
+ --let $CRC_ARG_level= 2
+ --let $CRC_ARG_type= $call_type_2
+ --let $CRC_ARG_stmt_sidef= $stmt_sidef_1
+ --let $CRC_ARG_value= $value_1
+ --let $CRC_ARG_sel_sidef= $sel_sidef_1
+ --let $CRC_ARG_sel_retval= $sel_retval_1
+ --let $CRC_ARG_desc= $desc_1
+ --source suite/rpl/include/create_recursive_construct.inc
+ --let $stmt_sidef_2= $CRC_RET_stmt_sidef
+ --let $value_2= $CRC_RET_value
+ --let $sel_sidef_2= $CRC_RET_sel_sidef
+ --let $sel_retval_2= $CRC_RET_sel_retval
+ --let $is_toplevel_2= $CRC_RET_is_toplevel
+ --let $drop_2= $CRC_RET_drop
+ --let $desc_2= $CRC_RET_desc
+
+ if (!$is_toplevel_2) {
+
+ # Conditioned out since it makes result file really big.
+
+ if (0) {
+
+ # In each iteration of this loop, we select one way to enclose
+ # the previous recursive construct in another recursive
+ # construct.
+
+ --let $call_type_3= 0
+ while ($call_type_3 < 7) {
+ #--echo debug: level 3, types $call_type_2 -> $call_type_2 -> $call_type_1 -> $unsafe_type
+ --let $CRC_ARG_level= 3
+ --let $CRC_ARG_type= $call_type_3
+ --let $CRC_ARG_stmt_sidef= $stmt_sidef_2
+ --let $CRC_ARG_value= $value_2
+ --let $CRC_ARG_sel_sidef= $sel_sidef_2
+ --let $CRC_ARG_sel_retval= $sel_retval_2
+ --let $CRC_ARG_desc= $desc_2
+ --source suite/rpl/include/create_recursive_construct.inc
+
+ # Drop created object.
+ if ($drop_3) {
+ --eval $drop_3
+ }
+ --inc $call_type_3
+ } # while (call_type_3)
+ } # if (0)
+ } # if (!is_toplevel_2)
+
+ # Drop created object.
+ if ($drop_2) {
+ --eval $drop_2
+ }
+ --inc $call_type_2
+ } # while (call_type_2)
+ } # if (!is_toplevel_1)
+
+ # Drop created object.
+ if ($drop_1) {
+ --eval $drop_1
+ }
+ --inc $call_type_1
+ } # while (call_type_1)
+
+ --inc $unsafe_type
+} # while (unsafe_type)
+
+DROP TRIGGER double_autoinc_trig;
+DROP TABLE t0, t1, t2, t3, ta0, ta1, ta2, ta3,
+ autoinc_table, double_autoinc_table,
+ data_table,
+ trigger_table_1, trigger_table_2, trigger_table_3;
+DROP FUNCTION myfunc_int;
+DROP FUNCTION multi_unsafe_func;
+
+
+--echo ==== Special system variables that should *not* be unsafe ====
+
+CREATE TABLE t1 (a VARCHAR(1000));
+CREATE TABLE autoinc_table (a INT PRIMARY KEY AUTO_INCREMENT);
+
+INSERT INTO t1 VALUES (@@session.auto_increment_increment);
+INSERT INTO t1 VALUES (@@session.auto_increment_offset);
+INSERT INTO t1 VALUES (@@session.character_set_client);
+INSERT INTO t1 VALUES (@@session.character_set_connection);
+INSERT INTO t1 VALUES (@@session.character_set_database);
+INSERT INTO t1 VALUES (@@session.character_set_server);
+INSERT INTO t1 VALUES (@@session.collation_connection);
+INSERT INTO t1 VALUES (@@session.collation_database);
+INSERT INTO t1 VALUES (@@session.collation_server);
+INSERT INTO t1 VALUES (@@session.foreign_key_checks);
+INSERT INTO t1 VALUES (@@session.identity);
+INSERT INTO t1 VALUES (@@session.last_insert_id);
+INSERT INTO t1 VALUES (@@session.lc_time_names);
+INSERT INTO t1 VALUES (@@session.pseudo_thread_id);
+INSERT INTO t1 VALUES (@@session.sql_auto_is_null);
+INSERT INTO t1 VALUES (@@session.timestamp);
+INSERT INTO t1 VALUES (@@session.time_zone);
+INSERT INTO t1 VALUES (@@session.unique_checks);
+
+SET @my_var= 4711;
+INSERT INTO t1 VALUES (@my_var);
+
+# using insert_id implicitly should be ok.
+SET insert_id= 12;
+INSERT INTO autoinc_table VALUES (NULL);
+
+# See set_var.cc for explanation.
+--echo The following variables *should* give a warning, despite they are replicated.
+INSERT INTO t1 VALUES (@@session.sql_mode);
+INSERT INTO t1 VALUES (@@session.insert_id);
+
+
+DROP TABLE t1, autoinc_table;
+
+
+#
+# BUG#34768 - nondeterministic INSERT using LIMIT logged in stmt mode if
+# binlog_format=mixed
+#
+CREATE TABLE t1(a INT, b INT, KEY(a), PRIMARY KEY(b));
+INSERT INTO t1 SELECT * FROM t1 LIMIT 1;
+REPLACE INTO t1 SELECT * FROM t1 LIMIT 1;
+UPDATE t1 SET a=1 LIMIT 1;
+DELETE FROM t1 LIMIT 1;
+delimiter |;
+CREATE PROCEDURE p1()
+BEGIN
+ INSERT INTO t1 SELECT * FROM t1 LIMIT 1;
+ REPLACE INTO t1 SELECT * FROM t1 LIMIT 1;
+ UPDATE t1 SET a=1 LIMIT 1;
+ DELETE FROM t1 LIMIT 1;
+END|
+delimiter ;|
+CALL p1();
+DROP PROCEDURE p1;
+DROP TABLE t1;
+
+#
+# Bug#42634: % character in query can cause mysqld signal 11 segfault
+#
+
+--disable_warnings
+DROP TABLE IF EXISTS t1;
+--enable_warnings
+
+CREATE TABLE t1 (a VARCHAR(200), b VARCHAR(200));
+INSERT INTO t1 VALUES ('a','b');
+UPDATE t1 SET b = '%s%s%s%s%s%s%s%s%s%s%s%s%s%s' WHERE a = 'a' LIMIT 1;
+DROP TABLE t1;
+
+#
+#For bug#41980, SBL, INSERT .. SELECT .. LIMIT = ERROR, even when @@SQL_LOG_BIN is 0
+#
+
+--disable_warnings
+DROP TABLE IF EXISTS t1, t2;
+--enable_warnings
+CREATE TABLE t1(i INT PRIMARY KEY);
+CREATE TABLE t2(i INT PRIMARY KEY);
+CREATE TABLE t3(i INT, ch CHAR(50));
+
+--echo "Should issue message Statement may not be safe to log in statement format."
+INSERT INTO t1 SELECT * FROM t2 LIMIT 1;
+
+DELIMITER |;
+CREATE FUNCTION func6()
+RETURNS INT
+BEGIN
+ INSERT INTO t1 VALUES (10);
+ INSERT INTO t1 VALUES (11);
+ INSERT INTO t1 VALUES (12);
+ RETURN 0;
+END|
+DELIMITER ;|
+--echo "Should issue message Statement may not be safe to log in statement format only once"
+INSERT INTO t3 VALUES(func6(), UUID());
+
+--echo "Check whether SET @@SQL_LOG_BIN = 0/1 doesn't work in substatements"
+DELIMITER |;
+CREATE FUNCTION fun_check_log_bin() RETURNS INT
+BEGIN
+ SET @@SQL_LOG_BIN = 0;
+ INSERT INTO t1 VALUES(@@global.sync_binlog);
+ RETURN 200;
+END|
+DELIMITER ;|
+--echo "One unsafe warning should be issued in the following statement"
+--error ER_STORED_FUNCTION_PREVENTS_SWITCH_SQL_LOG_BIN
+SELECT fun_check_log_bin();
+--echo "SQL_LOG_BIN should be ON still"
+SHOW VARIABLES LIKE "SQL_LOG_BIN";
+
+set @save_log_bin = @@SESSION.SQL_LOG_BIN;
+set @@SESSION.SQL_LOG_BIN = 0;
+--echo "Should NOT have any warning message issued in the following statements"
+INSERT INTO t1 SELECT * FROM t2 LIMIT 1;
+DROP TABLE t1,t2;
+
+--echo "Should NOT have any warning message issued in the following func7() and trig"
+CREATE TABLE t1 (a INT);
+CREATE TABLE t2 (a TEXT);
+CREATE TABLE trigger_table (a CHAR(7));
+DELIMITER |;
+CREATE FUNCTION func7()
+RETURNS INT
+BEGIN
+ INSERT INTO t1 VALUES (@@global.sync_binlog);
+ INSERT INTO t1 VALUES (@@session.insert_id);
+ INSERT INTO t2 SELECT UUID();
+ INSERT INTO t2 VALUES (@@session.sql_mode);
+ INSERT INTO t2 VALUES (@@global.init_slave);
+ RETURN 0;
+END|
+DELIMITER ;|
+SHOW VARIABLES LIKE "SQL_LOG_BIN";
+SELECT func7();
+
+--echo ---- Insert from trigger ----
+
+DELIMITER |;
+CREATE TRIGGER trig
+BEFORE INSERT ON trigger_table
+FOR EACH ROW
+BEGIN
+ INSERT INTO t1 VALUES (@@global.sync_binlog);
+ INSERT INTO t1 VALUES (@@session.insert_id);
+ INSERT INTO t1 VALUES (@@global.auto_increment_increment);
+ INSERT INTO t2 SELECT UUID();
+ INSERT INTO t2 VALUES (@@session.sql_mode);
+ INSERT INTO t2 VALUES (@@global.init_slave);
+ INSERT INTO t2 VALUES (@@hostname);
+END|
+DELIMITER ;|
+
+INSERT INTO trigger_table VALUES ('bye.');
+
+#clean up
+DROP FUNCTION fun_check_log_bin;
+DROP FUNCTION func6;
+DROP FUNCTION func7;
+DROP TRIGGER trig;
+DROP TABLE t1, t2, t3, trigger_table;
+set @@SESSION.SQL_LOG_BIN = @save_log_bin;
+
+#
+# For BUG#42640: mysqld crashes when unsafe statements are executed (STRICT_TRANS_TABLES mode)
+#
+SET @save_sql_mode = @@SESSION.SQL_MODE;
+SET @@SESSION.SQL_MODE = STRICT_ALL_TABLES;
+
+CREATE TABLE t1(i INT PRIMARY KEY);
+CREATE TABLE t2(i INT PRIMARY KEY);
+
+INSERT INTO t1 SELECT * FROM t2 LIMIT 1;
+INSERT INTO t1 VALUES(@@global.sync_binlog);
+
+UPDATE t1 SET i = 999 LIMIT 1;
+DELETE FROM t1 LIMIT 1;
+
+DROP TABLE t1, t2;
+SET @@SESSION.SQL_MODE = @save_sql_mode;
+
+#
+# BUG#45825: INSERT DELAYED is not unsafe: logged in statement format
+# BUG#45785: LIMIT in SP does not cause RBL if binlog_format=MIXED
+#
+SET @old_binlog_format = @@session.binlog_format;
+SET binlog_format = MIXED;
+
+CREATE TABLE t1 (a INT);
+CREATE TABLE t2 (a INT);
+INSERT INTO t2 VALUES (1), (2);
+
+--DELIMITER |
+CREATE PROCEDURE proc_insert_delayed ()
+BEGIN
+ INSERT DELAYED INTO t1 VALUES (1), (2);
+END|
+
+CREATE FUNCTION func_limit ()
+RETURNS INT
+BEGIN
+ INSERT INTO t1 SELECT * FROM t2 LIMIT 1;
+ RETURN 1;
+END|
+--DELIMITER ;
+
+RESET MASTER;
+CALL proc_insert_delayed();
+--disable_ps2_protocol
+SELECT func_limit();
+--enable_ps2_protocol
+source include/show_binlog_events.inc;
+
+SET @@session.binlog_format = @old_binlog_format;
+DROP TABLE t1, t2;
+DROP PROCEDURE proc_insert_delayed;
+DROP FUNCTION func_limit;
+
+#
+# BUG#45827
+# The test verifies if stmt that have more than one
+# different tables to update with autoinc columns
+# will produce unsafe warning
+#
+
+# Test case1: stmt that have more than one different tables
+# to update with autoinc columns should produce
+# unsafe warning when calling a function
+CREATE TABLE t1 (a INT, b INT PRIMARY KEY AUTO_INCREMENT);
+CREATE TABLE t2 (a INT, b INT PRIMARY KEY AUTO_INCREMENT);
+
+# The purpose of this function is to insert into t1 so that the second
+# column is auto_increment'ed.
+DELIMITER |;
+CREATE FUNCTION func_modify_t1 ()
+RETURNS INT
+BEGIN
+ INSERT INTO t1 SET a = 1;
+ RETURN 0;
+END|
+DELIMITER ;|
+--echo # The following statement causes auto-incrementation
+--echo # of both t1 and t2. It is logged in statement format,
+--echo # so it should produce unsafe warning.
+INSERT INTO t2 SET a = func_modify_t1();
+
+SET SESSION binlog_format = MIXED;
+--echo # Check if the statement is logged in row format.
+let $binlog_start= query_get_value(SHOW MASTER STATUS, Position, 1);
+INSERT INTO t2 SET a = func_modify_t1();
+--source include/show_binlog_events.inc
+
+# clean up
+DROP TABLE t1,t2;
+DROP FUNCTION func_modify_t1;
+#
+# Test case2: stmt that have more than one different tables
+# to update with autoinc columns should produce
+# unsafe warning when invoking a trigger
+SET SESSION binlog_format = STATEMENT;
+CREATE TABLE t1 (a INT);
+CREATE TABLE t2 (a INT, b INT PRIMARY KEY AUTO_INCREMENT);
+CREATE TABLE t3 (a INT, b INT PRIMARY KEY AUTO_INCREMENT);
+
+# The purpose of this function is to insert into t1 so that the second
+# column is auto_increment'ed.
+delimiter |;
+create trigger tri_modify_two_tables before insert on t1 for each row begin
+ insert into t2(a) values(new.a);
+ insert into t3(a) values(new.a);
+end |
+delimiter ;|
+--echo # The following statement causes auto-incrementation
+--echo # of both t2 and t3. It is logged in statement format,
+--echo # so it should produce unsafe warning
+INSERT INTO t1 SET a = 1;
+
+SET SESSION binlog_format = MIXED;
+--echo # Check if the statement is logged in row format.
+let $binlog_start= query_get_value(SHOW MASTER STATUS, Position, 1);
+INSERT INTO t1 SET a = 2;
+--source include/show_binlog_events.inc
+
+# clean up
+DROP TABLE t1,t2,t3;
+
+#
+# BUG#47995: Mark user functions as unsafe
+# BUG#49222: Mark RAND() unsafe
+#
+# Test that the system functions that are supposed to be marked unsafe
+# generate a warning. Each INSERT statement below should generate a
+# warning.
+#
+SET SESSION binlog_format = STATEMENT;
+
+CREATE TABLE t1 (a VARCHAR(1000));
+INSERT INTO t1 VALUES (CURRENT_USER()); #marked unsafe before BUG#47995
+INSERT INTO t1 VALUES (FOUND_ROWS()); #marked unsafe before BUG#47995
+INSERT INTO t1 VALUES (GET_LOCK('tmp', 1)); #marked unsafe in BUG#47995
+INSERT INTO t1 VALUES (IS_FREE_LOCK('tmp')); #marked unsafe in BUG#47995
+INSERT INTO t1 VALUES (IS_USED_LOCK('tmp')); #marked unsafe in BUG#47995
+INSERT INTO t1 VALUES (LOAD_FILE('../../std_data/words2.dat')); #marked unsafe in BUG#39701
+INSERT INTO t1 VALUES (MASTER_POS_WAIT('dummy arg', 4711, 1));
+INSERT INTO t1 VALUES (RELEASE_LOCK('tmp')); #marked unsafe in BUG#47995
+INSERT INTO t1 VALUES (ROW_COUNT()); #marked unsafe before BUG#47995
+INSERT INTO t1 VALUES (SESSION_USER()); #marked unsafe before BUG#47995
+INSERT INTO t1 VALUES (SLEEP(1)); #marked unsafe in BUG#47995
+INSERT INTO t1 VALUES (SYSDATE()); #marked unsafe in BUG#47995
+INSERT INTO t1 VALUES (SYSTEM_USER()); #marked unsafe before BUG#47995
+INSERT INTO t1 VALUES (USER()); #marked unsafe before BUG#47995
+INSERT INTO t1 VALUES (UUID()); #marked unsafe before BUG#47995
+INSERT INTO t1 VALUES (UUID_SHORT()); #marked unsafe before BUG#47995
+INSERT INTO t1 VALUES (VERSION()); #marked unsafe in BUG#47995
+INSERT INTO t1 VALUES (RAND()); #marked unsafe in BUG#49222
+INSERT INTO t1 VALUES (RANDOM_BYTES(1000)); #marked unsafe in MDEV-25704
+DELETE FROM t1;
+
+# Since we replicate the TIMESTAMP variable, functions affected by the
+# TIMESTAMP variable are safe to replicate. So we check that the
+# following following functions that depend on the TIMESTAMP variable
+# are not unsafe and don't generate a warning.
+
+SET TIME_ZONE= '+03:00';
+SET TIMESTAMP=1000000;
+INSERT INTO t1 VALUES
+ (CURDATE()),
+ (CURRENT_DATE()),
+ (CURRENT_TIME()),
+ (CURRENT_TIMESTAMP()),
+ (CURTIME()),
+ (LOCALTIME()),
+ (LOCALTIMESTAMP()),
+ (NOW()),
+ (UNIX_TIMESTAMP()),
+ (UTC_DATE()),
+ (UTC_TIME()),
+ (UTC_TIMESTAMP());
+SELECT * FROM t1;
+
+DROP TABLE t1;
+#
+#BUG#11758262-50439: MARK INSERT...SEL...ON DUP KEY UPD,REPLACE..
+#The following statement may be unsafe when logged in statement format.
+#INSERT IGNORE...SELECT
+#INSERT ... SELECT ... ON DUPLICATE KEY UPDATE
+#REPLACE ... SELECT
+#UPDATE IGNORE
+#CREATE TABLE... IGNORE SELECT
+#CREATE TABLE... REPLACE SELECT
+#
+###BUG 11765650 - 58637: MARK UPDATES THAT DEPEND ON ORDER OF TWO KEYS UNSAFE
+#INSERT.... ON DUP KEY UPDATE on a table with more than one UNIQUE KEY
+
+#setup tables
+CREATE TABLE filler_table (a INT, b INT);
+INSERT INTO filler_table values (1,1),(1,2);
+CREATE TABLE insert_table (a INT, b INT, PRIMARY KEY(a));
+CREATE TABLE replace_table (a INT, b INT, PRIMARY KEY(a));
+INSERT INTO replace_table values (1,1),(2,2);
+CREATE TABLE update_table (a INT, b INT, PRIMARY KEY(a));
+INSERT INTO update_table values (1,1),(2,2);
+CREATE TABLE insert_2_keys (a INT UNIQUE KEY, b INT UNIQUE KEY);
+INSERT INTO insert_2_keys values (1, 1);
+
+#INSERT IGNORE... SELECT
+INSERT IGNORE INTO insert_table SELECT * FROM filler_table;
+TRUNCATE TABLE insert_table;
+#INSERT ... SELECT ... ON DUPLICATE KEY UPDATE
+INSERT INTO insert_table SELECT * FROM filler_table ON DUPLICATE KEY UPDATE a = 1;
+TRUNCATE TABLE insert_table;
+#REPLACE...SELECT
+REPLACE INTO replace_table SELECT * FROM filler_table;
+#UPDATE IGNORE
+UPDATE IGNORE update_table SET a=2;
+#CREATE TABLE [IGNORE/REPLACE] SELECT
+CREATE TABLE create_ignore_test (a INT, b INT, PRIMARY KEY(b)) IGNORE SELECT * FROM filler_table;
+CREATE TABLE create_replace_test (a INT, b INT, PRIMARY KEY(b)) REPLACE SELECT * FROM filler_table;
+#temporary tables should not throw the warning.
+CREATE TEMPORARY TABLE temp1 (a INT, b INT, PRIMARY KEY(b)) REPLACE SELECT * FROM filler_table;
+
+#INSERT.... ON DUP KEY UPDATE on a table with more than one UNIQUE KEY
+INSERT INTO insert_2_keys VALUES (1, 2)
+ ON DUPLICATE KEY UPDATE a=VALUES(a)+10, b=VALUES(b)+10;
+
+###clean up
+DROP TABLE filler_table;
+DROP TABLE insert_table;
+DROP TABLE update_table;
+DROP TABLE replace_table;
+DROP TABLE create_ignore_test;
+DROP TABLE create_replace_test;
+DROP TABLE insert_2_keys;
+
+--echo "End of tests"
diff --git a/mysql-test/suite/binlog/t/binlog_variables_log_bin-master.opt b/mysql-test/suite/binlog/t/binlog_variables_log_bin-master.opt
new file mode 100644
index 00000000..85d14ea7
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_variables_log_bin-master.opt
@@ -0,0 +1 @@
+--log-bin=other
diff --git a/mysql-test/suite/binlog/t/binlog_variables_log_bin.test b/mysql-test/suite/binlog/t/binlog_variables_log_bin.test
new file mode 100644
index 00000000..afaea3d9
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_variables_log_bin.test
@@ -0,0 +1,5 @@
+--source include/not_embedded.inc
+
+let $log_bin_index=`select substring_index(@@log_bin_index,'/',-1)`;
+--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR $log_bin_index mysqld-bin.index
+--query_vertical SHOW VARIABLES LIKE 'log_bin%'
diff --git a/mysql-test/suite/binlog/t/binlog_variables_log_bin_index-master.opt b/mysql-test/suite/binlog/t/binlog_variables_log_bin_index-master.opt
new file mode 100644
index 00000000..68e580bd
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_variables_log_bin_index-master.opt
@@ -0,0 +1,2 @@
+--log-bin=other
+--log-bin-index=$MYSQLTEST_VARDIR/tmp/something.index
diff --git a/mysql-test/suite/binlog/t/binlog_variables_log_bin_index.test b/mysql-test/suite/binlog/t/binlog_variables_log_bin_index.test
new file mode 100644
index 00000000..d94d565d
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_variables_log_bin_index.test
@@ -0,0 +1,4 @@
+--source include/not_embedded.inc
+
+--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
+--query_vertical SHOW VARIABLES LIKE 'log_bin%'
diff --git a/mysql-test/suite/binlog/t/binlog_variables_relay_log-master.opt b/mysql-test/suite/binlog/t/binlog_variables_relay_log-master.opt
new file mode 100644
index 00000000..a01432d7
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_variables_relay_log-master.opt
@@ -0,0 +1 @@
+--relay-log=other-relay
diff --git a/mysql-test/suite/binlog/t/binlog_variables_relay_log.test b/mysql-test/suite/binlog/t/binlog_variables_relay_log.test
new file mode 100644
index 00000000..27ef1d73
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_variables_relay_log.test
@@ -0,0 +1,5 @@
+--source include/not_embedded.inc
+
+let $relay_log_index=`select substring_index(@@relay_log_index,'/',-1)`;
+--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR $relay_log_index mysqld-relay-bin.index
+--query_vertical SHOW VARIABLES LIKE 'relay_log%'
diff --git a/mysql-test/suite/binlog/t/binlog_variables_relay_log_index-master.opt b/mysql-test/suite/binlog/t/binlog_variables_relay_log_index-master.opt
new file mode 100644
index 00000000..eeabaca1
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_variables_relay_log_index-master.opt
@@ -0,0 +1,2 @@
+--relay-log=other-relay
+--relay-log-index=$MYSQLTEST_VARDIR/tmp/something-relay.index
diff --git a/mysql-test/suite/binlog/t/binlog_variables_relay_log_index.test b/mysql-test/suite/binlog/t/binlog_variables_relay_log_index.test
new file mode 100644
index 00000000..1e987901
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_variables_relay_log_index.test
@@ -0,0 +1,4 @@
+--source include/not_embedded.inc
+
+--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
+--query_vertical SHOW VARIABLES LIKE 'relay_log%'
diff --git a/mysql-test/suite/binlog/t/binlog_verbose_compressed_fields.test b/mysql-test/suite/binlog/t/binlog_verbose_compressed_fields.test
new file mode 100644
index 00000000..8cbcdbef
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_verbose_compressed_fields.test
@@ -0,0 +1,70 @@
+#
+# Purpose:
+# This test validates that mysqlbinlog is able to annotate compressed column
+# types with two levels of verbosity.
+#
+# Methodology:
+# Validate that the output from mysqlbinlog -vv after creating and inserting
+# into a table with compressed and uncompressed fields correctly annotates
+# which columns are compressed
+#
+# References:
+# MDEV-25277: mysqlbinlog --verbose cannot read row events with compressed
+# columns: Don't know how to handle column type: 140
+#
+--source include/have_binlog_format_row.inc
+
+CREATE TABLE t1 (a TEXT, ac TEXT COMPRESSED, b TINYTEXT, bc TINYTEXT COMPRESSED, c MEDIUMTEXT, cc MEDIUMTEXT COMPRESSED, d LONGTEXT, dc LONGTEXT COMPRESSED, e VARCHAR(10), ec VARCHAR(10) COMPRESSED);
+
+--echo # Isolate row event into its own binary log
+FLUSH BINARY LOGS;
+INSERT INTO t1 VALUES ('mya', 'myac', 'myb', 'mybc', 'myc', 'mycc', 'myd', 'mydc', 'mye', 'myec');
+FLUSH BINARY LOGS;
+
+--let $binlog_file= query_get_value(SHOW BINARY LOGS, Log_name, 2)
+--let $datadir= `SELECT @@datadir`
+--let $result_binlog= $MYSQLTEST_VARDIR/tmp/$binlog_file
+
+--echo # MYSQLBINLOG --base64-output=decode-rows -vv datadir/binlog_file --result-file=result_binlog
+--exec $MYSQL_BINLOG --base64-output=decode-rows -vv $datadir/$binlog_file --result-file=$result_binlog
+
+--let $assert_file= $result_binlog
+--let $assert_count= 1
+
+--let $assert_text= Ensure compressed TEXT fields are annotated correctly
+--let $assert_select=\WTEXT COMPRESSED
+--source include/assert_grep.inc
+
+--let $assert_text= Ensure compressed TINYTEXT fields are annotated correctly
+--let $assert_select=\WTINYTEXT COMPRESSED
+--source include/assert_grep.inc
+
+--let $assert_text= Ensure compressed MEDIUMTEXT fields are annotated correctly
+--let $assert_select=\WMEDIUMTEXT COMPRESSED
+--source include/assert_grep.inc
+
+--let $assert_text= Ensure compressed LONGTEXT fields are annotated correctly
+--let $assert_select=\WLONGTEXT COMPRESSED
+--source include/assert_grep.inc
+
+--let $assert_text= Ensure compressed VARSTRING fields are annotated correctly
+--let $assert_select=\WVARSTRING\(\d+\) COMPRESSED
+--source include/assert_grep.inc
+
+--let $assert_text= Ensure COMPRESSED only shows up for corresponding fields
+--let $assert_count= 5
+--let $assert_select= COMPRESSED
+--source include/assert_grep.inc
+
+--let $assert_text= Ensure non-compressed TEXT fields are annotated correctly
+--let $assert_count= 8
+--let $assert_select=/*.*TEXT
+--source include/assert_grep.inc
+
+--let $assert_text= Ensure non-compressed VARSTRING fields are annotated correctly
+--let $assert_count= 2
+--let $assert_select=/*.*VARSTRING
+--source include/assert_grep.inc
+
+# Cleanup
+DROP TABLE t1;
diff --git a/mysql-test/suite/binlog/t/binlog_write_error.test b/mysql-test/suite/binlog/t/binlog_write_error.test
new file mode 100644
index 00000000..bd1cb530
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_write_error.test
@@ -0,0 +1,84 @@
+#
+# This file is included by binlog_encryption.binlog_write_error
+# Please check all dependent tests after modifying it
+#
+
+#
+# === Name ===
+#
+# binlog_write_error.test
+#
+# === Description ===
+#
+# This test case check if the error of writing binlog file is properly
+# reported and handled when executing statements.
+#
+# === Related Bugs ===
+#
+# BUG#37148
+#
+
+source include/have_debug.inc;
+source include/have_binlog_format_mixed_or_statement.inc;
+
+call mtr.add_suppression("Write to binary log failed: Error writing file*");
+
+--echo #
+--echo # Test injecting binlog write error when executing queries
+--echo #
+
+let $query= CREATE TABLE t1 (a INT);
+source include/binlog_inject_error.inc;
+
+INSERT INTO t1 VALUES (1),(2),(3);
+
+let $query= INSERT INTO t1 VALUES (4),(5),(6);
+source include/binlog_inject_error.inc;
+
+let $query= UPDATE t1 set a=a+1;
+source include/binlog_inject_error.inc;
+
+let $query= DELETE FROM t1;
+source include/binlog_inject_error.inc;
+
+let $query= CREATE TRIGGER tr1 AFTER INSERT ON t1 FOR EACH ROW INSERT INTO t1 VALUES (new.a + 100);
+source include/binlog_inject_error.inc;
+
+let $query= DROP TRIGGER tr1;
+source include/binlog_inject_error.inc;
+
+let $query= ALTER TABLE t1 ADD (b INT);
+source include/binlog_inject_error.inc;
+
+let $query= CREATE VIEW v1 AS SELECT a FROM t1;
+source include/binlog_inject_error.inc;
+
+let $query= DROP VIEW v1;
+source include/binlog_inject_error.inc;
+
+let $query= CREATE PROCEDURE p1(OUT rows_cnt INT) SELECT count(*) INTO rows_cnt FROM t1;
+source include/binlog_inject_error.inc;
+
+let $query= DROP PROCEDURE p1;
+source include/binlog_inject_error.inc;
+
+let $query= DROP TABLE t1;
+source include/binlog_inject_error.inc;
+
+let $query= CREATE FUNCTION f1() RETURNS INT return 1;
+source include/binlog_inject_error.inc;
+
+let $query= DROP FUNCTION f1;
+source include/binlog_inject_error.inc;
+
+let $query= CREATE USER user1;
+source include/binlog_inject_error.inc;
+
+let $query= REVOKE ALL PRIVILEGES, GRANT OPTION FROM user1;
+source include/binlog_inject_error.inc;
+
+let $query= SET PASSWORD FOR user1=PASSWORD('foobar');
+source include/binlog_inject_error.inc;
+
+let $query= DROP USER user1;
+source include/binlog_inject_error.inc;
diff --git a/mysql-test/suite/binlog/t/binlog_xa_checkpoint.test b/mysql-test/suite/binlog/t/binlog_xa_checkpoint.test
new file mode 100644
index 00000000..b208d02c
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_xa_checkpoint.test
@@ -0,0 +1,57 @@
+--source include/have_innodb.inc
+--source include/have_debug.inc
+--source include/have_debug_sync.inc
+--source include/have_binlog_format_row.inc
+
+RESET MASTER;
+
+CREATE TABLE t1 (a INT PRIMARY KEY, b MEDIUMTEXT) ENGINE=Innodb;
+
+# Test that
+# 1. XA PREPARE is binlogged before the XA has been prepared in Engine
+# 2. While XA PREPARE already binlogged in an old binlog file which has been rotated,
+# Binlog checkpoint is not generated for the latest log until
+# XA PREPARE returns, e.g OK to the client.
+
+
+# con1 will hang before doing commit checkpoint, blocking RESET MASTER.
+connect(con1,localhost,root,,);
+SET DEBUG_SYNC= "at_unlog_xa_prepare SIGNAL con1_ready WAIT_FOR con1_go";
+XA START '1';
+INSERT INTO t1 SET a=1;
+XA END '1';
+--send XA PREPARE '1';
+
+
+connection default;
+SET DEBUG_SYNC= "now WAIT_FOR con1_ready";
+FLUSH LOGS;
+FLUSH LOGS;
+FLUSH LOGS;
+
+--source include/show_binary_logs.inc
+--let $binlog_file= master-bin.000004
+--let $binlog_start= 4
+--source include/show_binlog_events.inc
+
+SET DEBUG_SYNC= "now SIGNAL con1_go";
+
+connection con1;
+reap;
+--echo *** master-bin.000004 checkpoint must show up now ***
+--source include/wait_for_binlog_checkpoint.inc
+
+# Todo: think about the error code returned, move to an appropriate test, or remove
+# connection default;
+#--error 1399
+# DROP TABLE t1;
+
+connection con1;
+XA ROLLBACK '1';
+SET debug_sync = 'reset';
+
+# Clean up.
+connection default;
+
+DROP TABLE t1;
+SET debug_sync = 'reset';
diff --git a/mysql-test/suite/binlog/t/binlog_xa_handling.test b/mysql-test/suite/binlog/t/binlog_xa_handling.test
new file mode 100644
index 00000000..c454e831
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_xa_handling.test
@@ -0,0 +1,28 @@
+###############################################################################
+# Bug#19928622: ASSERTION `! IS_SET()' FAILED. | ABORT IN
+# DIAGNOSTICS_AREA::SET_OK_STATUS
+#
+# MDEV-27536 Invalid BINLOG_BASE64_EVENT and assertion Diagnostics_area:: !is_set()
+#
+# Test:
+# =====
+# Begin an XA transaction and execte a DML statement so that XA state becomes
+# XA_ACTIVE. Execute the BINLOG command it should not cause any assert.
+# Execution should be successful.
+###############################################################################
+--source include/have_log_bin.inc
+--source include/have_innodb.inc
+
+--connection default
+CREATE TABLE t1(f1 int) ENGINE=Innodb;
+
+XA START 'xa';
+INSERT INTO t1 VALUES(10);
+BINLOG '
+SOgWTg8BAAAAbgAAAHIAAAAAAAQANS42LjMtbTUtZGVidWctbG9nAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAABI6BZOEzgNAAgAEgAEBAQEEgAAVgAEGggAAAAICAgCAAAAAAVAYI8=';
+XA END 'xa';
+XA PREPARE 'xa';
+XA ROLLBACK 'xa';
+
+DROP TABLE t1;
diff --git a/mysql-test/suite/binlog/t/binlog_xa_prepared.inc b/mysql-test/suite/binlog/t/binlog_xa_prepared.inc
new file mode 100644
index 00000000..e93832db
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_xa_prepared.inc
@@ -0,0 +1,106 @@
+--source include/have_innodb.inc
+--source include/have_perfschema.inc
+#
+# The test verifies binlogging of XA transaction and state of prepared XA
+# as far as binlog is concerned.
+#
+# The prepared XA transactions can be disconnected from the client,
+# discovered from another connection and commited or rolled back
+# later. They also survive the server restart. The test runs two
+# loops each consisting of prepared XA:s generation, their
+# manipulation and a server restart followed with survived XA:s
+# completion.
+#
+# Prepared XA can't get available to an external connection
+# until connection that either leaves actively or is killed
+# has completed a necessary part of its cleanup.
+# Selecting from P_S.threads provides a method to learn that.
+#
+# Total number of connection each performing one insert into table
+--let $conn_number=20
+# Number of rollbacks and commits from either side of the server restart
+--let $rollback_number=5
+--let $commit_number=5
+# Number of transactions that are terminated before server restarts
+--let $term_number=`SELECT $rollback_number + $commit_number`
+# Instead of disconnect make some connections killed when their
+# transactions got prepared.
+--let $killed_number=5
+# make some connections disconnected by shutdown rather than actively
+--let $server_disconn_number=5
+--let $prepared_at_server_restart = `SELECT $conn_number - $term_number`
+# number a "warmup" connection after server restart, they all commit
+--let $post_restart_conn_number=10
+
+# Counter to be used in GTID consistency check.
+# It's incremented per each non-XA transaction commit.
+# Local to this file variable to control one-phase commit loop
+--let $one_phase_number = 5
+
+--connection default
+
+# Remove possibly preceeding binlogs and clear initialization time
+# GTID executed info. In the following all transactions are counted
+# to conduct verification at the end of the test.
+if (`SELECT @@global.log_bin`)
+{
+ RESET MASTER;
+}
+
+# Disconected and follower threads need synchronization
+CREATE VIEW v_processlist as SELECT * FROM performance_schema.threads where type = 'FOREGROUND';
+
+--eval call mtr.add_suppression("Found $prepared_at_server_restart prepared XA transactions")
+
+CREATE TABLE t (a INT) ENGINE=innodb;
+
+# MDEV-515 takes X-lock on the table for the first insert.
+# So concurrent insert won't happen on the table
+INSERT INTO t VALUES(100);
+
+# Counter is incremented at the end of post restart to
+# reflect number of loops done in correctness computation.
+--let $restart_number = 0
+--let $how_to_restart=restart_mysqld.inc
+--source suite/binlog/include/binlog_xa_prepared_do_and_restart.inc
+
+--let $how_to_restart=kill_and_restart_mysqld.inc
+--source suite/binlog/include/binlog_xa_prepared_do_and_restart.inc
+
+--connection default
+
+# Few xs that commit in one phase, not subject to the server restart
+# nor reconnect.
+# This piece of test is related to mysqlbinlog recovery examine below.
+--let $k = 0
+while ($k < $one_phase_number)
+{
+ --eval XA START 'one_phase_trx_$k'
+ --eval INSERT INTO t SET a=$k
+ --eval XA END 'one_phase_trx_$k'
+ --eval XA COMMIT 'one_phase_trx_$k' ONE PHASE
+
+ --inc $k
+}
+
+SELECT SUM(a) FROM t;
+DROP TABLE t;
+DROP VIEW v_processlist;
+
+let $outfile= $MYSQLTEST_VARDIR/tmp/mysqlbinlog.sql;
+if (`SELECT @@global.log_bin`)
+{
+ # Recording proper samples of binlogged prepared XA:s
+ --source include/show_binlog_events.inc
+ --exec $MYSQL_BINLOG -R --to-last-log master-bin.000001 > $outfile
+}
+
+--echo All transactions must be completed, to empty-list the following:
+XA RECOVER;
+
+if (`SELECT @@global.log_bin`)
+{
+ --exec $MYSQL test < $outfile
+ --remove_file $outfile
+ XA RECOVER;
+}
diff --git a/mysql-test/suite/binlog/t/binlog_xa_prepared_disconnect.test b/mysql-test/suite/binlog/t/binlog_xa_prepared_disconnect.test
new file mode 100644
index 00000000..2a318403
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_xa_prepared_disconnect.test
@@ -0,0 +1,11 @@
+###############################################################################
+# Bug#12161 Xa recovery and client disconnection
+# Testing new server options and binary logging prepared XA transaction.
+###############################################################################
+
+#
+# MIXED mode is chosen because formats are varied inside the sourced tests.
+#
+--source include/have_binlog_format_mixed.inc
+
+--source suite/binlog/t/binlog_xa_prepared.inc
diff --git a/mysql-test/suite/binlog/t/binlog_xa_recover.opt b/mysql-test/suite/binlog/t/binlog_xa_recover.opt
new file mode 100644
index 00000000..f645a058
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_xa_recover.opt
@@ -0,0 +1 @@
+--loose-skip-stack-trace --skip-core-file --loose-debug-dbug=+d,xa_recover_expect_master_bin_000004
diff --git a/mysql-test/suite/binlog/t/binlog_xa_recover.test b/mysql-test/suite/binlog/t/binlog_xa_recover.test
new file mode 100644
index 00000000..3b2a7e45
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_xa_recover.test
@@ -0,0 +1,277 @@
+#
+# This include file is used by more than one test suite
+# (currently binlog and binlog_encryption).
+# Please check all dependent tests after modifying it
+#
+
+--source include/have_innodb.inc
+--source include/have_debug.inc
+--source include/have_debug_sync.inc
+--source include/have_binlog_format_row.inc
+--source include/have_perfschema.inc
+# Valgrind does not work well with test that crashes the server
+--source include/not_valgrind.inc
+
+# (We do not need to restore these settings, as we crash the server).
+SET GLOBAL max_binlog_size= 4096;
+SET GLOBAL innodb_flush_log_at_trx_commit= 1;
+RESET MASTER;
+
+CREATE TABLE t1 (a INT PRIMARY KEY, b MEDIUMTEXT) ENGINE=Innodb;
+# Insert some data to force a couple binlog rotations (3), so we get some
+# normal binlog checkpoints before starting the test.
+INSERT INTO t1 VALUES (100, REPEAT("x", 4100));
+# Wait for the master-bin.000002 binlog checkpoint to appear.
+--let $wait_for_all= 0
+--let $show_statement= SHOW BINLOG EVENTS IN "master-bin.000002"
+--let $field= Info
+--let $condition= = "master-bin.000002"
+--source include/wait_show_condition.inc
+INSERT INTO t1 VALUES (101, REPEAT("x", 4100));
+--let $wait_for_all= 0
+--let $show_statement= SHOW BINLOG EVENTS IN "master-bin.000003"
+--let $field= Info
+--let $condition= = "master-bin.000003"
+--source include/wait_show_condition.inc
+INSERT INTO t1 VALUES (102, REPEAT("x", 4100));
+--let $wait_for_all= 0
+--let $show_statement= SHOW BINLOG EVENTS IN "master-bin.000004"
+--let $field= Info
+--let $condition= = "master-bin.000004"
+--source include/wait_show_condition.inc
+
+# Now start a bunch of transactions that span multiple binlog
+# files. Leave then in the state prepared-but-not-committed in the engine
+# and crash the server. Check that crash recovery is able to recover all
+# of them.
+#
+# We use debug_sync to get all the transactions into the prepared state before
+# we commit any of them. This is because the prepare step flushes the InnoDB
+# redo log - including any commits made before, so recovery would become
+# unnecessary, decreasing the value of this test.
+#
+# We arrange to have con1 with a prepared transaction in master-bin.000004,
+# con2 and con3 with a prepared transaction in master-bin.000005, and a new
+# empty master-bin.000006. So the latest binlog checkpoint should be
+# master-bin.000006.
+
+connect(con1,localhost,root,,);
+# First wait after prepare and before write to binlog.
+SET DEBUG_SYNC= "ha_commit_trans_before_log_and_order SIGNAL con1_wait WAIT_FOR con1_cont";
+# Then complete InnoDB commit in memory (but not commit checkpoint / write to
+# disk), and hang until crash, leaving a transaction to be XA recovered.
+SET DEBUG_SYNC= "commit_after_group_release_commit_ordered SIGNAL con1_ready WAIT_FOR _ever";
+send INSERT INTO t1 VALUES (1, REPEAT("x", 4100));
+
+connection default;
+SET DEBUG_SYNC= "now WAIT_FOR con1_wait";
+
+connect(con2,localhost,root,,);
+SET DEBUG_SYNC= "ha_commit_trans_before_log_and_order SIGNAL con2_wait WAIT_FOR con2_cont";
+SET DEBUG_SYNC= "commit_after_group_release_commit_ordered SIGNAL con2_ready WAIT_FOR _ever";
+send INSERT INTO t1 VALUES (2, NULL);
+
+connection default;
+SET DEBUG_SYNC= "now WAIT_FOR con2_wait";
+
+connect(con3,localhost,root,,);
+SET DEBUG_SYNC= "ha_commit_trans_before_log_and_order SIGNAL con3_wait WAIT_FOR con3_cont";
+SET DEBUG_SYNC= "commit_after_group_release_commit_ordered SIGNAL con3_ready WAIT_FOR _ever";
+send INSERT INTO t1 VALUES (3, REPEAT("x", 4100));
+
+connection default;
+SET DEBUG_SYNC= "now WAIT_FOR con3_wait";
+
+connect(con4,localhost,root,,);
+SET DEBUG_SYNC= "ha_commit_trans_before_log_and_order SIGNAL con4_wait WAIT_FOR con4_cont";
+SET SESSION debug_dbug="+d,crash_commit_after_log";
+send INSERT INTO t1 VALUES (4, NULL);
+
+connection default;
+SET DEBUG_SYNC= "now WAIT_FOR con4_wait";
+
+SET DEBUG_SYNC= "now SIGNAL con1_cont";
+SET DEBUG_SYNC= "now WAIT_FOR con1_ready";
+SET DEBUG_SYNC= "now SIGNAL con2_cont";
+SET DEBUG_SYNC= "now WAIT_FOR con2_ready";
+SET DEBUG_SYNC= "now SIGNAL con3_cont";
+SET DEBUG_SYNC= "now WAIT_FOR con3_ready";
+
+# Check that everything is committed in binary log.
+--source include/show_binary_logs.inc
+--let $binlog_file= master-bin.000003
+--let $binlog_start= 4
+--source include/show_binlog_events.inc
+--let $binlog_file= master-bin.000004
+--source include/show_binlog_events.inc
+--let $binlog_file= master-bin.000005
+--source include/show_binlog_events.inc
+--let $binlog_file= master-bin.000006
+--source include/show_binlog_events.inc
+
+
+# Check that server will not purge too much.
+PURGE BINARY LOGS TO "master-bin.000006";
+--source include/show_binary_logs.inc
+
+# Now crash the server with one more transaction in prepared state.
+--write_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
+wait-binlog_xa_recover.test
+EOF
+--error 0,2006,2013
+SET DEBUG_SYNC= "now SIGNAL con4_cont";
+connection con4;
+--error 2006,2013
+reap;
+
+--append_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
+restart-group_commit_binlog_pos.test
+EOF
+
+connection default;
+--enable_reconnect
+--source include/wait_until_connected_again.inc
+
+# Check that all transactions are recovered.
+SELECT a FROM t1 ORDER BY a;
+
+--echo Test that with multiple binlog checkpoints, recovery starts from the last one.
+SET GLOBAL max_binlog_size= 4096;
+SET GLOBAL innodb_flush_log_at_trx_commit= 1;
+RESET MASTER;
+
+# Rotate to binlog master-bin.000003 while delaying binlog checkpoints.
+# So we get multiple binlog checkpoints in master-bin.000003.
+# Then complete the checkpoints, crash, and check that we only scan
+# the necessary binlog file (ie. that we use the _last_ checkpoint).
+
+connect(con10,localhost,root,,);
+SET DEBUG_SYNC= "commit_after_group_release_commit_ordered SIGNAL con10_ready WAIT_FOR con10_cont";
+send INSERT INTO t1 VALUES (10, REPEAT("x", 4100));
+
+connection default;
+SET DEBUG_SYNC= "now WAIT_FOR con10_ready";
+
+connect(con11,localhost,root,,);
+SET DEBUG_SYNC= "commit_after_group_release_commit_ordered SIGNAL con11_ready WAIT_FOR con11_cont";
+send INSERT INTO t1 VALUES (11, REPEAT("x", 4100));
+
+connection default;
+SET DEBUG_SYNC= "now WAIT_FOR con11_ready";
+
+connect(con12,localhost,root,,);
+SET DEBUG_SYNC= "commit_after_group_release_commit_ordered SIGNAL con12_ready WAIT_FOR con12_cont";
+send INSERT INTO t1 VALUES (12, REPEAT("x", 4100));
+
+connection default;
+SET DEBUG_SYNC= "now WAIT_FOR con12_ready";
+INSERT INTO t1 VALUES (13, NULL);
+
+--source include/show_binary_logs.inc
+--let $binlog_file= master-bin.000004
+--let $binlog_start= 4
+--source include/show_binlog_events.inc
+
+SET DEBUG_SYNC= "now SIGNAL con10_cont";
+connection con10;
+reap;
+connection default;
+
+# We need to sync the test case with the background processing of the
+# commit checkpoint, otherwise we get nondeterministic results.
+let $wait_condition= select count(*) = 1 from performance_schema.threads where processlist_state = "Waiting for background binlog tasks";
+--source include/wait_condition.inc
+
+SET DEBUG_SYNC= "now SIGNAL con12_cont";
+connection con12;
+reap;
+connection default;
+
+SET DEBUG_SYNC= "now SIGNAL con11_cont";
+connection con11;
+reap;
+
+connection default;
+# Wait for the last (master-bin.000004) binlog checkpoint to appear.
+--let $wait_for_all= 0
+--let $show_statement= SHOW BINLOG EVENTS IN "master-bin.000004"
+--let $field= Info
+--let $condition= = "master-bin.000004"
+--source include/wait_show_condition.inc
+
+--echo Now crash the server
+# It is not too easy to test XA recovery, as it runs early during server
+# startup, before any connections can be made.
+# What we do is set a DBUG error insert which will crash if XA recovery
+# starts from any other binlog than master-bin.000004 (check the file
+# binlog_xa_recover-master.opt). Then we will fail here if XA recovery
+# would start from the wrong place.
+--write_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
+wait-binlog_xa_recover.test
+EOF
+SET SESSION debug_dbug="+d,crash_commit_after_log";
+--error 2006,2013
+INSERT INTO t1 VALUES (14, NULL);
+
+--append_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
+restart-group_commit_binlog_pos.test
+EOF
+
+connection default;
+--enable_reconnect
+--source include/wait_until_connected_again.inc
+
+# Check that all transactions are recovered.
+SELECT a FROM t1 ORDER BY a;
+
+
+--echo *** Check that recovery works if we crashed early during rotate, before
+--echo *** binlog checkpoint event could be written.
+
+SET GLOBAL max_binlog_size= 4096;
+SET GLOBAL innodb_flush_log_at_trx_commit= 1;
+RESET MASTER;
+
+# We need some initial data to reach binlog master-bin.000004. Otherwise
+# crash recovery fails due to the error insert used for previous test.
+INSERT INTO t1 VALUES (21, REPEAT("x", 4100));
+INSERT INTO t1 VALUES (22, REPEAT("x", 4100));
+# Wait for the master-bin.000003 binlog checkpoint to appear.
+--let $wait_for_all= 0
+--let $show_statement= SHOW BINLOG EVENTS IN "master-bin.000003"
+--let $field= Info
+--let $condition= = "master-bin.000003"
+--source include/wait_show_condition.inc
+INSERT INTO t1 VALUES (23, REPEAT("x", 4100));
+# Wait for the last (master-bin.000004) binlog checkpoint to appear.
+--let $wait_for_all= 0
+--let $show_statement= SHOW BINLOG EVENTS IN "master-bin.000004"
+--let $field= Info
+--let $condition= = "master-bin.000004"
+--source include/wait_show_condition.inc
+
+--write_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
+wait-binlog_xa_recover.test
+EOF
+SET SESSION debug_dbug="+d,crash_before_write_checkpoint_event";
+--error 2006,2013
+INSERT INTO t1 VALUES (24, REPEAT("x", 4100));
+
+--append_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
+restart-group_commit_binlog_pos.test
+EOF
+
+--enable_reconnect
+--source include/wait_until_connected_again.inc
+
+# Check that all transactions are recovered.
+SELECT a FROM t1 ORDER BY a;
+
+--source include/show_binary_logs.inc
+--let $binlog_file= master-bin.000004
+--let $binlog_start= 4
+--source include/show_binlog_events.inc
+
+# Cleanup
+connection default;
+DROP TABLE t1;
diff --git a/mysql-test/suite/binlog/t/binlog_xa_recover_using_new_server_id.test b/mysql-test/suite/binlog/t/binlog_xa_recover_using_new_server_id.test
new file mode 100644
index 00000000..a7f2a206
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_xa_recover_using_new_server_id.test
@@ -0,0 +1,44 @@
+# This test verifies attempt to xa recover using a new server id that
+# different from the transaction's original server_id.
+#
+
+--source include/have_innodb.inc
+--source include/have_debug.inc
+--source include/have_binlog_format_row.inc
+# Valgrind does not work well with test that crashes the server
+--source include/not_valgrind.inc
+
+
+--echo ========= Set server_id to 99 and prepare test table.
+SET GLOBAL server_id= 99;
+CREATE TABLE t1 (a INT PRIMARY KEY, b MEDIUMTEXT) ENGINE=Innodb;
+
+
+--echo ========= Crash the server.
+--write_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
+wait-binlog_xa_recover_using_new_server_id.test
+EOF
+SET SESSION debug_dbug="+d,crash_commit_after_log";
+--error 2006,2013
+INSERT INTO t1 VALUES (1, NULL);
+
+
+--echo ========= Restart the server with default config file in which server_id= 1.
+--append_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
+restart-binlog_xa_recover_using_new_server_id.test
+EOF
+
+
+--echo ========= Check that recover succeeds and server is up.
+connection default;
+--enable_reconnect
+--source include/wait_until_connected_again.inc
+
+
+--echo ========= Check that all transactions are recovered.
+SELECT a FROM t1 ORDER BY a;
+
+
+--echo ========= Cleanup.
+connection default;
+DROP TABLE t1;
diff --git a/mysql-test/suite/binlog/t/flashback-largebinlog.test b/mysql-test/suite/binlog/t/flashback-largebinlog.test
new file mode 100644
index 00000000..80b0da52
--- /dev/null
+++ b/mysql-test/suite/binlog/t/flashback-largebinlog.test
@@ -0,0 +1,114 @@
+# mysqlbinlog_big.test
+#
+# Show that mysqlbinlog can handle big rows.
+#
+
+#
+# The *huge* output of mysqlbinlog will be redirected to
+# $MYSQLTEST_VARDIR/$mysqlbinlog_output
+#
+--let $mysqlbinlog_output= tmp/mysqlbinlog_big_1.out
+
+--source include/have_binlog_format_row.inc
+--source include/have_log_bin.inc
+
+# This is a big test.
+--source include/big_test.inc
+--source include/not_msan.inc
+# Test needs more than 4G of memory
+--source include/have_64bit.inc
+
+--echo #
+--echo # Preparatory cleanup.
+--echo #
+--disable_warnings
+drop database if exists mysqltest;
+create database mysqltest;
+use mysqltest;
+DROP TABLE IF EXISTS t1;
+--enable_warnings
+
+--echo #
+--echo # We need a fixed timestamp to avoid varying results.
+--echo #
+SET timestamp=1000000000;
+
+--echo #
+--echo # We need big packets.
+--echo #
+--echo # Capture initial value to reset at the end of the test
+# use let $<var> = query_get_value as FLUSH statements
+# in the test will set @<var> values to NULL
+let $orig_max_allowed_packet =
+query_get_value(SELECT @@global.max_allowed_packet, @@global.max_allowed_packet, 1);
+
+--echo # Now adjust max_allowed_packet
+SET @@global.max_allowed_packet= 10*1024*1024*1024;
+
+--echo max_allowed_packet is a global variable.
+--echo In order for the preceding change in max_allowed_packets' value
+--echo to be seen and used, we must start a new connection.
+--echo The change does not take effect with the current one.
+--echo For simplicity, we just disconnect / reconnect connection default here.
+disconnect default;
+connect (default, localhost,root,,);
+
+--echo #
+--echo # Delete all existing binary logs.
+--echo #
+RESET MASTER;
+
+--echo #
+--echo # Create a test table.
+--echo #
+use mysqltest;
+eval CREATE TABLE t1 (
+ c1 LONGTEXT
+ ) DEFAULT CHARSET latin1;
+
+--echo #
+--echo # Show how many rows are affected by each statement.
+--echo #
+--enable_info
+
+--echo #
+--echo # Insert some big rows.
+--echo #
+
+--echo insert 1024MB data twice
+INSERT INTO t1 VALUES (REPEAT('ManyMegaByteBlck', 67108864));
+INSERT INTO t1 VALUES (REPEAT('MegaByteBlckMany', 67108864));
+
+--echo #
+--echo # Flush all log buffers to the log file.
+--echo #
+FLUSH LOGS;
+
+--echo #
+--echo # Call mysqlbinlog to display the log file contents.
+--echo # NOTE: The output of mysqlbinlog is redirected to
+--echo # \$MYSQLTEST_VARDIR/$mysqlbinlog_output
+--echo # If you want to examine it, disable remove_file
+--echo # at the bottom of the test script.
+--echo #
+let $MYSQLD_DATADIR= `select @@datadir`;
+--replace_result $MYSQLTEST_VARDIR <MYSQLTEST_VARDIR>
+--replace_regex /SQL_LOAD_MB-[0-9]-[0-9]/SQL_LOAD_MB-#-#/ /exec_time=[0-9]*/exec_time=#/ /end_log_pos [0-9]*/end_log_pos #/ /# at [0-9]*/# at #/ /Xid = [0-9]*/Xid = #/
+--exec $MYSQL_BINLOG -B -v -v $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/$mysqlbinlog_output
+
+--echo #
+--echo # Cleanup.
+--echo #
+--echo # reset variable value to pass testcase checks
+--disable_query_log
+eval SET @@global.max_allowed_packet = $orig_max_allowed_packet;
+--enable_query_log
+DROP TABLE t1;
+drop database if exists mysqltest;
+
+--echo remove_file \$MYSQLTEST_VARDIR/$mysqlbinlog_output
+#
+# NOTE: If you want to see the *huge* mysqlbinlog output, disable next line:
+#
+--remove_file $MYSQLTEST_VARDIR/$mysqlbinlog_output
+
diff --git a/mysql-test/suite/binlog/t/flashback-master.opt b/mysql-test/suite/binlog/t/flashback-master.opt
new file mode 100644
index 00000000..476efbe2
--- /dev/null
+++ b/mysql-test/suite/binlog/t/flashback-master.opt
@@ -0,0 +1,2 @@
+--flashback
+--timezone=GMT-8
diff --git a/mysql-test/suite/binlog/t/flashback.test b/mysql-test/suite/binlog/t/flashback.test
new file mode 100644
index 00000000..7c58b56c
--- /dev/null
+++ b/mysql-test/suite/binlog/t/flashback.test
@@ -0,0 +1,378 @@
+--source include/have_log_bin.inc
+--source include/have_innodb.inc
+
+--echo #
+--echo # Preparatory cleanup.
+--echo #
+--disable_warnings
+DROP TABLE IF EXISTS t1;
+--enable_warnings
+
+--echo #
+--echo # We need a fixed timestamp to avoid varying results.
+--echo #
+SET timestamp=1000000000;
+
+--echo # < CASE 1 >
+--echo # Delete all existing binary logs.
+--echo #
+RESET MASTER;
+
+CREATE TABLE t1 (
+ c01 tinyint,
+ c02 smallint,
+ c03 mediumint,
+ c04 int,
+ c05 bigint,
+ c06 char(10),
+ c07 varchar(20),
+ c08 TEXT
+) ENGINE=InnoDB;
+
+--echo # < CASE 1 >
+--echo # Insert data to t1
+--echo #
+INSERT INTO t1 VALUES(0,0,0,0,0,'','','');
+INSERT INTO t1 VALUES(1,2,3,4,5, "abc", "abcdefg", "abcedfghijklmnopqrstuvwxyz");
+INSERT INTO t1 VALUES(127, 32767, 8388607, 2147483647, 9223372036854775807, repeat('a', 10), repeat('a', 20), repeat('a', 255));
+
+
+--echo # < CASE 1 >
+--echo # Update t1
+--echo #
+UPDATE t1 SET c01=100 WHERE c02=0 OR c03=3;
+
+--echo # < CASE 1 >
+--echo # Clear t1
+--echo #
+DELETE FROM t1;
+
+FLUSH LOGS;
+
+--echo # < CASE 1 >
+--echo # Show mysqlbinlog result without -B
+--echo #
+
+let $MYSQLD_DATADIR= `select @@datadir`;
+--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
+--replace_regex /SQL_LOAD_MB-[0-9]-[0-9]/SQL_LOAD_MB-#-#/ /exec_time=[0-9]*/exec_time=#/ /end_log_pos [0-9]*/end_log_pos #/ /# at [0-9]*/# at #/ /Xid = [0-9]*/Xid = #/ /thread_id=[0-9]*/thread_id=#/ /table id [0-9]*/table id #/ /mapped to number [0-9]*/mapped to number #/ /server v [^ ]*/server v #.##.##/ /CRC32 0x[0-9a-f]*/CRC32 XXX/ /collation_server=[0-9]+/collation_server=X/ /character_set_client=[a-zA-Z0-9]+/character_set_client=X/ /collation_connection=[0-9]+/collation_connection=X/ /xid=\d*/xid=<xid>/
+--exec $MYSQL_BINLOG --base64-output=decode-rows -v -v $MYSQLD_DATADIR/master-bin.000001
+
+--echo # < CASE 1 >
+--echo # Show mysqlbinlog result with -B
+--echo #
+
+let $MYSQLD_DATADIR= `select @@datadir`;
+--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
+--replace_regex /SQL_LOAD_MB-[0-9]-[0-9]/SQL_LOAD_MB-#-#/ /exec_time=[0-9]*/exec_time=#/ /end_log_pos [0-9]*/end_log_pos #/ /# at [0-9]*/# at #/ /Xid = [0-9]*/Xid = #/ /thread_id=[0-9]*/thread_id=#/ /table id [0-9]*/table id #/ /mapped to number [0-9]*/mapped to number #/ /server v [^ ]*/server v #.##.##/ /CRC32 0x[0-9a-f]*/CRC32 XXX/ /collation_server=[0-9]+/collation_server=X/ /character_set_client=[a-zA-Z0-9]+/character_set_client=X/ /collation_connection=[0-9]+/collation_connection=X/ /xid=\d*/xid=<xid>/
+--exec $MYSQL_BINLOG -B --base64-output=decode-rows -v -v $MYSQLD_DATADIR/master-bin.000001
+
+--echo # < CASE 1 >
+--echo # Insert data to t1
+--echo #
+TRUNCATE TABLE t1;
+INSERT INTO t1 VALUES(0,0,0,0,0,'','','');
+INSERT INTO t1 VALUES(1,2,3,4,5, "abc", "abcdefg", "abcedfghijklmnopqrstuvwxyz");
+INSERT INTO t1 VALUES(127, 32767, 8388607, 2147483647, 9223372036854775807, repeat('a', 10), repeat('a', 20), repeat('a', 60));
+
+--echo # < CASE 1 >
+--echo # Delete all existing binary logs.
+--echo #
+RESET MASTER;
+SELECT * FROM t1;
+
+--echo # < CASE 1 >
+--echo # Operate some data
+--echo #
+
+UPDATE t1 SET c01=20;
+UPDATE t1 SET c02=200;
+UPDATE t1 SET c03=2000;
+
+DELETE FROM t1;
+
+FLUSH LOGS;
+
+--echo # < CASE 1 >
+--echo # Flashback & Check the result
+--echo #
+
+let $MYSQLD_DATADIR= `select @@datadir`;
+--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
+--exec $MYSQL_BINLOG -vv $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/mysqlbinlog_row_flashback_original_1.sql
+--exec $MYSQL_BINLOG -B -vv $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/mysqlbinlog_row_flashback_1.sql
+--exec $MYSQL -e "SET binlog_format= ROW; source $MYSQLTEST_VARDIR/tmp/mysqlbinlog_row_flashback_1.sql;"
+
+SELECT * FROM t1;
+
+RESET MASTER;
+
+--echo # < CASE 2 >
+--echo # UPDATE multi-rows in one event
+--echo #
+
+BEGIN;
+UPDATE t1 SET c01=10 WHERE c01=0;
+UPDATE t1 SET c01=20 WHERE c01=10;
+COMMIT;
+
+FLUSH LOGS;
+
+--echo # < CASE 2 >
+--echo # Flashback & Check the result
+--echo #
+
+let $MYSQLD_DATADIR= `select @@datadir`;
+--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
+--exec $MYSQL_BINLOG -vv $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/mysqlbinlog_row_flashback_original_2.sql
+--exec $MYSQL_BINLOG -B -vv $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/mysqlbinlog_row_flashback_2.sql
+--exec $MYSQL -e "SET binlog_format= ROW; source $MYSQLTEST_VARDIR/tmp/mysqlbinlog_row_flashback_2.sql;"
+
+SELECT * FROM t1;
+
+DROP TABLE t1;
+
+--echo # < CASE 3 >
+--echo # Self-referencing foreign keys
+--echo #
+
+CREATE TABLE t1 (a INT PRIMARY KEY, b INT, FOREIGN KEY my_fk(b) REFERENCES t1(a)) ENGINE=InnoDB;
+
+BEGIN;
+INSERT INTO t1 VALUES (1, NULL);
+INSERT INTO t1 VALUES (2, 1), (3, 2), (4, 3);
+COMMIT;
+
+SELECT * FROM t1;
+
+# New binlog
+RESET MASTER;
+
+DELETE FROM t1 ORDER BY a DESC;
+
+FLUSH LOGS;
+
+--echo # < CASE 3 >
+--echo # Flashback & Check the result
+--echo #
+
+let $MYSQLD_DATADIR= `select @@datadir`;
+--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
+--exec $MYSQL_BINLOG -vv $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/mysqlbinlog_row_flashback_original_3.sql
+--exec $MYSQL_BINLOG -B -vv $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/mysqlbinlog_row_flashback_3.sql
+--exec $MYSQL -e "SET binlog_format= ROW; source $MYSQLTEST_VARDIR/tmp/mysqlbinlog_row_flashback_3.sql;"
+
+SELECT * FROM t1;
+
+DROP TABLE t1;
+
+--echo # < CASE 4 >
+--echo # Trigger
+--echo #
+
+CREATE TABLE t1 (a INT PRIMARY KEY, b INT) ENGINE=InnoDB;
+CREATE TABLE t2 (a INT PRIMARY KEY, b INT) ENGINE=InnoDB;
+
+BEGIN;
+INSERT INTO t1 VALUES (1, NULL);
+INSERT INTO t1 VALUES (2, 1), (3, 2), (4, 3);
+INSERT INTO t2 VALUES (6, 7), (7, 8), (8, 9);
+COMMIT;
+
+SELECT * FROM t1;
+SELECT * FROM t2;
+
+CREATE TRIGGER trg1 BEFORE INSERT ON t1 FOR EACH ROW DELETE FROM t2 WHERE a = NEW.b;
+
+# New binlog
+RESET MASTER;
+
+INSERT INTO t1 VALUES (5, 6), (7, 8);
+
+SELECT * FROM t1;
+SELECT * FROM t2;
+
+FLUSH LOGS;
+
+--echo # < CASE 4 >
+--echo # Flashback & Check the result
+--echo #
+
+let $MYSQLD_DATADIR= `select @@datadir`;
+--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
+--exec $MYSQL_BINLOG -vv $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/mysqlbinlog_row_flashback_original_4.sql
+--exec $MYSQL_BINLOG -B $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/mysqlbinlog_row_flashback_4.sql
+--exec $MYSQL -e "SET binlog_format= ROW; source $MYSQLTEST_VARDIR/tmp/mysqlbinlog_row_flashback_4.sql;"
+
+SELECT * FROM t1;
+SELECT * FROM t2;
+
+DROP TRIGGER trg1;
+DROP TABLE t1;
+DROP TABLE t2;
+
+--echo # < CASE 5 >
+--echo # REPLCAE Queries
+--echo #
+
+CREATE TABLE t1 (a INT PRIMARY KEY, b INT, UNIQUE uk(b)) ENGINE=InnoDB;
+
+BEGIN;
+INSERT INTO t1 VALUES (1, NULL);
+INSERT INTO t1 VALUES (2, 1), (3, 2), (4, 3);
+INSERT INTO t1 VALUES (5, 4), (6, 5), (7, 6);
+COMMIT;
+
+SELECT * FROM t1;
+
+# New binlog
+RESET MASTER;
+
+REPLACE INTO t1 VALUES (3, 100);
+REPLACE INTO t1 SET a=4, b=200;
+
+SELECT * FROM t1;
+
+REPLACE INTO t1 VALUES (5,5);
+
+SELECT * FROM t1;
+
+FLUSH LOGS;
+
+--echo # < CASE 5 >
+--echo # Flashback & Check the result
+--echo #
+
+let $MYSQLD_DATADIR= `select @@datadir`;
+--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
+--exec $MYSQL_BINLOG -vv $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/mysqlbinlog_row_flashback_original_5.sql
+--exec $MYSQL_BINLOG -B $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/mysqlbinlog_row_flashback_5.sql
+--exec $MYSQL -e "SET binlog_format= ROW; source $MYSQLTEST_VARDIR/tmp/mysqlbinlog_row_flashback_5.sql;"
+
+SELECT * FROM t1;
+
+DROP TABLE t1;
+
+
+--echo # < CASE 6 >
+--echo # Test Case from MDEV-21067
+--echo #
+
+# Init Structure
+CREATE DATABASE world;
+CREATE TABLE world.city (
+ ID INT AUTO_INCREMENT PRIMARY KEY,
+ Name VARCHAR(64),
+ CountryCode VARCHAR(64),
+ District VARCHAR(64),
+ Population INT
+) ENGINE=InnoDB;
+CREATE TABLE test.test (
+ ID INT AUTO_INCREMENT PRIMARY KEY,
+ REC VARCHAR(64),
+ ts TIMESTAMP
+) ENGINE=InnoDB;
+
+INSERT INTO world.city VALUES (NULL, 'Davenport', 'USA', 'Iowa', 100);
+INSERT INTO world.city VALUES (NULL, 'Boulder', 'USA', 'Colorado', 1000);
+INSERT INTO world.city VALUES (NULL, 'Gweru', 'ZWE', 'Midlands', 10000);
+
+RESET MASTER;
+
+CHECKSUM TABLE world.city;
+
+# Insert test data
+INSERT INTO test.test VALUES (NULL, 'Good record 1', CURRENT_TIMESTAMP());
+
+INSERT INTO world.city VALUES (NULL, 'Wrong value 1', '000', 'Wrong', 0);
+INSERT INTO world.city VALUES (NULL, 'Wrong value 2', '000', 'Wrong', 0) , (NULL, 'Wrong value 3', '000', 'Wrong', 0);
+
+INSERT INTO test.test VALUES (NULL, 'Good record 2', CURRENT_TIMESTAMP());
+
+UPDATE world.city SET Population = 99999999 WHERE ID IN (1, 2, 3);
+
+INSERT INTO test.test VALUES (NULL, 'Good record 3', CURRENT_TIMESTAMP());
+
+DELETE FROM world.city WHERE ID BETWEEN 1 AND 2;
+
+INSERT INTO test.test VALUES (NULL, 'Good record 5', CURRENT_TIMESTAMP());
+
+REPLACE INTO world.city VALUES (4074, 'Wrong value 4', '000', 'Wrong', 0);
+REPLACE INTO world.city VALUES (4078, 'Wrong value 5', '000', 'Wrong', 0), (NULL, 'Wrong value 6', '000', 'Wrong', 0);
+
+INSERT INTO test.test VALUES (NULL, 'Good record 6', CURRENT_TIMESTAMP());
+
+INSERT INTO world.city
+SELECT NULL, Name, CountryCode, District, Population FROM world.city WHERE ID BETWEEN 2 AND 10;
+
+INSERT INTO test.test VALUES (NULL, 'Good record 7', CURRENT_TIMESTAMP());
+
+INSERT INTO test.test VALUES (NULL, 'Good record 8', CURRENT_TIMESTAMP());
+
+DELETE FROM world.city;
+
+INSERT INTO test.test VALUES (NULL, 'Good record 9', CURRENT_TIMESTAMP());
+
+FLUSH LOGS;
+
+--echo # < CASE 6 >
+--echo # Flashback & Check the result
+--echo #
+
+let $MYSQLD_DATADIR= `select @@datadir`;
+--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
+--exec $MYSQL_BINLOG --database=world --table=city -vv $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/mysqlbinlog_row_flashback_original_6.sql
+--exec $MYSQL_BINLOG --database=world --table=city -B $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/mysqlbinlog_row_flashback_6.sql
+--exec $MYSQL -e "SET binlog_format= ROW; source $MYSQLTEST_VARDIR/tmp/mysqlbinlog_row_flashback_6.sql;"
+
+SELECT * FROM world.city;
+
+SELECT * FROM test.test;
+
+CHECKSUM TABLE world.city;
+
+DROP TABLE test.test;
+DROP TABLE world.city;
+DROP DATABASE world;
+
+--echo # < CASE 7 >
+--echo # Test Case for MDEV-17260
+--echo #
+
+RESET MASTER;
+
+CREATE TABLE t1 ( f INT PRIMARY KEY ) ENGINE=innodb;
+INSERT INTO t1 VALUES (1),(2),(3),(4),(5),(6);
+--echo # 6- Rows must be present
+SELECT COUNT(*) FROM t1;
+FLUSH LOGS;
+DELETE FROM t1;
+FLUSH LOGS;
+
+--echo # 0- Rows must be present
+--let $assert_cond= COUNT(*) = 0 FROM t1
+--let $assert_text= Table t1 should have 0 rows.
+--source include/assert.inc
+
+--exec $MYSQL_BINLOG -vv -B --read-from-remote-server --user=root --host=127.0.0.1 --port=$MASTER_MYPORT master-bin.000002> $MYSQLTEST_VARDIR/tmp/mysqlbinlog_row_flashback_7.sql
+--exec $MYSQL -e "SET binlog_format= ROW; source $MYSQLTEST_VARDIR/tmp/mysqlbinlog_row_flashback_7.sql;"
+
+--echo # 6- Rows must be present upon restoring from flashback
+--let $assert_cond= COUNT(*) = 6 FROM t1
+--let $assert_text= Table t1 should have six rows.
+--source include/assert.inc
+
+DROP TABLE t1;
+
+--echo #
+--echo # MDEV-30698 Cover missing test cases for mariadb-binlog options
+--echo # --raw [and] --flashback
+--echo #
+
+--error 1 # --raw mode and --flashback mode are not allowed
+--exec $MYSQL_BINLOG -vv -B --raw --read-from-remote-server --user=root --host=127.0.0.1 --port=$MASTER_MYPORT master-bin.000003> $MYSQLTEST_VARDIR/tmp/mysqlbinlog_row_flashback_8.sql
+
+## Clear
+SET binlog_format=statement;
+--error ER_FLASHBACK_NOT_SUPPORTED
+SET GLOBAL binlog_format=statement;
diff --git a/mysql-test/suite/binlog/t/foreign_key.test b/mysql-test/suite/binlog/t/foreign_key.test
new file mode 100644
index 00000000..87c719e4
--- /dev/null
+++ b/mysql-test/suite/binlog/t/foreign_key.test
@@ -0,0 +1,22 @@
+--source include/have_innodb.inc
+--source include/have_binlog_format_row.inc
+
+reset master;
+
+CREATE TABLE t1 (
+ id INT,
+ k INT,
+ c CHAR(8),
+ KEY (k),
+ PRIMARY KEY (id),
+ FOREIGN KEY (id) REFERENCES t1 (k)
+) ENGINE=InnoDB;
+LOCK TABLES t1 WRITE;
+SET SESSION FOREIGN_KEY_CHECKS= OFF;
+SET AUTOCOMMIT=OFF;
+INSERT INTO t1 VALUES (1,1,'foo');
+DROP TABLE t1;
+SET SESSION FOREIGN_KEY_CHECKS= ON;
+SET AUTOCOMMIT=ON;
+
+source include/show_binlog_events.inc;
diff --git a/mysql-test/suite/binlog/t/innodb_autoinc_lock_mode_binlog.opt b/mysql-test/suite/binlog/t/innodb_autoinc_lock_mode_binlog.opt
new file mode 100644
index 00000000..824f656c
--- /dev/null
+++ b/mysql-test/suite/binlog/t/innodb_autoinc_lock_mode_binlog.opt
@@ -0,0 +1 @@
+--innodb_autoinc_lock_mode=2
diff --git a/mysql-test/suite/binlog/t/innodb_autoinc_lock_mode_binlog.test b/mysql-test/suite/binlog/t/innodb_autoinc_lock_mode_binlog.test
new file mode 100644
index 00000000..283862ec
--- /dev/null
+++ b/mysql-test/suite/binlog/t/innodb_autoinc_lock_mode_binlog.test
@@ -0,0 +1,21 @@
+--source include/have_innodb.inc
+--source include/have_binlog_format_mixed.inc
+reset master; #clear up binlogs
+call mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT");
+
+select @@innodb_autoinc_lock_mode;
+select @@binlog_format;
+
+create table t1 (a int not null auto_increment,b int, primary key (a)) engine=InnoDB;
+insert into t1 values (NULL,1);
+--source include/show_binlog_events.inc
+
+set global binlog_format=STATEMENT;
+--connect (con1,localhost,root,,test,$MASTER_MYPORT,$MASTER_MYSOCK)
+insert into t1 values (NULL,1);
+insert into t1 values (NULL,1);
+--disconnect con1
+--connection default
+
+set global binlog_format=MIXED;
+DROP TABLE t1;
diff --git a/mysql-test/suite/binlog/t/innodb_rc_insert_before_delete.test b/mysql-test/suite/binlog/t/innodb_rc_insert_before_delete.test
new file mode 100644
index 00000000..228d9778
--- /dev/null
+++ b/mysql-test/suite/binlog/t/innodb_rc_insert_before_delete.test
@@ -0,0 +1,92 @@
+--source include/have_innodb.inc
+--source include/have_debug.inc
+--source include/have_debug_sync.inc
+--source include/have_binlog_format_mixed.inc
+--source include/count_sessions.inc
+
+RESET MASTER;
+
+# MDEV-30010 merely adds is a Read-Committed version MDEV-30225 test
+# solely to prove the RC isolation yields ROW binlog format as it is
+# supposed to:
+# https://mariadb.com/kb/en/unsafe-statements-for-statement-based-replication/#isolation-levels.
+# The original MDEV-30225 test is adapted to the RC to create
+# a similar safisticated scenario which does not lead to any deadlock though.
+
+--connect (pause_purge,localhost,root)
+START TRANSACTION WITH CONSISTENT SNAPSHOT;
+
+--connection default
+CREATE TABLE t (pk int PRIMARY KEY, sk INT UNIQUE) ENGINE=InnoDB;
+INSERT INTO t VALUES (10, 100);
+
+--connect (con1,localhost,root)
+BEGIN; # trx 0
+SELECT * FROM t WHERE sk = 100 FOR UPDATE;
+
+--connect (con2,localhost,root)
+SET DEBUG_SYNC="lock_wait_start SIGNAL insert_wait_started";
+# trx 1 is locked on try to read the record in secondary index during duplicates
+# check. It's the first in waiting queue, that's why it will be woken up firstly
+# when trx 0 commits.
+--send INSERT INTO t VALUES (5, 100) # trx 1
+
+--connect (con3,localhost,root)
+SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
+SET DEBUG_SYNC="now WAIT_FOR insert_wait_started";
+SET DEBUG_SYNC="lock_wait_start SIGNAL delete_started_waiting";
+# trx 2 can delete (5, 100) on master, but not on slave, as on slave trx 1
+# can insert (5, 100) after trx 2 positioned it's cursor. Trx 2 lock is placed
+# in waiting queue after trx 1 lock, but its persistent cursor position was
+# stored on (100, 10) record in secondary index before suspending. After trx 1
+# is committed, trx 2 will restore persistent cursor position on (100, 10). As
+# (100, 5) secondary index record was inserted before (100, 10) in logical
+# order, and (100, 10) record is delete-marked, trx 2 just continues scanning.
+#
+# Note. There can be several records with the same key in unique secondary
+# index, but only one of them must be non-delete-marked. That's why when we do
+# point query, cursor position is set in the first record in logical order, and
+# then records are iterated until either non-delete-marked record is found or
+# all records with the same unique fields are iterated.
+
+# to prepare showing interesting binlog events
+--let $binlog_start= query_get_value(SHOW MASTER STATUS, Position, 1)
+--let $binlog_file=query_get_value(SHOW MASTER STATUS, File, 1)
+BEGIN;
+--send UPDATE t SET sk = 200 WHERE sk = 100; # trx 2
+
+--connection con1
+SET DEBUG_SYNC="now WAIT_FOR delete_started_waiting";
+DELETE FROM t WHERE sk=100; # trx 0
+COMMIT;
+--disconnect con1
+
+--connection con2
+--reap
+--disconnect con2
+
+--connection con3
+--error 0
+--reap
+if (`SELECT ROW_COUNT() > 0`)
+{
+ --echo unexpected effective UPDATE
+ --die
+}
+--echo must be logged in ROW format as the only event of trx 2 (con3)
+INSERT INTO t VALUES (11, 101);
+COMMIT;
+--source include/show_binlog_events.inc
+--disconnect con3
+
+--connection default
+# If the bug is not fixed, we will see the row inserted by trx 1 here. This can
+# cause duplicate key error on slave, when some other trx tries in insert row
+# with the same secondary key, as was inserted by trx 1, and not deleted by trx
+# 2.
+SELECT * FROM t;
+
+--disconnect pause_purge
+SET DEBUG_SYNC="RESET";
+DROP TABLE t;
+--source include/wait_until_count_sessions.inc
diff --git a/mysql-test/suite/binlog/t/load_data_stm_view.test b/mysql-test/suite/binlog/t/load_data_stm_view.test
new file mode 100644
index 00000000..9f64b813
--- /dev/null
+++ b/mysql-test/suite/binlog/t/load_data_stm_view.test
@@ -0,0 +1,24 @@
+#
+# MDEV-3940 Server crash or assertion `item->type() == Item::STRING_ITEM' failure on LOAD DATA through a view with statement binary logging
+#
+
+--source include/have_binlog_format_statement.inc
+
+--write_file $MYSQLTEST_VARDIR/3940.data
+1
+EOF
+
+reset master;
+
+create table t1 (i int, j int);
+create view v1 as select i from t1;
+--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
+--eval LOAD DATA LOCAL INFILE '$MYSQLTEST_VARDIR/3940.data' INTO TABLE v1 (i)
+--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
+--eval LOAD DATA LOCAL INFILE '$MYSQLTEST_VARDIR/3940.data' INTO TABLE v1
+select * from v1;
+--let $binlog_file = LAST
+--source include/show_binlog_events.inc
+drop view v1;
+drop table t1;
+--remove_file $MYSQLTEST_VARDIR/3940.data
diff --git a/mysql-test/suite/binlog/t/mysqladmin.test b/mysql-test/suite/binlog/t/mysqladmin.test
new file mode 100644
index 00000000..3c2fbc0a
--- /dev/null
+++ b/mysql-test/suite/binlog/t/mysqladmin.test
@@ -0,0 +1,12 @@
+source include/have_binlog_format_statement.inc;
+#
+# MDEV-12612 mysqladmin --local flush... to use FLUSH LOCAL
+#
+create user adm@localhost identified by 'foobar';
+grant reload on *.* to adm@localhost;
+reset master;
+exec $MYSQLADMIN -uadm -pfoobar flush-status;
+source include/show_binlog_events.inc;
+exec $MYSQLADMIN --local -uadm -pfoobar flush-status;
+source include/show_binlog_events.inc;
+drop user adm@localhost;
diff --git a/mysql-test/suite/binlog/t/read_only.inc b/mysql-test/suite/binlog/t/read_only.inc
new file mode 100644
index 00000000..78136b90
--- /dev/null
+++ b/mysql-test/suite/binlog/t/read_only.inc
@@ -0,0 +1,79 @@
+--echo #
+--echo # MDEV-17863 DROP TEMPORARY TABLE creates a transaction in
+--echo # binary log on read only server
+--echo # MDEV-19074 Improved read_only mode for slaves with
+--echo # gtid_strict_mode enabled
+--echo #
+
+create user test@localhost;
+grant CREATE TEMPORARY TABLES, DROP, INSERT, SELECT on *.* to test@localhost;
+create table t1 (a int) engine=myisam;
+insert into t1 values (1),(2);
+reset master;
+
+set global read_only=1;
+--echo # Ensure that optimize and analyze doesn't log to binary log
+connect (con1,localhost,test,,test);
+--error ER_OPTION_PREVENTS_STATEMENT
+insert into t1 values(3);
+analyze table t1;
+check table t1;
+repair table t1;
+--error ER_OPTION_PREVENTS_STATEMENT
+optimize table t1;
+
+--echo # Ensure that using temporary tables is not logged
+create temporary table tmp1 (a int) engine=myisam;
+insert into tmp1 values (1),(2);
+update tmp1 set a=10 where a=2;
+delete from tmp1 where a=1;
+create temporary table tmp2 select * from t1;
+select * from tmp1;
+select * from tmp2;
+create temporary table tmp3 like t1;
+create or replace temporary table tmp3 like t1;
+alter table tmp2 add column (b int);
+select * from tmp2;
+--error ER_OPTION_PREVENTS_STATEMENT
+insert into t1 select a+100 from tmp2;
+drop table tmp1,tmp2,tmp3;
+
+--echo # Clean up test connection
+disconnect con1;
+connection default;
+
+--echo # Execute some commands as root that should not be logged
+optimize table t1;
+repair table t1;
+
+--echo # Changes to temporary tables created under readonly should not
+--echo # be logged
+create temporary table tmp4 (a int) engine=myisam;
+insert into tmp4 values (1),(2);
+create temporary table tmp5 (a int) engine=myisam;
+insert into tmp5 select * from tmp4;
+alter table tmp5 add column (b int);
+
+set global read_only=0;
+
+insert into tmp4 values (3),(4);
+insert into tmp5 values (10,3),(11,4);
+select * from tmp4;
+select * from tmp5;
+update tmp4 set a=10 where a=2;
+delete from tmp4 where a=1;
+create table t2 select * from tmp4;
+alter table tmp5 add column (c int);
+insert into tmp5 values (20,5,1),(21,5,2);
+select * from tmp5;
+insert into t1 select a+200 from tmp5;
+select * from t1;
+drop table tmp4,tmp5;
+
+--echo # Check what is logged. Only last create select and the insert...select's should be
+--echo # row-logged
+source include/show_binlog_events.inc;
+
+--echo # Clean up
+drop user test@localhost;
+drop table t1,t2;
diff --git a/mysql-test/suite/binlog/t/read_only.test b/mysql-test/suite/binlog/t/read_only.test
new file mode 100644
index 00000000..14a4650b
--- /dev/null
+++ b/mysql-test/suite/binlog/t/read_only.test
@@ -0,0 +1,2 @@
+--source include/have_binlog_format_mixed_or_row.inc
+--source read_only.inc
diff --git a/mysql-test/suite/binlog/t/read_only_statement.test b/mysql-test/suite/binlog/t/read_only_statement.test
new file mode 100644
index 00000000..a976854f
--- /dev/null
+++ b/mysql-test/suite/binlog/t/read_only_statement.test
@@ -0,0 +1,2 @@
+--source include/have_binlog_format_statement.inc
+--source read_only.inc
diff --git a/mysql-test/suite/binlog/t/show_concurrent_rotate.test b/mysql-test/suite/binlog/t/show_concurrent_rotate.test
new file mode 100644
index 00000000..b5758e3a
--- /dev/null
+++ b/mysql-test/suite/binlog/t/show_concurrent_rotate.test
@@ -0,0 +1,29 @@
+--source include/have_debug.inc
+--source include/have_debug_sync.inc
+# mere to limit it run rate
+--source include/have_binlog_format_row.inc
+
+connect(con1,localhost,root,,);
+FLUSH LOGS;
+FLUSH LOGS;
+FLUSH LOGS;
+
+# This forced synchronization pattern ensures con1 will execute its retry
+# path. More specifically, con1 should see that the cache of log files it
+# creates during SHOW BINARY LOGS becomes invalidated after con2 completes
+# RESET MASTER.
+SET DEBUG_SYNC= "at_after_lock_index SIGNAL con1_ready WAIT_FOR con1_go";
+--send SHOW BINARY LOGS
+
+connect(con2,localhost,root,,);
+SET DEBUG_SYNC= "now WAIT_FOR con1_ready";
+RESET MASTER;
+FLUSH LOGS;
+SET DEBUG_SYNC= "now SIGNAL con1_go";
+
+--connection con1
+--echo # The correct result must consists of two records
+--replace_column 2 #
+--reap
+
+SET debug_sync = 'reset';
diff --git a/mysql-test/suite/binlog/t/start_alter_mysqlbinlog_replay.test b/mysql-test/suite/binlog/t/start_alter_mysqlbinlog_replay.test
new file mode 100644
index 00000000..d59456d7
--- /dev/null
+++ b/mysql-test/suite/binlog/t/start_alter_mysqlbinlog_replay.test
@@ -0,0 +1,61 @@
+#
+# MENT-662: Lag Free Alter On Slave
+#
+
+--echo #
+--echo # Test verifies replay of binary logs which contain
+--echo # SA/RA/CA works fine.
+--echo # Generate a binary log with alter events and use mysqlbinlog tool to
+--echo # generate a sql file for replay. Source it on an clean master and
+--echo # verify the correctness. Use the latest binlog and repeat the same
+--echo # process mentioned above and observe replay works fine.
+--echo #
+--source include/have_log_bin.inc
+--source include/have_innodb.inc
+--source include/have_binlog_format_statement.inc
+
+--let $binlog_alter_two_phase= `select @@binlog_alter_two_phase`
+set global binlog_alter_two_phase = ON;
+set binlog_alter_two_phase = ON;
+
+create table t1 (f1 int primary key) engine=InnoDB;
+create table t2 (f1 int primary key, constraint c1 foreign key (f1) references t1(f1)) engine=innodb;
+
+--error ER_CANT_CREATE_TABLE
+alter table t2 add constraint c1 foreign key (f1) references t1(f1);
+
+drop table t2, t1;
+select @@gtid_binlog_state;
+FLUSH LOGS;
+
+let MYSQLD_DATADIR= `select @@datadir;`;
+--exec $MYSQL_BINLOG $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/slave_1.sql
+
+--echo # reset the binlog
+RESET MASTER;
+--echo # execute the binlog
+--exec $MYSQL --port=$MASTER_MYPORT --host=127.0.0.1 -e "source $MYSQLTEST_VARDIR/tmp/slave_1.sql"
+SELECT @@gtid_binlog_state;
+FLUSH LOGS;
+--echo # Replay 1: One more time to simulate S->S case
+--exec $MYSQL_BINLOG $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/slave_2.sql
+
+RESET MASTER;
+--echo # execute the binlog
+--exec $MYSQL --port=$MASTER_MYPORT --host=127.0.0.1 -e "source $MYSQLTEST_VARDIR/tmp/slave_2.sql"
+SELECT @@gtid_binlog_state;
+FLUSH LOGS;
+--echo # Replay 2: One more time to simulate S->S case
+--exec $MYSQL_BINLOG $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/slave_3.sql
+RESET MASTER;
+--echo # execute the binlog
+--exec $MYSQL --port=$MASTER_MYPORT --host=127.0.0.1 -e "source $MYSQLTEST_VARDIR/tmp/slave_3.sql"
+SELECT @@gtid_binlog_state;
+
+--echo # clean up
+remove_file $MYSQLTEST_VARDIR/tmp/slave_1.sql;
+remove_file $MYSQLTEST_VARDIR/tmp/slave_2.sql;
+remove_file $MYSQLTEST_VARDIR/tmp/slave_3.sql;
+RESET MASTER;
+
+--eval set global binlog_alter_two_phase=$binlog_alter_two_phase
diff --git a/mysql-test/suite/binlog/t/temptable_uservar_disconnect-7938.test b/mysql-test/suite/binlog/t/temptable_uservar_disconnect-7938.test
new file mode 100644
index 00000000..a1d91e2f
--- /dev/null
+++ b/mysql-test/suite/binlog/t/temptable_uservar_disconnect-7938.test
@@ -0,0 +1,17 @@
+#
+# MDEV-7938 MariaDB Crashes Suddenly while writing binlogs
+#
+--source include/have_log_bin.inc
+--source include/have_binlog_format_mixed.inc
+
+--connect(con1,localhost,root,,)
+create table t1 (i int);
+create trigger tr after insert on t1 for each row set @b=@a;
+
+create temporary table tmp like t1;
+insert into t1 values (1);
+--disconnect con1
+
+--connection default
+select * from t1;
+drop table t1;