summaryrefslogtreecommitdiffstats
path: root/mysql-test/suite/rpl/t
diff options
context:
space:
mode:
Diffstat (limited to 'mysql-test/suite/rpl/t')
-rw-r--r--mysql-test/suite/rpl/t/circular_serverid0.cnf30
-rw-r--r--mysql-test/suite/rpl/t/circular_serverid0.test103
-rw-r--r--mysql-test/suite/rpl/t/create_or_replace.inc227
-rw-r--r--mysql-test/suite/rpl/t/create_or_replace2.test42
-rw-r--r--mysql-test/suite/rpl/t/create_or_replace_mix.cnf9
-rw-r--r--mysql-test/suite/rpl/t/create_or_replace_mix.test4
-rw-r--r--mysql-test/suite/rpl/t/create_or_replace_row.cnf9
-rw-r--r--mysql-test/suite/rpl/t/create_or_replace_row.test4
-rw-r--r--mysql-test/suite/rpl/t/create_or_replace_statement.cnf9
-rw-r--r--mysql-test/suite/rpl/t/create_or_replace_statement.test4
-rw-r--r--mysql-test/suite/rpl/t/create_select.cnf16
-rw-r--r--mysql-test/suite/rpl/t/create_select.test37
-rw-r--r--mysql-test/suite/rpl/t/failed_create_view-6409.test24
-rw-r--r--mysql-test/suite/rpl/t/grant_replication_slave.test39
-rw-r--r--mysql-test/suite/rpl/t/ignore_table_autoinc-9737.test35
-rw-r--r--mysql-test/suite/rpl/t/kill_hard-6290.test11
-rw-r--r--mysql-test/suite/rpl/t/kill_race_condition.test36
-rw-r--r--mysql-test/suite/rpl/t/last_insert_id.cnf20
-rw-r--r--mysql-test/suite/rpl/t/last_insert_id.test30
-rw-r--r--mysql-test/suite/rpl/t/mdev-31448_kill_ooo_finish_optimistic.test93
-rw-r--r--mysql-test/suite/rpl/t/mdev_17588-slave.opt1
-rw-r--r--mysql-test/suite/rpl/t/mdev_17588.test44
-rw-r--r--mysql-test/suite/rpl/t/mdev_24667.cnf8
-rw-r--r--mysql-test/suite/rpl/t/mdev_24667.test56
-rw-r--r--mysql-test/suite/rpl/t/myisam_external_lock-slave.opt2
-rw-r--r--mysql-test/suite/rpl/t/myisam_external_lock.test24
-rw-r--r--mysql-test/suite/rpl/t/mysql-wsrep#110-2.test44
-rw-r--r--mysql-test/suite/rpl/t/parallel_backup.test107
-rw-r--r--mysql-test/suite/rpl/t/parallel_backup_lsu_off-slave.opt2
-rw-r--r--mysql-test/suite/rpl/t/parallel_backup_lsu_off.test7
-rw-r--r--mysql-test/suite/rpl/t/parallel_backup_slave_binlog_off-slave.opt1
-rw-r--r--mysql-test/suite/rpl/t/parallel_backup_slave_binlog_off.test7
-rw-r--r--mysql-test/suite/rpl/t/parallel_backup_xa.inc79
-rw-r--r--mysql-test/suite/rpl/t/password_expiration.test53
-rw-r--r--mysql-test/suite/rpl/t/rename.test33
-rw-r--r--mysql-test/suite/rpl/t/replace.test24
-rw-r--r--mysql-test/suite/rpl/t/rpl_000010-slave.opt1
-rw-r--r--mysql-test/suite/rpl/t/rpl_000010.test22
-rw-r--r--mysql-test/suite/rpl/t/rpl_000011-slave.opt1
-rw-r--r--mysql-test/suite/rpl/t/rpl_000011.test34
-rw-r--r--mysql-test/suite/rpl/t/rpl_000013.test55
-rw-r--r--mysql-test/suite/rpl/t/rpl_000017.test47
-rw-r--r--mysql-test/suite/rpl/t/rpl_15867.test11
-rw-r--r--mysql-test/suite/rpl/t/rpl_15919-slave.opt1
-rw-r--r--mysql-test/suite/rpl/t/rpl_15919.test18
-rw-r--r--mysql-test/suite/rpl/t/rpl_EE_err.test2
-rw-r--r--mysql-test/suite/rpl/t/rpl_LD_INFILE.test39
-rw-r--r--mysql-test/suite/rpl/t/rpl_alter.test71
-rw-r--r--mysql-test/suite/rpl/t/rpl_alter_db.test15
-rw-r--r--mysql-test/suite/rpl/t/rpl_alter_extra_persistent.test106
-rw-r--r--mysql-test/suite/rpl/t/rpl_alter_instant.test50
-rw-r--r--mysql-test/suite/rpl/t/rpl_alter_rollback.test42
-rw-r--r--mysql-test/suite/rpl/t/rpl_auto_increment-master.opt1
-rw-r--r--mysql-test/suite/rpl/t/rpl_auto_increment-slave.opt1
-rw-r--r--mysql-test/suite/rpl/t/rpl_auto_increment.test7
-rw-r--r--mysql-test/suite/rpl/t/rpl_auto_increment_11932.test66
-rw-r--r--mysql-test/suite/rpl/t/rpl_auto_increment_bug33029.test60
-rw-r--r--mysql-test/suite/rpl/t/rpl_auto_increment_bug45679.test64
-rw-r--r--mysql-test/suite/rpl/t/rpl_auto_increment_update_failure.test211
-rw-r--r--mysql-test/suite/rpl/t/rpl_autogen_query_multi_byte_char.test87
-rw-r--r--mysql-test/suite/rpl/t/rpl_begin_commit_rollback-master.opt1
-rw-r--r--mysql-test/suite/rpl/t/rpl_begin_commit_rollback-slave.opt1
-rw-r--r--mysql-test/suite/rpl/t/rpl_begin_commit_rollback.test173
-rw-r--r--mysql-test/suite/rpl/t/rpl_binlog_compress.test61
-rw-r--r--mysql-test/suite/rpl/t/rpl_binlog_corruption.test50
-rw-r--r--mysql-test/suite/rpl/t/rpl_binlog_dump_slave_gtid_state_info.test121
-rw-r--r--mysql-test/suite/rpl/t/rpl_binlog_dup_entry.test72
-rw-r--r--mysql-test/suite/rpl/t/rpl_binlog_errors-master.opt1
-rw-r--r--mysql-test/suite/rpl/t/rpl_binlog_errors.test447
-rw-r--r--mysql-test/suite/rpl/t/rpl_binlog_grant.test42
-rw-r--r--mysql-test/suite/rpl/t/rpl_binlog_index.test217
-rw-r--r--mysql-test/suite/rpl/t/rpl_binlog_rollback_cleanup.test46
-rw-r--r--mysql-test/suite/rpl/t/rpl_bit.test92
-rw-r--r--mysql-test/suite/rpl/t/rpl_bit_npk.test113
-rw-r--r--mysql-test/suite/rpl/t/rpl_blackhole.test25
-rw-r--r--mysql-test/suite/rpl/t/rpl_blackhole_row_annotate-master.opt1
-rw-r--r--mysql-test/suite/rpl/t/rpl_blackhole_row_annotate-slave.opt1
-rw-r--r--mysql-test/suite/rpl/t/rpl_blackhole_row_annotate.test49
-rw-r--r--mysql-test/suite/rpl/t/rpl_bug26395.test93
-rw-r--r--mysql-test/suite/rpl/t/rpl_bug31076.test151
-rw-r--r--mysql-test/suite/rpl/t/rpl_bug33931.test49
-rw-r--r--mysql-test/suite/rpl/t/rpl_bug37426.test22
-rw-r--r--mysql-test/suite/rpl/t/rpl_bug38694-slave.opt1
-rw-r--r--mysql-test/suite/rpl/t/rpl_bug38694.test13
-rw-r--r--mysql-test/suite/rpl/t/rpl_bug41902.test67
-rw-r--r--mysql-test/suite/rpl/t/rpl_cant_read_event_incident.test88
-rw-r--r--mysql-test/suite/rpl/t/rpl_change_master.test117
-rw-r--r--mysql-test/suite/rpl/t/rpl_change_master_demote.test470
-rw-r--r--mysql-test/suite/rpl/t/rpl_change_master_find_log_pos_err.test93
-rw-r--r--mysql-test/suite/rpl/t/rpl_charset.test2
-rw-r--r--mysql-test/suite/rpl/t/rpl_charset_sjis.test54
-rw-r--r--mysql-test/suite/rpl/t/rpl_checksum-master.opt1
-rw-r--r--mysql-test/suite/rpl/t/rpl_checksum.test342
-rw-r--r--mysql-test/suite/rpl/t/rpl_checksum_cache.test261
-rw-r--r--mysql-test/suite/rpl/t/rpl_circular_for_4_hosts.cnf24
-rw-r--r--mysql-test/suite/rpl/t/rpl_circular_for_4_hosts.test339
-rw-r--r--mysql-test/suite/rpl/t/rpl_circular_semi_sync.cnf11
-rw-r--r--mysql-test/suite/rpl/t/rpl_circular_semi_sync.test188
-rw-r--r--mysql-test/suite/rpl/t/rpl_colSize.test228
-rw-r--r--mysql-test/suite/rpl/t/rpl_commit_after_flush.test5
-rw-r--r--mysql-test/suite/rpl/t/rpl_concurrency_error-master.opt1
-rw-r--r--mysql-test/suite/rpl/t/rpl_concurrency_error.test150
-rw-r--r--mysql-test/suite/rpl/t/rpl_conditional_comments.test84
-rw-r--r--mysql-test/suite/rpl/t/rpl_connection.test24
-rw-r--r--mysql-test/suite/rpl/t/rpl_corruption-master.opt1
-rw-r--r--mysql-test/suite/rpl/t/rpl_corruption-slave.opt1
-rw-r--r--mysql-test/suite/rpl/t/rpl_corruption.test181
-rw-r--r--mysql-test/suite/rpl/t/rpl_create_database-master.opt1
-rw-r--r--mysql-test/suite/rpl/t/rpl_create_database-slave.opt1
-rw-r--r--mysql-test/suite/rpl/t/rpl_create_database.test73
-rw-r--r--mysql-test/suite/rpl/t/rpl_create_drop_db.test33
-rw-r--r--mysql-test/suite/rpl/t/rpl_create_drop_event.test27
-rw-r--r--mysql-test/suite/rpl/t/rpl_create_drop_function.test54
-rw-r--r--mysql-test/suite/rpl/t/rpl_create_drop_index.test17
-rw-r--r--mysql-test/suite/rpl/t/rpl_create_drop_procedure.test81
-rw-r--r--mysql-test/suite/rpl/t/rpl_create_drop_role.test48
-rw-r--r--mysql-test/suite/rpl/t/rpl_create_drop_trigger.test48
-rw-r--r--mysql-test/suite/rpl/t/rpl_create_drop_udf.test56
-rw-r--r--mysql-test/suite/rpl/t/rpl_create_drop_user.test57
-rw-r--r--mysql-test/suite/rpl/t/rpl_create_drop_view.test56
-rw-r--r--mysql-test/suite/rpl/t/rpl_create_if_not_exists.test195
-rw-r--r--mysql-test/suite/rpl/t/rpl_create_or_replace_fail.test56
-rw-r--r--mysql-test/suite/rpl/t/rpl_create_tmp_table_if_not_exists.test45
-rw-r--r--mysql-test/suite/rpl/t/rpl_create_xa_prepared.inc9
-rw-r--r--mysql-test/suite/rpl/t/rpl_critical_errors.test66
-rw-r--r--mysql-test/suite/rpl/t/rpl_cross_version-master.opt1
-rw-r--r--mysql-test/suite/rpl/t/rpl_cross_version.test48
-rw-r--r--mysql-test/suite/rpl/t/rpl_ctype_latin1.test44
-rw-r--r--mysql-test/suite/rpl/t/rpl_current_user.cnf8
-rw-r--r--mysql-test/suite/rpl/t/rpl_current_user.test225
-rw-r--r--mysql-test/suite/rpl/t/rpl_ddl-slave.opt1
-rw-r--r--mysql-test/suite/rpl/t/rpl_ddl.test32
-rw-r--r--mysql-test/suite/rpl/t/rpl_deadlock_innodb-slave.opt1
-rw-r--r--mysql-test/suite/rpl/t/rpl_deadlock_innodb.test4
-rw-r--r--mysql-test/suite/rpl/t/rpl_default.test29
-rw-r--r--mysql-test/suite/rpl/t/rpl_delayed_slave.combinations4
-rw-r--r--mysql-test/suite/rpl/t/rpl_delayed_slave.test428
-rw-r--r--mysql-test/suite/rpl/t/rpl_delayed_slave2.test65
-rw-r--r--mysql-test/suite/rpl/t/rpl_delete_no_where.test4
-rw-r--r--mysql-test/suite/rpl/t/rpl_do_grant.test350
-rw-r--r--mysql-test/suite/rpl/t/rpl_domain_id_filter.test400
-rw-r--r--mysql-test/suite/rpl/t/rpl_domain_id_filter_io_crash.test384
-rw-r--r--mysql-test/suite/rpl/t/rpl_domain_id_filter_master_crash.test87
-rw-r--r--mysql-test/suite/rpl/t/rpl_domain_id_filter_parallel.test196
-rw-r--r--mysql-test/suite/rpl/t/rpl_domain_id_filter_restart.test73
-rw-r--r--mysql-test/suite/rpl/t/rpl_drop.test12
-rw-r--r--mysql-test/suite/rpl/t/rpl_drop_db.test66
-rw-r--r--mysql-test/suite/rpl/t/rpl_drop_db_fail.test34
-rw-r--r--mysql-test/suite/rpl/t/rpl_drop_temp-slave.opt2
-rw-r--r--mysql-test/suite/rpl/t/rpl_drop_temp.test94
-rw-r--r--mysql-test/suite/rpl/t/rpl_drop_temp_table_invalid_lex.test41
-rw-r--r--mysql-test/suite/rpl/t/rpl_drop_view.test35
-rw-r--r--mysql-test/suite/rpl/t/rpl_dual_pos_advance.test97
-rw-r--r--mysql-test/suite/rpl/t/rpl_dump_request_retry_warning.test66
-rw-r--r--mysql-test/suite/rpl/t/rpl_empty_master_host.test53
-rw-r--r--mysql-test/suite/rpl/t/rpl_empty_string_is_null.test15
-rw-r--r--mysql-test/suite/rpl/t/rpl_err_ignoredtable-slave.opt1
-rw-r--r--mysql-test/suite/rpl/t/rpl_err_ignoredtable.test70
-rw-r--r--mysql-test/suite/rpl/t/rpl_events.test249
-rw-r--r--mysql-test/suite/rpl/t/rpl_extra_col_master_innodb.test11
-rw-r--r--mysql-test/suite/rpl/t/rpl_extra_col_master_myisam.test10
-rw-r--r--mysql-test/suite/rpl/t/rpl_extra_col_slave_innodb.test7
-rw-r--r--mysql-test/suite/rpl/t/rpl_extra_col_slave_myisam.test6
-rw-r--r--mysql-test/suite/rpl/t/rpl_fail_register.test33
-rw-r--r--mysql-test/suite/rpl/t/rpl_failed_drop_tbl_binlog.opt1
-rw-r--r--mysql-test/suite/rpl/t/rpl_failed_optimize.test3
-rw-r--r--mysql-test/suite/rpl/t/rpl_filter_dbs_dynamic.test63
-rw-r--r--mysql-test/suite/rpl/t/rpl_filter_revoke_missing_user.test92
-rw-r--r--mysql-test/suite/rpl/t/rpl_filter_set_var_missing_data.test83
-rw-r--r--mysql-test/suite/rpl/t/rpl_filter_tables_dynamic.test217
-rw-r--r--mysql-test/suite/rpl/t/rpl_filter_tables_not_exist-slave.opt1
-rw-r--r--mysql-test/suite/rpl/t/rpl_filter_tables_not_exist.test267
-rw-r--r--mysql-test/suite/rpl/t/rpl_filter_wild_tables_dynamic.test49
-rw-r--r--mysql-test/suite/rpl/t/rpl_flush_logs-master.opt1
-rw-r--r--mysql-test/suite/rpl/t/rpl_flush_logs.test141
-rw-r--r--mysql-test/suite/rpl/t/rpl_flushlog_loop-master.opt1
-rw-r--r--mysql-test/suite/rpl/t/rpl_flushlog_loop-slave.opt1
-rw-r--r--mysql-test/suite/rpl/t/rpl_flushlog_loop.test46
-rw-r--r--mysql-test/suite/rpl/t/rpl_foreign_key_innodb.test78
-rw-r--r--mysql-test/suite/rpl/t/rpl_free_items-slave.opt1
-rw-r--r--mysql-test/suite/rpl/t/rpl_free_items.test23
-rw-r--r--mysql-test/suite/rpl/t/rpl_function_defaults.test86
-rw-r--r--mysql-test/suite/rpl/t/rpl_geometry.test26
-rw-r--r--mysql-test/suite/rpl/t/rpl_get_lock.test47
-rw-r--r--mysql-test/suite/rpl/t/rpl_get_master_version_and_clock-slave.opt1
-rw-r--r--mysql-test/suite/rpl/t/rpl_get_master_version_and_clock.test52
-rw-r--r--mysql-test/suite/rpl/t/rpl_grant.test37
-rw-r--r--mysql-test/suite/rpl/t/rpl_gtid_basic.cnf24
-rw-r--r--mysql-test/suite/rpl/t/rpl_gtid_basic.test652
-rw-r--r--mysql-test/suite/rpl/t/rpl_gtid_crash-master.opt1
-rw-r--r--mysql-test/suite/rpl/t/rpl_gtid_crash-slave.opt1
-rw-r--r--mysql-test/suite/rpl/t/rpl_gtid_crash.test668
-rw-r--r--mysql-test/suite/rpl/t/rpl_gtid_crash_myisam-master.opt1
-rw-r--r--mysql-test/suite/rpl/t/rpl_gtid_crash_myisam.test64
-rw-r--r--mysql-test/suite/rpl/t/rpl_gtid_delete_domain.test101
-rw-r--r--mysql-test/suite/rpl/t/rpl_gtid_errorhandling.test291
-rw-r--r--mysql-test/suite/rpl/t/rpl_gtid_errorlog.test85
-rw-r--r--mysql-test/suite/rpl/t/rpl_gtid_excess_initial_delay.test58
-rw-r--r--mysql-test/suite/rpl/t/rpl_gtid_glle_no_terminate.test72
-rw-r--r--mysql-test/suite/rpl/t/rpl_gtid_grouping.test97
-rw-r--r--mysql-test/suite/rpl/t/rpl_gtid_ignored.test141
-rw-r--r--mysql-test/suite/rpl/t/rpl_gtid_master_promote.cnf35
-rw-r--r--mysql-test/suite/rpl/t/rpl_gtid_master_promote.test266
-rw-r--r--mysql-test/suite/rpl/t/rpl_gtid_mdev4473.cnf18
-rw-r--r--mysql-test/suite/rpl/t/rpl_gtid_mdev4473.test72
-rw-r--r--mysql-test/suite/rpl/t/rpl_gtid_mdev4474.cnf11
-rw-r--r--mysql-test/suite/rpl/t/rpl_gtid_mdev4474.test72
-rw-r--r--mysql-test/suite/rpl/t/rpl_gtid_mdev4484.test106
-rw-r--r--mysql-test/suite/rpl/t/rpl_gtid_mdev4485.cnf18
-rw-r--r--mysql-test/suite/rpl/t/rpl_gtid_mdev4485.test41
-rw-r--r--mysql-test/suite/rpl/t/rpl_gtid_mdev4820.test118
-rw-r--r--mysql-test/suite/rpl/t/rpl_gtid_mdev9033.cnf20
-rw-r--r--mysql-test/suite/rpl/t/rpl_gtid_mdev9033.test72
-rw-r--r--mysql-test/suite/rpl/t/rpl_gtid_misc.test49
-rw-r--r--mysql-test/suite/rpl/t/rpl_gtid_nobinlog.cnf9
-rw-r--r--mysql-test/suite/rpl/t/rpl_gtid_nobinlog.test65
-rw-r--r--mysql-test/suite/rpl/t/rpl_gtid_reconnect.test201
-rw-r--r--mysql-test/suite/rpl/t/rpl_gtid_sort.test77
-rw-r--r--mysql-test/suite/rpl/t/rpl_gtid_startpos.test360
-rw-r--r--mysql-test/suite/rpl/t/rpl_gtid_stop_start.cnf5
-rw-r--r--mysql-test/suite/rpl/t/rpl_gtid_stop_start.test355
-rw-r--r--mysql-test/suite/rpl/t/rpl_gtid_strict.test179
-rw-r--r--mysql-test/suite/rpl/t/rpl_gtid_until.test253
-rw-r--r--mysql-test/suite/rpl/t/rpl_heartbeat.test175
-rw-r--r--mysql-test/suite/rpl/t/rpl_heartbeat_2slaves.cnf12
-rw-r--r--mysql-test/suite/rpl/t/rpl_heartbeat_2slaves.test124
-rw-r--r--mysql-test/suite/rpl/t/rpl_heartbeat_basic.cnf7
-rw-r--r--mysql-test/suite/rpl/t/rpl_heartbeat_basic.test575
-rw-r--r--mysql-test/suite/rpl/t/rpl_heartbeat_debug.test52
-rw-r--r--mysql-test/suite/rpl/t/rpl_heartbeat_ssl.test57
-rw-r--r--mysql-test/suite/rpl/t/rpl_hrtime.test7
-rw-r--r--mysql-test/suite/rpl/t/rpl_hrtime_row.test3
-rw-r--r--mysql-test/suite/rpl/t/rpl_idempotency.test107
-rw-r--r--mysql-test/suite/rpl/t/rpl_ignore_grant-slave.opt1
-rw-r--r--mysql-test/suite/rpl/t/rpl_ignore_grant.test55
-rw-r--r--mysql-test/suite/rpl/t/rpl_ignore_revoke-slave.opt1
-rw-r--r--mysql-test/suite/rpl/t/rpl_ignore_revoke.test52
-rw-r--r--mysql-test/suite/rpl/t/rpl_ignore_table-slave.opt1
-rw-r--r--mysql-test/suite/rpl/t/rpl_ignore_table.test198
-rw-r--r--mysql-test/suite/rpl/t/rpl_ignore_table_update-slave.opt1
-rw-r--r--mysql-test/suite/rpl/t/rpl_ignore_table_update.test35
-rw-r--r--mysql-test/suite/rpl/t/rpl_incident.test61
-rw-r--r--mysql-test/suite/rpl/t/rpl_incompatible_heartbeat.test44
-rw-r--r--mysql-test/suite/rpl/t/rpl_init_slave-slave.opt1
-rw-r--r--mysql-test/suite/rpl/t/rpl_init_slave.test34
-rw-r--r--mysql-test/suite/rpl/t/rpl_init_slave_errors.test96
-rw-r--r--mysql-test/suite/rpl/t/rpl_innodb-master.opt1
-rw-r--r--mysql-test/suite/rpl/t/rpl_innodb_bug28430-master.opt1
-rw-r--r--mysql-test/suite/rpl/t/rpl_innodb_bug28430-slave.opt1
-rw-r--r--mysql-test/suite/rpl/t/rpl_innodb_bug28430.test163
-rw-r--r--mysql-test/suite/rpl/t/rpl_innodb_bug30888.opt1
-rw-r--r--mysql-test/suite/rpl/t/rpl_innodb_bug30888.test67
-rw-r--r--mysql-test/suite/rpl/t/rpl_innodb_mixed_ddl.test9
-rw-r--r--mysql-test/suite/rpl/t/rpl_innodb_mixed_dml.test9
-rw-r--r--mysql-test/suite/rpl/t/rpl_insert.test45
-rw-r--r--mysql-test/suite/rpl/t/rpl_insert_delayed.test5
-rw-r--r--mysql-test/suite/rpl/t/rpl_insert_id.test6
-rw-r--r--mysql-test/suite/rpl/t/rpl_insert_id_pk.test6
-rw-r--r--mysql-test/suite/rpl/t/rpl_insert_ignore.test15
-rw-r--r--mysql-test/suite/rpl/t/rpl_invoked_features-master.opt1
-rw-r--r--mysql-test/suite/rpl/t/rpl_invoked_features.test311
-rw-r--r--mysql-test/suite/rpl/t/rpl_iodku.test50
-rw-r--r--mysql-test/suite/rpl/t/rpl_ip_mix.cnf56
-rw-r--r--mysql-test/suite/rpl/t/rpl_ip_mix.test48
-rw-r--r--mysql-test/suite/rpl/t/rpl_ip_mix2.cnf56
-rw-r--r--mysql-test/suite/rpl/t/rpl_ip_mix2.test49
-rw-r--r--mysql-test/suite/rpl/t/rpl_ipv4_as_ipv6.cnf56
-rw-r--r--mysql-test/suite/rpl/t/rpl_ipv4_as_ipv6.test63
-rw-r--r--mysql-test/suite/rpl/t/rpl_ipv6.cnf56
-rw-r--r--mysql-test/suite/rpl/t/rpl_ipv6.test49
-rw-r--r--mysql-test/suite/rpl/t/rpl_killed_ddl-master.opt1
-rw-r--r--mysql-test/suite/rpl/t/rpl_killed_ddl.test349
-rw-r--r--mysql-test/suite/rpl/t/rpl_known_bugs_detection-master.opt1
-rw-r--r--mysql-test/suite/rpl/t/rpl_known_bugs_detection.test76
-rw-r--r--mysql-test/suite/rpl/t/rpl_lcase_tblnames_rewrite_db-slave.opt1
-rw-r--r--mysql-test/suite/rpl/t/rpl_lcase_tblnames_rewrite_db.test60
-rw-r--r--mysql-test/suite/rpl/t/rpl_loaddata.test4
-rw-r--r--mysql-test/suite/rpl/t/rpl_loaddata_charset.test49
-rw-r--r--mysql-test/suite/rpl/t/rpl_loaddata_fatal-slave.opt1
-rw-r--r--mysql-test/suite/rpl/t/rpl_loaddata_fatal.test27
-rw-r--r--mysql-test/suite/rpl/t/rpl_loaddata_local.test244
-rw-r--r--mysql-test/suite/rpl/t/rpl_loaddata_m-master.opt1
-rw-r--r--mysql-test/suite/rpl/t/rpl_loaddata_m.test51
-rw-r--r--mysql-test/suite/rpl/t/rpl_loaddata_map-master.opt1
-rw-r--r--mysql-test/suite/rpl/t/rpl_loaddata_map-slave.opt1
-rw-r--r--mysql-test/suite/rpl/t/rpl_loaddata_map.test74
-rw-r--r--mysql-test/suite/rpl/t/rpl_loaddata_s-slave.opt1
-rw-r--r--mysql-test/suite/rpl/t/rpl_loaddata_s.test27
-rw-r--r--mysql-test/suite/rpl/t/rpl_loaddata_simple.test15
-rw-r--r--mysql-test/suite/rpl/t/rpl_loaddata_symlink-master.opt1
-rw-r--r--mysql-test/suite/rpl/t/rpl_loaddata_symlink-master.sh2
-rw-r--r--mysql-test/suite/rpl/t/rpl_loaddata_symlink-slave.opt1
-rw-r--r--mysql-test/suite/rpl/t/rpl_loaddata_symlink-slave.sh2
-rw-r--r--mysql-test/suite/rpl/t/rpl_loaddata_symlink.test22
-rw-r--r--mysql-test/suite/rpl/t/rpl_loadfile.test122
-rw-r--r--mysql-test/suite/rpl/t/rpl_locale.test25
-rw-r--r--mysql-test/suite/rpl/t/rpl_log_pos.test57
-rw-r--r--mysql-test/suite/rpl/t/rpl_lost_events_on_rotate.test52
-rw-r--r--mysql-test/suite/rpl/t/rpl_manual_change_index_file.test114
-rw-r--r--mysql-test/suite/rpl/t/rpl_many_optimize.test23
-rw-r--r--mysql-test/suite/rpl/t/rpl_mariadb_slave_capability.test167
-rw-r--r--mysql-test/suite/rpl/t/rpl_mark_optimize_tbl_ddl.test142
-rw-r--r--mysql-test/suite/rpl/t/rpl_master_pos_wait.test79
-rw-r--r--mysql-test/suite/rpl/t/rpl_mdev-11092.opt1
-rw-r--r--mysql-test/suite/rpl/t/rpl_mdev-11092.test543
-rw-r--r--mysql-test/suite/rpl/t/rpl_mdev10863.test105
-rw-r--r--mysql-test/suite/rpl/t/rpl_mdev12179.test319
-rw-r--r--mysql-test/suite/rpl/t/rpl_mdev359.test31
-rw-r--r--mysql-test/suite/rpl/t/rpl_mdev382.test264
-rw-r--r--mysql-test/suite/rpl/t/rpl_mdev6020.test69
-rw-r--r--mysql-test/suite/rpl/t/rpl_mdev6386-slave.opt1
-rw-r--r--mysql-test/suite/rpl/t/rpl_mdev6386.test70
-rw-r--r--mysql-test/suite/rpl/t/rpl_mdev8193.test56
-rw-r--r--mysql-test/suite/rpl/t/rpl_mdev_17614.test172
-rw-r--r--mysql-test/suite/rpl/t/rpl_misc_functions-slave.sh1
-rw-r--r--mysql-test/suite/rpl/t/rpl_misc_functions.test133
-rw-r--r--mysql-test/suite/rpl/t/rpl_mix_found_rows.test152
-rw-r--r--mysql-test/suite/rpl/t/rpl_mixed_binlog_max_cache_size.test8
-rw-r--r--mysql-test/suite/rpl/t/rpl_mixed_bit_pk.test83
-rw-r--r--mysql-test/suite/rpl/t/rpl_mixed_ddl_dml.test51
-rw-r--r--mysql-test/suite/rpl/t/rpl_mixed_drop_create_temp_table.test12
-rw-r--r--mysql-test/suite/rpl/t/rpl_mixed_implicit_commit_binlog.test12
-rw-r--r--mysql-test/suite/rpl/t/rpl_mixed_mixing_engines.test14
-rw-r--r--mysql-test/suite/rpl/t/rpl_mixed_row_innodb-master.opt1
-rw-r--r--mysql-test/suite/rpl/t/rpl_multi_delete-slave.opt1
-rw-r--r--mysql-test/suite/rpl/t/rpl_multi_delete.test25
-rw-r--r--mysql-test/suite/rpl/t/rpl_multi_delete2-slave.opt1
-rw-r--r--mysql-test/suite/rpl/t/rpl_multi_delete2.test67
-rw-r--r--mysql-test/suite/rpl/t/rpl_multi_engine.test102
-rw-r--r--mysql-test/suite/rpl/t/rpl_multi_update.test2
-rw-r--r--mysql-test/suite/rpl/t/rpl_multi_update2-slave.opt1
-rw-r--r--mysql-test/suite/rpl/t/rpl_multi_update2.test9
-rw-r--r--mysql-test/suite/rpl/t/rpl_multi_update3.test9
-rw-r--r--mysql-test/suite/rpl/t/rpl_multi_update4-slave.opt1
-rw-r--r--mysql-test/suite/rpl/t/rpl_multi_update4.test46
-rw-r--r--mysql-test/suite/rpl/t/rpl_mysql57_stm_temporal_round.test58
-rw-r--r--mysql-test/suite/rpl/t/rpl_mysql80_stm_temporal_round.test62
-rw-r--r--mysql-test/suite/rpl/t/rpl_mysql_manager_race_condition-slave.opt1
-rw-r--r--mysql-test/suite/rpl/t/rpl_mysql_manager_race_condition.test67
-rw-r--r--mysql-test/suite/rpl/t/rpl_mysql_upgrade.test80
-rw-r--r--mysql-test/suite/rpl/t/rpl_mysqlbinlog_slave_consistency.test401
-rw-r--r--mysql-test/suite/rpl/t/rpl_name_const.test45
-rw-r--r--mysql-test/suite/rpl/t/rpl_non_direct_mixed_mixing_engines.test17
-rw-r--r--mysql-test/suite/rpl/t/rpl_non_direct_row_mixing_engines.test19
-rw-r--r--mysql-test/suite/rpl/t/rpl_non_direct_stm_mixing_engines.test17
-rw-r--r--mysql-test/suite/rpl/t/rpl_nondeterministic_functions.test58
-rw-r--r--mysql-test/suite/rpl/t/rpl_not_null_innodb.test20
-rw-r--r--mysql-test/suite/rpl/t/rpl_not_null_myisam.test19
-rw-r--r--mysql-test/suite/rpl/t/rpl_old_decimal.test25
-rw-r--r--mysql-test/suite/rpl/t/rpl_old_master.test57
-rw-r--r--mysql-test/suite/rpl/t/rpl_old_master_29078-master.opt1
-rw-r--r--mysql-test/suite/rpl/t/rpl_old_master_29078.test53
-rw-r--r--mysql-test/suite/rpl/t/rpl_optimize.test65
-rw-r--r--mysql-test/suite/rpl/t/rpl_packet-master.opt1
-rw-r--r--mysql-test/suite/rpl/t/rpl_packet-slave.opt1
-rw-r--r--mysql-test/suite/rpl/t/rpl_packet.test184
-rw-r--r--mysql-test/suite/rpl/t/rpl_parallel2.test230
-rw-r--r--mysql-test/suite/rpl/t/rpl_parallel_29322.test64
-rw-r--r--mysql-test/suite/rpl/t/rpl_parallel_analyze.test84
-rw-r--r--mysql-test/suite/rpl/t/rpl_parallel_analyze_table_hang.test73
-rw-r--r--mysql-test/suite/rpl/t/rpl_parallel_autoinc.test140
-rw-r--r--mysql-test/suite/rpl/t/rpl_parallel_charset.test56
-rw-r--r--mysql-test/suite/rpl/t/rpl_parallel_conflicts.test269
-rw-r--r--mysql-test/suite/rpl/t/rpl_parallel_deadlock_corrupt_binlog.test80
-rw-r--r--mysql-test/suite/rpl/t/rpl_parallel_deadlock_victim.test86
-rw-r--r--mysql-test/suite/rpl/t/rpl_parallel_deadlock_victim2.test83
-rw-r--r--mysql-test/suite/rpl/t/rpl_parallel_domain.test87
-rw-r--r--mysql-test/suite/rpl/t/rpl_parallel_domain_slave_single_grp.test128
-rw-r--r--mysql-test/suite/rpl/t/rpl_parallel_free_deferred_event.test67
-rw-r--r--mysql-test/suite/rpl/t/rpl_parallel_ftwrl.test143
-rw-r--r--mysql-test/suite/rpl/t/rpl_parallel_gco_wait_kill.test369
-rw-r--r--mysql-test/suite/rpl/t/rpl_parallel_gtid_slave_pos_update_fail.test98
-rw-r--r--mysql-test/suite/rpl/t/rpl_parallel_ignore_error_on_rotate.test96
-rw-r--r--mysql-test/suite/rpl/t/rpl_parallel_ignored_errors.test115
-rw-r--r--mysql-test/suite/rpl/t/rpl_parallel_incorrect_relay_pos.test1
-rw-r--r--mysql-test/suite/rpl/t/rpl_parallel_innodb_lock_conflict.test107
-rw-r--r--mysql-test/suite/rpl/t/rpl_parallel_kill.test15
-rw-r--r--mysql-test/suite/rpl/t/rpl_parallel_mdev6589.test132
-rw-r--r--mysql-test/suite/rpl/t/rpl_parallel_missed_error_handling.test87
-rw-r--r--mysql-test/suite/rpl/t/rpl_parallel_mode.test87
-rw-r--r--mysql-test/suite/rpl/t/rpl_parallel_multilevel.cnf24
-rw-r--r--mysql-test/suite/rpl/t/rpl_parallel_multilevel.test284
-rw-r--r--mysql-test/suite/rpl/t/rpl_parallel_multilevel2.cnf17
-rw-r--r--mysql-test/suite/rpl/t/rpl_parallel_multilevel2.test78
-rw-r--r--mysql-test/suite/rpl/t/rpl_parallel_no_log_slave_updates-slave.opt1
-rw-r--r--mysql-test/suite/rpl/t/rpl_parallel_no_log_slave_updates.test205
-rw-r--r--mysql-test/suite/rpl/t/rpl_parallel_optimistic.test583
-rw-r--r--mysql-test/suite/rpl/t/rpl_parallel_optimistic_error_stop.test180
-rw-r--r--mysql-test/suite/rpl/t/rpl_parallel_optimistic_nobinlog.cnf10
-rw-r--r--mysql-test/suite/rpl/t/rpl_parallel_optimistic_nobinlog.test77
-rw-r--r--mysql-test/suite/rpl/t/rpl_parallel_optimistic_until.test486
-rw-r--r--mysql-test/suite/rpl/t/rpl_parallel_optimistic_xa.test235
-rw-r--r--mysql-test/suite/rpl/t/rpl_parallel_optimistic_xa_lsu_off-slave.opt1
-rw-r--r--mysql-test/suite/rpl/t/rpl_parallel_optimistic_xa_lsu_off.test2
-rw-r--r--mysql-test/suite/rpl/t/rpl_parallel_partial_binlog_trans.test71
-rw-r--r--mysql-test/suite/rpl/t/rpl_parallel_partition.test81
-rw-r--r--mysql-test/suite/rpl/t/rpl_parallel_record_gtid_wakeup.test72
-rw-r--r--mysql-test/suite/rpl/t/rpl_parallel_retry.test514
-rw-r--r--mysql-test/suite/rpl/t/rpl_parallel_retry_deadlock.test281
-rw-r--r--mysql-test/suite/rpl/t/rpl_parallel_rollback_assert.test62
-rw-r--r--mysql-test/suite/rpl/t/rpl_parallel_sbm-slave.opt1
-rw-r--r--mysql-test/suite/rpl/t/rpl_parallel_sbm.test218
-rw-r--r--mysql-test/suite/rpl/t/rpl_parallel_seq.test198
-rw-r--r--mysql-test/suite/rpl/t/rpl_parallel_show_binlog_events_purge_logs.test38
-rw-r--r--mysql-test/suite/rpl/t/rpl_parallel_single_grpcmt.test170
-rw-r--r--mysql-test/suite/rpl/t/rpl_parallel_slave_bgc_kill.test458
-rw-r--r--mysql-test/suite/rpl/t/rpl_parallel_stop_on_con_kill.test129
-rw-r--r--mysql-test/suite/rpl/t/rpl_parallel_stop_slave.test118
-rw-r--r--mysql-test/suite/rpl/t/rpl_parallel_temptable-master.opt1
-rw-r--r--mysql-test/suite/rpl/t/rpl_parallel_temptable.test277
-rw-r--r--mysql-test/suite/rpl/t/rpl_parallel_wrong_binlog_order.test91
-rw-r--r--mysql-test/suite/rpl/t/rpl_parallel_wrong_exec_master_pos.test56
-rw-r--r--mysql-test/suite/rpl/t/rpl_parallel_xa_same_xid.test138
-rw-r--r--mysql-test/suite/rpl/t/rpl_partition_archive.test12
-rw-r--r--mysql-test/suite/rpl/t/rpl_partition_innodb-master.opt1
-rw-r--r--mysql-test/suite/rpl/t/rpl_partition_innodb.test12
-rw-r--r--mysql-test/suite/rpl/t/rpl_partition_memory.test11
-rw-r--r--mysql-test/suite/rpl/t/rpl_partition_myisam.test11
-rw-r--r--mysql-test/suite/rpl/t/rpl_password_boundaries.test104
-rw-r--r--mysql-test/suite/rpl/t/rpl_performance_schema.test10
-rw-r--r--mysql-test/suite/rpl/t/rpl_perfschema_applier_config.test97
-rw-r--r--mysql-test/suite/rpl/t/rpl_perfschema_applier_status.test73
-rw-r--r--mysql-test/suite/rpl/t/rpl_perfschema_applier_status_by_coordinator-slave.opt1
-rw-r--r--mysql-test/suite/rpl/t/rpl_perfschema_applier_status_by_coordinator.test318
-rw-r--r--mysql-test/suite/rpl/t/rpl_perfschema_applier_status_by_worker.test257
-rw-r--r--mysql-test/suite/rpl/t/rpl_perfschema_connect_config.test331
-rw-r--r--mysql-test/suite/rpl/t/rpl_plugin_load.test59
-rw-r--r--mysql-test/suite/rpl/t/rpl_ps.test94
-rw-r--r--mysql-test/suite/rpl/t/rpl_query_cache.test27
-rw-r--r--mysql-test/suite/rpl/t/rpl_rbr_monitor.test76
-rw-r--r--mysql-test/suite/rpl/t/rpl_rbr_to_sbr.test31
-rw-r--r--mysql-test/suite/rpl/t/rpl_read_new_relay_log_info.test48
-rw-r--r--mysql-test/suite/rpl/t/rpl_read_old_relay_log_info.test48
-rw-r--r--mysql-test/suite/rpl/t/rpl_read_only.test157
-rw-r--r--mysql-test/suite/rpl/t/rpl_read_only2.test30
-rw-r--r--mysql-test/suite/rpl/t/rpl_relay_max_extension.test111
-rw-r--r--mysql-test/suite/rpl/t/rpl_relay_space_innodb.test3
-rw-r--r--mysql-test/suite/rpl/t/rpl_relay_space_myisam.test2
-rw-r--r--mysql-test/suite/rpl/t/rpl_relayrotate-slave.opt2
-rw-r--r--mysql-test/suite/rpl/t/rpl_relayrotate.test18
-rw-r--r--mysql-test/suite/rpl/t/rpl_relayspace-slave.opt1
-rw-r--r--mysql-test/suite/rpl/t/rpl_relayspace.test52
-rw-r--r--mysql-test/suite/rpl/t/rpl_reopen_temp_table.test43
-rw-r--r--mysql-test/suite/rpl/t/rpl_replicate_do-slave.opt1
-rw-r--r--mysql-test/suite/rpl/t/rpl_replicate_do.test65
-rw-r--r--mysql-test/suite/rpl/t/rpl_replicate_ignore_db-slave.opt1
-rw-r--r--mysql-test/suite/rpl/t/rpl_replicate_ignore_db.test31
-rw-r--r--mysql-test/suite/rpl/t/rpl_report-slave.opt2
-rw-r--r--mysql-test/suite/rpl/t/rpl_report.test22
-rw-r--r--mysql-test/suite/rpl/t/rpl_report_port.test74
-rw-r--r--mysql-test/suite/rpl/t/rpl_reset_slave_all_clears_filters.test72
-rw-r--r--mysql-test/suite/rpl/t/rpl_reset_slave_fail.test91
-rw-r--r--mysql-test/suite/rpl/t/rpl_rewrite_db_sys_vars-slave.opt2
-rw-r--r--mysql-test/suite/rpl/t/rpl_rewrite_db_sys_vars.test163
-rw-r--r--mysql-test/suite/rpl/t/rpl_rewrt_db-slave.opt6
-rw-r--r--mysql-test/suite/rpl/t/rpl_rewrt_db.test250
-rw-r--r--mysql-test/suite/rpl/t/rpl_rotate_logs.cnf6
-rw-r--r--mysql-test/suite/rpl/t/rpl_rotate_logs.test203
-rw-r--r--mysql-test/suite/rpl/t/rpl_rotate_purge_deadlock-master.opt1
-rw-r--r--mysql-test/suite/rpl/t/rpl_rotate_purge_deadlock.test96
-rw-r--r--mysql-test/suite/rpl/t/rpl_row_001.test51
-rw-r--r--mysql-test/suite/rpl/t/rpl_row_4_bytes-master.opt2
-rw-r--r--mysql-test/suite/rpl/t/rpl_row_4_bytes.test34
-rw-r--r--mysql-test/suite/rpl/t/rpl_row_NOW.test75
-rw-r--r--mysql-test/suite/rpl/t/rpl_row_USER.test59
-rw-r--r--mysql-test/suite/rpl/t/rpl_row_UUID.test8
-rw-r--r--mysql-test/suite/rpl/t/rpl_row_annotate_do-slave.opt1
-rw-r--r--mysql-test/suite/rpl/t/rpl_row_annotate_do.test16
-rw-r--r--mysql-test/suite/rpl/t/rpl_row_annotate_dont-slave.opt1
-rw-r--r--mysql-test/suite/rpl/t/rpl_row_annotate_dont.test9
-rw-r--r--mysql-test/suite/rpl/t/rpl_row_basic_11bugs-master.opt2
-rw-r--r--mysql-test/suite/rpl/t/rpl_row_basic_11bugs.test242
-rw-r--r--mysql-test/suite/rpl/t/rpl_row_basic_2myisam.test11
-rw-r--r--mysql-test/suite/rpl/t/rpl_row_basic_3innodb.test11
-rw-r--r--mysql-test/suite/rpl/t/rpl_row_basic_8partition.test190
-rw-r--r--mysql-test/suite/rpl/t/rpl_row_big_table_id.opt1
-rw-r--r--mysql-test/suite/rpl/t/rpl_row_big_table_id.test58
-rw-r--r--mysql-test/suite/rpl/t/rpl_row_binlog_max_cache_size.test8
-rw-r--r--mysql-test/suite/rpl/t/rpl_row_blob_innodb.test13
-rw-r--r--mysql-test/suite/rpl/t/rpl_row_blob_myisam.test12
-rw-r--r--mysql-test/suite/rpl/t/rpl_row_colSize.test173
-rw-r--r--mysql-test/suite/rpl/t/rpl_row_conflicts.test33
-rw-r--r--mysql-test/suite/rpl/t/rpl_row_corruption-slave.opt1
-rw-r--r--mysql-test/suite/rpl/t/rpl_row_corruption.test115
-rw-r--r--mysql-test/suite/rpl/t/rpl_row_create_select.test30
-rw-r--r--mysql-test/suite/rpl/t/rpl_row_create_table.test285
-rw-r--r--mysql-test/suite/rpl/t/rpl_row_delayed_ins.test2
-rw-r--r--mysql-test/suite/rpl/t/rpl_row_drop.test38
-rw-r--r--mysql-test/suite/rpl/t/rpl_row_drop_create_temp_table.test11
-rw-r--r--mysql-test/suite/rpl/t/rpl_row_drop_temp_table.test54
-rw-r--r--mysql-test/suite/rpl/t/rpl_row_end_of_statement_loss-master.opt2
-rw-r--r--mysql-test/suite/rpl/t/rpl_row_end_of_statement_loss.test66
-rw-r--r--mysql-test/suite/rpl/t/rpl_row_err_daisychain-master.opt1
-rw-r--r--mysql-test/suite/rpl/t/rpl_row_err_daisychain-slave.opt1
-rw-r--r--mysql-test/suite/rpl/t/rpl_row_find_row.test103
-rw-r--r--mysql-test/suite/rpl/t/rpl_row_find_row_debug.test57
-rw-r--r--mysql-test/suite/rpl/t/rpl_row_flsh_tbls.test7
-rw-r--r--mysql-test/suite/rpl/t/rpl_row_func001.test60
-rw-r--r--mysql-test/suite/rpl/t/rpl_row_func002.test105
-rw-r--r--mysql-test/suite/rpl/t/rpl_row_func003.test12
-rw-r--r--mysql-test/suite/rpl/t/rpl_row_idempotency.test333
-rw-r--r--mysql-test/suite/rpl/t/rpl_row_img.cnf21
-rw-r--r--mysql-test/suite/rpl/t/rpl_row_img_blobs.cnf1
-rw-r--r--mysql-test/suite/rpl/t/rpl_row_img_blobs.test59
-rw-r--r--mysql-test/suite/rpl/t/rpl_row_img_eng_min.cnf1
-rw-r--r--mysql-test/suite/rpl/t/rpl_row_img_eng_min.test39
-rw-r--r--mysql-test/suite/rpl/t/rpl_row_img_eng_noblob.cnf1
-rw-r--r--mysql-test/suite/rpl/t/rpl_row_img_eng_noblob.test39
-rw-r--r--mysql-test/suite/rpl/t/rpl_row_img_sequence_full.cnf21
-rw-r--r--mysql-test/suite/rpl/t/rpl_row_img_sequence_full.test48
-rw-r--r--mysql-test/suite/rpl/t/rpl_row_img_sequence_min.cnf21
-rw-r--r--mysql-test/suite/rpl/t/rpl_row_img_sequence_min.test52
-rw-r--r--mysql-test/suite/rpl/t/rpl_row_img_sequence_noblob.cnf21
-rw-r--r--mysql-test/suite/rpl/t/rpl_row_img_sequence_noblob.test51
-rw-r--r--mysql-test/suite/rpl/t/rpl_row_implicit_commit_binlog.test12
-rw-r--r--mysql-test/suite/rpl/t/rpl_row_index_choice.test243
-rw-r--r--mysql-test/suite/rpl/t/rpl_row_inexist_tbl.test40
-rw-r--r--mysql-test/suite/rpl/t/rpl_row_lcase_tblnames-slave.opt1
-rw-r--r--mysql-test/suite/rpl/t/rpl_row_lcase_tblnames.test12
-rw-r--r--mysql-test/suite/rpl/t/rpl_row_loaddata_concurrent.test13
-rw-r--r--mysql-test/suite/rpl/t/rpl_row_log-master.opt1
-rw-r--r--mysql-test/suite/rpl/t/rpl_row_log-slave.opt1
-rw-r--r--mysql-test/suite/rpl/t/rpl_row_log.test15
-rw-r--r--mysql-test/suite/rpl/t/rpl_row_log_innodb-master.opt2
-rw-r--r--mysql-test/suite/rpl/t/rpl_row_log_innodb.test13
-rw-r--r--mysql-test/suite/rpl/t/rpl_row_max_relay_size.test9
-rw-r--r--mysql-test/suite/rpl/t/rpl_row_merge_engine.test52
-rw-r--r--mysql-test/suite/rpl/t/rpl_row_mixing_engines.test14
-rw-r--r--mysql-test/suite/rpl/t/rpl_row_mysqlbinlog-master.opt1
-rw-r--r--mysql-test/suite/rpl/t/rpl_row_mysqlbinlog.test285
-rw-r--r--mysql-test/suite/rpl/t/rpl_row_rec_comp_innodb.test11
-rw-r--r--mysql-test/suite/rpl/t/rpl_row_rec_comp_myisam.test32
-rw-r--r--mysql-test/suite/rpl/t/rpl_row_reset_slave.test5
-rw-r--r--mysql-test/suite/rpl/t/rpl_row_rollback_to_savepoint.test312
-rw-r--r--mysql-test/suite/rpl/t/rpl_row_show_relaylog_events.test19
-rw-r--r--mysql-test/suite/rpl/t/rpl_row_sp001.test145
-rw-r--r--mysql-test/suite/rpl/t/rpl_row_sp002_innodb.test3
-rw-r--r--mysql-test/suite/rpl/t/rpl_row_sp003.test16
-rw-r--r--mysql-test/suite/rpl/t/rpl_row_sp005.test102
-rw-r--r--mysql-test/suite/rpl/t/rpl_row_sp006_InnoDB.test12
-rw-r--r--mysql-test/suite/rpl/t/rpl_row_sp007_innodb.test3
-rw-r--r--mysql-test/suite/rpl/t/rpl_row_sp008.test52
-rw-r--r--mysql-test/suite/rpl/t/rpl_row_sp009.test98
-rw-r--r--mysql-test/suite/rpl/t/rpl_row_sp010.test77
-rw-r--r--mysql-test/suite/rpl/t/rpl_row_sp011.test112
-rw-r--r--mysql-test/suite/rpl/t/rpl_row_sp012.test74
-rw-r--r--mysql-test/suite/rpl/t/rpl_row_spatial.test17
-rw-r--r--mysql-test/suite/rpl/t/rpl_row_tabledefs_2myisam.test9
-rw-r--r--mysql-test/suite/rpl/t/rpl_row_tabledefs_3innodb.test10
-rw-r--r--mysql-test/suite/rpl/t/rpl_row_tbl_metadata.test338
-rw-r--r--mysql-test/suite/rpl/t/rpl_row_to_stmt-master.opt1
-rw-r--r--mysql-test/suite/rpl/t/rpl_row_to_stmt-slave.opt1
-rw-r--r--mysql-test/suite/rpl/t/rpl_row_to_stmt.test23
-rw-r--r--mysql-test/suite/rpl/t/rpl_row_trig001.test116
-rw-r--r--mysql-test/suite/rpl/t/rpl_row_trig002.test77
-rw-r--r--mysql-test/suite/rpl/t/rpl_row_trig003.test155
-rw-r--r--mysql-test/suite/rpl/t/rpl_row_trig004.test15
-rw-r--r--mysql-test/suite/rpl/t/rpl_row_trigger_multi_db.test98
-rw-r--r--mysql-test/suite/rpl/t/rpl_row_triggers.test442
-rw-r--r--mysql-test/suite/rpl/t/rpl_row_trunc_temp.test35
-rw-r--r--mysql-test/suite/rpl/t/rpl_row_type_conv_err_msg.test356
-rw-r--r--mysql-test/suite/rpl/t/rpl_row_unsafe_funcs.test36
-rw-r--r--mysql-test/suite/rpl/t/rpl_row_until.test150
-rw-r--r--mysql-test/suite/rpl/t/rpl_row_utf16.test26
-rw-r--r--mysql-test/suite/rpl/t/rpl_row_utf32.test113
-rw-r--r--mysql-test/suite/rpl/t/rpl_row_vcol_crash.test425
-rw-r--r--mysql-test/suite/rpl/t/rpl_row_view01.test85
-rw-r--r--mysql-test/suite/rpl/t/rpl_row_virt.test27
-rw-r--r--mysql-test/suite/rpl/t/rpl_row_wide_table.test340
-rw-r--r--mysql-test/suite/rpl/t/rpl_savepoint.test43
-rw-r--r--mysql-test/suite/rpl/t/rpl_seconds_behind_master_spike.test191
-rw-r--r--mysql-test/suite/rpl/t/rpl_semi_sync.test532
-rw-r--r--mysql-test/suite/rpl/t/rpl_semi_sync_after_sync.test4
-rw-r--r--mysql-test/suite/rpl/t/rpl_semi_sync_after_sync_row.test4
-rw-r--r--mysql-test/suite/rpl/t/rpl_semi_sync_crash.inc112
-rw-r--r--mysql-test/suite/rpl/t/rpl_semi_sync_event-master.opt1
-rw-r--r--mysql-test/suite/rpl/t/rpl_semi_sync_event.test91
-rw-r--r--mysql-test/suite/rpl/t/rpl_semi_sync_event_after_sync-master.opt1
-rw-r--r--mysql-test/suite/rpl/t/rpl_semi_sync_event_after_sync.test3
-rw-r--r--mysql-test/suite/rpl/t/rpl_semi_sync_fail_over.cnf13
-rw-r--r--mysql-test/suite/rpl/t/rpl_semi_sync_fail_over.test221
-rw-r--r--mysql-test/suite/rpl/t/rpl_semi_sync_gtid_reconnect.test74
-rw-r--r--mysql-test/suite/rpl/t/rpl_semi_sync_master_shutdown.test60
-rw-r--r--mysql-test/suite/rpl/t/rpl_semi_sync_shutdown_await_ack.cnf14
-rw-r--r--mysql-test/suite/rpl/t/rpl_semi_sync_shutdown_await_ack.inc163
-rw-r--r--mysql-test/suite/rpl/t/rpl_semi_sync_shutdown_await_ack.test217
-rw-r--r--mysql-test/suite/rpl/t/rpl_semi_sync_skip_repl.test66
-rw-r--r--mysql-test/suite/rpl/t/rpl_semi_sync_slave_compressed_protocol-slave.opt1
-rw-r--r--mysql-test/suite/rpl/t/rpl_semi_sync_slave_compressed_protocol.test55
-rw-r--r--mysql-test/suite/rpl/t/rpl_semi_sync_slave_reply_fail.test97
-rw-r--r--mysql-test/suite/rpl/t/rpl_semi_sync_wait_no_slave-master.opt1
-rw-r--r--mysql-test/suite/rpl/t/rpl_semi_sync_wait_no_slave.test14
-rw-r--r--mysql-test/suite/rpl/t/rpl_semi_sync_wait_point.opt1
-rw-r--r--mysql-test/suite/rpl/t/rpl_semi_sync_wait_point.test251
-rw-r--r--mysql-test/suite/rpl/t/rpl_semisync_ali_issues-master.opt1
-rw-r--r--mysql-test/suite/rpl/t/rpl_semisync_ali_issues-slave.opt1
-rw-r--r--mysql-test/suite/rpl/t/rpl_semisync_ali_issues.test429
-rw-r--r--mysql-test/suite/rpl/t/rpl_server_id1.test22
-rw-r--r--mysql-test/suite/rpl/t/rpl_server_id2-slave.opt1
-rw-r--r--mysql-test/suite/rpl/t/rpl_server_id2.test72
-rw-r--r--mysql-test/suite/rpl/t/rpl_server_id_ignore-slave.opt1
-rw-r--r--mysql-test/suite/rpl/t/rpl_server_id_ignore.test116
-rw-r--r--mysql-test/suite/rpl/t/rpl_session_var.test61
-rw-r--r--mysql-test/suite/rpl/t/rpl_set_charset.test30
-rw-r--r--mysql-test/suite/rpl/t/rpl_set_null_innodb.test7
-rw-r--r--mysql-test/suite/rpl/t/rpl_set_null_myisam.test6
-rw-r--r--mysql-test/suite/rpl/t/rpl_set_statement.test61
-rw-r--r--mysql-test/suite/rpl/t/rpl_set_statement_default_master.test34
-rw-r--r--mysql-test/suite/rpl/t/rpl_show_slave_hosts.cnf20
-rw-r--r--mysql-test/suite/rpl/t/rpl_show_slave_hosts.test52
-rw-r--r--mysql-test/suite/rpl/t/rpl_show_slave_running.test83
-rw-r--r--mysql-test/suite/rpl/t/rpl_shutdown_wait_semisync_slaves.cnf16
-rw-r--r--mysql-test/suite/rpl/t/rpl_shutdown_wait_semisync_slaves.test46
-rw-r--r--mysql-test/suite/rpl/t/rpl_shutdown_wait_slaves.cnf16
-rw-r--r--mysql-test/suite/rpl/t/rpl_shutdown_wait_slaves.test11
-rw-r--r--mysql-test/suite/rpl/t/rpl_skip_error-slave.opt1
-rw-r--r--mysql-test/suite/rpl/t/rpl_skip_error.test175
-rw-r--r--mysql-test/suite/rpl/t/rpl_skip_incident-master.opt1
-rw-r--r--mysql-test/suite/rpl/t/rpl_skip_incident-slave.opt1
-rw-r--r--mysql-test/suite/rpl/t/rpl_skip_incident.test42
-rw-r--r--mysql-test/suite/rpl/t/rpl_skip_replication.test408
-rw-r--r--mysql-test/suite/rpl/t/rpl_slave_alias_replica.test103
-rw-r--r--mysql-test/suite/rpl/t/rpl_slave_grp_exec.test186
-rw-r--r--mysql-test/suite/rpl/t/rpl_slave_invalid_external_user.test42
-rw-r--r--mysql-test/suite/rpl/t/rpl_slave_load_in.test49
-rw-r--r--mysql-test/suite/rpl/t/rpl_slave_load_remove_tmpfile.test80
-rw-r--r--mysql-test/suite/rpl/t/rpl_slave_load_tmpdir_not_exist-slave.opt1
-rw-r--r--mysql-test/suite/rpl/t/rpl_slave_load_tmpdir_not_exist.test22
-rw-r--r--mysql-test/suite/rpl/t/rpl_slave_max_statement_time.test110
-rw-r--r--mysql-test/suite/rpl/t/rpl_slave_shutdown_mdev20821.cnf19
-rw-r--r--mysql-test/suite/rpl/t/rpl_slave_shutdown_mdev20821.test171
-rw-r--r--mysql-test/suite/rpl/t/rpl_slave_skip.test293
-rw-r--r--mysql-test/suite/rpl/t/rpl_slave_status.test81
-rw-r--r--mysql-test/suite/rpl/t/rpl_slow_query_log-slave.opt1
-rw-r--r--mysql-test/suite/rpl/t/rpl_slow_query_log.test345
-rw-r--r--mysql-test/suite/rpl/t/rpl_sp-master.opt1
-rw-r--r--mysql-test/suite/rpl/t/rpl_sp-slave.opt1
-rw-r--r--mysql-test/suite/rpl/t/rpl_sp.test732
-rw-r--r--mysql-test/suite/rpl/t/rpl_sp004.test92
-rw-r--r--mysql-test/suite/rpl/t/rpl_sp_effects-master.opt1
-rw-r--r--mysql-test/suite/rpl/t/rpl_sp_effects-slave.opt1
-rw-r--r--mysql-test/suite/rpl/t/rpl_sp_effects.test294
-rw-r--r--mysql-test/suite/rpl/t/rpl_sp_variables.test28
-rw-r--r--mysql-test/suite/rpl/t/rpl_spec_variables.test312
-rw-r--r--mysql-test/suite/rpl/t/rpl_special_charset.opt1
-rw-r--r--mysql-test/suite/rpl/t/rpl_special_charset.test32
-rw-r--r--mysql-test/suite/rpl/t/rpl_sporadic_master-master.opt1
-rw-r--r--mysql-test/suite/rpl/t/rpl_sporadic_master.test32
-rw-r--r--mysql-test/suite/rpl/t/rpl_sql_thd_start_errno_cleared.test93
-rw-r--r--mysql-test/suite/rpl/t/rpl_ssl.test116
-rw-r--r--mysql-test/suite/rpl/t/rpl_ssl1.test110
-rw-r--r--mysql-test/suite/rpl/t/rpl_start_alter_1.test33
-rw-r--r--mysql-test/suite/rpl/t/rpl_start_alter_2.test53
-rw-r--r--mysql-test/suite/rpl/t/rpl_start_alter_3.test54
-rw-r--r--mysql-test/suite/rpl/t/rpl_start_alter_4.test54
-rw-r--r--mysql-test/suite/rpl/t/rpl_start_alter_5.test54
-rw-r--r--mysql-test/suite/rpl/t/rpl_start_alter_6.test58
-rw-r--r--mysql-test/suite/rpl/t/rpl_start_alter_7.cnf19
-rw-r--r--mysql-test/suite/rpl/t/rpl_start_alter_7.test112
-rw-r--r--mysql-test/suite/rpl/t/rpl_start_alter_8.cnf19
-rw-r--r--mysql-test/suite/rpl/t/rpl_start_alter_8.test109
-rw-r--r--mysql-test/suite/rpl/t/rpl_start_alter_bugs.test47
-rw-r--r--mysql-test/suite/rpl/t/rpl_start_alter_chain_basic.cnf24
-rw-r--r--mysql-test/suite/rpl/t/rpl_start_alter_chain_basic.test54
-rw-r--r--mysql-test/suite/rpl/t/rpl_start_alter_ftwrl.test91
-rw-r--r--mysql-test/suite/rpl/t/rpl_start_alter_instant.test30
-rw-r--r--mysql-test/suite/rpl/t/rpl_start_alter_mysqlbinlog_1.test38
-rw-r--r--mysql-test/suite/rpl/t/rpl_start_alter_mysqlbinlog_2.cnf19
-rw-r--r--mysql-test/suite/rpl/t/rpl_start_alter_mysqlbinlog_2.test164
-rw-r--r--mysql-test/suite/rpl/t/rpl_start_alter_optimize.test25
-rw-r--r--mysql-test/suite/rpl/t/rpl_start_alter_options.test31
-rw-r--r--mysql-test/suite/rpl/t/rpl_start_alter_para_to_seq.test24
-rw-r--r--mysql-test/suite/rpl/t/rpl_start_alter_restart_master.test81
-rw-r--r--mysql-test/suite/rpl/t/rpl_start_alter_restart_slave.test121
-rw-r--r--mysql-test/suite/rpl/t/rpl_start_stop_slave-slave.opt1
-rw-r--r--mysql-test/suite/rpl/t/rpl_start_stop_slave.test65
-rw-r--r--mysql-test/suite/rpl/t/rpl_stm_000001.test118
-rw-r--r--mysql-test/suite/rpl/t/rpl_stm_EE_err2.test8
-rw-r--r--mysql-test/suite/rpl/t/rpl_stm_auto_increment_bug33029.test106
-rw-r--r--mysql-test/suite/rpl/t/rpl_stm_binlog_direct-master.opt1
-rw-r--r--mysql-test/suite/rpl/t/rpl_stm_binlog_max_cache_size.test8
-rw-r--r--mysql-test/suite/rpl/t/rpl_stm_conflicts.test6
-rw-r--r--mysql-test/suite/rpl/t/rpl_stm_drop_create_temp_table.test12
-rw-r--r--mysql-test/suite/rpl/t/rpl_stm_flsh_tbls.test6
-rw-r--r--mysql-test/suite/rpl/t/rpl_stm_found_rows.test124
-rw-r--r--mysql-test/suite/rpl/t/rpl_stm_implicit_commit_binlog.test12
-rw-r--r--mysql-test/suite/rpl/t/rpl_stm_innodb.test9
-rw-r--r--mysql-test/suite/rpl/t/rpl_stm_lcase_tblnames-slave.opt1
-rw-r--r--mysql-test/suite/rpl/t/rpl_stm_lcase_tblnames.test12
-rw-r--r--mysql-test/suite/rpl/t/rpl_stm_loaddata_concurrent.test14
-rw-r--r--mysql-test/suite/rpl/t/rpl_stm_loadfile.test24
-rw-r--r--mysql-test/suite/rpl/t/rpl_stm_log-slave.opt1
-rw-r--r--mysql-test/suite/rpl/t/rpl_stm_log.test8
-rw-r--r--mysql-test/suite/rpl/t/rpl_stm_maria.test59
-rw-r--r--mysql-test/suite/rpl/t/rpl_stm_max_relay_size.test8
-rw-r--r--mysql-test/suite/rpl/t/rpl_stm_mix_show_relaylog_events.test19
-rw-r--r--mysql-test/suite/rpl/t/rpl_stm_mixing_engines.test50
-rw-r--r--mysql-test/suite/rpl/t/rpl_stm_multi_query.test7
-rw-r--r--mysql-test/suite/rpl/t/rpl_stm_no_op.test94
-rw-r--r--mysql-test/suite/rpl/t/rpl_stm_relay_ign_space-slave.opt1
-rw-r--r--mysql-test/suite/rpl/t/rpl_stm_relay_ign_space.test107
-rw-r--r--mysql-test/suite/rpl/t/rpl_stm_reset_slave.test6
-rw-r--r--mysql-test/suite/rpl/t/rpl_stm_sp.test30
-rw-r--r--mysql-test/suite/rpl/t/rpl_stm_sql_mode.test25
-rw-r--r--mysql-test/suite/rpl/t/rpl_stm_start_stop_slave.test26
-rw-r--r--mysql-test/suite/rpl/t/rpl_stm_stop_middle_group.test11
-rw-r--r--mysql-test/suite/rpl/t/rpl_stm_until.test184
-rw-r--r--mysql-test/suite/rpl/t/rpl_stm_user_variables.test202
-rw-r--r--mysql-test/suite/rpl/t/rpl_stop_slave.test146
-rw-r--r--mysql-test/suite/rpl/t/rpl_stop_slave_error-slave.opt1
-rw-r--r--mysql-test/suite/rpl/t/rpl_stop_slave_error.test16
-rw-r--r--mysql-test/suite/rpl/t/rpl_strict_password_validation.test24
-rw-r--r--mysql-test/suite/rpl/t/rpl_switch_stm_row_mixed.test651
-rw-r--r--mysql-test/suite/rpl/t/rpl_sync-master.opt2
-rw-r--r--mysql-test/suite/rpl/t/rpl_sync-slave.opt2
-rw-r--r--mysql-test/suite/rpl/t/rpl_sync.test159
-rw-r--r--mysql-test/suite/rpl/t/rpl_table_options.test38
-rw-r--r--mysql-test/suite/rpl/t/rpl_temp_table.test85
-rw-r--r--mysql-test/suite/rpl/t/rpl_temp_table_mix_row.test206
-rw-r--r--mysql-test/suite/rpl/t/rpl_temporal_format_default_to_default.test82
-rw-r--r--mysql-test/suite/rpl/t/rpl_temporal_format_mariadb53_to_mariadb53.test4
-rw-r--r--mysql-test/suite/rpl/t/rpl_temporal_format_mariadb53_to_mysql56.test14
-rw-r--r--mysql-test/suite/rpl/t/rpl_temporal_format_mariadb53_to_mysql56_dst.test37
-rw-r--r--mysql-test/suite/rpl/t/rpl_temporal_format_mysql56_to_mariadb53.test4
-rw-r--r--mysql-test/suite/rpl/t/rpl_temporal_format_mysql56_to_mysql56.test4
-rw-r--r--mysql-test/suite/rpl/t/rpl_temporal_mysql56.test48
-rw-r--r--mysql-test/suite/rpl/t/rpl_temporal_mysql56_to_mariadb.test55
-rw-r--r--mysql-test/suite/rpl/t/rpl_temporal_mysql56_to_mariadb53.test2
-rw-r--r--mysql-test/suite/rpl/t/rpl_temporal_round.test35
-rw-r--r--mysql-test/suite/rpl/t/rpl_temporary.test420
-rw-r--r--mysql-test/suite/rpl/t/rpl_temporary_error2.test79
-rw-r--r--mysql-test/suite/rpl/t/rpl_temporary_errors-slave.opt1
-rw-r--r--mysql-test/suite/rpl/t/rpl_temporary_errors.test116
-rw-r--r--mysql-test/suite/rpl/t/rpl_test_framework.cnf28
-rw-r--r--mysql-test/suite/rpl/t/rpl_test_framework.test143
-rw-r--r--mysql-test/suite/rpl/t/rpl_timestamp.test18
-rw-r--r--mysql-test/suite/rpl/t/rpl_timezone-master.opt1
-rw-r--r--mysql-test/suite/rpl/t/rpl_timezone-slave.opt1
-rw-r--r--mysql-test/suite/rpl/t/rpl_timezone.test211
-rw-r--r--mysql-test/suite/rpl/t/rpl_tmp_table_and_DDL.test169
-rw-r--r--mysql-test/suite/rpl/t/rpl_tmp_table_and_DDL_innodb.test55
-rw-r--r--mysql-test/suite/rpl/t/rpl_trans_no_trans.test72
-rw-r--r--mysql-test/suite/rpl/t/rpl_trigger.test596
-rw-r--r--mysql-test/suite/rpl/t/rpl_trunc_temp.test57
-rw-r--r--mysql-test/suite/rpl/t/rpl_truncate_2myisam.test2
-rw-r--r--mysql-test/suite/rpl/t/rpl_truncate_3innodb.test3
-rw-r--r--mysql-test/suite/rpl/t/rpl_typeconv-slave.opt1
-rw-r--r--mysql-test/suite/rpl/t/rpl_typeconv.test78
-rw-r--r--mysql-test/suite/rpl/t/rpl_typeconv_innodb.test26
-rw-r--r--mysql-test/suite/rpl/t/rpl_udf.test11
-rw-r--r--mysql-test/suite/rpl/t/rpl_unsafe_statements.test215
-rw-r--r--mysql-test/suite/rpl/t/rpl_update.test15
-rw-r--r--mysql-test/suite/rpl/t/rpl_upgrade_master_info.test167
-rw-r--r--mysql-test/suite/rpl/t/rpl_user.test73
-rw-r--r--mysql-test/suite/rpl/t/rpl_user_variables.test385
-rw-r--r--mysql-test/suite/rpl/t/rpl_using_gtid_default.test303
-rw-r--r--mysql-test/suite/rpl/t/rpl_variables.test739
-rw-r--r--mysql-test/suite/rpl/t/rpl_variables_stm.test618
-rw-r--r--mysql-test/suite/rpl/t/rpl_view.test171
-rw-r--r--mysql-test/suite/rpl/t/rpl_view_debug.test35
-rw-r--r--mysql-test/suite/rpl/t/rpl_view_multi.test133
-rw-r--r--mysql-test/suite/rpl/t/rpl_xa-master.opt1
-rw-r--r--mysql-test/suite/rpl/t/rpl_xa.inc433
-rw-r--r--mysql-test/suite/rpl/t/rpl_xa.test5
-rw-r--r--mysql-test/suite/rpl/t/rpl_xa_empty_transaction.cnf18
-rw-r--r--mysql-test/suite/rpl/t/rpl_xa_empty_transaction.test175
-rw-r--r--mysql-test/suite/rpl/t/rpl_xa_gap_lock-slave.opt1
-rw-r--r--mysql-test/suite/rpl/t/rpl_xa_gap_lock.test137
-rw-r--r--mysql-test/suite/rpl/t/rpl_xa_gtid_pos_auto_engine-master.opt1
-rw-r--r--mysql-test/suite/rpl/t/rpl_xa_gtid_pos_auto_engine.test29
-rw-r--r--mysql-test/suite/rpl/t/rpl_xa_prepare_gtid_fail.test102
-rw-r--r--mysql-test/suite/rpl/t/rpl_xa_survive_disconnect.test301
-rw-r--r--mysql-test/suite/rpl/t/rpl_xa_survive_disconnect_lsu_off-slave.opt2
-rw-r--r--mysql-test/suite/rpl/t/rpl_xa_survive_disconnect_lsu_off.test8
-rw-r--r--mysql-test/suite/rpl/t/rpl_xa_survive_disconnect_mixed_engines.test68
-rw-r--r--mysql-test/suite/rpl/t/sec_behind_master-5114.test63
-rw-r--r--mysql-test/suite/rpl/t/semisync_future-7591.test33
-rw-r--r--mysql-test/suite/rpl/t/semisync_memleak_4066.test14
-rw-r--r--mysql-test/suite/rpl/t/sequence.cnf8
-rw-r--r--mysql-test/suite/rpl/t/sequence.test54
-rw-r--r--mysql-test/suite/rpl/t/show_status_stop_slave_race-7126.test22
-rw-r--r--mysql-test/suite/rpl/t/temporal_row-9560-master.opt1
-rw-r--r--mysql-test/suite/rpl/t/temporal_row-9560.combinations6
-rw-r--r--mysql-test/suite/rpl/t/temporal_row-9560.test20
784 files changed, 61635 insertions, 0 deletions
diff --git a/mysql-test/suite/rpl/t/circular_serverid0.cnf b/mysql-test/suite/rpl/t/circular_serverid0.cnf
new file mode 100644
index 00000000..277aac28
--- /dev/null
+++ b/mysql-test/suite/rpl/t/circular_serverid0.cnf
@@ -0,0 +1,30 @@
+!include ../my.cnf
+
+[mysqld.1]
+gtid-domain-id=4
+server-id=4
+#
+log-slave-updates
+slave-parallel-threads=0
+gtid-strict-mode=1
+gtid-ignore-duplicates=1
+
+#
+# Max-size row events to minimum with the idea to create
+# a number of Rows_log_event per Query.
+#
+binlog-row-event-max-size=1024
+
+[mysqld.2]
+gtid-domain-id=2
+server-id=2
+#
+log-slave-updates
+slave-parallel-threads=0
+gtid-strict-mode=1
+gtid-ignore-duplicates=1
+binlog-row-event-max-size=1024
+# The slave will be initialized with a @@global.dbug-var value
+skip-slave-start=1
+
+
diff --git a/mysql-test/suite/rpl/t/circular_serverid0.test b/mysql-test/suite/rpl/t/circular_serverid0.test
new file mode 100644
index 00000000..64cf231c
--- /dev/null
+++ b/mysql-test/suite/rpl/t/circular_serverid0.test
@@ -0,0 +1,103 @@
+#
+# Testing chain/circular replication scenario of MDEV-9670
+# The effect of the bug was that we got a commit with a GTID with server_id
+#
+
+--source include/have_binlog_format_row.inc
+--source include/have_innodb.inc
+--source include/have_debug.inc
+--source include/have_debug_sync.inc
+
+--let $rpl_topology= 1->2->1
+--source include/rpl_init.inc
+
+--let $rpl_connection_name= M4
+--let $rpl_server_number= 1
+--source include/rpl_connect.inc
+
+--let $rpl_connection_name= M2
+--let $rpl_server_number= 2
+--source include/rpl_connect.inc
+
+# The parameter reflects binlog-row-event-max-size @cnf.
+--let $row_size=1024
+
+--connection M2
+STOP SLAVE;
+SET @old_debug= @@global.debug_dbug;
+SET GLOBAL debug_dbug= "d,dbug.rows_events_to_delay_relay_logging";
+START SLAVE IO_THREAD;
+--source include/wait_for_slave_io_to_start.inc
+
+--connection M2
+# This query also creates a Gtid event group whose Gtid will remain in
+# ignored status for too long causing a following group split.
+
+CREATE TABLE t1 (a INT AUTO_INCREMENT PRIMARY KEY, b VARCHAR(30000)) ENGINE=innodb;
+--sync_slave_with_master M4
+
+# This INSERT will be logged as two Write_log events which the buggy
+# slave applier would split.
+
+--connection M4
+eval INSERT INTO `t1` VALUES (null, repeat('a', $row_size)), (null, repeat('b', $row_size));
+
+# START M2 IO thread and wait for its signal to follow with the SQL
+# thread start. At this moment the SQL thread shall be having 2 and
+# "half" groups to execute. The "hafl" one would be committed by the
+# buggy applier after which the IO is released to queue the rest of
+# the 3rd group which the SQL thread commits separately to complete
+# the split.
+
+--connection M2
+
+# wait for IO signal to start the SQL thread. IO will be hanging upon that.
+SET debug_sync='now WAIT_FOR start_sql_thread';
+
+# Now the slave server has relay log whose last group is incomplete.
+# An unfixed slave server would go to "insert" a "fake"
+# Gtid_list_log_event event which actually would commit the incomplete
+# group. However before to actual commit do_apply_event() hits some assert.
+# In the fixed server the fake Gtid_list_log_event is *not* inserted
+# in the middle of a group.
+START SLAVE SQL_THREAD;
+
+# Sleep for a little time to give SQL thread a chance to commit while
+# the IO thread is hanging (see
+# DBUG_EXECUTE_IF("dbug.rows_events_to_delay_relay_logging"...) in
+# queue_event). Alternatively to reproduce the case when buggy slave
+# wait for the 1st group commit
+
+#--let $count= 1
+#--let $table= t1
+#--source include/wait_until_rows_count.inc
+
+--sleep 2
+
+# Demonstrate either no split group in the correct slave or the 1nd
+# group in the buggy one
+--source include/show_binlog_events.inc
+
+# Release the IO thread
+SET debug_sync='now SIGNAL go_on_relay_logging';
+
+# Sync servers
+--sync_slave_with_master M4
+--connection M4
+--sync_slave_with_master M2
+--connection M2
+
+# Demonstrate replication goes correctly not to create any split, or
+# the 2nd group in the buggy slave
+--source include/show_binlog_events.inc
+
+#
+# Cleanup
+#
+--connection M4
+drop table t1;
+
+--connection M2
+SET GLOBAL debug_dbug= @old_debug;
+SET debug_sync='RESET';
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/create_or_replace.inc b/mysql-test/suite/rpl/t/create_or_replace.inc
new file mode 100644
index 00000000..df46cc36
--- /dev/null
+++ b/mysql-test/suite/rpl/t/create_or_replace.inc
@@ -0,0 +1,227 @@
+# Test CREATE OR REPLACE TABLE in replication
+--source include/have_innodb.inc
+
+--let $rpl_topology=1->2
+--source include/rpl_init.inc
+
+# Create help tables
+create table t2 (a int) engine=myisam;
+insert into t2 values (0),(1),(2),(2);
+create temporary table t3 (a_in_temporary int) engine=myisam;
+
+--echo #
+--echo # Check how create table and create or replace table are logged
+--echo #
+
+save_master_pos;
+connection server_2;
+sync_with_master;
+create table t1 (to_be_deleted int);
+
+connection server_1;
+CREATE TABLE t1 AS SELECT 1 AS f1;
+CREATE OR REPLACE TABLE t1 AS SELECT 2 AS f1;
+CREATE OR REPLACE table t1 like t2;
+CREATE OR REPLACE table t1 like t3;
+drop table t1;
+
+--echo binlog from server 1
+--source include/show_binlog_events.inc
+save_master_pos;
+connection server_2;
+sync_with_master;
+--echo binlog from server 2
+--source include/show_binlog_events.inc
+
+connection server_1;
+
+--echo #
+--echo # Ensure that also failed create_or_replace are logged
+--echo #
+
+--let $binlog_start=query_get_value(SHOW MASTER STATUS, Position, 1)
+
+create table t1 (a int);
+--error ER_TABLE_MUST_HAVE_COLUMNS
+create or replace table t1;
+drop table if exists t1;
+# The following is not logged as t1 does not exists;
+--error ER_DUP_ENTRY
+create or replace table t1 (a int primary key) select a from t2;
+
+create table t1 (a int);
+# This should as a delete as we will delete t1
+--error ER_DUP_ENTRY
+create or replace table t1 (a int primary key) select a from t2;
+
+# Same with temporary table
+create temporary table t9 (a int);
+
+--error ER_DUP_ENTRY
+create or replace temporary table t9 (a int primary key) select a from t2;
+
+--echo binlog from server 1
+--source include/show_binlog_events.inc
+save_master_pos;
+connection server_2;
+sync_with_master;
+show tables;
+connection server_1;
+
+--let $binlog_start=query_get_value(SHOW MASTER STATUS, Position, 1)
+create table t1 (a int);
+--error ER_DUP_FIELDNAME
+create or replace table t1 (a int, a int) select * from t2;
+--source include/show_binlog_events.inc
+
+drop table if exists t1,t2;
+drop temporary table if exists t9;
+
+--echo #
+--echo # Ensure that CREATE are run as CREATE OR REPLACE on slave
+--echo #
+
+save_master_pos;
+connection server_2;
+sync_with_master;
+create table t1 (server_2_to_be_delete int);
+connection server_1;
+create table t1 (new_table int);
+
+save_master_pos;
+connection server_2;
+sync_with_master;
+
+show create table t1;
+connection server_1;
+drop table t1;
+
+--echo #
+--echo # Check how CREATE is logged on slave in case of conflicts
+--echo #
+
+save_master_pos;
+connection server_2;
+sync_with_master;
+--let $binlog_start=query_get_value(SHOW MASTER STATUS, Position, 1)
+create table t1 (server_2_to_be_delete int);
+create table t2 (server_2_to_be_delete int);
+create table t4 (server_2_to_be_delete int);
+set @org_binlog_format=@@binlog_format;
+set @@global.binlog_format="ROW";
+stop slave;
+--source include/wait_for_slave_to_stop.inc
+start slave;
+--source include/wait_for_slave_to_start.inc
+connection server_1;
+create temporary table t9 (a int);
+insert into t9 values(1);
+create table t1 (new_table int);
+create table t2 select * from t9;
+create table t4 like t9;
+create table t5 select * from t9;
+save_master_pos;
+connection server_2;
+sync_with_master;
+--echo binlog from server 2
+--source include/show_binlog_events.inc
+set @@global.binlog_format=@org_binlog_format;
+stop slave;
+--source include/wait_for_slave_to_stop.inc
+start slave;
+--source include/wait_for_slave_to_start.inc
+connection server_1;
+drop table t1,t2,t4,t5,t9;
+
+--echo #
+--echo # Ensure that DROP TABLE is run as DROP IF NOT EXISTS
+--echo #
+
+create table t1 (server_1_ver_1 int);
+create table t4 (server_1_ver_2 int);
+
+save_master_pos;
+connection server_2;
+sync_with_master;
+--let $binlog_start=query_get_value(SHOW MASTER STATUS, Position, 1)
+
+# Drop the table on the slave
+drop table t1;
+connection server_1;
+drop table t1,t4;
+create table t1 (server_2_ver_2 int);
+save_master_pos;
+connection server_2;
+sync_with_master;
+show create table t1;
+--echo binlog from server 2
+--source include/show_binlog_events.inc
+connection server_1;
+drop table t1;
+
+--echo #
+--echo # Ensure that CREATE ... SELECT is recorded as one GTID on the slave
+--echo #
+
+save_master_pos;
+connection server_2;
+sync_with_master;
+--let $binlog_start=query_get_value(SHOW MASTER STATUS, Position, 1)
+connection server_1;
+
+create table t1 (a int);
+insert into t1 values (0),(1),(2);
+create table t2 engine=myisam select * from t1;
+create or replace table t2 engine=innodb select * from t1;
+save_master_pos;
+connection server_2;
+sync_with_master;
+--echo binlog from server 2
+--source include/show_binlog_events.inc
+connection server_1;
+drop table t1;
+
+--echo #
+--echo # Check logging of drop temporary table
+--echo #
+
+drop temporary table t3;
+
+--let $binlog_start=query_get_value(SHOW MASTER STATUS, Position, 1)
+
+set @org_binlog_format=@@binlog_format;
+set binlog_format="STATEMENT";
+create temporary table t5 (a int);
+drop temporary table t5;
+set binlog_format="ROW";
+create temporary table t6 (a int);
+drop temporary table t6;
+set binlog_format="STATEMENT";
+create temporary table t7 (a int);
+set binlog_format="ROW";
+drop temporary table t7;
+create temporary table t8 (a int);
+--error ER_TEMP_TABLE_PREVENTS_SWITCH_OUT_OF_RBR
+set binlog_format="STATEMENT";
+drop temporary table t8;
+set @@binlog_format=@org_binlog_format;
+
+# MDEV-20091:
+# 1. No DROP should be logged for non-existing tmp table, nor
+# 2. at the connection close when its creation has not been logged.
+set @@session.binlog_format=default;
+drop temporary table if exists t9;
+
+--connect(con1,localhost,root,,)
+set session binlog_format=default;
+create temporary table t9 (i int);
+--echo *** Must be no DROP logged for t9 when there was no CREATE, at disconnect too ***
+--disconnect con1
+
+--connection server_1
+--source include/show_binlog_events.inc
+
+# Clean up
+drop table t2;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/create_or_replace2.test b/mysql-test/suite/rpl/t/create_or_replace2.test
new file mode 100644
index 00000000..f0091db7
--- /dev/null
+++ b/mysql-test/suite/rpl/t/create_or_replace2.test
@@ -0,0 +1,42 @@
+--source include/have_innodb.inc
+--source include/have_binlog_format_row_or_statement.inc
+--source include/have_metadata_lock_info.inc
+--source include/master-slave.inc
+
+--echo #
+--echo # MDEV-6525 ; Problems with CREATE OR REPLACE under lock
+--echo #
+
+CREATE TABLE t1 (a INT) ENGINE=InnoDB;
+CREATE FUNCTION f1() RETURNS INT RETURN ( SELECT MAX(a) FROM t1 );
+
+--connect (con1,localhost,root,,test)
+
+CREATE TEMPORARY TABLE tmp (b INT) ENGINE=InnoDB;
+LOCK TABLE t1 WRITE;
+
+SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
+
+CREATE OR REPLACE TABLE t1 LIKE tmp;
+SHOW CREATE TABLE t1;
+
+--connection default
+set session lock_wait_timeout=1;
+--error 1205
+SELECT f1();
+
+set session lock_wait_timeout=@@global.lock_wait_timeout;
+--send SELECT f1()
+--connection con1
+# This is here just in case, any timeout should be ok
+--sleep 1
+unlock tables;
+--connection default
+--error 1054
+--reap
+--disconnect con1
+
+# Cleanup
+drop function f1;
+drop table t1;
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/create_or_replace_mix.cnf b/mysql-test/suite/rpl/t/create_or_replace_mix.cnf
new file mode 100644
index 00000000..03d69b28
--- /dev/null
+++ b/mysql-test/suite/rpl/t/create_or_replace_mix.cnf
@@ -0,0 +1,9 @@
+!include suite/rpl/my.cnf
+
+[mysqld.1]
+log-slave-updates
+loose-innodb
+
+[mysqld.2]
+log-slave-updates
+loose-innodb
diff --git a/mysql-test/suite/rpl/t/create_or_replace_mix.test b/mysql-test/suite/rpl/t/create_or_replace_mix.test
new file mode 100644
index 00000000..0cabef15
--- /dev/null
+++ b/mysql-test/suite/rpl/t/create_or_replace_mix.test
@@ -0,0 +1,4 @@
+# Testing create or replace table in mixed mode.
+
+--source include/have_binlog_format_mixed.inc
+--source create_or_replace.inc
diff --git a/mysql-test/suite/rpl/t/create_or_replace_row.cnf b/mysql-test/suite/rpl/t/create_or_replace_row.cnf
new file mode 100644
index 00000000..03d69b28
--- /dev/null
+++ b/mysql-test/suite/rpl/t/create_or_replace_row.cnf
@@ -0,0 +1,9 @@
+!include suite/rpl/my.cnf
+
+[mysqld.1]
+log-slave-updates
+loose-innodb
+
+[mysqld.2]
+log-slave-updates
+loose-innodb
diff --git a/mysql-test/suite/rpl/t/create_or_replace_row.test b/mysql-test/suite/rpl/t/create_or_replace_row.test
new file mode 100644
index 00000000..88dd8fd2
--- /dev/null
+++ b/mysql-test/suite/rpl/t/create_or_replace_row.test
@@ -0,0 +1,4 @@
+# Testing create or replace table in mixed mode.
+
+--source include/have_binlog_format_row.inc
+--source create_or_replace.inc
diff --git a/mysql-test/suite/rpl/t/create_or_replace_statement.cnf b/mysql-test/suite/rpl/t/create_or_replace_statement.cnf
new file mode 100644
index 00000000..03d69b28
--- /dev/null
+++ b/mysql-test/suite/rpl/t/create_or_replace_statement.cnf
@@ -0,0 +1,9 @@
+!include suite/rpl/my.cnf
+
+[mysqld.1]
+log-slave-updates
+loose-innodb
+
+[mysqld.2]
+log-slave-updates
+loose-innodb
diff --git a/mysql-test/suite/rpl/t/create_or_replace_statement.test b/mysql-test/suite/rpl/t/create_or_replace_statement.test
new file mode 100644
index 00000000..2709e414
--- /dev/null
+++ b/mysql-test/suite/rpl/t/create_or_replace_statement.test
@@ -0,0 +1,4 @@
+# Testing create or replace table in mixed mode.
+
+--source include/have_binlog_format_statement.inc
+--source create_or_replace.inc
diff --git a/mysql-test/suite/rpl/t/create_select.cnf b/mysql-test/suite/rpl/t/create_select.cnf
new file mode 100644
index 00000000..65a4396e
--- /dev/null
+++ b/mysql-test/suite/rpl/t/create_select.cnf
@@ -0,0 +1,16 @@
+!include suite/rpl/my.cnf
+
+[mysqld.1]
+
+[mysqld.2]
+log-slave-updates
+binlog-checksum=CRC32
+
+[mysqld.3]
+log-slave-updates
+binlog-checksum=CRC32
+
+[ENV]
+SERVER_MYPORT_3= @mysqld.3.port
+SERVER_MYSOCK_3= @mysqld.3.socket
+
diff --git a/mysql-test/suite/rpl/t/create_select.test b/mysql-test/suite/rpl/t/create_select.test
new file mode 100644
index 00000000..c1f8fc8f
--- /dev/null
+++ b/mysql-test/suite/rpl/t/create_select.test
@@ -0,0 +1,37 @@
+--source include/have_innodb.inc
+
+--let $rpl_topology=1->2->3
+--source include/rpl_init.inc
+
+#
+# Test of MDEV-8428 Mangled DML statements on 2nd level slave when enabling
+# binlog checksums
+#
+
+connection server_1;
+
+CREATE DATABASE test_8428;
+USE test_8428;
+CREATE TABLE t1(i INT) ENGINE=INNODB;
+INSERT INTO t1 VALUES(1), (2), (3), (4), (5);
+CREATE TABLE t2 AS SELECT * FROM t1;
+CREATE TABLE t3 ENGINE=MyISAM AS SELECT * FROM t1;
+
+save_master_pos;
+connection server_2;
+sync_with_master;
+
+SHOW TABLES IN test_8428;
+
+save_master_pos;
+connection server_3;
+sync_with_master;
+
+SHOW TABLES IN test_8428;
+SELECT * from test_8428.t1;
+
+# Cleanup
+connection server_1;
+DROP DATABASE test_8428;
+--source include/rpl_end.inc
+--echo # End of test
diff --git a/mysql-test/suite/rpl/t/failed_create_view-6409.test b/mysql-test/suite/rpl/t/failed_create_view-6409.test
new file mode 100644
index 00000000..5d96e6f8
--- /dev/null
+++ b/mysql-test/suite/rpl/t/failed_create_view-6409.test
@@ -0,0 +1,24 @@
+#
+# MDEV-6409 CREATE VIEW replication problem if error occurs in mysql_register_view
+#
+
+#
+#
+# verify that failed CREATE VIEW is not replicated
+
+create table v1 (a int);
+
+source include/master-slave.inc;
+
+connection master;
+create table t1 (a int);
+--error ER_TABLE_EXISTS_ERROR
+create view v1 as select * from t1;
+show tables;
+sync_slave_with_master;
+show tables;
+
+connection master;
+drop table if exists t1, v1;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/grant_replication_slave.test b/mysql-test/suite/rpl/t/grant_replication_slave.test
new file mode 100644
index 00000000..c5aca0a6
--- /dev/null
+++ b/mysql-test/suite/rpl/t/grant_replication_slave.test
@@ -0,0 +1,39 @@
+--echo #
+--echo # MDEV-21743 Split up SUPER privilege to smaller privileges
+--echo #
+
+# Checking that REPLICATION SLAVE is enough to start replication
+
+create user rpl@localhost;
+grant replication slave on *.* to rpl@localhost;
+
+source include/master-slave.inc;
+connection slave;
+stop slave;
+change master to master_user='rpl';
+connection master;
+
+create database mysqltest1;
+create table mysqltest1.t1 (a int);
+insert mysqltest1.t1 values (1),(2),(3);
+select * from mysqltest1.t1;
+flush tables;
+create user foo@localhost;
+grant select on *.* to foo@localhost;
+
+connection slave;
+start slave;
+connection master;
+sync_slave_with_master;
+select * from mysqltest1.t1;
+show grants for foo@localhost;
+connection master;
+drop user foo@localhost;
+drop database mysqltest1;
+sync_slave_with_master;
+stop slave;
+change master to master_user='root';
+start slave;
+
+source include/rpl_end.inc;
+drop user rpl@localhost;
diff --git a/mysql-test/suite/rpl/t/ignore_table_autoinc-9737.test b/mysql-test/suite/rpl/t/ignore_table_autoinc-9737.test
new file mode 100644
index 00000000..405d1a92
--- /dev/null
+++ b/mysql-test/suite/rpl/t/ignore_table_autoinc-9737.test
@@ -0,0 +1,35 @@
+#
+# MDEV-9737 Duplicate error in replication with slave triggers and auto increment
+#
+source include/master-slave.inc;
+call mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT");
+
+
+create table t1(id int auto_increment primary key);
+create table t2(id int auto_increment primary key);
+
+sync_slave_with_master;
+create table slave_only(id int auto_increment primary key);
+insert into slave_only values(NULL);
+create trigger t1i after insert on t1 for each row insert into slave_only values(NULL);
+
+stop slave;
+set global replicate_ignore_table="test.t2";
+start slave;
+
+connection master;
+insert into t2 values(NULL);
+insert into t1 values(NULL);
+
+sync_slave_with_master;
+
+drop table t1, t2, slave_only;
+stop slave;
+set global replicate_ignore_table="";
+start slave;
+
+connection master;
+drop table t1, t2;
+
+source include/rpl_end.inc;
+
diff --git a/mysql-test/suite/rpl/t/kill_hard-6290.test b/mysql-test/suite/rpl/t/kill_hard-6290.test
new file mode 100644
index 00000000..76242356
--- /dev/null
+++ b/mysql-test/suite/rpl/t/kill_hard-6290.test
@@ -0,0 +1,11 @@
+#
+# MDEV-6290 Crash in KILL HARD QUERY USER x@y when slave threads are running
+#
+
+# this test doesn't depend on the binlog format, no need to run it three times
+--source include/have_binlog_format_mixed.inc
+
+--source include/master-slave.inc
+--connection server_2
+kill user test2@nohost;
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/kill_race_condition.test b/mysql-test/suite/rpl/t/kill_race_condition.test
new file mode 100644
index 00000000..25a7b18b
--- /dev/null
+++ b/mysql-test/suite/rpl/t/kill_race_condition.test
@@ -0,0 +1,36 @@
+source include/have_debug_sync.inc;
+source include/have_binlog_format_row.inc;
+source include/master-slave.inc;
+
+connection master;
+create table t1 (a int);
+--sync_slave_with_master
+
+connection slave;
+SET @saved_dbug = @@GLOBAL.debug_dbug;
+set global debug_dbug='d,rows_log_event_before_open_table';
+
+connection master;
+insert t1 values (1),(2),(3);
+
+connection slave;
+set debug_sync='now WAIT_FOR before_open_table';
+let $a=`select id from information_schema.processlist where state='debug sync point: now'`;
+replace_result $a slave_sql_thread;
+eval kill $a;
+set debug_sync='now SIGNAL go_ahead_sql';
+--let $slave_sql_errno= 1927
+--source include/wait_for_slave_sql_error.inc
+let $error= query_get_value(SHOW SLAVE STATUS, Last_SQL_Error, 1);
+--echo Last_SQL_Error = $error
+SET @@GLOBAL.debug_dbug = @saved_dbug;
+set debug_sync='RESET';
+connection master;
+drop table t1;
+
+connection slave;
+--source include/start_slave.inc
+let $error= query_get_value(SHOW SLAVE STATUS, Last_SQL_Error, 1);
+--echo Last_SQL_Error = $error
+
+source include/rpl_end.inc;
diff --git a/mysql-test/suite/rpl/t/last_insert_id.cnf b/mysql-test/suite/rpl/t/last_insert_id.cnf
new file mode 100644
index 00000000..1c229e4a
--- /dev/null
+++ b/mysql-test/suite/rpl/t/last_insert_id.cnf
@@ -0,0 +1,20 @@
+!include suite/rpl/my.cnf
+
+[mysqld.1]
+log-slave-updates
+loose-innodb
+
+[mysqld.2]
+log-slave-updates
+loose-innodb
+replicate-ignore-table=db.t2
+
+[mysqld.3]
+log-slave-updates
+loose-innodb
+
+[ENV]
+SERVER_MYPORT_3= @mysqld.3.port
+SERVER_MYSOCK_3= @mysqld.3.socket
+
+
diff --git a/mysql-test/suite/rpl/t/last_insert_id.test b/mysql-test/suite/rpl/t/last_insert_id.test
new file mode 100644
index 00000000..f23cca40
--- /dev/null
+++ b/mysql-test/suite/rpl/t/last_insert_id.test
@@ -0,0 +1,30 @@
+--source include/have_innodb.inc
+--source include/have_binlog_format_mixed_or_statement.inc
+--let $rpl_topology=1->2->3
+--source include/rpl_init.inc
+
+connection server_1;
+
+create table t1 (id int not null auto_increment primary key, i int) engine=InnoDB;
+insert into t1 (i) values (-1);
+insert into t1 (i) values (LAST_INSERT_ID());
+select * from t1;
+
+save_master_pos;
+
+connection server_2;
+
+sync_with_master;
+select * from t1;
+save_master_pos;
+
+connection server_3;
+
+sync_with_master;
+select * from t1;
+
+connection server_1;
+drop table t1;
+
+--source include/rpl_end.inc
+
diff --git a/mysql-test/suite/rpl/t/mdev-31448_kill_ooo_finish_optimistic.test b/mysql-test/suite/rpl/t/mdev-31448_kill_ooo_finish_optimistic.test
new file mode 100644
index 00000000..1297fcda
--- /dev/null
+++ b/mysql-test/suite/rpl/t/mdev-31448_kill_ooo_finish_optimistic.test
@@ -0,0 +1,93 @@
+--source include/master-slave.inc
+--source include/have_innodb.inc
+--source include/have_debug.inc
+--source include/have_binlog_format_row.inc
+
+--echo # MDEV-31448 OOO finish event group by killed worker
+# The test demonstrates how a killed worker access gco lists
+# in finish_event_group() out-of-order to fire
+# DBUG_ASSERT(!tmp_gco->next_gco || tmp_gco->last_sub_id > sub_id);
+# in the buggy version.
+
+--echo # Initialize test data
+--connection master
+call mtr.add_suppression("Slave: Connection was killed");
+call mtr.add_suppression("Slave: Commit failed due to failure of an earlier commit on which this one depends");
+create table t1 (a int) engine=innodb;
+create table t2 (a int) engine=innodb;
+
+insert into t1 values (1);
+--source include/save_master_gtid.inc
+
+--connection slave
+--source include/sync_with_master_gtid.inc
+--source include/stop_slave.inc
+--let $save_slave_parallel_threads= `SELECT @@global.slave_parallel_threads`
+--let $save_slave_parallel_mode= `SELECT @@global.slave_parallel_mode`
+--let $save_innodb_lock_wait_timeout= `SELECT @@global.innodb_lock_wait_timeout`
+--let $save_transaction_retries= `SELECT @@global.slave_transaction_retries`
+set @@global.slave_parallel_threads= 4;
+set @@global.slave_parallel_mode= OPTIMISTIC;
+set @@global.innodb_lock_wait_timeout= 30;
+set @@global.slave_transaction_retries= 0;
+
+--connection slave1
+BEGIN;
+SELECT * FROM t1 WHERE a=1 FOR UPDATE;
+
+--connection master
+SET @old_dbug= @@SESSION.debug_dbug;
+SET @@SESSION.debug_dbug="+d,binlog_force_commit_id";
+
+# GCO 1
+SET @commit_id= 10000;
+# T1
+update t1 set a=2 where a=1;
+# T2
+set statement skip_parallel_replication=1 for insert into t2 values (1);
+
+# GCO 2
+# T3
+drop table t2;
+
+--connection slave
+--source include/start_slave.inc
+
+--echo # wait for T1
+--let $wait_condition= SELECT count(*)=1 FROM information_schema.processlist WHERE state LIKE 'Update_rows_log_event::find_row(-1)%' and command LIKE 'Slave_worker';
+--source include/wait_condition.inc
+
+--echo # wait for T2
+--let $wait_condition= SELECT count(*)=1 FROM information_schema.processlist WHERE state LIKE 'Waiting for prior transaction to commit%' and command LIKE 'Slave_worker';
+--source include/wait_condition.inc
+--let $t2_tid= `SELECT ID FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE LIKE 'Waiting for prior transaction to commit%' and command LIKE 'Slave_worker'`
+--echo # wait for T3
+--let $wait_condition= SELECT count(*)=1 FROM information_schema.processlist WHERE state LIKE 'Waiting for prior transaction to start commit%' and command LIKE 'Slave_worker';
+--source include/wait_condition.inc
+
+--replace_result $t2_tid T2_TID
+--eval kill $t2_tid
+
+--sleep 1
+
+--connection slave1
+# Release the blocked T1
+ROLLBACK;
+
+--connection master
+DROP TABLE t1;
+--source include/save_master_gtid.inc
+
+--connection slave
+--echo #
+--echo # Cleanup
+--source include/stop_slave.inc
+eval set @@global.slave_parallel_threads= $save_slave_parallel_threads;
+eval set @@global.slave_parallel_mode= $save_slave_parallel_mode;
+eval set @@global.innodb_lock_wait_timeout= $save_innodb_lock_wait_timeout;
+eval set @@global.slave_transaction_retries= $save_transaction_retries;
+--source include/start_slave.inc
+--source include/sync_with_master_gtid.inc
+
+--source include/rpl_end.inc
+
diff --git a/mysql-test/suite/rpl/t/mdev_17588-slave.opt b/mysql-test/suite/rpl/t/mdev_17588-slave.opt
new file mode 100644
index 00000000..d73dbeca
--- /dev/null
+++ b/mysql-test/suite/rpl/t/mdev_17588-slave.opt
@@ -0,0 +1 @@
+--loose-disable-innodb --replicate-ignore-table=test.t3
diff --git a/mysql-test/suite/rpl/t/mdev_17588.test b/mysql-test/suite/rpl/t/mdev_17588.test
new file mode 100644
index 00000000..44644158
--- /dev/null
+++ b/mysql-test/suite/rpl/t/mdev_17588.test
@@ -0,0 +1,44 @@
+--source include/master-slave.inc
+--source include/have_innodb.inc
+
+--connection slave
+--source include/stop_slave.inc
+CHANGE MASTER TO master_use_gtid=slave_pos;
+--source include/start_slave.inc
+
+--connection master
+create table t1 (a int) engine=innodb;
+create table t2 (a int);
+create table t3 (a int) engine=innodb;
+--save_master_pos
+
+--connection slave
+# Using ER_UNKNOWN_STORAGE_ENGINE wont work
+let $slave_sql_errno= 1286;
+--source include/wait_for_slave_sql_error_and_skip.inc
+--sync_with_master
+
+--let $assert_text= Status should be 'Slave has read all relay log...'
+--let $assert_cond= "[SHOW SLAVE STATUS, Slave_SQL_Running_State, 1]"
+#Like "Slave has read all relay log%"
+--source include/rpl_assert.inc
+
+show tables;
+show create table t2;
+--error ER_NO_SUCH_TABLE
+show create table t1;
+--error ER_NO_SUCH_TABLE
+show create table t3;
+
+--connection master
+drop table if exists t1;
+drop table if exists t2;
+drop table if exists t3;
+--source include/save_master_gtid.inc
+
+--connection slave
+--source include/sync_with_master_gtid.inc
+
+
+CALL mtr.add_suppression('Slave: Unknown storage engine .* Error_code: 1286');
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/mdev_24667.cnf b/mysql-test/suite/rpl/t/mdev_24667.cnf
new file mode 100644
index 00000000..58b605ad
--- /dev/null
+++ b/mysql-test/suite/rpl/t/mdev_24667.cnf
@@ -0,0 +1,8 @@
+!include ../my.cnf
+
+[mysqld.3]
+log-slave-updates
+
+[ENV]
+SERVER_MYPORT_3= @mysqld.3.port
+SERVER_MYSOCK_3= @mysqld.3.socket
diff --git a/mysql-test/suite/rpl/t/mdev_24667.test b/mysql-test/suite/rpl/t/mdev_24667.test
new file mode 100644
index 00000000..d8490b33
--- /dev/null
+++ b/mysql-test/suite/rpl/t/mdev_24667.test
@@ -0,0 +1,56 @@
+#
+# MDEV-24667 LOAD DATA INFILE/inserted rows not written to binlog
+#
+# In this test we will have a replication configuration like 1->2->3
+# 1 will have statement format
+# 2 and 3 will have mixed format
+# We will make some updates on temporary table which are unsafe , So 2 must
+# Log these queries in row format, Since it is on tmp table , It wont be logged
+# So the next query which copies the data from tmp table to normal must be logged
+# into the row format. Instead of checking for the binlog We will compare the
+# results on the 3, If no binlog is lost(ie it is logged into row format), There
+# should not be any data loss.
+--let $rpl_topology=1->2->3
+--source include/rpl_init.inc
+--source include/have_binlog_format_mixed.inc
+call mtr.add_suppression('Unsafe statement written to the binary log using ');
+--connection server_1
+
+set binlog_format=statement;
+--echo #first bug
+create table t1 (a int);
+create temporary table tmp like t1;
+--write_file $MYSQLTEST_VARDIR/load_data
+1
+2
+EOF
+--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
+eval load data local infile '$MYSQLTEST_VARDIR/load_data' INTO TABLE tmp;
+insert into t1 select * from tmp;
+
+--echo #second bug
+create table t2 (a int);
+#insert into t2 values(10);
+create temporary table tmp2 like t2;
+insert into tmp2 values(10);
+update tmp2 set a = 20 limit 1;
+insert into t2 select * from tmp2;
+--save_master_pos
+
+--connection server_2
+--sync_with_master
+--save_master_pos
+
+--connection server_3
+--sync_with_master
+--echo #t1 should have 2 rows
+select count(*) = 2 from t1;
+--echo #t2 should have 1 rows with a = 20
+select * from t2;
+
+
+# cleanup
+--connection server_1
+drop table t1, t2, tmp, tmp2;
+--remove_file $MYSQLTEST_VARDIR/load_data
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/myisam_external_lock-slave.opt b/mysql-test/suite/rpl/t/myisam_external_lock-slave.opt
new file mode 100644
index 00000000..db53e17d
--- /dev/null
+++ b/mysql-test/suite/rpl/t/myisam_external_lock-slave.opt
@@ -0,0 +1,2 @@
+--log-slave-updates=0
+--skip_external_locking=0
diff --git a/mysql-test/suite/rpl/t/myisam_external_lock.test b/mysql-test/suite/rpl/t/myisam_external_lock.test
new file mode 100644
index 00000000..14824fd8
--- /dev/null
+++ b/mysql-test/suite/rpl/t/myisam_external_lock.test
@@ -0,0 +1,24 @@
+--source include/have_binlog_format_row.inc
+--source include/master-slave.inc
+
+#
+# MDEV-6871 Multi-value insert on MyISAM table that makes slaves crash
+# This only happens if external_lock is enabled
+#
+
+drop table if exists t1;
+CREATE TABLE `t1` (`col1` int(11) NOT NULL,`col2` int(11) NOT NULL,
+ PRIMARY KEY (`col1`,`col2`),
+ KEY `col2` (`col2`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+INSERT INTO `t1` VALUES (2775,974),(2775,975),(2775,976),(2778,977),(2778,978),(2782,979),(2790,986),(2790,1139),(2792,840),(2792,984),(2792,989),(2793,982),(2793,992),(2793,993),(2793,994),(2795,323),(2795,332),(2797,980),(2797,997),(2797,998),(2798,1103),(2798,1104),(2799,841),(2799,985),(2799,988),(2833,983),(2833,990),(2833,991),(2834,981),(2834,995),(2834,996),(2835,316),(2835,317),(3007,854),(3007,856),(3008,855),(3008,857),(3009,823),(3009,824),(3014,1),(3015,1),(3016,2),(3017,2),(3018,3),(3019,3),(3024,842),(3024,843),(3024,844),(3025,845),(3025,846),(3025,847),(3040,31),(3041,32),(3042,52),(3042,55),(3043,53),(3043,54),(3044,278),(3044,279),(3044,280),(3044,281),(3044,282),(3044,283),(3044,284),(3044,285),(3045,1),(3046,1),(3049,220),(3050,221),(3050,222),(3051,2),(3052,2),(3053,223),(3054,224),(3055,225),(3056,226),(3057,227),(3058,228),(3059,229),(3060,327),(3066,236),(3067,237),(3068,238),(3069,239),(3070,240),(3080,241),(3081,242),(3082,247),(3083,248),(3084,249),(3085,250),(3086,251),(3087,252),(3088,253),(3089,254),(3090,255),(3091,256),(3092,257),(3093,258),(3094,259),(3096,263),(3097,264),(3100,273),(3100,302),(3101,266),(3102,267),(3103,268),(3104,269),(3105,270),(3111,275),(3112,238),(3113,272),(3115,286),(3116,318),(3116,319),(3117,290),(3117,292),(3118,238),(3119,291),(3119,293),(3120,304),(3121,305),(3122,306),(3123,307),(3124,308),(3125,309),(3126,310),(3127,311),(3128,312),(3128,336),(3129,313),(3129,350),(3130,314),(3131,315),(3131,351),(3132,325),(3132,328),(3134,502),(3138,334),(3139,338),(3139,339),(3140,340),(3140,341),(3141,344),(3141,345),(3142,346),(3142,347),(3149,351),(3149,354),(3150,351),(3150,356),(3152,358),(3152,359),(3153,361),(3153,370),(3154,363),(3154,369),(3156,350),(3156,371),(3159,376),(3160,377),(3160,379),(3160,384),(3161,378),(3161,380),(3161,383),(3162,388),(3162,389),(3162,390),(3169,392),(3169,393),(3169,394),(3170,395),(3170,396),(3170,397),(3171,398),(3171,399),(3171,400),(3172,401),(3172,402),(3172,403),(3173,404),(3173,405),(3173,406),(3178,351),(3178,421),(3190,411),(3190,412),(3191,413),(3191,414),(3192,415),(3192,416),(3193,417),(3193,418),(3194,419),(3194,420),(3195,353),(3195,424),(3196,425),(3196,426),(3197,427),(3197,428),(3198,429),(3198,430),(3199,431),(3199,432),(3200,433),(3200,434),(3201,435),(3201,436),(3202,437),(3202,438),(3203,439),(3203,440),(3204,441),(3204,442),(3205,443),(3205,444),(3206,445),(3206,446),(3207,447),(3207,448),(3208,449),(3208,450),(3209,451),(3209,452),(3210,453),(3210,454),(3211,455),(3211,456),(3212,457),(3212,458),(3213,459),(3213,460),(3214,461),(3214,462),(3215,463),(3215,464),(3218,466),(3218,467),(3218,468),(3219,469),(3219,470),(3219,471),(3220,474),(3220,475),(3220,476),(3221,477),(3221,478),(3221,479),(3222,480),(3222,481),(3223,482),(3223,483),(3224,484),(3224,485),(3225,486),(3225,487),(3227,503),(3227,505),(3228,506),(3228,507),(3230,508),(3230,509),(3231,510),(3231,511),(3232,512),(3232,513),(3233,514),(3233,515),(3234,516),(3234,517),(3235,518),(3235,519),(3237,521),(3237,522),(3239,524),(3239,525),(3240,526),(3240,527),(3241,528),(3241,529),(3242,530),(3242,531),(3243,532),(3243,533),(3244,534),(3244,535),(3245,536),(3245,537),(3246,538),(3246,539),(3252,540),(3252,541),(3254,543),(3254,544),(3254,545),(3255,547),(3255,548),(3255,571),(3256,550),(3256,551),(3256,572),(3257,553),(3257,554),(3257,573),(3258,556),(3258,557),(3258,574),(3259,559),(3259,560),(3259,575),(3260,561),(3260,562),(3260,563),(3261,565),(3261,576),(3262,566),(3262,567),(3263,568),(3263,569),(3263,570),(3264,577),(3264,578),(3265,579),(3265,580),(3266,581),(3266,582),(3266,591),(3267,583),(3267,584),(3267,592),(3268,585),(3268,586),(3268,593),(3269,587),(3269,588),(3269,594),(3270,589),(3270,590),(3271,595),(3271,596),(3271,597),(3272,598),(3272,599),(3273,600),(3273,601),(3273,602),(3274,603),(3274,604),(3274,605),(3275,606),(3275,607),(3275,608),(3276,609),(3276,610),(3276,611),(3277,612),(3277,613),(3277,614),(3278,615),(3278,616),(3279,617),(3279,618),(3279,619),(3279,628),(3279,629),(3280,620),(3280,621),(3280,622),(3281,623),(3281,624),(3281,625),(3282,626),(3282,825),(3283,630),(3283,631),(3284,632),(3284,633),(3284,634),(3285,635),(3285,940),(3286,638),(3286,639),(3286,640),(3287,641),(3287,642),(3287,643),(3288,644),(3288,645),(3288,646),(3289,647),(3289,648),(3289,649),(3290,650),(3290,651),(3290,652),(3291,653),(3291,654),(3291,655),(3292,656),(3292,657),(3292,658),(3293,659),(3293,660),(3293,661),(3294,662),(3294,663),(3294,664),(3295,665),(3295,666),(3295,667),(3296,668),(3296,669),(3296,670),(3297,671),(3297,672),(3297,673),(3298,674),(3298,675),(3298,676),(3299,677),(3299,678),(3299,679),(3300,680),(3300,681),(3300,682),(3301,683),(3301,684),(3301,685),(3302,686),(3302,687),(3302,688),(3303,689),(3303,690),(3303,691),(3304,692),(3304,693),(3304,694),(3305,695),(3305,696),(3305,697),(3306,698),(3306,699),(3306,700),(3307,701),(3307,702),(3307,703),(3308,704),(3308,705),(3308,706),(3309,707),(3309,708),(3310,709),(3310,710),(3311,711),(3311,712),(3311,713),(3312,714),(3312,715),(3312,716),(3313,717),(3313,1167),(3314,720),(3314,721),(3314,722),(3315,723),(3315,724),(3315,725),(3316,726),(3316,727),(3316,728),(3317,729),(3317,730),(3317,731),(3318,732),(3318,733),(3318,734),(3319,735),(3319,736),(3319,737),(3320,738),(3320,739),(3320,740),(3321,741),(3321,742),(3322,743),(3322,744),(3323,745),(3323,746),(3323,747),(3324,748),(3324,749),(3324,750),(3325,751),(3325,752),(3325,753),(3326,754),(3326,755),(3327,756),(3327,757),(3328,758),(3328,789),(3329,761),(3329,790),(3330,762),(3330,763),(3331,768),(3331,785),(3331,786),(3332,769),(3332,783),(3332,784),(3335,766),(3336,767),(3343,770),(3343,771),(3344,772),(3344,773),(3345,774),(3345,775),(3347,776),(3347,777),(3347,987),(3348,778),(3348,779),(3349,780),(3372,781),(3372,782),(3373,787),(3373,788),(3376,791),(3376,792),(3377,793),(3377,794),(3378,799),(3378,800),(3379,801),(3379,802),(3380,795),(3380,796),(3381,797),(3381,798),(3383,805),(3384,806),(3384,807),(3385,808),(3385,809),(3386,810),(3386,811),(3387,812),(3387,814),(3388,815),(3388,816),(3391,817),(3391,818),(3391,819),(3392,820),(3392,821),(3392,822),(3393,826),(3393,827),(3394,828),(3394,829),(3395,830),(3395,831),(3396,834),(3396,835),(3397,832),(3397,833),(3398,836),(3398,837),(3399,838),(3399,839),(3410,850),(3410,851),(3411,852),(3411,853),(3412,848),(3412,849),(3419,860),(3419,951),(3420,859),(3420,861),(3422,862),(3422,863),(3423,864),(3423,865),(3424,866),(3424,867),(3424,872),(3424,873),(3425,868),(3425,869),(3425,874),(3425,875),(3426,878),(3426,879),(3427,876),(3427,877),(3428,880),(3432,884),(3432,885),(3432,886),(3434,887),(3434,888),(3434,889),(3441,894),(3441,895),(3442,896),(3442,897),(3444,904),(3445,905),(3449,906),(3449,907),(3450,908),(3450,909),(3453,910),(3458,915),(3458,916),(3459,917),(3459,918),(3463,919),(3463,920),(3485,929),(3486,930),(3487,931),(3488,932),(3489,933),(3493,2),(3494,2),(3501,934),(3502,936),(3503,938),(3504,939),(3505,941),(3506,942),(3507,943),(3508,944),(3509,945),(3510,946),(3511,947),(3512,948),(3514,949),(3514,950),(3515,953),(3516,954),(3517,955),(3518,956),(3519,957),(3520,958),(3521,959),(3527,960),(3527,965),(3528,961),(3528,962),(3529,963),(3529,964),(3530,966),(3530,967),(3531,968),(3531,969),(3535,970),(3535,971),(3536,972),(3536,973),(3540,999),(3540,1000),(3541,1001),(8888,9999);
+
+drop table t1;
+
+save_master_pos;
+connection slave;
+sync_with_master;
+
+connection master;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/mysql-wsrep#110-2.test b/mysql-test/suite/rpl/t/mysql-wsrep#110-2.test
new file mode 100644
index 00000000..2b6d0791
--- /dev/null
+++ b/mysql-test/suite/rpl/t/mysql-wsrep#110-2.test
@@ -0,0 +1,44 @@
+#
+# codership/mysql-wsrep/110 - Assertion `table_found' failed in unpack_row() with SAVEPOINT, trigger, error handler
+#
+
+--source include/have_innodb.inc
+--source include/have_binlog_format_row.inc
+--source include/master-slave.inc
+
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY);
+CREATE TABLE t2 (f1 INTEGER PRIMARY KEY);
+CREATE TABLE t3 (f1 INTEGER PRIMARY KEY);
+
+CREATE TRIGGER tr1 AFTER INSERT ON t1 FOR EACH ROW CALL p1(NEW.f1);
+
+DELIMITER |;
+
+CREATE PROCEDURE p1 (IN x INT)
+BEGIN
+ DECLARE EXIT HANDLER FOR SQLEXCEPTION
+ BEGIN
+ ROLLBACK TO event_logging;
+ INSERT t3 VALUES (x);
+ END;
+ SAVEPOINT event_logging;
+
+ INSERT INTO t2 VALUES (x);
+
+ RELEASE SAVEPOINT event_logging;
+END|
+DELIMITER ;|
+
+INSERT INTO t2 VALUES (1);
+INSERT INTO t1 VALUES (1);
+
+
+DROP TABLE t3;
+DROP TABLE t2;
+DROP TABLE t1;
+
+DROP PROCEDURE p1;
+
+sync_slave_with_master;
+--source include/rpl_end.inc
+
diff --git a/mysql-test/suite/rpl/t/parallel_backup.test b/mysql-test/suite/rpl/t/parallel_backup.test
new file mode 100644
index 00000000..4f5ffa9f
--- /dev/null
+++ b/mysql-test/suite/rpl/t/parallel_backup.test
@@ -0,0 +1,107 @@
+--source include/have_innodb.inc
+# The test is not format specific, MIXED is required to optimize testing time
+--source include/have_binlog_format_mixed.inc
+--source include/master-slave.inc
+
+--echo #
+--echo # MDEV-21953: deadlock between BACKUP STAGE BLOCK_COMMIT and parallel
+--echo # replication
+--echo #
+
+--connection master
+CREATE TABLE t1 (a INT PRIMARY KEY) 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 t1 VALUES(100);
+
+--sync_slave_with_master
+call mtr.add_suppression("Deadlock found when trying to get lock");
+call mtr.add_suppression("Commit failed due to failure of an earlier commit");
+
+--source include/stop_slave.inc
+SET @old_parallel_threads= @@GLOBAL.slave_parallel_threads;
+SET @old_parallel_mode = @@GLOBAL.slave_parallel_mode;
+SET @@global.slave_parallel_threads= 2;
+SET @@global.slave_parallel_mode = 'optimistic';
+
+--connection master
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+--save_master_pos
+
+# The plot:
+# Block the 1st of two workers and, at waiting-for-prior-commit by the 2nd,
+# issue BACKUP commands.
+# BLOCK_COMMIT may hang so it is --send.
+# Release the 1st worker to observe a deadlock unless its fixed.
+
+--connect (aux_slave,127.0.0.1,root,,test,$SLAVE_MYPORT,)
+BEGIN;
+# block the 1st worker and wait for the 2nd ready to commit
+INSERT INTO t1 VALUES (1);
+
+--connection slave
+--source include/start_slave.inc
+
+--connection aux_slave
+--let $wait_condition= SELECT COUNT(*) > 0 FROM information_schema.processlist WHERE state = "Waiting for prior transaction to commit"
+--source include/wait_condition.inc
+
+# While the 1st worker is locked out run backup
+--connect (backup_slave,127.0.0.1,root,,test,$SLAVE_MYPORT,)
+BACKUP STAGE START;
+--send BACKUP STAGE BLOCK_COMMIT
+
+# release the 1st work
+--connection aux_slave
+--sleep 1
+ROLLBACK;
+
+--connection backup_slave
+--reap
+BACKUP STAGE END;
+
+--connection slave
+--sync_with_master
+
+--let $diff_tables= master:t1,slave:t1
+--source include/diff_tables.inc
+
+#
+--echo # MDEV-30423: dealock XA COMMIT vs BACKUP
+# Prove XA "COMPLETE" 'xid' does not dealock similary to the normal trx case.
+# The slave binlog group commit leader is blocked by a local trx like in
+# the above normal trx case.
+# [Notice a reuse of t1,aux_conn from above.]
+#
+--let $complete = COMMIT
+--source parallel_backup_xa.inc
+--let $complete = ROLLBACK
+--source parallel_backup_xa.inc
+
+--let $slave_ooo_error = 1
+--let $complete = COMMIT
+--source parallel_backup_xa.inc
+--connection slave
+--source include/start_slave.inc
+--source include/sync_with_master_gtid.inc
+
+--let $slave_ooo_error = 1
+--let $complete = ROLLBACK
+--source parallel_backup_xa.inc
+--connection slave
+--source include/start_slave.inc
+--source include/sync_with_master_gtid.inc
+
+
+# Clean up.
+--connection slave
+--source include/stop_slave.inc
+SET @@global.slave_parallel_threads= @old_parallel_threads;
+SET @@global.slave_parallel_mode = @old_parallel_mode;
+--source include/start_slave.inc
+
+--connection server_1
+DROP TABLE t1;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/parallel_backup_lsu_off-slave.opt b/mysql-test/suite/rpl/t/parallel_backup_lsu_off-slave.opt
new file mode 100644
index 00000000..2f2a9c43
--- /dev/null
+++ b/mysql-test/suite/rpl/t/parallel_backup_lsu_off-slave.opt
@@ -0,0 +1,2 @@
+--log-slave-updates=0
+
diff --git a/mysql-test/suite/rpl/t/parallel_backup_lsu_off.test b/mysql-test/suite/rpl/t/parallel_backup_lsu_off.test
new file mode 100644
index 00000000..8e266307
--- /dev/null
+++ b/mysql-test/suite/rpl/t/parallel_backup_lsu_off.test
@@ -0,0 +1,7 @@
+#
+--echo # Specialized --log-slave-updates = 0 version of parallel_backup test.
+#
+--echo # MDEV-21953: deadlock between BACKUP STAGE BLOCK_COMMIT and parallel
+--echo # MDEV-30423: dealock XA COMMIT vs BACKUP
+--let $rpl_skip_reset_master_and_slave = 1
+--source parallel_backup.test
diff --git a/mysql-test/suite/rpl/t/parallel_backup_slave_binlog_off-slave.opt b/mysql-test/suite/rpl/t/parallel_backup_slave_binlog_off-slave.opt
new file mode 100644
index 00000000..a02b6d05
--- /dev/null
+++ b/mysql-test/suite/rpl/t/parallel_backup_slave_binlog_off-slave.opt
@@ -0,0 +1 @@
+--skip-log-bin \ No newline at end of file
diff --git a/mysql-test/suite/rpl/t/parallel_backup_slave_binlog_off.test b/mysql-test/suite/rpl/t/parallel_backup_slave_binlog_off.test
new file mode 100644
index 00000000..7cefbdb3
--- /dev/null
+++ b/mysql-test/suite/rpl/t/parallel_backup_slave_binlog_off.test
@@ -0,0 +1,7 @@
+#
+--echo # Specialized --skip-log-bin slave version of parallel_backup test.
+#
+--echo # MDEV-21953: deadlock between BACKUP STAGE BLOCK_COMMIT and parallel
+--echo # MDEV-30423: dealock XA COMMIT vs BACKUP
+--let $rpl_server_skip_log_bin= 1
+--source parallel_backup.test
diff --git a/mysql-test/suite/rpl/t/parallel_backup_xa.inc b/mysql-test/suite/rpl/t/parallel_backup_xa.inc
new file mode 100644
index 00000000..2d831199
--- /dev/null
+++ b/mysql-test/suite/rpl/t/parallel_backup_xa.inc
@@ -0,0 +1,79 @@
+# Invoked from parallel_backup.test
+# Parameters:
+# $complete = COMMIT or ROLLBACK
+# $slave_ooo_error = 1 means slave group commit did not succeed
+#
+--let $kind = Normal
+if ($slave_ooo_error)
+{
+ --let $kind = Errored out
+}
+--echo #
+--echo # $kind XA $complete
+
+--connection slave
+--source include/stop_slave.inc
+
+--connection master
+# val_0 is the first value to insert on master in prepared xa
+# val_1 is the next one to insert which is the value to block on slave
+--let $val_0 = `SELECT max(a)+1 FROM t1`
+--let $val_1 = $val_0
+--inc $val_1
+
+--connection aux_slave
+BEGIN;
+--eval INSERT INTO t1 VALUES ($val_1)
+
+--connection master
+XA START '1';
+--eval INSERT INTO t1 VALUES ($val_0)
+XA END '1';
+XA PREPARE '1';
+--connection master1
+--eval INSERT INTO t1 VALUES ($val_1)
+--connection master
+--eval XA $complete '1'
+--source include/save_master_gtid.inc
+
+--connection slave
+if ($slave_ooo_error)
+{
+ SET @sav_innodb_lock_wait_timeout = @@global.innodb_lock_wait_timeout;
+ SET @sav_slave_transaction_retries = @@global.slave_transaction_retries;
+ SET @@global.innodb_lock_wait_timeout =1;
+ SET @@global.slave_transaction_retries=0;
+}
+--source include/start_slave.inc
+--connection aux_slave
+--let $wait_condition= SELECT COUNT(*) = 1 FROM information_schema.processlist WHERE state = "Waiting for prior transaction to commit"
+--source include/wait_condition.inc
+--echo # Xid '1' must be in the output:
+XA RECOVER;
+--connection backup_slave
+ BACKUP STAGE START;
+--send BACKUP STAGE BLOCK_COMMIT
+--connection aux_slave
+ --sleep 1
+ if ($slave_ooo_error)
+ {
+ --let $wait_condition= SELECT COUNT(*) = 0 FROM information_schema.processlist WHERE state = "Waiting for prior transaction to commit"
+ --source include/wait_condition.inc
+ }
+ ROLLBACK;
+--let $wait_condition= SELECT COUNT(*) = 1 FROM information_schema.processlist WHERE state = "Waiting for backup lock"
+--source include/wait_condition.inc
+--connection backup_slave
+ --reap
+ BACKUP STAGE END;
+--connection slave
+if (!$slave_ooo_error)
+{
+ --source include/sync_with_master_gtid.inc
+}
+--source include/stop_slave.inc
+if ($slave_ooo_error)
+{
+ SET @@global.innodb_lock_wait_timeout = @sav_innodb_lock_wait_timeout;
+ SET @@global.slave_transaction_retries= @sav_slave_transaction_retries;
+}
diff --git a/mysql-test/suite/rpl/t/password_expiration.test b/mysql-test/suite/rpl/t/password_expiration.test
new file mode 100644
index 00000000..6934500c
--- /dev/null
+++ b/mysql-test/suite/rpl/t/password_expiration.test
@@ -0,0 +1,53 @@
+#
+# Test a slave connection is properly handled when the replication
+# user has an expired password
+#
+
+--source include/not_embedded.inc
+--source include/have_binlog_format_mixed.inc
+--source include/master-slave.inc
+
+--connection slave
+--source include/stop_slave.inc
+
+--connection master
+create user 'repl_user' password expire;
+grant replication slave on *.* to repl_user;
+flush privileges;
+set global disconnect_on_expired_password=ON;
+
+--connection slave
+--let $master_user= query_get_value(SHOW SLAVE STATUS, Master_User, 1)
+CHANGE MASTER TO MASTER_USER= 'repl_user';
+
+START SLAVE;
+# ER_MUST_CHANGE_PASSWORD_LOGIN
+--let $slave_io_errno= 1862
+--source include/wait_for_slave_io_error.inc
+
+# restart slave
+--source include/stop_slave_sql.inc
+RESET SLAVE;
+
+--connection master
+# force sandbox mode for repl_user
+set global disconnect_on_expired_password=OFF;
+
+--connection slave
+START SLAVE;
+# ER_MUST_CHANGE_PASSWORD
+--let $slave_io_errno= 1820
+--source include/wait_for_slave_io_error.inc
+
+--connection master
+DROP USER 'repl_user';
+set global disconnect_on_expired_password=default;
+
+--connection slave
+--source include/stop_slave_sql.inc
+eval CHANGE MASTER TO MASTER_USER='$master_user';
+RESET SLAVE;
+
+--let $rpl_only_running_threads= 1
+--source include/rpl_end.inc
+
diff --git a/mysql-test/suite/rpl/t/rename.test b/mysql-test/suite/rpl/t/rename.test
new file mode 100644
index 00000000..ac499157
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rename.test
@@ -0,0 +1,33 @@
+--source include/have_binlog_format_mixed.inc
+--source include/master-slave.inc
+
+--echo #
+--echo # MDEV-16229 Replication aborts with ER_VIEW_SELECT_TMPTABLE after
+--echo # half-failed RENAME
+--echo #
+
+CREATE TABLE t1 (a INT);
+CREATE TEMPORARY TABLE t1 (b INT);
+RENAME TABLE t1 TO tmp, tmp TO t1;
+SHOW CREATE TABLE t1;
+--error ER_VIEW_SELECT_TMPTABLE
+CREATE VIEW v AS SELECT * FROM t1;
+
+RENAME TABLE t1 TO tmp, t1 TO t2;
+SHOW CREATE TABLE tmp;
+SHOW CREATE TABLE t2;
+--error ER_VIEW_SELECT_TMPTABLE
+CREATE VIEW v AS SELECT * FROM tmp;
+CREATE VIEW v AS SELECT * FROM t2;
+
+--sync_slave_with_master
+
+# Cleanup
+
+--connection master
+
+DROP VIEW v;
+DROP TABLE tmp;
+DROP TABLE t2;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/replace.test b/mysql-test/suite/rpl/t/replace.test
new file mode 100644
index 00000000..36afda0d
--- /dev/null
+++ b/mysql-test/suite/rpl/t/replace.test
@@ -0,0 +1,24 @@
+#
+# Test of REPLACE with replication
+#
+
+source include/master-slave.inc;
+
+#
+# Test of doing replace on unique key on table with auto_increment
+#
+
+drop table if exists t1;
+CREATE TABLE t1 (pr_id int(10) unsigned NOT NULL AUTO_INCREMENT PRIMARY KEY, pr_page int(11) NOT NULL, pr_type varbinary(60) NOT NULL, test int, UNIQUE KEY pr_pagetype (pr_page,pr_type)) ENGINE=myisam AUTO_INCREMENT=136;
+insert into t1 (pr_page, pr_type, test) values(1,"one",0),(2,"two",0);
+select * from t1;
+replace into t1 (pr_page, pr_type,test) values(1,"one",2);
+select * from t1;
+sync_slave_with_master;
+connection slave;
+select * from t1;
+connection master;
+drop table t1;
+
+# End of 5.5 tests
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_000010-slave.opt b/mysql-test/suite/rpl/t/rpl_000010-slave.opt
new file mode 100644
index 00000000..cbd77ee2
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_000010-slave.opt
@@ -0,0 +1 @@
+--debug-disconnect-slave-event-count=2
diff --git a/mysql-test/suite/rpl/t/rpl_000010.test b/mysql-test/suite/rpl/t/rpl_000010.test
new file mode 100644
index 00000000..9ff2d6c5
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_000010.test
@@ -0,0 +1,22 @@
+# This tests the offset off by 22 mystery bug
+# Must run slave with --disconnect-slave-event-count=1 --master-connect-retry=1
+
+source include/master-slave.inc;
+
+--connection slave
+--source include/stop_slave.inc
+CHANGE MASTER TO MASTER_USE_GTID=NO;
+--source include/start_slave.inc
+--connection master
+
+create table t1 (n int not null auto_increment primary key);
+insert into t1 values(NULL);
+insert into t1 values(2);
+sync_slave_with_master;
+select n from t1;
+connection master;
+drop table t1;
+sync_slave_with_master;
+
+# End of 4.1 tests
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_000011-slave.opt b/mysql-test/suite/rpl/t/rpl_000011-slave.opt
new file mode 100644
index 00000000..7c3d2411
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_000011-slave.opt
@@ -0,0 +1 @@
+--verbose=1
diff --git a/mysql-test/suite/rpl/t/rpl_000011.test b/mysql-test/suite/rpl/t/rpl_000011.test
new file mode 100644
index 00000000..289b79f7
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_000011.test
@@ -0,0 +1,34 @@
+#
+# Test very simply slave replication (to ensure it works at all)
+# In addition, test also:
+# MDEV-5829 STOP SLAVE resets global status variables
+#
+
+source include/master-slave.inc;
+--connection slave
+let $initial_com_insert= query_get_value(show global status like "Com_insert", Value, 1);
+--connection master
+create table t1 (n int);
+insert into t1 values(1);
+sync_slave_with_master;
+let $current_com_insert= query_get_value(show global status like "Com_insert", Value, 1);
+--let $delta_com_insert= `select $current_com_insert - $initial_com_insert from dual`
+--echo # Com_insert = $delta_com_insert
+stop slave;
+let $current_com_insert= query_get_value(show global status like "Com_insert", Value, 1);
+--let $delta_com_insert= `select $current_com_insert - $initial_com_insert from dual`
+--echo # Com_insert = $delta_com_insert
+--source include/wait_for_slave_to_stop.inc
+start slave;
+--source include/wait_for_slave_to_start.inc
+connection master;
+insert into t1 values(2);
+#let slave catch up
+sync_slave_with_master;
+select * from t1;
+connection master;
+drop table t1;
+sync_slave_with_master;
+
+# End of 4.1 tests
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_000013.test b/mysql-test/suite/rpl/t/rpl_000013.test
new file mode 100644
index 00000000..9f1b0666
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_000013.test
@@ -0,0 +1,55 @@
+# This test is to verify that DROP TEMPORARY TABLE
+# is automatically binlogged and sent to slave
+# when a temp table is dropped by disconnection
+# of a master's conection.
+# So it does not apply to row-based, where we neither need
+# nor do this automatic binlogging. And if we run this test
+# in row-based, it hangs waiting for an offset which is never
+# reached (the "sync_with_master 1"), logically.
+
+--source include/have_binlog_format_mixed_or_statement.inc
+source include/master-slave.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
+
+create table t2(n int);
+create temporary table t1 (n int);
+insert into t1 values(1),(2),(3);
+--disable_warnings
+insert into t2 select * from t1;
+--enable_warnings
+connection master1;
+create temporary table t1 (n int);
+insert into t1 values (4),(5);
+--disable_warnings
+insert into t2 select * from t1 as t10;
+--enable_warnings
+save_master_pos;
+disconnect master;
+connection slave;
+#add 1 to catch drop table
+sync_with_master 1;
+connection master1;
+insert into t2 values(6);
+save_master_pos;
+disconnect master1;
+connection slave;
+# same trick to go one more event
+sync_with_master 1;
+select * from t2;
+show status like 'Slave_open_temp_tables';
+#
+# Clean up
+#
+connect (master2,localhost,root,,);
+connection master2;
+
+# We will get a warning for t1 as this is a temporary table that doesn't
+# exist in this connection.
+
+drop table if exists t1,t2;
+
+--source include/rpl_end.inc
+# End of 4.1 tests
diff --git a/mysql-test/suite/rpl/t/rpl_000017.test b/mysql-test/suite/rpl/t/rpl_000017.test
new file mode 100644
index 00000000..893117e6
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_000017.test
@@ -0,0 +1,47 @@
+# ==== Purpose ====
+#
+# Unknown.
+#
+# ==== Notes ====
+#
+# This test uses the -slave.opt file to start the slave with
+# --skip-slave-start.
+
+--source include/not_windows.inc
+
+--let $rpl_skip_start_slave= 1
+--source include/master-slave.inc
+
+--connection slave
+--let $slave_datadir= `SELECT @@datadir`
+
+--remove_file $slave_datadir/master.info
+--write_file $slave_datadir/master.info
+master-bin.000001
+4
+127.0.0.1
+replicate
+aaaaaaaaaaaaaaab
+$MASTER_MYPORT
+1
+0
+EOF
+
+connection master;
+grant replication slave on *.* to replicate@localhost identified by 'aaaaaaaaaaaaaaab';
+grant replication slave on *.* to replicate@127.0.0.1 identified by 'aaaaaaaaaaaaaaab';
+connection slave;
+--source include/start_slave.inc
+
+connection master;
+create table t1(n int);
+insert into t1 values(24);
+sync_slave_with_master;
+select * from t1;
+connection master;
+drop table t1;
+delete from mysql.user where user="replicate";
+
+# End of 4.1 tests
+--source include/rpl_end.inc
+
diff --git a/mysql-test/suite/rpl/t/rpl_15867.test b/mysql-test/suite/rpl/t/rpl_15867.test
new file mode 100644
index 00000000..6de39041
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_15867.test
@@ -0,0 +1,11 @@
+--source include/master-slave.inc
+CREATE TEMPORARY TABLE t (i INT);
+CREATE TABLE t AS SELECT * FROM t;
+
+--sync_slave_with_master
+
+# Cleanup
+--connection master
+DROP TEMPORARY TABLE t;
+DROP TABLE t;
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_15919-slave.opt b/mysql-test/suite/rpl/t/rpl_15919-slave.opt
new file mode 100644
index 00000000..62ab6dad
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_15919-slave.opt
@@ -0,0 +1 @@
+--lower_case_table_names=1
diff --git a/mysql-test/suite/rpl/t/rpl_15919.test b/mysql-test/suite/rpl/t/rpl_15919.test
new file mode 100644
index 00000000..a5b25929
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_15919.test
@@ -0,0 +1,18 @@
+--source include/have_case_sensitive_file_system.inc
+--source include/have_innodb.inc
+--source include/master-slave.inc
+
+--connection master
+create table RPL(a int);
+insert into RPL values(1);
+
+--sync_slave_with_master
+select * from rpl;
+insert into RPL values(3);
+insert into rpl values(4);
+select * from rpl;
+
+--connection master
+drop table RPL;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_EE_err.test b/mysql-test/suite/rpl/t/rpl_EE_err.test
new file mode 100644
index 00000000..b2ca3aac
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_EE_err.test
@@ -0,0 +1,2 @@
+let $engine_type=myisam;
+-- source include/rpl_EE_err.test
diff --git a/mysql-test/suite/rpl/t/rpl_LD_INFILE.test b/mysql-test/suite/rpl/t/rpl_LD_INFILE.test
new file mode 100644
index 00000000..0f02bdcc
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_LD_INFILE.test
@@ -0,0 +1,39 @@
+#############################################################################
+# Original Author: JBM #
+# Original Date: Aug/18/2005 #
+#############################################################################
+# TEST: To test the LOAD DATA INFILE in rbr #
+#############################################################################
+
+# Includes
+-- source include/master-slave.inc
+
+# Begin clean up test section
+--disable_warnings
+connection master;
+DROP TABLE IF EXISTS test.t1;
+--enable_warnings
+
+# Section 1 test
+CREATE TABLE test.t1 (a VARCHAR(255), PRIMARY KEY(a));
+LOAD DATA INFILE '../../std_data/words2.dat' INTO TABLE test.t1;
+DELETE FROM test.t1 WHERE a = 'abashed';
+DELETE FROM test.t1;
+LOAD DATA INFILE '../../std_data/words2.dat' INTO TABLE test.t1;
+
+
+SELECT * FROM test.t1 ORDER BY a DESC;
+save_master_pos;
+sync_slave_with_master;
+connection slave;
+SELECT * FROM test.t1 ORDER BY a DESC;
+
+# Cleanup
+#show binlog events;
+connection master;
+DROP TABLE test.t1;
+sync_slave_with_master;
+
+# End of 5.0 test case
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_alter.test b/mysql-test/suite/rpl/t/rpl_alter.test
new file mode 100644
index 00000000..8b8bcfb3
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_alter.test
@@ -0,0 +1,71 @@
+source include/master-slave.inc;
+create database mysqltest;
+
+create table mysqltest.t1 ( n int);
+alter table mysqltest.t1 add m int;
+insert into mysqltest.t1 values (1,2);
+create table mysqltest.t2 (n int);
+insert into mysqltest.t2 values (45);
+rename table mysqltest.t2 to mysqltest.t3, mysqltest.t1 to mysqltest.t2;
+sync_slave_with_master;
+select * from mysqltest.t2;
+select * from mysqltest.t3;
+connection master;
+drop database mysqltest;
+sync_slave_with_master;
+
+# End of 4.1 tests
+
+connection master;
+use test;
+
+--echo #
+--echo # Test bug where ALTER TABLE MODIFY didn't replicate properly
+--echo #
+
+create table t1 (a int unsigned primary key, b int);
+show create table t1;
+insert into t1 (a) values (1),((1<<32)-1);
+select * from t1;
+alter table t1 modify a bigint;
+show create table t1;
+select * from t1;
+alter table t1 modify a int unsigned;
+show create table t1;
+select * from t1;
+alter table t1 modify a bigint unsigned;
+show create table t1;
+select * from t1;
+sync_slave_with_master;
+use test;
+select * from t1;
+show create table t1;
+connection master;
+#
+create table t2 (a int unsigned auto_increment primary key, b int);
+show create table t2;
+alter table t2 modify a bigint;
+show create table t2;
+alter table t2 modify a bigint auto_increment;
+show create table t2;
+drop table t1,t2;
+
+--echo #
+--echo # MDEV-8432: Slave cannot replicate signed integer-type values
+--echo # with high bit set to 1
+--echo # Test replication when we have int on master and bigint on slave
+--echo #
+
+create table t1 (a int unsigned primary key, b int);
+sync_slave_with_master;
+SET GLOBAL SLAVE_TYPE_CONVERSIONS='ALL_NON_LOSSY';
+alter table t1 modify a bigint unsigned;
+connection master;
+insert into t1 (a) values (1),((1<<32)-1);
+sync_slave_with_master;
+select * from t1;
+SET GLOBAL SLAVE_TYPE_CONVERSIONS='';
+connection master;
+drop table t1;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_alter_db.test b/mysql-test/suite/rpl/t/rpl_alter_db.test
new file mode 100644
index 00000000..f6f07825
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_alter_db.test
@@ -0,0 +1,15 @@
+source include/master-slave.inc;
+
+--echo ==== Verify that alter database does not stop replication ====
+
+create database temp_db;
+use temp_db; # to be different from initial `test' db of mysqltest client
+alter database collate latin1_bin;
+
+sync_slave_with_master;
+
+--echo ==== Clean up ====
+connection master;
+drop database temp_db;
+sync_slave_with_master;
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_alter_extra_persistent.test b/mysql-test/suite/rpl/t/rpl_alter_extra_persistent.test
new file mode 100644
index 00000000..4e604787
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_alter_extra_persistent.test
@@ -0,0 +1,106 @@
+--source include/have_binlog_format_row.inc
+--source include/master-slave.inc
+
+--enable_connect_log
+--connection master
+create table t1(a int primary key);
+insert into t1 values(1);
+insert into t1 values(2);
+insert into t1 values(3);
+insert into t1 values(4);
+
+--sync_slave_with_master
+select * from t1 order by a;
+alter table t1 add column z1 int as(a+1) virtual, add column z2 int as (a+2) persistent;
+select * from t1 order by a;
+
+--connection master
+insert into t1 values(5);
+insert into t1 values(6);
+
+--sync_slave_with_master
+select * from t1 order by a;
+
+
+--echo #UPDATE query
+
+--connection master
+update t1 set a = a+10;
+select * from t1 order by a;
+
+--sync_slave_with_master
+select * from t1 order by a;
+
+--connection master
+update t1 set a = a-10;
+select * from t1 order by a;
+
+--sync_slave_with_master
+select * from t1 order by a;
+
+--echo #DELETE quert
+--connection master
+delete from t1 where a > 2 and a < 4;
+select * from t1 order by a;
+
+--sync_slave_with_master
+select * from t1 order by a;
+
+--echo #REPLACE query
+--connection master
+replace into t1 values(1);
+replace into t1 values(3);
+replace into t1 values(1);
+
+--sync_slave_with_master
+select * from t1 order by a;
+
+--echo #SELECT query
+--connection master
+select * from t1 where a > 2 and a < 4;
+
+--connection slave
+select * from t1 where a > 2 and a < 4;
+
+--echo #UPDATE with SELECT query
+--connection master
+update t1 set a = a + 10 where a > 2 and a < 4;
+select * from t1 order by a;
+
+--sync_slave_with_master
+select * from t1 order by a;
+
+--connection master
+update t1 set a = a - 10 where a = 13;
+select * from t1 order by a;
+
+--sync_slave_with_master
+select * from t1 order by a;
+
+--echo #Break Unique Constraint
+alter table t1 add column z4 int as (a % 6) persistent unique;
+
+--connection master
+
+--echo #entering duplicate value for slave persistent column
+insert into t1 values(7);
+select * from t1 order by a;
+
+--connection slave
+--let $slave_sql_errno= 1062
+--source include/wait_for_slave_sql_error.inc
+select * from t1 order by a;
+alter table t1 drop column z4;
+start slave;
+
+--source include/wait_for_slave_sql_to_start.inc
+
+--connection master
+--sync_slave_with_master
+select * from t1 order by a;
+
+--connection master
+select * from t1 order by a;
+drop table t1;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_alter_instant.test b/mysql-test/suite/rpl/t/rpl_alter_instant.test
new file mode 100644
index 00000000..260f7e92
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_alter_instant.test
@@ -0,0 +1,50 @@
+source include/have_innodb.inc;
+source include/master-slave.inc;
+
+use test;
+create table t1 (id int primary key, c1 int default 10, c2 varchar(20) default 'holiday') engine = innodb;
+
+insert into t1 values(1, 12345, 'abcde'), (2, default, default), (3, 23456, 'xyzab');
+
+set time_zone='+03:00';
+set timestamp = 1;
+alter table t1 add column d1 timestamp not null default current_timestamp;
+
+select * from t1;
+sync_slave_with_master;
+
+connection slave;
+set time_zone='+03:00';
+select * from t1;
+
+connection master;
+alter table t1 add column d2 timestamp not null default current_timestamp, ALGORITHM=copy;
+
+sync_slave_with_master;
+
+connection slave;
+select * from t1;
+
+connection master;
+drop table t1;
+
+
+# datetime
+create table t4 (id int primary key, c2 int);
+insert into t4 values(1,1),(2,2),(3,3);
+set timestamp = 1000;
+alter table t4 add column (c3 datetime default current_timestamp(), c4 timestamp not null default current_timestamp());
+select * from t4;
+alter table t4 add column c5 time not null default current_timestamp();
+alter table t4 add column c6 date not null default current_timestamp();
+
+select * from t4;
+sync_slave_with_master;
+
+connection slave;
+select * from t4;
+
+connection master;
+drop table t4;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_alter_rollback.test b/mysql-test/suite/rpl/t/rpl_alter_rollback.test
new file mode 100644
index 00000000..c24f01ff
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_alter_rollback.test
@@ -0,0 +1,42 @@
+#
+# MENT-662: Lag Free Alter On Slave
+#
+
+--echo #
+--echo # Test verifies that "ROLLBACK ALTER" is written to binary log upon
+--echo #ALTER command execution failure.
+--echo #
+--source include/have_innodb.inc
+--source include/master-slave.inc
+
+--connection master
+--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;
+--error ER_CANT_CREATE_TABLE
+create table t2 (f1 int primary key,
+constraint c1 foreign key (f1) references t1(f1),
+constraint c1 foreign key (f1) references t1(f1)) 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);
+--source include/show_binlog_events.inc
+
+set foreign_key_checks = 0;
+--error ER_DUP_CONSTRAINT_NAME
+alter table t2 add constraint c1 foreign key (f1) references t1(f1);
+--source include/show_binlog_events.inc
+--sync_slave_with_master
+
+--connection master
+drop table t2, t1;
+--sync_slave_with_master
+
+--connection master
+--eval set global binlog_alter_two_phase=$binlog_alter_two_phase;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_auto_increment-master.opt b/mysql-test/suite/rpl/t/rpl_auto_increment-master.opt
new file mode 100644
index 00000000..a8a6af19
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_auto_increment-master.opt
@@ -0,0 +1 @@
+--auto-increment-increment=10 --auto-increment-offset=2
diff --git a/mysql-test/suite/rpl/t/rpl_auto_increment-slave.opt b/mysql-test/suite/rpl/t/rpl_auto_increment-slave.opt
new file mode 100644
index 00000000..79ed6f96
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_auto_increment-slave.opt
@@ -0,0 +1 @@
+--replicate-ignore-table=test.t_ignored1
diff --git a/mysql-test/suite/rpl/t/rpl_auto_increment.test b/mysql-test/suite/rpl/t/rpl_auto_increment.test
new file mode 100644
index 00000000..6d01fdb8
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_auto_increment.test
@@ -0,0 +1,7 @@
+#####################################
+# Wrapper for rpl_auto_increment.test#
+#####################################
+-- source include/have_innodb.inc
+let $engine_type=innodb;
+let $engine_type2=myisam;
+-- source include/rpl_auto_increment.test
diff --git a/mysql-test/suite/rpl/t/rpl_auto_increment_11932.test b/mysql-test/suite/rpl/t/rpl_auto_increment_11932.test
new file mode 100644
index 00000000..1e5f9e53
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_auto_increment_11932.test
@@ -0,0 +1,66 @@
+#
+# Test of auto_increment
+# BUG#11932
+#
+# Bug reported that master and slave get out of sync after TRUNCATE
+# TABLE.
+#
+# Test supplied by Are Casilla
+
+source include/master-slave.inc;
+call mtr.add_suppression('Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT.');
+--disable_warnings
+connection master;
+drop database if exists test1;
+--enable_warnings
+create database test1;
+use test1;
+
+CREATE TABLE `t1` (
+ `id` int(10) unsigned NOT NULL auto_increment,
+ `fname` varchar(100) default NULL,
+ PRIMARY KEY (`id`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=2 ;
+
+INSERT INTO `t1` VALUES (1, 'blablabla');
+
+CREATE TABLE `t2` (
+ `id` int(10) NOT NULL auto_increment,
+ `comment` varchar(255) NOT NULL default '',
+ PRIMARY KEY (`id`)
+) ENGINE=MyISAM AUTO_INCREMENT=3 ;
+
+INSERT INTO `t2` VALUES (1, 'testtest 1');
+INSERT INTO `t2` VALUES (2, 'test 2');
+
+DELIMITER $;
+CREATE PROCEDURE simpleproc3 ()
+ NOT DETERMINISTIC
+ BEGIN
+ INSERT INTO t1 (fname) (SELECT t2.comment FROM t2 WHERE t2.id = '1');
+ INSERT INTO t1 (fname) VALUES('test');
+ END
+ $
+DELIMITER ;$
+
+--disable_warnings
+CALL simpleproc3();
+--enable_warnings
+
+select * from t2;
+
+TRUNCATE TABLE `t1`;
+--disable_warnings
+CALL simpleproc3();
+--enable_warnings
+
+select * from t1;
+
+sync_slave_with_master;
+
+use test1;
+select * from t1;
+
+connection master;
+drop database test1;
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_auto_increment_bug33029.test b/mysql-test/suite/rpl/t/rpl_auto_increment_bug33029.test
new file mode 100644
index 00000000..6f7e0d80
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_auto_increment_bug33029.test
@@ -0,0 +1,60 @@
+# BUG#33029 5.0 to 5.1 replication fails on dup key when inserting
+# using a trig in SP
+
+# For all 5.0 up to 5.0.58 exclusive, and 5.1 up to 5.1.12 exclusive,
+# if one statement in a SP generated AUTO_INCREMENT value by the top
+# statement, all statements after it would be considered generated
+# AUTO_INCREMENT value by the top statement, and a erroneous INSERT_ID
+# value might be associated with these statement, which could cause
+# duplicate entry error and stop the slave.
+
+# Test if the slave can replicate from such a buggy master
+
+# The bug33029-slave-relay-bin.000001 file is the
+# slave-replay-bin.000003 file generated by run the
+# rpl_auto_increment_bug33029.test with clean up statements at the end
+# of the test case removed on a buggy 5.0 server
+
+--let $rpl_skip_start_slave= 1
+--source include/master-slave.inc
+
+--echo ==== Initialize ====
+--connection slave
+
+# The binlog we read does funny things with triggers and causes this warning.
+--disable_query_log
+CALL mtr.add_suppression('Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT');
+--enable_query_log
+
+# Need to restore this at the end; CHANGE MASTER modifies it (see the
+# manual for CHANGE MASTER).
+SET @old_relay_log_purge= @@global.relay_log_purge;
+
+# the relay log contains create t1, t2 tables and load data infile
+--let $fake_relay_log = $MYSQL_TEST_DIR/std_data/bug33029-slave-relay-bin.000001
+--source include/setup_fake_relay_log.inc
+
+--echo ==== Test ====
+start slave sql_thread;
+--let $slave_param= Exec_Master_Log_Pos
+--let $slave_param_value= 3776
+--source include/wait_for_slave_param.inc
+
+
+echo # Result on slave;
+SELECT * FROM t1;
+SELECT * FROM t2;
+
+--echo ==== Clean up ====
+
+stop slave sql_thread;
+--source include/cleanup_fake_relay_log.inc
+
+DROP TABLE t1, t2;
+DROP PROCEDURE p1;
+DROP PROCEDURE p2;
+DROP FUNCTION f1;
+
+SET @@global.relay_log_purge= @old_relay_log_purge;
+--let $rpl_only_running_threads= 1
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_auto_increment_bug45679.test b/mysql-test/suite/rpl/t/rpl_auto_increment_bug45679.test
new file mode 100644
index 00000000..25bfa134
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_auto_increment_bug45679.test
@@ -0,0 +1,64 @@
+# Test of auto-increment.
+#
+# BUG#11754117-45670
+# Multipart primary key with the autoincrement part not first in it
+# is replication unsafe.
+#
+
+source include/have_binlog_format_mixed.inc;
+source include/have_innodb.inc;
+source include/master-slave.inc;
+
+call mtr.add_suppression('Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT.');
+
+--connection master
+create table tm (b int auto_increment, a int, primary key (a,b)) engine= myisam;
+--error ER_WRONG_AUTO_KEY
+create table ti (b int auto_increment, a int, primary key (a,b)) engine= innodb;
+create table ti (b int auto_increment, a int, primary key (b,a)) engine= innodb;
+
+set @@binlog_format=statement;
+--echo *** autoincrement field is not the first in PK warning must be there: ***
+insert into tm set b=null, a=1;
+show warnings;
+--echo *** no warning when autoincrement is the first in PK
+insert into ti set b=null, a=1;
+show warnings;
+
+delimiter //;
+create function multi_part_pk_with_autoinc (arg int)
+returns int
+begin
+ insert into tm set b=null, a=arg;
+ return arg;
+end//
+delimiter ;//
+
+--disable_ps2_protocol
+select multi_part_pk_with_autoinc (3);
+--enable_ps2_protocol
+--echo *** autoincrement field is not the first in PK warning must be there: ***
+show warnings;
+
+set @@binlog_format=mixed;
+insert into tm set b=null, a=2;
+
+sync_slave_with_master;
+
+if (`select count(*) <> 3 from tm`)
+{
+ --echo Wrong result from SELECT on the slave side.
+ select * from tm;
+ --die
+}
+
+# cleanup
+
+--connection master
+
+drop table tm, ti;
+drop function multi_part_pk_with_autoinc;
+
+sync_slave_with_master;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_auto_increment_update_failure.test b/mysql-test/suite/rpl/t/rpl_auto_increment_update_failure.test
new file mode 100644
index 00000000..82db8f08
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_auto_increment_update_failure.test
@@ -0,0 +1,211 @@
+#
+# Bug45677
+# This test verifies the following two properties:
+# P1) insert/update in an autoinc column causes statement to
+# be logged in row format if binlog_format=mixed.
+# P2) if binlog_format=mixed, and a trigger or function contains
+# two or more inserts/updates in a table that has an autoinc
+# column, then the slave should not go out of sync, even if
+# there are concurrent transactions.
+#
+# Property (P1) is tested by executing an insert and an update on
+# a table that has an autoinc column, and verifying that these
+# statements result in row events in the binlog.
+# Property (P2) is tested by setting up the test scenario and
+# verifying that the tables are identical on master and slave.
+#
+
+source include/have_binlog_format_mixed.inc;
+source include/have_innodb.inc;
+source include/master-slave.inc;
+
+--echo # Test case1: INVOKES A TRIGGER with after insert action
+let $trigger_action = after insert;
+source include/rpl_auto_increment_invoke_trigger.test;
+
+--echo # Test case2: INVOKES A TRIGGER with before insert action
+let $trigger_action = before insert;
+source include/rpl_auto_increment_invoke_trigger.test;
+
+--echo # Test case3: INVOKES A TRIGGER with after update action
+let $trigger_action = after update;
+source include/rpl_auto_increment_invoke_trigger.test;
+
+--echo # Test case4: INVOKES A TRIGGER with before update action
+let $trigger_action = before update;
+source include/rpl_auto_increment_invoke_trigger.test;
+
+--echo # Test case5: INVOKES A TRIGGER with after delete action
+let $trigger_action = after delete;
+source include/rpl_auto_increment_invoke_trigger.test;
+
+--echo # Test case6: INVOKES A TRIGGER with before delete action
+let $trigger_action = before delete;
+source include/rpl_auto_increment_invoke_trigger.test;
+
+--echo # Test case7: CALLS A FUNCTION which INVOKES A TRIGGER with after insert action
+let $insert_action = after insert;
+source include/rpl_autoinc_func_invokes_trigger.test;
+
+--echo # Test case8: CALLS A FUNCTION which INVOKES A TRIGGER with before insert action
+let $insert_action = before insert;
+source include/rpl_autoinc_func_invokes_trigger.test;
+
+--echo # Test case9: INSERT DATA INTO VIEW WHICH INVOKES TRIGGERS with after insert action
+let $insert_action = after insert;
+source include/rpl_auto_increment_insert_view.test;
+
+--echo # Test case10: INSERT DATA INTO VIEW WHICH INVOKES TRIGGERS with before insert action
+let $insert_action = before insert;
+source include/rpl_auto_increment_insert_view.test;
+
+--echo # Test case11: INVOKES A FUNCTION TO INSERT TWO OR MORE VALUES INTO A TABLE WITH AUTOINC COLUMN
+connection master;
+create table t1(a int) engine=innodb;
+create table t2(i1 int not null auto_increment, a int, primary key(i1)) engine=innodb;
+delimiter //;
+CREATE FUNCTION f1_two_inserts() RETURNS INTEGER
+BEGIN
+ INSERT INTO t2(a) values(2);
+ INSERT INTO t2(a) values(2);
+ RETURN 1;
+END//
+delimiter ;//
+begin;
+insert into t1(a) values(f1_two_inserts());
+
+connection master1;
+#The default autocommit is set to 1, so the statement is auto committed
+insert into t2(a) values(4),(5);
+
+connection master;
+commit;
+insert into t1(a) values(f1_two_inserts());
+commit;
+
+connection master;
+--echo #Test result for INVOKES A FUNCTION TO INSERT TWO OR MORE VALUES on master
+select * from t2 ORDER BY i1;
+
+sync_slave_with_master;
+connection slave;
+--echo #Test result for INVOKES A FUNCTION TO INSERT TWO OR MORE VALUES on slave
+select * from t2 ORDER BY i1;
+
+connection master;
+drop table t1;
+drop table t2;
+drop function f1_two_inserts;
+sync_slave_with_master;
+
+--echo # Test case12: INVOKES A FUNCTION TO UPDATE TWO OR MORE VALUES OF A TABLE WITH AUTOINC COLUMN
+connection master;
+create table t1(a int) engine=innodb;
+create table t2(i1 int not null auto_increment, a int, b int, primary key(i1)) engine=innodb;
+delimiter //;
+CREATE FUNCTION f1_two_updates() RETURNS INTEGER
+BEGIN
+ update t2 set a = a + 5 where b = 1;
+ update t2 set a = a + 5 where b = 2;
+ update t2 set a = a + 5 where b = 3;
+ update t2 set a = a + 5 where b = 4;
+ RETURN 1;
+END//
+delimiter ;//
+
+connection master1;
+#The default autocommit is set to 1, so the statement is auto committed
+insert into t2(a,b) values(1,1);
+insert into t2(a,b) values(2,2);
+insert into t2(a,b) values(3,3);
+insert into t2(a,b) values(4,4);
+insert into t1(a) values(f1_two_updates());
+
+connection master;
+begin;
+insert into t1(a) values(f1_two_updates());
+commit;
+
+connection master;
+--echo #Test result for INVOKES A FUNCTION TO UPDATE TWO OR MORE VALUES on master
+select * from t2 ORDER BY i1;
+
+sync_slave_with_master;
+connection slave;
+--echo #Test result for INVOKES A FUNCTION TO UPDATE TWO OR MORE VALUES on slave
+select * from t2 ORDER BY i1;
+
+connection master;
+drop table t1;
+drop table t2;
+drop function f1_two_updates;
+sync_slave_with_master;
+
+--echo # Test case13: UPDATE MORE THAN ONE TABLES ON TOP-STATEMENT
+connection master;
+create table t1(i1 int not null auto_increment, a int, b int, primary key(i1)) engine=innodb;
+create table t2(i1 int not null auto_increment, a int, b int, primary key(i1)) engine=innodb;
+begin;
+let $binlog_start= query_get_value(SHOW MASTER STATUS, Position, 1);
+insert into t1(a,b) values(1,1),(2,2);
+insert into t2(a,b) values(1,1),(2,2);
+update t1,t2 set t1.a=t1.a+5, t2.a=t2.a+5 where t1.b=t2.b;
+insert into t1(a,b) values(3,3);
+insert into t2(a,b) values(3,3);
+commit;
+--echo # To verify if it works fine when these statements are not be marked as unsafe
+source include/show_binlog_events.inc;
+
+sync_slave_with_master;
+--echo #Test if the results are consistent on master and slave
+--echo #for 'UPDATE MORE THAN ONE TABLES ON TOP-STATEMENT'
+let $diff_tables= master:t1, slave:t1;
+source include/diff_tables.inc;
+let $diff_tables= master:t2, slave:t2;
+source include/diff_tables.inc;
+
+connection master;
+drop table t1;
+drop table t2;
+sync_slave_with_master;
+
+--echo # Test case14: INSERT DATA INTO VIEW WHICH INVOLVED MORE THAN ONE TABLES
+connection master;
+CREATE TABLE t1(i1 int not null auto_increment, c1 INT, primary key(i1)) engine=innodb;
+CREATE TABLE t2(i1 int not null auto_increment, c2 INT, primary key(i1)) engine=innodb;
+let $binlog_start= query_get_value(SHOW MASTER STATUS, Position, 1);
+begin;
+INSERT INTO t1(c1) VALUES (11), (12);
+INSERT INTO t2(c2) VALUES (13), (14);
+
+CREATE VIEW v15 AS SELECT c1, c2 FROM t1, t2;
+
+INSERT INTO v15(c1) VALUES (15),(16);
+INSERT INTO v15(c2) VALUES (17),(18);
+
+connection master1;
+INSERT INTO v15(c1) VALUES (19),(20);
+INSERT INTO v15(c2) VALUES (21),(22);
+
+connection master;
+INSERT INTO v15(c1) VALUES (23), (24);
+INSERT INTO v15(c2) VALUES (25), (26);
+commit;
+--echo # To verify if it works fine when these statements are not be marked as unsafe
+source include/show_binlog_events.inc;
+
+sync_slave_with_master;
+--echo #Test if the results are consistent on master and slave
+--echo #for 'INSERT DATA INTO VIEW WHICH INVOLVED MORE THAN ONE TABLES'
+let $diff_tables= master:t1, slave:t1;
+source include/diff_tables.inc;
+let $diff_tables= master:t2, slave:t2;
+source include/diff_tables.inc;
+
+connection master;
+drop table t1;
+drop table t2;
+drop view v15;
+sync_slave_with_master;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_autogen_query_multi_byte_char.test b/mysql-test/suite/rpl/t/rpl_autogen_query_multi_byte_char.test
new file mode 100644
index 00000000..a93fcbac
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_autogen_query_multi_byte_char.test
@@ -0,0 +1,87 @@
+###############################################################################
+# Bug#21205695 DROP TABLE MAY CAUSE SLAVES TO BREAK
+#
+# Problem:
+# ========
+# 1) Drop table queries are re-generated by server
+# before writing the events(queries) into binlog
+# for various reasons. If table name/db name contains
+# a non regular characters (like latin characters),
+# the generated query is wrong. Hence it breaks the
+# replication.
+# 2) In the edge case, when table name contains
+# 64 latin characters (latin takes 2 bytes), server is
+# throwing an assert (M_TBLLEN < 128)
+#
+# 3) In the edge case, when db name contains 64 latin
+# characters, binlog contents are interpreted wrongly
+# which is leading to replication issues.
+#
+###############################################################################
+
+--source include/not_windows.inc
+--source include/master-slave.inc
+
+--let iter=1
+# Change iteration to 4 after fixing Bug #22280214
+while ($iter <= 2)
+{
+ --connection master
+ if ($iter == 1)
+ {
+ --echo Test case 1:- table name with one character latin name.
+ --let $tblname= REPEAT(CHAR(131),1)
+ }
+ if ($iter == 2)
+ {
+ --echo Test case 2:- table name and database names with one character latin name.
+ --let $tblname= REPEAT(CHAR(131),1),"`.`",REPEAT(CHAR(131),1)
+ --eval SET @s:=CONCAT("CREATE DATABASE `",REPEAT(CHAR(131),1),"`")
+ PREPARE STMT FROM @s; EXECUTE stmt;
+ }
+ # After fixing Bug #22280214 DATADIR LOCATION IS LIMITING
+ # IDENTIFIER MAX LENGTH, the following two tests (iter 3 and 4) can be
+ # uncommented.
+ #if ($iter == 3)
+ #{
+ # --echo Test case 3:- table name and database names with 64 latin characters name.
+ # --let $tblname= REPEAT(CHAR(131),64),"`.`", REPEAT(CHAR(131),64)
+ # --eval SET @s:=CONCAT("CREATE DATABASE `",REPEAT(CHAR(131),64),"`")
+ # PREPARE STMT FROM @s; EXECUTE stmt;
+ #}
+ #if ($iter == 4)
+ #{
+ # --echo Test case 4:- table name and database names with 64 Euro(€) characters.
+ # --let $tblname= REPEAT(CHAR(226,130,172),64),"`.`", REPEAT(CHAR(226,130,172),64)
+ # --eval SET @s:=CONCAT("CREATE DATABASE `",REPEAT(CHAR(226,130,172),64),"`")
+ # PREPARE STMT FROM @s; EXECUTE stmt;
+ #}
+ --eval SET @s:=CONCAT("CREATE TABLE `",$tblname,"` (a INT)")
+ PREPARE STMT FROM @s; EXECUTE stmt;
+ --eval SET @s:=CONCAT("INSERT INTO `",$tblname,"` VALUES (1)")
+ PREPARE STMT FROM @s; EXECUTE stmt;
+ --eval SET @s:=CONCAT("DROP TABLE `",$tblname, "`")
+ PREPARE STMT FROM @s; EXECUTE stmt;
+ if ($iter == 2)
+ {
+ --eval SET @s:=CONCAT("DROP DATABASE `",REPEAT(CHAR(131),1),"`")
+ PREPARE STMT FROM @s; EXECUTE stmt;
+ }
+ # After fixing Bug #22280214 DATADIR LOCATION IS LIMITING
+ # IDENTIFIER MAX LENGTH, the following two tests (iter 3 and 4) can be
+ # uncommented.
+ #if ($iter == 3)
+ #{
+ # --eval SET @s:=CONCAT("DROP DATABASE `",REPEAT(CHAR(131),64),"`")
+ # PREPARE STMT FROM @s; EXECUTE stmt;
+ #}
+ #if ($iter == 4)
+ #{
+ # --eval SET @s:=CONCAT("DROP DATABASE `",REPEAT(CHAR(226,130,172),64),"`")
+ # PREPARE STMT FROM @s; EXECUTE stmt;
+ #}
+ --sync_slave_with_master
+ --inc $iter
+}
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_begin_commit_rollback-master.opt b/mysql-test/suite/rpl/t/rpl_begin_commit_rollback-master.opt
new file mode 100644
index 00000000..a8de78ed
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_begin_commit_rollback-master.opt
@@ -0,0 +1 @@
+--loose-innodb --binlog-ignore-db=db2
diff --git a/mysql-test/suite/rpl/t/rpl_begin_commit_rollback-slave.opt b/mysql-test/suite/rpl/t/rpl_begin_commit_rollback-slave.opt
new file mode 100644
index 00000000..264b1728
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_begin_commit_rollback-slave.opt
@@ -0,0 +1 @@
+--loose-innodb --replicate-do-db=db1
diff --git a/mysql-test/suite/rpl/t/rpl_begin_commit_rollback.test b/mysql-test/suite/rpl/t/rpl_begin_commit_rollback.test
new file mode 100644
index 00000000..659f074e
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_begin_commit_rollback.test
@@ -0,0 +1,173 @@
+source include/have_innodb.inc;
+source include/have_binlog_format_statement.inc;
+source include/master-slave.inc;
+
+connection slave;
+call mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT");
+
+connection master;
+call mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT");
+
+SET @@session.binlog_direct_non_transactional_updates= FALSE;
+
+disable_warnings;
+DROP DATABASE IF EXISTS db1;
+DROP DATABASE IF EXISTS db2;
+enable_warnings;
+
+CREATE DATABASE db1;
+CREATE DATABASE db2;
+
+use db1;
+
+CREATE TABLE db1.t1 (a INT) ENGINE=InnoDB;
+CREATE TABLE db1.t2 (s CHAR(255)) ENGINE=MyISAM;
+
+sync_slave_with_master;
+source include/stop_slave.inc;
+connection master;
+
+DELIMITER //;
+CREATE PROCEDURE db1.p1 ()
+BEGIN
+ INSERT INTO t1 VALUES (1);
+ INSERT INTO t1 VALUES (2);
+ INSERT INTO t1 VALUES (3);
+ INSERT INTO t1 VALUES (4);
+ INSERT INTO t1 VALUES (5);
+END//
+
+CREATE PROCEDURE db1.p2 ()
+BEGIN
+ INSERT INTO t1 VALUES (6);
+ INSERT INTO t1 VALUES (7);
+ INSERT INTO t1 VALUES (8);
+ INSERT INTO t1 VALUES (9);
+ INSERT INTO t1 VALUES (10);
+ INSERT INTO t2 VALUES ('executed db1.p2()');
+END//
+DELIMITER ;//
+
+INSERT INTO db1.t2 VALUES ('before call db1.p1()');
+
+# Note: the master_log_pos is set to be the position of the BEGIN + 1,
+# so before fix of BUG#43263 if the BEGIN is ignored, then all the
+# INSERTS in p1 will be replicated in AUTOCOMMIT=1 mode and the slave
+# SQL thread will stop right before the first INSERT. After fix of
+# BUG#43263, BEGIN will not be ignored by the replication db rules,
+# and then the whole transaction will be executed before slave SQL
+# stop.
+let $master_pos= query_get_value(SHOW MASTER STATUS, Position, 1);
+let $master_pos= `SELECT $master_pos + 1`;
+
+use test;
+BEGIN;
+CALL db1.p1();
+COMMIT;
+
+# The position where the following START SLAVE UNTIL will stop at
+let $master_end_trans_pos= query_get_value(SHOW MASTER STATUS, Position, 1);
+
+INSERT INTO db1.t2 VALUES ('after call db1.p1()');
+SELECT * FROM db1.t1;
+SELECT * FROM db1.t2;
+
+connection slave;
+
+replace_result $master_pos MASTER_POS;
+eval start slave until master_log_file='master-bin.000001', master_log_pos=$master_pos;
+source include/wait_for_slave_sql_to_stop.inc;
+let $slave_sql_stop_pos= query_get_value(SHOW SLAVE STATUS, Exec_Master_Log_Pos, 1);
+let $result= query_get_value(SELECT $slave_sql_stop_pos - $master_end_trans_pos as result, result, 1);
+
+--echo #
+--echo # If we got non-zero here, then we're suffering BUG#43263
+--echo #
+eval SELECT $result as 'Must be 0';
+SELECT * from db1.t1;
+SELECT * from db1.t2;
+
+connection master;
+
+INSERT INTO db1.t2 VALUES ('before call db1.p2()');
+
+# See comments above.
+let $master_pos= query_get_value(SHOW MASTER STATUS, Position, 1);
+let $master_pos= `SELECT $master_pos + 1`;
+
+BEGIN;
+CALL db1.p2();
+disable_warnings;
+ROLLBACK;
+enable_warnings;
+let $master_end_trans_pos= query_get_value(SHOW MASTER STATUS, Position, 1);
+
+INSERT INTO db1.t2 VALUES ('after call db1.p2()');
+SELECT * FROM db1.t1;
+SELECT * FROM db1.t2;
+
+connection slave;
+
+replace_result $master_pos MASTER_POS;
+eval start slave until master_log_file='master-bin.000001', master_log_pos=$master_pos;
+source include/wait_for_slave_sql_to_stop.inc;
+
+let $slave_sql_stop_pos= query_get_value(SHOW SLAVE STATUS, Exec_Master_Log_Pos, 1);
+let $result= query_get_value(SELECT $slave_sql_stop_pos - $master_end_trans_pos as result, result, 1);
+
+--echo #
+--echo # If we got non-zero here, then we're suffering BUG#43263
+--echo #
+eval SELECT $result as 'Must be 0';
+SELECT * from db1.t1;
+SELECT * from db1.t2;
+
+START SLAVE;
+source include/wait_for_slave_sql_to_start.inc;
+
+--echo #
+--echo # SAVEPOINT and ROLLBACK TO have the same problem in BUG#43263
+--echo # This was reported by BUG#50407
+connection master;
+let $binlog_start=query_get_value(SHOW MASTER STATUS, Position, 1);
+
+BEGIN;
+INSERT INTO db1.t1 VALUES(20);
+
+--echo #
+--echo # Verify whether this statement is binlogged correctly
+/*comment*/ SAVEPOINT has_comment;
+USE db1;
+INSERT INTO db1.t1 VALUES(30);
+INSERT INTO db1.t2 VALUES("in savepoint has_comment");
+USE db2;
+SavePoint mixed_cases;
+USE db1;
+INSERT INTO db1.t2 VALUES("in savepoint mixed_cases");
+INSERT INTO db1.t1 VALUES(40);
+USE db2;
+ROLLBACK TO mixed_cases;
+ROLLBACK TO has_comment;
+USE db1;
+INSERT INTO db1.t2 VALUES("after rollback to");
+INSERT INTO db1.t1 VALUES(50);
+USE db2;
+COMMIT;
+source include/show_binlog_events.inc;
+sync_slave_with_master;
+
+--echo #
+--echo # Verify INSERT statements in savepoints are executed, for MyISAM table
+--echo # is not effected by ROLLBACK TO
+SELECT * FROM db1.t2 WHERE s LIKE '% savepoint %';
+--echo #
+--echo # Verify INSERT statements on the Innodb table are rolled back;
+SELECT * FROM db1.t1 WHERE a IN (30, 40);
+
+--echo #
+--echo # Clean up
+--echo #
+connection master;
+DROP DATABASE db1;
+DROP DATABASE db2;
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_binlog_compress.test b/mysql-test/suite/rpl/t/rpl_binlog_compress.test
new file mode 100644
index 00000000..ef1e4508
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_binlog_compress.test
@@ -0,0 +1,61 @@
+#
+# Test of compressed binlog with replication
+#
+
+source include/master-slave.inc;
+
+set @old_log_bin_compress=@@log_bin_compress;
+set @old_log_bin_compress_min_len=@@log_bin_compress_min_len;
+set @old_binlog_format=@@binlog_format;
+set @old_binlog_row_image=@@binlog_row_image;
+
+set global log_bin_compress=on;
+set global log_bin_compress_min_len=10;
+
+drop table if exists t1;
+CREATE TABLE t1 (pr_id int(10) unsigned NOT NULL AUTO_INCREMENT PRIMARY KEY, pr_page int(11) NOT NULL, pr_type varbinary(60) NOT NULL, test int, UNIQUE KEY pr_pagetype (pr_page,pr_type)) ENGINE=myisam AUTO_INCREMENT=136;
+
+set binlog_format=statement;
+insert into t1 (pr_page, pr_type, test) values(1,"one",0),(2,"two",0);
+replace into t1 (pr_page, pr_type,test) values(1,"one",2);
+update t1 set test=test+1 where pr_page > 1;
+delete from t1 where test=1;
+
+select * from t1;
+sync_slave_with_master;
+connection slave;
+select * from t1;
+connection master;
+
+
+set binlog_format=row;
+insert into t1 (pr_page, pr_type, test) values(3,"three",0),(4,"four",4),(5, "five", 0);
+replace into t1 (pr_page, pr_type,test) values(3,"one",2);
+update t1 set test=test+1 where pr_page > 3;
+delete from t1 where test=1;
+
+select * from t1;
+sync_slave_with_master;
+connection slave;
+select * from t1;
+connection master;
+
+
+set binlog_row_image=minimal;
+insert into t1 (pr_page, pr_type, test) values(6,"six",0),(7,"seven",7),(8, "eight", 0);
+replace into t1 (pr_page, pr_type,test) values(6,"six",2);
+update t1 set test=test+1 where pr_page > 6;
+delete from t1 where test=1;
+
+select * from t1;
+sync_slave_with_master;
+connection slave;
+select * from t1;
+connection master;
+drop table t1;
+
+set global log_bin_compress=@old_log_bin_compress;
+set global log_bin_compress_min_len=@old_log_bin_compress_min_len;
+set binlog_format=@old_binlog_format;
+set binlog_row_image=@old_binlog_row_image;
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_binlog_corruption.test b/mysql-test/suite/rpl/t/rpl_binlog_corruption.test
new file mode 100644
index 00000000..66b0c80f
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_binlog_corruption.test
@@ -0,0 +1,50 @@
+# ==== Purpose ====
+#
+# Verify that the slave stops gracefully when reading a relay log with
+# corrupted data.
+#
+# ==== Implementation ====
+#
+# Setup "fake replication" where the slave only starts the SQL thread,
+# not the IO thread, and reads from an existing relay log that has
+# been prepared so that it contains the error. This requires some
+# extra server options: see the -master.opt file.
+#
+# ==== Related bugs ====
+#
+# BUG#31793: log event corruption causes crash
+# BUG#40482: server/mysqlbinlog crashes when reading invalid Incident_log_event
+
+--source include/master-slave.inc
+
+# BUG#40482 only manifested itself in debug-compiled binaries.
+-- source include/have_debug.inc
+
+--connection slave
+call mtr.add_suppression('Found invalid event in binary log');
+call mtr.add_suppression('Slave SQL.*Relay log read failure: Could not parse relay log event entry.* 1594');
+
+#
+# BUG#40482: server/mysqlbinlog crashes when reading invalid Incident_log_event
+#
+# The relay log contains an Incident_log_event with a non-existing
+# incident number.
+
+--echo ==== Initialize ====
+--source include/stop_slave.inc
+RESET SLAVE;
+
+let $fake_relay_log= $MYSQL_TEST_DIR/std_data/bug40482-bin.000001;
+source include/setup_fake_relay_log.inc;
+
+--echo ==== Test ====
+START SLAVE SQL_THREAD;
+let $slave_sql_errno= 1594; # ER_SLAVE_RELAY_LOG_READ_FAILURE
+source include/wait_for_slave_sql_error.inc;
+let $error= query_get_value(SHOW SLAVE STATUS, Last_SQL_Error, 1);
+--echo Last_SQL_Error = $error
+
+--echo ==== Clean up ====
+source include/cleanup_fake_relay_log.inc;
+--let $rpl_only_running_threads= 1
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_binlog_dump_slave_gtid_state_info.test b/mysql-test/suite/rpl/t/rpl_binlog_dump_slave_gtid_state_info.test
new file mode 100644
index 00000000..bba41295
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_binlog_dump_slave_gtid_state_info.test
@@ -0,0 +1,121 @@
+# ==== Purpose ====
+#
+# Test verifies that Start binlog_dump message will report GTID position
+# requested by slave when log_warnings > 1.
+#
+# ==== Implementation ====
+#
+# Steps:
+# 0 - Have LOG_WARNINGS=2
+# 1 - On a fresh slave server which has not replicated any GTIDs execute
+# "CHANGE MASTER TO MASTER_USE_GTID=slave_pos;" command. Start the
+# slave.
+# 2 - In Master error log verify that pattern "using_gtid(1), gtid('')" is
+# present.
+# 3 - On slave server do STOP SLAVE and execute "CHANGE MASTER TO
+# MASTER_USE_GTID=no;" command. Start the slave threads.
+# 4 - In Master error log verify that pattern "using_gtid(0), gtid('')" is
+# present.
+# 5- Execute a DDL and DML on master server. This will generated two GTIDs
+# on the master server ('0-1-2'). Sync the slave server with master.
+# 6 - On slave do STOP SLAVE and execute "CHANGE MASTER TO
+# MASTER_USE_GTID=slave_pos;" command. Start slave threads.
+# 7 - In Master error verify that pattern "using_gtid(1), gtid('0-1-2')" is
+# present.
+# 8 - On Master change domain ID to 10 and execute a DML operation. It will
+# generate a GTID 10-1-1.
+# 9 - On slave do STOP SLAVE and execute "CHANGE MASTER TO
+# MASTER_USE_GTID=slave_pos;" command. Start slave threads.
+# 10 -In Master error verify that pattern "using_gtid(1),
+# gtid('0-1-2,10-1-1')" is present.
+#
+# ==== References ====
+#
+# MDEV-20428: "Start binlog_dump" message doesn't indicate GTID position
+#
+
+--source include/have_binlog_format_mixed.inc
+--source include/have_innodb.inc
+--source include/master-slave.inc
+
+--connection master
+SET GLOBAL LOG_WARNINGS=2;
+
+--connection slave
+--source include/stop_slave.inc
+CHANGE MASTER TO MASTER_USE_GTID=slave_pos;
+--source include/start_slave.inc
+
+--connection master
+# 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;
+}
+--echo "Test Case 1: Start binlog_dump to slave_server(#), pos(master-bin.000001, ###), using_gtid(1), gtid('')"
+--let SEARCH_FILE=$log_error_
+--let SEARCH_RANGE=-50000
+--let SEARCH_PATTERN=using_gtid\(1\), gtid\(\'\'\).*
+--source include/search_pattern_in_file.inc
+
+--connection slave
+--source include/stop_slave.inc
+CHANGE MASTER TO MASTER_USE_GTID=no;
+--source include/start_slave.inc
+
+--connection master
+--echo "Test Case 2: Start binlog_dump to slave_server(#), pos(master-bin.000001, ###), using_gtid(0), gtid('')"
+--let SEARCH_FILE=$log_error_
+--let SEARCH_RANGE=-50000
+--let SEARCH_PATTERN=using_gtid\(0\), gtid\(\'\'\).*
+--source include/search_pattern_in_file.inc
+CREATE TABLE t (f INT) ENGINE=INNODB;
+INSERT INTO t VALUES(10);
+save_master_pos;
+
+--connection slave
+sync_with_master;
+
+--connection slave
+--source include/stop_slave.inc
+CHANGE MASTER TO MASTER_USE_GTID=slave_pos;
+--source include/start_slave.inc
+
+--connection master
+--echo "Test Case 3: Start binlog_dump to slave_server(#), pos(master-bin.000001, ###), using_gtid(1), gtid('0-1-2')"
+--let SEARCH_FILE=$log_error_
+--let SEARCH_RANGE=-50000
+--let SEARCH_PATTERN=using_gtid\(1\), gtid\(\'0-1-2\'\).*
+--source include/search_pattern_in_file.inc
+SET @@SESSION.gtid_domain_id=10;
+INSERT INTO t VALUES(20);
+save_master_pos;
+
+--connection slave
+sync_with_master;
+
+--connection slave
+--source include/stop_slave.inc
+CHANGE MASTER TO MASTER_USE_GTID=slave_pos;
+--source include/start_slave.inc
+
+--connection master
+--echo "Test Case 4: Start binlog_dump to slave_server(#), pos(master-bin.000001, ###), using_gtid(1), gtid('0-1-2,10-1-1')"
+--let SEARCH_FILE=$log_error_
+--let SEARCH_RANGE=-50000
+--let SEARCH_PATTERN=using_gtid\(1\), gtid\(\'0-1-2,10-1-1\'\).*
+--source include/search_pattern_in_file.inc
+
+--echo "===== Clean up ====="
+--connection slave
+--source include/stop_slave.inc
+CHANGE MASTER TO MASTER_USE_GTID=no;
+--source include/start_slave.inc
+
+--connection master
+DROP TABLE t;
+SET GLOBAL LOG_WARNINGS=default;
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_binlog_dup_entry.test b/mysql-test/suite/rpl/t/rpl_binlog_dup_entry.test
new file mode 100644
index 00000000..869c715f
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_binlog_dup_entry.test
@@ -0,0 +1,72 @@
+# ==== Purpose ====
+#
+# Test verifies that there are no duplicate entries in binlog (i.e a safe
+# statement which follows an unsafe statement gets logged in both row format
+# and statement format resulting in duplicate entry) when binlog-format=MIXED
+# and LOCK TABLES are enabled.
+#
+# ==== Implementation ====
+#
+# Steps:
+# 1 - Create three tables t1,t2 and t3 with AUTO_INCREMENT on.
+# 2 - Create a trigger on table t3, so that trigger execution results in
+# unsafe statement. Note query that modifies autoinc column in
+# sub-statement can make the master and slave inconsistent. Hence they
+# are logged in row format.
+# 3 - Lock tables t1,t2 and t3.
+# 4 - Execute an unsafe update which modifies tables t1 and t3. But since t2
+# table is also locked its table map event also gets written into the
+# binary log during the execution of update.
+# 5 - Execute a safe DML operation using table 't2' and verify that master
+# doesn't report any assert.
+# 6 - Ensure that slave is in sync with master and data is consistent.
+#
+# ==== References ====
+#
+# MDEV-19158: MariaDB 10.2.22 is writing duplicate entries into binary log
+
+--source include/have_binlog_format_mixed.inc
+--source include/master-slave.inc
+
+CREATE TABLE t1 (id mediumint(8) unsigned NOT NULL AUTO_INCREMENT, someLabel varchar(30) NOT NULL, flag tinyint(1) NOT NULL DEFAULT 0, PRIMARY KEY (id)) Engine=MyISAM;
+CREATE TABLE t2 (id mediumint(8) unsigned NOT NULL AUTO_INCREMENT, data varchar(30) NOT NULL, status tinyint(1) NOT NULL, PRIMARY KEY (id)) Engine=MyISAM;
+CREATE TABLE t3 (id mediumint(8) unsigned NOT NULL AUTO_INCREMENT, t1id mediumint(8) unsigned NOT NULL, flag tinyint(1) NOT NULL DEFAULT 0, status tinyint(1) NOT NULL DEFAULT 0, PRIMARY KEY (id)) Engine=MyISAM;
+
+INSERT INTO t1 ( id, someLabel, flag ) VALUES ( 1, 'ABC', 0 );
+
+DELIMITER |;
+
+CREATE OR REPLACE TRIGGER doNothing
+BEFORE UPDATE ON t1
+FOR EACH ROW
+ BEGIN
+ IF
+ new.someLabel != old.someLabel
+ THEN
+ UPDATE t3 SET t3.flag = 0;
+ END IF;
+ END|
+
+DELIMITER ;|
+
+FLUSH LOGS;
+
+LOCK TABLES t1 WRITE, t2 WRITE;
+INSERT INTO t2 (data, status) VALUES ('1', 4);
+UPDATE t1 SET flag = 1 WHERE id = 1;
+INSERT INTO t2 (data, status) VALUES ('2', 4);
+UNLOCK TABLES;
+
+sync_slave_with_master;
+
+let $diff_tables= master:t1, slave:t1;
+--source include/diff_tables.inc
+let $diff_tables= master:t2, slave:t2;
+--source include/diff_tables.inc
+let $diff_tables= master:t3, slave:t3;
+--source include/diff_tables.inc
+
+--connection master
+DROP TABLE t1, t2, t3;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_binlog_errors-master.opt b/mysql-test/suite/rpl/t/rpl_binlog_errors-master.opt
new file mode 100644
index 00000000..f8e46a44
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_binlog_errors-master.opt
@@ -0,0 +1 @@
+--max_binlog_size=4096
diff --git a/mysql-test/suite/rpl/t/rpl_binlog_errors.test b/mysql-test/suite/rpl/t/rpl_binlog_errors.test
new file mode 100644
index 00000000..4dbd8eca
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_binlog_errors.test
@@ -0,0 +1,447 @@
+#
+# This include file is used by more than one test suite
+# (currently rpl and binlog_encryption).
+# Please check all dependent tests after modifying it
+#
+# Usage:
+# --let $binlog_limit= X[,Y] # optional
+#
+# Semantics of the value is the same as in include/show_binlog_events.inc
+# which the script calls as a part of the test flow.
+# The goal is to print the event demonstrating the triggered error,
+# so normally Y should be 1 (print the exact event only);
+# however, depending on test-specific server options, the offset X
+# can be different.
+#
+
+# BUG#46166: MYSQL_BIN_LOG::new_file_impl is not propagating error
+# when generating new name.
+#
+# WHY
+# ===
+#
+# We want to check whether error is reported or not when
+# new_file_impl fails (this may happen when rotation is not
+# possible because there is some problem finding an
+# unique filename).
+#
+# HOW
+# ===
+#
+# Test cases are documented inline.
+
+-- source include/have_innodb.inc
+-- source include/have_debug.inc
+-- source include/master-slave.inc
+
+-- echo #######################################################################
+-- echo ####################### PART 1: MASTER TESTS ##########################
+-- echo #######################################################################
+
+
+### ACTION: stopping slave as it is not needed for the first part of
+### the test
+
+-- connection slave
+-- source include/stop_slave.inc
+-- connection master
+
+call mtr.add_suppression("Can't generate a unique log-filename");
+call mtr.add_suppression("Writing one row to the row-based binary log failed.*");
+call mtr.add_suppression("Error writing file .*");
+call mtr.add_suppression("Could not use master-bin for logging");
+
+SET @old_debug= @@global.debug_dbug;
+
+### ACTION: create a large file (> 4096 bytes) that will be later used
+### in LOAD DATA INFILE to check binlog errors in its vacinity
+-- let $load_file= $MYSQLTEST_VARDIR/tmp/bug_46166.data
+-- let $MYSQLD_DATADIR= `select @@datadir`
+-- replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
+--disable_ps2_protocol
+-- eval SELECT repeat('x',8192) INTO OUTFILE '$load_file'
+--enable_ps2_protocol
+
+### ACTION: create a small file (< 4096 bytes) that will be later used
+### in LOAD DATA INFILE to check for absence of binlog errors
+### when file loading this file does not force flushing and
+### rotating the binary log
+-- let $load_file2= $MYSQLTEST_VARDIR/tmp/bug_46166-2.data
+-- let $MYSQLD_DATADIR= `select @@datadir`
+-- replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
+--disable_ps2_protocol
+-- eval SELECT repeat('x',10) INTO OUTFILE '$load_file2'
+--enable_ps2_protocol
+
+RESET MASTER;
+
+-- echo ###################### TEST #1
+
+### ASSERTION: no problem flushing logs (should show two binlogs)
+FLUSH LOGS;
+-- echo # assert: must show two binlogs
+-- source include/show_binary_logs.inc
+
+-- echo ###################### TEST #2
+
+### ASSERTION: check that FLUSH LOGS actually fails and reports
+### failure back to the user if find_uniq_filename fails
+### (should show just one binlog)
+
+RESET MASTER;
+SET @@global.debug_dbug="d,error_unique_log_filename";
+-- error ER_NO_UNIQUE_LOGFILE
+FLUSH LOGS;
+-- echo # assert: must show one binlog
+-- source include/show_binary_logs.inc
+
+### ACTION: clean up and move to next test
+SET @@global.debug_dbug=@old_debug;
+RESET MASTER;
+
+-- echo ###################### TEST #3
+
+### ACTION: create some tables (t1, t2, t4) and insert some values in
+### table t1
+CREATE TABLE t1 (a INT);
+CREATE TABLE t2 (a VARCHAR(16384)) Engine=InnoDB;
+CREATE TABLE t4 (a VARCHAR(16384));
+INSERT INTO t1 VALUES (1);
+RESET MASTER;
+
+### ASSERTION: we force rotation of the binary log because it exceeds
+### the max_binlog_size option (should show two binary
+### logs)
+
+-- replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
+-- eval LOAD DATA INFILE '$load_file' INTO TABLE t2
+
+# shows two binary logs
+-- echo # assert: must show two binlog
+-- source include/show_binary_logs.inc
+
+# clean up the table and the binlog to be used in next part of test
+SET @@global.debug_dbug=@old_debug;
+DELETE FROM t2;
+RESET MASTER;
+
+-- echo ###################### TEST #4
+
+### ASSERTION: load the big file into a transactional table and check
+### that it reports error. The table will contain the
+### changes performed despite the fact that it reported an
+### error.
+
+SET @@global.debug_dbug="d,error_unique_log_filename";
+-- replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
+-- error ER_NO_UNIQUE_LOGFILE
+-- eval LOAD DATA INFILE '$load_file' INTO TABLE t2
+
+# show table
+-- echo # assert: must show one entry
+SELECT count(*) FROM t2;
+
+# clean up the table and the binlog to be used in next part of test
+SET @@global.debug_dbug=@old_debug;
+DELETE FROM t2;
+RESET MASTER;
+
+-- echo ###################### TEST #5
+
+### ASSERTION: load the small file into a transactional table and
+### check that it succeeds
+
+SET @@global.debug_dbug="d,error_unique_log_filename";
+-- replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
+-- eval LOAD DATA INFILE '$load_file2' INTO TABLE t2
+
+# show table
+-- echo # assert: must show one entry
+SELECT count(*) FROM t2;
+
+# clean up the table and the binlog to be used in next part of test
+SET @@global.debug_dbug=@old_debug;
+DELETE FROM t2;
+RESET MASTER;
+
+-- echo ###################### TEST #6
+
+### ASSERTION: check that even if one is using a transactional table
+### and explicit transactions (no autocommit) if rotation
+### fails we get the error. Transaction is not rolledback
+### because rotation happens after the commit.
+
+SET @@global.debug_dbug="d,error_unique_log_filename";
+SET AUTOCOMMIT=0;
+INSERT INTO t2 VALUES ('muse');
+-- replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
+-- eval LOAD DATA INFILE '$load_file' INTO TABLE t2
+INSERT INTO t2 VALUES ('muse');
+-- error ER_NO_UNIQUE_LOGFILE
+COMMIT;
+
+### ACTION: Show the contents of the table after the test
+-- echo # assert: must show three entries
+SELECT count(*) FROM t2;
+
+### ACTION: clean up and move to the next test
+SET AUTOCOMMIT= 1;
+SET @@global.debug_dbug=@old_debug;
+DELETE FROM t2;
+RESET MASTER;
+
+-- echo ###################### TEST #7
+
+### ASSERTION: check that on a non-transactional table, if rotation
+### fails then an error is reported and an incident event
+### is written to the current binary log.
+
+SET @@global.debug_dbug="d,error_unique_log_filename";
+
+# Disable logging Annotate_rows events to preserve events count.
+let $binlog_annotate_row_events_saved= `SELECT @@binlog_annotate_row_events`;
+SET @@binlog_annotate_row_events= 0;
+
+SELECT count(*) FROM t4;
+-- replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
+-- error ER_NO_UNIQUE_LOGFILE
+-- eval LOAD DATA INFILE '$load_file' INTO TABLE t4
+
+-- echo # assert: must show 1 entry
+SELECT count(*) FROM t4;
+
+-- echo ### check that the incident event is written to the current log
+SET @@global.debug_dbug=@old_debug;
+if (!$binlog_limit)
+{
+ -- let $binlog_limit= 4,1
+}
+-- source include/show_binlog_events.inc
+
+# clean up and move to next test
+DELETE FROM t4;
+
+--disable_query_log
+eval SET @@binlog_annotate_row_events= $binlog_annotate_row_events_saved;
+--enable_query_log
+
+RESET MASTER;
+
+-- echo ###################### TEST #8
+
+### ASSERTION: check that statements end up in error but they succeed
+### on changing the data.
+
+SET @@global.debug_dbug="d,error_unique_log_filename";
+-- echo # must show 0 entries
+SELECT count(*) FROM t4;
+SELECT count(*) FROM t2;
+
+-- replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
+-- error ER_NO_UNIQUE_LOGFILE
+-- eval LOAD DATA INFILE '$load_file' INTO TABLE t4
+-- replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
+-- error ER_NO_UNIQUE_LOGFILE
+-- eval LOAD DATA INFILE '$load_file' INTO TABLE t2
+-- error ER_NO_UNIQUE_LOGFILE
+INSERT INTO t2 VALUES ('aaa'), ('bbb'), ('ccc');
+
+-- echo # INFO: Count(*) Before Offending DELETEs
+-- echo # assert: must show 1 entry
+SELECT count(*) FROM t4;
+-- echo # assert: must show 4 entries
+SELECT count(*) FROM t2;
+
+-- error ER_NO_UNIQUE_LOGFILE
+DELETE FROM t4;
+-- error ER_NO_UNIQUE_LOGFILE
+DELETE FROM t2;
+
+-- echo # INFO: Count(*) After Offending DELETEs
+-- echo # assert: must show zero entries
+SELECT count(*) FROM t4;
+SELECT count(*) FROM t2;
+
+# remove fault injection
+SET @@global.debug_dbug=@old_debug;
+
+-- echo ###################### TEST #9
+
+### ASSERTION: check that if we disable binlogging, then statements
+### succeed.
+SET @@global.debug_dbug="d,error_unique_log_filename";
+SET SQL_LOG_BIN=0;
+INSERT INTO t2 VALUES ('aaa'), ('bbb'), ('ccc'), ('ddd');
+INSERT INTO t4 VALUES ('eee'), ('fff'), ('ggg'), ('hhh');
+-- echo # assert: must show four entries
+SELECT count(*) FROM t2;
+SELECT count(*) FROM t4;
+DELETE FROM t2;
+DELETE FROM t4;
+-- echo # assert: must show zero entries
+SELECT count(*) FROM t2;
+SELECT count(*) FROM t4;
+SET SQL_LOG_BIN=1;
+SET @@global.debug_dbug=@old_debug;
+
+-- echo ###################### TEST #10
+
+### ASSERTION: check that error is reported if there is a failure
+### while registering the index file and the binary log
+### file or failure to write the rotate event.
+
+call mtr.add_suppression("MYSQL_BIN_LOG::open failed to sync the index file.");
+call mtr.add_suppression("Could not use .*");
+
+RESET MASTER;
+SHOW WARNINGS;
+
+# +d,fault_injection_registering_index => injects fault on MYSQL_BIN_LOG::open
+SET @@global.debug_dbug="d,fault_injection_registering_index";
+-- replace_regex /\.[\\\/]master/master/
+-- error ER_CANT_OPEN_FILE
+FLUSH LOGS;
+SET @@global.debug_dbug=@old_debug;
+
+-- error ER_NO_BINARY_LOGGING
+SHOW BINARY LOGS;
+
+# issue some statements and check that they don't fail
+CREATE TABLE t5 (a INT);
+INSERT INTO t4 VALUES ('bbbbb');
+INSERT INTO t2 VALUES ('aaaaa');
+DELETE FROM t4;
+DELETE FROM t2;
+DROP TABLE t5;
+flush tables;
+
+-- echo ###################### TEST #11
+
+### ASSERTION: check that error is reported if there is a failure
+### while opening the index file and the binary log file or
+### failure to write the rotate event.
+
+# restart the server so that we have binlog again
+--let $rpl_server_number= 1
+--source include/rpl_restart_server.inc
+
+# +d,fault_injection_openning_index => injects fault on MYSQL_BIN_LOG::open_index_file
+SET @@global.debug_dbug="d,fault_injection_openning_index";
+-- replace_regex /\.[\\\/]master/master/
+-- error ER_CANT_OPEN_FILE
+FLUSH LOGS;
+SET @@global.debug_dbug=@old_debug;
+
+-- error ER_FLUSH_MASTER_BINLOG_CLOSED
+RESET MASTER;
+
+# issue some statements and check that they don't fail
+CREATE TABLE t5 (a INT);
+INSERT INTO t4 VALUES ('bbbbb');
+INSERT INTO t2 VALUES ('aaaaa');
+DELETE FROM t4;
+DELETE FROM t2;
+DROP TABLE t5;
+flush tables;
+
+# restart the server so that we have binlog again
+--let $rpl_server_number= 1
+--source include/rpl_restart_server.inc
+
+-- echo ###################### TEST #12
+
+### ASSERTION: check that error is reported if there is a failure
+### while writing the rotate event when creating a new log
+### file.
+
+# +d,fault_injection_new_file_rotate_event => injects fault on MYSQL_BIN_LOG::MYSQL_BIN_LOG::new_file_impl
+SET @@global.debug_dbug="d,fault_injection_new_file_rotate_event";
+-- error ER_ERROR_ON_WRITE
+FLUSH LOGS;
+SET @@global.debug_dbug=@old_debug;
+
+-- error ER_FLUSH_MASTER_BINLOG_CLOSED
+RESET MASTER;
+
+# issue some statements and check that they don't fail
+CREATE TABLE t5 (a INT);
+INSERT INTO t4 VALUES ('bbbbb');
+INSERT INTO t2 VALUES ('aaaaa');
+DELETE FROM t4;
+DELETE FROM t2;
+DROP TABLE t5;
+flush tables;
+
+# restart the server so that we have binlog again
+--let $rpl_server_number= 1
+--source include/rpl_restart_server.inc
+
+## clean up
+DROP TABLE t1, t2, t4;
+RESET MASTER;
+
+# restart slave again
+-- connection slave
+-- source include/start_slave.inc
+-- connection master
+
+-- echo #######################################################################
+-- echo ####################### PART 2: SLAVE TESTS ###########################
+-- echo #######################################################################
+
+### setup
+--source include/rpl_reset.inc
+-- connection slave
+
+# Slave tests rely on logic of non-gtid mode
+--source include/stop_slave.inc
+CHANGE MASTER TO MASTER_USE_GTID=NO;
+--source include/start_slave.inc
+
+# slave suppressions
+
+call mtr.add_suppression("Slave I/O: Relay log write failure: could not queue event from master.*");
+call mtr.add_suppression("Error writing file .*");
+call mtr.add_suppression("Could not use .*");
+call mtr.add_suppression("MYSQL_BIN_LOG::open failed to sync the index file.");
+call mtr.add_suppression("Can't generate a unique log-filename .*");
+-- echo ###################### TEST #13
+
+#### ASSERTION: check against unique log filename error
+-- let $io_thd_injection_fault_flag= error_unique_log_filename
+-- let $slave_io_errno= 1595
+-- let $show_slave_io_error= 1
+-- source include/io_thd_fault_injection.inc
+
+-- echo ###################### TEST #14
+
+#### ASSERTION: check against rotate failing
+-- let $io_thd_injection_fault_flag= fault_injection_new_file_rotate_event
+-- let $slave_io_errno= 1595
+-- let $show_slave_io_error= 1
+-- source include/io_thd_fault_injection.inc
+
+-- echo ###################### TEST #15
+
+#### ASSERTION: check against relay log open failure
+-- let $io_thd_injection_fault_flag= fault_injection_registering_index
+-- let $slave_io_errno= 1595
+-- let $show_slave_io_error= 1
+-- source include/io_thd_fault_injection.inc
+
+-- echo ###################### TEST #16
+
+#### ASSERTION: check against relay log index open failure
+-- let $io_thd_injection_fault_flag= fault_injection_openning_index
+-- let $slave_io_errno= 1595
+-- let $show_slave_io_error= 1
+-- source include/io_thd_fault_injection.inc
+
+### clean up
+-- source include/stop_slave_sql.inc
+RESET SLAVE;
+RESET MASTER;
+--remove_file $load_file
+--remove_file $load_file2
+--let $rpl_only_running_threads= 1
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_binlog_grant.test b/mysql-test/suite/rpl/t/rpl_binlog_grant.test
new file mode 100644
index 00000000..f8513021
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_binlog_grant.test
@@ -0,0 +1,42 @@
+-- source include/have_innodb.inc
+-- source include/not_embedded.inc
+-- source include/have_binlog_format_mixed_or_statement.inc
+source include/master-slave.inc;
+
+let $VERSION=`select version()`;
+
+# Bug #21975: grant/revoke statements in transaction
+# used to disappear from binlog upon rallback.
+# Now GRANT/REVOKE do implicitly commit
+# transaction
+
+create database d1;
+use d1;
+create table t (s1 int) engine=innodb;
+set @@autocommit=0;
+start transaction;
+insert into t values (1);
+create user x@y;
+grant select on t to x@y;
+let $wait_binlog_event= grant select;
+source include/wait_for_binlog_event.inc;
+#
+# There is no active transaction here
+#
+rollback;
+show grants for x@y;
+start transaction;
+insert into t values (2);
+revoke select on t from x@y;
+let $wait_binlog_event= revoke select;
+source include/wait_for_binlog_event.inc;
+#
+# There is no active transaction here
+#
+commit;
+select * from t;
+show grants for x@y;
+drop user x@y;
+drop database d1;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_binlog_index.test b/mysql-test/suite/rpl/t/rpl_binlog_index.test
new file mode 100644
index 00000000..6112affb
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_binlog_index.test
@@ -0,0 +1,217 @@
+# ==== Purpose ====
+#
+# Test that server can work fine after moving binlog or relay log
+# files to another directory and setting binlog or relay log paths to
+# the new path.
+#
+# ==== Method ====
+#
+# Start replication, and then shutdown the master, move the binary
+# logs and the log index file to a another directory and then restart
+# the server with option to set the new binlog directory. After master
+# restarted successfully, do the similar on slave to check the relay
+# log of slave.
+#
+# ==== Reference ====
+#
+# BUG#12133 master.index file keeps mysqld from starting if bin log has been moved
+# BUG#42576 Relay logs in relay-log.info&localhost-relay-bin.index not processed after move
+
+# Since this test relies heavily on filesystem operations (like
+# moving files around, backslashes and so forth) we avoid messing
+# around with windows access violations for not cluttering the
+# test case any further. It is prepared to support windows, but
+# it is not 100% compliant.
+--source include/not_windows.inc
+
+source include/master-slave.inc;
+# There is no need to run this test case on all binlog format
+source include/have_binlog_format_row.inc;
+
+connection master;
+--let $master_datadir= `select @@datadir`
+connection slave;
+--let $slave_datadir= `select @@datadir`
+connection master;
+--let $dirname= `select uuid()`
+--let $tmpdir= $MYSQLTEST_VARDIR/tmp/$dirname
+--mkdir $tmpdir
+
+CREATE TABLE t1 (a INT);
+# flush to generate one more binlog file.
+FLUSH BINARY LOGS;
+INSERT INTO t1 VALUES (1);
+
+sync_slave_with_master;
+--source include/stop_slave.inc
+#
+# Test on master
+#
+connection master;
+--echo # Shutdown master
+--let $rpl_server_number=1
+source include/rpl_stop_server.inc;
+
+--echo # Move the master binlog files and the index file to a new place
+--move_file $master_datadir/master-bin.000001 $tmpdir/master-bin.000001
+--move_file $master_datadir/master-bin.000002 $tmpdir/master-bin.000002
+--move_file $master_datadir/master-bin.index $tmpdir/master-bin.index
+
+--echo # Restart master with log-bin option set to the new path
+--let $rpl_server_parameters=--log-bin=$tmpdir/master-bin --log-bin-index=$tmpdir/master-bin
+--let $keep_include_silent=1
+source include/rpl_start_server.inc;
+--let $keep_include_silent=0
+
+--echo # Master has restarted successfully
+--connection slave
+--source include/start_slave.inc
+--connection master
+#
+# Test master can handle old format with directory path in index file
+#
+--let $is_windows= `select convert(@@version_compile_os using latin1) in ('Win32', 'Win64', 'Windows')`
+
+# write_var_to_file.inc will call SELECT INTO DUMPFILE, which has to be
+# done before shutdown the server
+--echo # Create the master-bin.index file with the old format
+--let $write_to_file= $master_datadir/master-bin.index
+if ($is_windows)
+{
+ --let $write_var= .\\\\master-bin.000001\n.\\\\master-bin.000002\n.\\\\master-bin.000003\n
+}
+if (!$is_windows)
+{
+ --let $write_var= ./master-bin.000001\n./master-bin.000002\n./master-bin.000003\n
+}
+--disable_query_log
+source include/write_var_to_file.inc;
+--enable_query_log
+--sync_slave_with_master
+--source include/stop_slave.inc
+
+--connection master
+--echo # Shutdown master
+--let $rpl_server_number=1
+source include/rpl_stop_server.inc;
+
+--echo # Move back the master binlog files
+--move_file $tmpdir/master-bin.000001 $master_datadir/master-bin.000001
+--move_file $tmpdir/master-bin.000002 $master_datadir/master-bin.000002
+--move_file $tmpdir/master-bin.000003 $master_datadir/master-bin.000003
+
+--echo # Remove the unneeded master-bin.index file
+--remove_file $tmpdir/master-bin.index
+
+--echo # Restart master with log-bin option set to default
+--let $rpl_server_parameters=--log-bin=$master_datadir/master-bin --log-bin-index=$master_datadir/master-bin
+--let $keep_include_silent=1
+source include/rpl_start_server.inc;
+--let $keep_include_silent=0
+
+--echo # Master has restarted successfully
+--connection slave
+--source include/start_slave.inc
+
+--connection master
+--sync_slave_with_master
+--echo # stop slave
+--source include/stop_slave.inc
+--let $rpl_server_number= 2
+--source include/rpl_stop_server.inc
+
+# switch to master because the slave has been shutdown
+# and relocate_binlogs requires a running server to do
+# SQL operations
+--connection master
+
+--let $relocate_disable_query_log= 1
+--let $relocate_is_windows= $is_windows
+--let $relocate_from=$slave_datadir
+--let $relocate_into=$tmpdir
+
+--echo # relocate binlogs
+--let $relocate_index_file=$slave_datadir/slave-bin.index
+--source include/relocate_binlogs.inc
+
+--echo # relocate relay logs
+--let $relocate_index_file=$slave_datadir/slave-relay-bin.index
+--source include/relocate_binlogs.inc
+
+--echo # Restart slave with options log-bin, relay-log set to the new paths
+--let $rpl_server_parameters=--log-bin=$tmpdir/slave-bin --relay-log=$tmpdir/slave-relay-bin --relay-log-index=$tmpdir/slave-relay-bin.index
+--let $keep_include_silent=1
+--let $rpl_server_number= 2
+source include/rpl_start_server.inc;
+--let $keep_include_silent=0
+
+--connection slave
+
+--echo # Slave server has restarted successfully
+--source include/start_slave.inc
+--source include/stop_slave.inc
+
+connection master;
+FLUSH LOGS;
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (2);
+
+FLUSH LOGS;
+
+connection slave;
+FLUSH LOGS;
+--source include/start_slave.inc
+connection master;
+sync_slave_with_master;
+--let $diff_tables= master:t1,slave:t1
+source include/diff_tables.inc;
+
+connection master;
+DROP TABLE t1;
+--sync_slave_with_master
+--source include/stop_slave.inc
+--let $rpl_server_number= 2
+--source include/rpl_stop_server.inc
+
+--connection master
+
+--let $relocate_from=$tmpdir
+--let $relocate_into=$slave_datadir
+--let $relocate_recreate_index= 1
+
+# binlogs
+--let $relocate_index_file=$tmpdir/slave-bin.index
+--source include/relocate_binlogs.inc
+
+# relay logs
+
+# since the complete fix for the relocation of logs is
+# done in BUG#13428851 it does not help here to try
+# to start the slave as it would fail (relay-log.info is
+# tainted with the full path in the RELAY_LOG_FILE position).
+# Instead, we reset the slave and let the test clean up.
+--let $relocate_fix_relay_log_info= $slave_datadir/relay-log.info
+--let $relocate_index_file=$tmpdir/slave-relay-bin.index
+--source include/relocate_binlogs.inc
+
+--echo # remove tmpdir
+--remove_files_wildcard $tmpdir *
+--rmdir $tmpdir
+
+--echo # restarted with previous slave settings
+--let $rpl_server_parameters=--log-bin=$slave_datadir/slave-bin --relay-log=$slave_datadir/slave-relay-bin --relay-log-index=$slave_datadir/slave-relay-bin.index
+--let $keep_include_silent=1
+--let $rpl_server_number= 2
+--source include/rpl_start_server.inc
+--let $keep_include_silent=0
+
+--connection slave
+
+# The slave will restart if we have fixed the relay-log.info
+# correctly
+--source include/start_slave.inc
+
+--connection master
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_binlog_rollback_cleanup.test b/mysql-test/suite/rpl/t/rpl_binlog_rollback_cleanup.test
new file mode 100644
index 00000000..ed4d713f
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_binlog_rollback_cleanup.test
@@ -0,0 +1,46 @@
+# ==== Purpose ====
+#
+# Test verifies that when flushing an event to binary log fails the transaction
+# is successfully rolled back and following COMMIT command doesn't report any
+# assert.
+#
+# ==== Implementation ====
+#
+# Steps:
+# 0 - SET max_binlog_cache_size=64K
+# 1 - Create an Innodb table and insert required amount of data. Execute an
+# UPDATE operation which generates a big update event whose size exceeds
+# max_binlog_cache_size.
+# 2 - Wait for error 1197. Execute COMMIT command.
+# 3 - COMMIT should be successful.
+#
+# ==== References ====
+#
+# MDEV-18514: Assertion `!writer.checksum_len || writer.remains == 0' failed
+#
+--source include/have_innodb.inc
+--source include/have_binlog_format_row.inc
+--source include/master-slave.inc
+--connection master
+let $old_max_binlog_cache_size= query_get_value(SHOW VARIABLES LIKE "max_binlog_cache_size", Value, 1);
+SET GLOBAL max_binlog_cache_size = 65536;
+CREATE TABLE t1(a INT PRIMARY KEY, data VARCHAR(30000)) ENGINE=INNODB;
+let $data = `select concat('"', repeat('a',6000), '"')`;
+let $data1 = `select concat('"', repeat('b',6000), '"')`;
+--disable_query_log
+eval INSERT INTO t1 (a, data) VALUES (1, CONCAT($data, $data));
+eval INSERT INTO t1 (a, data) VALUES (2, CONCAT($data, $data));
+eval INSERT INTO t1 (a, data) VALUES (3, CONCAT($data, $data));
+eval INSERT INTO t1 (a, data) VALUES (4, CONCAT($data, $data));
+eval INSERT INTO t1 (a, data) VALUES (5, CONCAT($data, $data));
+START TRANSACTION;
+--error ER_TRANS_CACHE_FULL
+eval UPDATE t1 SET data=$data1;
+COMMIT;
+--enable_query_log
+
+--replace_result $old_max_binlog_cache_size ORIGINAL_VALUE
+--eval SET GLOBAL max_binlog_cache_size= $old_max_binlog_cache_size
+DROP TABLE t1;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_bit.test b/mysql-test/suite/rpl/t/rpl_bit.test
new file mode 100644
index 00000000..305a2abc
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_bit.test
@@ -0,0 +1,92 @@
+#############################################################################
+# Original Author: JBM #
+# Original Date: Sept/15/2005 #
+#############################################################################
+# Test: To test the replication of the bit field #
+#############################################################################
+# Change Author: JBM
+# Change Date: 2006-01-16
+##########
+
+-- source include/master-slave.inc
+
+
+# Begin clean up test section
+connection master;
+--disable_warnings
+DROP TABLE IF EXISTS test.t1;
+--enable_warnings
+# End of cleanup
+
+# Begin test section 1
+
+CREATE TABLE test.t1 (
+ dummyKey INTEGER NOT NULL,
+ f01 TINYINT,
+ f10 TINYINT,
+ f12 TINYINT,
+ f15 TINYINT,
+ f16 TINYINT,
+ f7 TINYINT,
+ f9 TINYINT,
+ f29 TINYINT,
+ f0 TINYINT,
+ fA1 TINYINT,
+ C32 TINYINT,
+ A42 TINYINT,
+ CA3 TINYINT,
+ A044 TINYINT,
+ f001 TINYINT,
+ A3002 TINYINT,
+ fC003 TINYINT,
+ CA300 TINYINT,
+ A305 TINYINT,
+ CA321 TINYINT,
+ r001 TINYINT,
+ bit1 BIT(6),
+ bit2 BIT(6),
+ bit3 BIT(6),
+ State1 TINYINT,
+ State2 TINYINT,
+ State3 TINYINT,
+ State4 TINYINT,
+ SubState TINYINT,
+ gState TINYINT,
+ oSupp TINYINT,
+ tSupp TINYINT,
+ sSuppD TINYINT,
+ mSuppf TINYINT,
+ GSuppDf TINYINT,
+ VNotSupp TINYINT,
+ x034 TINYINT,
+PRIMARY KEY USING HASH (dummyKey) );
+
+LOCK TABLES test.t1 WRITE;
+INSERT INTO test.t1 VALUES (6,1,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,b'111111',b'111110',b'110101',4,5,5,5,5,5,5,5,5,5,3,2,1);
+INSERT INTO test.t1 VALUES (1,1,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,b'111111',b'000000',b'100100',4,5,5,5,5,5,5,5,5,5,3,2,1);
+INSERT INTO test.t1 VALUES (2,1,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,b'000000',b'101010',b'010101',4,5,5,5,5,5,5,5,5,5,3,2,1);
+INSERT INTO test.t1 VALUES (3,1,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,b'101010',b'111111',b'000000',4,5,5,5,5,5,5,5,5,5,3,2,1);
+INSERT INTO test.t1 VALUES (4,1,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,4,5,5,5,5,5,5,5,5,5,3,2,1);
+INSERT INTO test.t1 VALUES (5,1,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,4,5,5,5,5,5,5,5,5,5,3,2,1);
+INSERT INTO test.t1 VALUES (7,1,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,4,5,5,5,5,5,5,5,5,5,3,2,1);
+INSERT INTO test.t1 VALUES (8,1,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,4,5,5,5,5,5,5,5,5,5,3,2,1);
+UNLOCK TABLES;
+
+
+SELECT oSupp, sSuppD, GSuppDf, VNotSupp, x034 FROM test.t1;
+SELECT hex(bit1) FROM test.t1 ORDER BY bit1;
+SELECT hex(bit2) from test.t1 ORDER BY bit2;
+SELECT hex(bit3) from test.t1 ORDER BY bit3;
+sync_slave_with_master;
+
+SELECT oSupp, sSuppD, GSuppDf, VNotSupp, x034 FROM test.t1;
+SELECT hex(bit1) FROM test.t1 ORDER BY bit1;
+SELECT hex(bit2) from test.t1 ORDER BY bit2;
+SELECT hex(bit3) from test.t1 ORDER BY bit3;
+
+connection master;
+DROP TABLE IF EXISTS test.t1;
+sync_slave_with_master;
+
+# End of 5.0 test case
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_bit_npk.test b/mysql-test/suite/rpl/t/rpl_bit_npk.test
new file mode 100644
index 00000000..d65ef66a
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_bit_npk.test
@@ -0,0 +1,113 @@
+#############################################################################
+# Original Author: JBM #
+# Original Date: Sept/15/2005 #
+#############################################################################
+# Test: To test the replication of the bit field #
+#############################################################################
+
+-- source include/master-slave.inc
+
+
+# Begin clean up test section
+connection master;
+--disable_warnings
+DROP TABLE IF EXISTS test.t1;
+--enable_warnings
+# End of cleanup
+
+# Begin test section 1
+
+CREATE TABLE test.t1 (
+ dummyKey INTEGER NOT NULL,
+ f01 TINYINT,
+ f10 TINYINT,
+ f12 TINYINT,
+ f15 TINYINT,
+ f16 TINYINT,
+ f7 TINYINT,
+ f9 TINYINT,
+ f29 TINYINT,
+ f0 TINYINT,
+ fA1 TINYINT,
+ C32 TINYINT,
+ A42 TINYINT,
+ CA3 TINYINT,
+ A044 TINYINT,
+ f001 TINYINT,
+ A3002 TINYINT,
+ fC003 TINYINT,
+ CA300 TINYINT,
+ A305 TINYINT,
+ CA321 TINYINT,
+ r001 TINYINT,
+ bit1 BIT(6),
+ bit2 BIT(6),
+ bit3 BIT(6),
+ State1 TINYINT,
+ State2 TINYINT,
+ State3 TINYINT,
+ State4 TINYINT,
+ SubState TINYINT,
+ gState TINYINT,
+ oSupp TINYINT,
+ tSupp TINYINT,
+ sSuppD TINYINT,
+ mSuppf TINYINT,
+ GSuppDf TINYINT,
+ VNotSupp TINYINT,
+ x034 TINYINT);
+
+LOCK TABLES test.t1 WRITE;
+INSERT INTO test.t1 VALUES (6,1,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,b'111111',b'111110',b'110101',4,5,5,5,5,5,5,5,5,5,3,NULL,1);
+INSERT INTO test.t1 VALUES (1,1,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,b'111111',b'000000',b'100100',4,5,5,5,5,5,5,5,5,5,3,2,1);
+INSERT INTO test.t1 VALUES (2,1,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,b'000000',b'101010',b'010101',4,5,5,5,5,5,5,5,5,5,3,2,1);
+INSERT INTO test.t1 VALUES (3,1,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,b'101010',b'111111',b'000000',4,5,5,5,5,5,5,5,5,5,3,2,1);
+INSERT INTO test.t1 VALUES (4,1,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,b'0',1,1,4,5,5,5,5,5,5,5,5,5,3,2,1);
+INSERT INTO test.t1 VALUES (5,1,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,4,5,5,5,5,5,5,5,5,5,3,2,1);
+INSERT INTO test.t1 VALUES (7,1,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,4,5,5,5,5,5,5,5,5,5,3,2,1);
+INSERT INTO test.t1 VALUES (8,1,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,4,5,5,5,5,5,5,5,5,5,3,2,1);
+UNLOCK TABLES;
+
+UPDATE test.t1 set x034 = 50 where bit3 = b'000000';
+UPDATE test.t1 set VNotSupp = 33 where bit1 = b'0';
+SELECT oSupp, sSuppD, GSuppDf, VNotSupp, x034
+ FROM test.t1
+ ORDER BY oSupp, sSuppD, GSuppDf, VNotSupp, x034;
+SELECT hex(bit1) from test.t1 ORDER BY bit1;
+SELECT hex(bit2) from test.t1 ORDER BY bit2;
+SELECT hex(bit3) from test.t1 ORDER BY bit3;
+sync_slave_with_master;
+
+SELECT oSupp, sSuppD, GSuppDf, VNotSupp, x034
+ FROM test.t1
+ ORDER BY oSupp, sSuppD, GSuppDf, VNotSupp, x034;
+SELECT hex(bit1) from test.t1 ORDER BY bit1;
+SELECT hex(bit2) from test.t1 ORDER BY bit2;
+SELECT hex(bit3) from test.t1 ORDER BY bit3;
+
+connection master;
+CREATE TABLE test.t2 (a INT, b BIT(1));
+INSERT INTO test.t2 VALUES (1, b'0');
+INSERT INTO test.t2 VALUES (1, b'1');
+UPDATE test.t2 SET a = 2 WHERE b = b'1';
+
+CREATE TABLE test.t3 (a INT, b INT);
+INSERT INTO test.t3 VALUES (1, NULL);
+INSERT INTO test.t3 VALUES (1, 0);
+UPDATE test.t3 SET a = 2 WHERE b = 0;
+
+SELECT a, hex(b) FROM test.t2 ORDER BY a,b;
+SELECT * FROM test.t3 ORDER BY a,b;
+sync_slave_with_master;
+
+SELECT a, hex(b) FROM test.t2 ORDER BY a,b;
+SELECT * FROM test.t3 ORDER BY a,b;
+
+connection master;
+DROP TABLE IF EXISTS test.t1;
+DROP TABLE IF EXISTS test.t2;
+DROP TABLE IF EXISTS test.t3;
+sync_slave_with_master;
+
+# End of 5.0 test case
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_blackhole.test b/mysql-test/suite/rpl/t/rpl_blackhole.test
new file mode 100644
index 00000000..927f0d80
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_blackhole.test
@@ -0,0 +1,25 @@
+# PURPOSE. Test that blackhole works with replication in all three
+# modes: STATEMENT, MIXED, and ROW.
+#
+# METHOD. We start by creating a table on the master and then change
+# the engine to use blackhole on the slave.
+#
+# After insert/update/delete of one or more rows, the test the
+# proceeds to check that replication is running after replicating an
+# change, that the blackhole engine does not contain anything (which
+# is just a check that the correct engine is used), and that something
+# is written to the binary log.
+#
+# Whe check INSERT, UPDATE, and DELETE statement for tables with no
+# key (forcing a range search on the slave), primary keys (using a
+# primary key lookup), and index/key with multiple matches (forcing an
+# index search).
+
+source include/have_blackhole.inc;
+source include/master-slave.inc;
+
+call mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT");
+
+source include/rpl_blackhole_basic.test;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_blackhole_row_annotate-master.opt b/mysql-test/suite/rpl/t/rpl_blackhole_row_annotate-master.opt
new file mode 100644
index 00000000..91302791
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_blackhole_row_annotate-master.opt
@@ -0,0 +1 @@
+--binlog_annotate_row_events --timezone=GMT-3
diff --git a/mysql-test/suite/rpl/t/rpl_blackhole_row_annotate-slave.opt b/mysql-test/suite/rpl/t/rpl_blackhole_row_annotate-slave.opt
new file mode 100644
index 00000000..7ac6a84f
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_blackhole_row_annotate-slave.opt
@@ -0,0 +1 @@
+--binlog_annotate_row_events --replicate_annotate_row_events
diff --git a/mysql-test/suite/rpl/t/rpl_blackhole_row_annotate.test b/mysql-test/suite/rpl/t/rpl_blackhole_row_annotate.test
new file mode 100644
index 00000000..f7aefd62
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_blackhole_row_annotate.test
@@ -0,0 +1,49 @@
+# ==== Purpose ====
+#
+# Test verifies that when "replicate_annotate_row_events" are enabled on slave
+# the DML operations on blackhole engine will be successful. It also ensures
+# that Annotate events are logged into slave's binary log.
+#
+# ==== Implementation ====
+#
+# Steps:
+# 0 - Enable "replicate_annotate_row_events" on slave and do DML operations
+# on master.
+# 1 - Slave server will successfully apply the DML operations and it is in
+# sync with master.
+# 2 - Verify that the "show binlog events" prints all annotate events.
+# 3 - Stream the slave's binary log using "mysqlbinlog" tool and verify
+# that the Annotate events are being displayed.
+#
+# ==== References ====
+#
+# MDEV-11094: Blackhole table updates on slave fail when row annotation is
+# enabled
+
+source include/have_blackhole.inc;
+source include/have_binlog_format_row.inc;
+source include/binlog_start_pos.inc;
+source include/master-slave.inc;
+
+SET timestamp=1000000000;
+RESET MASTER;
+connection slave;
+SET timestamp=1000000000;
+RESET MASTER;
+
+connection master;
+source include/rpl_blackhole_basic.test;
+
+# Verify on slave.
+connection slave;
+FLUSH LOGS;
+--replace_column 2 # 5 #
+--replace_result $binlog_start_pos <start_pos>
+--replace_regex /table_id: [0-9]+/table_id: #/ /\/\* xid=.* \*\//\/* xid= *\//
+--eval show binlog events in 'slave-bin.000001' from $binlog_start_pos
+
+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/ /xid=\d*/xid=<xid>/
+--exec $MYSQL_BINLOG --base64-output=decode-rows --skip-gtid-strict-mode $MYSQLD_DATADIR/slave-bin.000001
+
+source include/rpl_end.inc;
diff --git a/mysql-test/suite/rpl/t/rpl_bug26395.test b/mysql-test/suite/rpl/t/rpl_bug26395.test
new file mode 100644
index 00000000..0c1b2a7a
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_bug26395.test
@@ -0,0 +1,93 @@
+# ==== Purpose ====
+#
+# Tests that an autocommitted XA transaction where the master crashes
+# just before writing the XID log event is executed correctly. The
+# master rolls back, so the slave should not execute statement.
+#
+# ==== Method ====
+#
+# We want master to be alive so that it can replicate the statement to
+# the slave. So in the test case, we must not crash the
+# master. Instead, we fake the crash by just not writing the XID event
+# to the binlog. This is done by the @@debug_dbug='d,do_not_write_xid'
+# flag. This, in turn, requires us to do 'source
+# include/have_debug.inc'
+#
+# So, unlike if the master had crashed, the master *will* execute the
+# statement. But the slave should not execute it. Hence, after the
+# test is executed, the expected result on master is a table with one
+# row, and on slave a table with no rows.
+#
+# To simulate the slave correctly, we wait until everything up to but
+# not including the XID is replicated. This has to be done with
+# include/sync_slave_io_with_master.inc, not sync_slave_with_master,
+# since the latter waits until the slave *SQL* thread has caught up
+# with the master's position, which it will never do.
+#
+#
+# ==== Related bugs ====
+#
+# BUG#26395: if crash during autocommit update to transactional table on master, slave fails
+
+source include/have_innodb.inc;
+# have_debug is needed since we use the @@debug variable on master
+source include/have_debug.inc;
+source include/master-slave.inc;
+
+
+--echo ==== Initialize ====
+
+--connection master
+
+CREATE TABLE tinnodb (a INT) ENGINE = INNODB;
+SHOW CREATE TABLE tinnodb;
+
+# do_not_write_xid stops the master from writing an XID event.
+set @old_debug= @@debug;
+set @@debug_dbug= 'd,do_not_write_xid';
+
+
+--echo ==== Test ====
+
+# Save the position up to which the slave SQL thread should execute.
+save_master_pos;
+
+# Execute query and check that the row made it to the table.
+INSERT INTO tinnodb VALUES (1);
+SELECT * FROM tinnodb ORDER BY a;
+
+# Sync slave's IO thread.
+--echo [on slave]
+source include/sync_slave_io_with_master.inc;
+
+# Sync slave's SQL thread.
+sync_with_master 0;
+
+
+--echo ==== Verify results on slave ====
+
+source include/stop_slave.inc;
+let $tmp= query_get_value("SHOW SLAVE STATUS", Slave_IO_State, 1);
+eval SELECT "$tmp" AS Slave_IO_State;
+let $tmp= query_get_value("SHOW SLAVE STATUS", Last_SQL_Error, 1);
+eval SELECT "$tmp" AS Last_SQL_Error;
+let $tmp= query_get_value("SHOW SLAVE STATUS", Last_IO_Error, 1);
+eval SELECT "$tmp" AS Last_IO_Error;
+SELECT * FROM tinnodb ORDER BY a;
+
+
+--echo ==== Clean up ====
+
+# Easiest to clean up master and slave separately, without
+# replication, since master and slave are out of sync.
+
+connection master;
+DROP TABLE tinnodb;
+set @@debug_dbug= @old_debug;
+
+connection slave;
+DROP TABLE tinnodb;
+
+# Warning: do not add more tests here. The binlog is in a bad state.
+--let $rpl_only_running_threads= 1
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_bug31076.test b/mysql-test/suite/rpl/t/rpl_bug31076.test
new file mode 100644
index 00000000..7e523297
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_bug31076.test
@@ -0,0 +1,151 @@
+if (`SELECT $PS_PROTOCOL != 0`)
+{
+ --skip Need regular protocol but ps-protocol was specified
+}
+
+source include/have_binlog_format_mixed_or_row.inc;
+source include/master-slave.inc;
+
+SET @saved_slave_type_conversions = @@slave_type_conversions;
+SET GLOBAL SLAVE_TYPE_CONVERSIONS = 'ALL_NON_LOSSY';
+
+CREATE DATABASE track;
+USE track;
+
+CREATE TABLE `visits` (
+ `visits_id` int(11) unsigned NOT NULL AUTO_INCREMENT,
+ `myid` varchar(32) NOT NULL DEFAULT '',
+ `src` varchar(64) NOT NULL DEFAULT '',
+ `ip` int(10) unsigned NOT NULL DEFAULT '0',
+ `cc` char(2) NOT NULL DEFAULT '',
+ `org` varchar(80) DEFAULT NULL,
+ `ref` varchar(255) NOT NULL DEFAULT '',
+ `time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+ `host` varchar(30) NOT NULL DEFAULT '',
+ `entry` varchar(255) NOT NULL DEFAULT '',
+ `visit_exit` varchar(255) NOT NULL DEFAULT '',
+ `user_id` int(11) unsigned NOT NULL DEFAULT '0',
+ `visit_start` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
+ PRIMARY KEY (`visits_id`),
+ KEY `ip` (`ip`),
+ KEY `time` (`time`),
+ KEY `user_id` (`user_id`)
+) ENGINE=MyISAM AUTO_INCREMENT=21293381 DEFAULT CHARSET=latin1;
+
+CREATE TABLE `visits_events` (
+ `event_id` mediumint(8) unsigned NOT NULL DEFAULT '0',
+ `visit_id` int(11) unsigned NOT NULL DEFAULT '0',
+ `timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ `src` varchar(64) NOT NULL DEFAULT '',
+ `data` varchar(255) NOT NULL DEFAULT '',
+ `visits_events_id` int(11) unsigned NOT NULL AUTO_INCREMENT,
+ PRIMARY KEY (`visits_events_id`),
+ KEY `event_id` (`event_id`),
+ KEY `visit_id` (`visit_id`),
+ KEY `data` (`data`)
+) ENGINE=MyISAM AUTO_INCREMENT=33900731 DEFAULT CHARSET=latin1;
+
+/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=1*/;
+/*!40019 SET @@session.max_delayed_threads=0*/;
+/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/;
+--delimiter /*!*/;
+
+# at 4 (0x4)
+#071204 14:29:31 server id 1 end_log_pos 106
+# Position Timestamp Type Master ID Size Master Pos Flags
+# 4 3b 56 55 47 0f 01 00 00 00 66 00 00 00 6a 00 00 00 00 00
+# 17 04 00 35 2e 31 2e 32 33 2d 72 63 2d 64 65 62 75 |..5.1.23.rc.debu|
+# 27 67 2d 6c 6f 67 00 00 00 00 00 00 00 00 00 00 00 |g.log...........|
+# 37 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+# 47 00 00 00 00 3b 56 55 47 13 38 0d 00 08 00 12 00 |.....VUG.8......|
+# 57 04 04 04 04 12 00 00 53 00 04 1a 08 00 00 00 08 |.......S........|
+# 67 08 08 02 |...|
+# Start: binlog v 4, server v 5.1.23-rc-debug-log created 071204 14:29:31 at startup
+
+BINLOG '
+O1ZVRw8BAAAAZgAAAGoAAAAAAAQANS4xLjIzLXJjLWRlYnVnLWxvZwAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAA7VlVHEzgNAAgAEgAEBAQEEgAAUwAEGggAAAAICAgC
+'/*!*/;
+
+# at 164170623
+# at 164170679
+#7918 3:59:2 server id 436 end_log_pos 164170679
+# 9c90b7f 06 4d ef 46 13 b4 01 00 00 38 00 00 00 b7 0b c9 |.M.F.....8......|
+# 9c90b8f 09 00 00 99 57 17 02 00 00 00 00 05 74 72 61 63 |....W.......trac|
+# 9c90b9f 6b 00 0d 76 69 |k..vi|
+# Table_map: `track`.`visits_events` mapped to number 35084185
+#7918 3:59:2 server id 436 end_log_pos 164170769
+# 9c90bb7 06 4d ef 46 17 b4 01 00 00 5a 00 00 00 11 0c c9 |.M.F.....Z......|
+# 9c90bc7 09 10 00 99 57 17 02 00 00 01 00 06 ff c0 20 4e |....W..........N|
+# 9c90bd7 00 be f5 43 01 06 4d ef 46 00 2b 44 6f 77 6e 6c |...C..M.F..Downl|
+# 9c90be7 6f 61 64 73 2f 4d 79 53 51 4c 2d 34 2e 31 2f 6d |oads.MySQL.4.1.m|
+# 9c90bf7 79 73 71 6c 2d 34 2e |ysql.4.|
+# Write_rows: table id 35084185 flags: STMT_END_F
+
+BINLOG '
+Bk3vRhO0AQAAOAAAALcLyQkAAJlXFwIAAAAABXRyYWNrAA12aXNpdHNfZXZlbnRzAAYJAwcPDwM=
+Bk3vRhe0AQAAWgAAABEMyQkQAJlXFwIAAAEABv/AIE4AvvVDAQZN70YAK0Rvd25sb2Fkcy9NeVNR
+TC00LjEvbXlzcWwtNC4xLjEyYS13aW4zMi56aXBPaAIC
+'/*!*/;
+# at 164170769
+#7918 3:59:2 server id 436 end_log_pos 164170797
+# 9c90c11 06 4d ef 46 05 b4 01 00 00 |.M.F.....|
+# Intvar
+SET INSERT_ID=21231039/*!*/;
+# at 164170797
+#7918 3:59:2 server id 436 end_log_pos 164171293
+# 9c90c2d 06 4d ef 46 02 b4 01 00 00 f0 01 00 00 1d 0e c9 |.M.F............|
+# 9c90c3d 09 10 00 28 80 af 01 00 00 00 00 05 00 00 1f 00 |................|
+# 9c90c4d 00 00 40 00 00 01 00 00 00 00 00 00 00 00 06 03 |................|
+# 9c90c5d 73 74 64 04 08 00 08 00 08 00 05 03 55 54 43 74 |std.........UTCt|
+# 9c90c6d 72 61 63 6b 00 49 4e 53 45 52 54 20 49 4e 54 4f |rack.INSERT.INTO|
+# 9c90c7d 20 76 69 73 69 74 73 20 28 6d 79 69 64 2c 20 75 |.visits..myid..u|
+# 9c90c8d 73 65 72 5f 69 64 2c 20 73 72 63 2c 20 69 70 2c |ser.id..src..ip.|
+# 9c90c9d 20 63 63 2c 20 6f 72 67 2c 20 72 65 66 2c 20 74 |.cc..org..ref..t|
+# 9c90cad 69 6d 65 2c 20 68 6f 73 74 2c 20 65 6e 74 72 79 |ime..host..entry|
+# 9c90cbd 2c 20 76 69 73 69 74 5f 65 78 69 74 2c 20 76 69 |..visit.exit..vi|
+# 9c90ccd 73 69 74 5f 73 74 61 72 74 29 0a 09 09 09 56 41 |sit.start.....VA|
+# 9c90cdd 4c 55 45 53 20 28 27 33 6d 33 6c 34 72 68 73 36 |LUES...3m3l4rhs6|
+# 9c90ced 64 6f 30 73 66 35 70 31 69 39 6c 72 39 34 67 39 |do0sf5p1i9lr94g9|
+# 9c90cfd 32 38 61 32 37 32 76 27 2c 20 27 27 2c 20 27 27 |28a272v.........|
+# 9c90d0d 2c 20 49 4e 45 54 5f 41 54 4f 4e 28 27 37 31 2e |..INET.ATON..71.|
+# 9c90d1d 31 31 38 2e 31 32 34 2e 39 38 27 29 2c 20 27 27 |118.124.98......|
+# 9c90d2d 2c 20 27 27 2c 20 27 68 74 74 70 3a 2f 2f 64 65 |.......http...de|
+# 9c90d3d 76 2e 6d 79 73 71 6c 2e 63 6f 6d 2f 64 6f 77 6e |v.mysql.com.down|
+# 9c90d4d 6c 6f 61 64 73 2f 63 6f 6e 6e 65 63 74 6f 72 2f |loads.connector.|
+# 9c90d5d 6a 2f 33 2e 30 2e 68 74 6d 6c 27 2c 20 4e 55 4c |j.3.0.html...NUL|
+# 9c90d6d 4c 2c 20 27 64 65 76 2e 6d 79 73 71 6c 2e 63 6f |L...dev.mysql.co|
+# 9c90d7d 6d 27 2c 20 27 2f 67 65 74 2f 44 6f 77 6e 6c 6f |m.....get.Downlo|
+# 9c90d8d 61 64 73 2f 43 6f 6e 6e 65 63 74 6f 72 2d 4a 2f |ads.Connector.J.|
+# 9c90d9d 6d 79 73 71 6c 2d 63 6f 6e 6e 65 63 74 6f 72 2d |mysql.connector.|
+# 9c90dad 6a 61 76 61 2d 33 2e 30 2e 31 37 2d 67 61 2e 7a |java.3.0.17.ga.z|
+# 9c90dbd 69 70 2f 66 72 6f 6d 2f 70 69 63 6b 27 2c 20 27 |ip.from.pick....|
+# 9c90dcd 2f 67 65 74 2f 44 6f 77 6e 6c 6f 61 64 73 2f 43 |.get.Downloads.C|
+# 9c90ddd 6f 6e 6e 65 63 74 6f 72 2d 4a 2f 6d 79 73 71 6c |onnector.J.mysql|
+# 9c90ded 2d 63 6f 6e 6e 65 63 74 6f 72 2d 6a 61 76 61 2d |.connector.java.|
+# 9c90dfd 33 2e 30 2e 31 37 2d 67 61 2e 7a 69 70 |3.0.17.ga.zip|
+# Query thread_id=28278824 exec_time=0 error_code=0
+/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=0*/;
+use track/*!*/;
+SET TIMESTAMP=1190087942/*!*/;
+SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.unique_checks=1/*!*/;
+SET @@session.sql_mode=0/*!*/;
+SET @@session.character_set_client=8,@@session.collation_connection=8,@@session.collation_server=8/*!*/;
+SET @@session.time_zone='UTC'/*!*/;
+INSERT INTO visits (myid, user_id, src, ip, cc, org, ref, time, host, entry, visit_exit, visit_start)
+VALUES ('3m3l4rhs6do0sf5p1i9lr94g928a272v', '', '', INET_ATON('71.118.124.98'), '', '', 'http://dev.mysql.com/downloads/connector/j/3.0.html', NULL, 'dev.mysql.com', '/get/Downloads/Connector-J/mysql-connector-java-3.0.17-ga.zip/from/pick', '/get/Downloads/Connector-J/mysql-connector-java-3.0.17-ga.zip/from/pick', NOW())/*!*/;
+# at 164171293
+
+--delimiter ;
+
+SELECT * FROM visits;
+SELECT * FROM visits_events;
+
+SET GLOBAL SLAVE_TYPE_CONVERSIONS = @saved_slave_type_conversions;
+
+# Cleanup
+DROP DATABASE track;
+sync_slave_with_master;
+
+--echo End of 5.1 tests
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_bug33931.test b/mysql-test/suite/rpl/t/rpl_bug33931.test
new file mode 100644
index 00000000..0b2cbb63
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_bug33931.test
@@ -0,0 +1,49 @@
+# Test for
+# Bug #33931 assertion at write_ignored_events_info_to_relay_log if init_slave_thread() fails
+# Bug #33932 assertion at handle_slave_sql if init_slave_thread() fails
+
+source include/have_debug.inc;
+source include/master-slave.inc;
+
+connection slave;
+
+# Add suppression for expected warnings in slaves error log
+call mtr.add_suppression("Failed during slave I/O thread initialization");
+call mtr.add_suppression("Slave SQL.*Failed during slave thread initialization.* 1593");
+
+--source include/stop_slave.inc
+reset slave;
+
+# Set debug flags on slave to force errors to occur
+SET @saved_dbug = @@GLOBAL.debug_dbug;
+SET GLOBAL debug_dbug="d,simulate_io_slave_error_on_init,simulate_sql_slave_error_on_init";
+
+--disable_query_log
+eval CHANGE MASTER TO MASTER_USER='root',
+ MASTER_CONNECT_RETRY=1,
+ MASTER_HOST='127.0.0.1',
+ MASTER_PORT=$MASTER_MYPORT;
+--enable_query_log
+
+start slave;
+
+#
+# slave is going to stop because of emulated failures
+# but there won't be any crashes nor asserts hit.
+#
+
+# 1593 = ER_SLAVE_FATAL_ERROR
+--let $slave_sql_errno= 1593
+--let $show_slave_sql_error= 1
+--source include/wait_for_slave_sql_error.inc
+
+#
+# Cleanup
+#
+SET @@GLOBAL.debug_dbug = @saved_dbug;
+
+# Clear Last_SQL_Error
+RESET SLAVE;
+
+--let $rpl_only_running_threads= 1
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_bug37426.test b/mysql-test/suite/rpl/t/rpl_bug37426.test
new file mode 100644
index 00000000..18e80a5f
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_bug37426.test
@@ -0,0 +1,22 @@
+#############################################################
+# Purpose: Test for BUG#37426
+# RBR breaks for CHAR() UTF8 fields > 85 chars
+#############################################################
+
+source include/have_binlog_format_row.inc;
+source include/master-slave.inc;
+
+connection master;
+CREATE TABLE char128_utf8 (i1 INT NOT NULL, c CHAR(128) CHARACTER SET utf8 NOT NULL, i2 INT NOT NULL);
+INSERT INTO char128_utf8 VALUES ( 1, "123", 1 );
+
+SELECT * FROM char128_utf8;
+sync_slave_with_master;
+
+SELECT * FROM char128_utf8;
+
+# Clean up
+connection master;
+DROP TABLE char128_utf8;
+sync_slave_with_master;
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_bug38694-slave.opt b/mysql-test/suite/rpl/t/rpl_bug38694-slave.opt
new file mode 100644
index 00000000..b457a7eb
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_bug38694-slave.opt
@@ -0,0 +1 @@
+--loose-debug-dbug=d,simulate_slave_delay_at_terminate_bug38694
diff --git a/mysql-test/suite/rpl/t/rpl_bug38694.test b/mysql-test/suite/rpl/t/rpl_bug38694.test
new file mode 100644
index 00000000..57d7dde0
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_bug38694.test
@@ -0,0 +1,13 @@
+# Testing replication threads stopping concurrency issue
+# at the server shutdown
+# Related bugs: bug#38694, bug#29968, bug#25306
+# The test checks if a delay at the termination phase of slave threads
+# DBUG_EXECUTE_IF("simulate_slave_delay_at_terminate_bug38694", sleep(5););
+# could cause any issue.
+
+source include/master-slave.inc;
+
+call mtr.add_suppression("Aborted connection");
+
+# End of tests
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_bug41902.test b/mysql-test/suite/rpl/t/rpl_bug41902.test
new file mode 100644
index 00000000..bb6c5725
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_bug41902.test
@@ -0,0 +1,67 @@
+# Test for Bug #41902 MYSQL_BIN_LOG::reset_logs() doesn't call my_error()
+# in face of an error
+#
+
+source include/have_debug.inc;
+source include/master-slave.inc;
+
+#
+# test checks that
+# a. there is no crash when find_log_pos() returns with an error
+# that tests expect to receive;
+# b. in the case of multiple error messages the first error message is
+# reported to the user and others are available as warnings.
+#
+
+connection slave;
+stop slave;
+SET @saved_dbug = @@GLOBAL.debug_dbug;
+SET @@debug_dbug="d,simulate_find_log_pos_error";
+
+--error ER_UNKNOWN_TARGET_BINLOG
+reset slave;
+show warnings;
+
+SET @@debug_dbug="";
+reset slave;
+change master to master_host='dummy';
+
+SET @@debug_dbug="d,simulate_find_log_pos_error";
+
+--error ER_UNKNOWN_TARGET_BINLOG
+change master to master_host='dummy';
+
+SET @@debug_dbug="";
+reset slave;
+change master to master_host='dummy';
+
+connection master;
+SET @saved_dbug_m = @@global.debug_dbug;
+SET @@debug_dbug="d,simulate_find_log_pos_error";
+--error ER_UNKNOWN_TARGET_BINLOG
+reset master;
+
+SET @@debug_dbug="";
+reset master;
+
+SET @@debug_dbug="d,simulate_find_log_pos_error";
+--error ER_UNKNOWN_TARGET_BINLOG
+purge binary logs to 'master-bin.000001';
+
+SET @@debug_dbug="";
+purge binary logs to 'master-bin.000001';
+
+--disable_query_log
+call mtr.add_suppression("Failed to locate old binlog or relay log files");
+call mtr.add_suppression("MYSQL_BIN_LOG::purge_logs was called with file ..master-bin.000001 not listed in the index");
+set @@global.debug_dbug = @saved_dbug_m;
+connection slave;
+call mtr.add_suppression("Failed to locate old binlog or relay log files");
+call mtr.add_suppression("MYSQL_BIN_LOG::purge_logs was called with file ..master-bin.000001 not listed in the index");
+--enable_query_log
+SET @@GLOBAL.debug_dbug = @saved_dbug;
+
+--echo ==== clean up ====
+CHANGE MASTER TO MASTER_HOST = '127.0.0.1';
+--let $rpl_only_running_threads= 1
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_cant_read_event_incident.test b/mysql-test/suite/rpl/t/rpl_cant_read_event_incident.test
new file mode 100644
index 00000000..7c1d0ea2
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_cant_read_event_incident.test
@@ -0,0 +1,88 @@
+#
+# This include file is used by more than one test suite
+# (currently rpl and binlog_encryption).
+# Please check all dependent tests after modifying it
+#
+
+#
+# Bug#11747416 : 32228 A disk full makes binary log corrupt.
+#
+#
+# The test demonstrates reading from binlog error propagation to slave
+# and reporting there.
+# Conditions for the bug include a crash at time of the last event to
+# the binlog was written partly. With the fixes the event is not sent out
+# any longer, but rather the dump thread sends out a sound error message.
+#
+# Crash is not simulated. A binlog with partly written event in its end is installed
+# and replication is started from it.
+#
+
+--source include/have_binlog_format_mixed.inc
+--source include/master-slave.inc
+
+--connection slave
+--source include/stop_slave.inc
+CHANGE MASTER TO MASTER_USE_GTID=NO;
+--source include/start_slave.inc
+
+# Make sure the slave is stopped while we are messing with master.
+# Otherwise we get occasional failures as the slave manages to re-connect
+# to the newly started master and we get extra events applied, causing
+# conflicts.
+--source include/stop_slave.inc
+
+--connection master
+call mtr.add_suppression("Error in Log_event::read_log_event()");
+--let $datadir= `SELECT @@datadir`
+
+--let $rpl_server_number= 1
+--source include/rpl_stop_server.inc
+
+--remove_file $datadir/master-bin.000001
+--copy_file $MYSQL_TEST_DIR/std_data/bug11747416_32228_binlog.000001 $datadir/master-bin.000001
+
+--let $rpl_server_number= 1
+--source include/rpl_start_server.inc
+
+--source include/wait_until_connected_again.inc
+
+# evidence of the partial binlog
+--error ER_ERROR_WHEN_EXECUTING_COMMAND
+show binlog events;
+
+--connection slave
+call mtr.add_suppression("Slave I/O: Got fatal error 1236 from master when reading data from binary log");
+--let $master_use_gtid_option= No
+--source include/reset_slave.inc
+start slave;
+
+# ER_MASTER_FATAL_ERROR_READING_BINLOG 1236
+--let $slave_param=Last_IO_Errno
+--let $slave_param_value=1236
+--source include/wait_for_slave_param.inc
+
+--let $slave_field_result_replace= / at [0-9]*/ at XXX/
+--let $status_items= Last_IO_Errno, Last_IO_Error
+--source include/show_slave_status.inc
+
+#
+# Cleanup
+#
+
+--connection master
+reset master;
+
+--connection slave
+stop slave;
+reset slave;
+# Table was created from binlog, it may not be created if SQL thread is running
+# slowly and IO thread reaches incident before SQL thread applies it.
+--disable_warnings
+drop table if exists t;
+--enable_warnings
+reset master;
+
+--echo End of the tests
+--let $rpl_only_running_threads= 1
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_change_master.test b/mysql-test/suite/rpl/t/rpl_change_master.test
new file mode 100644
index 00000000..2758f9d6
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_change_master.test
@@ -0,0 +1,117 @@
+# Verify that after CHANGE MASTER, replication (I/O thread and SQL
+# thread) restart from where SQL thread left, not from where
+# I/O thread left (some old bug fixed in 4.0.17)
+
+source include/master-slave.inc;
+call mtr.add_suppression("Slave I/O: The slave I/O thread stops because a fatal error is encountered when it tried to SET @master_binlog_checksum");
+
+connection master;
+# Make SQL slave thread advance a bit
+create table t1(n int);
+sync_slave_with_master;
+select * from t1;
+# Now stop it and make I/O slave thread be ahead
+stop slave sql_thread;
+connection master;
+insert into t1 values(1);
+insert into t1 values(2);
+save_master_pos;
+let $slave_param= Read_Master_Log_Pos;
+let $slave_param_value= query_get_value(SHOW MASTER STATUS, Position, 1);
+connection slave;
+source include/wait_for_slave_param.inc;
+source include/stop_slave.inc;
+
+let $read_pos= query_get_value(SHOW SLAVE STATUS, Read_Master_Log_Pos, 1);
+let $exec_pos= query_get_value(SHOW SLAVE STATUS, Exec_Master_Log_Pos, 1);
+if ($read_pos == $exec_pos)
+{
+ source include/show_rpl_debug_info.inc;
+ echo 'Read_Master_Log_Pos: $read_pos' == 'Exec_Master_Log_Pos: $exec_pos';
+ die Failed because Read_Master_Log_Pos is equal to Exec_Master_Log_Pos;
+}
+change master to master_user='root';
+let $read_pos= query_get_value(SHOW SLAVE STATUS, Read_Master_Log_Pos, 1);
+let $exec_pos= query_get_value(SHOW SLAVE STATUS, Exec_Master_Log_Pos, 1);
+if ($read_pos != $exec_pos)
+{
+ source include/show_rpl_debug_info.inc;
+ echo 'Read_Master_Log_Pos: $read_pos' <> 'Exec_Master_Log_Pos: $exec_pos';
+ die Failed because Read_Master_Log_Pos is not equal to Exec_Master_Log_Pos;
+}
+
+start slave;
+sync_with_master;
+select * from t1;
+connection master;
+drop table t1;
+sync_slave_with_master;
+
+# End of 4.1 tests
+
+#
+# BUG#12190 CHANGE MASTER has differ path requiremts on MASTER_LOG_FILE and RELAY_LOG_FILE
+#
+
+if ($bug_59037_is_fixed == 'true') {
+--source include/rpl_reset.inc
+
+connection master;
+create table t1 (a int);
+insert into t1 values (1);
+flush logs;
+insert into t1 values (2);
+
+# Note: the master positon saved by this will also be used by the
+# 'sync_with_master' below.
+sync_slave_with_master;
+
+# Check if the table t1 and t2 are identical on master and slave;
+let $diff_tables= master:t1,slave:t1
+source include/diff_tables.inc;
+
+connection slave;
+source include/stop_slave.inc;
+delete from t1 where a=2;
+
+# start replication from the second insert, after fix of BUG#12190,
+# relay_log_file does not use absolute path, only the filename is
+# required
+#
+# Note: the follow change master will automatically reset
+# relay_log_purge to false, save the old value to restore
+let $relay_log_purge= `select @@global.relay_log_purge`;
+CHANGE MASTER TO relay_log_file='slave-relay-bin.000005', relay_log_pos=4;
+start slave sql_thread;
+source include/wait_for_slave_sql_to_start.inc;
+
+# Sync to the same position saved by the 'sync_slave_with_master' above.
+sync_with_master;
+
+# Check if the table t1 and t2 are identical on master and slave;
+let $diff_tables= master:t1,slave:t1
+source include/diff_tables.inc;
+
+# clean up
+connection slave;
+start slave io_thread;
+source include/wait_for_slave_io_to_start.inc;
+eval set global relay_log_purge=$relay_log_purge;
+connection master;
+drop table t1;
+}
+
+--connection master
+# MDEV-22741: *SAN: ERROR: AddressSanitizer: use-after-poison on address in
+# instrings/strmake.c:36 from change_master (on optimized builds)
+CHANGE MASTER TO MASTER_USER='root', MASTER_SSL=0, MASTER_SSL_CA='', MASTER_SSL_CERT='',
+ MASTER_SSL_KEY='', MASTER_SSL_CRL='', MASTER_SSL_CRLPATH='';
+CHANGE MASTER TO MASTER_USER='root', MASTER_PASSWORD='', MASTER_SSL=0;
+
+
+# MDEV-20122: Deprecate MASTER_USE_GTID=Current_Pos to favor new MASTER_DEMOTE_TO_SLAVE option
+--echo "Usage of CURRENT_POS in CHANGE MASTER MASTER_USE_GTID is dreprecated.
+CHANGE MASTER TO MASTER_USE_GTID=CURRENT_POS;
+CHANGE MASTER TO MASTER_USE_GTID=SLAVE_POS;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_change_master_demote.test b/mysql-test/suite/rpl/t/rpl_change_master_demote.test
new file mode 100644
index 00000000..15b55014
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_change_master_demote.test
@@ -0,0 +1,470 @@
+#
+# Purpose:
+#
+# This test suite ensures that the MASTER_DEMOTE_TO_SLAVE option of
+# CHANGE MASTER TO will merge the binlog GTID position (gtid_binlog_pos) into
+# the replication state (gtid_slave_pos).
+#
+#
+# Methodology:
+#
+# A series of test cases validate that MASTER_DEMOTE_TO_SLAVE correctly
+# merges the binlog GTID state into the replication state. Each test case
+# sets up the context in which it will demote the master to a slave, and then
+# calls into an include file to perform the actual demotion and validation.
+# Specifically, the include file will demote the master to be the slave,
+# promote the slave to be the master, ensure that gtid_slave_pos matches
+# gtid_current_pos, ensure replication works correctly in this new
+# configuration, and return the master and slave to their previous roles.
+#
+# The test cases are as follows:
+# 1) When both gtid_binlog_pos and gtid_slave_pos are empty,
+# MASTER_DEMOTE_TO_SLAVE=1 results in no change to replication state.
+#
+# 2) If gtid_slave_pos is empty, gtid_binlog_pos will completely
+# overwrite it with MASTER_DEMOTE_TO_SLAVE=1.
+#
+# 3) Using a single domain id, if neither gtid_slave_pos nor
+# gtid_binlog_pos are empty, and gtid_binlog_pos is more recent, then
+# gtid_binlog_pos will overwrite gtid_slave_pos when MASTER_DEMOTE_TO_SLAVE=1.
+#
+# 4) If gtid_slave_pos and gtid_binlog_pos are equivalent,
+# MASTER_DEMOTE_TO_SLAVE=1 will not change gtid_slave_pos.
+#
+# 5) If multiple new domain ids are added into gtid_binlog_pos while
+# gtid_slave_pos already has a state, MASTER_DEMOTE_TO_SLAVE=1 will append
+# new GTIDs to gtid_slave_pos with the latest seq_no from each domain.
+#
+# 6) If gtid_slave_pos has multiple GTID positions and gtid_binlog_pos
+# contains updates on existing domain ids, new domains, and differing
+# server_ids, MASTER_DEMOTE_TO_SLAVE=1 will update gtid_slave_pos such that
+# it will have the seq_nos only from the GTIDs last applied by this server.
+# In other words, any GTIDs with server ids that don't match that of the
+# demoting server will be ignored in the update.
+#
+# 7) If MASTER_DEMOTE_TO_SLAVE=1 is combined with IGNORE_DOMAIN_IDS such
+# that gtid_binlog_pos has more recent GTIDs than gtid_slave_pos in ignored
+# domains, the CHANGE MASTER TO command will still update gtid_slave_pos with
+# the most recent transactions from gtid_binlog_pos, despite being ignored by
+# CHANGE MASTER TO because they were already applied on the server.
+#
+# 8) If gtid_binlog_pos is more recent than gtid_slave_pos, and
+# MASTER_DEMOTE_TO_SLAVE=1 is combined with a later call to
+# START SLAVE UNTIL master_gtid_pos=<G> such that
+# gtid_slave_pos < G < gtid_binlog_pos, then the slave should stop
+# immediately after SSU because gtid_slave_pos should already be after the
+# UNTIL GTID.
+#
+# 9) If gtid_slave_pos is more recent than gtid_binlog_pos when demoting
+# the master to become a slave, the replication state should be preserved.
+#
+# 10) MASTER_DEMOTE_TO_SLAVE=0 should not change replication state,
+# regardless of gtid_slave_pos in comparison to gtid_binlog_pos.
+#
+#
+# Error cases:
+# Error Case 1) MASTER_DEMOTE_TO_SLAVE=1 combined with
+# MASTER_USE_GTID=NO should result in an error.
+#
+# Error Case 2) Error when MASTER_DEMOTE_TO_SLAVE=1 is used without
+# binary logging enabled.
+#
+# Error Case 3) Error when MASTER_DEMOTE_TO_SLAVE is provided a
+# non-boolean value.
+#
+#
+# References:
+# MDEV-19801: Change defaults for CHANGE MASTER TO so that GTID-based
+# replication is used by default if master supports it
+#
+--source include/master-slave.inc
+--source include/have_log_bin.inc
+--source include/have_binlog_format_mixed.inc
+
+--connection slave
+--source include/stop_slave.inc
+change master to master_use_gtid=slave_pos;
+--source include/start_slave.inc
+--source include/sync_with_master_gtid.inc
+
+--echo #
+--echo # Test Case 1: When both gtid_binlog_pos and gtid_slave_pos are
+--echo # empty, MASTER_DEMOTE_TO_SLAVE=1 results in no change to replication
+--echo # state.
+--echo #
+--source include/rpl_change_master_demote.inc
+
+
+--echo #
+--echo # Test Case 2: If gtid_slave_pos is empty, gtid_binlog_pos will
+--echo # completely overwrite it with MASTER_DEMOTE_TO_SLAVE=1.
+--echo #
+--connection slave
+--source include/stop_slave.inc
+RESET MASTER;
+set @@global.gtid_slave_pos="";
+--source include/start_slave.inc
+--connection master
+RESET MASTER;
+set @@global.gtid_slave_pos="";
+set session gtid_domain_id= 0;
+CREATE TABLE t1 (a int);
+INSERT INTO t1 VALUES (1);
+--source include/save_master_gtid.inc
+--connection slave
+--source include/sync_with_master_gtid.inc
+--source include/rpl_change_master_demote.inc
+
+
+--echo #
+--echo # Test Case 3: Using a single domain id, if neither gtid_slave_pos nor
+--echo # gtid_binlog_pos are empty, and gtid_binlog_pos is more recent, then
+--echo # gtid_binlog_pos will overwrite gtid_slave_pos when
+--echo # MASTER_DEMOTE_TO_SLAVE=1.
+--echo #
+--connection master
+INSERT INTO t1 VALUES (2);
+--source include/save_master_gtid.inc
+--connection slave
+--source include/sync_with_master_gtid.inc
+--source include/rpl_change_master_demote.inc
+
+
+--echo #
+--echo # Test Case 4: If gtid_slave_pos and gtid_binlog_pos are equivalent,
+--echo # MASTER_DEMOTE_TO_SLAVE=1 will not change gtid_slave_pos.
+--echo #
+--connection master
+
+--echo # update gtid_binlog_pos and demote it (we have proven this works)
+INSERT INTO t1 VALUES (3);
+--echo # Update to account for statements to verify replication in include file
+--replace_result $SLAVE_MYPORT SLAVE_PORT
+--eval CHANGE MASTER TO master_host='127.0.0.1', master_port=$SLAVE_MYPORT, master_user='root', master_use_gtid=slave_pos, master_demote_to_slave=1
+RESET SLAVE ALL;
+
+--source include/save_master_gtid.inc
+--connection slave
+--source include/sync_with_master_gtid.inc
+--source include/rpl_change_master_demote.inc
+
+
+--echo #
+--echo # Test Case 5: If a new domain id is added into gtid_binlog_pos while
+--echo # gtid_slave_pos already has a state, MASTER_DEMOTE_TO_SLAVE=1 will
+--echo # append a new GTID to gtid_slave_pos with the latest seq_no from that
+--echo # domain.
+--echo #
+--connection master
+
+--echo # Domain_id
+set session gtid_domain_id= 0;
+INSERT INTO t1 VALUES (4);
+
+set session gtid_domain_id= 1;
+CREATE TABLE t2 (a int);
+INSERT INTO t2 VALUES (1);
+
+--source include/save_master_gtid.inc
+--connection slave
+--source include/sync_with_master_gtid.inc
+--source include/rpl_change_master_demote.inc
+
+
+--echo #
+--echo # Test Case 6: If gtid_slave_pos has multiple GTID positions and
+--echo # gtid_binlog_pos contains updates on existing domain ids, new
+--echo # domains, and differing server_ids, MASTER_DEMOTE_TO_SLAVE=1 will
+--echo # update gtid_slave_pos such that it will have the seq_nos only from
+--echo # the GTIDs last applied by this server. In other words, any GTIDs
+--echo # with server ids that don't match that of the demoting server will be
+--echo # ignored in the update.
+--echo #
+
+--connection master
+--echo # Update to account for statements to verify replication in include file
+set session gtid_domain_id= 0;
+INSERT INTO t1 VALUES (5);
+--replace_result $SLAVE_MYPORT SLAVE_PORT
+--eval CHANGE MASTER TO master_host='127.0.0.1', master_port=$SLAVE_MYPORT, master_user='root', master_use_gtid=slave_pos, master_demote_to_slave=1
+RESET SLAVE ALL;
+
+set session gtid_domain_id= 1;
+INSERT INTO t2 VALUES (2);
+
+set session gtid_domain_id= 2;
+CREATE TABLE t3 (a int);
+INSERT INTO t3 VALUES (1);
+
+--echo # The following events have a different server_id and should not go into
+--echo # gtid_slave_pos
+set @old_server_id = @@server_id;
+set session gtid_domain_id= 1;
+set session server_id= 3;
+INSERT INTO t2 VALUES (3);
+
+set session gtid_domain_id= 4;
+set session server_id= 3;
+CREATE TABLE t5 (a int);
+INSERT INTO t5 VALUES (1);
+set session server_id= @old_server_id;
+
+--source include/save_master_gtid.inc
+--connection slave
+--source include/sync_with_master_gtid.inc
+--source include/rpl_change_master_demote.inc
+
+
+--echo #
+--echo # Test Case 7: If MASTER_DEMOTE_TO_SLAVE=1 is combined with
+--echo # IGNORE_DOMAIN_IDS such that gtid_binlog_pos has more recent GTIDs
+--echo # than gtid_slave_pos in ignored domains, the CHANGE MASTER TO command
+--echo # will still update gtid_slave_pos with the most recent transactions
+--echo # from gtid_binlog_pos, despite being ignored by CHANGE MASTER TO
+--echo # because they were already applied on the server.
+--echo #
+--connection master
+
+set session gtid_domain_id= 2;
+INSERT INTO t3 VALUES (2);
+
+set session gtid_domain_id= 3;
+CREATE TABLE t4 (a int);
+INSERT INTO t4 VALUES (1);
+
+--source include/save_master_gtid.inc
+--connection slave
+--source include/sync_with_master_gtid.inc
+--let $ignore_domain_ids=2,3
+--source include/rpl_change_master_demote.inc
+
+
+--echo #
+--echo # Test Case 8: If gtid_binlog_pos is more recent than gtid_slave_pos,
+--echo # and MASTER_DEMOTE_TO_SLAVE=1 is combined with a later call to
+--echo # START SLAVE UNTIL master_gtid_pos=<G> such that
+--echo # gtid_slave_pos < G < gtid_binlog_pos, then the slave should stop
+--echo # immediately after SSU because gtid_slave_pos should be updated to be
+--echo # after G.
+--echo #
+
+--connection master
+set session gtid_domain_id= 0;
+INSERT INTO t1 VALUES (6);
+--let $ssu_middle_binlog_pos= `SELECT @@GLOBAL.gtid_binlog_pos`
+--echo # Tagging ssu_middle_binlog_pos here to be used for START SLAVE UNTIL
+INSERT INTO t1 VALUES (7);
+--source include/save_master_gtid.inc
+
+--echo # Ensure slave is up-to-date with master and then disable slave status
+--connection slave
+--source include/sync_with_master_gtid.inc
+--source include/stop_slave.inc
+
+--connection master
+SELECT VARIABLE_NAME, GLOBAL_VALUE FROM INFORMATION_SCHEMA.SYSTEM_VARIABLES WHERE VARIABLE_NAME LIKE 'gtid_binlog_pos' OR VARIABLE_NAME LIKE 'gtid_slave_pos' ORDER BY VARIABLE_NAME ASC;
+--replace_result $SLAVE_MYPORT SLAVE_PORT
+--eval CHANGE MASTER TO master_host='127.0.0.1', master_port=$SLAVE_MYPORT, master_user='root', master_use_gtid=Slave_Pos, master_demote_to_slave=1
+SELECT VARIABLE_NAME, GLOBAL_VALUE FROM INFORMATION_SCHEMA.SYSTEM_VARIABLES WHERE VARIABLE_NAME LIKE 'gtid_binlog_pos' OR VARIABLE_NAME LIKE 'gtid_slave_pos' ORDER BY VARIABLE_NAME ASC;
+
+--echo # GTID ssu_middle_binlog_pos should be considered in the past because
+--echo # gtid_slave_pos should be updated using the latest binlog gtids.
+--echo # The following call to sync_with_master_gtid.inc uses the latest
+--echo # binlog position and should still succeed despite the SSU stop
+--echo # position pointing to a previous event (because
+--echo # master_demote_to_slave=1 merges gtid_binlog_pos into gtid_slave_pos).
+--replace_result $ssu_middle_binlog_pos ssu_middle_binlog_pos
+eval START SLAVE UNTIL master_gtid_pos="$ssu_middle_binlog_pos";
+
+--echo # Slave needs time to start and stop automatically
+# Note sync_with_master_gtid.inc, wait_for_slave_to_start.inc, and
+# wait_for_slave_to_stop.inc won't work due to replication state and race
+# conditions
+--sleep 1
+
+--echo # Validating neither SQL nor IO threads are running..
+--let $io_state= query_get_value("SHOW SLAVE STATUS", Slave_IO_State, 1)
+if (`SELECT strcmp("$io_state","") != 0`)
+{
+ die "IO thread should not be running after START SLAVE UNTIL master_gtid_pos using a pre-existing GTID";
+}
+--let $sql_state= query_get_value("SHOW SLAVE STATUS", Slave_SQL_Running_State, 1)
+if (`SELECT strcmp("$sql_state","") != 0`)
+{
+ die "SQL thread should not be running after START SLAVE UNTIL master_gtid_pos using a pre-existing GTID";
+}
+--echo # ..success
+
+--echo # Clean slave state of master
+RESET SLAVE ALL;
+
+
+--echo #
+--echo # Test Case 9: If gtid_slave_pos is more recent than gtid_binlog_pos
+--echo # when demoting the master to become a slave, the replication state
+--echo # should be preserved.
+--echo #
+
+--echo # rpl_change_master_demote.inc should force
+--echo # gtid_slave_pos > gtid_binlog_pos in domain 0 (due to the step which
+--echo # validates replication works)
+--connection master
+--source include/rpl_change_master_demote.inc
+
+--let $current_pos= `SELECT @@gtid_current_pos`
+
+--echo # Demote master to slave with the more recent gtid_slave_pos
+--connection master
+--let $old_slave_pos= `SELECT @@gtid_slave_pos`
+--replace_result $SLAVE_MYPORT SLAVE_PORT
+--eval CHANGE MASTER TO master_host='127.0.0.1', master_port=$SLAVE_MYPORT, master_user='root', master_use_gtid=slave_pos, master_demote_to_slave=1
+--let $new_slave_pos= `SELECT @@gtid_slave_pos`
+
+--echo # Validating gtid_slave_pos is unchanged..
+if ($old_slave_pos != $new_slave_pos)
+{
+ SELECT VARIABLE_NAME, GLOBAL_VALUE FROM INFORMATION_SCHEMA.SYSTEM_VARIABLES WHERE VARIABLE_NAME LIKE 'gtid_binlog_pos' OR VARIABLE_NAME LIKE 'gtid_slave_pos' OR VARIABLE_NAME LIKE 'gtid_current_pos' ORDER BY VARIABLE_NAME ASC;
+ die "gtid_slave_pos should not change when MASTER_DEMOTE_TO_SLAVE=0";
+}
+--echo # ..success
+
+--echo # Validating gtid_slave_pos == gtid_binlog_pos..
+if ($new_slave_pos != $current_pos)
+{
+ SELECT VARIABLE_NAME, GLOBAL_VALUE FROM INFORMATION_SCHEMA.SYSTEM_VARIABLES WHERE VARIABLE_NAME LIKE 'gtid_binlog_pos' OR VARIABLE_NAME LIKE 'gtid_slave_pos' OR VARIABLE_NAME LIKE 'gtid_current_pos' ORDER BY VARIABLE_NAME ASC;
+ die gtid_slave_pos calculation after master_demote_to_slave=1 differs from gtid_current_pos;
+}
+--echo # ..success
+
+--echo # Clean slave state of master
+RESET SLAVE ALL;
+
+
+--echo #
+--echo # Test Case 10: MASTER_DEMOTE_TO_SLAVE=0 should not change replication
+--echo # state, regardless of gtid_slave_pos in comparison to gtid_binlog_pos.
+--echo #
+
+--echo # In domain 0, make gtid_slave_pos > gtid_binlog_pos
+--connection master
+--source include/rpl_change_master_demote.inc
+
+--echo # Tag gtid_slave_pos now (before binlog updates) for later comparison
+--let $old_slave_pos= `SELECT @@gtid_slave_pos`
+
+--connection master
+--echo # In domain 1, make gtid_slave_pos < gtid_binlog_pos
+set session gtid_domain_id= 1;
+INSERT INTO t2 VALUES (4);
+
+--echo # In domains 2, 3 and 4, gtid_slave_pos == gtid_binlog_pos
+
+--echo # Include a new domain id (5)
+set session gtid_domain_id= 5;
+CREATE TABLE t6 (a int);
+INSERT INTO t6 VALUES (1);
+
+SELECT VARIABLE_NAME, GLOBAL_VALUE FROM INFORMATION_SCHEMA.SYSTEM_VARIABLES WHERE VARIABLE_NAME LIKE 'gtid_binlog_pos' OR VARIABLE_NAME LIKE 'gtid_slave_pos' ORDER BY VARIABLE_NAME ASC;
+--replace_result $SLAVE_MYPORT SLAVE_PORT
+--eval CHANGE MASTER TO master_host='127.0.0.1', master_port=$SLAVE_MYPORT, master_user='root', master_use_gtid=slave_pos, master_demote_to_slave=0
+
+--echo # Validating gtid_slave_pos is unchanged..
+--let $new_slave_pos= `SELECT @@gtid_slave_pos`
+if ($old_slave_pos != $new_slave_pos)
+{
+ SELECT VARIABLE_NAME, GLOBAL_VALUE FROM INFORMATION_SCHEMA.SYSTEM_VARIABLES WHERE VARIABLE_NAME LIKE 'gtid_binlog_pos' OR VARIABLE_NAME LIKE 'gtid_slave_pos' ORDER BY VARIABLE_NAME ASC;
+ die gtid_slave_pos should not change when MASTER_DEMOTE_TO_SLAVE=0;
+}
+--echo # ..success
+
+--echo # Clean slave state of master
+--replace_result $SLAVE_MYPORT SLAVE_PORT
+--eval CHANGE MASTER TO master_host='127.0.0.1', master_port=$SLAVE_MYPORT, master_user='root', master_use_gtid=slave_pos, master_demote_to_slave=1
+RESET SLAVE ALL;
+SELECT VARIABLE_NAME, GLOBAL_VALUE FROM INFORMATION_SCHEMA.SYSTEM_VARIABLES WHERE VARIABLE_NAME LIKE 'gtid_binlog_pos' OR VARIABLE_NAME LIKE 'gtid_slave_pos' ORDER BY VARIABLE_NAME ASC;
+
+
+--echo #
+--echo #
+--echo # Stop slave for error test cases
+--connection slave
+--source include/stop_slave.inc
+
+--echo #
+--echo # Error Case 1: MASTER_DEMOTE_TO_SLAVE=1 combined with
+--echo # MASTER_USE_GTID=NO should result in an error.
+--echo #
+--connection master
+--replace_result $SLAVE_MYPORT SLAVE_PORT
+--error 4191
+--eval CHANGE MASTER TO master_host='127.0.0.1', master_port=$SLAVE_MYPORT, master_user='root', master_use_gtid=no, master_demote_to_slave=1
+
+
+--echo #
+--echo # Error Case 2: Error when MASTER_DEMOTE_TO_SLAVE=1 is used without
+--echo # binary logging enabled.
+--echo #
+--connection master
+
+--echo # Restarting master without binary log
+--write_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
+wait
+EOF
+--shutdown_server
+--source include/wait_until_disconnected.inc
+--append_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
+restart: --skip-slave-start=1 --skip-log-bin
+EOF
+--enable_reconnect
+--source include/wait_until_connected_again.inc
+
+--replace_result $SLAVE_MYPORT SLAVE_PORT
+--error 1381
+--eval CHANGE MASTER TO master_host='127.0.0.1', master_port=$SLAVE_MYPORT, master_user='root', master_use_gtid=Slave_Pos, master_demote_to_slave=1
+
+--echo # Restarting master to re-enable binary log
+--write_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
+wait
+EOF
+--shutdown_server
+--source include/wait_until_disconnected.inc
+--append_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
+restart: --skip-slave-start=1
+EOF
+--enable_reconnect
+--source include/wait_until_connected_again.inc
+
+--connection server_1
+--enable_reconnect
+--source include/wait_until_connected_again.inc
+
+--connection default
+--enable_reconnect
+--source include/wait_until_connected_again.inc
+
+
+--echo #
+--echo # Error Case 3: Error when MASTER_DEMOTE_TO_SLAVE is provided a
+--echo # non-boolean value.
+--echo #
+
+--connection master
+--replace_result $SLAVE_MYPORT SLAVE_PORT
+--error 1064
+--eval CHANGE MASTER TO master_host='127.0.0.1', master_port=$SLAVE_MYPORT, master_user='root', master_use_gtid=Slave_Pos, master_demote_to_slave=invalid
+
+
+--echo #
+--echo # Cleanup
+--echo #
+--connection master
+DROP TABLE t1, t2, t3, t4, t5, t6;
+--source include/save_master_gtid.inc
+
+--connection slave
+--source include/start_slave.inc
+--source include/sync_with_master_gtid.inc
+
+--source include/rpl_end.inc
+--echo #
+--echo ### End rpl_change_master_demote.test
diff --git a/mysql-test/suite/rpl/t/rpl_change_master_find_log_pos_err.test b/mysql-test/suite/rpl/t/rpl_change_master_find_log_pos_err.test
new file mode 100644
index 00000000..d1c2c03f
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_change_master_find_log_pos_err.test
@@ -0,0 +1,93 @@
+#
+# Purpose:
+# This test ensures that issuing a CHANGE MASTER will not put a replica into
+# an inconsistent state if the slave cannot find the log files (i.e. the call to
+# find_log_pos in reset_logs fails). More specifically, right before a replica
+# purges the relay logs (part of the `CHANGE MASTER TO` logic), the relay log is
+# temporarily closed with state LOG_TO_BE_OPENED. If the server is issued a
+# CHANGE MASTER and it errors in-between the temporary log closure and purge,
+# i.e. during the function find_log_pos, the log should be closed. The bug
+# reported by MDEV-25284 revealed the log is not properly closed, such that
+# future relay log updates fail, and future CHANGE MASTER calls crash the
+# server.
+#
+# Methodology:
+# This test ensures that the relay log is properly closed by ensuring future
+# updates and CHANGE MASTER calls succeed.
+#
+# References:
+# MDEV-25284: Assertion `info->type == READ_CACHE ||
+# info->type == WRITE_CACHE' failed
+#
+--source include/master-slave.inc
+--source include/have_debug.inc
+
+--echo #
+--echo # Failed CHANGE MASTER TO should not change relay log status
+--echo #
+
+--connection slave
+--source include/stop_slave.inc
+SET @@debug_dbug="d,simulate_find_log_pos_error";
+error 1373;
+CHANGE MASTER TO IGNORE_DOMAIN_IDS=(1), MASTER_USE_GTID=SLAVE_POS;
+SET @@debug_dbug="";
+--source include/start_slave.inc
+
+
+--echo #
+--echo # Ensure relay log can be updated after a failed CHANGE MASTER
+--echo #
+
+FLUSH RELAY LOGS;
+--let $slave_param= Relay_Log_File
+--let $slave_param_value= slave-relay-bin.000003
+--source include/wait_for_slave_param.inc
+
+
+--echo #
+--echo # Slave should continue to receive data from old master after failed
+--echo # CHANGE MASTER TO
+--echo #
+
+--connection master
+CREATE TABLE t1 (a int);
+insert into t1 values (1);
+--let $master_checksum= `CHECKSUM TABLE t1`
+--sync_slave_with_master
+
+--connection slave
+if ($master_checksum != `CHECKSUM TABLE t1`)
+{
+ die("Replica failed to pull data from primary after failed CHANGE MASTER TO");
+}
+
+
+--echo #
+--echo # Future CHANGE MASTER calls should succeed
+--echo #
+
+--source include/stop_slave.inc
+CHANGE MASTER TO MASTER_USE_GTID=SLAVE_POS;
+--source include/start_slave.inc
+
+
+--echo ########################
+--echo # Cleanup
+--echo ########################
+
+--connection master
+DROP TABLE t1;
+
+--connection slave
+--source include/stop_slave.inc
+RESET SLAVE ALL;
+--replace_result $MASTER_MYPORT MASTER_MYPORT
+eval change master to master_port=$MASTER_MYPORT, master_host='127.0.0.1', master_user='root';
+--source include/start_slave.inc
+
+--disable_query_log
+call mtr.add_suppression("Failed to locate old binlog or relay log files");
+--enable_query_log
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_charset.test b/mysql-test/suite/rpl/t/rpl_charset.test
new file mode 100644
index 00000000..31ea2bc8
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_charset.test
@@ -0,0 +1,2 @@
+let $engine_type=myisam;
+source include/rpl_charset.test;
diff --git a/mysql-test/suite/rpl/t/rpl_charset_sjis.test b/mysql-test/suite/rpl/t/rpl_charset_sjis.test
new file mode 100644
index 00000000..af4e8ff5
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_charset_sjis.test
@@ -0,0 +1,54 @@
+source include/have_sjis.inc;
+source include/master-slave.inc;
+
+--disable_warnings
+drop table if exists t1;
+drop procedure if exists p1;
+--enable_warnings
+create table t1 (a varchar(255) character set sjis);
+create procedure p1 (in a varchar(255) character set sjis) insert into t1 values (a);
+
+SET NAMES binary;
+CALL p1 ('–\\');
+select hex(a) from t1 ;
+sync_slave_with_master;
+connection slave;
+select hex(a) from t1;
+connection master;
+drop table t1;
+drop procedure p1;
+sync_slave_with_master;
+connection master;
+
+# End of 5.0 tests
+
+--echo #
+--echo # Start of 5.5 tests
+--echo #
+
+--echo #
+--echo # Bug#MDEV-4489 Replication of big5, cp932, gbk, sjis strings makes wrong values on slave
+--echo #
+
+connection master;
+SET NAMES sjis;
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (0x31),(X'31'),('1');
+PREPARE stmt FROM 'INSERT INTO t1 (a) VALUES (?)';
+SET @a='1';
+EXECUTE stmt USING @a;
+DROP PREPARE stmt;
+SELECT * FROM t1;
+sync_slave_with_master;
+connection slave;
+SELECT * FROM t1;
+connection master;
+DROP TABLE t1;
+sync_slave_with_master;
+connection master;
+
+--echo #
+--echo # End of 5.5 tests
+--echo #
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_checksum-master.opt b/mysql-test/suite/rpl/t/rpl_checksum-master.opt
new file mode 100644
index 00000000..a6e99a9f
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_checksum-master.opt
@@ -0,0 +1 @@
+--binlog-checksum=CRC32
diff --git a/mysql-test/suite/rpl/t/rpl_checksum.test b/mysql-test/suite/rpl/t/rpl_checksum.test
new file mode 100644
index 00000000..fc765744
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_checksum.test
@@ -0,0 +1,342 @@
+#
+# This include file is used by more than one test suite
+# (currently rpl and binlog_encryption).
+# Please check all dependent tests after modifying it
+#
+
+# WL2540 replication events checksum
+# Testing configuration parameters
+
+--source include/have_debug.inc
+--source include/have_binlog_format_mixed.inc
+--source include/master-slave.inc
+
+--connection slave
+--source include/stop_slave.inc
+CHANGE MASTER TO MASTER_USE_GTID=NO;
+--source include/start_slave.inc
+
+--connection master
+call mtr.add_suppression('Slave can not handle replication events with the checksum that master is configured to log');
+call mtr.add_suppression('Replication event checksum verification failed');
+# due to C failure simulation
+call mtr.add_suppression('Relay log write failure: could not queue event from master');
+call mtr.add_suppression('Master is configured to log replication events with checksum, but will not send such events to slaves that cannot process them');
+
+# A. read/write access to the global vars:
+# binlog_checksum master_verify_checksum slave_sql_verify_checksum
+
+connection master;
+
+set @master_save_binlog_checksum= @@global.binlog_checksum;
+set @save_master_verify_checksum = @@global.master_verify_checksum;
+
+select @@global.binlog_checksum as 'must be CRC32 because of the command line option';
+--error ER_INCORRECT_GLOBAL_LOCAL_VAR
+select @@session.binlog_checksum as 'no session var';
+
+select @@global.master_verify_checksum as 'must be zero because of default';
+--error ER_INCORRECT_GLOBAL_LOCAL_VAR
+select @@session.master_verify_checksum as 'no session var';
+
+connection slave;
+
+set @slave_save_binlog_checksum= @@global.binlog_checksum;
+set @save_slave_sql_verify_checksum = @@global.slave_sql_verify_checksum;
+
+select @@global.slave_sql_verify_checksum as 'must be one because of default';
+--error ER_INCORRECT_GLOBAL_LOCAL_VAR
+select @@session.slave_sql_verify_checksum as 'no session var';
+
+connection master;
+
+source include/show_binary_logs.inc;
+set @@global.binlog_checksum = NONE;
+select @@global.binlog_checksum;
+--echo *** must be rotations seen ***
+source include/show_binary_logs.inc;
+
+set @@global.binlog_checksum = default;
+select @@global.binlog_checksum;
+
+# testing lack of side-effects in non-effective update of binlog_checksum:
+set @@global.binlog_checksum = CRC32;
+select @@global.binlog_checksum;
+set @@global.binlog_checksum = CRC32;
+
+set @@global.master_verify_checksum = 0;
+set @@global.master_verify_checksum = default;
+
+--error ER_WRONG_VALUE_FOR_VAR
+set @@global.binlog_checksum = ADLER32;
+--error ER_WRONG_VALUE_FOR_VAR
+set @@global.master_verify_checksum = 2; # the var is of bool type
+
+connection slave;
+
+set @@global.slave_sql_verify_checksum = 0;
+set @@global.slave_sql_verify_checksum = default;
+--error ER_WRONG_VALUE_FOR_VAR
+set @@global.slave_sql_verify_checksum = 2; # the var is of bool type
+
+#
+# B. Old Slave to New master conditions
+#
+# while master does not send a checksum-ed binlog the Old Slave can
+# work with the New Master
+
+connection master;
+
+set @@global.binlog_checksum = NONE;
+create table t1 (a int);
+
+# testing that binlog rotation preserves opt_binlog_checksum value
+flush logs;
+flush logs;
+-- source include/wait_for_binlog_checkpoint.inc
+flush logs;
+
+sync_slave_with_master;
+#connection slave;
+# checking that rotation on the slave side leaves slave stable
+flush logs;
+flush logs;
+flush logs;
+select count(*) as zero from t1;
+
+source include/stop_slave.inc;
+
+connection master;
+set @@global.binlog_checksum = CRC32;
+-- source include/wait_for_binlog_checkpoint.inc
+insert into t1 values (1) /* will not be applied on slave due to simulation */;
+
+# instruction to the dump thread
+
+connection slave;
+set @saved_dbug = @@global.debug_dbug;
+set @@global.debug_dbug='d,simulate_slave_unaware_checksum';
+start slave;
+--let $slave_io_errno= 1236
+--let $show_slave_io_error= 1
+source include/wait_for_slave_io_error.inc;
+
+select count(*) as zero from t1;
+
+set @@global.debug_dbug = @saved_dbug;
+
+connection slave;
+source include/start_slave.inc;
+
+#
+# C. checksum failure simulations
+#
+
+# C1. Failure by a client thread
+connection master;
+set @@global.master_verify_checksum = 1;
+set @save_dbug = @@session.debug_dbug;
+set @@session.debug_dbug='d,simulate_checksum_test_failure';
+--error ER_ERROR_WHEN_EXECUTING_COMMAND
+show binlog events;
+SET debug_dbug= @save_dbug;
+set @@global.master_verify_checksum = default;
+
+#connection master;
+sync_slave_with_master;
+
+connection slave;
+source include/stop_slave.inc;
+
+connection master;
+create table t2 (a int);
+let $pos_master= query_get_value(SHOW MASTER STATUS, Position, 1);
+
+connection slave;
+
+# C2. Failure by IO thread
+# instruction to io thread
+set @saved_dbug = @@global.debug_dbug;
+set @@global.debug_dbug='d,simulate_checksum_test_failure';
+start slave io_thread;
+# When the checksum error is detected, the slave sets error code 1913
+# (ER_NETWORK_READ_EVENT_CHECKSUM_FAILURE) in queue_event(), then immediately
+# sets error 1595 (ER_SLAVE_RELAY_LOG_WRITE_FAILURE) in handle_slave_io().
+# So we usually get 1595, but it is occasionally possible to get 1913.
+--let $slave_io_errno= 1595,1913
+--let $show_slave_io_error= 0
+source include/wait_for_slave_io_error.inc;
+set @@global.debug_dbug = @saved_dbug;
+
+# to make IO thread re-read it again w/o the failure
+start slave io_thread;
+let $slave_param= Read_Master_Log_Pos;
+let $slave_param_value= $pos_master;
+source include/wait_for_slave_param.inc;
+
+# C3. Failure by SQL thread
+# instruction to sql thread;
+set @@global.slave_sql_verify_checksum = 1;
+
+set @@global.debug_dbug='d,simulate_checksum_test_failure';
+
+start slave sql_thread;
+--let $slave_sql_errno= 1593
+--let $show_slave_sql_error= 1
+source include/wait_for_slave_sql_error.inc;
+
+# resuming SQL thread to parse out the event w/o the failure
+
+set @@global.debug_dbug = @saved_dbug;
+source include/start_slave.inc;
+
+connection master;
+sync_slave_with_master;
+
+#connection slave;
+select count(*) as 'must be zero' from t2;
+
+#
+# D. Reset slave, Change-Master, Binlog & Relay-log rotations with
+# random value on binlog_checksum on both master and slave
+#
+connection slave;
+stop slave;
+--let $master_use_gtid_option= No
+--source include/reset_slave.inc
+
+# randomize slave server's own checksum policy
+set @@global.binlog_checksum= IF(floor((rand()*1000)%2), "CRC32", "NONE");
+flush logs;
+
+connection master;
+set @@global.binlog_checksum= CRC32;
+reset master;
+flush logs;
+create table t3 (a int, b char(5));
+
+connection slave;
+source include/start_slave.inc;
+
+connection master;
+sync_slave_with_master;
+
+#connection slave;
+select count(*) as 'must be zero' from t3;
+source include/stop_slave.inc;
+--replace_result $MASTER_MYPORT MASTER_PORT
+eval change master to master_host='127.0.0.1',master_port=$MASTER_MYPORT, master_user='root';
+
+connection master;
+flush logs;
+reset master;
+insert into t3 value (1, @@global.binlog_checksum);
+
+connection slave;
+source include/start_slave.inc;
+flush logs;
+
+connection master;
+sync_slave_with_master;
+
+#connection slave;
+select count(*) as 'must be one' from t3;
+
+connection master;
+set @@global.binlog_checksum= IF(floor((rand()*1000)%2), "CRC32", "NONE");
+insert into t3 value (1, @@global.binlog_checksum);
+sync_slave_with_master;
+
+#connection slave;
+
+#clean-up
+
+connection master;
+drop table t1, t2, t3;
+set @@global.binlog_checksum = @master_save_binlog_checksum;
+set @@global.master_verify_checksum = @save_master_verify_checksum;
+
+#
+# BUG#58564: flush_read_lock fails in mysql-trunk-bugfixing after merging with WL#2540
+#
+# Sanity check that verifies that no assertions are triggered because
+# of old FD events (generated by versions prior to server released with
+# checksums feature)
+#
+# There is no need for query log, if something wrong this should trigger
+# an assertion
+
+--disable_query_log
+
+BINLOG '
+MfmqTA8BAAAAZwAAAGsAAAABAAQANS41LjctbTMtZGVidWctbG9nAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAx+apMEzgNAAgAEgAEBAQEEgAAVAAEGggAAAAICAgCAA==
+';
+
+--enable_query_log
+
+#connection slave;
+sync_slave_with_master;
+
+
+--echo *** Bug#59123 / MDEV-5799: INCIDENT_EVENT checksum written to error log as garbage characters ***
+
+--connection master
+
+--source include/wait_for_binlog_checkpoint.inc
+CREATE TABLE t4 (a INT PRIMARY KEY);
+INSERT INTO t4 VALUES (1);
+
+SET sql_log_bin=0;
+CALL mtr.add_suppression("\\[ERROR\\] Can't generate a unique log-filename");
+SET sql_log_bin=1;
+SET @old_dbug= @@GLOBAL.debug_dbug;
+SET debug_dbug= '+d,binlog_inject_new_name_error';
+--error ER_NO_UNIQUE_LOGFILE
+FLUSH LOGS;
+SET debug_dbug= @old_dbug;
+
+INSERT INTO t4 VALUES (2);
+
+--connection slave
+--let $slave_sql_errno= 1590
+--source include/wait_for_slave_sql_error.inc
+
+# Search the error log for the error message.
+# The bug was that 4 garbage bytes were output in the middle of the error
+# message; by searching for a pattern that spans that location, we can
+# catch the error.
+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.2.err;
+}
+--let SEARCH_FILE= $log_error_
+--let SEARCH_PATTERN= Slave SQL: The incident LOST_EVENTS occurred on the master\. Message: error writing to the binary log, Internal MariaDB error code: 1590
+--source include/search_pattern_in_file.inc
+
+SELECT * FROM t4 ORDER BY a;
+STOP SLAVE IO_THREAD;
+SET sql_slave_skip_counter= 1;
+--source include/start_slave.inc
+
+--connection master
+--save_master_pos
+
+--connection slave
+--sync_with_master
+SELECT * FROM t4 ORDER BY a;
+
+
+--connection slave
+set @@global.binlog_checksum = @slave_save_binlog_checksum;
+set @@global.slave_sql_verify_checksum = @save_slave_sql_verify_checksum;
+
+--echo End of tests
+
+--connection master
+DROP TABLE t4;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_checksum_cache.test b/mysql-test/suite/rpl/t/rpl_checksum_cache.test
new file mode 100644
index 00000000..e04f618b
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_checksum_cache.test
@@ -0,0 +1,261 @@
+#
+# This include file is used by more than one test suite
+# (currently rpl and binlog_encryption).
+# Please check all dependent tests after modifying it
+#
+
+-- source include/have_innodb.inc
+-- source include/master-slave.inc
+
+--disable_warnings
+call mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. .*Statement: insert into t2 set data=repeat.*'a', @act_size.*");
+call mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. .*Statement: insert into t1 values.* NAME_CONST.*'n',.*, @data .*");
+--enable_warnings
+
+connection master;
+set @save_binlog_cache_size = @@global.binlog_cache_size;
+set @save_binlog_checksum = @@global.binlog_checksum;
+set @save_master_verify_checksum = @@global.master_verify_checksum;
+set @@global.binlog_cache_size = 4096;
+set @@global.binlog_checksum = CRC32;
+set @@global.master_verify_checksum = 1;
+
+# restart slave to force the dump thread to verify events (on master side)
+connection slave;
+source include/stop_slave.inc;
+source include/start_slave.inc;
+
+connection master;
+
+#
+# Testing a critical part of checksum handling dealing with transaction cache.
+# The cache's buffer size is set to be less than the transaction's footprint
+# in binlog.
+#
+# To verify combined buffer-by-buffer read out of the file and fixing crc per event
+# there are the following parts:
+#
+# 1. the event size is much less than the cache's buffer
+# 2. the event size is bigger than the cache's buffer
+# 3. the event size if approximately the same as the cache's buffer
+# 4. all in above
+
+#
+# 1. the event size is much less than the cache's buffer
+#
+
+flush status;
+show status like "binlog_cache_use";
+show status like "binlog_cache_disk_use";
+--disable_warnings
+drop table if exists t1;
+--enable_warnings
+
+#
+# parameter to ensure the test slightly varies binlog content
+# between different invocations
+#
+let $deviation_size=32;
+eval create table t1 (a int PRIMARY KEY, b CHAR($deviation_size)) engine=innodb;
+
+# Now we are going to create transaction which is long enough so its
+# transaction binlog will be flushed to disk...
+
+delimiter |;
+create procedure test.p_init (n int, size int)
+begin
+ while n > 0 do
+ select round(RAND() * size) into @act_size;
+ set @data = repeat('a', @act_size);
+ insert into t1 values(n, @data );
+ set n= n-1;
+ end while;
+end|
+
+delimiter ;|
+
+let $1 = 4000; # PB2 can run it slow to time out on following sync_slave_with_master:s
+
+begin;
+--disable_warnings
+# todo: check if it is really so.
+#+Note 1592 Unsafe statement binlogged in statement format since BINLOG_FORMAT = STATEMENT. Reason for unsafeness: Statement uses a system function whose value may differ on slave.
+eval call test.p_init($1, $deviation_size);
+--enable_warnings
+commit;
+
+show status like "binlog_cache_use";
+--echo *** binlog_cache_disk_use must be non-zero ***
+show status like "binlog_cache_disk_use";
+
+sync_slave_with_master;
+
+let $diff_tables=master:test.t1, slave:test.t1;
+source include/diff_tables.inc;
+
+# undoing changes with verifying the above once again
+connection master;
+
+begin;
+delete from t1;
+commit;
+
+sync_slave_with_master;
+
+
+#
+# 2. the event size is bigger than the cache's buffer
+#
+connection master;
+
+flush status;
+let $t2_data_size= `select 3 * @@global.binlog_cache_size`;
+let $t2_aver_size= `select 2 * @@global.binlog_cache_size`;
+let $t2_max_rand= `select 1 * @@global.binlog_cache_size`;
+
+eval create table t2(a int auto_increment primary key, data VARCHAR($t2_data_size)) ENGINE=Innodb;
+let $1=100;
+--disable_query_log
+begin;
+while ($1)
+{
+ eval select round($t2_aver_size + RAND() * $t2_max_rand) into @act_size;
+ set @data = repeat('a', @act_size);
+ insert into t2 set data = @data;
+ dec $1;
+}
+commit;
+--enable_query_log
+show status like "binlog_cache_use";
+--echo *** binlog_cache_disk_use must be non-zero ***
+show status like "binlog_cache_disk_use";
+
+sync_slave_with_master;
+
+let $diff_tables=master:test.t2, slave:test.t2;
+source include/diff_tables.inc;
+
+# undoing changes with verifying the above once again
+connection master;
+
+begin;
+delete from t2;
+commit;
+
+sync_slave_with_master;
+
+#
+# 3. the event size if approximately the same as the cache's buffer
+#
+
+connection master;
+
+flush status;
+let $t3_data_size= `select 2 * @@global.binlog_cache_size`;
+let $t3_aver_size= `select (9 * @@global.binlog_cache_size) / 10`;
+let $t3_max_rand= `select (2 * @@global.binlog_cache_size) / 10`;
+
+eval create table t3(a int auto_increment primary key, data VARCHAR($t3_data_size)) engine=innodb;
+
+let $1= 300;
+--disable_query_log
+begin;
+while ($1)
+{
+ eval select round($t3_aver_size + RAND() * $t3_max_rand) into @act_size;
+ insert into t3 set data= repeat('a', @act_size);
+ dec $1;
+}
+commit;
+--enable_query_log
+show status like "binlog_cache_use";
+--echo *** binlog_cache_disk_use must be non-zero ***
+show status like "binlog_cache_disk_use";
+
+sync_slave_with_master;
+
+let $diff_tables=master:test.t3, slave:test.t3;
+source include/diff_tables.inc;
+
+# undoing changes with verifying the above once again
+connection master;
+
+begin;
+delete from t3;
+commit;
+
+sync_slave_with_master;
+
+
+#
+# 4. all in above
+#
+
+connection master;
+flush status;
+
+delimiter |;
+eval create procedure test.p1 (n int)
+begin
+ while n > 0 do
+ case (select (round(rand()*100) % 3) + 1)
+ when 1 then
+ select round(RAND() * $deviation_size) into @act_size;
+ set @data = repeat('a', @act_size);
+ insert into t1 values(n, @data);
+ when 2 then
+ begin
+ select round($t2_aver_size + RAND() * $t2_max_rand) into @act_size;
+ insert into t2 set data=repeat('a', @act_size);
+ end;
+ when 3 then
+ begin
+ select round($t3_aver_size + RAND() * $t3_max_rand) into @act_size;
+ insert into t3 set data= repeat('a', @act_size);
+ end;
+ end case;
+ set n= n-1;
+ end while;
+end|
+delimiter ;|
+
+let $1= 1000;
+set autocommit= 0;
+begin;
+--disable_warnings
+eval call test.p1($1);
+--enable_warnings
+commit;
+
+show status like "binlog_cache_use";
+--echo *** binlog_cache_disk_use must be non-zero ***
+show status like "binlog_cache_disk_use";
+
+sync_slave_with_master;
+
+let $diff_tables=master:test.t1, slave:test.t1;
+source include/diff_tables.inc;
+
+let $diff_tables=master:test.t2, slave:test.t2;
+source include/diff_tables.inc;
+
+let $diff_tables=master:test.t3, slave:test.t3;
+source include/diff_tables.inc;
+
+
+connection master;
+
+begin;
+delete from t1;
+delete from t2;
+delete from t3;
+commit;
+
+drop table t1, t2, t3;
+set @@global.binlog_cache_size = @save_binlog_cache_size;
+set @@global.binlog_checksum = @save_binlog_checksum;
+set @@global.master_verify_checksum = @save_master_verify_checksum;
+drop procedure test.p_init;
+drop procedure test.p1;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_circular_for_4_hosts.cnf b/mysql-test/suite/rpl/t/rpl_circular_for_4_hosts.cnf
new file mode 100644
index 00000000..3ff94e45
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_circular_for_4_hosts.cnf
@@ -0,0 +1,24 @@
+!include ../my.cnf
+
+[mysqld.1]
+log-slave-updates
+loose-innodb
+
+[mysqld.2]
+log-slave-updates
+loose-innodb
+
+[mysqld.3]
+log-slave-updates
+loose-innodb
+
+[mysqld.4]
+log-slave-updates
+loose-innodb
+
+[ENV]
+SERVER_MYPORT_3= @mysqld.3.port
+SERVER_MYSOCK_3= @mysqld.3.socket
+
+SERVER_MYPORT_4= @mysqld.4.port
+SERVER_MYSOCK_4= @mysqld.4.socket
diff --git a/mysql-test/suite/rpl/t/rpl_circular_for_4_hosts.test b/mysql-test/suite/rpl/t/rpl_circular_for_4_hosts.test
new file mode 100644
index 00000000..aeb849b8
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_circular_for_4_hosts.test
@@ -0,0 +1,339 @@
+# ==== Purpose ====
+#
+# Setup: circular replication on four hosts, i.e., topology
+# server_1 -> server_2 -> server_3 -> server_4 -> server_1
+#
+# Tested properties:
+# - Correctly configured autoinc works.
+# - Manual failover works.
+#
+# ==== Related bugs and worklogs ====
+#
+# WL#3754
+# BUG#49978
+
+--source include/have_innodb.inc
+
+# Use wait_for_slave_to_(start|stop) for current connections
+let $keep_connection= 1;
+
+# Set up circular ring and new names for servers
+--echo *** Set up circular replication on four servers ***
+--let $rpl_topology= 1->2->3->4->1
+--source include/rpl_init.inc
+--echo
+
+#set auto inc variables at each server
+--let $_rpl_server= $rpl_server_count
+while ($_rpl_server)
+{
+ connection server_$_rpl_server;
+ eval SET auto_increment_increment= $rpl_server_count;
+ eval SET auto_increment_offset= $_rpl_server;
+
+ --dec $_rpl_server
+}
+
+# Preparing data.
+--echo *** Preparing data ***
+--connection server_1
+CREATE TABLE t1 (a INT NOT NULL AUTO_INCREMENT, b VARCHAR(100), c INT NOT NULL, PRIMARY KEY(a)) ENGINE=MyISAM;
+CREATE TABLE t2 (a INT NOT NULL AUTO_INCREMENT, b VARCHAR(100), c INT NOT NULL, PRIMARY KEY(a)) ENGINE=InnoDB;
+# MDEV-515 takes X-lock on the table. So it won't allow
+# concurrent DML to happen at the same time
+INSERT INTO t2 (b,c) VALUES('MDEV-515', 100);
+--source include/rpl_sync.inc
+--connection server_4
+call mtr.add_suppression("Slave SQL.*Request to stop slave SQL Thread received while applying a group that has non-transactional changes; waiting for completion of the group");
+--echo
+
+#
+# Testing
+#
+
+--echo *** Testing schema A->B->C->D->A ***
+--echo
+# insert data via all hosts
+--connection server_1
+INSERT INTO t1(b,c) VALUES('A',1);
+--sync_slave_with_master server_2
+INSERT INTO t1(b,c) VALUES('B',1);
+--sync_slave_with_master server_3
+INSERT INTO t1(b,c) VALUES('C',1);
+--sync_slave_with_master server_4
+INSERT INTO t1(b,c) VALUES('D',1);
+
+--source include/rpl_sync.inc
+
+--connection server_1
+SELECT 'Master A',a,b FROM t1 WHERE c = 1 ORDER BY a,b;
+--connection server_2
+SELECT 'Master B',a,b FROM t1 WHERE c = 1 ORDER BY a,b;
+--connection server_3
+SELECT 'Master C',a,b FROM t1 WHERE c = 1 ORDER BY a,b;
+--connection server_4
+SELECT 'Master D',a,b FROM t1 WHERE c = 1 ORDER BY a,b;
+--echo
+
+--echo *** Testing schema A->B->D->A if C has failure ***
+--echo
+--echo * Do failure for C and then make new connection B->D *
+
+# Note: server_N has auto_increment_offset=N. Below, we insert value 6
+# in the autoinc column on server_3 (and prevent it from replicating
+# further using SQL_SLAVE_SKIP_COUNTER on server_4). Due to the
+# auto_increment_offset setting, the autoinc value 6 is normally
+# generated on server_2. When we later insert a row on server_2, we
+# thus cause a duplicate key error on server_3.
+
+# Do not replicate next event from C
+--connection server_4
+STOP SLAVE;
+SET GLOBAL SQL_SLAVE_SKIP_COUNTER = 1;
+source include/start_slave.inc;
+--connection server_3
+INSERT INTO t1 VALUES(6,'C',2);
+--sync_slave_with_master server_4
+
+--connection server_2
+INSERT INTO t1(b,c) VALUES('B',2);
+# Wait while C will stop.
+--connection server_3
+# 1062 = ER_DUP_ENTRY
+call mtr.add_suppression("Slave SQL.*Duplicate entry .6. for key .PRIMARY.* error.* 1062");
+--let $slave_sql_errno= 1062
+--source include/wait_for_slave_sql_error.inc
+--connection server_1
+INSERT INTO t1(b,c) VALUES('A',2);
+--connection server_4
+INSERT INTO t1(b,c) VALUES('D',2);
+
+
+# Sync all servers except C
+--connection server_2
+let $wait_condition= SELECT COUNT(*)=3 FROM t1 WHERE a > 4;
+--let $server_connection= server_1
+--source include/wait_condition.inc
+
+--echo
+--echo * Data on servers (C failed) *
+# Masters C,D shouldn't have correct data
+--connection server_1
+SELECT 'Master A',a,b FROM t1 WHERE c = 2 ORDER BY a,b;
+--connection server_2
+SELECT 'Master B',a,b FROM t1 WHERE c = 2 ORDER BY a,b;
+--connection server_3
+SELECT 'Master C',a,b FROM t1 WHERE c = 2 ORDER BY a,b;
+--connection server_4
+SELECT 'Master D',a,b FROM t1 WHERE c = 2 ORDER BY a,b;
+--echo
+
+--echo * Reconfigure replication to schema A->B->D->A *
+# Exclude Master C
+--connection server_3
+--source include/stop_slave_io.inc
+--let $pos_c= query_get_value(SHOW SLAVE STATUS, Exec_Master_Log_Pos, 1)
+--let $file_c= query_get_value(SHOW SLAVE STATUS, Master_Log_File, 1)
+
+--connection server_4
+--source include/stop_slave.inc
+
+--let $rpl_topology= 1->2->4->1,2->3
+--let $rpl_master_log_file= 4:$file_c
+--let $rpl_master_log_pos= 4:$pos_c
+--source include/rpl_change_topology.inc
+
+#--replace_result $SERVER_MYPORT_2 SERVER_MYPORT_2 $file_c LOG_FILE $pos_c LOG_POS
+#--eval CHANGE MASTER TO master_host='127.0.0.1',master_port=$SERVER_MYPORT_2,master_user='root',master_log_file='$file_c',master_log_pos=$pos_c
+source include/start_slave.inc;
+--connection server_2
+--sync_slave_with_master server_4
+--sync_slave_with_master server_1
+--echo
+
+--echo * Check data inserted before failure *
+--connection server_1
+SELECT 'Master A',a,b FROM t1 WHERE c = 2 ORDER BY a,b;
+--connection server_2
+SELECT 'Master B',a,b FROM t1 WHERE c = 2 ORDER BY a,b;
+--connection server_3
+SELECT 'Master C',a,b FROM t1 WHERE c = 2 ORDER BY a,b;
+--connection server_4
+SELECT 'Master D',a,b FROM t1 WHERE c = 2 ORDER BY a,b;
+--echo
+
+--echo * Check data inserted after failure *
+--connection server_1
+INSERT INTO t1(b,c) VALUES('A',3);
+--connection server_2
+INSERT INTO t1(b,c) VALUES('B',3);
+--connection server_4
+INSERT INTO t1(b,c) VALUES('D',3);
+connection server_1;
+
+--let $rpl_only_running_threads= 1
+--source include/rpl_sync.inc
+
+--connection server_1
+SELECT 'Master A',a,b FROM t1 WHERE c = 3 ORDER BY a,b;
+--connection server_2
+SELECT 'Master B',a,b FROM t1 WHERE c = 3 ORDER BY a,b;
+--connection server_3
+SELECT 'Master C',a,b FROM t1 WHERE c = 3 ORDER BY a,b;
+--connection server_4
+SELECT 'Master D',a,b FROM t1 WHERE c = 3 ORDER BY a,b;
+--connection server_1
+--echo
+
+--echo *** Testing restoring scheme A->B->C->D->A after failure ***
+--echo
+# Master D will ignore a next event from C so that event will not be
+# distributed to other servers
+--echo * Remove wrong event from C and restore B->C->D *
+--connection server_4
+source include/stop_slave.inc;
+--connection server_3
+DELETE FROM t1 WHERE a = 6;
+--source include/start_slave.inc
+--connection server_2
+--sync_slave_with_master server_3
+RESET MASTER;
+--let $file_d= query_get_value(SHOW MASTER STATUS, File, 1)
+--let $pos_d= query_get_value(SHOW MASTER STATUS, Position, 1)
+--connection server_4
+RESET SLAVE;
+--let $rpl_topology= 1->2->3->4->1
+--let $rpl_master_log_file= 4:$file_d
+--let $rpl_master_log_pos= 4:$pos_d
+--source include/rpl_change_topology.inc
+#--replace_result $SERVER_MYPORT_3 SERVER_MYPORT_3 $file_d LOG_FILE $pos_d LOG_POS
+#--eval CHANGE MASTER TO master_host='127.0.0.1',master_port=$SERVER_MYPORT_3,master_user='root',master_log_file='$file_d',master_log_pos=$pos_d
+--source include/start_slave.inc
+--connection server_3
+--sync_slave_with_master server_4
+--source include/rpl_sync.inc
+
+--echo
+--echo * Check data inserted before restoring schema A->B->C->D->A *
+--connection server_1
+SELECT 'Master A',a,b FROM t1 WHERE c IN (2,3) ORDER BY a,b;
+--sync_slave_with_master server_2
+SELECT 'Master B',a,b FROM t1 WHERE c IN (2,3) ORDER BY a,b;
+--sync_slave_with_master server_3
+SELECT 'Master C',a,b FROM t1 WHERE c IN (2,3) ORDER BY a,b;
+--sync_slave_with_master server_4
+SELECT 'Master D',a,b FROM t1 WHERE c IN (2,3) ORDER BY a,b;
+--sync_slave_with_master server_1
+--echo
+
+--echo * Check data inserted after restoring schema A->B->C->D->A *
+--connection server_1
+INSERT INTO t1(b,c) VALUES('A',4);
+--connection server_2
+INSERT INTO t1(b,c) VALUES('B',4);
+--connection server_3
+INSERT INTO t1(b,c) VALUES('C',4);
+--connection server_4
+INSERT INTO t1(b,c) VALUES('D',4);
+--connection server_1
+
+--source include/rpl_sync.inc
+
+--connection server_1
+SELECT 'Master A',a,b FROM t1 WHERE c = 4 ORDER BY a,b;
+--connection server_2
+SELECT 'Master B',a,b FROM t1 WHERE c = 4 ORDER BY a,b;
+--connection server_3
+SELECT 'Master C',a,b FROM t1 WHERE c = 4 ORDER BY a,b;
+--connection server_4
+SELECT 'Master D',a,b FROM t1 WHERE c = 4 ORDER BY a,b;
+--connection server_1
+--echo
+
+--echo * Transactions with commits *
+# Testing mixing of transactions and regular inserts
+--connection server_1
+BEGIN;
+--connection server_3
+BEGIN;
+let $counter= 100;
+--connection server_1
+--disable_query_log
+while ($counter) {
+ --connection server_1
+ INSERT INTO t2(b,c) VALUES('A',1);
+ --connection server_2
+ INSERT INTO t2(b,c) VALUES('B',1);
+ --connection server_3
+ INSERT INTO t2(b,c) VALUES('C',1);
+ --connection server_4
+ INSERT INTO t2(b,c) VALUES('D',1);
+ dec $counter;
+}
+--connection server_1
+COMMIT;
+--connection server_3
+COMMIT;
+--connection server_1
+--enable_query_log
+
+--source include/rpl_sync.inc
+
+--connection server_1
+SELECT 'Master A',b,COUNT(*) FROM t2 WHERE c = 1 GROUP BY b ORDER BY b;
+--connection server_2
+SELECT 'Master B',b,COUNT(*) FROM t2 WHERE c = 1 GROUP BY b ORDER BY b;
+--connection server_3
+SELECT 'Master C',b,COUNT(*) FROM t2 WHERE c = 1 GROUP BY b ORDER BY b;
+--connection server_4
+SELECT 'Master D',b,COUNT(*) FROM t2 WHERE c = 1 GROUP BY b ORDER BY b;
+--connection server_1
+--echo
+
+--echo * Transactions with rollbacks *
+# Testing mixing of transactions with rollback and regular inserts
+--connection server_1
+BEGIN;
+--connection server_3
+BEGIN;
+let $counter= 100;
+--connection server_1
+--disable_query_log
+while ($counter) {
+ --connection server_1
+ INSERT INTO t2(b,c) VALUES('A',2);
+ --connection server_2
+ INSERT INTO t2(b,c) VALUES('B',2);
+ --connection server_3
+ INSERT INTO t2(b,c) VALUES('C',2);
+ --connection server_4
+ INSERT INTO t2(b,c) VALUES('D',2);
+ dec $counter;
+}
+--connection server_1
+ROLLBACK;
+--connection server_3
+ROLLBACK;
+--connection server_1
+--enable_query_log
+
+--source include/rpl_sync.inc
+
+--connection server_1
+SELECT 'Master A',b,COUNT(*) FROM t2 WHERE c = 2 GROUP BY b ORDER BY b;
+--connection server_2
+SELECT 'Master B',b,COUNT(*) FROM t2 WHERE c = 2 GROUP BY b ORDER BY b;
+--connection server_3
+SELECT 'Master C',b,COUNT(*) FROM t2 WHERE c = 2 GROUP BY b ORDER BY b;
+--connection server_4
+SELECT 'Master D',b,COUNT(*) FROM t2 WHERE c = 2 GROUP BY b ORDER BY b;
+--connection server_1
+
+--echo
+
+# Clean up
+--echo *** Clean up ***
+--connection server_1
+DROP TABLE t1,t2;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_circular_semi_sync.cnf b/mysql-test/suite/rpl/t/rpl_circular_semi_sync.cnf
new file mode 100644
index 00000000..be39fea9
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_circular_semi_sync.cnf
@@ -0,0 +1,11 @@
+!include suite/rpl/rpl_1slave_base.cnf
+!include include/default_client.cnf
+
+
+[mysqld.1]
+log-slave-updates
+sync-binlog=1
+
+[mysqld.2]
+log-slave-updates
+sync-binlog=1
diff --git a/mysql-test/suite/rpl/t/rpl_circular_semi_sync.test b/mysql-test/suite/rpl/t/rpl_circular_semi_sync.test
new file mode 100644
index 00000000..267fa621
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_circular_semi_sync.test
@@ -0,0 +1,188 @@
+# ==== References ====
+#
+# MDEV-27760 event may non stop replicate in circular semisync setup
+# MDEV-28609 refine gtid-strict-mode to ignore same server-id gtid from the past
+# on semisync slave
+--source include/have_innodb.inc
+--source include/have_binlog_format_mixed.inc
+--source include/master-slave.inc
+
+# The following tests prove
+# A.
+# no out-of-order gtid error is done to the stict gtid mode semisync
+# slave receives the same server-id gtid event from the past (of its gtid
+# state). Such transaction is silently ignored similarly to
+# replicate_same_sever_id; and
+# B.
+# In contrast to A. the out-of-order gtid error is thrown when a "foreign"
+# server-id transaction makes its round-trip to the originator server.
+
+--echo # Master server_1 and Slave server_2 initialization ...
+--connection server_2
+--source include/stop_slave.inc
+
+# Initial master
+--connection server_1
+RESET MASTER;
+set @@session.gtid_domain_id=10;
+set @@global.rpl_semi_sync_master_enabled = 1;
+set @@global.rpl_semi_sync_master_wait_point=AFTER_SYNC;
+
+--connection server_2
+RESET MASTER;
+ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
+set @@session.gtid_domain_id=20;
+set @@global.rpl_semi_sync_slave_enabled = 1;
+--echo # a 1948 warning is expected
+set @@global.gtid_slave_pos = "";
+CHANGE MASTER TO master_use_gtid= slave_pos;
+--source include/start_slave.inc
+--echo # server_1 -> server_2 semisync link is set up.
+
+--connection server_1
+CREATE TABLE t1 (a INT PRIMARY KEY, b INT default 0) ENGINE=Innodb;
+INSERT INTO t1(a) VALUES (1);
+--source include/save_master_gtid.inc
+
+--connection server_2
+--source include/sync_with_master_gtid.inc
+
+--echo # Circular configuration server_1 -> server_2 -> server_1 ...
+--connection server_1
+set @@global.gtid_strict_mode = true;
+set @@global.rpl_semi_sync_slave_enabled = 1;
+
+evalp CHANGE MASTER TO master_host='127.0.0.1', master_port=$SERVER_MYPORT_2, master_user='root', master_use_gtid=SLAVE_POS;
+--source include/start_slave.inc
+--echo ... is done.
+
+--echo ## A. no out-of-order gtid error for own transaction made round trip
+
+# A0. server_1 has already originated the transaction
+--let $wait_condition=select @@gtid_slave_pos=@@gtid_binlog_pos
+--source include/wait_condition.inc
+
+# A1. server_2 originates
+--connection server_2
+set @@global.gtid_strict_mode = true;
+set @@global.rpl_semi_sync_master_enabled = 1;
+INSERT INTO t1(a) VALUES (2);
+--source include/save_master_gtid.inc
+
+--connection server_1
+--echo #
+--echo # the successful sync is a required proof
+--echo #
+--source include/sync_with_master_gtid.inc
+# A2. server_1 is originating now
+update t1 set b=b+1 where a=2;
+--source include/save_master_gtid.inc
+
+--connection server_2
+--source include/sync_with_master_gtid.inc
+
+--echo # Post-execution state check on both servers synchronized with each other
+--connection server_1
+--echo # ... the gtid states on server_1
+--let $wait_condition=select @@gtid_slave_pos=@@gtid_binlog_pos
+--source include/wait_condition.inc
+SHOW VARIABLES LIKE 'gtid_slave_pos';
+SHOW VARIABLES LIKE 'gtid_binlog_pos';
+SELECT * from t1;
+
+--connection server_2
+--echo # The gtid states on server_2 must be equal to ...
+--let $wait_condition=select @@gtid_slave_pos=@@gtid_binlog_pos
+--source include/wait_condition.inc
+SHOW VARIABLES LIKE 'gtid_binlog_pos';
+SHOW VARIABLES LIKE 'gtid_slave_pos';
+SELECT * from t1;
+
+--echo ## B. out-of-order gtid error for a "foreign" server-id transaction
+# B1. circulation starts from server_1
+
+--connection server_1
+set statement sql_log_bin=0 for call mtr.add_suppression("Slave: An attempt was made to binlog GTID 10-2-4");
+set @@session.server_id=2;
+INSERT INTO t1(a) VALUES (3);
+set @@session.server_id=default;
+--source include/save_master_gtid.inc
+
+--connection server_2
+--source include/sync_with_master_gtid.inc
+INSERT INTO t1(a) VALUES (4);
+--source include/save_master_gtid.inc
+
+--connection server_1
+--let $slave_sql_errno = 1950
+--source include/wait_for_slave_sql_error.inc
+set sql_slave_skip_counter=1;
+--source include/start_slave.inc
+--source include/sync_with_master_gtid.inc
+
+# B2. circulation starts from server_2
+--connection server_2
+set statement sql_log_bin=0 for call mtr.add_suppression("Slave: An attempt was made to binlog GTID 20-1-3");
+set @@session.server_id=1;
+INSERT INTO t1(a) VALUES (5);
+set @@session.server_id=default;
+--source include/save_master_gtid.inc
+
+--connection server_1
+--source include/sync_with_master_gtid.inc
+INSERT INTO t1(a) VALUES (6);
+--source include/save_master_gtid.inc
+
+
+--connection server_2
+--let $slave_sql_errno = 1950
+--source include/wait_for_slave_sql_error.inc
+set sql_slave_skip_counter=1;
+--source include/start_slave.inc
+--source include/sync_with_master_gtid.inc
+
+--echo # Post-execution state check on both servers synchronized with each other
+--connection server_1
+--echo # ... the gtid states on server_1
+--let $wait_condition=select @@gtid_slave_pos=@@gtid_binlog_pos
+--source include/wait_condition.inc
+SHOW VARIABLES LIKE 'gtid_slave_pos';
+SHOW VARIABLES LIKE 'gtid_binlog_pos';
+SELECT * from t1;
+
+--connection server_2
+--source include/sync_with_master_gtid.inc
+--echo # The gtid states on server_2 must be equal to ...
+--let $wait_condition=select @@gtid_slave_pos=@@gtid_binlog_pos
+--source include/wait_condition.inc
+SHOW VARIABLES LIKE 'gtid_binlog_pos';
+SHOW VARIABLES LIKE 'gtid_slave_pos';
+SELECT * from t1;
+
+--echo #
+--echo # Cleanup
+--echo #
+--connection server_1
+DROP TABLE t1;
+--source include/save_master_gtid.inc
+
+--connection server_2
+--source include/sync_with_master_gtid.inc
+
+--connection server_1
+--source include/stop_slave.inc
+set @@global.rpl_semi_sync_master_enabled = default;
+set @@global.rpl_semi_sync_slave_enabled = default;
+set @@global.rpl_semi_sync_master_wait_point=default;
+set @@global.gtid_ignore_duplicates = default;
+set @@global.gtid_strict_mode = default;
+
+--connection server_2
+--source include/stop_slave.inc
+set @@global.gtid_ignore_duplicates = default;
+set @@global.rpl_semi_sync_master_enabled = default;
+set @@global.rpl_semi_sync_slave_enabled = default;
+set @@global.gtid_strict_mode = default;
+--source include/start_slave.inc
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_colSize.test b/mysql-test/suite/rpl/t/rpl_colSize.test
new file mode 100644
index 00000000..23c8bdc3
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_colSize.test
@@ -0,0 +1,228 @@
+##################################################################
+# rpl_colSize #
+# #
+# This test is designed to test the changes included in WL#3228. #
+# The changes include the ability to replicate with the master #
+# having columns that are smaller (shorter) than the slave. #
+##################################################################
+
+-- source include/master-slave.inc
+
+--disable_warnings
+DROP TABLE IF EXISTS t1;
+--enable_warnings
+
+--echo **** Testing WL#3228 changes. ****
+--echo *** Create "wider" table on slave ***
+sync_slave_with_master;
+STOP SLAVE;
+--source include/wait_for_slave_to_stop.inc
+--source include/reset_slave.inc
+
+SET @saved_slave_type_conversions = @@slave_type_conversions;
+SET GLOBAL SLAVE_TYPE_CONVERSIONS = 'ALL_NON_LOSSY';
+
+eval CREATE TABLE t1 (
+ a float (47),
+ b double (143,9),
+ c decimal (65,30),
+ d numeric (4,0),
+ e bit (32),
+ f char (21),
+ g varchar (1300),
+ h binary (33),
+ j varbinary (200),
+ k enum ('5','6','7', '8','9','0'),
+ l set ('1','2','3','4','5','6','7','8','9','0','11','12','13','14','15','16','17','18','19','21','22','23','24','25','26','27','28','29'),
+ m TINYBLOB,
+ n BLOB,
+ o MEDIUMBLOB,
+ p LONGBLOB,
+ q TINYTEXT,
+ r TEXT,
+ s MEDIUMTEXT,
+ t LONGTEXT
+);
+
+--echo *** Create same table on master but with narrow columns ***
+connection master;
+eval CREATE TABLE t1 (
+ a float (44),
+ b double (10,3),
+ c decimal (10,2),
+ d numeric (3,0),
+ e bit (16),
+ f char (10),
+ g varchar (100),
+ h binary (20),
+ j varbinary (20),
+ k enum ('5','6','7'),
+ l set ('1','2','3','4','5','6','7','8','9','0'),
+ m TINYBLOB,
+ n BLOB,
+ o MEDIUMBLOB,
+ p LONGBLOB,
+ q TINYTEXT,
+ r TEXT,
+ s MEDIUMTEXT,
+ t LONGTEXT
+);
+
+RESET MASTER;
+
+--echo *** Start replication ***
+connection slave;
+START SLAVE;
+--source include/wait_for_slave_to_start.inc
+
+--echo *** Insert data on master and display it. ***
+connection master;
+
+INSERT INTO t1 () VALUES (
+ 17.567,
+ 2.123,
+ 10.20,
+ 125,
+ hex(64),
+ 'TEST',
+ 'This is a test',
+ 'binary data',
+ 'more binary data',
+ '6',
+ '7',
+ "blob 1",
+ "blob 2",
+ "blob 3",
+ "blob 4",
+ "text 1",
+ "text 2",
+ "text 3",
+ "text 4");
+
+# Replace values in columns that display differently between SBR & RBR
+--replace_column 5 # 8 #
+SELECT * FROM t1 ORDER BY a;
+
+--echo *** Select data from slave to compare ***
+sync_slave_with_master;
+connection slave;
+
+# Replace values in columns that display differently between SBR & RBR
+--replace_column 5 # 8 #
+SELECT * FROM t1 ORDER BY a;
+
+# Test boundary limits of varchar and char fields
+# Master/Slave
+# <256/<256 with m < s, m > s, and m == s <-- col a
+# >255/<256 with m < s, m > s, and m == s <-- error will be caught in BUG#22086
+# <256/>255 with m < s, m > s, and m == s <-- col b
+# >255/>255 with m < s, m > s, and m == s <-- col c
+#
+# Test boundary limits of CHAR fields
+# Master/Slave
+# <256/<256 with m < s, m > s, and m == s <-- col d
+# >255/<256 with m < s, m > s, and m == s <-- error char limited to 255 chars
+# <256/>255 with m < s, m > s, and m == s <-- error char limited to 255 chars
+# >255/>255 with m < s, m > s, and m == s <-- error char limited to 255 chars
+
+connection master;
+DROP TABLE t1;
+
+--echo Create varchar table on master
+CREATE TABLE t1 (
+ a VARCHAR(50),
+ b VARCHAR(100),
+ c VARCHAR(300),
+ d CHAR(5)
+);
+
+sync_slave_with_master slave;
+
+--echo Alter varchar table on slave
+ALTER TABLE t1 CHANGE COLUMN a a VARCHAR(100);
+ALTER TABLE t1 CHANGE COLUMN b b VARCHAR(400);
+ALTER TABLE t1 CHANGE COLUMN c c VARCHAR(500);
+ALTER TABLE t1 CHANGE COLUMN d d CHAR(100);
+
+connection master;
+
+--echo Insert some values and select them on master
+INSERT INTO t1 VALUES ("This is a test of col a.",
+ "This is another test of col b.",
+ "This is a test of the large col c.",
+ "Col d");
+SELECT * FROM t1;
+--replace_result default DEFAULT
+SHOW CREATE TABLE t1;
+
+sync_slave_with_master slave;
+
+--echo Insert some values and select them on slave
+SELECT * FROM t1;
+--replace_result default DEFAULT
+SHOW CREATE TABLE t1;
+
+
+# Test boundary limits of bit fields
+# m < s, m % 8 != 0, and s % 8 == 0 col a
+# m < s, m % 8 == 0, and s % 8 != 0 col b
+# m < s, m % 8 != 0, and s % 8 != 0 col c
+# m > s, m % 8 != 0, and s % 8 == 0 <-- error will be caught in BUG#22086
+# m > s, m % 8 == 0, and s % 8 != 0 <-- error will be caught in BUG#22086
+# m > s, m % 8 != 0, and s % 8 != 0 <-- error will be caught in BUG#22086
+
+connection master;
+DROP TABLE t1;
+
+--echo Create bit table on master
+CREATE TABLE t1 (
+ a BIT(7),
+ b BIT(8),
+ c BIT(21),
+ d BIT(11),
+ e BIT(11)
+);
+
+sync_slave_with_master slave;
+
+--echo Create bit table on slave
+DROP TABLE t1;
+CREATE TABLE t1 (
+ a BIT(16),
+ b BIT(22),
+ c BIT(54),
+ d BIT(25),
+ e BIT(13)
+);
+
+connection master;
+
+--echo Insert some values and select them on master
+INSERT INTO t1 VALUES (
+ b'1010101',
+ b'10101011',
+ b'101010110101010101111',
+ b'10101010101',
+ b'10101011111'
+ );
+
+SELECT BIN(a), BIN(b), BIN(c), BIN(d), BIN(e) FROM t1;
+--replace_result default DEFAULT
+SHOW CREATE TABLE t1;
+
+sync_slave_with_master slave;
+
+--echo Insert some values and select them on master
+SELECT BIN(a), BIN(b), BIN(c), BIN(d), BIN(e) FROM t1;
+--replace_result default DEFAULT
+SHOW CREATE TABLE t1;
+
+--echo *** Cleanup ***
+connection master;
+DROP TABLE t1;
+sync_slave_with_master;
+
+SET GLOBAL SLAVE_TYPE_CONVERSIONS = @saved_slave_type_conversions;
+
+# END 5.1 Test Case
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_commit_after_flush.test b/mysql-test/suite/rpl/t/rpl_commit_after_flush.test
new file mode 100644
index 00000000..5d547908
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_commit_after_flush.test
@@ -0,0 +1,5 @@
+-- source include/have_innodb.inc
+-- source include/master-slave.inc
+let $engine_type=innodb;
+-- source include/rpl_commit_after_flush.test
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_concurrency_error-master.opt b/mysql-test/suite/rpl/t/rpl_concurrency_error-master.opt
new file mode 100644
index 00000000..3f82baff
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_concurrency_error-master.opt
@@ -0,0 +1 @@
+--loose-innodb-lock-wait-timeout=1
diff --git a/mysql-test/suite/rpl/t/rpl_concurrency_error.test b/mysql-test/suite/rpl/t/rpl_concurrency_error.test
new file mode 100644
index 00000000..72179ef2
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_concurrency_error.test
@@ -0,0 +1,150 @@
+###############################################################################
+#BUG#44581 Slave stops when transaction with non-transactional table gets
+#lock wait timeout
+#
+# In STMT and MIXED modes, a statement that changes both non-transactional and
+# transactional tables must be written to the binary log whenever there are
+# changes to non-transactional tables. This means that the statement gets into
+# the # binary log even when the changes to the transactional tables fail. In
+# particular, in the presence of a failure such statement is annotated with the
+# error number and wrapped in a begin/rollback. On the slave, while applying
+# the statement, it is expected the same failure and the rollback prevents the
+# transactional changes to be persisted.
+
+# This test aims to verify if a statement that updates both transactional and
+# non-transacitonal tables and fails due to concurrency problems is correctly
+# processed by the slave in the sense that the statements get into the binary
+# log, the error is ignored and only the non-transactional tables are changed.
+###############################################################################
+
+--source include/have_innodb.inc
+--source include/have_binlog_format_statement.inc
+--source include/master-slave.inc
+
+call mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT");
+
+--echo ########################################################################
+--echo # Environment
+--echo ########################################################################
+connection master;
+
+CREATE TABLE t (i INT, PRIMARY KEY(i), f CHAR(8)) engine = Innodb;
+CREATE TABLE n (d DATETIME, f CHAR(32)) engine = MyIsam;
+
+DELIMITER |;
+CREATE TRIGGER tr AFTER UPDATE ON t FOR EACH ROW
+BEGIN
+ INSERT INTO n VALUES ( now(), concat( 'updated t: ', old.f, ' -> ', new.f ) );
+END |
+DELIMITER ;|
+
+INSERT INTO t VALUES (4,'black'), (2,'red'), (3,'yelow'), (1,'cyan');
+
+connect (conn1, 127.0.0.1,root,,);
+connect (conn2, 127.0.0.1,root,,);
+
+--echo ########################################################################
+--echo # Testing ER_LOCK_WAIT_TIMEOUT
+--echo ########################################################################
+
+let $type=2;
+
+while ($type)
+{
+ let $binlog_start= query_get_value("SHOW MASTER STATUS", Position, 1);
+ connection conn1;
+ if ($type == 2)
+ {
+ SET AUTOCOMMIT = 1;
+ BEGIN;
+ }
+ if ($type == 1)
+ {
+ SET AUTOCOMMIT = 0;
+ }
+ eval UPDATE t SET f = 'yellow $type' WHERE i = 3;
+
+ connection conn2;
+ if ($type == 2)
+ {
+ SET AUTOCOMMIT = 1;
+ BEGIN;
+ }
+ if ($type == 1)
+ {
+ SET AUTOCOMMIT = 0;
+ }
+ --error ER_LOCK_WAIT_TIMEOUT
+ eval UPDATE IGNORE t SET f = 'magenta $type' WHERE f = 'red';
+ eval INSERT INTO t VALUES (5 + ($type * 10),"brown");
+ INSERT INTO n VALUES (now(),"brown");
+
+ connection conn1;
+ COMMIT;
+
+ connection conn2;
+ ROLLBACK;
+ --source include/show_binlog_events.inc
+
+ let $binlog_start= query_get_value("SHOW MASTER STATUS", Position, 1);
+ connection conn1;
+ if ($type == 2)
+ {
+ SET AUTOCOMMIT = 1;
+ BEGIN;
+ }
+ if ($type == 1)
+ {
+ SET AUTOCOMMIT = 0;
+ }
+ eval UPDATE t SET f = 'gray $type' WHERE i = 3;
+
+ connection conn2;
+ if ($type == 2)
+ {
+ SET AUTOCOMMIT = 1;
+ BEGIN;
+ }
+ if ($type == 1)
+ {
+ SET AUTOCOMMIT = 0;
+ }
+ --error ER_LOCK_WAIT_TIMEOUT
+ eval UPDATE IGNORE t SET f = 'dark blue $type' WHERE f = 'red';
+ eval INSERT INTO t VALUES (6 + ($type * 10),"brown");
+ INSERT INTO n VALUES (now(),"brown");
+
+ connection conn1;
+ COMMIT;
+
+ connection conn2;
+ COMMIT;
+ --source include/show_binlog_events.inc
+
+ dec $type;
+}
+
+connection master;
+sync_slave_with_master;
+
+let $rpl_diff_statement= SELECT * FROM t order by i;
+source include/rpl_diff.inc;
+
+let $rpl_diff_statement= SELECT * FROM n order by d, f;
+source include/rpl_diff.inc;
+
+--echo ########################################################################
+--echo # Cleanup
+--echo ########################################################################
+
+connection master;
+DROP TRIGGER tr;
+DROP TABLE t;
+DROP TABLE n;
+
+sync_slave_with_master;
+
+connection master;
+disconnect conn1;
+disconnect conn2;
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_conditional_comments.test b/mysql-test/suite/rpl/t/rpl_conditional_comments.test
new file mode 100644
index 00000000..6e4ec874
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_conditional_comments.test
@@ -0,0 +1,84 @@
+###############################################################################
+# After the patch for BUG#49124:
+# - Use ' ' instead of '!' in the conditional comments which are not applied on
+# master. So they become common comments and will not be applied on slave.
+#
+# - Example:
+# 'INSERT INTO t1 VALUES (1) /*!10000, (2)*/ /*!999999 ,(3)*/
+# will be binlogged as
+# 'INSERT INTO t1 VALUES (1) /*!10000, (2)*/ /* 99999 ,(3)*/'.
+###############################################################################
+source include/have_binlog_format_statement.inc;
+source include/master-slave.inc;
+
+CREATE TABLE t1(c1 INT);
+source include/show_binlog_events.inc;
+let $binlog_start= query_get_value(SHOW MASTER STATUS, Position, 1);
+
+--echo
+--echo # Case 1:
+--echo # ------------------------------------------------------------------
+--echo # In a statement, some CCs are applied while others are not. The CCs
+--echo # which are not applied on master will be binlogged as common comments.
+
+/*!999999 --- */INSERT /*!INTO*/ /*!10000 t1 */ VALUES(10) /*!999999 ,(11)*/;
+
+source include/show_binlog_events.inc;
+let $binlog_start= query_get_value(SHOW MASTER STATUS, Position, 1);
+sync_slave_with_master;
+--let $diff_tables= master:t1,slave:t1
+--source include/diff_tables.inc
+
+--echo
+--echo # Case 2:
+--echo # -----------------------------------------------------------------
+--echo # Verify whether it can be binlogged correctly when executing prepared
+--echo # statement.
+--connection master
+PREPARE stmt FROM 'INSERT INTO /*!999999 blabla*/ t1 VALUES(60) /*!999999 ,(61)*/';
+EXECUTE stmt;
+DROP TABLE t1;
+CREATE TABLE t1(c1 INT);
+EXECUTE stmt;
+
+sync_slave_with_master;
+--let $diff_tables= master:t1,slave:t1
+--source include/diff_tables.inc
+
+--connection master
+--echo
+SET @value=62;
+PREPARE stmt FROM 'INSERT INTO /*!999999 blabla */ t1 VALUES(?) /*!999999 ,(63)*/';
+EXECUTE stmt USING @value;
+DROP TABLE t1;
+CREATE TABLE t1(c1 INT);
+EXECUTE stmt USING @value;
+
+source include/show_binlog_events.inc;
+let $binlog_start= query_get_value(SHOW MASTER STATUS, Position, 1);
+
+sync_slave_with_master;
+--let $diff_tables= master:t1,slave:t1
+--source include/diff_tables.inc
+
+--echo
+--echo # Case 3:
+--echo # -----------------------------------------------------------------
+--echo # Verify it can restore the '!', if the it is an uncomplete conditional
+--echo # comments
+--connection master
+--error 1064
+SELECT c1 FROM /*!999999 t1 WHEREN; #*/
+
+#
+# Bug#28388217 - SERVER CAN FAIL WHILE REPLICATING CONDITIONAL COMMENTS
+#
+insert t1 values (/*!50505 1 /* foo */ */ + 2);
+insert t1 values (/*!999999 10 /* foo */ */ + 20);
+source include/show_binlog_events.inc;
+sync_slave_with_master;
+select * from t1;
+connection master;
+
+DROP TABLE t1;
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_connection.test b/mysql-test/suite/rpl/t/rpl_connection.test
new file mode 100644
index 00000000..31024006
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_connection.test
@@ -0,0 +1,24 @@
+--source include/not_embedded.inc
+--source include/have_binlog_format_mixed.inc
+--source include/master-slave.inc
+
+#
+# BUG#13427949: CHANGE MASTER TO USER='' (EMPTY USER) CAUSES ERRORS ON VALGRING
+#
+
+--connection slave
+call mtr.add_suppression(".*Invalid .* username when attempting to connect to the master server.*");
+
+
+# Assert that we disallow empty users and that no problem
+--source include/stop_slave.inc
+CHANGE MASTER TO MASTER_USER= '', MASTER_PASSWORD= '';
+START SLAVE;
+--let $slave_io_errno= 1045, 1593
+--source include/wait_for_slave_io_error.inc
+--source include/stop_slave.inc
+
+CHANGE MASTER TO MASTER_USER= 'root', MASTER_PASSWORD= '';
+START SLAVE;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_corruption-master.opt b/mysql-test/suite/rpl/t/rpl_corruption-master.opt
new file mode 100644
index 00000000..2612c17a
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_corruption-master.opt
@@ -0,0 +1 @@
+--binlog-checksum=CRC32 --master-verify-checksum=1
diff --git a/mysql-test/suite/rpl/t/rpl_corruption-slave.opt b/mysql-test/suite/rpl/t/rpl_corruption-slave.opt
new file mode 100644
index 00000000..b32a5240
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_corruption-slave.opt
@@ -0,0 +1 @@
+--binlog-checksum=CRC32 --slave-sql-verify-checksum=1
diff --git a/mysql-test/suite/rpl/t/rpl_corruption.test b/mysql-test/suite/rpl/t/rpl_corruption.test
new file mode 100644
index 00000000..cd2a1cc7
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_corruption.test
@@ -0,0 +1,181 @@
+#
+# This include file is used by more than one test suite
+# (currently rpl and binlog_encryption).
+# Please check all dependent tests after modifying it
+#
+
+############################################################
+# Purpose: WL#5064 Testing with corrupted events.
+# The test emulates the corruption at the vary stages
+# of replication:
+# - in binlog file
+# - in network
+# - in relay log
+############################################################
+
+#
+# The tests intensively utilize @@global.debug. Note,
+# Bug#11765758 - 58754,
+# @@global.debug is read by the slave threads through dbug-interface.
+# Hence, before a client thread set @@global.debug we have to ensure that:
+# (a) the slave threads are stopped, or (b) the slave threads are in
+# sync and waiting.
+
+--source include/have_debug.inc
+--source include/master-slave.inc
+
+--connection slave
+--source include/stop_slave.inc
+CHANGE MASTER TO MASTER_USE_GTID=NO;
+--source include/start_slave.inc
+--connection master
+
+# Block legal errors for MTR
+call mtr.add_suppression('Found invalid event in binary log');
+call mtr.add_suppression('Slave I/O: Relay log write failure: could not queue event from master');
+call mtr.add_suppression('event read from binlog did not pass crc check');
+call mtr.add_suppression('Replication event checksum verification failed');
+call mtr.add_suppression('Event crc check failed! Most likely there is event corruption');
+call mtr.add_suppression('Slave SQL: Error initializing relay log position: I/O error reading event at position .*, error.* 1593');
+
+SET @old_master_verify_checksum = @@master_verify_checksum;
+
+# Creating test table/data and set corruption position for testing
+--echo # 1. Creating test table/data and set corruption position for testing
+--connection master
+--echo * insert/update/delete rows in table t1 *
+# Corruption algorithm modifies only the first event and
+# then will be reset. To avoid checking always the first event
+# from binlog (usually it is FD) we randomly execute different
+# statements and set position for corruption inside events.
+
+CREATE TABLE t1 (a INT NOT NULL PRIMARY KEY, b VARCHAR(10), c VARCHAR(100));
+--disable_query_log
+let $i=`SELECT 3+CEILING(10*RAND())`;
+let $j=1;
+let $pos=0;
+while ($i) {
+ eval INSERT INTO t1 VALUES ($j, 'a', NULL);
+ if (`SELECT RAND() > 0.7`)
+ {
+ eval UPDATE t1 SET c = REPEAT('a', 20) WHERE a = $j;
+ }
+ if (`SELECT RAND() > 0.8`)
+ {
+ eval DELETE FROM t1 WHERE a = $j;
+ }
+ if (!$pos) {
+ let $pos= query_get_value(SHOW MASTER STATUS, Position, 1);
+ --sync_slave_with_master
+ --source include/stop_slave.inc
+ --disable_query_log
+ --connection master
+ }
+ dec $i;
+ inc $j;
+}
+--enable_query_log
+
+
+# Emulate corruption in binlog file when SHOW BINLOG EVENTS is executing
+--echo # 2. Corruption in master binlog and SHOW BINLOG EVENTS
+SET @saved_dbug = @@global.debug_dbug;
+SET @@global.debug_dbug="d,corrupt_read_log_event_char";
+--echo SHOW BINLOG EVENTS;
+--disable_query_log
+send_eval SHOW BINLOG EVENTS FROM $pos;
+--enable_query_log
+--error ER_ERROR_WHEN_EXECUTING_COMMAND
+reap;
+
+SET @@global.debug_dbug=@saved_dbug;
+
+# Emulate corruption on master with crc checking on master
+--echo # 3. Master read a corrupted event from binlog and send the error to slave
+
+# We have a rare but nasty potential race here: if the dump thread on
+# the master for the _old_ slave connection has not yet discovered
+# that the slave has disconnected, we will inject the corrupt event on
+# the wrong connection, and the test will fail
+# (+d,corrupt_read_log_event2 corrupts only one event).
+# So kill any lingering dump thread (we need to kill; otherwise dump thread
+# could manage to send all events down the socket before seeing it close, and
+# hang forever waiting for new binlog events to be created).
+let $id= `select id from information_schema.processlist where command = "Binlog Dump"`;
+if ($id)
+{
+ --disable_query_log
+ --error 0,1094
+ eval kill $id;
+ --enable_query_log
+}
+let $wait_condition=
+ SELECT COUNT(*)=0 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE command = 'Binlog Dump';
+--source include/wait_condition.inc
+
+SET @@global.debug_dbug="d,corrupt_read_log_event2_set";
+--connection slave
+START SLAVE IO_THREAD;
+let $slave_io_errno= 1236;
+--let $slave_timeout= 10
+--source include/wait_for_slave_io_error.inc
+--connection master
+SET @@global.debug_dbug=@saved_dbug;
+
+# Emulate corruption on master without crc checking on master
+--echo # 4. Master read a corrupted event from binlog and send it to slave
+--connection master
+SET GLOBAL master_verify_checksum=0;
+SET @@global.debug_dbug="d,corrupt_read_log_event2_set";
+--connection slave
+START SLAVE IO_THREAD;
+# When the checksum error is detected, the slave sets error code 1743
+# (ER_NETWORK_READ_EVENT_CHECKSUM_FAILURE) in queue_event(), then immediately
+# sets error 1595 (ER_SLAVE_RELAY_LOG_WRITE_FAILURE) in handle_slave_io().
+# So we usually get 1595, but it is occasionally possible to get 1743.
+let $slave_io_errno= 1595,1743; # ER_SLAVE_RELAY_LOG_WRITE_FAILURE, ER_NETWORK_READ_EVENT_CHECKSUM_FAILURE
+--source include/wait_for_slave_io_error.inc
+--connection master
+SET @@global.debug_dbug=@saved_dbug;
+SET GLOBAL master_verify_checksum=1;
+
+# Emulate corruption in network
+--echo # 5. Slave. Corruption in network
+--connection slave
+SET @saved_dbug_slave = @@GLOBAL.debug_dbug;
+SET @@global.debug_dbug="d,corrupt_queue_event";
+START SLAVE IO_THREAD;
+let $slave_io_errno= 1595,1743; # ER_SLAVE_RELAY_LOG_WRITE_FAILURE, ER_NETWORK_READ_EVENT_CHECKSUM_FAILURE
+--source include/wait_for_slave_io_error.inc
+SET @@global.debug_dbug=@saved_dbug_slave;
+
+# Emulate corruption in relay log
+--echo # 6. Slave. Corruption in relay log
+
+SET @@global.debug_dbug="d,corrupt_read_log_event_char";
+
+START SLAVE SQL_THREAD;
+let $slave_sql_errno= 1593;
+--source include/wait_for_slave_sql_error.inc
+
+SET @@global.debug_dbug=@saved_dbug_slave;
+
+# Start normal replication and compare same table on master
+# and slave
+--echo # 7. Seek diff for tables on master and slave
+--connection slave
+--source include/start_slave.inc
+--connection master
+--sync_slave_with_master
+let $diff_tables= master:test.t1, slave:test.t1;
+--source include/diff_tables.inc
+
+# Clean up
+--echo # 8. Clean up
+--connection master
+set @@global.debug_dbug = @saved_dbug;
+SET GLOBAL master_verify_checksum = @old_master_verify_checksum;
+DROP TABLE t1;
+--sync_slave_with_master
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_create_database-master.opt b/mysql-test/suite/rpl/t/rpl_create_database-master.opt
new file mode 100644
index 00000000..85660a17
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_create_database-master.opt
@@ -0,0 +1 @@
+--binlog-do-db=mysqltest_sisyfos --binlog-do-db=mysqltest_prometheus
diff --git a/mysql-test/suite/rpl/t/rpl_create_database-slave.opt b/mysql-test/suite/rpl/t/rpl_create_database-slave.opt
new file mode 100644
index 00000000..96d630c9
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_create_database-slave.opt
@@ -0,0 +1 @@
+--replicate-do-db=mysqltest_sisyfos --replicate-do-db=mysqltest_prometheus
diff --git a/mysql-test/suite/rpl/t/rpl_create_database.test b/mysql-test/suite/rpl/t/rpl_create_database.test
new file mode 100644
index 00000000..5eac3de0
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_create_database.test
@@ -0,0 +1,73 @@
+#
+# Tests for replication of statements that manipulate databases.
+#
+# For this test file, we have a number of databases. All databases
+# with "greek" names will be replicated on the slave, while other names
+# (e.g., american) will not be replicated.
+#
+
+source include/master-slave.inc;
+
+# Bug#6391 (binlog-do-db rules ignored)
+# In this case, 'mysqltest_bob' should not be replicated to the slave.
+--disable_warnings
+DROP DATABASE IF EXISTS mysqltest_prometheus;
+DROP DATABASE IF EXISTS mysqltest_sisyfos;
+DROP DATABASE IF EXISTS mysqltest_bob;
+sync_slave_with_master;
+# This database is not replicated
+DROP DATABASE IF EXISTS mysqltest_bob;
+--enable_warnings
+
+connection master;
+CREATE DATABASE mysqltest_prometheus;
+CREATE DATABASE mysqltest_sisyfos;
+CREATE DATABASE mysqltest_bob;
+
+USE mysqltest_sisyfos;
+# These should be replicated
+CREATE TABLE t1 (b int);
+INSERT INTO t1 VALUES(1);
+
+USE mysqltest_bob;
+# These should *not* be replicated
+CREATE TABLE t2 (b int);
+INSERT INTO t2 VALUES(2);
+
+# Current database is now 'mysqltest_bob'
+# The following should be replicated
+ALTER DATABASE mysqltest_sisyfos CHARACTER SET latin1;
+
+USE mysqltest_sisyfos;
+# The following should *not* be replicated
+ALTER DATABASE mysqltest_bob CHARACTER SET latin1;
+
+SHOW DATABASES LIKE 'mysql%';
+sync_slave_with_master;
+SHOW DATABASES LIKE 'mysql%';
+
+connection master;
+DROP DATABASE IF EXISTS mysqltest_sisyfos;
+USE mysqltest_prometheus;
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (1);
+CREATE DATABASE mysqltest_sisyfos;
+USE mysqltest_sisyfos;
+CREATE TABLE t2 (a INT);
+let $VERSION=`select version()`;
+SHOW DATABASES LIKE 'mysql%';
+sync_slave_with_master;
+SHOW DATABASES LIKE 'mysql%';
+USE mysqltest_prometheus;
+SHOW TABLES;
+USE mysqltest_sisyfos;
+SHOW TABLES;
+
+connection master;
+DROP DATABASE IF EXISTS mysqltest_prometheus;
+DROP DATABASE IF EXISTS mysqltest_sisyfos;
+DROP DATABASE IF EXISTS mysqltest_bob;
+sync_slave_with_master;
+
+# End of 4.1 tests
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_create_drop_db.test b/mysql-test/suite/rpl/t/rpl_create_drop_db.test
new file mode 100644
index 00000000..04721c9c
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_create_drop_db.test
@@ -0,0 +1,33 @@
+--source include/master-slave.inc
+
+connection master;
+
+CREATE DATABASE db1;
+CREATE DATABASE IF NOT EXISTS db1;
+CREATE OR REPLACE DATABASE db2;
+CREATE OR REPLACE DATABASE db1;
+sync_slave_with_master;
+
+SHOW DATABASES LIKE 'db%';
+
+connection master;
+--error ER_DB_CREATE_EXISTS
+CREATE DATABASE db1;
+
+--error ER_DB_DROP_EXISTS
+DROP DATABASE db3;
+
+CREATE DATABASE IF NOT EXISTS db3;
+sync_slave_with_master;
+
+SHOW DATABASES LIKE 'db%';
+
+connection master;
+DROP DATABASE db1;
+DROP DATABASE db2;
+DROP DATABASE IF EXISTS db3;
+sync_slave_with_master;
+
+SHOW DATABASES LIKE 'db%';
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_create_drop_event.test b/mysql-test/suite/rpl/t/rpl_create_drop_event.test
new file mode 100644
index 00000000..96a7e82d
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_create_drop_event.test
@@ -0,0 +1,27 @@
+--source include/master-slave.inc
+
+connection master;
+SET GLOBAL event_scheduler=off;
+
+CREATE TABLE t1 (a INT);
+CREATE EVENT ev1 ON SCHEDULE EVERY 1 SECOND DO INSERT INTO t1 VALUES (10);
+--error ER_EVENT_ALREADY_EXISTS
+CREATE EVENT ev1 ON SCHEDULE EVERY 1 SECOND DO INSERT INTO t1 VALUES (11);
+CREATE OR REPLACE EVENT ev1 ON SCHEDULE EVERY 1 SECOND DO INSERT INTO t1 VALUES (11);
+SELECT EVENT_NAME,STATUS,EVENT_DEFINITION FROM INFORMATION_SCHEMA.EVENTS;
+
+SET GLOBAL event_scheduler=on;
+let $wait_condition= SELECT count(*)>0 FROM t1;
+--source include/wait_condition.inc
+SET GLOBAL event_scheduler=off;
+SELECT DISTINCT a FROM t1;
+DELETE FROM t1;
+
+--echo # Syncing slave with master
+sync_slave_with_master;
+SELECT EVENT_NAME,STATUS,EVENT_DEFINITION FROM INFORMATION_SCHEMA.EVENTS;
+connection master;
+DROP TABLE t1;
+DROP EVENT ev1;
+sync_slave_with_master;
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_create_drop_function.test b/mysql-test/suite/rpl/t/rpl_create_drop_function.test
new file mode 100644
index 00000000..5ae0b765
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_create_drop_function.test
@@ -0,0 +1,54 @@
+--source include/master-slave.inc
+
+connection master;
+
+CREATE FUNCTION hello (str CHAR(20)) RETURNS CHAR(50) DETERMINISTIC RETURN
+CONCAT('Hello, ', str, '!');
+
+--error ER_SP_ALREADY_EXISTS
+CREATE FUNCTION hello (str CHAR(20)) RETURNS CHAR(50) DETERMINISTIC RETURN
+CONCAT('Hello, ', str, '!');
+
+sync_slave_with_master;
+
+SHOW CREATE FUNCTION hello;
+
+connection master;
+
+--error ER_WRONG_USAGE
+CREATE OR REPLACE FUNCTION IF NOT EXISTS hello (str CHAR(20)) RETURNS CHAR(50) DETERMINISTIC RETURN
+CONCAT('Hello, ', str, '!');
+
+CREATE OR REPLACE FUNCTION hello (str CHAR(20)) RETURNS CHAR(50) DETERMINISTIC RETURN
+CONCAT('Hello, ', str, '!');
+
+SELECT hello('master');
+sync_slave_with_master;
+
+SELECT hello('slave');
+
+connection master;
+CREATE FUNCTION IF NOT EXISTS hello (str CHAR(20)) RETURNS CHAR(50) DETERMINISTIC RETURN
+CONCAT('Hello, ', str, '!');
+
+CREATE OR REPLACE FUNCTION bye (str CHAR(20)) RETURNS CHAR(50) DETERMINISTIC RETURN
+CONCAT('Bye, ', str, '!');
+
+SELECT hello('master');
+SELECT bye('master');
+sync_slave_with_master;
+
+SELECT hello('slave');
+SELECT bye('slave');
+
+connection master;
+DROP FUNCTION hello;
+DROP FUNCTION IF EXISTS bye;
+sync_slave_with_master;
+
+--error ER_SP_DOES_NOT_EXIST
+DROP FUNCTION hello;
+
+DROP FUNCTION IF EXISTS bye;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_create_drop_index.test b/mysql-test/suite/rpl/t/rpl_create_drop_index.test
new file mode 100644
index 00000000..f1b65349
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_create_drop_index.test
@@ -0,0 +1,17 @@
+--source include/master-slave.inc
+
+connection master;
+
+CREATE TABLE t1 (a INT, b INT);
+CREATE INDEX i1 ON t1 (a);
+CREATE OR REPLACE INDEX i1 ON t1 (a, b);
+sync_slave_with_master;
+
+SHOW CREATE TABLE t1;
+
+connection master;
+SHOW CREATE TABLE t1;
+DROP TABLE t1;
+sync_slave_with_master;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_create_drop_procedure.test b/mysql-test/suite/rpl/t/rpl_create_drop_procedure.test
new file mode 100644
index 00000000..6fb0313c
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_create_drop_procedure.test
@@ -0,0 +1,81 @@
+--source include/master-slave.inc
+
+connection master;
+CREATE TABLE t1 (id INT);
+DELIMITER $$;
+CREATE PROCEDURE proc1 (OUT cnt INT) BEGIN SELECT COUNT(*) INTO cnt FROM t1; END$$
+DELIMITER ;$$
+CALL proc1(@cnt);
+SELECT @cnt;
+INSERT INTO t1 VALUES (1), (2), (3);
+CALL proc1(@cnt);
+SELECT @cnt;
+
+--echo # Syncing with slave
+sync_slave_with_master;
+
+CALL proc1(@cnt);
+SELECT @cnt;
+
+connection master;
+DELIMITER $$;
+--error ER_SP_ALREADY_EXISTS
+CREATE PROCEDURE proc1 (OUT cnt INT) BEGIN SELECT COUNT(*) INTO cnt FROM t1; END$$
+
+CREATE PROCEDURE IF NOT EXISTS proc1 (OUT cnt INT) BEGIN SELECT COUNT(*) INTO cnt FROM t1; END$$
+
+--error ER_WRONG_USAGE
+CREATE OR REPLACE PROCEDURE IF NOT EXISTS proc1 (OUT cnt INT) BEGIN SELECT COUNT(*) INTO cnt FROM t1; END$$
+
+CREATE OR REPLACE PROCEDURE proc1 (OUT cnt INT) BEGIN SELECT COUNT(*) INTO cnt FROM t1; END$$
+DELIMITER ;$$
+
+--echo # Syncing with slave
+sync_slave_with_master;
+
+CALL proc1(@cnt);
+SELECT @cnt;
+
+connection master;
+DROP PROCEDURE proc1;
+DELIMITER $$;
+CREATE PROCEDURE IF NOT EXISTS proc1 (OUT cnt INT) BEGIN SELECT COUNT(*) INTO cnt FROM t1; END$$
+DELIMITER ;$$
+INSERT INTO t1 VALUES (1), (2), (3);
+CALL proc1(@cnt);
+SELECT @cnt;
+
+--echo # Syncing with slave
+sync_slave_with_master;
+
+CALL proc1(@cnt);
+SELECT @cnt;
+
+connection master;
+DROP PROCEDURE proc1;
+DELIMITER $$;
+CREATE OR REPLACE PROCEDURE proc1 (OUT cnt INT) BEGIN SELECT COUNT(*) INTO cnt FROM t1; END$$
+DELIMITER ;$$
+INSERT INTO t1 VALUES (1), (2), (3);
+CALL proc1(@cnt);
+SELECT @cnt;
+
+--echo # Syncing with slave
+sync_slave_with_master;
+
+CALL proc1(@cnt);
+SELECT @cnt;
+
+connection master;
+DROP TABLE IF EXISTS t1;
+DROP PROCEDURE proc1;
+
+DROP PROCEDURE IF EXISTS proc2;
+
+--echo # Syncing with slave
+sync_slave_with_master;
+
+--error ER_SP_DOES_NOT_EXIST
+DROP PROCEDURE proc1;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_create_drop_role.test b/mysql-test/suite/rpl/t/rpl_create_drop_role.test
new file mode 100644
index 00000000..7260b473
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_create_drop_role.test
@@ -0,0 +1,48 @@
+--source include/master-slave.inc
+
+connection master;
+CREATE ROLE role_1;
+sync_slave_with_master;
+
+SELECT User FROM mysql.user WHERE is_role='Y' ORDER BY User;
+
+connection master;
+CREATE ROLE IF NOT EXISTS role_1;
+CREATE ROLE IF NOT EXISTS role_2;
+sync_slave_with_master;
+
+SELECT User FROM mysql.user WHERE is_role='Y' ORDER BY User;
+
+connection master;
+
+--error ER_WRONG_USAGE
+CREATE OR REPLACE ROLE IF NOT EXISTS role_3;
+
+CREATE OR REPLACE ROLE role_3;
+CREATE OR REPLACE ROLE role_2;
+sync_slave_with_master;
+
+SELECT User FROM mysql.user WHERE is_role='Y' ORDER BY User;
+
+connection master;
+--error ER_CANNOT_USER
+CREATE ROLE role_2;
+
+sync_slave_with_master;
+
+SELECT User FROM mysql.user WHERE is_role='Y' ORDER BY User;
+
+connection master;
+DROP ROLE role_1;
+DROP ROLE IF EXISTS role_2;
+DROP ROLE IF EXISTS role_3;
+DROP ROLE IF EXISTS role_4;
+
+--error ER_CANNOT_USER
+DROP ROLE role_4;
+
+sync_slave_with_master;
+
+SELECT User FROM mysql.user WHERE is_role='Y' ORDER BY User;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_create_drop_trigger.test b/mysql-test/suite/rpl/t/rpl_create_drop_trigger.test
new file mode 100644
index 00000000..568d4e22
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_create_drop_trigger.test
@@ -0,0 +1,48 @@
+--source include/master-slave.inc
+
+--echo # Part 1 - initial creation
+connection master;
+CREATE DATABASE db1;
+USE db1;
+CREATE TABLE t1 (val INT);
+CREATE TRIGGER val_sum BEFORE INSERT ON t1 FOR EACH ROW SET @sum = @sum + NEW.val + 1;
+SET @sum=0;
+INSERT INTO t1 VALUES (10), (20), (30);
+SELECT ACTION_STATEMENT AS ACTION_STATEMENT_Master FROM INFORMATION_SCHEMA.TRIGGERS WHERE TRIGGER_NAME='val_sum';
+sync_slave_with_master;
+SELECT ACTION_STATEMENT AS ACTION_STATEMENT_Slave FROM INFORMATION_SCHEMA.TRIGGERS WHERE TRIGGER_NAME='val_sum';
+
+--echo # Part 2 - CREATE IF NOT EXISTS (on a existing trigger)
+connection master;
+CREATE TRIGGER IF NOT EXISTS val_sum AFTER INSERT ON t1 FOR EACH ROW SET @sum = @sum + NEW.val + 2;
+SELECT ACTION_STATEMENT AS ACTION_STATEMENT_Master FROM INFORMATION_SCHEMA.TRIGGERS WHERE TRIGGER_NAME='val_sum';
+sync_slave_with_master;
+SELECT ACTION_STATEMENT AS ACTION_STATEMENT_Slave FROM INFORMATION_SCHEMA.TRIGGERS WHERE TRIGGER_NAME='val_sum';
+
+--echo # Part 3 - CREATE OR REPLACE (on a existing trigger)
+connection master;
+CREATE OR REPLACE TRIGGER val_sum BEFORE INSERT ON t1 FOR EACH ROW SET @sum = @sum + NEW.val + 3;
+SELECT ACTION_STATEMENT AS ACTION_STATEMENT_Master FROM INFORMATION_SCHEMA.TRIGGERS WHERE TRIGGER_NAME='val_sum';
+sync_slave_with_master;
+SELECT ACTION_STATEMENT AS ACTION_STATEMENT_Slave FROM INFORMATION_SCHEMA.TRIGGERS WHERE TRIGGER_NAME='val_sum';
+
+--echo # Clearing up
+connection master;
+DROP TRIGGER val_sum;
+DROP TABLE t1;
+DROP TRIGGER IF EXISTS val_sum;
+
+--error ER_TRG_DOES_NOT_EXIST
+DROP TRIGGER random_trigger;
+DROP DATABASE db1;
+
+--error ER_NO_DB_ERROR
+DROP TRIGGER IF EXISTS val_sum;
+
+--echo # Syncing slave with master
+sync_slave_with_master;
+
+--error ER_TRG_DOES_NOT_EXIST
+DROP TRIGGER val_sum;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_create_drop_udf.test b/mysql-test/suite/rpl/t/rpl_create_drop_udf.test
new file mode 100644
index 00000000..af24cabd
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_create_drop_udf.test
@@ -0,0 +1,56 @@
+--source include/have_udf.inc
+--source include/master-slave.inc
+
+connection master;
+
+--replace_result $UDF_EXAMPLE_SO UDF_EXAMPLE_LIB
+eval CREATE FUNCTION metaphon RETURNS STRING SONAME "$UDF_EXAMPLE_SO";
+SELECT metaphon('master');
+
+--replace_result $UDF_EXAMPLE_SO UDF_EXAMPLE_LIB
+--error ER_UDF_EXISTS
+eval CREATE FUNCTION metaphon RETURNS INT SONAME "$UDF_EXAMPLE_SO";
+
+sync_slave_with_master;
+
+SELECT metaphon('slave');
+
+connection master;
+
+--replace_result $UDF_EXAMPLE_SO UDF_EXAMPLE_LIB
+eval CREATE FUNCTION IF NOT EXISTS metaphon RETURNS STRING SONAME "$UDF_EXAMPLE_SO";
+DROP FUNCTION IF EXISTS random_function_name;
+--replace_result $UDF_EXAMPLE_SO UDF_EXAMPLE_LIB
+eval CREATE FUNCTION IF NOT EXISTS metaphon RETURNS STRING SONAME "$UDF_EXAMPLE_SO";
+
+--replace_result $UDF_EXAMPLE_SO UDF_EXAMPLE_LIB
+--error ER_WRONG_USAGE
+eval CREATE OR REPLACE FUNCTION IF NOT EXISTS metaphon RETURNS STRING SONAME "$UDF_EXAMPLE_SO";
+sync_slave_with_master;
+
+SELECT metaphon('slave');
+
+connection master;
+DROP FUNCTION metaphon;
+
+--replace_result $UDF_EXAMPLE_SO UDF_EXAMPLE_LIB
+eval CREATE OR REPLACE FUNCTION metaphon RETURNS STRING SONAME "$UDF_EXAMPLE_SO";
+
+--replace_result $UDF_EXAMPLE_SO UDF_EXAMPLE_LIB
+--error ER_UDF_EXISTS
+eval CREATE FUNCTION metaphon RETURNS STRING SONAME "$UDF_EXAMPLE_SO";
+sync_slave_with_master;
+
+SELECT metaphon('slave');
+
+connection master;
+DROP FUNCTION metaphon;
+DROP FUNCTION IF EXISTS metaphon;
+sync_slave_with_master;
+
+--error ER_SP_DOES_NOT_EXIST
+DROP FUNCTION metaphon;
+
+DROP FUNCTION IF EXISTS metaphon;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_create_drop_user.test b/mysql-test/suite/rpl/t/rpl_create_drop_user.test
new file mode 100644
index 00000000..c5f193a0
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_create_drop_user.test
@@ -0,0 +1,57 @@
+--source include/master-slave.inc
+
+connection master;
+CREATE USER u1@localhost IDENTIFIED BY 'abcdefghijk';
+connect (user_a, localhost, u1,'abcdefghijk',);
+connection user_a;
+SELECT CURRENT_USER;
+disconnect user_a;
+
+connection master;
+CREATE USER IF NOT EXISTS u2@localhost;
+connect (user_a, localhost, u2,,);
+connection user_a;
+SELECT CURRENT_USER;
+disconnect user_a;
+
+connection master;
+--sorted_result
+SELECT user,password,plugin,authentication_string FROM mysql.user WHERE user LIKE 'u%' ;
+sync_slave_with_master;
+--sorted_result
+SELECT user,password,plugin,authentication_string FROM mysql.user WHERE user LIKE 'u%' ;
+
+connection master;
+CREATE OR REPLACE USER u1@localhost IDENTIFIED BY 'abcdefghijk2';
+connect (user_a, localhost, u1,'abcdefghijk2',);
+connection user_a;
+SELECT CURRENT_USER;
+disconnect user_a;
+connection master;
+--sorted_result
+SELECT user,password,plugin,authentication_string FROM mysql.user WHERE user LIKE 'u%' ;
+sync_slave_with_master;
+--sorted_result
+SELECT user,password,plugin,authentication_string FROM mysql.user WHERE user LIKE 'u%' ;
+
+connection master;
+--error ER_CANNOT_USER
+CREATE USER u1@localhost;
+
+--error ER_CANNOT_USER
+DROP USER u3@localhost;
+
+sync_slave_with_master;
+--sorted_result
+SELECT user,password,plugin,authentication_string FROM mysql.user WHERE user LIKE 'u%' ;
+
+connection master;
+DROP USER IF EXISTS u1@localhost;
+DROP USER u2@localhost;
+DROP USER IF EXISTS u3@localhost;
+sync_slave_with_master;
+
+--sorted_result
+SELECT user,password,plugin,authentication_string FROM mysql.user WHERE user LIKE 'u%' ;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_create_drop_view.test b/mysql-test/suite/rpl/t/rpl_create_drop_view.test
new file mode 100644
index 00000000..4abb3ffb
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_create_drop_view.test
@@ -0,0 +1,56 @@
+--source include/master-slave.inc
+
+connection master;
+CREATE TABLE t1(id INT);
+CREATE VIEW v1 AS SELECT * FROM t1 WHERE id>10;
+INSERT INTO t1 VALUES (5), (8), (10), (20), (30);
+SELECT * FROM t1;
+SELECT * FROM v1;
+
+--echo # Syncing slave with master
+sync_slave_with_master;
+SELECT * FROM t1;
+SELECT * FROM v1;
+
+connection master;
+--error ER_TABLE_EXISTS_ERROR
+CREATE VIEW v1 AS SELECT * FROM t1 WHERE id>10;
+
+CREATE VIEW IF NOT EXISTS v1 AS SELECT * FROM t1 WHERE id>10;
+
+--error ER_WRONG_USAGE
+CREATE OR REPLACE VIEW IF NOT EXISTS v1 AS SELECT * FROM t1 WHERE id>10;
+
+--echo # Syncing slave with master
+sync_slave_with_master;
+SELECT * FROM t1;
+SELECT * FROM v1;
+
+connection master;
+CREATE OR REPLACE VIEW v1 AS SELECT * FROM t1 WHERE id>10;
+INSERT INTO t1 VALUES (50), (80), (3), (2), (40);
+SELECT * FROM t1;
+SELECT * FROM v1;
+
+--echo # Syncing slave with master
+sync_slave_with_master;
+SELECT * FROM t1;
+SELECT * FROM v1;
+
+connection master;
+RENAME TABLE v1 TO v2;
+DROP VIEW v2;
+DROP TABLE t1;
+
+--error ER_UNKNOWN_VIEW
+DROP VIEW v1;
+
+DROP VIEW IF EXISTS v2;
+
+--echo # Syncing slave with master
+sync_slave_with_master;
+
+--error ER_NO_SUCH_TABLE
+SELECT * FROM v1;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_create_if_not_exists.test b/mysql-test/suite/rpl/t/rpl_create_if_not_exists.test
new file mode 100644
index 00000000..b27250f9
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_create_if_not_exists.test
@@ -0,0 +1,195 @@
+# BUG#45574:
+# SP: CREATE DATABASE|TABLE IF NOT EXISTS not binlogged if routine exists.
+#
+# There is an inconsistency with DROP DATABASE|TABLE|EVENT IF EXISTS and
+# CREATE DATABASE|TABLE|EVENT IF NOT EXISTS. DROP IF EXISTS statements are
+# binlogged even if either the DB, TABLE or EVENT does not exist. In
+# contrast, Only the CREATE EVENT IF NOT EXISTS is binlogged when the EVENT
+# exists.
+#
+# This problem caused some of the tests to fail randomly on PB or PB2.
+#
+# Description:
+# Fixed this bug by adding calls to write_bin_log in:
+# mysql_create_db
+# mysql_create_table_no_lock
+# mysql_create_like_table
+# create_table_from_items
+#
+# Test is implemented as follows:
+# i) test each "CREATE IF NOT EXISTS" (DDL), found in MySQL 5.1 manual
+# exclude CREATE TEMPORARY TABLE, on existent objects;
+#
+# Note:
+# rpl_create_tmp_table_if_not_exists.test tests CREATE TEMPORARY TABLE cases.
+#
+# References:
+# http://dev.mysql.com/doc/refman/5.1/en/sql-syntax-data-definition.html
+#
+
+source include/master-slave.inc;
+disable_warnings;
+DROP DATABASE IF EXISTS mysqltest;
+
+CREATE DATABASE IF NOT EXISTS mysqltest;
+USE mysqltest;
+CREATE TABLE IF NOT EXISTS t(c1 int);
+CREATE TABLE IF NOT EXISTS t1 LIKE t;
+CREATE TABLE IF NOT EXISTS t2 SELECT * FROM t;
+CREATE EVENT IF NOT EXISTS e
+ON SCHEDULE AT CURRENT_TIMESTAMP + INTERVAL 1 HOUR
+DO SELECT now();
+sync_slave_with_master;
+
+connection slave;
+#DROP database from slave.
+#The database and all tables can be recreated in slave
+#if binlog of the second CREATE command is recorded and sent from master to slave.
+DROP DATABASE mysqltest;
+
+connection master;
+CREATE DATABASE IF NOT EXISTS mysqltest;
+USE mysqltest;
+CREATE TABLE IF NOT EXISTS t(c1 int);
+CREATE TABLE IF NOT EXISTS t1 LIKE t;
+# The following will not be logged because t2 existed and we will not
+# put the data of SELECT into the binary log
+CREATE TABLE IF NOT EXISTS t2 SELECT * FROM t;
+CREATE EVENT IF NOT EXISTS e
+ON SCHEDULE AT CURRENT_TIMESTAMP + INTERVAL 1 HOUR
+DO SELECT now();
+sync_slave_with_master;
+
+connection slave;
+SHOW TABLES in mysqltest;
+#Execution time changes in each run. So we disregard it by calling replace_column.
+replace_column 6 #;
+SHOW EVENTS in mysqltest;
+
+
+connection master;
+DROP DATABASE IF EXISTS mysqltest;
+
+#
+# BUG#47418 RBR fails, failure with mixup of base/temporary/view TABLE DDL
+#
+# Before the patch for this bug, 'CREATE TABLE IF NOT EXIST ... SELECT'
+# statement was binlogged as a TEMPORARY table if the object existed as
+# a temporary table. This was caused by that the temporary table was opened
+# and the results of the 'SELECT' was inserted into the temporary table if
+# a temporary table existed with the same name.
+#
+# After the patch for this bug, the base table is created and the results of
+# the 'SELECT' are inserted into it, even though a temporary table exists with
+# the same name, and the statement is still binlogged as a base table.
+#
+
+echo -------------BUG#47418-------------;
+connection master;
+USE test;
+DROP TABLE IF EXISTS t3;
+--enable_warnings
+CREATE TABLE t3(c1 INTEGER);
+INSERT INTO t3 VALUES(33);
+
+CREATE TEMPORARY TABLE t1(c1 INTEGER);
+CREATE TEMPORARY TABLE t2(c1 INTEGER);
+INSERT INTO t1 VALUES(1);
+INSERT INTO t2 VALUES(1);
+
+CREATE TABLE IF NOT EXISTS t1(c1 INTEGER) SELECT c1 FROM t3;
+CREATE TABLE t2(c1 INTEGER) SELECT c1 FROM t3;
+
+# In these two statements, t1 and t2 are the temporary table. there is only
+# value '1' in them. The records of t2 are not inserted into them.
+SELECT * FROM t1;
+SELECT * FROM t2;
+sync_slave_with_master;
+
+# In these two statements, t1 and t2 are the base table. The records of t2
+# are inserted into it when CREATE TABLE ... SELECT was executed.
+SELECT * FROM t1;
+SELECT * FROM t2;
+
+connection master;
+DROP TEMPORARY TABLE t1;
+DROP TEMPORARY TABLE t2;
+#In these two statements, t1 and t2 are the base table.
+SELECT * FROM t1;
+SELECT * FROM t2;
+
+DROP TABLE t1;
+DROP TABLE t2;
+DROP TABLE t3;
+
+--echo # WL#5370
+--echo # The behavior of statement 'CREATE TABLE SELECT IF NOT EXISTS' is changed.
+--echo # After the worklog, it will insert nothing and the statement will not be
+--echo # binlogged if the table already exists.
+--echo # After the worklog, some bugs will disappear automotically.
+--source include/rpl_reset.inc
+
+--echo
+--echo # Case 1: BUG#47132
+connection master;
+call mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT.*");
+
+CREATE TABLE t1 (id int);
+CREATE TABLE t2 (id int);
+INSERT INTO t1 VALUES (1), (1);
+INSERT INTO t2 VALUES (2), (2);
+
+CREATE VIEW v1 AS SELECT id FROM t2;
+--let binlog_start= query_get_value(SHOW MASTER STATUS, Position, 1)
+CREATE TABLE IF NOT EXISTS v1(a int, b int) SELECT id, id as di FROM t1;
+--source include/show_binlog_events.inc
+
+SHOW CREATE TABLE v1;
+SELECT * FROM t2;
+SELECT * FROM v1;
+DROP VIEW v1;
+
+# the warning only happens on SBR, so we disable it.
+--disable_warnings
+CREATE TEMPORARY TABLE tt1 AS SELECT id FROM t2;
+--enable_warnings
+
+--let binlog_start= query_get_value(SHOW MASTER STATUS, Position, 1)
+CREATE TEMPORARY TABLE IF NOT EXISTS tt1(a int, b int) SELECT id, id FROM t1;
+--source include/show_binlog_events.inc
+SELECT * FROM t2;
+SELECT * FROM tt1;
+DROP TEMPORARY TABLE tt1;
+
+--echo
+--echo # Case 1: BUG#47132
+--echo # RBR breaks on CREATE TABLE IF EXISTS <existing VIEW> AS SELECT
+CREATE VIEW v1 AS SELECT 1 as a;
+--let binlog_start= query_get_value(SHOW MASTER STATUS, Position, 1)
+CREATE TABLE IF NOT EXISTS v1 SELECT 2 as a;
+--source include/show_binlog_events.inc
+sync_slave_with_master;
+
+connection master;
+DROP VIEW v1;
+
+DROP TABLE t1, t2;
+
+
+--echo #
+--echo # Test case which has failed on assertion after refactoring which was
+--echo # made as part of fix for bug #27480 "Extend CREATE TEMPORARY TABLES
+--echo # privilege to allow temp table operations".
+--echo #
+CREATE TEMPORARY TABLE t1 (id int);
+CREATE TABLE IF NOT EXISTS t2 LIKE t1;
+--echo # The below statement should succeed with warning and
+--echo # should not crash due to failing assertion.
+CREATE TABLE IF NOT EXISTS t2 LIKE t1;
+--echo # Clean-up.
+DROP TABLE t1, t2;
+sync_slave_with_master;
+connection master;
+
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_create_or_replace_fail.test b/mysql-test/suite/rpl/t/rpl_create_or_replace_fail.test
new file mode 100644
index 00000000..8624d3c9
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_create_or_replace_fail.test
@@ -0,0 +1,56 @@
+# ==== Purpose ====
+#
+# Test verifies that failed CREATE OR REPLACE TEMPORARY TABLE statement which
+# dropped the table but failed at a later stage of creation of temporary table
+# is written to binarylog in row based replication.
+#
+# ==== Implementation ====
+#
+# Steps:
+# 0 - Have mixed based replication mode.
+# 1 - Create a temporary table. It will be replicated as mixed replication
+# mode is in use.
+# 2 - Execute an unsafe statement which will switch current statement
+# binlog format to 'ROW'. i.e If binlog_format=MIXED, there are open
+# temporary tables, and an unsafe statement is executed, then subsequent
+# statements are logged in row format.
+# 3 - Execute a CREATE OR REPLACE TEMPORARY TABLE statement which tries to
+# create partitions on temporary table. Since it is not supported it will
+# fail.
+# 4 - Check the binary log output to ensure that the failed statement is
+# written to the binary log.
+# 5 - Slave should be up and running and in sync with master.
+#
+# ==== References ====
+#
+# MDEV-18930: Failed CREATE OR REPLACE TEMPORARY not written into binary log
+# makes data on master and slave diverge
+#
+
+--source include/have_partition.inc
+--source include/have_binlog_format_mixed.inc
+--source include/master-slave.inc
+
+CREATE TEMPORARY TABLE t1 (a INT NOT NULL);
+
+# Execute an unsafe statement which switches replication mode internally from
+# "STATEMENT" to "ROW".
+--error ER_NO_SUCH_TABLE
+LOAD DATA INFILE 'x' INTO TABLE x;
+
+--error ER_FEATURE_NOT_SUPPORTED_WITH_PARTITIONING
+CREATE OR REPLACE TEMPORARY TABLE t1 (x INT) PARTITION BY HASH(x);
+
+--echo "************** DROP TEMPORARY TABLE Should be present in Binary log **************"
+--source include/show_binlog_events.inc
+
+CREATE TABLE t1 (b INT);
+INSERT INTO t1 VALUES (NULL);
+--sync_slave_with_master
+
+# Cleanup
+--connection master
+DROP TABLE t1;
+
+--source include/rpl_end.inc
+
diff --git a/mysql-test/suite/rpl/t/rpl_create_tmp_table_if_not_exists.test b/mysql-test/suite/rpl/t/rpl_create_tmp_table_if_not_exists.test
new file mode 100644
index 00000000..3107fdfa
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_create_tmp_table_if_not_exists.test
@@ -0,0 +1,45 @@
+# BUG#45574:
+# SP: CREATE DATABASE|TABLE IF NOT EXISTS not binlogged if routine exists.
+#
+# There is an inconsistency with DROP DATABASE|TABLE|EVENT IF EXISTS and
+# CREATE DATABASE|TABLE|EVENT IF NOT EXISTS. DROP IF EXISTS statements are
+# binlogged even if either the DB, TABLE or EVENT does not exist. In
+# contrast, Only the CREATE EVENT IF NOT EXISTS is binlogged when the EVENT
+# exists.
+#
+# This problem caused some of the tests to fail randomly on PB or PB2.
+#
+# Test is implemented as follows:
+#
+# i) test each "CREATE TEMPORARY TABLE IF EXISTS" (DDL), found in MySQL
+# 5.1 manual, on existent objects;
+# ii) show binlog events;
+#
+# Note:
+# rpl_create_if_not_exists.test tests other cases.
+#
+# References:
+# http://dev.mysql.com/doc/refman/5.1/en/sql-syntax-data-definition.html
+#
+
+#CREATE TEMPORARY TABLE statements are not binlogged in row mode,
+#So it must be test by itself.
+source include/have_binlog_format_mixed_or_statement.inc;
+source include/master-slave.inc;
+disable_warnings;
+
+DROP DATABASE IF EXISTS mysqltest;
+
+CREATE TEMPORARY TABLE IF NOT EXISTS tmp(c1 int);
+CREATE TEMPORARY TABLE IF NOT EXISTS tmp(c1 int);
+CREATE TEMPORARY TABLE IF NOT EXISTS tmp1 LIKE tmp;
+CREATE TEMPORARY TABLE IF NOT EXISTS tmp1 LIKE tmp;
+CREATE TEMPORARY TABLE IF NOT EXISTS tmp2 SELECT * FROM tmp;
+CREATE TEMPORARY TABLE IF NOT EXISTS tmp2 SELECT * FROM tmp;
+source include/show_binlog_events.inc;
+
+DROP TEMPORARY TABLE tmp;
+DROP TEMPORARY TABLE tmp1;
+DROP TEMPORARY TABLE tmp2;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_create_xa_prepared.inc b/mysql-test/suite/rpl/t/rpl_create_xa_prepared.inc
new file mode 100644
index 00000000..b823ebf6
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_create_xa_prepared.inc
@@ -0,0 +1,9 @@
+# param $xid to name xa and take part in the connection name
+# param $query to execute as the xa body
+# param $db_ign the default database
+
+--connect (master_$xid, 127.0.0.1,root,,$db,$MASTER_MYPORT,)
+--eval xa start '$xid'
+--eval $query
+--eval xa end '$xid'
+--eval xa prepare '$xid';
diff --git a/mysql-test/suite/rpl/t/rpl_critical_errors.test b/mysql-test/suite/rpl/t/rpl_critical_errors.test
new file mode 100644
index 00000000..bc0d7096
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_critical_errors.test
@@ -0,0 +1,66 @@
+# Test for BUG#26551
+#
+
+# This test is unfortunately very fragile and very dependent on the
+# load of the computer. The test is therefore disabled normally. It is
+# entered here to demonstrate how to check that the bug is actually
+# solved.
+
+--echo Turn on parsing to run this test
+
+disable_parsing;
+
+source include/master-slave.inc;
+
+connection master;
+CREATE TABLE t1 (data LONGBLOB) ENGINE=MYISAM;
+CREATE TABLE t2 (data LONGBLOB) ENGINE=MYISAM;
+
+INSERT INTO t1 (data) VALUES (repeat('a',1024*1024));
+INSERT INTO t1 SELECT * FROM t1;
+INSERT INTO t1 SELECT * FROM t1;
+INSERT INTO t1 SELECT * FROM t1;
+INSERT INTO t1 SELECT * FROM t1;
+INSERT INTO t1 SELECT * FROM t1;
+INSERT INTO t1 SELECT * FROM t1;
+INSERT INTO t1 SELECT * FROM t1;
+INSERT INTO t1 SELECT * FROM t1;
+sync_slave_with_master;
+
+connection master;
+send INSERT INTO t2 SELECT * FROM t1;
+
+connection master1;
+
+# This sleep is picked so that the query above has started to insert
+# some rows into t2. If it hasn't the slave will not stop below.
+let $wait_condition= SELECT COUNT(*) > 1000 FROM t1;
+--source include/wait_condition.inc
+
+# SHOW PROCESSLIST;
+
+# Code for the 5.1 server to get the thread id of the thread executing
+# the query above.
+#
+#SET @id = 0;
+#SELECT id INTO @id
+# FROM information_schema.processlist
+# WHERE info LIKE 'INSERT INTO t2%';
+
+# This is the connection that is executing the INSERT INTO t2...
+KILL QUERY 2;
+
+connection slave;
+
+# Here the slave will only stop if the query above actually started
+# inserting some rows into t2. Otherwise, it will hang forever. ... and there
+# the error code should be 1317 (ER_QUERY_INTERRUPTED)
+--let $slave_sql_errno= 1317
+--let $show_slave_sql_error= 1
+--source include/wait_for_slave_sql_error.inc
+
+# The following should be 0
+SELECT COUNT(*) FROM t2;
+
+--source include/rpl_end.inc
+enable_parsing;
diff --git a/mysql-test/suite/rpl/t/rpl_cross_version-master.opt b/mysql-test/suite/rpl/t/rpl_cross_version-master.opt
new file mode 100644
index 00000000..815a8f81
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_cross_version-master.opt
@@ -0,0 +1 @@
+--replicate-same-server-id --relay-log=slave-relay-bin
diff --git a/mysql-test/suite/rpl/t/rpl_cross_version.test b/mysql-test/suite/rpl/t/rpl_cross_version.test
new file mode 100644
index 00000000..94c9f043
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_cross_version.test
@@ -0,0 +1,48 @@
+# ==== Purpose ====
+#
+# Verify cross-version replication from an old master to the up-to-date slave
+#
+# ==== Implementation ====
+#
+# Feed to the slave server a binlog recorded on an old version master
+# via setting up slave-to-slave replication. The latter is done by means of
+# the opt file and include/setup_fake_relay_log.inc.
+# The master's binlog is treated as a relay log that the SQL thread executes.
+#
+
+--source include/master-slave.inc
+
+#
+# Bug#31240 load data infile replication between (4.0 or 4.1) and 5.1 fails
+#
+
+--echo ==== Initialize ====
+--connection slave
+
+--disable_query_log
+# The binlog contains the function RAND which is unsafe.
+CALL mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT");
+--enable_query_log
+
+--source include/stop_slave.inc
+RESET SLAVE;
+
+# the relay log contains create t1, t3 tables and load data infile
+--let $fake_relay_log = $MYSQL_TEST_DIR/suite/binlog/std_data/binlog_old_version_4_1.000001
+--source include/setup_fake_relay_log.inc
+
+--echo ==== Test ====
+start slave sql_thread;
+--let $slave_param = Exec_Master_Log_Pos
+# end_log_pos of the last event of the relay log
+--let $slave_param_value = 149436
+--source include/wait_for_slave_param.inc
+--echo ==== a prove that the fake has been processed successfully ====
+SELECT COUNT(*) - 17920 as zero FROM t3;
+
+--echo ==== Clean up ====
+--source include/stop_slave_sql.inc
+--source include/cleanup_fake_relay_log.inc
+drop table t1, t3;
+--let $rpl_only_running_threads= 1
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_ctype_latin1.test b/mysql-test/suite/rpl/t/rpl_ctype_latin1.test
new file mode 100644
index 00000000..4c3535a1
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_ctype_latin1.test
@@ -0,0 +1,44 @@
+--source include/have_lowercase0.inc
+--disable_warnings
+--source include/master-slave.inc
+--enable_warnings
+
+--echo #
+--echo # Start of 10.2 tests
+--echo #
+
+
+--echo #
+--echo # MDEV-14249 Wrong character set info of Query_log_event and the query in Query_log_event constructed by different charsets cause error when slave apply the event.
+--echo #
+
+#
+# The below tests uses a sequence of bytes 0xD191,
+# which in a utf8 console looks like Ñ‘ (CYRILIC SMALL LETTER YO).
+# Don't be mislead. This sequence is used in latin1 context and
+# represents a sequence of two characters:
+# U+00D1 CAPITAL LATIN LETTER N WITH TILDE (_latin1 0xD1)
+# U+2018 LEFT SINGLE QUOTATION MARK (_latin1 0x91)
+#
+
+SET NAMES latin1;
+CREATE TABLE `tё` (`tё` INT);
+CREATE VIEW `vё` AS SELECT 'vё';
+CREATE PROCEDURE `pё`() SELECT 'pё';
+
+select hex(table_name) from information_schema.tables where table_schema="test" and table_name like "t%";
+select hex(table_name) from information_schema.tables where table_schema="test" and table_name like "v%";
+
+--sync_slave_with_master
+select hex(table_name) from information_schema.tables where table_schema="test" and table_name like "t%";
+select hex(table_name) from information_schema.tables where table_schema="test" and table_name like "v%";
+--replace_column 5 ts 6 ts
+SHOW PROCEDURE STATUS WHERE Name LIKE 'p%' and Db = 'test';
+
+--connection master
+DROP TABLE `tё`;
+DROP VIEW `vё`;
+DROP PROCEDURE `pё`;
+--sync_slave_with_master
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_current_user.cnf b/mysql-test/suite/rpl/t/rpl_current_user.cnf
new file mode 100644
index 00000000..58b605ad
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_current_user.cnf
@@ -0,0 +1,8 @@
+!include ../my.cnf
+
+[mysqld.3]
+log-slave-updates
+
+[ENV]
+SERVER_MYPORT_3= @mysqld.3.port
+SERVER_MYSOCK_3= @mysqld.3.socket
diff --git a/mysql-test/suite/rpl/t/rpl_current_user.test b/mysql-test/suite/rpl/t/rpl_current_user.test
new file mode 100644
index 00000000..391606e3
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_current_user.test
@@ -0,0 +1,225 @@
+##############################################################################
+# BUG#48321 CURRENT_USER() incorrectly replicated for DROP/RENAME USER,
+# REVOKE, GRANT, ALTER EVENT
+#
+# Calling CURRENT_USER() results into inconsistency between slave and master,
+# as the slave SQL thread has different user with common users.
+#
+# After the patch for bug#48321, session's user will be written into query log
+# event if CURRENT_USER() is called in 'DROP/RENAME USER', 'REVOKE', 'GRANT',
+# 'ALTER EVENT'.
+#
+##############################################################################
+
+source include/have_binlog_format_statement.inc;
+
+--let $rpl_topology= 1->2->3
+--source include/rpl_init.inc
+
+--let $rpl_connection_name= master
+--let $rpl_server_number= 1
+--source include/rpl_connect.inc
+
+--let $rpl_connection_name= slave
+--let $rpl_server_number= 2
+--source include/rpl_connect.inc
+
+--disable_query_log
+--connection server_1
+call mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT.*");
+--connection server_2
+call mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT.*");
+--connection server_3
+call mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT.*");
+--enable_query_log
+
+--connection master
+
+CREATE TABLE t1(c1 char(100));
+CREATE VIEW test.v_user AS SELECT * FROM mysql.user WHERE User LIKE 'bug48321%';
+CREATE VIEW test.v_tables_priv AS SELECT * FROM mysql.tables_priv WHERE User LIKE 'bug48321%';
+CREATE VIEW test.v_procs_priv AS SELECT * FROM mysql.procs_priv WHERE User LIKE 'bug48321%';
+CREATE VIEW test.v_event AS SELECT definer FROM mysql.event WHERE name = 'e1';
+CREATE PROCEDURE p1() SELECT 1;
+--echo # bug48321_1-01234 has the max length(16) of user.
+CREATE USER 'bug48321_1-01234'@'localhost';
+GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1-01234'@'localhost' WITH GRANT OPTION;
+
+--echo
+--echo # Test the max lengths of user and host names
+--echo # the user name is too long
+--error ER_WRONG_STRING_LENGTH
+GRANT CREATE USER ON *.* TO '012345678901234567890123456789012345678901234567890123456789012345678901234567890'@'fakehost';
+--echo # the host name is too long
+--error ER_WRONG_STRING_LENGTH
+GRANT CREATE USER ON *.* TO 'fakename'@'0123456789012345678901234567890123456789012345678901234567890';
+
+--echo
+--echo # User 'bug48321_1-01234' connects to master by conn1
+connect (conn1, 127.0.0.1, 'bug48321_1-01234'@'localhost',,);
+connection conn1;
+--echo # Verify 'REVOKE ALL' statement
+REVOKE ALL PRIVILEGES, GRANT OPTION FROM CURRENT_USER();
+--source include/rpl_sync.inc
+let $diff_tables= server_1:v_user, server_2:v_user, server_3:v_user;
+source include/diff_tables.inc;
+
+--echo
+--echo # Verify 'GRANT ... ON TABLE ...' statement
+GRANT CREATE, INSERT, SELECT ON TABLE test.t1 TO CURRENT_USER();
+--source include/rpl_sync.inc
+let $diff_tables= server_1:v_tables_priv, server_2:v_tables_priv, server_3:v_tables_priv;
+source include/diff_tables.inc;
+
+--echo
+--echo # Verify 'GRANT ... ON PROCEDURE...' statement
+GRANT ALTER ROUTINE, EXECUTE ON PROCEDURE p1 TO CURRENT_USER();
+--source include/rpl_sync.inc
+let $diff_tables= server_1:v_procs_priv, server_2:v_procs_priv, server_3:v_procs_priv;
+source include/diff_tables.inc;
+
+--echo
+--echo # Verify 'GRANT ... ON *.* ...' statement
+GRANT ALL PRIVILEGES ON *.* TO CURRENT_USER() WITH GRANT OPTION;
+--source include/rpl_sync.inc
+let $diff_tables= server_1:v_procs_priv, server_2:v_procs_priv, server_3:v_procs_priv;
+source include/diff_tables.inc;
+
+--echo
+--echo # Verify 'REVOKE ... ON TABLE ...' statement
+REVOKE CREATE, INSERT, SELECT ON TABLE t1 FROM CURRENT_USER();
+--source include/rpl_sync.inc
+let $diff_tables= server_1:v_tables_priv, server_2:v_tables_priv, server_3:v_tables_priv;
+source include/diff_tables.inc;
+
+--echo
+--echo # Verify 'REVOKE ... ON PROCEDURE...' statement
+REVOKE ALTER ROUTINE, EXECUTE ON PROCEDURE p1 FROM CURRENT_USER();
+--source include/rpl_sync.inc
+let $diff_tables= server_1:v_procs_priv, server_2:v_procs_priv, server_3:v_procs_priv;
+source include/diff_tables.inc;
+
+--echo
+--echo # Verify 'REVOKE ... ON *.* ...' statement
+REVOKE ALL PRIVILEGES ON *.* FROM CURRENT_USER();
+--source include/rpl_sync.inc
+let $diff_tables= server_1:v_user, server_2:v_user, server_3:v_user;
+source include/diff_tables.inc;
+
+--echo
+--echo # Verify 'GRANT ...' statement in the procedure
+CREATE PROCEDURE my_grant()
+ GRANT CREATE, INSERT, SELECT ON TABLE test.t1 TO CURRENT_USER();
+call my_grant;
+--source include/rpl_sync.inc
+let $diff_tables= server_1:v_tables_priv, server_2:v_tables_priv, server_3:v_tables_priv;
+source include/diff_tables.inc;
+
+--echo
+--echo # Verify 'REVOKE ... ON TABLE ...' statement in the procedure
+CREATE PROCEDURE my_revoke()
+ REVOKE CREATE, INSERT, SELECT ON TABLE t1 FROM CURRENT_USER();
+call my_revoke;
+--source include/rpl_sync.inc
+let $diff_tables= server_1:v_tables_priv, server_2:v_tables_priv, server_3:v_tables_priv;
+source include/diff_tables.inc;
+
+--echo
+--echo # Verify 'RENAME USER ...' statement
+RENAME USER CURRENT_USER TO 'bug48321_2'@'localhost';
+--source include/rpl_sync.inc
+let $diff_tables= server_1:v_user, server_2:v_user, server_3:v_user;
+source include/diff_tables.inc;
+
+disconnect conn1;
+
+--echo
+--echo # Verify 'DROP USER ...' statement
+connection master;
+GRANT CREATE USER ON *.* TO 'bug48321_2'@'localhost';
+connect (conn1, 127.0.0.1, 'bug48321_2'@'localhost',,);
+connection conn1;
+DROP USER CURRENT_USER();
+--source include/rpl_sync.inc
+let $diff_tables= server_1:v_user, server_2:v_user, server_3:v_user;
+source include/diff_tables.inc;
+
+--echo
+--echo # Verify 'ALTER EVENT...' statement
+connection master;
+CREATE EVENT e1 ON SCHEDULE EVERY 1 DAY DO SELECT * FROM t1;
+
+--echo # Explicitly assign CURRENT_USER() to definer
+ALTER DEFINER=CURRENT_USER() EVENT e1 ENABLE;
+--source include/rpl_sync.inc
+let $diff_tables= server_1:v_event, server_2:v_event, server_3:v_event;
+source include/diff_tables.inc;
+
+--echo
+--echo # Session user will be set as definer, if the statement does not assign
+--echo # a definer
+ALTER EVENT e1 ENABLE;
+--source include/rpl_sync.inc
+let $diff_tables= server_1:v_event, server_2:v_event, server_3:v_event;
+source include/diff_tables.inc;
+
+--echo
+--echo # Verify that this patch does not affect the calling of CURRENT_USER()
+--echo # in the other statements
+connection master;
+INSERT INTO t1 VALUES(CURRENT_USER()), ('1234');
+SELECT * FROM t1;
+sync_slave_with_master;
+SELECT * FROM t1;
+sync_slave_with_master server_3;
+SELECT * FROM t1;
+
+connection master;
+UPDATE t1 SET c1=CURRENT_USER() WHERE c1='1234';
+SELECT * FROM t1;
+sync_slave_with_master;
+SELECT * FROM t1;
+sync_slave_with_master server_3;
+SELECT * FROM t1;
+
+connection master;
+DELETE FROM t1 WHERE c1=CURRENT_USER();
+SELECT * FROM t1;
+sync_slave_with_master;
+SELECT * FROM t1;
+sync_slave_with_master server_3;
+SELECT * FROM t1;
+
+connection master;
+CREATE TABLE t2(c1 char(100));
+
+DELIMITER |;
+CREATE FUNCTION my_user() RETURNS VARCHAR(64)
+ SQL SECURITY INVOKER
+BEGIN
+ INSERT INTO t2 VALUES(CURRENT_USER());
+ RETURN CURRENT_USER();
+END |
+DELIMITER ;|
+
+INSERT INTO t1 VALUES(my_user());
+SELECT * FROM t1;
+SELECT * FROM t2;
+sync_slave_with_master;
+SELECT * FROM t1;
+SELECT * FROM t2;
+sync_slave_with_master server_3;
+SELECT * FROM t1;
+SELECT * FROM t2;
+
+--echo
+--echo # END
+connection master;
+DROP TABLE t1, t2;
+DROP VIEW v_user, v_tables_priv, v_procs_priv, v_event;
+DROP PROCEDURE p1;
+DROP PROCEDURE my_grant;
+DROP PROCEDURE my_revoke;
+DROP FUNCTION my_user;
+DROP EVENT e1;
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_ddl-slave.opt b/mysql-test/suite/rpl/t/rpl_ddl-slave.opt
new file mode 100644
index 00000000..21356507
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_ddl-slave.opt
@@ -0,0 +1 @@
+--loose-skip-innodb
diff --git a/mysql-test/suite/rpl/t/rpl_ddl.test b/mysql-test/suite/rpl/t/rpl_ddl.test
new file mode 100644
index 00000000..b11a6927
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_ddl.test
@@ -0,0 +1,32 @@
+######################## rpl_ddl.test ########################
+# #
+# DDL statements (sometimes with implicit COMMIT) executed #
+# by the master and it's propagation into the slave #
+# #
+##############################################################
+
+#
+# NOTE, PLEASE BE CAREFUL, WHEN MODIFYING THE TESTS !!
+#
+# 1. !All! objects to be dropped, renamed, altered ... must be created
+# in AUTOCOMMIT= 1 mode before AUTOCOMMIT is set to 0 and the test
+# sequences start.
+#
+# 2. Never use a test object, which was direct or indirect affected by a
+# preceding test sequence again.
+# Except table d1.t1 where ONLY DML is allowed.
+#
+# If one preceding test sequence hits a (sometimes not good visible,
+# because the sql error code of the statement might be 0) bug
+# and these rules are ignored, a following test sequence might earn ugly
+# effects like failing 'sync_slave_with_master', crashes of the slave or
+# abort of the test case etc..
+#
+--source include/have_innodb.inc
+--source include/master-slave.inc
+let $engine_type= InnoDB;
+let $temp_engine_type= MEMORY;
+let $show_binlog = 0;
+let $manipulate = 0;
+-- source include/rpl_ddl.test
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_deadlock_innodb-slave.opt b/mysql-test/suite/rpl/t/rpl_deadlock_innodb-slave.opt
new file mode 100644
index 00000000..f516b1b7
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_deadlock_innodb-slave.opt
@@ -0,0 +1 @@
+--loose-innodb-lock-wait-timeout=4 --slave-transaction-retries=2 --max-relay-log-size=4096
diff --git a/mysql-test/suite/rpl/t/rpl_deadlock_innodb.test b/mysql-test/suite/rpl/t/rpl_deadlock_innodb.test
new file mode 100644
index 00000000..e2311cb0
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_deadlock_innodb.test
@@ -0,0 +1,4 @@
+-- source include/have_innodb.inc
+-- source include/long_test.inc
+let $engine_type=innodb;
+-- source include/rpl_deadlock.test
diff --git a/mysql-test/suite/rpl/t/rpl_default.test b/mysql-test/suite/rpl/t/rpl_default.test
new file mode 100644
index 00000000..9adf15c9
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_default.test
@@ -0,0 +1,29 @@
+#
+# Test of replicating default values
+# As the table is using non deterministic functions, replication must
+# switch to binlog format.
+#
+
+-- source include/have_binlog_format_mixed_or_row.inc
+-- source include/master-slave.inc
+
+connection master;
+
+create table t1 (a int DEFAULT (1+1), b bigint default uuid_short(), u blob default user());
+insert into t1 (a) values(1);
+
+let $b=query_get_value(select * from t1, b, 1);
+let $u=query_get_value(select * from t1, u, 1);
+
+sync_slave_with_master;
+connection slave;
+
+show create table t1;
+--disable_query_log
+eval select a,"$b"=b as uuid,"$u"=u as user from t1;
+--enable_query_log
+connection master;
+
+drop table t1;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_delayed_slave.combinations b/mysql-test/suite/rpl/t/rpl_delayed_slave.combinations
new file mode 100644
index 00000000..bac7cb33
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_delayed_slave.combinations
@@ -0,0 +1,4 @@
+[nonparallel]
+
+[parallel]
+--slave-parallel-threads=10
diff --git a/mysql-test/suite/rpl/t/rpl_delayed_slave.test b/mysql-test/suite/rpl/t/rpl_delayed_slave.test
new file mode 100644
index 00000000..d00e796b
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_delayed_slave.test
@@ -0,0 +1,428 @@
+# ==== Purpose ====
+#
+# Test the time-delayed replication feature, i.e.,
+# CHANGE MASTER TO MASTER_DELAY=X:
+#
+# - Verify that slave has executed the events after but not before the
+# delay timeout.
+#
+# - Verify that delay is correct when slave is already lagging
+# due to slow queries.
+#
+# - Verify that Seconds_Behind_Master is greater than or equal to the
+# delay if the slave still has unprocessed events in the relay log
+# and more time than the delay has elapsed since the last event was
+# executed on the master.
+#
+# - Verify that STOP SLAVE works instantly even during a delay, and
+# that it does not cause the waited-for event to be executed too
+# early on slave.
+#
+# - Verify that changing back to no delay works.
+#
+# - Verify that RESET SLAVE sets the delay to 0.
+#
+# - Verify that setting a bad value for the delay gives an error.
+#
+# ==== Implementation ====
+#
+# We run the slave with 10 seconds lag.
+#
+# In general, to test that a query has not been executed by the slave
+# before this time, we wait until the slave IO thread has received the
+# event, and then 5 seconds more, and check that the table has not
+# been updated. To test that a query has been executed after this
+# time, we wait 10 seconds more.
+#
+# To simulate that the slave lags due to slow queries, we invoke a
+# stored function that executes SLEEP if @@gloval.server_id==2. This
+# requires that we run with binlog_format=STATEMENT.
+#
+# ==== Related Bugs and Worklogs ====
+#
+# WL#344: Time-delayed replication
+# BUG#28760: Simulating a replication lag
+# [duplicate] BUG#22072: configurable delayed replication
+# [duplicate] BUG#21639: Add Replication Delay parameter
+# BUG#56442: Slave executes delayed statements when STOP SLAVE is issued
+#
+# ==== Issues with this Test Case ====
+#
+# The test is inherently timing-sensitive (i.e., contains races) and
+# is likely to fail sporadically on a loaded host.
+#
+# The test takes a long time; it sleeps for around 20*10 seconds.
+
+--source include/big_test.inc
+--source include/not_valgrind.inc
+--source include/master-slave.inc
+# Needed so that sleeps get executed in the slave SQL thread.
+--source include/have_binlog_format_statement.inc
+
+
+call mtr.add_suppression("Unsafe statement written to the binary log using statement format");
+--connection slave
+call mtr.add_suppression("Unsafe statement written to the binary log using statement format");
+--source include/stop_slave.inc
+CHANGE MASTER TO MASTER_USE_GTID=NO;
+--source include/start_slave.inc
+--connection master
+
+
+# We assume that any simple operation takes zero time, with an error
+# margin of $time1 seconds. Hence, if we run with a delay of $time2
+# seconds, we expect that:
+# - If we execute a query on master and wait $time1 seconds, then the
+# query has been copied to slave but not yet executed.
+# - If we execute a query on master and wait $time3 seconds, then the
+# query has been executed.
+--let $time1= 10
+if (`SELECT '$max_query_execution_time' > 0`) {
+ --let $time1= $max_query_execution_time
+}
+--let $time2= `SELECT 2 * $time1`
+--let $time3= `SELECT 3 * $time1`
+
+
+--echo [on master]
+CREATE TABLE t1 (a VARCHAR(100), b INT);
+INSERT INTO t1 VALUES ("zero", 0);
+
+
+--echo ==== Normal setup ====
+
+--echo [on slave]
+--sync_slave_with_master
+
+--source include/stop_slave.inc
+
+--echo # CHANGE MASTER TO MASTER_DELAY = 2*T
+--disable_query_log
+eval CHANGE MASTER TO MASTER_DELAY = $time2;
+--enable_query_log
+
+--source include/start_slave.inc
+
+--let $assert_text= SHOW SLAVE STATUS should return the same delay that we set with CHANGE MASTER
+--let $assert_cond= [SHOW SLAVE STATUS, SQL_Delay, 1] = $time2
+--source include/rpl_assert.inc
+
+--echo [on master]
+--connection master
+INSERT INTO t1 VALUES ('normal setup', 1);
+
+--let $query_number= 1
+--source include/delayed_slave_wait_on_query.inc
+
+
+--echo ==== Slave lags "naturally" after master ====
+
+--echo [on master]
+--connection master
+
+--disable_query_log
+--echo # CREATE FUNCTION delay_on_slave(time_units INT) RETURNS INT BEGIN IF @@GLOBAL.server_id = 2 THEN RETURN SLEEP(time_units * T); ELSE RETURN 0; END IF; END
+--eval CREATE FUNCTION delay_on_slave(time_units INT) RETURNS INT BEGIN IF @@GLOBAL.server_id = 2 THEN RETURN SLEEP(time_units * $time1); ELSE RETURN 0; END IF; END
+--enable_query_log
+
+INSERT INTO t1 SELECT delay_on_slave(3), 2;
+
+--save_master_pos
+INSERT INTO t1 VALUES ('slave is already lagging: this statement should execute immediately', 3);
+INSERT INTO t1 SELECT delay_on_slave(2), 4;
+
+--echo [on slave]
+--source include/sync_slave_io_with_master.inc
+--echo # sleep 1*T
+--sleep $time1
+
+--let $assert_text= No query executed
+--let $assert_cond= MAX(b) = 1 FROM t1
+--source include/rpl_assert.inc
+
+--let $assert_text= Status should be 'Waiting until MASTER_DELAY...'
+--let $assert_cond= "[SHOW SLAVE STATUS, Slave_SQL_Running_State, 1]" LIKE "Waiting until MASTER_DELAY%"
+--source include/rpl_assert.inc
+
+--echo # wait for first query to execute
+--sync_with_master
+
+--echo # sleep 1*T
+--sleep $time1
+
+--let $assert_text= Second query executed
+--let $assert_cond= MAX(b) = 3 FROM t1
+--source include/rpl_assert.inc
+
+let $parallel= `SELECT @@GLOBAL.slave_parallel_threads`;
+if (!$parallel)
+{
+ let $assert_text= Status should be executing third query (i.e., 'User sleep');
+ let $assert_cond= "[SHOW SLAVE STATUS, Slave_SQL_Running_State, 1]" = "User sleep";
+ source include/rpl_assert.inc;
+}
+
+--echo # sleep 2*T
+--sleep $time2
+
+--let $assert_text= Third query executed
+--let $assert_cond= MAX(b) = 4 FROM t1
+--source include/rpl_assert.inc
+
+--let $assert_text= Status should be 'Has read all relay log...'
+--let $assert_cond= "[SHOW SLAVE STATUS, Slave_SQL_Running_State, 1]" LIKE "Slave has read all relay log%"
+--source include/rpl_assert.inc
+
+
+--echo ==== Seconds_Behind_Master ====
+
+--echo # Bring slave to sync.
+--source include/stop_slave.inc
+CHANGE MASTER TO MASTER_DELAY = 0;
+--source include/start_slave.inc
+
+--connection master
+INSERT INTO t1 VALUES ('Syncing slave', 5);
+--sync_slave_with_master
+
+--source include/stop_slave.inc
+--echo # CHANGE MASTER TO MASTER_DELAY = 2*T
+--disable_query_log
+eval CHANGE MASTER TO MASTER_DELAY = $time2;
+--enable_query_log
+--source include/start_slave.inc
+
+--connection master
+INSERT INTO t1 VALUES (delay_on_slave(1), 6);
+--save_master_pos
+--connection slave
+
+--echo # sleep 1*T
+--sleep $time1
+
+--let $assert_cond= [SHOW SLAVE STATUS, Seconds_Behind_Master, 1] >= 0 AND <1> < $time2
+--let $assert_text= Seconds_Behind_Master should be between 0 and the 2*T
+--source include/rpl_assert.inc
+
+--echo # sleep 1*T
+--sleep $time1
+
+--let $assert_cond= [SHOW SLAVE STATUS, Seconds_Behind_Master, 1] >= $time2
+--let $assert_text= Seconds_Behind_Master should be at least 2*T
+--source include/rpl_assert.inc
+
+--sync_with_master
+
+
+--echo ==== STOP SLAVE / START SLAVE + DML ====
+
+# Set up a longer delay.
+--source include/stop_slave.inc
+
+--echo # CHANGE MASTER TO MASTER_DELAY = 3*T
+--disable_query_log
+eval CHANGE MASTER TO MASTER_DELAY = $time3;
+--enable_query_log
+
+--source include/start_slave.inc
+
+--echo [on master]
+--connection master
+INSERT INTO t1 VALUES ('stop slave and start slave: DML', 7);
+
+--echo [on slave]
+--connection slave
+--echo # sleep 1*T
+--sleep $time1
+--let $timestamp_before_stop= `SELECT UNIX_TIMESTAMP()`
+--let $relay_log_pos_before_stop= query_get_value(SHOW SLAVE STATUS, Relay_Log_Pos, 1)
+--source include/stop_slave.inc
+
+--let $assert_text= STOP SLAVE should finish quickly, not wait for the ongoing sleep to finish
+--let $assert_cond= UNIX_TIMESTAMP() - $timestamp_before_stop < $time1
+--source include/rpl_assert.inc
+
+--let $assert_text= SQL thread position should not increase after STOP SLAVE
+--let $assert_cond= [SHOW SLAVE STATUS, Relay_Log_Pos, 1] = $relay_log_pos_before_stop
+--source include/rpl_assert.inc
+
+--let $assert_text= Query should not be executed after STOP SLAVE
+--let $assert_cond= MAX(b) = 6 FROM t1
+--source include/rpl_assert.inc
+
+--let $assert_text= Status should be '' after STOP SLAVE
+--let $assert_cond= "[SHOW SLAVE STATUS, Slave_SQL_Running_State, 1]" = ""
+--source include/rpl_assert.inc
+
+--source include/start_slave.inc
+
+--let $assert_text= START SLAVE should finish quickly
+--let $assert_cond= UNIX_TIMESTAMP() - $timestamp_before_stop < $time1
+--source include/rpl_assert.inc
+
+--let $query_number= 7
+--source include/delayed_slave_wait_on_query.inc
+
+
+--echo ==== STOP SLAVE / START SLAVE + DDL ====
+
+--echo This verifies BUG#56442
+
+--echo [on master]
+--connection master
+CREATE TABLE t_check_dml_not_executed_prematurely (a INT);
+--source include/save_master_pos.inc
+
+--echo [on slave]
+--connection slave
+--echo # sleep 1*T
+--sleep $time1
+
+--let $timestamp_before_stop= `SELECT UNIX_TIMESTAMP()`
+--let $relay_log_pos_before_stop= query_get_value(SHOW SLAVE STATUS, Relay_Log_Pos, 1)
+--source include/stop_slave.inc
+
+--let $assert_text= STOP SLAVE should finish quickly, not wait for the ongoing sleep to finish
+--let $assert_cond= UNIX_TIMESTAMP() - $timestamp_before_stop < $time1
+--source include/rpl_assert.inc
+
+--let $assert_text= SQL thread position should not increase after STOP SLAVE
+--let $assert_cond= [SHOW SLAVE STATUS, Relay_Log_Pos, 1] = $relay_log_pos_before_stop
+--source include/rpl_assert.inc
+
+--let $assert_text= Query should not be executed after STOP SLAVE
+--let $assert_cond= COUNT(*) = 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = "t_check_dml_not_executed_prematurely"
+--source include/rpl_assert.inc
+
+--let $assert_text= Status should be '' after STOP SLAVE
+--let $assert_cond= "[SHOW SLAVE STATUS, Slave_SQL_Running_State, 1]" = ""
+--source include/rpl_assert.inc
+
+--source include/start_slave.inc
+
+--let $assert_text= START SLAVE should finish quickly
+--let $assert_cond= UNIX_TIMESTAMP() - $timestamp_before_stop < $time1
+--source include/rpl_assert.inc
+
+--echo # sleep 1*T
+--sleep $time1
+
+--let $assert_text= DDL Query should not be executed after START SLAVE
+--let $assert_cond= COUNT(*) = 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = "t_check_dml_not_executed_prematurely"
+--source include/rpl_assert.inc
+
+--let $assert_text= Status should be 'Waiting until MASTER_DELAY...'
+--let $assert_cond= "[SHOW SLAVE STATUS, Slave_SQL_Running_State, 1]" LIKE "Waiting until MASTER_DELAY%"
+--source include/rpl_assert.inc
+
+--echo # sleep 1*T
+--sleep $time1
+
+--echo # sync with master (with timeout 1*T)
+--source include/sync_with_master.inc
+
+--let $assert_text= DDL Query should be executed
+--let $assert_cond= COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = "t_check_dml_not_executed_prematurely"
+--source include/rpl_assert.inc
+
+--let $assert_text= Status should be 'Has read all relay log...'
+--let $assert_cond= "[SHOW SLAVE STATUS, Slave_SQL_Running_State, 1]" LIKE "Slave has read all relay log%"
+--source include/rpl_assert.inc
+
+--source include/check_slave_is_running.inc
+
+
+--echo ==== Change back to no delay ====
+
+--echo [on slave]
+--connection slave
+--source include/stop_slave.inc
+CHANGE MASTER TO MASTER_DELAY = 0;
+
+--let $assert_text= Delay should be 0 when we set it to 0
+--let $assert_cond= [SHOW SLAVE STATUS, SQL_Delay, 1] = 0
+--source include/rpl_assert.inc
+
+--source include/start_slave.inc
+
+--echo [on master]
+--connection master
+INSERT INTO t1 VALUES ('change back to no delay', 8);
+
+--echo [on slave]
+--source include/sync_slave_io_with_master.inc
+--echo # sleep 1*T
+--sleep $time1
+
+--let $assert_text= Query should be executed
+--let $assert_cond= MAX(b) = 8 FROM t1
+--source include/rpl_assert.inc
+
+--let $assert_text= Status should be 'Slave has read all relay log...'
+--let $assert_cond= "[SHOW SLAVE STATUS, Slave_SQL_Running_State, 1]" Like "Slave has read all relay log%"
+--source include/rpl_assert.inc
+
+
+--echo ==== Reset delay with RESET SLAVE ====
+
+--source include/stop_slave.inc
+CHANGE MASTER TO MASTER_DELAY = 71;
+--source include/start_slave.inc
+
+--let $assert_text= Delay should be 71 when we set it to 71
+--let $assert_cond= [SHOW SLAVE STATUS, SQL_Delay, 1] = 71
+--source include/rpl_assert.inc
+
+--source include/stop_slave.inc
+--let $master_use_gtid_option= No
+--source include/reset_slave.inc
+--echo [on master]
+--connection master
+RESET MASTER;
+--echo [on slave]
+--connection slave
+--source include/start_slave.inc
+
+--let $assert_text= Delay should be 0 after RESET SLAVE
+--let $assert_cond= [SHOW SLAVE STATUS, SQL_Delay, 1] = 0
+--source include/rpl_assert.inc
+
+
+--echo ==== Set an invalid value for the delay ====
+
+--source include/stop_slave.inc
+
+--echo # Expect error for setting negative delay
+--error ER_PARSE_ERROR
+CHANGE MASTER TO MASTER_DELAY = -1;
+
+--echo # Expect that it's ok to set delay of 2^31-1
+CHANGE MASTER TO MASTER_DELAY = 2147483647;
+--echo # Expect error for setting delay between 2^31 and 2^32-1
+--error ER_MASTER_DELAY_VALUE_OUT_OF_RANGE
+CHANGE MASTER TO MASTER_DELAY = 2147483648;
+
+--echo # Expect error for setting delay to nonsense
+--error ER_PARSE_ERROR
+CHANGE MASTER TO MASTER_DELAY = blah;
+
+# todo: CHANGE MASTER TO MASTER_DELAY = 999999999999999999999999999
+# should give error
+
+CHANGE MASTER TO MASTER_DELAY = 0;
+--source include/start_slave.inc
+
+
+--echo ==== Clean up ====
+
+--echo [on master]
+--connection master
+DROP TABLE t1, t_check_dml_not_executed_prematurely;
+DROP FUNCTION delay_on_slave;
+
+--echo [on slave]
+--sync_slave_with_master
+SELECT @@GLOBAL.slave_parallel_mode;
+SELECT @@GLOBAL.slave_parallel_threads;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_delayed_slave2.test b/mysql-test/suite/rpl/t/rpl_delayed_slave2.test
new file mode 100644
index 00000000..68e8f8e1
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_delayed_slave2.test
@@ -0,0 +1,65 @@
+--source include/have_innodb.inc
+--source include/master-slave.inc
+
+# This test file tests delayed slave for parallel replication (and GTID).
+# Uses a different approach from rpl_delayed_slave.test, setting @@timestamp
+# to simulate events logged on master at different times.
+
+--connection master
+ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
+CREATE TABLE t1 (a INT PRIMARY KEY, b VARCHAR(100));
+INSERT INTO t1 VALUES (1, "a");
+--save_master_pos
+
+--connection slave
+--sync_with_master
+--source include/stop_slave.inc
+CHANGE MASTER TO master_use_gtid=slave_pos;
+SET @old_mode= @@GLOBAL.slave_parallel_mode;
+SET GLOBAL slave_parallel_mode=optimistic;
+SET @old_threads= @@GLOBAL.slave_parallel_threads;
+SET GLOBAL slave_parallel_threads=10;
+
+--connection master
+INSERT INTO t1 VALUES (2, "b");
+INSERT INTO t1 VALUES (3, "b");
+INSERT INTO t1 VALUES (4, "b");
+--let $gtid1= `SELECT @@gtid_binlog_pos`
+# Simulate an event a days in the future, for delayed slave to wait on.
+SET timestamp= @@timestamp + 24*60*60;
+INSERT INTO t1 VALUES (5, "c");
+INSERT INTO t1 VALUES (6, "c");
+SET timestamp= 0;
+--let $gtid2= `SELECT @@gtid_binlog_pos`
+--source include/save_master_gtid.inc
+
+--connection slave
+CHANGE MASTER TO master_delay=1;
+--source include/start_slave.inc
+--replace_result $gtid1 GTID1
+# First sync halfways, to avoid timing-dependent test failures.
+eval SELECT MASTER_GTID_WAIT('$gtid1');
+# Try to sync up, should timeout because slave is waiting for one day.
+--replace_result $gtid2 GTID2
+eval SELECT MASTER_GTID_WAIT('$gtid2', 2);
+
+# Check that we can stop slave while delaying.
+--source include/stop_slave.inc
+SELECT * FROM t1 ORDER BY a;
+CHANGE MASTER TO master_delay=0;
+--source include/start_slave.inc
+--source include/sync_with_master_gtid.inc
+SELECT * FROM t1 ORDER BY a;
+
+
+--connection slave
+--source include/stop_slave.inc
+CHANGE MASTER TO master_use_gtid=no, master_delay=0;
+SET GLOBAL slave_parallel_mode=@old_mode;
+SET GLOBAL slave_parallel_threads=@old_threads;
+--source include/start_slave.inc
+
+--connection master
+DROP TABLE t1;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_delete_no_where.test b/mysql-test/suite/rpl/t/rpl_delete_no_where.test
new file mode 100644
index 00000000..c07649cb
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_delete_no_where.test
@@ -0,0 +1,4 @@
+-- source include/master-slave.inc
+let $engine_type=myisam;
+-- source include/rpl_delete_no_where.test
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_do_grant.test b/mysql-test/suite/rpl/t/rpl_do_grant.test
new file mode 100644
index 00000000..1350585f
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_do_grant.test
@@ -0,0 +1,350 @@
+# Works in statement-based and row-based binlogging.
+# Test that GRANT and other user management commands are replicated to the slave
+
+-- source include/master-slave.inc
+
+# test replication of GRANT
+connection master;
+create user rpl_do_grant@localhost;
+grant select on *.* to rpl_do_grant@localhost;
+grant drop on test.* to rpl_do_grant@localhost;
+sync_slave_with_master;
+show grants for rpl_do_grant@localhost;
+
+# test replication of SET PASSWORD
+connection master;
+set password for rpl_do_grant@localhost=password("does it work?");
+sync_slave_with_master;
+select authentication_string<>'' from mysql.user where user='rpl_do_grant';
+
+#
+# Bug#24158 SET PASSWORD in binary log fails under ANSI_QUOTES
+#
+connection master;
+update mysql.global_priv set priv=json_remove(priv, '$.authentication_string') where user='rpl_do_grant';
+flush privileges;
+select authentication_string<>'' from mysql.user where user='rpl_do_grant';
+set sql_mode='ANSI_QUOTES';
+set password for rpl_do_grant@localhost=password('does it work?');
+set sql_mode='';
+sync_slave_with_master;
+select authentication_string<>'' from mysql.user where user='rpl_do_grant';
+
+# clear what we have done, to not influence other tests.
+connection master;
+drop user rpl_do_grant@localhost;
+sync_slave_with_master;
+
+# End of 4.1 tests
+
+connection master;
+--error 1141
+show grants for rpl_do_grant@localhost;
+connection slave;
+--error 1141
+show grants for rpl_do_grant@localhost;
+
+connection master;
+create user rpl_do_grant@localhost;
+show grants for rpl_do_grant@localhost;
+--error 1141
+show grants for rpl_do_grant2@localhost;
+sync_slave_with_master;
+show grants for rpl_do_grant@localhost;
+--error 1141
+show grants for rpl_do_grant2@localhost;
+
+connection master;
+rename user rpl_do_grant@localhost to rpl_do_grant2@localhost;
+show grants for rpl_do_grant2@localhost;
+sync_slave_with_master;
+show grants for rpl_do_grant2@localhost;
+
+connection master;
+grant DELETE,INSERT on mysqltest1.* to rpl_do_grant2@localhost;
+show grants for rpl_do_grant2@localhost;
+sync_slave_with_master;
+show grants for rpl_do_grant2@localhost;
+
+connection master;
+revoke DELETE on mysqltest1.* from rpl_do_grant2@localhost;
+show grants for rpl_do_grant2@localhost;
+sync_slave_with_master;
+show grants for rpl_do_grant2@localhost;
+
+connection master;
+revoke all privileges, grant option from rpl_do_grant2@localhost;
+show grants for rpl_do_grant2@localhost;
+sync_slave_with_master;
+show grants for rpl_do_grant2@localhost;
+
+connection master;
+drop user rpl_do_grant2@localhost;
+--error 1141
+show grants for rpl_do_grant2@localhost;
+sync_slave_with_master;
+--error 1141
+show grants for rpl_do_grant2@localhost;
+
+#####################################################
+# Purpose
+# Test whether mysql.procs_priv get replicated
+# Related bugs:
+# BUG42217 mysql.procs_priv does not get replicated
+#####################################################
+connection master;
+call mtr.add_suppression("Slave: Operation DROP USER failed for 'create_rout_db'@'localhost' error.* 1396");
+sync_slave_with_master;
+connection master;
+
+--disable_warnings
+DROP DATABASE IF EXISTS bug42217_db;
+--enable_warnings
+CREATE DATABASE bug42217_db;
+
+GRANT CREATE ROUTINE ON bug42217_db.* TO 'create_rout_db'@'localhost'
+ IDENTIFIED BY 'create_rout_db' WITH GRANT OPTION;
+
+-- sync_slave_with_master
+-- connection master
+
+connect (create_rout_db_master, localhost, create_rout_db, create_rout_db, bug42217_db,$MASTER_MYPORT,);
+connect (create_rout_db_slave, localhost, create_rout_db, create_rout_db, bug42217_db, $SLAVE_MYPORT,);
+
+connection create_rout_db_master;
+
+
+USE bug42217_db;
+
+DELIMITER //;
+CREATE FUNCTION upgrade_del_func() RETURNS CHAR(30)
+BEGIN
+ RETURN "INSIDE upgrade_del_func()";
+END//
+
+DELIMITER ;//
+
+connection master;
+
+USE bug42217_db;
+--replace_column 8 #
+SELECT * FROM mysql.procs_priv;
+SELECT upgrade_del_func();
+
+sync_slave_with_master;
+--replace_column 8 #
+SELECT * FROM mysql.procs_priv;
+SHOW GRANTS FOR 'create_rout_db'@'localhost';
+
+USE bug42217_db;
+SHOW CREATE FUNCTION upgrade_del_func;
+SELECT upgrade_del_func();
+
+--echo "Check whether the definer user will be able to execute the replicated routine on slave"
+connection create_rout_db_slave;
+USE bug42217_db;
+SHOW CREATE FUNCTION upgrade_del_func;
+SELECT upgrade_del_func();
+
+connection slave;
+DELETE FROM mysql.procs_priv;
+FLUSH PRIVILEGES;
+USE bug42217_db;
+--echo "Can't execute the replicated routine on slave like before after procs privilege is deleted "
+--error 1370
+SELECT upgrade_del_func();
+
+--echo "Test the user who creates a function on master doesn't exist on slave."
+--echo "Hence SQL thread ACL_GLOBAL privilege jumps in and no mysql.procs_priv is inserted"
+DROP USER 'create_rout_db'@'localhost';
+
+connection create_rout_db_master;
+DELIMITER //;
+CREATE FUNCTION upgrade_alter_func() RETURNS CHAR(30)
+BEGIN
+ RETURN "INSIDE upgrade_alter_func()";
+END//
+DELIMITER ;//
+
+connection master;
+SELECT upgrade_alter_func();
+
+sync_slave_with_master;
+SHOW CREATE FUNCTION upgrade_alter_func;
+--echo "Should no privilege record for upgrade_alter_func in mysql.procs_priv"
+--replace_column 8 #
+SELECT * FROM mysql.procs_priv;
+--error 1449
+SELECT upgrade_alter_func();
+
+###### CLEAN UP SECTION ##############
+disconnect create_rout_db_master;
+disconnect create_rout_db_slave;
+connection master;
+USE bug42217_db;
+DROP FUNCTION upgrade_del_func;
+DROP FUNCTION upgrade_alter_func;
+DROP DATABASE bug42217_db;
+-- sync_slave_with_master
+-- connection master
+
+# user was already dropped in the slave before
+# so we should not replicate this statement.
+SET SQL_LOG_BIN= 0;
+DROP USER 'create_rout_db'@'localhost';
+SET SQL_LOG_BIN= 1;
+
+# finish entire clean up (remove binlogs)
+# so that we leave a pristine environment for the
+# following tests
+--let $rpl_only_running_threads= 1
+-- source include/rpl_reset.inc
+USE test;
+
+# BUG#49119: Master crashes when executing 'REVOKE ... ON
+# {PROCEDURE|FUNCTION} FROM ...'
+#
+# The tests are divided into two test cases:
+#
+# i) a test case that mimics the one in the bug report.
+#
+# - We show that, despite the fact, that a revoke command fails
+# when binlogging is active, the master will not hit an
+# assertion.
+#
+# ii) a test case that partially succeeds on the master will also
+# partially succeed on the slave.
+#
+# - The revoke statement that partially succeeds tries to revoke
+# an EXECUTE grant for two users, and only one of the user has
+# the specific grant. This will cause mysql to drop one of the
+# grants and report error for the statement. The slave should
+# also drop the grants that the master succeed and the SQL
+# thread should not stop on statement failure.
+
+-- echo ######## BUG#49119 #######
+-- echo ### i) test case from the 'how to repeat section'
+
+-- connection master
+
+CREATE TABLE t1(c1 INT);
+DELIMITER |;
+CREATE PROCEDURE p1() SELECT * FROM t1 |
+DELIMITER ;|
+-- error ER_NONEXISTING_PROC_GRANT
+REVOKE EXECUTE ON PROCEDURE p1 FROM 'root'@'localhost';
+
+-- sync_slave_with_master
+
+-- connection master
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+-- sync_slave_with_master
+
+-- echo ### ii) Test case in which REVOKE partially succeeds
+
+-- connection master
+-- source include/rpl_reset.inc
+-- connection master
+
+CREATE TABLE t1(c1 INT);
+DELIMITER |;
+CREATE PROCEDURE p1() SELECT * FROM t1 |
+DELIMITER ;|
+
+CREATE USER 'user49119'@'localhost';
+GRANT EXECUTE ON PROCEDURE p1 TO 'user49119'@'localhost';
+
+-- echo ##############################################################
+-- echo ### Showing grants for both users: root and user49119 (master)
+SHOW GRANTS FOR 'user49119'@'localhost';
+SHOW GRANTS FOR CURRENT_USER;
+-- echo ##############################################################
+
+-- sync_slave_with_master
+
+-- echo ##############################################################
+-- echo ### Showing grants for both users: root and user49119 (master)
+SHOW GRANTS FOR 'user49119'@'localhost';
+SHOW GRANTS FOR CURRENT_USER;
+-- echo ##############################################################
+
+-- connection master
+
+-- echo ## This statement will make the revoke fail because root has no
+-- echo ## execute grant. However, it will still revoke the grant for
+-- echo ## user49119.
+-- error ER_NONEXISTING_PROC_GRANT
+REVOKE EXECUTE ON PROCEDURE p1 FROM 'user49119'@'localhost', 'root'@'localhost';
+
+-- echo ##############################################################
+-- echo ### Showing grants for both users: root and user49119 (master)
+-- echo ### after revoke statement failure
+SHOW GRANTS FOR 'user49119'@'localhost';
+SHOW GRANTS FOR CURRENT_USER;
+-- echo ##############################################################
+
+-- sync_slave_with_master
+
+-- echo #############################################################
+-- echo ### Showing grants for both users: root and user49119 (slave)
+-- echo ### after revoke statement failure (should match
+SHOW GRANTS FOR 'user49119'@'localhost';
+SHOW GRANTS FOR CURRENT_USER;
+-- echo ##############################################################
+
+-- connection master
+DROP TABLE t1;
+DROP PROCEDURE p1;
+DROP USER 'user49119'@'localhost';
+
+-- sync_slave_with_master
+
+#
+# Bug #51987 revoke privileges logs wrong error code
+#
+
+-- source include/rpl_reset.inc
+-- connection master
+
+grant all on *.* to foo@"1.2.3.4";
+-- error ER_REVOKE_GRANTS
+revoke all privileges, grant option from "foo";
+
+## assertion: revoke is logged
+-- source include/show_binlog_events.inc
+
+-- sync_slave_with_master
+
+## assertion: slave replicates revoke and does not fail because master
+## logged revoke with correct expected error code
+--source include/check_slave_no_error.inc
+
+-- connection master
+DROP USER foo@"1.2.3.4";
+-- sync_slave_with_master
+
+--echo
+--echo # Bug#27606 GRANT statement should be replicated with DEFINER information
+--source include/rpl_reset.inc
+--connection master
+GRANT SELECT, INSERT ON mysql.user TO user_bug27606@localhost;
+
+SELECT Grantor FROM mysql.tables_priv WHERE User='user_bug27606';
+sync_slave_with_master;
+SELECT Grantor FROM mysql.tables_priv WHERE User='user_bug27606';
+
+--connection master
+REVOKE SELECT ON mysql.user FROM user_bug27606@localhost;
+SELECT Grantor FROM mysql.tables_priv WHERE User='user_bug27606';
+sync_slave_with_master;
+SELECT Grantor FROM mysql.tables_priv WHERE User='user_bug27606';
+
+--connection master
+DROP USER user_bug27606@localhost;
+select priv into @root_priv from mysql.global_priv where user='root' and host='127.0.0.1';
+update mysql.global_priv set priv=@root_priv where user='root' and host='localhost';
+
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_domain_id_filter.test b/mysql-test/suite/rpl/t/rpl_domain_id_filter.test
new file mode 100644
index 00000000..2b8ac17c
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_domain_id_filter.test
@@ -0,0 +1,400 @@
+--source include/have_innodb.inc
+--source include/master-slave.inc
+
+#
+# Test for DO_DOMAIN_IDS=(M1, M2, ..) and IGNORE_DOMAIN_IDS=(N1, N2, ..)
+#
+
+connection slave;
+call mtr.add_suppression("Both DO_DOMAIN_IDS & IGNORE_DOMAIN_IDS lists can't be non-empty at the same time");
+call mtr.add_suppression("DO_DOMAIN_IDS or IGNORE_DOMAIN_IDS lists can't be non-empty in non-GTID mode.*");
+
+connection master;
+SET @@session.gtid_domain_id= 1;
+SELECT @@session.gtid_domain_id;
+CREATE TABLE t1(i INT) ENGINE=INNODB;
+INSERT INTO t1 VALUES(1);
+SELECT * FROM t1;
+--source include/save_master_gtid.inc
+
+connection slave;
+--source include/sync_with_master_gtid.inc
+##### Case 0 : When both DO_DOMAIN_IDS and IGNORE_DOMAIN_IDS are empty.
+SELECT * FROM t1;
+
+##### Case 1: When DO_DOMAIN_IDS is non-empty.
+--source include/stop_slave.inc
+let $do_domain_ids_before= query_get_value(SHOW SLAVE STATUS, Replicate_Do_Domain_Ids, 1);
+let $ignore_domain_ids_before= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Domain_Ids, 1);
+--echo DO_DOMAIN_IDS (BEFORE) : $do_domain_ids_before
+--echo IGNORE_DOMAIN_IDS (BEFORE) : $ignore_domain_ids_before
+
+# Replicate events belonging to "domain_id 1".
+CHANGE MASTER TO DO_DOMAIN_IDS=(1), MASTER_USE_GTID=slave_pos;
+--source include/start_slave.inc
+
+let $do_domain_ids_after= query_get_value(SHOW SLAVE STATUS, Replicate_Do_Domain_Ids, 1);
+let $ignore_domain_ids_after= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Domain_Ids, 1);
+--echo DO_DOMAIN_IDS (AFTER) : $do_domain_ids_after
+--echo IGNORE_DOMAIN_IDS (AFTER) : $ignore_domain_ids_after
+
+connection master;
+# Lets change the session domain_id to 2(not in DO_DOMAIN_IDS).
+SET @@session.gtid_domain_id= 2;
+# Should get filtered out on slave.
+INSERT INTO t1 VALUES(2);
+# Change it back to 1 (in DO_DOMAIN_IDS).
+SET @@session.gtid_domain_id= 1;
+# Should get applied on slave.
+INSERT INTO t1 VALUES(3);
+
+SELECT * FROM t1;
+--source include/save_master_gtid.inc
+
+connection slave;
+--source include/sync_with_master_gtid.inc
+SELECT * FROM t1;
+
+##### Case 2: When IGNORE_DOMAIN_IDS is non-empty.
+--source include/stop_slave.inc
+let $do_domain_ids_before= query_get_value(SHOW SLAVE STATUS, Replicate_Do_Domain_Ids, 1);
+let $ignore_domain_ids_before= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Domain_Ids, 1);
+--echo DO_DOMAIN_IDS (BEFORE) : $do_domain_ids_before
+--echo IGNORE_DOMAIN_IDS (BEFORE) : $ignore_domain_ids_before
+
+# Ignore events belonging to "domain_id 1".
+CHANGE MASTER TO DO_DOMAIN_IDS=(), IGNORE_DOMAIN_IDS=(1), MASTER_USE_GTID=slave_pos;
+--source include/start_slave.inc
+
+let $do_domain_ids_after= query_get_value(SHOW SLAVE STATUS, Replicate_Do_Domain_Ids, 1);
+let $ignore_domain_ids_after= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Domain_Ids, 1);
+--echo DO_DOMAIN_IDS (AFTER) : $do_domain_ids_after
+--echo IGNORE_DOMAIN_IDS (AFTER) : $ignore_domain_ids_after
+
+connection master;
+# @@session.gtid_domain_id = 1 (in IGNORE_DOMAIN_IDS)
+SELECT @@session.gtid_domain_id;
+# Should get filtered out on slave.
+INSERT INTO t1 VALUES(4);
+# Change it to 2 (not in IGNORE_DOMAIN_IDS).
+SET @@session.gtid_domain_id= 2;
+# Should get applied on slave.
+INSERT INTO t1 VALUES(5);
+
+SELECT * FROM t1;
+--source include/save_master_gtid.inc
+
+connection slave;
+--source include/sync_with_master_gtid.inc
+SELECT * FROM t1;
+
+##### Case 3: When both DO_DOMAIN_IDS and IGNORE_DOMAIN_IDS are non-empty
+
+--source include/stop_slave.inc
+let $do_domain_ids_before= query_get_value(SHOW SLAVE STATUS, Replicate_Do_Domain_Ids, 1);
+let $ignore_domain_ids_before= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Domain_Ids, 1);
+--echo DO_DOMAIN_IDS (BEFORE) : $do_domain_ids_before
+--echo IGNORE_DOMAIN_IDS (BEFORE) : $ignore_domain_ids_before
+
+--error ER_MASTER_INFO
+CHANGE MASTER TO DO_DOMAIN_IDS=(1), IGNORE_DOMAIN_IDS=(2), MASTER_USE_GTID=slave_pos;
+
+let $do_domain_ids_after= query_get_value(SHOW SLAVE STATUS, Replicate_Do_Domain_Ids, 1);
+let $ignore_domain_ids_after= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Domain_Ids, 1);
+--echo DO_DOMAIN_IDS (AFTER) : $do_domain_ids_after
+--echo IGNORE_DOMAIN_IDS (AFTER) : $ignore_domain_ids_after
+
+##### Case 4: Multiple domain ids.
+
+--source include/stop_slave.inc
+let $do_domain_ids_before= query_get_value(SHOW SLAVE STATUS, Replicate_Do_Domain_Ids, 1);
+let $ignore_domain_ids_before= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Domain_Ids, 1);
+--echo DO_DOMAIN_IDS (BEFORE) : $do_domain_ids_before
+--echo IGNORE_DOMAIN_IDS (BEFORE) : $ignore_domain_ids_before
+
+# Replicate events belonging to "domain_id 1".
+CHANGE MASTER TO DO_DOMAIN_IDS=(4,4,5,1,7,7,7,1,1,2,6,8,1,4,5,5,9,3), IGNORE_DOMAIN_IDS=(), MASTER_USE_GTID=slave_pos;
+--source include/start_slave.inc
+
+let $do_domain_ids_after= query_get_value(SHOW SLAVE STATUS, Replicate_Do_Domain_Ids, 1);
+let $ignore_domain_ids_after= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Domain_Ids, 1);
+--echo DO_DOMAIN_IDS (AFTER) : $do_domain_ids_after
+--echo IGNORE_DOMAIN_IDS (AFTER) : $ignore_domain_ids_after
+
+connection master;
+# @@session.gtid_domain_id = 1 (in DO_DOMAIN_IDS)
+SELECT @@session.gtid_domain_id;
+# Should get applied on slave.
+INSERT INTO t1 VALUES(8);
+# Change it to 7 (in DO_DOMAIN_IDS).
+SET @@session.gtid_domain_id= 7;
+# Should get applied on slave.
+INSERT INTO t1 VALUES(9);
+# Change it to 10 (no in DO_DOMAIN_IDS).
+SET @@session.gtid_domain_id= 10;
+# Following should get filtered out on slave.
+INSERT INTO t1 VALUES(10);
+INSERT INTO t1 VALUES(11);
+START TRANSACTION;
+INSERT INTO t1 VALUES(12);
+INSERT INTO t1 VALUES(13);
+COMMIT;
+INSERT INTO t1 VALUES(14);
+INSERT INTO t1 VALUES(15);
+--source include/save_master_gtid.inc
+
+connection slave;
+--source include/sync_with_master_gtid.inc
+SELECT * FROM t1;
+
+##### Case 5: Seconds_Behind_Master
+connection slave;
+--echo # Seconds_Behind_Master should be zero here because the slave is fully caught up and idle.
+--let $status_items= Seconds_Behind_Master
+--source include/show_slave_status.inc
+
+##### Case 6: Stop slave before a transaction (involving MyISAM and InnoDB
+# table) being filtered commits.
+
+connection slave;
+--source include/stop_slave.inc
+let $do_domain_ids_before= query_get_value(SHOW SLAVE STATUS, Replicate_Do_Domain_Ids, 1);
+let $ignore_domain_ids_before= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Domain_Ids, 1);
+--echo DO_DOMAIN_IDS (BEFORE) : $do_domain_ids_before
+--echo IGNORE_DOMAIN_IDS (BEFORE) : $ignore_domain_ids_before
+
+# IGNORE_DOMAIN_IDS=(1)
+CHANGE MASTER TO DO_DOMAIN_IDS=(), IGNORE_DOMAIN_IDS=(1), MASTER_USE_GTID=slave_pos;
+--source include/start_slave.inc
+
+let $do_domain_ids_after= query_get_value(SHOW SLAVE STATUS, Replicate_Do_Domain_Ids, 1);
+let $ignore_domain_ids_after= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Domain_Ids, 1);
+--echo DO_DOMAIN_IDS (AFTER) : $do_domain_ids_after
+--echo IGNORE_DOMAIN_IDS (AFTER) : $ignore_domain_ids_after
+
+connection master;
+# following statements should not get filtered.
+SET @@session.gtid_domain_id=2;
+CREATE TABLE t2(i int) ENGINE=MYISAM;
+CREATE TABLE t3(i int) ENGINE=INNODB;
+
+SET @@session.gtid_domain_id=1;
+BEGIN;
+INSERT INTO t2 VALUES(1);
+INSERT INTO t3 VALUES(1);
+
+# Now switch to slave to stop replication.
+connection slave;
+--source include/stop_slave.inc
+--source include/wait_for_slave_to_stop.inc
+
+# Back to master to finish the transaction.
+connection master;
+INSERT INTO t2 VALUES(2);
+INSERT INTO t3 VALUES(2);
+COMMIT;
+--source include/save_master_gtid.inc
+
+# On slave to start replication.
+connection slave;
+--source include/start_slave.inc
+--source include/sync_with_master_gtid.inc
+
+SELECT * FROM t2;
+SELECT * FROM t3;
+
+##### Case 7: Stop slave before a transaction (involving MyISAM and InnoDB
+# table) being filtered commits and start it back with filtering
+# disabled.
+
+connection master;
+SET @@session.gtid_domain_id=1;
+BEGIN;
+INSERT INTO t2 VALUES(3);
+INSERT INTO t3 VALUES(3);
+--source include/save_master_gtid.inc
+
+connection slave;
+--source include/sync_with_master_gtid.inc
+--source include/stop_slave.inc
+let $do_domain_ids_before= query_get_value(SHOW SLAVE STATUS, Replicate_Do_Domain_Ids, 1);
+let $ignore_domain_ids_before= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Domain_Ids, 1);
+--echo DO_DOMAIN_IDS (BEFORE) : $do_domain_ids_before
+--echo IGNORE_DOMAIN_IDS (BEFORE) : $ignore_domain_ids_before
+
+# Clear IGNORE_DOMAIN_IDS
+CHANGE MASTER TO DO_DOMAIN_IDS=(), IGNORE_DOMAIN_IDS=(), MASTER_USE_GTID=slave_pos;
+--source include/start_slave.inc
+
+let $do_domain_ids_after= query_get_value(SHOW SLAVE STATUS, Replicate_Do_Domain_Ids, 1);
+let $ignore_domain_ids_after= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Domain_Ids, 1);
+--echo DO_DOMAIN_IDS (AFTER) : $do_domain_ids_after
+--echo IGNORE_DOMAIN_IDS (AFTER) : $ignore_domain_ids_after
+
+connection master;
+INSERT INTO t2 VALUES(4);
+INSERT INTO t3 VALUES(4);
+COMMIT;
+--source include/save_master_gtid.inc
+
+connection slave;
+--source include/sync_with_master_gtid.inc
+SELECT * FROM t2;
+SELECT * FROM t3;
+
+##### Case 8: Stop slave into the middle of a transaction and start it back
+# with filtering enabled.
+
+connection master;
+SET @@session.gtid_domain_id=1;
+BEGIN;
+INSERT INTO t2 VALUES(5);
+INSERT INTO t3 VALUES(5);
+--source include/save_master_gtid.inc
+
+connection slave;
+--source include/sync_with_master_gtid.inc
+--source include/stop_slave.inc
+let $do_domain_ids_before= query_get_value(SHOW SLAVE STATUS, Replicate_Do_Domain_Ids, 1);
+let $ignore_domain_ids_before= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Domain_Ids, 1);
+--echo DO_DOMAIN_IDS (BEFORE) : $do_domain_ids_before
+--echo IGNORE_DOMAIN_IDS (BEFORE) : $ignore_domain_ids_before
+
+# IGNORE_DOMAIN_IDS(1)
+CHANGE MASTER TO DO_DOMAIN_IDS=(), IGNORE_DOMAIN_IDS=(1), MASTER_USE_GTID=slave_pos;
+--source include/start_slave.inc
+
+let $do_domain_ids_after= query_get_value(SHOW SLAVE STATUS, Replicate_Do_Domain_Ids, 1);
+let $ignore_domain_ids_after= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Domain_Ids, 1);
+--echo DO_DOMAIN_IDS (AFTER) : $do_domain_ids_after
+--echo IGNORE_DOMAIN_IDS (AFTER) : $ignore_domain_ids_after
+
+connection master;
+INSERT INTO t2 VALUES(6);
+INSERT INTO t3 VALUES(6);
+COMMIT;
+--source include/save_master_gtid.inc
+
+connection slave;
+--source include/sync_with_master_gtid.inc
+SELECT * FROM t2;
+SELECT * FROM t3;
+
+##### Case 9: Initially filter out events belonging to domain_id=2 and then
+# remove the rule to check if event are not being filtered out.
+
+connection slave;
+--source include/stop_slave.inc
+let $do_domain_ids_before= query_get_value(SHOW SLAVE STATUS, Replicate_Do_Domain_Ids, 1);
+let $ignore_domain_ids_before= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Domain_Ids, 1);
+--echo DO_DOMAIN_IDS (BEFORE) : $do_domain_ids_before
+--echo IGNORE_DOMAIN_IDS (BEFORE) : $ignore_domain_ids_before
+
+# IGNORE_DOMAIN_IDS(2)
+CHANGE MASTER TO IGNORE_DOMAIN_IDS=(2), MASTER_USE_GTID=slave_pos;
+--source include/start_slave.inc
+
+let $do_domain_ids_after= query_get_value(SHOW SLAVE STATUS, Replicate_Do_Domain_Ids, 1);
+let $ignore_domain_ids_after= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Domain_Ids, 1);
+--echo DO_DOMAIN_IDS (AFTER) : $do_domain_ids_after
+--echo IGNORE_DOMAIN_IDS (AFTER) : $ignore_domain_ids_after
+
+connection master;
+SET @@session.gtid_domain_id=2;
+BEGIN;
+INSERT INTO t2 VALUES(7);
+INSERT INTO t3 VALUES(7);
+COMMIT;
+--source include/save_master_gtid.inc
+
+# Clear the filter
+connection slave;
+--source include/sync_with_master_gtid.inc
+--source include/stop_slave.inc
+let $do_domain_ids_before= query_get_value(SHOW SLAVE STATUS, Replicate_Do_Domain_Ids, 1);
+let $ignore_domain_ids_before= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Domain_Ids, 1);
+--echo DO_DOMAIN_IDS (BEFORE) : $do_domain_ids_before
+--echo IGNORE_DOMAIN_IDS (BEFORE) : $ignore_domain_ids_before
+
+# IGNORE_DOMAIN_IDS()
+CHANGE MASTER TO IGNORE_DOMAIN_IDS=(), MASTER_USE_GTID=slave_pos;
+--source include/start_slave.inc
+
+let $do_domain_ids_after= query_get_value(SHOW SLAVE STATUS, Replicate_Do_Domain_Ids, 1);
+let $ignore_domain_ids_after= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Domain_Ids, 1);
+--echo DO_DOMAIN_IDS (AFTER) : $do_domain_ids_after
+--echo IGNORE_DOMAIN_IDS (AFTER) : $ignore_domain_ids_after
+
+connection master;
+SET @@session.gtid_domain_id=2;
+BEGIN;
+INSERT INTO t2 VALUES(8);
+INSERT INTO t3 VALUES(8);
+COMMIT;
+--source include/save_master_gtid.inc
+
+connection slave;
+--source include/sync_with_master_gtid.inc
+SELECT * FROM t2;
+SELECT * FROM t3;
+
+##### Case 10: Test CHANGE MASTER with various "incompatible" combinations.
+connection slave;
+--source include/stop_slave.inc
+
+# 10a: Both DO_DOMAIN_IDS & IGNORE_DOMAIN_IDS can't be non-empty at the same
+# time.
+
+let $do_domain_ids_before= query_get_value(SHOW SLAVE STATUS, Replicate_Do_Domain_Ids, 1);
+let $ignore_domain_ids_before= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Domain_Ids, 1);
+--echo DO_DOMAIN_IDS (BEFORE) : $do_domain_ids_before
+--echo IGNORE_DOMAIN_IDS (BEFORE) : $ignore_domain_ids_before
+
+--error ER_MASTER_INFO
+CHANGE MASTER TO DO_DOMAIN_IDS=(1), IGNORE_DOMAIN_IDS=(1), MASTER_USE_GTID=SLAVE_POS;
+CHANGE MASTER TO DO_DOMAIN_IDS=(1), MASTER_USE_GTID=SLAVE_POS;
+--error ER_MASTER_INFO
+CHANGE MASTER TO IGNORE_DOMAIN_IDS=(1), MASTER_USE_GTID=SLAVE_POS;
+CHANGE MASTER TO DO_DOMAIN_IDS=(), IGNORE_DOMAIN_IDS=(1), MASTER_USE_GTID=SLAVE_POS;
+--error ER_MASTER_INFO
+CHANGE MASTER TO DO_DOMAIN_IDS=(1), MASTER_USE_GTID=SLAVE_POS;
+
+# 10b: Neither DO_DOMAIN_IDS nor IGNORE_DOMAIN_IDS can be set when
+# MASTER_USE_GTID=NO
+
+let $do_domain_ids_before= query_get_value(SHOW SLAVE STATUS, Replicate_Do_Domain_Ids, 1);
+let $ignore_domain_ids_before= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Domain_Ids, 1);
+--echo DO_DOMAIN_IDS (BEFORE) : $do_domain_ids_before
+--echo IGNORE_DOMAIN_IDS (BEFORE) : $ignore_domain_ids_before
+
+# MASTER_USE_GTID can't be set to NO when either of IGNORE_DOMAIN_IDS or
+# DO_DOMAIN_IDS is non-empty.
+--error ER_MASTER_INFO
+CHANGE MASTER TO MASTER_USE_GTID=NO;
+CHANGE MASTER TO DO_DOMAIN_IDS=(), IGNORE_DOMAIN_IDS=(), MASTER_USE_GTID=NO;
+--error ER_MASTER_INFO
+CHANGE MASTER TO DO_DOMAIN_IDS=(1), MASTER_USE_GTID=NO;
+--error ER_MASTER_INFO
+CHANGE MASTER TO IGNORE_DOMAIN_IDS=(1), MASTER_USE_GTID=NO;
+
+let $do_domain_ids_after= query_get_value(SHOW SLAVE STATUS, Replicate_Do_Domain_Ids, 1);
+let $ignore_domain_ids_after= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Domain_Ids, 1);
+--echo DO_DOMAIN_IDS (AFTER) : $do_domain_ids_after
+--echo IGNORE_DOMAIN_IDS (AFTER) : $ignore_domain_ids_after
+
+CHANGE MASTER TO IGNORE_DOMAIN_IDS=(1), DO_DOMAIN_IDS=(), MASTER_USE_GTID=SLAVE_POS;
+--source include/start_slave.inc
+
+# Cleanup
+connection master;
+SET @@session.gtid_domain_id=2;
+DROP TABLE t1, t2, t3;
+--source include/save_master_gtid.inc
+
+connection slave;
+--source include/sync_with_master_gtid.inc
+--source include/stop_slave.inc
+CHANGE MASTER TO DO_DOMAIN_IDS=(), IGNORE_DOMAIN_IDS=();
+--source include/start_slave.inc
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_domain_id_filter_io_crash.test b/mysql-test/suite/rpl/t/rpl_domain_id_filter_io_crash.test
new file mode 100644
index 00000000..a949da0c
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_domain_id_filter_io_crash.test
@@ -0,0 +1,384 @@
+--source include/have_debug.inc
+--source include/have_innodb.inc
+--source include/master-slave.inc
+
+connection master;
+SET @@session.gtid_domain_id= 1;
+SELECT @@session.gtid_domain_id;
+CREATE TABLE t1(i INT) ENGINE=INNODB;
+INSERT INTO t1 VALUES(1);
+SELECT * FROM t1;
+sync_slave_with_master;
+
+connection slave;
+
+call mtr.add_suppression("Slave I/O: Relay log write failure: could not queue event from master.*");
+
+--echo # Case 0 : Start slave with IGNORE_DOMAIN_IDS=(), then restart
+--echo # replication with IGNORE_DOMAIN_IDS=() after IO thread is
+--echo # killed due to DBUG_EXECUTE_IF("+d,kill_slave_io_before_commit").
+
+SELECT * FROM t1;
+
+--source include/stop_slave.inc
+let $do_domain_ids_before= query_get_value(SHOW SLAVE STATUS, Replicate_Do_Domain_Ids, 1);
+let $ignore_domain_ids_before= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Domain_Ids, 1);
+--echo DO_DOMAIN_IDS (BEFORE) : $do_domain_ids_before
+--echo IGNORE_DOMAIN_IDS (BEFORE) : $ignore_domain_ids_before
+
+CHANGE MASTER TO IGNORE_DOMAIN_IDS=(), MASTER_USE_GTID=slave_pos;
+--source include/start_slave.inc
+sync_with_master;
+
+let $do_domain_ids_after= query_get_value(SHOW SLAVE STATUS, Replicate_Do_Domain_Ids, 1);
+let $ignore_domain_ids_after= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Domain_Ids, 1);
+--echo DO_DOMAIN_IDS (AFTER) : $do_domain_ids_after
+--echo IGNORE_DOMAIN_IDS (AFTER) : $ignore_domain_ids_after
+
+SET @saved_dbug = @@GLOBAL.debug_dbug;
+SET @@global.debug_dbug="d,kill_slave_io_before_commit";
+
+connection master;
+
+START TRANSACTION;
+INSERT INTO t1 VALUES(2);
+INSERT INTO t1 VALUES(3);
+COMMIT;
+save_master_pos;
+SELECT * FROM t1;
+
+connection slave;
+--let $slave_io_errno= 1595
+--source include/wait_for_slave_io_error.inc
+SELECT * FROM t1;
+SET @@global.debug_dbug=@saved_dbug;
+
+START SLAVE io_thread;
+--source include/wait_for_slave_io_to_start.inc
+sync_with_master;
+SELECT * FROM t1;
+
+--echo # Case 1 : Start slave with IGNORE_DOMAIN_IDS=(1), then restart
+--echo # replication with IGNORE_DOMAIN_IDS=(1) after IO thread is
+--echo # killed due to DBUG_EXECUTE_IF("+d,kill_slave_io_before_commit").
+
+--source include/stop_slave.inc
+let $do_domain_ids_before= query_get_value(SHOW SLAVE STATUS, Replicate_Do_Domain_Ids, 1);
+let $ignore_domain_ids_before= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Domain_Ids, 1);
+--echo DO_DOMAIN_IDS (BEFORE) : $do_domain_ids_before
+--echo IGNORE_DOMAIN_IDS (BEFORE) : $ignore_domain_ids_before
+
+CHANGE MASTER TO IGNORE_DOMAIN_IDS=(1), MASTER_USE_GTID=slave_pos;
+--source include/start_slave.inc
+sync_with_master;
+
+let $do_domain_ids_after= query_get_value(SHOW SLAVE STATUS, Replicate_Do_Domain_Ids, 1);
+let $ignore_domain_ids_after= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Domain_Ids, 1);
+--echo DO_DOMAIN_IDS (AFTER) : $do_domain_ids_after
+--echo IGNORE_DOMAIN_IDS (AFTER) : $ignore_domain_ids_after
+
+SET @@global.debug_dbug="d,kill_slave_io_before_commit";
+
+connection master;
+
+START TRANSACTION;
+INSERT INTO t1 VALUES(4);
+INSERT INTO t1 VALUES(5);
+COMMIT;
+
+save_master_pos;
+SELECT * FROM t1;
+
+connection slave;
+--let $slave_io_errno= 1595
+--source include/wait_for_slave_io_error.inc
+SELECT * FROM t1;
+SET @@global.debug_dbug=@saved_dbug;
+
+START SLAVE io_thread;
+--source include/wait_for_slave_io_to_start.inc
+sync_with_master;
+SELECT * FROM t1;
+
+--echo # Case 2 : Start slave with IGNORE_DOMAIN_IDS=(), then restart
+--echo # replication with IGNORE_DOMAIN_IDS=(1) after IO thread is
+--echo # killed due to DBUG_EXECUTE_IF("+d,kill_slave_io_before_commit").
+
+--source include/stop_slave.inc
+let $do_domain_ids_before= query_get_value(SHOW SLAVE STATUS, Replicate_Do_Domain_Ids, 1);
+let $ignore_domain_ids_before= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Domain_Ids, 1);
+--echo DO_DOMAIN_IDS (BEFORE) : $do_domain_ids_before
+--echo IGNORE_DOMAIN_IDS (BEFORE) : $ignore_domain_ids_before
+
+CHANGE MASTER TO IGNORE_DOMAIN_IDS=(), MASTER_USE_GTID=slave_pos;
+--source include/start_slave.inc
+sync_with_master;
+
+let $do_domain_ids_after= query_get_value(SHOW SLAVE STATUS, Replicate_Do_Domain_Ids, 1);
+let $ignore_domain_ids_after= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Domain_Ids, 1);
+--echo DO_DOMAIN_IDS (AFTER) : $do_domain_ids_after
+--echo IGNORE_DOMAIN_IDS (AFTER) : $ignore_domain_ids_after
+
+SET @@global.debug_dbug="d,kill_slave_io_before_commit";
+
+connection master;
+
+START TRANSACTION;
+INSERT INTO t1 VALUES(6);
+INSERT INTO t1 VALUES(7);
+COMMIT; # IO thread gets killed here.
+
+START TRANSACTION;
+INSERT INTO t1 VALUES(8);
+INSERT INTO t1 VALUES(9);
+COMMIT;
+
+SET @@session.gtid_domain_id= 2;
+
+START TRANSACTION;
+INSERT INTO t1 VALUES(10);
+INSERT INTO t1 VALUES(11);
+COMMIT;
+
+save_master_pos;
+SELECT * FROM t1;
+
+connection slave;
+--let $slave_io_errno= 1595
+--source include/wait_for_slave_io_error.inc
+SELECT * FROM t1;
+
+SET @@global.debug_dbug=@saved_dbug;
+
+--source include/stop_slave.inc
+let $do_domain_ids_before= query_get_value(SHOW SLAVE STATUS, Replicate_Do_Domain_Ids, 1);
+let $ignore_domain_ids_before= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Domain_Ids, 1);
+--echo DO_DOMAIN_IDS (BEFORE) : $do_domain_ids_before
+--echo IGNORE_DOMAIN_IDS (BEFORE) : $ignore_domain_ids_before
+
+CHANGE MASTER TO IGNORE_DOMAIN_IDS=(1), MASTER_USE_GTID=slave_pos;
+--source include/start_slave.inc
+sync_with_master;
+
+let $do_domain_ids_after= query_get_value(SHOW SLAVE STATUS, Replicate_Do_Domain_Ids, 1);
+let $ignore_domain_ids_after= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Domain_Ids, 1);
+--echo DO_DOMAIN_IDS (AFTER) : $do_domain_ids_after
+--echo IGNORE_DOMAIN_IDS (AFTER) : $ignore_domain_ids_after
+
+SELECT * FROM t1;
+
+--echo # Case 3 : Start slave with IGNORE_DOMAIN_IDS=(1), then restart
+--echo # replication with IGNORE_DOMAIN_IDS=() after IO thread is
+--echo # killed due to DBUG_EXECUTE_IF("+d,kill_slave_io_before_commit").
+
+--source include/stop_slave.inc
+let $do_domain_ids_before= query_get_value(SHOW SLAVE STATUS, Replicate_Do_Domain_Ids, 1);
+let $ignore_domain_ids_before= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Domain_Ids, 1);
+--echo DO_DOMAIN_IDS (BEFORE) : $do_domain_ids_before
+--echo IGNORE_DOMAIN_IDS (BEFORE) : $ignore_domain_ids_before
+
+CHANGE MASTER TO IGNORE_DOMAIN_IDS=(1), MASTER_USE_GTID=slave_pos;
+--source include/start_slave.inc
+sync_with_master;
+
+let $do_domain_ids_after= query_get_value(SHOW SLAVE STATUS, Replicate_Do_Domain_Ids, 1);
+let $ignore_domain_ids_after= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Domain_Ids, 1);
+--echo DO_DOMAIN_IDS (AFTER) : $do_domain_ids_after
+--echo IGNORE_DOMAIN_IDS (AFTER) : $ignore_domain_ids_after
+
+SET @@global.debug_dbug="d,kill_slave_io_before_commit";
+
+connection master;
+
+SET @@session.gtid_domain_id= 1;
+
+START TRANSACTION;
+INSERT INTO t1 VALUES(12);
+INSERT INTO t1 VALUES(13);
+COMMIT; # IO thread gets killed here.
+
+START TRANSACTION;
+INSERT INTO t1 VALUES(14);
+INSERT INTO t1 VALUES(15);
+COMMIT;
+
+SET @@session.gtid_domain_id= 2;
+START TRANSACTION;
+INSERT INTO t1 VALUES(16);
+INSERT INTO t1 VALUES(17);
+COMMIT;
+
+save_master_pos;
+SELECT * FROM t1;
+
+connection slave;
+--let $slave_io_errno= 1595
+--source include/wait_for_slave_io_error.inc
+SELECT * FROM t1;
+
+SET @@global.debug_dbug=@saved_dbug;
+
+--source include/stop_slave.inc
+let $do_domain_ids_before= query_get_value(SHOW SLAVE STATUS, Replicate_Do_Domain_Ids, 1);
+let $ignore_domain_ids_before= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Domain_Ids, 1);
+--echo DO_DOMAIN_IDS (BEFORE) : $do_domain_ids_before
+--echo IGNORE_DOMAIN_IDS (BEFORE) : $ignore_domain_ids_before
+
+CHANGE MASTER TO IGNORE_DOMAIN_IDS=(), MASTER_USE_GTID=slave_pos;
+--source include/start_slave.inc
+sync_with_master;
+
+let $do_domain_ids_after= query_get_value(SHOW SLAVE STATUS, Replicate_Do_Domain_Ids, 1);
+let $ignore_domain_ids_after= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Domain_Ids, 1);
+--echo DO_DOMAIN_IDS (AFTER) : $do_domain_ids_after
+--echo IGNORE_DOMAIN_IDS (AFTER) : $ignore_domain_ids_after
+
+SELECT * FROM t1;
+
+--echo # Case 4 : Start slave with IGNORE_DOMAIN_IDS=(1), then restart
+--echo # replication with IGNORE_DOMAIN_IDS=() after IO thread is
+--echo # killed due to DBUG_EXECUTE_IF("+d,kill_slave_io_after_2_events").
+
+--source include/stop_slave.inc
+let $do_domain_ids_before= query_get_value(SHOW SLAVE STATUS, Replicate_Do_Domain_Ids, 1);
+let $ignore_domain_ids_before= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Domain_Ids, 1);
+--echo DO_DOMAIN_IDS (BEFORE) : $do_domain_ids_before
+--echo IGNORE_DOMAIN_IDS (BEFORE) : $ignore_domain_ids_before
+
+CHANGE MASTER TO IGNORE_DOMAIN_IDS=(1), MASTER_USE_GTID=slave_pos;
+--source include/start_slave.inc
+sync_with_master;
+
+let $do_domain_ids_after= query_get_value(SHOW SLAVE STATUS, Replicate_Do_Domain_Ids, 1);
+let $ignore_domain_ids_after= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Domain_Ids, 1);
+--echo DO_DOMAIN_IDS (AFTER) : $do_domain_ids_after
+--echo IGNORE_DOMAIN_IDS (AFTER) : $ignore_domain_ids_after
+
+SET @@global.debug_dbug="d,kill_slave_io_after_2_events";
+
+connection master;
+
+SET @@session.gtid_domain_id= 1;
+
+START TRANSACTION;
+INSERT INTO t1 VALUES(18);
+INSERT INTO t1 VALUES(19); # IO thread gets killed here.
+COMMIT;
+
+START TRANSACTION;
+INSERT INTO t1 VALUES(20);
+INSERT INTO t1 VALUES(21);
+COMMIT;
+
+SET @@session.gtid_domain_id= 2;
+START TRANSACTION;
+INSERT INTO t1 VALUES(22);
+INSERT INTO t1 VALUES(23);
+COMMIT;
+
+save_master_pos;
+SELECT * FROM t1;
+
+connection slave;
+--let $slave_io_errno= 1595
+--source include/wait_for_slave_io_error.inc
+SELECT * FROM t1;
+
+SET @@global.debug_dbug=@saved_dbug;
+
+--source include/stop_slave.inc
+let $do_domain_ids_before= query_get_value(SHOW SLAVE STATUS, Replicate_Do_Domain_Ids, 1);
+let $ignore_domain_ids_before= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Domain_Ids, 1);
+--echo DO_DOMAIN_IDS (BEFORE) : $do_domain_ids_before
+--echo IGNORE_DOMAIN_IDS (BEFORE) : $ignore_domain_ids_before
+
+CHANGE MASTER TO IGNORE_DOMAIN_IDS=(), MASTER_USE_GTID=slave_pos;
+--source include/start_slave.inc
+sync_with_master;
+
+let $do_domain_ids_after= query_get_value(SHOW SLAVE STATUS, Replicate_Do_Domain_Ids, 1);
+let $ignore_domain_ids_after= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Domain_Ids, 1);
+--echo DO_DOMAIN_IDS (AFTER) : $do_domain_ids_after
+--echo IGNORE_DOMAIN_IDS (AFTER) : $ignore_domain_ids_after
+
+SELECT * FROM t1;
+
+--echo # Case 5 : Start slave with IGNORE_DOMAIN_IDS=(), then restart
+--echo # replication with IGNORE_DOMAIN_IDS=(1) after IO thread is
+--echo # killed due to DBUG_EXECUTE_IF("+d,kill_slave_io_after_2_events").
+
+--source include/stop_slave.inc
+let $do_domain_ids_before= query_get_value(SHOW SLAVE STATUS, Replicate_Do_Domain_Ids, 1);
+let $ignore_domain_ids_before= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Domain_Ids, 1);
+--echo DO_DOMAIN_IDS (BEFORE) : $do_domain_ids_before
+--echo IGNORE_DOMAIN_IDS (BEFORE) : $ignore_domain_ids_before
+
+CHANGE MASTER TO IGNORE_DOMAIN_IDS=(), MASTER_USE_GTID=slave_pos;
+--source include/start_slave.inc
+sync_with_master;
+
+let $do_domain_ids_after= query_get_value(SHOW SLAVE STATUS, Replicate_Do_Domain_Ids, 1);
+let $ignore_domain_ids_after= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Domain_Ids, 1);
+--echo DO_DOMAIN_IDS (AFTER) : $do_domain_ids_after
+--echo IGNORE_DOMAIN_IDS (AFTER) : $ignore_domain_ids_after
+
+SET @@global.debug_dbug="d,kill_slave_io_after_2_events";
+
+connection master;
+
+SET @@session.gtid_domain_id= 1;
+
+START TRANSACTION;
+INSERT INTO t1 VALUES(24);
+INSERT INTO t1 VALUES(25); # IO thread gets killed here.
+COMMIT;
+
+START TRANSACTION;
+INSERT INTO t1 VALUES(26);
+INSERT INTO t1 VALUES(27);
+COMMIT;
+
+SET @@session.gtid_domain_id= 2;
+START TRANSACTION;
+INSERT INTO t1 VALUES(28);
+INSERT INTO t1 VALUES(29);
+COMMIT;
+
+save_master_pos;
+SELECT * FROM t1;
+
+connection slave;
+--let $slave_io_errno= 1595
+--source include/wait_for_slave_io_error.inc
+SELECT * FROM t1;
+
+SET @@global.debug_dbug=@saved_dbug;
+
+--source include/stop_slave.inc
+let $do_domain_ids_before= query_get_value(SHOW SLAVE STATUS, Replicate_Do_Domain_Ids, 1);
+let $ignore_domain_ids_before= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Domain_Ids, 1);
+--echo DO_DOMAIN_IDS (BEFORE) : $do_domain_ids_before
+--echo IGNORE_DOMAIN_IDS (BEFORE) : $ignore_domain_ids_before
+
+CHANGE MASTER TO IGNORE_DOMAIN_IDS=(1), MASTER_USE_GTID=slave_pos;
+--source include/start_slave.inc
+sync_with_master;
+
+let $do_domain_ids_after= query_get_value(SHOW SLAVE STATUS, Replicate_Do_Domain_Ids, 1);
+let $ignore_domain_ids_after= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Domain_Ids, 1);
+--echo DO_DOMAIN_IDS (AFTER) : $do_domain_ids_after
+--echo IGNORE_DOMAIN_IDS (AFTER) : $ignore_domain_ids_after
+
+SELECT * FROM t1;
+
+# Cleanup
+connection master;
+DROP TABLE t1;
+sync_slave_with_master;
+
+connection slave;
+--source include/stop_slave.inc
+CHANGE MASTER TO DO_DOMAIN_IDS=(), IGNORE_DOMAIN_IDS=();
+--source include/start_slave.inc
+SET @@GLOBAL.debug_dbug = @saved_dbug;
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_domain_id_filter_master_crash.test b/mysql-test/suite/rpl/t/rpl_domain_id_filter_master_crash.test
new file mode 100644
index 00000000..6dafab19
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_domain_id_filter_master_crash.test
@@ -0,0 +1,87 @@
+--source include/have_innodb.inc
+--source include/have_debug.inc
+# Valgrind does not work well with test that crashes the server
+--source include/not_valgrind.inc
+--source include/master-slave.inc
+
+connection master;
+
+call mtr.add_suppression("mysqld: Table '.*gtid_slave_pos' is marked as crashed and should be repaired");
+call mtr.add_suppression("Checking table: './mysql/gtid_slave_pos'");
+call mtr.add_suppression("mysql.gtid_slave_pos: 1 client is using or hasn't closed the table properly");
+SET @@session.gtid_domain_id= 0;
+
+create table ti (a int auto_increment primary key) engine=innodb;
+create table tm (a int auto_increment primary key) engine=myisam;
+
+insert into ti set a=null;
+insert into tm set a=null;
+
+save_master_pos;
+
+connection slave;
+sync_with_master;
+--source include/stop_slave.inc
+
+select * from ti;
+select * from tm;
+
+connection master;
+SET @@session.gtid_domain_id= 1;
+
+begin;
+insert into ti set a=null;
+insert into tm set a=null;
+commit;
+
+SET @@session.gtid_domain_id= 0;
+insert into ti set a=null;
+insert into tm set a=null;
+
+set @@global.debug_dbug="+d,crash_before_send_xid";
+--exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
+
+connection slave;
+let $do_domain_ids_before= query_get_value(SHOW SLAVE STATUS, Replicate_Do_Domain_Ids, 1);
+let $ignore_domain_ids_before= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Domain_Ids, 1);
+--echo DO_DOMAIN_IDS (BEFORE) : $do_domain_ids_before
+--echo IGNORE_DOMAIN_IDS (BEFORE) : $ignore_domain_ids_before
+
+# IGNORE_DOMAIN_IDS=(1)
+CHANGE MASTER TO IGNORE_DOMAIN_IDS=(1), MASTER_USE_GTID=slave_pos;
+--source include/start_slave.inc
+
+let $do_domain_ids_after= query_get_value(SHOW SLAVE STATUS, Replicate_Do_Domain_Ids, 1);
+let $ignore_domain_ids_after= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Domain_Ids, 1);
+--echo DO_DOMAIN_IDS (AFTER) : $do_domain_ids_after
+--echo IGNORE_DOMAIN_IDS (AFTER) : $ignore_domain_ids_after
+
+connection master;
+--source include/wait_until_disconnected.inc
+--enable_reconnect
+--let $rpl_server_number=1
+--source include/rpl_start_server.inc
+#--exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
+--source include/wait_until_connected_again.inc
+--echo # Master has restarted successfully
+save_master_pos;
+
+--connection slave
+--source include/stop_slave.inc
+--source include/start_slave.inc
+sync_with_master;
+select * from ti;
+select * from tm;
+
+# Cleanup
+--connection master
+drop table ti;
+drop table tm;
+sync_slave_with_master;
+
+--connection slave
+--source include/stop_slave.inc
+CHANGE MASTER TO DO_DOMAIN_IDS=(), IGNORE_DOMAIN_IDS=(), MASTER_USE_GTID=NO;
+--source include/start_slave.inc
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_domain_id_filter_parallel.test b/mysql-test/suite/rpl/t/rpl_domain_id_filter_parallel.test
new file mode 100644
index 00000000..902f6b52
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_domain_id_filter_parallel.test
@@ -0,0 +1,196 @@
+--source include/have_innodb.inc
+--source include/have_debug.inc
+--source include/have_debug_sync.inc
+--let $rpl_topology=1->2
+--source include/rpl_init.inc
+
+--connection server_2
+SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads;
+--source include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=10;
+
+##### Case 0 : When both DO_DOMAIN_IDS and IGNORE_DOMAIN_IDS are empty.
+
+--connection server_2
+CHANGE MASTER TO master_use_gtid=slave_pos, DO_DOMAIN_IDS=(), IGNORE_DOMAIN_IDS=();
+--source include/start_slave.inc
+
+--connection server_1
+SELECT @@session.gtid_domain_id;
+ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
+CREATE TABLE t1 (a int PRIMARY KEY) ENGINE=MyISAM;
+CREATE TABLE t2 (a int PRIMARY KEY) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t2 VALUES (1);
+--save_master_pos
+
+--connection server_2
+--sync_with_master
+
+# Block the table t1 to simulate a replicated query taking a long time.
+--connect (con_temp1,127.0.0.1,root,,test,$SERVER_MYPORT_2,)
+LOCK TABLE t1 WRITE;
+
+--connection server_1
+SET @@session.gtid_domain_id=1;
+# This query will be blocked on the slave until UNLOCK TABLES.
+INSERT INTO t1 VALUES (2);
+SET @@session.gtid_domain_id=0;
+# These t2 queries can be replicated in parallel with the prior t1 query, as
+# they are in a separate replication domain.
+INSERT INTO t2 VALUES (2);
+INSERT INTO t2 VALUES (3);
+BEGIN;
+INSERT INTO t2 VALUES (4);
+INSERT INTO t2 VALUES (5);
+COMMIT;
+INSERT INTO t2 VALUES (6);
+
+--connection server_2
+--let $wait_condition= SELECT COUNT(*) = 6 FROM t2
+--source include/wait_condition.inc
+
+SELECT * FROM t2 ORDER by a;
+
+--connection con_temp1
+SELECT * FROM t1;
+UNLOCK TABLES;
+
+--connection server_2
+--let $wait_condition= SELECT COUNT(*) = 2 FROM t1
+--source include/wait_condition.inc
+
+SELECT * FROM t1 ORDER BY a;
+
+##### Case 1 : When DO_DOMAIN_IDS=(1)
+
+--connection server_2
+--source include/stop_slave.inc
+let $do_domain_ids_before= query_get_value(SHOW SLAVE STATUS, Replicate_Do_Domain_Ids, 1);
+let $ignore_domain_ids_before= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Domain_Ids, 1);
+--echo DO_DOMAIN_IDS (BEFORE) : $do_domain_ids_before
+--echo IGNORE_DOMAIN_IDS (BEFORE) : $ignore_domain_ids_before
+
+# Replicate events belonging to "domain_id 1".
+CHANGE MASTER TO DO_DOMAIN_IDS=(1), MASTER_USE_GTID=slave_pos;
+--source include/start_slave.inc
+sync_with_master;
+
+let $do_domain_ids_after= query_get_value(SHOW SLAVE STATUS, Replicate_Do_Domain_Ids, 1);
+let $ignore_domain_ids_after= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Domain_Ids, 1);
+--echo DO_DOMAIN_IDS (AFTER) : $do_domain_ids_after
+--echo IGNORE_DOMAIN_IDS (AFTER) : $ignore_domain_ids_after
+
+--connection server_2
+--sync_with_master
+
+# Block the table t1 to simulate a replicated query taking a long time.
+--connection con_temp1
+LOCK TABLE t1 WRITE;
+
+--connection server_1
+SET @@session.gtid_domain_id=0;
+# This query will be blocked on the slave until UNLOCK TABLES.
+# But, since DO_DOMAIN_IDS=(1), it will be filtered out on slave.
+INSERT INTO t1 VALUES (3);
+
+SET @@session.gtid_domain_id=1;
+# These t2 queries can be replicated in parallel with the prior t1 query, as
+# they are in a separate replication domain.
+INSERT INTO t2 VALUES (7);
+INSERT INTO t2 VALUES (8);
+BEGIN;
+INSERT INTO t2 VALUES (9);
+INSERT INTO t2 VALUES (10);
+COMMIT;
+INSERT INTO t2 VALUES (11);
+
+--connection server_2
+--let $wait_condition= SELECT COUNT(*) = 11 FROM t2
+--source include/wait_condition.inc
+
+SELECT * FROM t2 ORDER by a;
+
+--connection con_temp1
+SELECT * FROM t1;
+UNLOCK TABLES;
+
+--connection server_2
+--let $wait_condition= SELECT COUNT(*) = 2 FROM t1
+--source include/wait_condition.inc
+
+SELECT * FROM t1 ORDER BY a;
+
+##### Case 2 : When IGNORE_DOMAIN_IDS=(1)
+
+--connection server_2
+--source include/stop_slave.inc
+let $do_domain_ids_before= query_get_value(SHOW SLAVE STATUS, Replicate_Do_Domain_Ids, 1);
+let $ignore_domain_ids_before= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Domain_Ids, 1);
+--echo DO_DOMAIN_IDS (BEFORE) : $do_domain_ids_before
+--echo IGNORE_DOMAIN_IDS (BEFORE) : $ignore_domain_ids_before
+
+# Replicate events belonging to "domain_id 1".
+CHANGE MASTER TO DO_DOMAIN_IDS=(), IGNORE_DOMAIN_IDS=(1), MASTER_USE_GTID=slave_pos;
+--source include/start_slave.inc
+sync_with_master;
+
+let $do_domain_ids_after= query_get_value(SHOW SLAVE STATUS, Replicate_Do_Domain_Ids, 1);
+let $ignore_domain_ids_after= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Domain_Ids, 1);
+--echo DO_DOMAIN_IDS (AFTER) : $do_domain_ids_after
+--echo IGNORE_DOMAIN_IDS (AFTER) : $ignore_domain_ids_after
+
+--connection server_2
+--sync_with_master
+
+# Block the table t1 to simulate a replicated query taking a long time.
+--connection con_temp1
+LOCK TABLE t1 WRITE;
+
+--connection server_1
+SET @@session.gtid_domain_id=1;
+# This query will be blocked on the slave until UNLOCK TABLES. However, since
+# IGNORE_DOMAIN_IDS=(1), it will be filtered out on slave.
+INSERT INTO t1 VALUES (4);
+SET @@session.gtid_domain_id=0;
+# These t2 queries can be replicated in parallel with the prior t1 query, as
+# they are in a separate replication domain.
+INSERT INTO t2 VALUES (12);
+INSERT INTO t2 VALUES (13);
+BEGIN;
+INSERT INTO t2 VALUES (14);
+INSERT INTO t2 VALUES (15);
+COMMIT;
+INSERT INTO t2 VALUES (16);
+
+--connection server_2
+--let $wait_condition= SELECT COUNT(*) = 16 FROM t2
+--source include/wait_condition.inc
+
+SELECT * FROM t2 ORDER by a;
+
+--connection con_temp1
+SELECT * FROM t1;
+UNLOCK TABLES;
+
+--connection server_2
+--let $wait_condition= SELECT COUNT(*) = 2 FROM t1
+--source include/wait_condition.inc
+
+SELECT * FROM t1 ORDER BY a;
+SELECT * FROM t2;
+
+--echo # Restore original settings.
+--connection server_1
+SET @@session.gtid_domain_id=0;
+DROP TABLE t1, t2;
+--save_master_pos
+
+--connection server_2
+--sync_with_master
+--source include/stop_slave.inc
+SET GLOBAL slave_parallel_threads= @old_parallel_threads;
+CHANGE MASTER TO DO_DOMAIN_IDS=(), IGNORE_DOMAIN_IDS=();
+--source include/start_slave.inc
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_domain_id_filter_restart.test b/mysql-test/suite/rpl/t/rpl_domain_id_filter_restart.test
new file mode 100644
index 00000000..8083b8f2
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_domain_id_filter_restart.test
@@ -0,0 +1,73 @@
+--source include/master-slave.inc
+
+#
+# Test for domain-id based filter on slave restart in GTID-mode.
+#
+
+
+connection slave;
+
+source include/stop_slave.inc;
+let $do_domain_ids_before= query_get_value(SHOW SLAVE STATUS, Replicate_Do_Domain_Ids, 1);
+let $ignore_domain_ids_before= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Domain_Ids, 1);
+--echo DO_DOMAIN_IDS (BEFORE) : $do_domain_ids_before
+--echo IGNORE_DOMAIN_IDS (BEFORE) : $ignore_domain_ids_before
+
+# Ignore events belonging to "domain_id 1".
+CHANGE MASTER TO IGNORE_DOMAIN_IDS=(1), MASTER_USE_GTID=slave_pos;
+source include/start_slave.inc;
+
+let $do_domain_ids_after= query_get_value(SHOW SLAVE STATUS, Replicate_Do_Domain_Ids, 1);
+let $ignore_domain_ids_after= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Domain_Ids, 1);
+--echo DO_DOMAIN_IDS (AFTER) : $do_domain_ids_after
+--echo IGNORE_DOMAIN_IDS (AFTER) : $ignore_domain_ids_after
+
+connection master;
+SET @@session.gtid_domain_id= 0;
+CREATE TABLE t1(i INT);
+CREATE TABLE t2(i INT);
+
+INSERT INTO t1 VALUES(1);
+SELECT * FROM t1;
+
+SET @@session.gtid_domain_id= 1;
+# the following will get filtered out.
+INSERT INTO t2 VALUES(1);
+SELECT * FROM t2;
+
+sync_slave_with_master;
+
+connection slave;
+SELECT * FROM t1;
+SELECT * FROM t2;
+
+# restart the slave
+--let $rpl_server_number= 2
+--source include/rpl_restart_server.inc
+
+# Replicate_Do_Domain_Ids/Replicate_Ignore_Domain_Ids should reinitialize
+# properly on restart.
+connection slave;
+let $do_domain_ids_after= query_get_value(SHOW SLAVE STATUS, Replicate_Do_Domain_Ids, 1);
+let $ignore_domain_ids_after= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Domain_Ids, 1);
+--echo DO_DOMAIN_IDS (AFTER RESTART) : $do_domain_ids_after
+--echo IGNORE_DOMAIN_IDS (AFTER RESTART) : $ignore_domain_ids_after
+
+# Now, lets clear IGNORE_DOMAIN_IDS.
+CHANGE MASTER TO IGNORE_DOMAIN_IDS=();
+--source include/start_slave.inc
+
+let $do_domain_ids_after= query_get_value(SHOW SLAVE STATUS, Replicate_Do_Domain_Ids, 1);
+let $ignore_domain_ids_after= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Domain_Ids, 1);
+--echo DO_DOMAIN_IDS (AFTER) : $do_domain_ids_after
+--echo IGNORE_DOMAIN_IDS (AFTER) : $ignore_domain_ids_after
+
+SELECT * FROM t1;
+SELECT * FROM t2;
+
+connection master;
+SET @@session.gtid_domain_id= 0;
+DROP TABLE t1, t2;
+sync_slave_with_master;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_drop.test b/mysql-test/suite/rpl/t/rpl_drop.test
new file mode 100644
index 00000000..7b887334
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_drop.test
@@ -0,0 +1,12 @@
+# Testcase for BUG#4552 (DROP on two tables, one of which does not
+# exist, must be binlogged with a non-zero error code)
+source include/master-slave.inc;
+
+create table t1 (a int);
+--error 1051
+drop table t1, t2;
+--sync_slave_with_master
+
+# End of 4.1 tests
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_drop_db.test b/mysql-test/suite/rpl/t/rpl_drop_db.test
new file mode 100644
index 00000000..245ab8b6
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_drop_db.test
@@ -0,0 +1,66 @@
+# test case for BUG#4680 -- if there are extra files in the db directory
+# dropping the db on the master causes replication problems
+
+-- source include/master-slave.inc
+connection master;
+
+--disable_warnings
+drop database if exists mysqltest1;
+--enable_warnings
+create database mysqltest1;
+create table mysqltest1.t1 (n int);
+insert into mysqltest1.t1 values (1);
+--enable_prepare_warnings
+--disable_ps2_protocol
+select * from mysqltest1.t1 into outfile 'mysqltest1/f1.txt';
+--disable_prepare_warnings
+--enable_ps2_protocol
+create table mysqltest1.t2 (n int);
+create table mysqltest1.t3 (n int);
+--replace_result \\ / 66 39 93 39 17 39 247 39 41 39 "File exists" "Directory not empty"
+--error ER_DB_DROP_RMDIR
+drop database mysqltest1;
+use mysqltest1;
+show tables;
+
+# test the branch of the code that deals with the query buffer overflow
+
+--disable_query_log
+let $1=50;
+while ($1)
+{
+ eval create table mysqltest1.mysqltest_long_table_name$1 (n int);
+ dec $1;
+}
+--enable_query_log
+
+--replace_result \\ / 66 39 93 39 17 39 247 39 41 39 "File exists" "Directory not empty"
+--error ER_DB_DROP_RMDIR
+drop database mysqltest1;
+use mysqltest1;
+show tables;
+use test;
+create table t1 (n int);
+insert into t1 values (1234);
+sync_slave_with_master;
+
+connection slave;
+use mysqltest1;
+show tables;
+use test;
+select * from t1;
+
+#cleanup
+connection master;
+
+# Remove the "extra" file created above
+let $MYSQLD_DATADIR= `select @@datadir`;
+remove_file $MYSQLD_DATADIR/mysqltest1/f1.txt;
+
+use test;
+drop table t1;
+drop database mysqltest1;
+
+sync_slave_with_master;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_drop_db_fail.test b/mysql-test/suite/rpl/t/rpl_drop_db_fail.test
new file mode 100644
index 00000000..c13bae1c
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_drop_db_fail.test
@@ -0,0 +1,34 @@
+###############################################################################
+# Bug#20041860: SLAVE ERROR WHEN DROP DATABASE
+#
+# Test:
+# =====
+# Create two databases such that one database has a dependency over the other
+# database and try to drop the database which has a dependency. This should
+# not cause slave to break.
+###############################################################################
+--source include/have_innodb.inc
+--source include/master-slave.inc
+
+connection master;
+CREATE DATABASE IF NOT EXISTS db1;
+CREATE DATABASE IF NOT EXISTS db2;
+
+use db1;
+CREATE TABLE a(id INT);
+CREATE VIEW v AS SELECT * FROM a;
+CREATE TABLE table_father(id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(20)) ENGINE=INNODB;
+--sync_slave_with_master
+
+connection master;
+use db2;
+CREATE TABLE table_child(id INT PRIMARY KEY, info VARCHAR(20), father_id INT) ENGINE=INNODB;
+ALTER TABLE table_child ADD CONSTRAINT aaa FOREIGN KEY (father_id) REFERENCES db1.table_father(id);
+
+--error ER_ROW_IS_REFERENCED_2
+DROP DATABASE db1;
+DROP DATABASE db2;
+--sync_slave_with_master
+--connection master
+DROP DATABASE db1;
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_drop_temp-slave.opt b/mysql-test/suite/rpl/t/rpl_drop_temp-slave.opt
new file mode 100644
index 00000000..2f9244c6
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_drop_temp-slave.opt
@@ -0,0 +1,2 @@
+--replicate-ignore-table=mysqltest.t2
+
diff --git a/mysql-test/suite/rpl/t/rpl_drop_temp.test b/mysql-test/suite/rpl/t/rpl_drop_temp.test
new file mode 100644
index 00000000..7158e2a8
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_drop_temp.test
@@ -0,0 +1,94 @@
+##############################################
+# Change Author: JBM
+# Change Date: 2006-02-07
+# Change: Added ENGINE=MyISAM
+##############################################
+source include/have_binlog_format_mixed_or_statement.inc;
+source include/master-slave.inc;
+
+--disable_warnings
+create database if not exists mysqltest;
+--enable_warnings
+
+connect (con_temp,127.0.0.1,root,,test,$MASTER_MYPORT,);
+
+connection con_temp;
+use mysqltest;
+create temporary table mysqltest.t1 (n int)ENGINE=MyISAM;
+create temporary table mysqltest.t2 (n int)ENGINE=MyISAM;
+
+disconnect con_temp;
+--source include/wait_until_disconnected.inc
+
+connection master;
+-- let $wait_binlog_event= DROP
+-- source include/wait_for_binlog_event.inc
+sync_slave_with_master;
+
+connection slave;
+show status like 'Slave_open_temp_tables';
+# Cleanup
+connection master;
+drop database mysqltest;
+sync_slave_with_master;
+
+#
+# Bug#49137
+# This test verifies if DROP MULTI TEMPORARY TABLE
+# will cause different errors on master and slave,
+# when one or more of these tables do not exist.
+#
+
+connection master;
+DROP TEMPORARY TABLE IF EXISTS tmp1;
+CREATE TEMPORARY TABLE t1 ( a int );
+--error 1051
+DROP TEMPORARY TABLE t1, t2;
+--error 1051
+DROP TEMPORARY TABLE tmp2;
+sync_slave_with_master;
+
+connection slave;
+stop slave;
+wait_for_slave_to_stop;
+
+connection master;
+CREATE TEMPORARY TABLE tmp3 (a int);
+DROP TEMPORARY TABLE tmp3;
+
+connection slave;
+SET GLOBAL SQL_SLAVE_SKIP_COUNTER=1;
+START SLAVE;
+
+connection master;
+sync_slave_with_master;
+
+
+#
+# BUG#54842: DROP TEMPORARY TABLE not binlogged after manual switching binlog format to ROW
+#
+
+--source include/rpl_reset.inc
+--connection master
+
+CREATE TABLE t1 ( i INT );
+--sync_slave_with_master
+SHOW STATUS LIKE 'Slave_open_temp_tables';
+
+--connect(con1,localhost,root,,)
+CREATE TEMPORARY TABLE ttmp1 ( i INT );
+SET SESSION binlog_format=ROW;
+--disconnect con1
+
+-- connection master
+--let $wait_binlog_event= DROP
+--source include/wait_for_binlog_event.inc
+--sync_slave_with_master
+SHOW STATUS LIKE 'Slave_open_temp_tables';
+
+--connection master
+--source include/show_binlog_events.inc
+DROP TABLE t1;
+
+# End of 4.1 tests
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_drop_temp_table_invalid_lex.test b/mysql-test/suite/rpl/t/rpl_drop_temp_table_invalid_lex.test
new file mode 100644
index 00000000..475afef1
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_drop_temp_table_invalid_lex.test
@@ -0,0 +1,41 @@
+# ==== Purpose ====
+#
+# Test verifies that no ASAN issues are reported at the time of writing DROP
+# TEMPORARY TABLE statements to binary log as part of session cleanup.
+#
+# ==== Implementation ====
+#
+# Steps:
+# 1 - Create a new connection named 'con1'.
+# 2 - Create a temporary table named 'tmp' as part of connection 'con1'.
+# 3 - Try to disconnect the current session when a CREATE .. SELECT
+# statement is in the middle of execution.
+# 4 - Observe that no ASAN issue is reported.
+#
+# ==== References ====
+#
+# MDEV-19716: ASAN use-after-poison in Query_log_event::Query_log_event /
+# THD::log_events_and_free_tmp_shares
+
+--source include/have_binlog_format_mixed_or_statement.inc
+--source include/master-slave.inc
+
+--connect (con1,localhost,root,,)
+CREATE TEMPORARY TABLE tmp (a INT);
+
+--send CREATE TABLE non_existing_db.t SELECT 1 AS b
+--disconnect con1
+--source include/wait_until_disconnected.inc
+
+--connection master
+--let $wait_binlog_event= DROP
+--source include/wait_for_binlog_event.inc
+sync_slave_with_master;
+
+--connection slave
+--let $open_temp_tbl_count=query_get_value(show status like 'Slave_open_temp_tables', Value, 1)
+--let $assert_cond= "open_temp_tbl_count" = 0
+--let $assert_text= "Slave_open_temp_tables count should be 0"
+--source include/assert.inc
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_drop_view.test b/mysql-test/suite/rpl/t/rpl_drop_view.test
new file mode 100644
index 00000000..1893dd21
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_drop_view.test
@@ -0,0 +1,35 @@
+# test case for bug#30998
+# Drop View breaks replication if view does not exist
+#
+
+source include/master-slave.inc;
+--disable_warnings
+drop table if exists t1, t2;
+drop view if exists v1, v2, v3, not_exist_view;
+--enable_warnings
+create table t1 (a int);
+create table t2 (b int);
+create table t3 (c int);
+create view v1 as select * from t1;
+create view v2 as select * from t2;
+create view v3 as select * from t3;
+--error ER_UNKNOWN_VIEW
+drop view not_exist_view;
+--error ER_UNKNOWN_VIEW
+drop view v1, not_exist_view;
+--error 1146
+select * from v1;
+drop view v2, v3;
+sync_slave_with_master;
+--error 1146
+select * from v1;
+--error 1146
+select * from v2;
+--error 1146
+select * from v3;
+
+--echo ==== clean up ====
+connection master;
+drop table t1, t2, t3;
+sync_slave_with_master;
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_dual_pos_advance.test b/mysql-test/suite/rpl/t/rpl_dual_pos_advance.test
new file mode 100644
index 00000000..618576f5
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_dual_pos_advance.test
@@ -0,0 +1,97 @@
+# This test checks that in a dual-head setup
+# A->B->A, where A has --log-slave-updates (why would it?
+# assume that there is a C as slave of A),
+# then the Exec_master_log_pos of SHOW SLAVE STATUS does
+# not stay too low on B(BUG#13023 due to events ignored because
+# of their server id).
+# It also will test BUG#13861.
+
+source include/have_innodb.inc;
+
+--let $rpl_topology= 1->2->1
+--source include/rpl_init.inc
+
+# now we test it
+
+connection server_2;
+
+create table t1 (n int);
+let $master_log_file= query_get_value(SHOW MASTER STATUS, File, 1);
+let $master_log_pos_1= query_get_value(SHOW MASTER STATUS, Position, 1);
+let $master_log_pos_1= `SELECT $master_log_pos_1 + 3`;
+
+--sync_slave_with_master server_1
+
+#
+# BUG#13861 - START SLAVE UNTIL may stop 1 evnt too late if
+# log-slave-updates and circul repl
+#
+source include/stop_slave.inc;
+
+create table t2 (n int); # create one ignored event
+
+--sync_slave_with_master server_2
+
+show tables;
+
+create table t3 (n int) engine=innodb;
+let $master_log_pos_2= query_get_value(SHOW MASTER STATUS, Position, 1);
+let $master_log_pos_2= `SELECT $master_log_pos_2 + 5`;
+set @a=1;
+insert into t3 values(@a);
+let $master_log_pos_3= query_get_value(SHOW MASTER STATUS, Position, 1);
+let $master_log_pos_3= `SELECT $master_log_pos_3 + 5`;
+begin;
+insert into t3 values(2);
+insert into t3 values(3);
+commit;
+insert into t3 values(4);
+
+
+connection server_1;
+
+# bug is that START SLAVE UNTIL may stop too late, we test that by
+# asking it to stop before creation of t3.
+
+--replace_result $master_log_file MASTER_LOG_FILE $master_log_pos_1 MASTER_LOG_POS
+eval start slave until master_log_file="$master_log_file",master_log_pos=$master_log_pos_1;
+--source include/wait_for_slave_sql_to_stop.inc
+
+# then BUG#13861 causes t3 to show up below (because stopped too
+# late).
+
+show tables;
+
+# ensure that we do not break set @a=1; insert into t3 values(@a);
+--replace_result $master_log_file MASTER_LOG_FILE $master_log_pos_2 MASTER_LOG_POS
+eval start slave until master_log_file="$master_log_file",master_log_pos=$master_log_pos_2;
+--source include/wait_for_slave_sql_to_stop.inc
+select * from t3;
+
+# ensure that we do not break transaction
+--replace_result $master_log_file MASTER_LOG_FILE $master_log_pos_3 MASTER_LOG_POS
+eval start slave until master_log_file="$master_log_file",master_log_pos=$master_log_pos_3;
+--source include/wait_for_slave_sql_to_stop.inc
+select * from t3;
+
+source include/start_slave.inc;
+
+# BUG#13023 is that Exec_master_log_pos may stay too low "forever":
+
+connection server_1;
+
+create table t4 (n int); # create 3 ignored events
+create table t5 (n int);
+create table t6 (n int);
+
+--sync_slave_with_master server_2
+
+# then BUG#13023 caused hang below ("master" looks behind, while it's
+# not in terms of updates done).
+--sync_slave_with_master server_1
+
+show tables;
+
+# cleanup
+drop table t1, t2, t3, t4, t5, t6;
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_dump_request_retry_warning.test b/mysql-test/suite/rpl/t/rpl_dump_request_retry_warning.test
new file mode 100644
index 00000000..1ee04362
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_dump_request_retry_warning.test
@@ -0,0 +1,66 @@
+# ==== Purpose ====
+#
+# Test verifies that, due to a temporary network error, if request dump
+# command specific packet write operation fails then the write error gets
+# handled appropriately. Further retry will be initiated with appropriate
+# slave registration on master. This will ensure that master has all the
+# details of slave and no warnings are reported on the master side.
+#
+# ==== Implementation ====
+#
+# Steps:
+# 0 - Skip the slave start.
+# 1 - Enable debug simulation which will simulate packet write error during
+# dump request command execution.
+# 2 - Start the slave. Observe that slave is able to reconnect post
+# temporary network write error.
+#
+# ==== References ====
+#
+# MDEV-14203: rpl.rpl_extra_col_master_myisam,
+# rpl.rpl_slave_load_tmpdir_not_exist failed in buildbot with a
+# warning
+#
+# MDEV-13258: rpl.rpl_skip_replication, rpl.rpl_set_statement_default_master
+# failed in buildbot
+#
+
+--source include/have_debug.inc
+--source include/have_debug_sync.inc
+--let $rpl_skip_start_slave=1
+--source include/master-slave.inc
+
+# Do an insert on master
+CREATE TABLE t1(a int);
+INSERT INTO t1 VALUES(1);
+
+# Add a debug point and start the slave so that dump request fails.
+connection slave;
+SET @saved_dbug = @@GLOBAL.debug_dbug;
+SET @@global.debug_dbug= 'd,simulate_error_on_packet_write';
+
+START SLAVE;
+SET DEBUG_SYNC= 'now WAIT_FOR parked';
+SET @@GLOBAL.debug_dbug = @saved_dbug;
+SET DEBUG_SYNC= 'now SIGNAL continue';
+
+# Ensure the last DEBUG_SYNC signal was received by the target thread before
+# reset; otherwise, the reset can drop the last signal before it gets
+# acknowledged
+let $wait_condition= select count(*)=0 from information_schema.processlist where state like "%debug%";
+source include/wait_condition.inc;
+SET DEBUG_SYNC= 'RESET';
+
+--source include/wait_for_slave_io_to_start.inc
+--source include/wait_for_slave_sql_to_start.inc
+
+# Sync the slave and verify that slave has caught up with the master.
+connection master;
+--source include/sync_slave_sql_with_master.inc
+SELECT * FROM t1;
+
+# Cleanup
+connection master;
+DROP TABLE t1;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_empty_master_host.test b/mysql-test/suite/rpl/t/rpl_empty_master_host.test
new file mode 100644
index 00000000..0fc2d11a
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_empty_master_host.test
@@ -0,0 +1,53 @@
+#
+# BUG
+# ---
+# BUG#28796: CHANGE MASTER TO MASTER_HOST="" leads to invalid master.info
+#
+# Description
+# -----------
+#
+# This test aims at:
+# i) verifying that an error is thrown when setting MASTER_HOST=''
+# ii) no error is thrown when setting non empty MASTER_HOST
+# iii) replication works after setting a correct host name/ip
+#
+# Implementation is performed by feeding different values (according
+# to i), ii) and iii) ) to CHANGE MASTER TO MASTER_HOST= x and checking
+# along the way if error/no error is thrown and/or if replication starts
+# working when expected.
+
+--source include/have_binlog_format_mixed.inc
+--source include/master-slave.inc
+
+connection slave;
+STOP SLAVE;
+--source include/wait_for_slave_to_stop.inc
+
+let $master_host= query_get_value(SHOW SLAVE STATUS, Master_Host, 1);
+--echo Master_Host = '$master_host' (expected '127.0.0.1')
+
+# attempt to change to an empty master host should
+# result in error ER_WRONG_ARGUMENTS: "Incorrect arguments to ..."
+error ER_WRONG_ARGUMENTS;
+CHANGE MASTER TO MASTER_HOST="";
+
+# show slave status still holds previous information
+let $master_host= query_get_value(SHOW SLAVE STATUS, Master_Host, 1);
+--echo Master_Host = '$master_host' (expected '127.0.0.1')
+
+# changing master to other than empty master host succeeds
+CHANGE MASTER TO MASTER_HOST="foo";
+
+# show slave status should hold "foo" as master host
+let $master_host= query_get_value(SHOW SLAVE STATUS, Master_Host, 1);
+--echo Master_Host = '$master_host' (expected 'foo')
+
+# changing back to localhost
+CHANGE MASTER TO MASTER_HOST="127.0.0.1";
+let $master_host= query_get_value(SHOW SLAVE STATUS, Master_Host, 1);
+--echo Master_Host = '$master_host' (expected '127.0.0.1')
+
+# start slave must succeed.
+START SLAVE;
+--source include/wait_for_slave_to_start.inc
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_empty_string_is_null.test b/mysql-test/suite/rpl/t/rpl_empty_string_is_null.test
new file mode 100644
index 00000000..a0fecbb5
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_empty_string_is_null.test
@@ -0,0 +1,15 @@
+--source include/master-slave.inc
+--source include/have_binlog_format_row.inc
+
+--echo #
+--echo # MDEV-18918 SQL mode EMPTY_STRING_IS_NULL breaks RBR upon CREATE TABLE .. SELECT
+--echo #
+
+SET SQL_MODE= 'EMPTY_STRING_IS_NULL';
+CREATE TABLE t1 AS SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE 1 = 0;
+--sync_slave_with_master
+SHOW CREATE TABLE t1;
+--connection master
+DROP TABLE t1;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_err_ignoredtable-slave.opt b/mysql-test/suite/rpl/t/rpl_err_ignoredtable-slave.opt
new file mode 100644
index 00000000..cb49119b
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_err_ignoredtable-slave.opt
@@ -0,0 +1 @@
+--replicate-ignore-table=test.t1 --replicate-ignore-table=test.t2 --replicate-ignore-table=test.t3
diff --git a/mysql-test/suite/rpl/t/rpl_err_ignoredtable.test b/mysql-test/suite/rpl/t/rpl_err_ignoredtable.test
new file mode 100644
index 00000000..9aee3582
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_err_ignoredtable.test
@@ -0,0 +1,70 @@
+# Test for
+# Bug #797: If a query is ignored on slave (replicate-ignore-table) the slave
+# still checks that it has the same error as on the master.
+##########################################################################
+
+-- source include/master-slave.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
+
+connection master;
+create table t1 (a int primary key);
+create table t4 (a int primary key);
+# generate an error that goes to the binlog
+--error 1022, ER_DUP_ENTRY
+insert into t1 values (1),(1);
+insert into t4 values (1),(2);
+# as the t1 table is ignored on the slave, the slave should be able to sync
+sync_slave_with_master;
+# check that the table has been ignored, because otherwise the test is nonsense
+show tables like 't1';
+show tables like 't4';
+SELECT * FROM test.t4 ORDER BY a;
+connection master;
+drop table t1;
+sync_slave_with_master;
+
+# Now test that even critical errors (connection killed)
+# are ignored if rules allow it.
+# The "kill" idea was copied from rpl000001.test.
+
+connection master1;
+select get_lock('crash_lock%20C', 10);
+
+connection master;
+create table t2 (a int primary key);
+insert into t2 values(1);
+create table t3 (id int);
+insert into t3 values(connection_id());
+send update t2 set a = a + 1 + get_lock('crash_lock%20C', 10);
+
+connection master1;
+let $wait_condition= SELECT count(*) > 0 FROM information_schema.processlist WHERE info LIKE 'update%' AND state='User lock';
+source include/wait_condition.inc;
+select (@id := id) - id from t3;
+kill @id;
+let $id= `SELECT @id`;
+let $wait_condition= SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE ID = $id;
+source include/wait_condition.inc;
+drop table t2,t3;
+insert into t4 values (3),(4);
+connection master;
+# The get_lock function causes warning for unsafe statement.
+--disable_warnings
+--error 0,1317,2013
+reap;
+--enable_warnings
+connection master1;
+sync_slave_with_master;
+SELECT * FROM test.t4 ORDER BY a;
+
+connection master1;
+DROP TABLE test.t4;
+sync_slave_with_master;
+# End of 4.1 tests
+# Adding comment for force manual merge 5.0 -> wl1012. delete me if needed
+
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_events.test b/mysql-test/suite/rpl/t/rpl_events.test
new file mode 100644
index 00000000..1d66c327
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_events.test
@@ -0,0 +1,249 @@
+##################################################################
+# Author: Giuseppe #
+# Date: 2006-12-20 #
+# Purpose: To test that event effects are replicated. #
+##################################################################
+
+if (`SELECT $PS_PROTOCOL != 0`)
+{
+ --skip Need regular protocol but ps-protocol was specified
+}
+
+--source include/master-slave.inc
+
+SET @old_event_scheduler = @@global.event_scheduler;
+set global event_scheduler=1;
+
+# first, we need a table to record something from an event
+
+eval CREATE TABLE `t1` (
+ `id` INT(10) UNSIGNED NOT NULL,
+ `c` VARCHAR(50) NOT NULL,
+ `ts` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+ PRIMARY KEY (`id`)
+) DEFAULT CHARSET=utf8;
+
+INSERT INTO t1 (id, c) VALUES (1, 'manually');
+
+# We create the event so that it inserts exactly 1 row in the table
+# A recuring event is used so that we can be sure the event will
+# fire regardless of timing delays on the server. Otherwise, it is
+# possible for the event to timeout before it has inserted a row.
+--echo "Creating event test.justonce on the master"
+CREATE EVENT test.justonce ON SCHEDULE EVERY 2 SECOND DO
+ INSERT IGNORE INTO t1 (id, c) VALUES (2, 'from justonce');
+
+# Show the event is alive and present on master
+--echo "Checking event is active on master"
+SELECT db, name, status, originator FROM mysql.event WHERE db = 'test' AND name = 'justonce';
+
+# Wait until event has fired. We know this because t1 will contain
+# the row from the event.
+let $wait_condition=
+ SELECT COUNT(*) = 1 FROM t1 WHERE c = 'from justonce';
+--source include/wait_condition.inc
+
+# check that table t1 contains something
+--echo "Checking event data on the master"
+let $events_done=`SELECT count(*) FROM t1 id`;
+--disable_query_log
+eval SELECT $events_done > 0 as ONE;
+--enable_query_log
+
+sync_slave_with_master;
+
+--echo "Checking event data on the slave"
+--disable_query_log
+eval SELECT count(*) - $events_done as ZERO FROM t1 id;
+--enable_query_log
+
+--echo "Checking event is inactive on slave"
+SELECT db, name, status, originator FROM mysql.event WHERE db = 'test' AND name = 'justonce';
+
+# Create an event on the slave and check to see what the originator is.
+--echo "Dropping event test.slave_once on the slave"
+--disable_warnings
+DROP EVENT IF EXISTS test.slave_once;
+--enable_warnings
+
+# Create an event on slave and check its state. An event shouldn't be executed
+# so set start time in 1 hour.
+CREATE EVENT test.slave_once ON SCHEDULE EVERY 5 MINUTE STARTS CURRENT_TIMESTAMP + INTERVAL 1 HOUR DO
+ INSERT IGNORE INTO t1(id, c) VALUES (3, 'from slave_once');
+
+--echo "Checking event status on the slave for originator value = slave's server_id"
+SELECT db, name, status, originator FROM mysql.event WHERE db = 'test' AND name = 'slave_once';
+
+--echo "Dropping event test.slave_once on the slave"
+--disable_warnings
+DROP EVENT IF EXISTS test.slave_once;
+--enable_warnings
+
+connection master;
+
+# BUG#20384 - disable events on slave
+--echo "Dropping event test.justonce on the master"
+--disable_warnings
+DROP EVENT IF EXISTS test.justonce;
+--enable_warnings
+
+# Create an event on master and check its state on slave. An event shouldn't be executed
+# so set start time in 1 hour. Check that changes of event statement replicated to slave
+
+--echo "Creating event test.er on the master"
+CREATE EVENT test.er ON SCHEDULE EVERY 3 SECOND STARTS CURRENT_TIMESTAMP + INTERVAL 1 HOUR DO
+ INSERT IGNORE INTO t1(id, c) VALUES (4, 'from er');
+
+--echo "Checking event status on the master"
+SELECT db, name, status, originator, body FROM mysql.event WHERE db = 'test' AND name = 'er';
+
+sync_slave_with_master;
+
+--echo "Checking event status on the slave"
+SELECT db, name, status, originator, body FROM mysql.event WHERE db = 'test' AND name = 'er';
+
+connection master;
+--echo "Altering event test.er on the master"
+ALTER EVENT test.er ON SCHEDULE EVERY 5 SECOND STARTS CURRENT_TIMESTAMP + INTERVAL 1 HOUR DO
+ INSERT IGNORE INTO t1(id, c) VALUES (5, 'from alter er');
+
+--echo "Checking event status on the master"
+SELECT db, name, status, originator, body FROM mysql.event WHERE db = 'test' AND name = 'er';
+
+sync_slave_with_master;
+
+--echo "Checking event status on the slave"
+SELECT db, name, status, originator, body FROM mysql.event WHERE db = 'test' AND name = 'er';
+
+connection master;
+--echo "Dropping event test.er on the master"
+DROP EVENT test.er;
+
+--echo "Checking event status on the master"
+SELECT db, name, status, originator FROM mysql.event WHERE db = 'test';
+
+--disable_info
+
+sync_slave_with_master;
+
+--echo "Checking event status on the slave"
+SELECT db, name, status, originator FROM mysql.event WHERE db = 'test';
+
+# test the DISABLE ON SLAVE for setting event SLAVESIDE_DISABLED as status
+# on CREATE EVENT
+
+# Create an event on slave and check its status. An event shouldn't be executed
+# so set start time in 1 hour.
+
+--echo "Creating event test.slave_terminate on the slave"
+CREATE EVENT test.slave_terminate ON SCHEDULE EVERY 3 SECOND STARTS CURRENT_TIMESTAMP + INTERVAL 1 HOUR DO
+ INSERT IGNORE INTO t1(id, c) VALUES (6, 'from slave_terminate');
+
+--echo "Checking event status on the slave"
+SELECT db, name, status, originator FROM mysql.event WHERE db = 'test' AND name = 'slave_terminate';
+
+--echo "Dropping event test.slave_terminate on the slave"
+DROP EVENT test.slave_terminate;
+
+--echo "Creating event test.slave_terminate with DISABLE ON SLAVE on the slave"
+CREATE EVENT test.slave_terminate ON SCHEDULE EVERY 3 SECOND DISABLE ON SLAVE DO
+ INSERT IGNORE INTO t1(c) VALUES (7, 'from slave_terminate');
+
+--echo "Checking event status on the slave"
+SELECT db, name, status, originator FROM mysql.event WHERE db = 'test' AND name = 'slave_terminate';
+
+--echo "Dropping event test.slave_terminate on the slave"
+DROP EVENT test.slave_terminate;
+
+--echo "Cleanup"
+
+connection master;
+DROP TABLE t1;
+sync_slave_with_master;
+connection master;
+
+#
+# Bug #28953 Using events in a replication let the slave crash.
+#
+
+CREATE TABLE t28953 (a INT);
+
+DELIMITER |;
+CREATE EVENT event1 ON SCHEDULE EVERY 1 YEAR
+DO BEGIN
+ select * from t28953;
+END;|
+DELIMITER ;|
+
+ALTER EVENT event1 RENAME TO event2;
+
+sync_slave_with_master;
+
+connection master;
+
+DROP EVENT event2;
+
+#
+# BUG#44331
+# This test verifies if the definer is consistent between master and slave,
+# when the event is created without the DEFINER clause set explicitly or the
+# DEFINER is set to CURRENT_USER
+#
+CREATE TABLE test.t1(details CHAR(30));
+
+CREATE EVENT /*!50000 event44331_1 */
+ ON SCHEDULE AT CURRENT_TIMESTAMP
+ ON COMPLETION PRESERVE DISABLE
+ DO INSERT INTO test.t1 VALUES('event event44331_1 fired - no definer');
+
+CREATE DEFINER=CURRENT_USER /*!50000 EVENT event44331_2 */
+ ON SCHEDULE AT CURRENT_TIMESTAMP
+ ON COMPLETION PRESERVE DISABLE
+ DO INSERT INTO test.t1 VALUES('event event44331_2 fired - DEFINER=CURRENT_USER');
+
+CREATE DEFINER=CURRENT_USER() EVENT event44331_3
+ ON SCHEDULE AT CURRENT_TIMESTAMP
+ ON COMPLETION PRESERVE DISABLE
+ DO INSERT INTO test.t1 VALUES('event event44331_3 fired - DEFINER=CURRENT_USER() function');
+
+DELIMITER |;
+CREATE /*!50000 DEFINER='user44331' */ EVENT event44331_4
+ ON SCHEDULE AT CURRENT_TIMESTAMP
+ ON COMPLETION PRESERVE DISABLE
+ DO INSERT INTO test.t1 VALUES('event event44331_4 fired - DEFINER=user1');
+# Test for bug#50095 Multi-statement including CREATE EVENT causes rotten
+# binlog entry
+ SELECT 'ABC';
+ SELECT '123'|
+DELIMITER ;|
+
+select EVENT_SCHEMA, EVENT_NAME, DEFINER from information_schema.events
+ where EVENT_NAME='event44331_1';
+select EVENT_SCHEMA, EVENT_NAME, DEFINER from information_schema.events
+ where EVENT_NAME='event44331_2';
+select EVENT_SCHEMA, EVENT_NAME, DEFINER from information_schema.events
+ where EVENT_NAME='event44331_3';
+select EVENT_SCHEMA, EVENT_NAME, DEFINER from information_schema.events
+ where EVENT_NAME='event44331_4';
+
+sync_slave_with_master;
+connection slave;
+select EVENT_SCHEMA, EVENT_NAME, DEFINER from information_schema.events
+ where EVENT_NAME='event44331_1';
+select EVENT_SCHEMA, EVENT_NAME, DEFINER from information_schema.events
+ where EVENT_NAME='event44331_2';
+select EVENT_SCHEMA, EVENT_NAME, DEFINER from information_schema.events
+ where EVENT_NAME='event44331_3';
+select EVENT_SCHEMA, EVENT_NAME, DEFINER from information_schema.events
+ where EVENT_NAME='event44331_4';
+
+connection master;
+SET @@global.event_scheduler= @old_event_scheduler;
+DROP TABLE t28953;
+DROP TABLE t1;
+DROP EVENT event44331_1;
+DROP EVENT event44331_2;
+DROP EVENT event44331_3;
+DROP EVENT event44331_4;
+sync_slave_with_master;
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_extra_col_master_innodb.test b/mysql-test/suite/rpl/t/rpl_extra_col_master_innodb.test
new file mode 100644
index 00000000..63ae0fce
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_extra_col_master_innodb.test
@@ -0,0 +1,11 @@
+#############################################################
+# Purpose: To test having extra columns on the master WL#3915
+#############################################################
+-- source include/have_binlog_format_row.inc
+-- source include/have_innodb.inc
+-- source include/master-slave.inc
+
+let $engine_type = 'InnoDB';
+--source include/rpl_extra_col_master.test
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_extra_col_master_myisam.test b/mysql-test/suite/rpl/t/rpl_extra_col_master_myisam.test
new file mode 100644
index 00000000..72a35992
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_extra_col_master_myisam.test
@@ -0,0 +1,10 @@
+#############################################################
+# Purpose: To test having extra columns on the master WL#3915
+#############################################################
+-- source include/have_binlog_format_row.inc
+-- source include/master-slave.inc
+
+let $engine_type = 'MyISAM';
+--source include/rpl_extra_col_master.test
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_extra_col_slave_innodb.test b/mysql-test/suite/rpl/t/rpl_extra_col_slave_innodb.test
new file mode 100644
index 00000000..e16e1dba
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_extra_col_slave_innodb.test
@@ -0,0 +1,7 @@
+-- source include/have_binlog_format_row.inc
+-- source include/have_innodb.inc
+-- source include/master-slave.inc
+
+let $engine_type = 'InnoDB';
+-- source include/rpl_extra_col_slave.test
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_extra_col_slave_myisam.test b/mysql-test/suite/rpl/t/rpl_extra_col_slave_myisam.test
new file mode 100644
index 00000000..f1e9fa24
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_extra_col_slave_myisam.test
@@ -0,0 +1,6 @@
+-- source include/have_binlog_format_row.inc
+-- source include/master-slave.inc
+
+let $engine_type = 'MyISAM';
+-- source include/rpl_extra_col_slave.test
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_fail_register.test b/mysql-test/suite/rpl/t/rpl_fail_register.test
new file mode 100644
index 00000000..d95a5c5f
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_fail_register.test
@@ -0,0 +1,33 @@
+source include/have_debug.inc;
+source include/have_binlog_format_mixed.inc;
+source include/master-slave.inc;
+
+connection slave;
+
+set @old_dbug=@@global.debug_dbug;
+set global debug_dbug='d,fail_com_register_slave';
+
+stop slave;
+reset slave;
+source include/wait_for_slave_to_stop.inc;
+start slave;
+stop slave;
+source include/wait_for_slave_to_stop.inc;
+set global debug_dbug=@old_dbug;
+
+connection master;
+
+let $id=`SELECT id from information_schema.processlist where command='Binlog Dump'`;
+
+if ($id) {
+ replace_result $id DUMP_THREAD;
+ eval kill $id;
+ let $wait_condition= SELECT count(*)=0 from information_schema.processlist where command='Killed';
+ source include/wait_condition.inc;
+}
+
+show slave hosts;
+
+connection slave;
+start slave;
+source include/rpl_end.inc;
diff --git a/mysql-test/suite/rpl/t/rpl_failed_drop_tbl_binlog.opt b/mysql-test/suite/rpl/t/rpl_failed_drop_tbl_binlog.opt
new file mode 100644
index 00000000..14fe8f7b
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_failed_drop_tbl_binlog.opt
@@ -0,0 +1 @@
+--loose-innodb-adaptive-hash-index
diff --git a/mysql-test/suite/rpl/t/rpl_failed_optimize.test b/mysql-test/suite/rpl/t/rpl_failed_optimize.test
new file mode 100644
index 00000000..a65c19cb
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_failed_optimize.test
@@ -0,0 +1,3 @@
+-- source include/have_innodb.inc
+let $engine_type=InnoDB;
+-- source include/rpl_failed_optimize.test
diff --git a/mysql-test/suite/rpl/t/rpl_filter_dbs_dynamic.test b/mysql-test/suite/rpl/t/rpl_filter_dbs_dynamic.test
new file mode 100644
index 00000000..05590a0a
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_filter_dbs_dynamic.test
@@ -0,0 +1,63 @@
+#
+# Test if dynamic replication database filter rules are properly evaluated.
+#
+
+source include/have_binlog_format_statement.inc;
+source include/master-slave.inc;
+
+connection slave;
+--error ER_SLAVE_MUST_STOP
+SET @@GLOBAL.replicate_do_db="db1";
+--error ER_SLAVE_MUST_STOP
+SET @@GLOBAL.replicate_ignore_db="db2";
+
+connection slave;
+source include/stop_slave.inc;
+SET @@GLOBAL.replicate_do_db="db1";
+SET @@GLOBAL.replicate_ignore_db="db2";
+source include/start_slave.inc;
+connection master;
+
+CREATE DATABASE db1;
+CREATE DATABASE db2;
+CREATE DATABASE db3;
+
+# db is mentioned in do-db rules
+USE db1;
+CREATE TABLE t1 (a INT);
+
+# db is mentioned in ignore-db rules
+USE db2;
+CREATE TABLE t2 (a INT);
+
+# db is not mentioned in do-db or ignore-db rules
+USE db3;
+CREATE TABLE t3 (a INT);
+
+USE db1;
+INSERT INTO t1 VALUES (1);
+
+USE db2;
+INSERT INTO t2 VALUES (2);
+
+USE db3;
+INSERT INTO t3 VALUES (3);
+
+# Only db1 should be replicated to slave
+sync_slave_with_master;
+echo [on slave];
+SHOW DATABASES LIKE 'db%';
+SHOW TABLES IN db1 LIKE 't%';
+
+connection master;
+
+# Clean up
+connection master;
+DROP DATABASE IF EXISTS db1;
+DROP DATABASE IF EXISTS db2;
+DROP DATABASE IF EXISTS db3;
+--source include/rpl_end.inc
+
+connection slave;
+SET @@GLOBAL.replicate_do_db="";
+SET @@GLOBAL.replicate_ignore_db="";
diff --git a/mysql-test/suite/rpl/t/rpl_filter_revoke_missing_user.test b/mysql-test/suite/rpl/t/rpl_filter_revoke_missing_user.test
new file mode 100644
index 00000000..ca2c18d3
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_filter_revoke_missing_user.test
@@ -0,0 +1,92 @@
+#
+# Purpose:
+# This test ensures that a binlogged Query_log_event which failed on the
+# primary server does not break replication if it is ignored by Grant_tables
+# on the replica. The bug reported by MDEV-28530 shows this with
+# REVOKE ALL PRIVILEGES.. using a non-existent user. The primary will binlog
+# the REVOKE command with an error code, and the replica will think the command
+# executed with success because the replication filter will ignore the command
+# while accessing the Grant_tables classes. When the replica performs an error
+# check, it sees the difference between the error codes, and replication
+# breaks.
+#
+# Methodology:
+# Using a replica configured with replicate_wild_ignore_table="schema.%",
+# on the primary, execute REVOKE ALL PRVILEGES using a non-existent user and
+# DROP USER using a list of users where not all users exist, and ensure that
+# the replica acknowledges and ignores the events without erroring.
+#
+# References:
+# MDEV-28530: Revoking privileges from a non-existing user on a master breaks
+# replication on the slave in the presence of replication filters
+#
+
+source include/master-slave.inc;
+source include/have_binlog_format_statement.inc;
+
+--echo #
+--echo # Set replica to ignore system tables
+connection slave;
+let $old_filter= query_get_value(SHOW SLAVE STATUS, Replicate_Wild_Ignore_Table, 1);
+source include/stop_slave.inc;
+SET @@GLOBAL.replicate_wild_ignore_table="mysql.%";
+source include/start_slave.inc;
+
+
+--echo #
+--echo # Trying to execute REVOKE ALL PRIVILEGES on a non-existent user and
+--echo # DROP USER on a list of users where not all users exist should error
+--echo # and be written into the binary log
+--connection master
+
+--error 1269
+REVOKE ALL PRIVILEGES, GRANT OPTION FROM 'nonexistentuser'@'%';
+
+CREATE USER 'testuser'@'localhost' IDENTIFIED by '';
+--error 1396
+DROP USER 'testuser'@'localhost', 'nonexistentuser'@'%';
+--save_master_pos
+
+
+--echo #
+--echo # Ensure the events exist in the primary's binary log
+--let $MYSQLD_DATADIR= `select @@datadir`
+--let $binlog_file=query_get_value(SHOW MASTER STATUS, File, 1)
+FLUSH BINARY LOGS;
+--echo # MYSQL_BINLOG MYSQLD_DATADIR/binlog_file > MYSQL_TMP_DIR/mysqlbinlog_out.sql
+--exec $MYSQL_BINLOG $MYSQLD_DATADIR/$binlog_file > $MYSQL_TMP_DIR/mysqlbinlog_out.sql
+
+--echo # There should be three Query events: REVOKE, CREATE USER, and DROP USER
+--let SEARCH_FILE= $MYSQL_TMP_DIR/mysqlbinlog_out.sql
+
+--let SEARCH_PATTERN= Query
+--source include/search_pattern_in_file.inc
+
+--let SEARCH_PATTERN= REVOKE ALL PRIVILEGES
+--source include/search_pattern_in_file.inc
+
+--let SEARCH_PATTERN= CREATE USER
+--source include/search_pattern_in_file.inc
+
+--let SEARCH_PATTERN= DROP USER
+--source include/search_pattern_in_file.inc
+
+
+--echo #
+--echo # Ensure that the replica receives the event without error
+connection slave;
+--sync_with_master
+let $error= query_get_value(SHOW SLAVE STATUS, Last_SQL_Error, 1);
+--echo Last_SQL_Error = $error
+let $errno= query_get_value(SHOW SLAVE STATUS, Last_SQL_Errno, 1);
+--echo Last_SQL_Errno = $errno
+
+
+--echo #
+--echo # Clean up
+--connection slave
+source include/stop_slave.inc;
+--eval SET @@GLOBAL.replicate_wild_ignore_table="$old_filter"
+source include/start_slave.inc;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_filter_set_var_missing_data.test b/mysql-test/suite/rpl/t/rpl_filter_set_var_missing_data.test
new file mode 100644
index 00000000..25efb6ed
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_filter_set_var_missing_data.test
@@ -0,0 +1,83 @@
+#
+# Purpose:
+# This test ensures that the SET DEFAULT ROLE and SET PASSWORD commands can
+# be ignored by replica filter rules. MDEV-28294 exposed a bug in which
+# SET DEFAULT ROLE would check for the existence of the given roles/user even
+# when the targeted tables are ignored, resulting in errors if the targeted
+# data does not exist. More specifically, when previously issued
+# CREATE USER/ROLE commands are ignored by the replica because of the
+# replication filtering rules, SET DEFAULT ROLE would result in an error
+# because the targeted data does not exist.
+#
+# Methodology:
+# Using a replica configured with replicate_wild_ignore_table="mysql.%",
+# execute SET DEFAULT ROLE and SET PASSWORD on the primary and ensure that the
+# replica neither errors nor executes the commands which the primary sends.
+#
+# References:
+# MDEV-28294: set default role bypasses Replicate_Wild_Ignore_Table: mysql.%
+#
+
+source include/master-slave.inc;
+source include/have_binlog_format_mixed.inc;
+
+--echo #
+--echo # Set replica to ignore system mysql tables
+connection slave;
+let $old_filter= query_get_value(SHOW SLAVE STATUS, Replicate_Wild_Ignore_Table, 1);
+source include/stop_slave.inc;
+SET @@GLOBAL.replicate_wild_ignore_table="mysql.%";
+source include/start_slave.inc;
+
+--echo #
+--echo # Execute grant-based commands on primary which modify mysql system
+--echo # tables
+connection master;
+CREATE ROLE journalist;
+CREATE USER testuser@localhost IDENTIFIED by '';
+GRANT journalist to testuser@localhost;
+
+--echo #
+--echo # Execute SET commands which use the previous user/role data
+SET DEFAULT ROLE journalist for testuser@localhost;
+SET PASSWORD for testuser@localhost= PASSWORD('123');
+--source include/save_master_gtid.inc
+
+--echo #
+--echo # Verify primary's grant tables have the correct user/role data
+select count(*)=1 from mysql.user where User='testuser';
+select count(*)=1 from mysql.roles_mapping where User='testuser';
+
+--echo #
+--echo # Ensure that the replica receives all of the primary's events without
+--echo # error
+connection slave;
+--source include/sync_with_master_gtid.inc
+let $error= query_get_value(SHOW SLAVE STATUS, Last_SQL_Error, 1);
+--echo Last_SQL_Error = $error
+let $errno= query_get_value(SHOW SLAVE STATUS, Last_SQL_Errno, 1);
+--echo Last_SQL_Errno = $errno
+
+--echo #
+--echo # Verify that the replica did not execute the master's commands
+select count(*)=0 from mysql.user where User='testuser';
+select count(*)=0 from mysql.roles_mapping where User='testuser';
+
+--echo #
+--echo # Clean up
+
+# The master has to drop the role/user combination while the slave still has
+# its filters active; otherwise, the slave would try to drop users/roles that
+# were never replicated.
+--connection master
+DROP ROLE journalist;
+DROP USER testuser@localhost;
+--source include/save_master_gtid.inc
+
+--connection slave
+--source include/sync_with_master_gtid.inc
+source include/stop_slave.inc;
+--eval SET @@GLOBAL.replicate_wild_ignore_table="$old_filter"
+source include/start_slave.inc;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_filter_tables_dynamic.test b/mysql-test/suite/rpl/t/rpl_filter_tables_dynamic.test
new file mode 100644
index 00000000..529613b3
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_filter_tables_dynamic.test
@@ -0,0 +1,217 @@
+# Test evaluation of replication table filter rules
+#
+# ==== Purpose ====
+#
+# Test if dynamic replication table filter rules are properly evaluated
+# when some of the tables referenced by the multiple-table update do not
+# exist on slave.
+#
+# ==== Method ====
+#
+# Master creates tables t1, t2, t3, t4, t5, t6, t7, t8, t9 and the
+# slave is started with the following replication table filter rules:
+#
+# SET @@GLOBAL.replicate_do_table="test.t1,test.t2,test.t3";
+#
+# and
+#
+# SET @@GLOBAL.replicate_ignore_table="test.t4,test.t5,test.t6";
+#
+# So the slave only replicate changes to tables t1, t2 and t3 and only
+# these tables exist on slave.
+#
+# From now on, tables t1, t2, and t3 are referenced as do tables,
+# tables t4, t5, t6 are referenced as ignore tables, and tables t7,
+# t8, t9 are referenced as other tables.
+#
+# All multi-table update tests reference tables that are not do
+# tables, which do not exist on slave. And the following situations
+# of multi-table update will be tested:
+#
+# 1. Do tables are not referenced at all
+# 2. Do tables are not referenced for update
+# 3. Ignore tables are referenced for update before do tables
+# 4. Only do tables are referenced for update
+# 5. Do tables and other tables are referenced for update
+# 6. Do tables are referenced for update before ignore tables
+#
+# For 1, 2 and 3, the statement should be ignored by slave, for 4, 5
+# and 6 the statement should be accepted by slave and cause an error
+# because of non-exist tables.
+#
+
+source include/have_binlog_format_statement.inc;
+source include/master-slave.inc;
+
+connection slave;
+--error ER_SLAVE_MUST_STOP
+SET @@GLOBAL.replicate_do_table="test.t1,test.t2,test.t3";
+--error ER_SLAVE_MUST_STOP
+SET @@GLOBAL.replicate_ignore_table="test.t4,test.t5,test.t6";
+
+connection slave;
+source include/stop_slave.inc;
+SET @@GLOBAL.replicate_do_table="";
+SET @@GLOBAL.replicate_ignore_table="";
+SET @@GLOBAL.replicate_do_table="test.t1,test.t2,test.t3";
+SET @@GLOBAL.replicate_ignore_table="test.t4,test.t5,test.t6";
+source include/start_slave.inc;
+connection master;
+
+# These tables are mentioned in do-table rules
+CREATE TABLE t1 (id int, a int);
+CREATE TABLE t2 (id int, b int);
+CREATE TABLE t3 (id int, c int);
+
+# These tables are mentioned in ignore-table rules
+CREATE TABLE t4 (id int, d int);
+CREATE TABLE t5 (id int, e int);
+CREATE TABLE t6 (id int, f int);
+
+# These tables are not mentioned in do-table or ignore-table rules
+CREATE TABLE t7 (id int, g int);
+CREATE TABLE t8 (id int, h int);
+CREATE TABLE t9 (id int, i int);
+
+INSERT INTO t1 VALUES (1, 1), (2, 2), (3, 3);
+INSERT INTO t2 VALUES (1, 1), (2, 2), (3, 3);
+INSERT INTO t3 VALUES (1, 1), (2, 2), (3, 3);
+
+INSERT INTO t4 VALUES (1, 1), (2, 2), (3, 3);
+INSERT INTO t5 VALUES (1, 1), (2, 2), (3, 3);
+INSERT INTO t6 VALUES (1, 1), (2, 2), (3, 3);
+
+INSERT INTO t7 VALUES (1, 1), (2, 2), (3, 3);
+INSERT INTO t8 VALUES (1, 1), (2, 2), (3, 3);
+INSERT INTO t9 VALUES (1, 1), (2, 2), (3, 3);
+
+# Only t1, t2, t3 should be replicated to slave
+sync_slave_with_master;
+SHOW TABLES LIKE 't%';
+
+connection master;
+
+#
+# Do tables are not referenced, these statements should be ignored by
+# slave.
+#
+UPDATE t7 LEFT JOIN t4 ON (t4.id=t7.id) SET d=0, g=0 where t7.id=1;
+UPDATE t7 LEFT JOIN (t4, t5, t6) ON (t7.id=t4.id and t7.id=t5.id and t7.id=t6.id) SET d=0, e=0, f=0, g=0 where t7.id=1;
+UPDATE t4 LEFT JOIN (t7, t8, t9) ON (t4.id=t7.id and t4.id=t8.id and t4.id=t9.id) SET d=0, g=0, h=0, i=0 where t4.id=1;
+UPDATE t7 LEFT JOIN (t8, t9) ON (t7.id=t8.id and t7.id=t9.id) SET g=0, h=0, i=0 where t7.id=1;
+
+#
+# Do tables are not referenced for update, these statements should be
+# ignored by slave.
+#
+UPDATE t1 LEFT JOIN t4 ON (t1.id=t4.id) SET d=0 where t1.id=1;
+UPDATE t1 LEFT JOIN t7 ON (t1.id=t7.id) SET g=0 where t1.id=1;
+UPDATE t1 LEFT JOIN (t4, t5, t6) ON (t1.id=t4.id and t1.id=t5.id and t1.id=t6.id) SET d=0, e=0, f=0 where t1.id=1;
+UPDATE t1 LEFT JOIN (t4, t5, t8) ON (t1.id=t4.id and t1.id=t5.id and t1.id=t8.id) SET d=0, e=0, h=0 where t1.id=1;
+UPDATE t1 LEFT JOIN (t7, t8, t5) ON (t1.id=t7.id and t1.id=t8.id and t1.id=t5.id) SET g=0, h=0, e=0 where t1.id=1;
+UPDATE t1 LEFT JOIN (t2, t3, t5) ON (t1.id=t2.id and t1.id=t3.id and t1.id=t5.id) SET e=0 where t1.id=1;
+
+#
+# Ignore tables are referenced for update before do tables, these
+# statements should be ignore by slave.
+#
+UPDATE t4 LEFT JOIN t1 ON (t1.id=t4.id) SET a=0, d=0 where t4.id=1;
+UPDATE t4 LEFT JOIN (t1, t7) ON (t4.id=t1.id and t7.id=t4.id) SET a = 0, d=0, g=0 where t4.id=1;
+UPDATE t4 LEFT JOIN (t1, t2, t3) ON (t1.id=t4.id and t2.id=t4.id and t3.id=t4.id) SET a=0, b=0, c=0, d=0 where t4.id=1;
+UPDATE t4 LEFT JOIN (t1, t2, t5) ON (t1.id=t4.id and t2.id=t4.id and t5.id=t4.id) SET a=0, b=0, e=0, d=0 where t4.id=1;
+UPDATE t4 LEFT JOIN (t1, t6, t7) ON (t4.id=t1.id and t4.id=t6.id and t4.id=t7.id) SET a=0, d=0, f=0, g=0 where t4.id=1;
+UPDATE t7 LEFT JOIN (t4, t1, t2) ON (t7.id=t4.id and t7.id=t1.id and t7.id=t2.id) SET a=0, b=0, d=0, g=0 where t7.id=1;
+UPDATE t7 LEFT JOIN (t8, t4, t1) ON (t7.id=t8.id and t7.id=t4.id and t7.id=t1.id) SET a=0, d=0, g=0, h=0 where t7.id=1;
+
+# Sync slave to make sure all above statements are correctly ignored,
+# if any of the above statement are not ignored, it would cause error
+# and stop slave sql thread.
+sync_slave_with_master;
+connection slave;
+call mtr.add_suppression("Slave SQL.*Error .Table .test.t[47]. doesn.t exist. on query.* error.* 1146");
+connection master;
+
+# Parameters for include/wait_for_slave_sql_error_and_skip.inc:
+# Ask it to show SQL error message.
+let $show_slave_sql_error= 1;
+# The expected error will always be 1146 (ER_NO_SUCH_TABLE).
+let $slave_sql_errno= 1146;
+
+#
+# Only do tables are referenced for update, these statements should
+# cause error on slave
+#
+UPDATE t1 LEFT JOIN t4 ON (t1.id=t4.id) SET a=0 where t1.id=1;
+source include/wait_for_slave_sql_error_and_skip.inc;
+
+UPDATE t1 LEFT JOIN (t4, t7) ON (t1.id=t4.id and t1.id=t7.id) SET a=0 where t1.id=1;
+source include/wait_for_slave_sql_error_and_skip.inc;
+
+UPDATE t1 LEFT JOIN (t2, t4, t7) ON (t1.id=t2.id and t1.id=t4.id and t1.id=t7.id) SET a=0, b=0 where t1.id=1;
+source include/wait_for_slave_sql_error_and_skip.inc;
+
+UPDATE t1 LEFT JOIN (t2, t3, t7) ON (t1.id=t2.id and t1.id=t3.id and t1.id=t7.id) SET a=0, b=0, c=0 where t1.id=1;
+source include/wait_for_slave_sql_error_and_skip.inc;
+
+#
+# Do tables and other tables are referenced for update, these
+# statements should cause error on slave
+#
+UPDATE t1 LEFT JOIN t7 ON (t1.id=t7.id) SET a=0, g=0 where t1.id=1;
+source include/wait_for_slave_sql_error_and_skip.inc;
+
+UPDATE t7 LEFT JOIN t1 ON (t1.id=t7.id) SET a=0, g=0 where t7.id=1;
+source include/wait_for_slave_sql_error_and_skip.inc;
+
+UPDATE t1 LEFT JOIN (t4, t5, t7) ON (t1.id=t4.id and t1.id=t5.id and t1.id=t7.id) SET a=0, g=0 where t1.id=1;
+source include/wait_for_slave_sql_error_and_skip.inc;
+
+UPDATE t1 LEFT JOIN (t4, t7, t8) ON (t1.id=t4.id and t1.id=t7.id and t1.id=t8.id) SET a=0, g=0 where t1.id=1;
+source include/wait_for_slave_sql_error_and_skip.inc;
+
+UPDATE t1 LEFT JOIN (t7, t8, t9) ON (t1.id=t7.id and t1.id=t8.id and t1.id=t9.id) SET a=0, g=0, h=0, i=0 where t1.id=1;
+source include/wait_for_slave_sql_error_and_skip.inc;
+
+UPDATE t7 LEFT JOIN (t1, t2, t3) ON (t7.id=t1.id and t7.id=t2.id and t7.id=t3.id) SET g=0, a=0, b=0, c=0 where t7.id=1;
+source include/wait_for_slave_sql_error_and_skip.inc;
+
+UPDATE t7 LEFT JOIN (t4, t5, t3) ON (t7.id=t4.id and t7.id=t5.id and t7.id=t3.id) SET g=0, c=0 where t7.id=1;
+source include/wait_for_slave_sql_error_and_skip.inc;
+
+UPDATE t7 LEFT JOIN (t8, t9, t3) ON (t7.id=t8.id and t7.id=t9.id and t7.id=t3.id) SET g=0, h=0, i=0, c=0 where t7.id=1;
+source include/wait_for_slave_sql_error_and_skip.inc;
+
+#
+# Do tables are referenced for update before ignore tables
+#
+UPDATE t1 LEFT JOIN t4 ON (t1.id=t4.id) SET a=0, d=0 where t1.id=1;
+source include/wait_for_slave_sql_error_and_skip.inc;
+
+UPDATE t1 LEFT JOIN (t4, t5, t6) ON (t1.id=t4.id and t1.id=t5.id and t1.id=t6.id) SET a=0, d=0, e=0, f=0 where t1.id=1;
+source include/wait_for_slave_sql_error_and_skip.inc;
+
+UPDATE t4 LEFT JOIN (t1, t5, t6) ON (t4.id=t1.id and t4.id=t5.id and t4.id=t6.id) SET a=0, e=0, f=0 where t4.id=1;
+source include/wait_for_slave_sql_error_and_skip.inc;
+
+UPDATE t7 LEFT JOIN (t1, t4, t2) ON (t7.id=t1.id and t7.id=t4.id and t7.id=t2.id) SET a=0, b=0, d=0, g=0 where t7.id=1;
+source include/wait_for_slave_sql_error_and_skip.inc;
+
+sync_slave_with_master;
+echo [on slave];
+
+# We should only have tables t1, t2, t3 on slave
+show tables like 't%';
+
+# The rows in these tables should remain untouched
+SELECT * FROM t1;
+SELECT * FROM t2;
+SELECT * FROM t3;
+
+# Clean up
+connection master;
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+--source include/rpl_end.inc
+
+connection slave;
+SET @@GLOBAL.replicate_do_table="";
+SET @@GLOBAL.replicate_ignore_table="";
diff --git a/mysql-test/suite/rpl/t/rpl_filter_tables_not_exist-slave.opt b/mysql-test/suite/rpl/t/rpl_filter_tables_not_exist-slave.opt
new file mode 100644
index 00000000..42acd3ea
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_filter_tables_not_exist-slave.opt
@@ -0,0 +1 @@
+--replicate-do-table=test.t1 --replicate-do-table=test.t2 --replicate-do-table=test.t3 --replicate-ignore-table=test.t4 --replicate-ignore-table=test.t5 --replicate-ignore-table=test.t6
diff --git a/mysql-test/suite/rpl/t/rpl_filter_tables_not_exist.test b/mysql-test/suite/rpl/t/rpl_filter_tables_not_exist.test
new file mode 100644
index 00000000..ee6daac7
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_filter_tables_not_exist.test
@@ -0,0 +1,267 @@
+# Test evaluation of replication table filter rules
+#
+# ==== Purpose ====
+#
+# Test if replication table filter rules are properly evaluated when
+# some of the tables referenced by the multiple-table update do not
+# exist on slave.
+#
+# ==== Method ====
+#
+# Master creates tables t1, t2, t3, t4, t5, t6, t7, t8, t9 and the
+# slave is started with the following replication table filter rules:
+#
+# --replicate-do-table=t1
+# --replicate-do-table=t2
+# --replicate-do-table=t3
+#
+# and
+#
+# --replicate-ignore-table=t4
+# --replicate-ignore-table=t5
+# --replicate-ignore-table=t6
+#
+# So the slave only replicate changes to tables t1, t2 and t3 and only
+# these tables exist on slave.
+#
+# From now on, tables t1, t2, and t3 are referenced as do tables,
+# tables t4, t5, t6 are referenced as ignore tables, and tables t7,
+# t8, t9 are referenced as other tables.
+#
+# All multi-table update tests reference tables that are not do
+# tables, which do not exist on slave. And the following situations
+# of multi-table update will be tested:
+#
+# 1. Do tables are not referenced at all
+# 2. Do tables are not referenced for update
+# 3. Ignore tables are referenced for update before do tables
+# 4. Only do tables are referenced for update
+# 5. Do tables and other tables are referenced for update
+# 6. Do tables are referenced for update before ignore tables
+#
+# For 1, 2 and 3, the statement should be ignored by slave, for 4, 5
+# and 6 the statement should be accepted by slave and cause an error
+# because of non-exist tables.
+#
+# ==== Related bugs ====
+#
+# BUG#37051 Replication rules not evaluated correctly
+
+
+source include/have_binlog_format_statement.inc;
+source include/master-slave.inc;
+
+# These tables are mentioned in do-table rules
+CREATE TABLE t1 (id int, a int);
+CREATE TABLE t2 (id int, b int);
+CREATE TABLE t3 (id int, c int);
+
+# These tables are mentioned in ignore-table rules
+CREATE TABLE t4 (id int, d int);
+CREATE TABLE t5 (id int, e int);
+CREATE TABLE t6 (id int, f int);
+
+# These tables are not mentioned in do-table or ignore-table rules
+CREATE TABLE t7 (id int, g int);
+CREATE TABLE t8 (id int, h int);
+CREATE TABLE t9 (id int, i int);
+
+INSERT INTO t1 VALUES (1, 1), (2, 2), (3, 3);
+INSERT INTO t2 VALUES (1, 1), (2, 2), (3, 3);
+INSERT INTO t3 VALUES (1, 1), (2, 2), (3, 3);
+
+INSERT INTO t4 VALUES (1, 1), (2, 2), (3, 3);
+INSERT INTO t5 VALUES (1, 1), (2, 2), (3, 3);
+INSERT INTO t6 VALUES (1, 1), (2, 2), (3, 3);
+
+INSERT INTO t7 VALUES (1, 1), (2, 2), (3, 3);
+INSERT INTO t8 VALUES (1, 1), (2, 2), (3, 3);
+INSERT INTO t9 VALUES (1, 1), (2, 2), (3, 3);
+
+# Only t1, t2, t3 should be replicated to slave
+sync_slave_with_master;
+SHOW TABLES LIKE 't%';
+
+connection master;
+
+#
+# Do tables are not referenced, these statements should be ignored by
+# slave.
+#
+UPDATE t7 LEFT JOIN t4 ON (t4.id=t7.id) SET d=0, g=0 where t7.id=1;
+UPDATE t7 LEFT JOIN (t4, t5, t6) ON (t7.id=t4.id and t7.id=t5.id and t7.id=t6.id) SET d=0, e=0, f=0, g=0 where t7.id=1;
+UPDATE t4 LEFT JOIN (t7, t8, t9) ON (t4.id=t7.id and t4.id=t8.id and t4.id=t9.id) SET d=0, g=0, h=0, i=0 where t4.id=1;
+UPDATE t7 LEFT JOIN (t8, t9) ON (t7.id=t8.id and t7.id=t9.id) SET g=0, h=0, i=0 where t7.id=1;
+
+#
+# Do tables are not referenced for update, these statements should be
+# ignored by slave.
+#
+UPDATE t1 LEFT JOIN t4 ON (t1.id=t4.id) SET d=0 where t1.id=1;
+UPDATE t1 LEFT JOIN t7 ON (t1.id=t7.id) SET g=0 where t1.id=1;
+UPDATE t1 LEFT JOIN (t4, t5, t6) ON (t1.id=t4.id and t1.id=t5.id and t1.id=t6.id) SET d=0, e=0, f=0 where t1.id=1;
+UPDATE t1 LEFT JOIN (t4, t5, t8) ON (t1.id=t4.id and t1.id=t5.id and t1.id=t8.id) SET d=0, e=0, h=0 where t1.id=1;
+UPDATE t1 LEFT JOIN (t7, t8, t5) ON (t1.id=t7.id and t1.id=t8.id and t1.id=t5.id) SET g=0, h=0, e=0 where t1.id=1;
+UPDATE t1 LEFT JOIN (t2, t3, t5) ON (t1.id=t2.id and t1.id=t3.id and t1.id=t5.id) SET e=0 where t1.id=1;
+
+#
+# Ignore tables are referenced for update before do tables, these
+# statements should be ignore by slave.
+#
+UPDATE t4 LEFT JOIN t1 ON (t1.id=t4.id) SET a=0, d=0 where t4.id=1;
+UPDATE t4 LEFT JOIN (t1, t7) ON (t4.id=t1.id and t7.id=t4.id) SET a = 0, d=0, g=0 where t4.id=1;
+UPDATE t4 LEFT JOIN (t1, t2, t3) ON (t1.id=t4.id and t2.id=t4.id and t3.id=t4.id) SET a=0, b=0, c=0, d=0 where t4.id=1;
+UPDATE t4 LEFT JOIN (t1, t2, t5) ON (t1.id=t4.id and t2.id=t4.id and t5.id=t4.id) SET a=0, b=0, e=0, d=0 where t4.id=1;
+UPDATE t4 LEFT JOIN (t1, t6, t7) ON (t4.id=t1.id and t4.id=t6.id and t4.id=t7.id) SET a=0, d=0, f=0, g=0 where t4.id=1;
+UPDATE t7 LEFT JOIN (t4, t1, t2) ON (t7.id=t4.id and t7.id=t1.id and t7.id=t2.id) SET a=0, b=0, d=0, g=0 where t7.id=1;
+UPDATE t7 LEFT JOIN (t8, t4, t1) ON (t7.id=t8.id and t7.id=t4.id and t7.id=t1.id) SET a=0, d=0, g=0, h=0 where t7.id=1;
+
+# Sync slave to make sure all above statements are correctly ignored,
+# if any of the above statement are not ignored, it would cause error
+# and stop slave sql thread.
+sync_slave_with_master;
+connection slave;
+call mtr.add_suppression("Slave SQL.*Error .Table .test.t[47]. doesn.t exist. on query.* error.* 1146");
+connection master;
+
+# Parameters for include/wait_for_slave_sql_error_and_skip.inc:
+# Ask it to show SQL error message.
+let $show_slave_sql_error= 1;
+# The expected error will always be 1146 (ER_NO_SUCH_TABLE).
+let $slave_sql_errno= 1146;
+
+#
+# Only do tables are referenced for update, these statements should
+# cause error on slave
+#
+UPDATE t1 LEFT JOIN t4 ON (t1.id=t4.id) SET a=0 where t1.id=1;
+source include/wait_for_slave_sql_error_and_skip.inc;
+
+UPDATE t1 LEFT JOIN (t4, t7) ON (t1.id=t4.id and t1.id=t7.id) SET a=0 where t1.id=1;
+source include/wait_for_slave_sql_error_and_skip.inc;
+
+UPDATE t1 LEFT JOIN (t2, t4, t7) ON (t1.id=t2.id and t1.id=t4.id and t1.id=t7.id) SET a=0, b=0 where t1.id=1;
+source include/wait_for_slave_sql_error_and_skip.inc;
+
+UPDATE t1 LEFT JOIN (t2, t3, t7) ON (t1.id=t2.id and t1.id=t3.id and t1.id=t7.id) SET a=0, b=0, c=0 where t1.id=1;
+source include/wait_for_slave_sql_error_and_skip.inc;
+
+#
+# Do tables and other tables are referenced for update, these
+# statements should cause error on slave
+#
+UPDATE t1 LEFT JOIN t7 ON (t1.id=t7.id) SET a=0, g=0 where t1.id=1;
+source include/wait_for_slave_sql_error_and_skip.inc;
+
+UPDATE t7 LEFT JOIN t1 ON (t1.id=t7.id) SET a=0, g=0 where t7.id=1;
+source include/wait_for_slave_sql_error_and_skip.inc;
+
+UPDATE t1 LEFT JOIN (t4, t5, t7) ON (t1.id=t4.id and t1.id=t5.id and t1.id=t7.id) SET a=0, g=0 where t1.id=1;
+source include/wait_for_slave_sql_error_and_skip.inc;
+
+UPDATE t1 LEFT JOIN (t4, t7, t8) ON (t1.id=t4.id and t1.id=t7.id and t1.id=t8.id) SET a=0, g=0 where t1.id=1;
+source include/wait_for_slave_sql_error_and_skip.inc;
+
+UPDATE t1 LEFT JOIN (t7, t8, t9) ON (t1.id=t7.id and t1.id=t8.id and t1.id=t9.id) SET a=0, g=0, h=0, i=0 where t1.id=1;
+source include/wait_for_slave_sql_error_and_skip.inc;
+
+UPDATE t7 LEFT JOIN (t1, t2, t3) ON (t7.id=t1.id and t7.id=t2.id and t7.id=t3.id) SET g=0, a=0, b=0, c=0 where t7.id=1;
+source include/wait_for_slave_sql_error_and_skip.inc;
+
+UPDATE t7 LEFT JOIN (t4, t5, t3) ON (t7.id=t4.id and t7.id=t5.id and t7.id=t3.id) SET g=0, c=0 where t7.id=1;
+source include/wait_for_slave_sql_error_and_skip.inc;
+
+UPDATE t7 LEFT JOIN (t8, t9, t3) ON (t7.id=t8.id and t7.id=t9.id and t7.id=t3.id) SET g=0, h=0, i=0, c=0 where t7.id=1;
+source include/wait_for_slave_sql_error_and_skip.inc;
+
+#
+# Do tables are referenced for update before ignore tables
+#
+UPDATE t1 LEFT JOIN t4 ON (t1.id=t4.id) SET a=0, d=0 where t1.id=1;
+source include/wait_for_slave_sql_error_and_skip.inc;
+
+UPDATE t1 LEFT JOIN (t4, t5, t6) ON (t1.id=t4.id and t1.id=t5.id and t1.id=t6.id) SET a=0, d=0, e=0, f=0 where t1.id=1;
+source include/wait_for_slave_sql_error_and_skip.inc;
+
+UPDATE t4 LEFT JOIN (t1, t5, t6) ON (t4.id=t1.id and t4.id=t5.id and t4.id=t6.id) SET a=0, e=0, f=0 where t4.id=1;
+source include/wait_for_slave_sql_error_and_skip.inc;
+
+UPDATE t7 LEFT JOIN (t1, t4, t2) ON (t7.id=t1.id and t7.id=t4.id and t7.id=t2.id) SET a=0, b=0, d=0, g=0 where t7.id=1;
+source include/wait_for_slave_sql_error_and_skip.inc;
+
+sync_slave_with_master;
+echo [on slave];
+
+# We should only have tables t1, t2, t3 on slave
+show tables like 't%';
+
+# The rows in these tables should remain untouched
+SELECT * FROM t1;
+SELECT * FROM t2;
+SELECT * FROM t3;
+
+# Clean up
+connection master;
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+
+--sync_slave_with_master
+
+#
+# BUG#11754117 - 45670: INTVAR_EVENTS FOR FILTERED-OUT QUERY_LOG_EVENTS ARE EXECUTED
+# Int-, Rand- and User- var events accompaning a filtered out Query-log-event should
+# be filtered as well.
+#
+connection master;
+# Although RAND() is from 0 to 1.0, DECIMAL(M,D), requires that M must be >= D.
+CREATE TABLE test.t5 (a INT AUTO_INCREMENT PRIMARY KEY, b DECIMAL(20,20), c INT); # ignored on slave
+CREATE TABLE test.t1 (a INT); # accepted on slave
+INSERT INTO test.t1 VALUES(1);
+
+--sync_slave_with_master
+call mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT");
+# Although RAND() is from 0 to 1.0, DECIMAL(M,D), requires that M must be >= D.
+CREATE TABLE test.t_slave (a INT AUTO_INCREMENT PRIMARY KEY, b DECIMAL(20,20), c INT);
+CREATE TRIGGER t1_update AFTER UPDATE ON test.t1 FOR EACH ROW
+ INSERT INTO test.t_slave VALUES(NULL, RAND(), @c);
+
+connection master;
+SET INSERT_ID=2;
+SET @c=2;
+SET @@rand_seed1=10000000, @@rand_seed2=1000000;
+INSERT INTO t5 VALUES (NULL, RAND(), @c); # to be ignored
+SELECT b into @b FROM test.t5;
+--let $b_master=`select @b`
+UPDATE test.t1 SET a=2; # to run trigger on slave
+
+--sync_slave_with_master
+
+# The proof:
+SELECT a AS 'ONE' into @a FROM test.t_slave;
+SELECT c AS 'NULL' into @c FROM test.t_slave;
+
+let $count= 1;
+let $table= test.t_slave;
+source include/wait_until_rows_count.inc;
+
+if (`SELECT @a != 2 and @c != NULL`)
+{
+ SELECT * FROM test.t_slave;
+ --die Intvar or user var from replication events unexpetedly escaped out to screw a following query applying context.
+}
+
+SELECT b into @b FROM test.t_slave;
+--let $b_slave=`select @b`
+
+--let $assert_text= Random values from master and slave must be different
+--let $assert_cond= $b_master != $b_slave
+--source include/assert.inc
+
+# cleanup BUG#11754117
+connection master;
+drop table test.t5;
+drop table test.t1;
+
+--sync_slave_with_master
+drop table test.t_slave;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_filter_wild_tables_dynamic.test b/mysql-test/suite/rpl/t/rpl_filter_wild_tables_dynamic.test
new file mode 100644
index 00000000..657a95ce
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_filter_wild_tables_dynamic.test
@@ -0,0 +1,49 @@
+#
+# Test if dynamic replication wild table filter rules are properly evaluated.
+#
+
+source include/have_binlog_format_statement.inc;
+source include/master-slave.inc;
+
+connection slave;
+--error ER_SLAVE_MUST_STOP
+SET @@GLOBAL.replicate_wild_do_table="test.a%";
+--error ER_SLAVE_MUST_STOP
+SET @@GLOBAL.replicate_wild_ignore_table="test.b%";
+
+connection slave;
+source include/stop_slave.inc;
+SET @@GLOBAL.replicate_wild_do_table="";
+SET @@GLOBAL.replicate_wild_ignore_table="";
+SET @@GLOBAL.replicate_wild_do_table="test.a%";
+SET @@GLOBAL.replicate_wild_ignore_table="test.b%";
+source include/start_slave.inc;
+connection master;
+
+# Table is mentioned in wild-do-table rules
+CREATE TABLE a1 (a INT);
+
+# Table is mentioned in wild-ignore-table rules
+CREATE TABLE b1 (a INT);
+
+# Table is not mentioned in wild-do-table or wild-ignore-table rules
+CREATE TABLE c1 (a INT);
+
+INSERT INTO a1 VALUES (1);
+INSERT INTO b1 VALUES (2);
+INSERT INTO c1 VALUES (3);
+
+# Only a1 should be replicated to slave
+sync_slave_with_master;
+SHOW TABLES LIKE '%1';
+
+connection master;
+
+# Clean up
+connection master;
+DROP TABLE IF EXISTS a1,b1,c1;
+--source include/rpl_end.inc
+
+connection slave;
+SET @@GLOBAL.replicate_wild_do_table="";
+SET @@GLOBAL.replicate_wild_ignore_table="";
diff --git a/mysql-test/suite/rpl/t/rpl_flush_logs-master.opt b/mysql-test/suite/rpl/t/rpl_flush_logs-master.opt
new file mode 100644
index 00000000..36eab1d6
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_flush_logs-master.opt
@@ -0,0 +1 @@
+--log-error=$MYSQLTEST_VARDIR/tmp/master_log.err
diff --git a/mysql-test/suite/rpl/t/rpl_flush_logs.test b/mysql-test/suite/rpl/t/rpl_flush_logs.test
new file mode 100644
index 00000000..6dad588f
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_flush_logs.test
@@ -0,0 +1,141 @@
+#
+# WL#5124
+# This test verifies if the 'flush individual logs' statement
+# works fine.
+#
+
+--source include/have_binlog_format_statement.inc
+--source include/master-slave.inc
+connection master;
+
+# Test 'flush error logs' statement.
+
+--echo # Test if support 'flush error logs' statement.
+flush error logs;
+
+file_exists $MYSQLTEST_VARDIR/tmp/master_log.err;
+
+--echo # Make sure binary logs was not be flushed
+--echo # after execute 'flush error logs' statement.
+--error 1
+file_exists $MYSQLTEST_VARDIR/mysqld.1/data/master-bin.000002;
+
+sync_slave_with_master;
+--echo # Make sure relay logs was not be flushed
+--echo # after execute 'flush error logs' statement.
+--error 1
+file_exists $MYSQLTEST_VARDIR/mysqld.2/data/slave-relay-bin.000003;
+
+connection master;
+--echo # Test if support 'flush relay logs' statement.
+flush relay logs;
+
+sync_slave_with_master;
+--echo # Check the 'slave-relay-bin.000003' file is not created
+--echo # after executed 'flush relay logs' statement.
+--error 1
+file_exists $MYSQLTEST_VARDIR/mysqld.2/data/slave-relay-bin.000003;
+
+connection master;
+--echo # Make sure binary logs was not be flushed
+--echo # after execute 'flush relay logs' statement.
+--error 1
+file_exists $MYSQLTEST_VARDIR/mysqld.1/data/master-bin.000002;
+
+
+# Test 'flush slow logs' statement.
+--echo # Test if support 'flush slow logs' statement.
+flush slow logs;
+
+--echo # Make sure binary logs was not be flushed
+--echo # after execute 'flush slow logs' statement.
+--error 1
+file_exists $MYSQLTEST_VARDIR/mysqld.1/data/master-bin.000002;
+
+
+# Test 'flush general logs' statement.
+--echo # Test if support 'flush general logs' statement.
+flush general logs;
+
+--echo # Make sure binary logs was not be flushed
+--echo # after execute 'flush general logs' statement.
+--error 1
+file_exists $MYSQLTEST_VARDIR/mysqld.1/data/master-bin.000002;
+
+
+# Test 'flush engine logs' statement.
+--echo # Test if support 'flush engine logs' statement.
+flush engine logs;
+
+--echo # Make sure binary logs was not be flushed
+--echo # after execute 'flush engine logs' statement.
+--error 1
+file_exists $MYSQLTEST_VARDIR/mysqld.1/data/master-bin.000002;
+
+
+# Test 'flush binary logs' statement.
+--echo # Make sure the 'master-bin.000002' file does not
+--echo # exist before execute 'flush binary logs' statement.
+--error 1
+file_exists $MYSQLTEST_VARDIR/mysqld.1/data/master-bin.000002;
+
+--echo # Test if support 'flush binary logs' statement.
+flush binary logs;
+
+--echo # Check the 'master-bin.000002' file is created
+--echo # after executed 'flush binary logs' statement.
+file_exists $MYSQLTEST_VARDIR/mysqld.1/data/master-bin.000002;
+file_exists $MYSQLTEST_VARDIR/mysqld.1/data/master-bin.000001;
+
+
+# Test 'flush error logs, relay logs' statement
+sync_slave_with_master;
+--echo # Make sure the 'slave-relay-bin.000005' file does not exist
+--echo # exist before execute 'flush error logs, relay logs' statement.
+--error 1
+file_exists $MYSQLTEST_VARDIR/mysqld.2/data/slave-relay-bin.000005;
+
+connection master;
+
+--echo # Test if support to combine all kinds of logs into one statement.
+flush error logs, relay logs;
+
+file_exists $MYSQLTEST_VARDIR/tmp/master_log.err;
+
+--echo # Make sure binary logs was not be flushed
+--echo # after execute 'flush error logs, relay logs' statement.
+--error 1
+file_exists $MYSQLTEST_VARDIR/mysqld.1/data/master-bin.000003;
+
+sync_slave_with_master;
+--echo # Check the 'slave-relay-bin.000004' file is created after
+--echo # execute 'flush error logs, relay logs' statement.
+file_exists $MYSQLTEST_VARDIR/mysqld.2/data/slave-relay-bin.000004;
+
+# Test 'flush logs' statement
+--echo # Make sure the 'slave-relay-bin.000005' and 'slave-relay-bin.000006'
+--echo # files do not exist before execute 'flush error logs, relay logs'
+--echo # statement.
+--error 1
+file_exists $MYSQLTEST_VARDIR/mysqld.2/data/slave-relay-bin.000005;
+--error 1
+file_exists $MYSQLTEST_VARDIR/mysqld.2/data/slave-relay-bin.000006;
+
+connection master;
+
+--echo # Test if 'flush logs' statement works fine and flush all the logs.
+flush logs;
+
+file_exists $MYSQLTEST_VARDIR/tmp/master_log.err;
+
+--echo # Check 'master-bin.000003' is created
+--echo # after execute 'flush logs' statement.
+file_exists $MYSQLTEST_VARDIR/mysqld.1/data/master-bin.000003;
+
+sync_slave_with_master;
+--echo # Check the 'slave-relay-bin.000005' and 'slave-relay-bin.000006'
+--echo # files are created after execute 'flush logs' statement.
+file_exists $MYSQLTEST_VARDIR/mysqld.2/data/slave-relay-bin.000005;
+file_exists $MYSQLTEST_VARDIR/mysqld.2/data/slave-relay-bin.000006;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_flushlog_loop-master.opt b/mysql-test/suite/rpl/t/rpl_flushlog_loop-master.opt
new file mode 100644
index 00000000..3b5d41d4
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_flushlog_loop-master.opt
@@ -0,0 +1 @@
+--max_binlog_size=1M
diff --git a/mysql-test/suite/rpl/t/rpl_flushlog_loop-slave.opt b/mysql-test/suite/rpl/t/rpl_flushlog_loop-slave.opt
new file mode 100644
index 00000000..3b5d41d4
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_flushlog_loop-slave.opt
@@ -0,0 +1 @@
+--max_binlog_size=1M
diff --git a/mysql-test/suite/rpl/t/rpl_flushlog_loop.test b/mysql-test/suite/rpl/t/rpl_flushlog_loop.test
new file mode 100644
index 00000000..d5d362ba
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_flushlog_loop.test
@@ -0,0 +1,46 @@
+# Testing if "flush logs" command bouncing resulting in logs created in a loop
+# in case of bi-directional replication
+--let $rpl_topology= 1->2->1
+--source include/rpl_init.inc
+
+let $MYSQLD_DATADIR= `select @@datadir`;
+--replace_result $MYSQLD_DATADIR MYSQLD_DATADIR/
+show variables like 'relay_log%';
+
+#
+# Flush logs of slave
+#
+# Create full loop by following way:
+# 1. Insert into t1 on master (1st).
+# 2. Insert into t1 on slave (2nd) when the event (1st) for t1 replicated.
+# 3. Master waits until the event (2nd) for t1 will be replicated.
+
+CREATE TABLE t1 (a INT KEY) ENGINE= MyISAM;
+let $wait_binlog_event= CREATE TABLE t1;
+--source include/wait_for_binlog_event.inc
+sync_slave_with_master server_2;
+
+connection server_1;
+INSERT INTO t1 VALUE(1);
+FLUSH LOGS;
+sync_slave_with_master server_2;
+
+INSERT INTO t1 VALUE(2);
+let $slave_param_value= query_get_value(SHOW MASTER STATUS, Position, 1);
+sync_slave_with_master server_1;
+
+#
+# Check that the master server's slave threads are still running and show
+# Relay_Log_File
+#
+--source include/check_slave_is_running.inc
+--let status_items= Relay_Log_File
+--source include/show_slave_status.inc
+
+--disable_query_log
+connection server_1;
+DROP TABLE t1;
+sync_slave_with_master server_2;
+--enable_query_log
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_foreign_key_innodb.test b/mysql-test/suite/rpl/t/rpl_foreign_key_innodb.test
new file mode 100644
index 00000000..2c4af75e
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_foreign_key_innodb.test
@@ -0,0 +1,78 @@
+-- source include/have_innodb.inc
+
+# Check the replication of the FOREIGN_KEY_CHECKS variable.
+
+-- source include/master-slave.inc
+
+CREATE TABLE t1 (a INT AUTO_INCREMENT KEY) ENGINE=INNODB;
+CREATE TABLE t2 (b INT AUTO_INCREMENT KEY, c INT, FOREIGN KEY(b) REFERENCES t1(a)) ENGINE=INNODB;
+
+SET FOREIGN_KEY_CHECKS=0;
+INSERT INTO t1 VALUES (10);
+INSERT INTO t1 VALUES (NULL),(NULL),(NULL);
+INSERT INTO t2 VALUES (5,0);
+INSERT INTO t2 VALUES (NULL,LAST_INSERT_ID());
+SET FOREIGN_KEY_CHECKS=1;
+SELECT * FROM t1 ORDER BY a;
+SELECT * FROM t2 ORDER BY b;
+sync_slave_with_master;
+SELECT * FROM t1 ORDER BY a;
+SELECT * FROM t2 ORDER BY b;
+
+connection master;
+SET TIMESTAMP=1000000000;
+CREATE TABLE t3 ( a INT UNIQUE );
+SET FOREIGN_KEY_CHECKS=0;
+--error ER_DUP_ENTRY
+INSERT INTO t3 VALUES (1),(1);
+sync_slave_with_master;
+
+connection master;
+SET FOREIGN_KEY_CHECKS=0;
+DROP TABLE IF EXISTS t1,t2,t3;
+SET FOREIGN_KEY_CHECKS=1;
+sync_slave_with_master;
+
+#
+# Bug #32468 delete rows event on a table with foreign key constraint fails
+#
+
+connection master;
+
+create table t1 (b int primary key) engine = INNODB;
+create table t2 (a int primary key, b int, foreign key (b) references t1(b)) engine = INNODB;
+
+insert into t1 set b=1;
+insert into t2 set a=1, b=1;
+
+set foreign_key_checks=0;
+delete from t1;
+
+--echo must sync w/o a problem (could not with the buggy code)
+sync_slave_with_master;
+select count(*) from t1 /* must be zero */;
+
+
+# cleanup for bug#32468
+
+connection master;
+drop table t2,t1;
+set foreign_key_checks=1;
+
+--echo #
+--echo # MDEV-25530 Error 1451 on slave: Cannot delete or update a parent row: a foreign key constraint fails
+--echo #
+
+create table t1 (id int primary key)engine=innodb;
+create table t2 (id int not null primary key auto_increment,
+ id2 int default null, key f1 (id2),
+ constraint f1 foreign key (id2) references t1 (id) on delete cascade) engine=innodb;
+error ER_ROW_IS_REFERENCED_2;
+drop table t1,t2;
+sync_slave_with_master;
+show tables;
+connection master;
+drop table t1;
+sync_slave_with_master;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_free_items-slave.opt b/mysql-test/suite/rpl/t/rpl_free_items-slave.opt
new file mode 100644
index 00000000..b828d03f
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_free_items-slave.opt
@@ -0,0 +1 @@
+--replicate-wild-ignore-table=test.%
diff --git a/mysql-test/suite/rpl/t/rpl_free_items.test b/mysql-test/suite/rpl/t/rpl_free_items.test
new file mode 100644
index 00000000..581409cf
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_free_items.test
@@ -0,0 +1,23 @@
+source include/master-slave.inc;
+create table t1 (a int);
+create table t2 (a int);
+disable_query_log;
+SET @query="INSERT INTO t2 SELECT * FROM t1 WHERE a REGEXP \"0\"";
+let $1 = 2000;
+while ($1)
+{
+ eval SET @query=concat(@query, " OR a REGEXP '$1'");
+ dec $1;
+}
+let $1=`select @query`;
+eval $1;
+enable_query_log;
+# I have seen the slave crash either now or at shutdown
+sync_slave_with_master;
+connection master;
+drop table t1;
+drop table t2;
+sync_slave_with_master;
+
+# End of 4.1 tests
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_function_defaults.test b/mysql-test/suite/rpl/t/rpl_function_defaults.test
new file mode 100644
index 00000000..f2413299
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_function_defaults.test
@@ -0,0 +1,86 @@
+--echo #
+--echo # Test of function defaults on replicated tables.
+--echo #
+
+source include/master-slave.inc;
+
+connection master;
+SET TIME_ZONE="+10:30";
+SET TIMESTAMP=123456.789123;
+SELECT CURRENT_TIMESTAMP;
+
+connection slave;
+SET TIME_ZONE="+00:00";
+SET TIMESTAMP=987654321.123456;
+SELECT CURRENT_TIMESTAMP;
+
+connection master;
+CREATE TABLE t1 (
+ a TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ b TIMESTAMP(1) NOT NULL DEFAULT CURRENT_TIMESTAMP(1),
+ c TIMESTAMP(2) NOT NULL DEFAULT CURRENT_TIMESTAMP(2),
+ d TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
+ e TIMESTAMP(4) NOT NULL DEFAULT CURRENT_TIMESTAMP(4),
+ f TIMESTAMP(5) NOT NULL DEFAULT CURRENT_TIMESTAMP(5),
+ g TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),
+ h DATETIME DEFAULT CURRENT_TIMESTAMP,
+ i DATETIME(1) DEFAULT CURRENT_TIMESTAMP(1),
+ j DATETIME(2) DEFAULT CURRENT_TIMESTAMP(2),
+ k DATETIME(3) DEFAULT CURRENT_TIMESTAMP(3),
+ l DATETIME(4) DEFAULT CURRENT_TIMESTAMP(4),
+ m DATETIME(5) DEFAULT CURRENT_TIMESTAMP(5),
+ n DATETIME(6) DEFAULT CURRENT_TIMESTAMP(6),
+ o INT
+);
+
+INSERT INTO t1 ( o ) VALUES ( 1 );
+
+CREATE TABLE t2 (
+ a TIMESTAMP NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP,
+ b TIMESTAMP(1) NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP(1),
+ c TIMESTAMP(2) NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP(2),
+ d TIMESTAMP(3) NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP(3),
+ e TIMESTAMP(4) NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP(4),
+ f TIMESTAMP(5) NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP(5),
+ g TIMESTAMP(6) NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP(6),
+ h DATETIME ON UPDATE CURRENT_TIMESTAMP,
+ i DATETIME(1) ON UPDATE CURRENT_TIMESTAMP(1),
+ j DATETIME(2) ON UPDATE CURRENT_TIMESTAMP(2),
+ k DATETIME(3) ON UPDATE CURRENT_TIMESTAMP(3),
+ l DATETIME(4) ON UPDATE CURRENT_TIMESTAMP(4),
+ m DATETIME(5) ON UPDATE CURRENT_TIMESTAMP(5),
+ n DATETIME(6) ON UPDATE CURRENT_TIMESTAMP(6),
+ o INT
+);
+
+INSERT INTO t2 ( o ) VALUES ( 1 );
+
+--echo sync_slave_with_master
+sync_slave_with_master;
+
+connection slave;
+
+query_vertical SELECT * FROM t1;
+query_vertical SELECT * FROM t2;
+
+connection master;
+
+SET TIMESTAMP=1234567890.123456;
+SELECT CURRENT_TIMESTAMP;
+
+UPDATE t1 SET o = 2;
+UPDATE t2 SET o = 2;
+
+--echo sync_slave_with_master
+sync_slave_with_master;
+
+connection slave;
+
+query_vertical SELECT * FROM t1;
+query_vertical SELECT * FROM t2;
+
+connection master;
+
+DROP TABLE t1, t2;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_geometry.test b/mysql-test/suite/rpl/t/rpl_geometry.test
new file mode 100644
index 00000000..415732a0
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_geometry.test
@@ -0,0 +1,26 @@
+source include/have_binlog_format_row.inc;
+source include/master-slave.inc;
+
+#
+# Bug#48776, Bug#43784
+#
+create table t1(a varchar(100),
+ b multipoint not null,
+ c varchar(256));
+
+insert into t1 set
+ a='hello',
+ b=geomfromtext('multipoint(1 1)'),
+ c='geometry';
+
+create table t2 (a int(11) not null auto_increment primary key,
+ b geometrycollection default null,
+ c decimal(10,0));
+
+insert into t2(c) values (null);
+
+sync_slave_with_master;
+
+connection master;
+drop table t1, t2;
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_get_lock.test b/mysql-test/suite/rpl/t/rpl_get_lock.test
new file mode 100644
index 00000000..b5c08858
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_get_lock.test
@@ -0,0 +1,47 @@
+source include/master-slave.inc;
+
+CALL mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT");
+
+create table t1(n int);
+# Use of get_lock gives a warning for unsafeness if binlog_format=statement
+--disable_warnings
+insert into t1 values(get_lock("lock",2));
+--enable_warnings
+dirty_close master;
+connection master1;
+select get_lock("lock",2);
+
+select release_lock("lock");
+#ignore
+disable_query_log;
+let $1=2000;
+while ($1)
+{
+ do get_lock("lock",2);
+ do release_lock("lock");
+ dec $1;
+}
+enable_query_log;
+sync_slave_with_master;
+select get_lock("lock",3);
+select * from t1;
+# There is no point in testing REPLICATIION of the IS_*_LOCK
+# functions; slave does not run with the same concurrency context as
+# master (generally in slave we can't know that on master this lock
+# was already held by another connection and so that the the
+# get_lock() we're replicating timed out on master hence returned 0,
+# or that the is_free_lock() we're playing returned 0 etc.
+# But here all we do is test these functions outside of replication.
+select is_free_lock("lock"), is_used_lock("lock") = connection_id();
+explain extended select is_free_lock("lock"), is_used_lock("lock");
+# Check lock functions
+select is_free_lock("lock2");
+select is_free_lock(NULL);
+connection master1;
+drop table t1;
+sync_slave_with_master;
+
+
+--source include/rpl_end.inc
+
+# End of 4.1 tests
diff --git a/mysql-test/suite/rpl/t/rpl_get_master_version_and_clock-slave.opt b/mysql-test/suite/rpl/t/rpl_get_master_version_and_clock-slave.opt
new file mode 100644
index 00000000..f9aa8c03
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_get_master_version_and_clock-slave.opt
@@ -0,0 +1 @@
+--master-retry-count=60
diff --git a/mysql-test/suite/rpl/t/rpl_get_master_version_and_clock.test b/mysql-test/suite/rpl/t/rpl_get_master_version_and_clock.test
new file mode 100644
index 00000000..e3d049f0
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_get_master_version_and_clock.test
@@ -0,0 +1,52 @@
+#
+# BUG#45214
+# This test verifies if the slave I/O tread tries to reconnect to
+# master when it tries to get the values of the UNIX_TIMESTAMP, SERVER_ID,
+# COLLATION_SERVER and TIME_ZONE from master under network disconnection.
+# The COLLATION_SERVER and TIME_ZONE are got only on master server version 4.
+# So they can't be verified by test case here.
+# Finish the following tests by calling its common test script:
+# include/rpl_get_master_version_and_clock.test.
+
+source include/not_valgrind.inc;
+source include/have_debug.inc;
+source include/have_debug_sync.inc;
+source include/master-slave.inc;
+
+#
+# The test is not supposed to have any binglog affairs.
+# Hence it's enough it to run only with one binlog format
+#
+source include/have_binlog_format_mixed.inc;
+
+connection slave;
+
+call mtr.add_suppression("Slave I/O: Master command COM_REGISTER_SLAVE failed: .*");
+call mtr.add_suppression("Slave I/O: .* failed with error: Lost connection to server at 'reading initial communication packet'");
+call mtr.add_suppression("Fatal error: The slave I/O thread stops because
+master and slave have equal MariaDB server ids; .*");
+call mtr.add_suppression("Slave I/O thread .* register on master");
+
+#Test case 1: Try to get the value of the UNIX_TIMESTAMP from master under network disconnection
+SET @saved_dbug = @@GLOBAL.debug_dbug;
+
+# set up two parameters to pass into include/rpl_get_master_version_and_clock
+let $dbug_sync_point= 'debug_lock.before_get_UNIX_TIMESTAMP';
+let $debug_sync_action= 'now SIGNAL signal.get_unix_timestamp';
+source include/rpl_get_master_version_and_clock.test;
+
+#Test case 2: Try to get the value of the SERVER_ID from master under network disconnection
+connection slave;
+
+let $dbug_sync_point= 'debug_lock.before_get_SERVER_ID';
+let $debug_sync_action= 'now SIGNAL signal.get_server_id';
+source include/rpl_get_master_version_and_clock.test;
+
+
+# cleanup
+SET @@GLOBAL.debug_dbug = @saved_dbug;
+# is not really necessary but avoids mtr post-run env check warnings
+SET DEBUG_SYNC= 'RESET';
+
+# End of tests
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_grant.test b/mysql-test/suite/rpl/t/rpl_grant.test
new file mode 100644
index 00000000..02206453
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_grant.test
@@ -0,0 +1,37 @@
+# Tests of grants and users
+
+source include/not_embedded.inc;
+source include/master-slave.inc;
+
+connection master;
+
+CREATE USER dummy@localhost;
+CREATE USER dummy1@localhost, dummy2@localhost;
+
+SELECT user, host FROM mysql.user WHERE user like 'dummy%';
+SELECT COUNT(*) FROM mysql.user WHERE user like 'dummy%';
+sync_slave_with_master;
+--echo **** On Slave ****
+SELECT user,host FROM mysql.user WHERE user like 'dummy%';
+SELECT COUNT(*) FROM mysql.user WHERE user like 'dummy%';
+
+connection master;
+
+# No user exists
+error ER_CANNOT_USER;
+DROP USER nonexisting@localhost;
+
+# At least one user exists, but not all
+error ER_CANNOT_USER;
+DROP USER nonexisting@localhost, dummy@localhost;
+
+# All users exist
+DROP USER dummy1@localhost, dummy2@localhost;
+
+SELECT user, host FROM mysql.user WHERE user like 'dummy%';
+SELECT COUNT(*) FROM mysql.user WHERE user like 'dummy%';
+sync_slave_with_master;
+SELECT user,host FROM mysql.user WHERE user like 'dummy%';
+SELECT COUNT(*) FROM mysql.user WHERE user like 'dummy%';
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_gtid_basic.cnf b/mysql-test/suite/rpl/t/rpl_gtid_basic.cnf
new file mode 100644
index 00000000..3ff94e45
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_gtid_basic.cnf
@@ -0,0 +1,24 @@
+!include ../my.cnf
+
+[mysqld.1]
+log-slave-updates
+loose-innodb
+
+[mysqld.2]
+log-slave-updates
+loose-innodb
+
+[mysqld.3]
+log-slave-updates
+loose-innodb
+
+[mysqld.4]
+log-slave-updates
+loose-innodb
+
+[ENV]
+SERVER_MYPORT_3= @mysqld.3.port
+SERVER_MYSOCK_3= @mysqld.3.socket
+
+SERVER_MYPORT_4= @mysqld.4.port
+SERVER_MYSOCK_4= @mysqld.4.socket
diff --git a/mysql-test/suite/rpl/t/rpl_gtid_basic.test b/mysql-test/suite/rpl/t/rpl_gtid_basic.test
new file mode 100644
index 00000000..70bd0087
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_gtid_basic.test
@@ -0,0 +1,652 @@
+#
+# This include file is used by more than one test suite
+# (currently rpl and binlog_encryption).
+# Please check all dependent tests after modifying it
+#
+
+--source include/have_innodb.inc
+--let $rpl_topology=1->2->3->4
+--source include/rpl_init.inc
+
+# Set up a 4-deep replication topology, then test various fail-overs
+# using GTID.
+#
+# A -> B -> C -> D
+
+connection server_1;
+--source include/wait_for_binlog_checkpoint.inc
+--let $binlog_file = query_get_value(SHOW MASTER STATUS,File,1)
+--let $binlog_pos = query_get_value(SHOW MASTER STATUS,Position,1)
+--echo *** GTID position should be empty here ***
+--replace_result $binlog_file <BINLOG_FILE> $binlog_pos <BINLOG_POS>
+eval SELECT BINLOG_GTID_POS('$binlog_file',$binlog_pos);
+
+CREATE TABLE t1 (a INT PRIMARY KEY, b VARCHAR(10)) ENGINE=MyISAM;
+CREATE TABLE t2 (a INT PRIMARY KEY, b VARCHAR(10)) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1, "m1");
+INSERT INTO t1 VALUES (2, "m2"), (3, "m3"), (4, "m4");
+INSERT INTO t2 VALUES (1, "i1");
+BEGIN;
+INSERT INTO t2 VALUES (2, "i2"), (3, "i3");
+INSERT INTO t2 VALUES (4, "i4");
+COMMIT;
+save_master_pos;
+source include/wait_for_binlog_checkpoint.inc;
+--let $binlog_file = query_get_value(SHOW MASTER STATUS,File,1)
+--let $binlog_pos = query_get_value(SHOW MASTER STATUS,Position,1)
+--let $gtid_pos_server_1 = `SELECT @@gtid_binlog_pos`
+--echo *** GTID position should be non-empty here ***
+--replace_result $binlog_file <BINLOG_FILE> $binlog_pos <BINLOG_POS> $gtid_pos_server_1 <GTID_POS_SERVER_1>
+eval SELECT BINLOG_GTID_POS('$binlog_file',$binlog_pos);
+
+connection server_2;
+sync_with_master;
+source include/wait_for_binlog_checkpoint.inc;
+--let $binlog_file = query_get_value(SHOW MASTER STATUS,File,1)
+--let $binlog_pos = query_get_value(SHOW MASTER STATUS,Position,1)
+--echo *** GTID position should be the same as on server_1 ***
+--replace_result $binlog_file <BINLOG_FILE> $binlog_pos <BINLOG_POS> $gtid_pos_server_1 <GTID_POS_SERVER_1>
+eval SELECT BINLOG_GTID_POS('$binlog_file',$binlog_pos);
+SELECT * FROM t1 ORDER BY a;
+SELECT * FROM t2 ORDER BY a;
+save_master_pos;
+
+connection server_3;
+sync_with_master;
+SELECT * FROM t1 ORDER BY a;
+SELECT * FROM t2 ORDER BY a;
+save_master_pos;
+
+connection server_4;
+sync_with_master;
+SELECT * FROM t1 ORDER BY a;
+SELECT * FROM t2 ORDER BY a;
+
+
+--echo *** Now take out D, let it fall behind a bit, and then test re-attaching it to A ***
+connection server_4;
+--source include/stop_slave.inc
+
+connection server_1;
+INSERT INTO t1 VALUES (5, "m1a");
+INSERT INTO t2 VALUES (5, "i1a");
+save_master_pos;
+
+connection server_4;
+--replace_result $MASTER_MYPORT MASTER_PORT
+eval CHANGE MASTER TO master_host = '127.0.0.1', master_port = $MASTER_MYPORT,
+ MASTER_USE_GTID=CURRENT_POS;
+--source include/start_slave.inc
+sync_with_master;
+SELECT * FROM t1 ORDER BY a;
+SELECT * FROM t2 ORDER BY a;
+
+--echo *** Now move B to D (C is still replicating from B) ***
+connection server_2;
+--source include/stop_slave.inc
+--replace_result $SERVER_MYPORT_4 SERVER_MYPORT_4
+eval CHANGE MASTER TO master_host = '127.0.0.1', master_port = $SERVER_MYPORT_4,
+ MASTER_USE_GTID=CURRENT_POS;
+--source include/start_slave.inc
+
+connection server_4;
+UPDATE t2 SET b="j1a" WHERE a=5;
+save_master_pos;
+
+connection server_2;
+sync_with_master;
+SELECT * FROM t1 ORDER BY a;
+SELECT * FROM t2 ORDER BY a;
+
+--echo *** Now move C to D, after letting it fall a little behind ***
+connection server_3;
+--source include/stop_slave.inc
+
+connection server_1;
+INSERT INTO t2 VALUES (6, "i6b");
+INSERT INTO t2 VALUES (7, "i7b");
+--source include/save_master_gtid.inc
+
+connection server_3;
+--replace_result $SERVER_MYPORT_4 SERVER_MYPORT_4
+eval CHANGE MASTER TO master_host = '127.0.0.1', master_port = $SERVER_MYPORT_4,
+ MASTER_USE_GTID=CURRENT_POS;
+--source include/start_slave.inc
+--source include/sync_with_master_gtid.inc
+SELECT * FROM t2 ORDER BY a;
+
+--echo *** Now change everything back to what it was, to make rpl_end.inc happy
+# Also check that MASTER_USE_GTID=CURRENT_POS is still enabled.
+connection server_2;
+# We need to sync up server_2 before switching. If it happened to have reached
+# the point 'UPDATE t2 SET b="j1a" WHERE a=5' it will fail to connect to
+# server_1, which is (deliberately) missing that transaction.
+--source include/sync_with_master_gtid.inc
+--source include/stop_slave.inc
+--replace_result $MASTER_MYPORT MASTER_MYPORT
+eval CHANGE MASTER TO master_host = '127.0.0.1', master_port = $MASTER_MYPORT;
+--source include/start_slave.inc
+--source include/wait_for_slave_to_start.inc
+
+connection server_3;
+--source include/stop_slave.inc
+--replace_result $SLAVE_MYPORT SLAVE_MYPORT
+eval CHANGE MASTER TO master_host = '127.0.0.1', master_port = $SLAVE_MYPORT;
+--source include/start_slave.inc
+--source include/sync_with_master_gtid.inc
+
+connection server_4;
+--source include/stop_slave.inc
+--replace_result $SERVER_MYPORT_3 SERVER_MYPORT_3
+eval CHANGE MASTER TO master_host = '127.0.0.1', master_port = $SERVER_MYPORT_3;
+--source include/start_slave.inc
+
+connection server_1;
+DROP TABLE t1,t2;
+--source include/save_master_gtid.inc
+
+--echo *** A few more checks for BINLOG_GTID_POS function ***
+--let $valid_binlog_name = query_get_value(SHOW BINARY LOGS,Log_name,1)
+--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT
+SELECT BINLOG_GTID_POS();
+--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT
+SELECT BINLOG_GTID_POS('a');
+--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT
+SELECT BINLOG_GTID_POS('a',1,NULL);
+SELECT BINLOG_GTID_POS(1,'a');
+SELECT BINLOG_GTID_POS(NULL,NULL);
+SELECT BINLOG_GTID_POS('',1);
+SELECT BINLOG_GTID_POS('a',1);
+eval SELECT BINLOG_GTID_POS('$valid_binlog_name',-1);
+eval SELECT BINLOG_GTID_POS('$valid_binlog_name',0);
+eval SELECT BINLOG_GTID_POS('$valid_binlog_name',18446744073709551615);
+eval SELECT BINLOG_GTID_POS('$valid_binlog_name',18446744073709551616);
+
+
+--echo *** Some tests of @@GLOBAL.gtid_binlog_state ***
+--connection server_2
+--source include/sync_with_master_gtid.inc
+--source include/stop_slave.inc
+
+--connection server_1
+SET @old_state= @@GLOBAL.gtid_binlog_state;
+
+--error ER_BINLOG_MUST_BE_EMPTY
+SET GLOBAL gtid_binlog_state = '';
+RESET MASTER;
+SET GLOBAL gtid_binlog_state = '';
+FLUSH LOGS;
+--source include/show_binary_logs.inc
+SET GLOBAL gtid_binlog_state = '0-1-10,1-2-20,0-3-30';
+--source include/show_binary_logs.inc
+--let $binlog_file= master-bin.000001
+--let $binlog_start= 4
+--source include/show_binlog_events.inc
+#SELECT @@GLOBAL.gtid_binlog_pos;
+#SELECT @@GLOBAL.gtid_binlog_state;
+--error ER_BINLOG_MUST_BE_EMPTY
+SET GLOBAL gtid_binlog_state = @old_state;
+RESET MASTER;
+SET GLOBAL gtid_binlog_state = @old_state;
+
+# Check that slave can reconnect again, despite the RESET MASTER, as we
+# restored the state.
+
+CREATE TABLE t1 (a INT PRIMARY KEY);
+SET gtid_seq_no=100;
+INSERT INTO t1 VALUES (1);
+--source include/save_master_gtid.inc
+
+--connection server_2
+--source include/start_slave.inc
+# We cannot just use sync_with_master as we've done RESET MASTER, so
+# slave old-style position is wrong.
+# So sync on gtid position instead.
+--source include/sync_with_master_gtid.inc
+
+SELECT * FROM t1;
+# Check that the IO gtid position in SHOW SLAVE STATUS is also correct.
+--let $status_items= Gtid_IO_Pos
+--source include/show_slave_status.inc
+
+--echo *** Test @@LAST_GTID and MASTER_GTID_WAIT() ***
+
+--disable_ps2_protocol
+--connection server_1
+DROP TABLE t1;
+CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=InnoDB;
+--save_master_pos
+
+--connection server_2
+--sync_with_master
+--source include/stop_slave.inc
+
+--connect (m1,127.0.0.1,root,,test,$SERVER_MYPORT_1,)
+SELECT @@last_gtid;
+SET gtid_seq_no=110;
+SELECT @@last_gtid;
+BEGIN;
+SELECT @@last_gtid;
+INSERT INTO t1 VALUES (2);
+SELECT @@last_gtid;
+COMMIT;
+SELECT @@last_gtid;
+--let $pos= `SELECT @@gtid_binlog_pos`
+
+--connect (s1,127.0.0.1,root,,test,$SERVER_MYPORT_2,)
+eval SET @pos= '$pos';
+# Check NULL argument.
+SELECT master_gtid_wait(NULL);
+# Check empty argument returns immediately.
+SELECT master_gtid_wait('', NULL);
+# Check this gets counted
+SHOW STATUS LIKE 'Master_gtid_wait_count';
+SHOW STATUS LIKE 'Master_gtid_wait_timeouts';
+SHOW STATUS LIKE 'Master_gtid_wait_time';
+# Let's check that we get a timeout
+SELECT master_gtid_wait(@pos, 0.5);
+SELECT * FROM t1 ORDER BY a;
+# Now actually wait until the slave reaches the position
+send SELECT master_gtid_wait(@pos);
+
+--connection server_2
+--source include/start_slave.inc
+
+--connection s1
+reap;
+SELECT * FROM t1 ORDER BY a;
+
+# Test waiting on a domain that does not exist yet.
+--source include/stop_slave.inc
+
+--connection server_1
+SET gtid_domain_id= 1;
+INSERT INTO t1 VALUES (3);
+--let $pos= `SELECT @@gtid_binlog_pos`
+
+--connection s1
+--replace_result $pos POS
+eval SET @pos= '$pos';
+SELECT master_gtid_wait(@pos, 0);
+SELECT * FROM t1 WHERE a >= 3;
+send SELECT master_gtid_wait(@pos, -1);
+
+--connection server_2
+--source include/start_slave.inc
+
+--connection s1
+reap;
+SELECT * FROM t1 WHERE a >= 3;
+# Waiting for only part of the position.
+SELECT master_gtid_wait('1-1-1', 0);
+
+# Now test a lot of parallel master_gtid_wait() calls, completing in different
+# order, and some of which time out or get killed on the way.
+
+--connection s1
+send SELECT master_gtid_wait('2-1-1,1-1-4,0-1-110');
+
+--connect (s2,127.0.0.1,root,,test,$SERVER_MYPORT_2,)
+# This will time out. No event 0-1-1000 exists
+send SELECT master_gtid_wait('0-1-1000', 0.5);
+
+--connect (s3,127.0.0.1,root,,test,$SERVER_MYPORT_2,)
+# This one we will kill
+--let $kill1_id= `SELECT connection_id()`
+send SELECT master_gtid_wait('0-1-2000');
+
+--connect (s4,127.0.0.1,root,,test,$SERVER_MYPORT_2,)
+send SELECT master_gtid_wait('2-1-10');
+
+--connect (s5,127.0.0.1,root,,test,$SERVER_MYPORT_2,)
+send SELECT master_gtid_wait('2-1-6', 1);
+
+# This one we will kill also.
+--connect (s6,127.0.0.1,root,,test,$SERVER_MYPORT_2,)
+--let $kill2_id= `SELECT connection_id()`
+send SELECT master_gtid_wait('2-1-5');
+
+--connect (s7,127.0.0.1,root,,test,$SERVER_MYPORT_2,)
+send SELECT master_gtid_wait('2-1-10');
+
+--connect (s8,127.0.0.1,root,,test,$SERVER_MYPORT_2,)
+send SELECT master_gtid_wait('2-1-5,1-1-4,0-1-110');
+
+--connect (s9,127.0.0.1,root,,test,$SERVER_MYPORT_2,)
+send SELECT master_gtid_wait('2-1-2');
+
+--connection server_2
+# This one completes immediately.
+SHOW STATUS LIKE 'Master_gtid_wait_timeouts';
+SHOW STATUS LIKE 'Master_gtid_wait_count';
+SELECT master_gtid_wait('1-1-1');
+SHOW STATUS LIKE 'Master_gtid_wait_timeouts';
+SHOW STATUS LIKE 'Master_gtid_wait_count';
+let $wait_time = query_get_value(SHOW STATUS LIKE 'Master_gtid_wait_time', Value, 1);
+--replace_result $wait_time MASTER_GTID_WAIT_TIME
+eval SET @a= $wait_time;
+SELECT IF(@a <= 100*1000*1000, "OK", CONCAT("Error: wait time ", @a, " is larger than expected"))
+ AS Master_gtid_wait_time_as_expected;
+
+
+--connect (s10,127.0.0.1,root,,test,$SERVER_MYPORT_2,)
+send SELECT master_gtid_wait('0-1-109');
+
+--connection server_2
+# This one should time out.
+SHOW STATUS LIKE 'Master_gtid_wait_timeouts';
+SHOW STATUS LIKE 'Master_gtid_wait_count';
+SELECT master_gtid_wait('2-1-2', 0.5);
+SHOW STATUS LIKE 'Master_gtid_wait_timeouts';
+SHOW STATUS LIKE 'Master_gtid_wait_count';
+let $wait_time = query_get_value(SHOW STATUS LIKE 'Master_gtid_wait_time', Value, 1);
+--replace_result $wait_time MASTER_GTID_WAIT_TIME
+eval SET @a= $wait_time;
+# We expect a wait time of just a bit over 0.5 seconds. But thread scheduling
+# and timer inaccuracies could introduce significant jitter. So allow a
+# generous interval.
+SELECT IF(@a BETWEEN 0.4*1000*1000 AND 100*1000*1000, "OK", CONCAT("Error: wait time ", @a, " not as expected")) AS Master_gtid_wait_time_as_expected;
+
+--replace_result $kill1_id KILL_ID
+eval KILL QUERY $kill1_id;
+--connection s3
+--error ER_QUERY_INTERRUPTED
+reap;
+
+--connection server_1
+SET gtid_domain_id=2;
+SET gtid_seq_no=2;
+INSERT INTO t1 VALUES (4);
+
+--connection s9
+reap;
+
+--connection server_2
+--replace_result $kill2_id KILL_ID
+eval KILL CONNECTION $kill2_id;
+
+--connection s6
+--error 2013,ER_CONNECTION_KILLED
+reap;
+
+--connection server_1
+SET gtid_domain_id=1;
+SET gtid_seq_no=4;
+INSERT INTO t1 VALUES (5);
+SET gtid_domain_id=2;
+SET gtid_seq_no=5;
+INSERT INTO t1 VALUES (6);
+
+--connection s8
+reap;
+--connection s1
+reap;
+--connection s2
+reap;
+--connection s5
+reap;
+--connection s10
+reap;
+
+--connection server_1
+SET gtid_domain_id=2;
+SET gtid_seq_no=10;
+INSERT INTO t1 VALUES (7);
+
+--connection s4
+reap;
+--connection s7
+reap;
+--enable_ps2_protocol
+
+--echo *** Test gtid_slave_pos when used with GTID ***
+
+--connection server_2
+--source include/stop_slave.inc
+
+--connection server_1
+SET gtid_domain_id=2;
+SET gtid_seq_no=1000;
+INSERT INTO t1 VALUES (10);
+INSERT INTO t1 VALUES (11);
+--save_master_pos
+
+--connection server_2
+SET sql_slave_skip_counter= 1;
+--source include/start_slave.inc
+--sync_with_master
+SELECT * FROM t1 WHERE a >= 10 ORDER BY a;
+SELECT IF(LOCATE("2-1-1001", @@GLOBAL.gtid_slave_pos)>0, "Ok", CONCAT("ERROR! expected GTID 2-1-1001 not found in gtid_slave_pos: ", @@GLOBAL.gtid_slave_pos)) AS status;
+
+--source include/stop_slave.inc
+
+--connection server_1
+SET gtid_domain_id=2;
+SET gtid_seq_no=1010;
+INSERT INTO t1 VALUES (12);
+INSERT INTO t1 VALUES (13);
+--save_master_pos
+
+--connection server_2
+SET sql_slave_skip_counter= 2;
+--source include/start_slave.inc
+--sync_with_master
+SELECT * FROM t1 WHERE a >= 10 ORDER BY a;
+SELECT IF(LOCATE("2-1-1011", @@GLOBAL.gtid_slave_pos)>0, "Ok", CONCAT("ERROR! expected GTID 2-1-1011 not found in gtid_slave_pos: ", @@GLOBAL.gtid_slave_pos)) AS status;
+
+--source include/stop_slave.inc
+
+--connection server_1
+SET gtid_domain_id=2;
+SET gtid_seq_no=1020;
+INSERT INTO t1 VALUES (14);
+INSERT INTO t1 VALUES (15);
+INSERT INTO t1 VALUES (16);
+--save_master_pos
+
+--connection server_2
+SET sql_slave_skip_counter= 3;
+--source include/start_slave.inc
+--sync_with_master
+SELECT * FROM t1 WHERE a >= 10 ORDER BY a;
+SELECT IF(LOCATE("2-1-1022", @@GLOBAL.gtid_slave_pos)>0, "Ok", CONCAT("ERROR! expected GTID 2-1-1022 not found in gtid_slave_pos: ", @@GLOBAL.gtid_slave_pos)) AS status;
+
+--source include/stop_slave.inc
+
+--connection server_1
+SET gtid_domain_id=2;
+SET gtid_seq_no=1030;
+# Disable logging Annotate_rows events to preserve events count.
+let $binlog_annotate_row_events_saved= `SELECT @@binlog_annotate_row_events`;
+SET @@binlog_annotate_row_events= 0;
+INSERT INTO t1 VALUES (17);
+INSERT INTO t1 VALUES (18);
+INSERT INTO t1 VALUES (19);
+eval SET @@binlog_annotate_row_events= $binlog_annotate_row_events_saved;
+--save_master_pos
+
+--connection server_2
+SET sql_slave_skip_counter= 5;
+--source include/start_slave.inc
+--sync_with_master
+SELECT * FROM t1 WHERE a >= 10 ORDER BY a;
+SELECT IF(LOCATE("2-1-1032", @@GLOBAL.gtid_slave_pos)>0, "Ok", CONCAT("ERROR! expected GTID 2-1-1032 not found in gtid_slave_pos: ", @@GLOBAL.gtid_slave_pos)) AS status;
+
+
+--source include/stop_slave.inc
+
+--connection server_1
+SET gtid_domain_id=3;
+SET gtid_seq_no=100;
+CREATE TABLE t2 (a INT PRIMARY KEY);
+DROP TABLE t2;
+SET gtid_domain_id=2;
+SET gtid_seq_no=1040;
+INSERT INTO t1 VALUES (20);
+--save_master_pos
+
+--connection server_2
+SET @saved_mode= @@GLOBAL.slave_ddl_exec_mode;
+SET GLOBAL slave_ddl_exec_mode=STRICT;
+SET sql_slave_skip_counter=1;
+START SLAVE UNTIL master_gtid_pos="3-1-100";
+--let $master_pos=3-1-100
+--source include/sync_with_master_gtid.inc
+--source include/wait_for_slave_to_stop.inc
+--error ER_NO_SUCH_TABLE
+SELECT * FROM t2;
+SELECT IF(LOCATE("3-1-100", @@GLOBAL.gtid_slave_pos)>0, "Ok", CONCAT("ERROR! expected GTID 3-1-100 not found in gtid_slave_pos: ", @@GLOBAL.gtid_slave_pos)) AS status;
+
+# Start the slave again, it should fail on the DROP TABLE as the table is not there.
+SET sql_log_bin=0;
+CALL mtr.add_suppression("Slave: Unknown table 'test\\.t2' Error_code: 1051");
+SET sql_log_bin=1;
+START SLAVE;
+--let $slave_sql_errno=1051
+--source include/wait_for_slave_sql_error.inc
+SELECT IF(LOCATE("3-1-100", @@GLOBAL.gtid_slave_pos)>0, "Ok", CONCAT("ERROR! expected GTID 3-1-100 not found in gtid_slave_pos: ", @@GLOBAL.gtid_slave_pos)) AS status;
+
+STOP SLAVE IO_THREAD;
+SET sql_slave_skip_counter=2;
+--source include/start_slave.inc
+--sync_with_master
+
+SELECT * FROM t1 WHERE a >= 20 ORDER BY a;
+SELECT IF(LOCATE("3-1-101", @@GLOBAL.gtid_slave_pos)>0, "Ok", CONCAT("ERROR! expected GTID 3-1-101 not found in gtid_slave_pos: ", @@GLOBAL.gtid_slave_pos)) AS status;
+SELECT IF(LOCATE("2-1-1040", @@GLOBAL.gtid_slave_pos)>0, "Ok", CONCAT("ERROR! expected GTID 2-1-1040 not found in gtid_slave_pos: ", @@GLOBAL.gtid_slave_pos)) AS status;
+
+SET GLOBAL slave_ddl_exec_mode= @saved_mode;
+
+
+--echo *** Test GTID-connecting to a master with out-of-order sequence numbers in the binlog. ***
+
+# Create an out-of-order binlog on server 2.
+# Let server 3 replicate to an out-of-order point, stop it, restart it,
+# and check that it replicates correctly despite the out-of-order.
+
+--connection server_1
+SET gtid_domain_id= @@GLOBAL.gtid_domain_id;
+INSERT INTO t1 VALUES (31);
+--save_master_pos
+
+--connection server_2
+--sync_with_master
+SET gtid_domain_id= @@GLOBAL.gtid_domain_id;
+INSERT INTO t1 VALUES (32);
+
+--connection server_1
+INSERT INTO t1 VALUES (33);
+--save_master_pos
+
+--connection server_2
+--sync_with_master
+--save_master_pos
+
+--connection server_3
+--sync_with_master
+--source include/stop_slave.inc
+
+--connection server_1
+INSERT INTO t1 VALUES (34);
+--save_master_pos
+
+--connection server_2
+--sync_with_master
+--save_master_pos
+
+--connection server_3
+--source include/start_slave.inc
+--sync_with_master
+SELECT * FROM t1 WHERE a >= 30 ORDER BY a;
+--save_master_pos
+
+--connection server_4
+--sync_with_master
+SELECT * FROM t1 WHERE a >= 30 ORDER BY a;
+
+
+--echo *** MDEV-31723: Crash on SET SESSION gtid_seq_no= DEFAULT
+--connection server_1
+
+# Setting gtid_seq_no forces the GTID logged, but only once.
+SET SESSION gtid_seq_no= 2000;
+SELECT @@SESSION.gtid_seq_no;
+INSERT INTO t1 VALUES (40);
+SELECT @@SESSION.gtid_seq_no;
+SELECT REGEXP_REPLACE(@@gtid_binlog_pos, ".*\\b(0-1-[0-9]+)\\b.*", "\\1") AS dom0_pos;
+INSERT INTO t1 VALUES (41);
+SELECT REGEXP_REPLACE(@@gtid_binlog_pos, ".*\\b(0-1-[0-9]+)\\b.*", "\\1") AS dom0_pos;
+
+# Setting to 0 has no effect.
+SET SESSION gtid_seq_no= 2010;
+INSERT INTO t1 VALUES (42);
+SELECT REGEXP_REPLACE(@@gtid_binlog_pos, ".*\\b(0-1-[0-9]+)\\b.*", "\\1") AS dom0_pos;
+SET @old_strict= @@GLOBAL.gtid_strict_mode;
+SET GLOBAL gtid_strict_mode= 1;
+SET SESSION gtid_seq_no= 0;
+INSERT INTO t1 VALUES (43);
+SELECT REGEXP_REPLACE(@@gtid_binlog_pos, ".*\\b(0-1-[0-9]+)\\b.*", "\\1") AS dom0_pos;
+SET GLOBAL gtid_strict_mode= @old_strict;
+INSERT INTO t1 VALUES (44);
+SELECT REGEXP_REPLACE(@@gtid_binlog_pos, ".*\\b(0-1-[0-9]+)\\b.*", "\\1") AS dom0_pos;
+
+# Setting gtid_seq_no multiple times.
+SET SESSION gtid_seq_no= 2020;
+SET SESSION gtid_seq_no= 2030;
+INSERT INTO t1 VALUES (45);
+SELECT REGEXP_REPLACE(@@gtid_binlog_pos, ".*\\b(0-1-[0-9]+)\\b.*", "\\1") AS dom0_pos;
+
+# Setting to DEFAULT or 0 disables prior setting.
+SET SESSION gtid_seq_no= 2040;
+SET SESSION gtid_seq_no= DEFAULT;
+INSERT INTO t1 VALUES (46);
+SELECT REGEXP_REPLACE(@@gtid_binlog_pos, ".*\\b(0-1-[0-9]+)\\b.*", "\\1") AS dom0_pos;
+INSERT INTO t1 VALUES (47);
+SELECT REGEXP_REPLACE(@@gtid_binlog_pos, ".*\\b(0-1-[0-9]+)\\b.*", "\\1") AS dom0_pos;
+SET SESSION gtid_seq_no= 2050;
+SET SESSION gtid_seq_no= 0;
+INSERT INTO t1 VALUES (48);
+SELECT REGEXP_REPLACE(@@gtid_binlog_pos, ".*\\b(0-1-[0-9]+)\\b.*", "\\1") AS dom0_pos;
+
+
+# Clean up.
+--connection server_1
+DROP TABLE t1;
+
+
+--source include/rpl_end.inc
+
+--echo #
+--echo # Start of 10.2 tests
+--echo #
+
+--echo #
+--echo # MDEV-10134 Add full support for DEFAULT
+--echo #
+
+--error ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED
+CREATE TABLE t1 (a VARCHAR(100) DEFAULT BINLOG_GTID_POS("master-bin.000001", 600));
+
+--echo #
+--echo # End of 10.2 tests
+--echo #
+
+
+--echo #
+--echo # Start of 10.3 tests
+--echo #
+
+--echo #
+--echo # MDEV-13967 Parameter data type control for Item_long_func
+--echo #
+
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT MASTER_GTID_WAIT(ROW(1,1),'str');
+
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT MASTER_GTID_WAIT('str',ROW(1,1));
+
+
+--echo #
+--echo # End of 10.3 tests
+--echo #
diff --git a/mysql-test/suite/rpl/t/rpl_gtid_crash-master.opt b/mysql-test/suite/rpl/t/rpl_gtid_crash-master.opt
new file mode 100644
index 00000000..590d44a6
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_gtid_crash-master.opt
@@ -0,0 +1 @@
+--loose-skip-stack-trace --skip-core-file
diff --git a/mysql-test/suite/rpl/t/rpl_gtid_crash-slave.opt b/mysql-test/suite/rpl/t/rpl_gtid_crash-slave.opt
new file mode 100644
index 00000000..69c1a64e
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_gtid_crash-slave.opt
@@ -0,0 +1 @@
+--master-retry-count=100
diff --git a/mysql-test/suite/rpl/t/rpl_gtid_crash.test b/mysql-test/suite/rpl/t/rpl_gtid_crash.test
new file mode 100644
index 00000000..28329831
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_gtid_crash.test
@@ -0,0 +1,668 @@
+--source include/have_innodb.inc
+--source include/have_debug.inc
+# Valgrind does not work well with test that crashes the server
+--source include/not_valgrind.inc
+
+--let $rpl_topology=1->2
+--source include/rpl_init.inc
+
+--echo *** Test crashing master, causing slave IO thread to reconnect while SQL thread is running ***
+
+--connection server_1
+call mtr.add_suppression("Checking table:");
+call mtr.add_suppression("client is using or hasn't closed the table properly");
+call mtr.add_suppression("Table .* is marked as crashed and should be repaired");
+flush tables;
+
+ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
+CREATE TABLE t1 (a INT PRIMARY KEY, b INT) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1, 0);
+--save_master_pos
+
+--connection server_2
+--sync_with_master
+SET sql_log_bin=0;
+call mtr.add_suppression('Master command COM_REGISTER_SLAVE failed: failed registering on master, reconnecting to try again');
+SET sql_log_bin=1;
+--source include/stop_slave.inc
+--replace_result $MASTER_MYPORT MASTER_PORT
+eval CHANGE MASTER TO master_host = '127.0.0.1', master_port = $MASTER_MYPORT,
+ MASTER_USE_GTID=SLAVE_POS;
+
+--connection server_1
+INSERT INTO t1 VALUES (2,1);
+INSERT INTO t1 VALUES (3,1);
+
+--connection server_2
+--source include/start_slave.inc
+
+--connection server_1
+
+--write_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
+wait-rpl_gtid_crash.test
+EOF
+
+let $1=200;
+--disable_query_log
+while ($1)
+{
+ eval INSERT INTO t1 VALUES ($1 + 10, 2);
+ dec $1;
+}
+--enable_query_log
+--source include/save_master_gtid.inc
+
+SET SESSION debug_dbug="+d,crash_dispatch_command_before";
+--error 2006,2013
+SELECT 1;
+--source include/wait_until_disconnected.inc
+
+--append_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
+restart-rpl_gtid_crash.test
+EOF
+
+--enable_reconnect
+--source include/wait_until_connected_again.inc
+
+--connection server_2
+--source include/sync_with_master_gtid.inc
+
+--connection server_1
+INSERT INTO t1 VALUES (1000, 3);
+--source include/save_master_gtid.inc
+
+--connection server_2
+--source include/sync_with_master_gtid.inc
+
+--connection server_1
+DROP TABLE t1;
+--save_master_pos
+
+--echo *** Test crashing the master mysqld and check that binlog state is recovered. ***
+--connection server_2
+--sync_with_master
+--source include/stop_slave.inc
+RESET MASTER;
+SET GLOBAL gtid_slave_pos='';
+
+--connection server_1
+RESET MASTER;
+--replace_column 2 # 4 # 5 #
+SHOW BINLOG EVENTS IN 'master-bin.000001' LIMIT 1,1;
+CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=InnoDB;
+
+--connection server_2
+--source include/start_slave.inc
+
+--connection server_1
+SET gtid_domain_id= 1;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+FLUSH LOGS;
+SET gtid_domain_id= 2;
+INSERT INTO t1 VALUES (3);
+FLUSH LOGS;
+--source include/show_binary_logs.inc
+--replace_column 2 # 4 # 5 # 6 #
+SHOW BINLOG EVENTS IN 'master-bin.000003' LIMIT 1,1;
+
+--write_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
+wait
+EOF
+
+SET SESSION debug_dbug="+d,crash_dispatch_command_before";
+--error 2006,2013
+SELECT 1;
+--source include/wait_until_disconnected.inc
+
+--append_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
+restart
+EOF
+
+--enable_reconnect
+--source include/wait_until_connected_again.inc
+
+--source include/show_binary_logs.inc
+--replace_column 2 # 4 # 5 # 6 #
+SHOW BINLOG EVENTS IN 'master-bin.000004' LIMIT 1,1;
+--save_master_pos
+
+--connection server_2
+--sync_with_master
+SELECT * FROM t1 ORDER BY a;
+
+
+--echo *** Test crashing slave at various points and check that it recovers crash-safe. ***
+
+# Crash the slave just before updating mysql.gtid_slave_pos table.
+--source include/stop_slave.inc
+--write_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect
+wait
+EOF
+# We do not have to save @@GLOBAL.debug_dbug, it is reset when slave crashes.
+SET GLOBAL debug_dbug="+d,inject_crash_before_write_rpl_slave_state";
+START SLAVE;
+
+--connection server_1
+INSERT INTO t1 VALUES (4);
+--source include/save_master_gtid.inc
+
+--connection server_2
+--source include/wait_until_disconnected.inc
+
+--append_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect
+restart: --skip-slave-start=0
+EOF
+
+--enable_reconnect
+--source include/wait_until_connected_again.inc
+
+--source include/sync_with_master_gtid.inc
+
+# Crash the slave just before committing.
+--source include/stop_slave.inc
+--write_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect
+wait
+EOF
+START SLAVE;
+--error 0,2006,2013
+SET GLOBAL debug_dbug="+d,crash_commit_before";
+
+--connection server_1
+INSERT INTO t1 VALUES (5);
+--source include/save_master_gtid.inc
+
+--connection server_2
+--source include/wait_until_disconnected.inc
+
+--append_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect
+restart: --skip-slave-start=0
+EOF
+
+--enable_reconnect
+--source include/wait_until_connected_again.inc
+
+--source include/sync_with_master_gtid.inc
+
+# Crash the slave just after committing.
+--source include/stop_slave.inc
+--write_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect
+wait
+EOF
+START SLAVE;
+--error 0,2006,2013
+SET GLOBAL debug_dbug="+d,crash_commit_after";
+
+--connection server_1
+INSERT INTO t1 VALUES (6);
+--source include/save_master_gtid.inc
+
+--connection server_2
+--source include/wait_until_disconnected.inc
+
+--append_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect
+restart: --skip-slave-start=0
+EOF
+
+--enable_reconnect
+--source include/wait_until_connected_again.inc
+
+--source include/sync_with_master_gtid.inc
+
+# Crash the slave just before updating relay-log.info
+--source include/stop_slave.inc
+--write_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect
+wait
+EOF
+SET GLOBAL debug_dbug="+d,inject_crash_before_flush_rli";
+--error 0,2006,2013
+START SLAVE;
+
+--connection server_1
+INSERT INTO t1 VALUES (7);
+--source include/save_master_gtid.inc
+
+--connection server_2
+--source include/wait_until_disconnected.inc
+
+--append_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect
+restart: --skip-slave-start=0
+EOF
+
+--enable_reconnect
+--source include/wait_until_connected_again.inc
+
+--source include/sync_with_master_gtid.inc
+
+# Crash the slave just after updating relay-log.info
+--source include/stop_slave.inc
+--write_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect
+wait
+EOF
+SET GLOBAL debug_dbug="+d,inject_crash_after_flush_rli";
+--error 0,2006,2013
+START SLAVE;
+
+--connection server_1
+INSERT INTO t1 VALUES (8);
+--source include/save_master_gtid.inc
+
+--connection server_2
+--source include/wait_until_disconnected.inc
+
+--append_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect
+restart: --skip-slave-start=0
+EOF
+
+--enable_reconnect
+--source include/wait_until_connected_again.inc
+
+--source include/sync_with_master_gtid.inc
+
+
+# Check that everything was replicated correctly.
+SELECT * FROM t1 ORDER BY a;
+
+
+--echo *** MDEV-4725: Incorrect recovery when crash in the middle of writing an event group ***
+
+--connection server_2
+--write_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect
+wait
+EOF
+
+--let $old_gtid_strict= `SELECT @@gtid_strict_mode`
+SET GLOBAL debug_dbug="+d,crash_before_writing_xid";
+
+--connection server_1
+INSERT INTO t1 VALUES (9), (10);
+--let $saved_gtid=`SELECT @@last_gtid`
+--save_master_pos
+
+--connection server_2
+--source include/wait_until_disconnected.inc
+
+# The bug was that during crash recovery we would update the binlog state
+# with the GTID of the half-written event group at the end of the slaves
+# binlog, even though this event group was not committed.
+# We restart the server with gtid_strict_mode; this way, we get an error
+# about duplicate gtid when the slave re-executes the event group, if the
+# binlog crash recovery is incorrect.
+--append_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect
+restart: --gtid_strict_mode=1
+EOF
+
+--enable_reconnect
+--source include/wait_until_connected_again.inc
+
+SHOW VARIABLES like 'gtid_strict_mode';
+--source include/start_slave.inc
+--sync_with_master
+--disable_query_log
+eval SET GLOBAL gtid_strict_mode= $old_gtid_strict;
+--enable_query_log
+
+
+--echo *** MDEV-6462: Incorrect recovery on a slave reconnecting to crashed master ***
+
+--connection server_1
+set sql_log_bin= 0;
+call mtr.add_suppression("Error writing file 'master-bin'");
+set sql_log_bin= 1;
+--connection server_2
+set sql_log_bin= 0;
+call mtr.add_suppression("The server_id of master server changed in the middle of GTID");
+call mtr.add_suppression("Unexpected change of master binlog file name in the middle of GTID");
+set sql_log_bin= 1;
+
+--connection server_1
+--write_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
+wait
+EOF
+
+SET GLOBAL debug_dbug="+d,inject_error_writing_xid";
+BEGIN;
+INSERT INTO t1 VALUES (11);
+--error ER_ERROR_ON_WRITE
+COMMIT;
+SET GLOBAL debug_dbug="+d,crash_dispatch_command_before";
+--error 2006,2013
+COMMIT;
+
+--source include/wait_until_disconnected.inc
+
+# Simulate that we reconnect to a different server (new server_id).
+--append_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
+restart: --server-id=3
+EOF
+
+--enable_reconnect
+--source include/wait_until_connected_again.inc
+
+SELECT @@GLOBAL.server_id;
+SELECT * from t1 WHERE a > 10 ORDER BY a;
+--disable_query_log
+eval SELECT IF(INSTR(@@gtid_binlog_pos, '$saved_gtid'), "Binlog pos ok", CONCAT("Unexpected binlog pos: ", @@gtid_binlog_pos, "; does not contain the GTID $saved_gtid.")) AS gtid_check;
+--enable_query_log
+
+--echo # Wait 60 seconds for SQL thread to catch up with IO thread
+--connection server_2
+--let $wait_timeout= 600
+while ($wait_timeout != 0)
+{
+ --let $read_log_pos= query_get_value('SHOW SLAVE STATUS', Read_Master_Log_Pos, 1)
+ --let $exec_log_pos= query_get_value('SHOW SLAVE STATUS', Exec_Master_Log_Pos, 1)
+ if ($read_log_pos == $exec_log_pos)
+ {
+ --let $wait_timeout= 0
+ }
+ if ($read_log_pos != $exec_log_pos)
+ {
+ --sleep 0.1
+ --dec $wait_timeout
+ }
+}
+if ($read_log_pos != $exec_log_pos)
+{
+ --die Timeout wait for SQL thread to catch up with IO thread
+}
+
+SELECT * from t1 WHERE a > 10 ORDER BY a;
+--disable_query_log
+eval SELECT IF(INSTR(@@gtid_binlog_pos, '$saved_gtid'), "Binlog pos ok", CONCAT("Unexpected binlog pos: ", @@gtid_binlog_pos, "; does not contain the GTID $saved_gtid.")) AS gtid_check;
+eval SELECT IF(INSTR(@@gtid_slave_pos, '$saved_gtid'), "Slave pos ok", CONCAT("Unexpected slave pos: ", @@gtid_slave_pos, "; does not contain the GTID $saved_gtid.")) AS gtid_check;
+eval SELECT IF(INSTR(@@gtid_current_pos, '$saved_gtid'), "Current pos ok", CONCAT("Unexpected current pos: ", @@gtid_current_pos, "; does not contain the GTID $saved_gtid.")) AS gtid_check;
+--enable_query_log
+
+--echo # Repeat this with additional transactions on the master
+
+--connection server_1
+--write_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
+wait
+EOF
+
+SET GLOBAL debug_dbug="+d,inject_error_writing_xid";
+BEGIN;
+INSERT INTO t1 VALUES (12);
+--error ER_ERROR_ON_WRITE
+COMMIT;
+SET GLOBAL debug_dbug="+d,crash_dispatch_command_before";
+--error 2006,2013
+COMMIT;
+
+--source include/wait_until_disconnected.inc
+
+# Simulate that we reconnect to a different server (new server_id).
+--append_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
+restart: --server-id=1
+EOF
+
+--enable_reconnect
+--source include/wait_until_connected_again.inc
+
+SELECT @@GLOBAL.server_id;
+INSERT INTO t1 VALUES (13);
+INSERT INTO t1 VALUES (14);
+--let $saved_gtid=`SELECT @@last_gtid`
+SELECT * from t1 WHERE a > 10 ORDER BY a;
+--source include/save_master_gtid.inc
+
+--connection server_2
+--source include/sync_with_master_gtid.inc
+SELECT * from t1 WHERE a > 10 ORDER BY a;
+
+--connection server_1
+--write_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
+wait
+EOF
+
+SET GLOBAL debug_dbug="+d,inject_error_writing_xid";
+BEGIN;
+INSERT INTO t1 VALUES (21);
+--error ER_ERROR_ON_WRITE
+COMMIT;
+SET GLOBAL debug_dbug="+d,crash_dispatch_command_before";
+--error 2006,2013
+COMMIT;
+
+--source include/wait_until_disconnected.inc
+
+# Simulate that we reconnect to the same server (same server_id).
+--append_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
+restart
+EOF
+
+--enable_reconnect
+--source include/wait_until_connected_again.inc
+
+SELECT @@GLOBAL.server_id;
+SELECT * from t1 WHERE a > 10 ORDER BY a;
+--disable_query_log
+eval SELECT IF(INSTR(@@gtid_binlog_pos, '$saved_gtid'), "Binlog pos ok", CONCAT("Unexpected binlog pos: ", @@gtid_binlog_pos, "; does not contain the GTID $saved_gtid.")) AS gtid_check;
+eval SELECT IF(INSTR(@@gtid_current_pos, '$saved_gtid'), "Current pos ok", CONCAT("Unexpected current pos: ", @@gtid_current_pos, "; does not contain the GTID $saved_gtid.")) AS gtid_check;
+--enable_query_log
+
+--echo # Wait 60 seconds for SQL thread to catch up with IO thread
+--connection server_2
+--let $wait_timeout= 600
+while ($wait_timeout != 0)
+{
+ --let $read_log_pos= query_get_value('SHOW SLAVE STATUS', Read_Master_Log_Pos, 1)
+ --let $exec_log_pos= query_get_value('SHOW SLAVE STATUS', Exec_Master_Log_Pos, 1)
+ if ($read_log_pos == $exec_log_pos)
+ {
+ --let $wait_timeout= 0
+ }
+ if ($read_log_pos != $exec_log_pos)
+ {
+ --sleep 0.1
+ --dec $wait_timeout
+ }
+}
+if ($read_log_pos != $exec_log_pos)
+{
+ --die Timeout wait for SQL thread to catch up with IO thread
+}
+
+SELECT * from t1 WHERE a > 10 ORDER BY a;
+--disable_query_log
+eval SELECT IF(INSTR(@@gtid_binlog_pos, '$saved_gtid'), "Binlog pos ok", CONCAT("Unexpected binlog pos: ", @@gtid_binlog_pos, "; does not contain the GTID $saved_gtid.")) AS gtid_check;
+eval SELECT IF(INSTR(@@gtid_slave_pos, '$saved_gtid'), "Slave pos ok", CONCAT("Unexpected slave pos: ", @@gtid_slave_pos, "; does not contain the GTID $saved_gtid.")) AS gtid_check;
+eval SELECT IF(INSTR(@@gtid_current_pos, '$saved_gtid'), "Current pos ok", CONCAT("Unexpected current pos: ", @@gtid_current_pos, "; does not contain the GTID $saved_gtid.")) AS gtid_check;
+--enable_query_log
+
+--echo # Repeat this with additional transactions on the master
+
+--connection server_1
+--write_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
+wait
+EOF
+
+SET GLOBAL debug_dbug="+d,inject_error_writing_xid";
+BEGIN;
+INSERT INTO t1 VALUES (22);
+--error ER_ERROR_ON_WRITE
+COMMIT;
+SET GLOBAL debug_dbug="+d,crash_dispatch_command_before";
+--error 2006,2013
+COMMIT;
+
+--source include/wait_until_disconnected.inc
+
+--append_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
+restart
+EOF
+
+--enable_reconnect
+--source include/wait_until_connected_again.inc
+
+INSERT INTO t1 VALUES (23);
+INSERT INTO t1 VALUES (24);
+--let $saved_gtid=`SELECT @@last_gtid`
+SELECT * from t1 WHERE a > 10 ORDER BY a;
+--source include/save_master_gtid.inc
+
+--connection server_2
+--source include/sync_with_master_gtid.inc
+SELECT * from t1 WHERE a > 10 ORDER BY a;
+
+--echo # Repeat this with slave restart
+
+--connection server_1
+--write_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
+wait
+EOF
+
+SET GLOBAL debug_dbug="+d,inject_error_writing_xid";
+BEGIN;
+INSERT INTO t1 VALUES (25);
+--error ER_ERROR_ON_WRITE
+COMMIT;
+SET GLOBAL debug_dbug="+d,crash_dispatch_command_before";
+--error 2006,2013
+COMMIT;
+
+--source include/wait_until_disconnected.inc
+
+--append_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
+restart
+EOF
+
+--connection server_1
+--enable_reconnect
+--source include/wait_until_connected_again.inc
+
+--connection server_2
+--echo # Wait 60 seconds for IO thread to connect and SQL thread to catch up
+--echo # with IO thread.
+--let $wait_timeout= 600
+while ($wait_timeout != 0)
+{
+ --let $connected=`SELECT COUNT(*) > 0 FROM information_schema.processlist WHERE State = 'Waiting for master to send event'`
+ if ($connected)
+ {
+ --let $read_log_pos= query_get_value('SHOW SLAVE STATUS', Read_Master_Log_Pos, 1)
+ --let $exec_log_pos= query_get_value('SHOW SLAVE STATUS', Exec_Master_Log_Pos, 1)
+ if ($read_log_pos == $exec_log_pos)
+ {
+ --let $wait_timeout= 0
+ }
+ if ($read_log_pos != $exec_log_pos)
+ {
+ --sleep 0.1
+ --dec $wait_timeout
+ }
+ }
+ if (!$connected)
+ {
+ --sleep 0.1
+ --dec $wait_timeout
+ }
+}
+if (`SELECT NOT $connected OR $read_log_pos != $exec_log_pos`)
+{
+ --die Timeout wait for IO thread to connect and SQL thread to catch up with IO thread
+}
+
+--source include/stop_slave.inc
+
+--connection server_1
+--disable_query_log
+eval SELECT IF(INSTR(@@gtid_binlog_pos, '$saved_gtid'), "Binlog pos ok", CONCAT("Unexpected binlog pos: ", @@gtid_binlog_pos, "; does not contain the GTID $saved_gtid.")) AS gtid_check;
+eval SELECT IF(INSTR(@@gtid_current_pos, '$saved_gtid'), "Current pos ok", CONCAT("Unexpected current pos: ", @@gtid_current_pos, "; does not contain the GTID $saved_gtid.")) AS gtid_check;
+--enable_query_log
+INSERT INTO t1 VALUES (26);
+INSERT INTO t1 VALUES (27);
+SELECT * from t1 WHERE a > 10 ORDER BY a;
+--source include/save_master_gtid.inc
+
+--connection server_2
+--disable_query_log
+eval SELECT IF(INSTR(@@gtid_binlog_pos, '$saved_gtid'), "Binlog pos ok", CONCAT("Unexpected binlog pos: ", @@gtid_binlog_pos, "; does not contain the GTID $saved_gtid.")) AS gtid_check;
+eval SELECT IF(INSTR(@@gtid_slave_pos, '$saved_gtid'), "Slave pos ok", CONCAT("Unexpected slave pos: ", @@gtid_slave_pos, "; does not contain the GTID $saved_gtid.")) AS gtid_check;
+eval SELECT IF(INSTR(@@gtid_current_pos, '$saved_gtid'), "Current pos ok", CONCAT("Unexpected current pos: ", @@gtid_current_pos, "; does not contain the GTID $saved_gtid.")) AS gtid_check;
+--enable_query_log
+--source include/start_slave.inc
+--source include/sync_with_master_gtid.inc
+SELECT * from t1 WHERE a > 10 ORDER BY a;
+
+
+--echo *** MDEV-6391: GTID binlog state not recovered if mariadb-bin.state is removed ***
+
+--connection server_2
+--source include/stop_slave.inc
+
+# Do some misc. transactions, stop the master, drop the master-bin.state file.
+# Start the master back up, check that binlog state is correct.
+
+--connection server_1
+
+INSERT INTO t1 VALUES (30);
+SET @old_server_id= @@server_id;
+SET @old_domain_id= @@gtid_domain_id;
+
+SET SESSION server_id= 10;
+INSERT INTO t1 VALUES (31);
+INSERT INTO t1 VALUES (32);
+SET SESSION gtid_domain_id= 1;
+SET SESSION server_id=11;
+INSERT INTO t1 VALUES (33);
+SET SESSION gtid_domain_id= 2;
+INSERT INTO t1 VALUES (34);
+SET SESSION server_id= 10;
+INSERT INTO t1 VALUES (35);
+INSERT INTO t1 VALUES (36);
+SET SESSION gtid_domain_id= 0;
+SET SESSION server_id= 12;
+INSERT INTO t1 VALUES (37);
+SET SESSION gtid_domain_id= @old_domain_id;
+SET SESSION server_id= @old_server_id;
+INSERT INTO t1 VALUES (38);
+INSERT INTO t1 VALUES (39);
+SELECT * FROM t1 WHERE a >= 30 ORDER BY a;
+--source include/save_master_gtid.inc
+
+--let OLD_STATE= `SELECT @@gtid_binlog_state`
+
+--let $datadir= `SELECT @@datadir`
+
+--write_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
+wait
+EOF
+shutdown_server;
+--source include/wait_until_disconnected.inc
+
+--remove_file $datadir/master-bin.state
+
+--append_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
+restart
+EOF
+--enable_reconnect
+--source include/wait_until_connected_again.inc
+
+--let NEW_STATE= `SELECT @@gtid_binlog_state`
+
+--perl
+my $old= $ENV{'OLD_STATE'};
+my $new= $ENV{'NEW_STATE'};
+# Make them order-independent, for easy comparison.
+$old= join(",", sort(split(",", $old)));
+$new= join(",", sort(split(",", $new)));
+die "ERROR: new binlog state '$new' differs from old '$old'\n"
+ unless $old eq $new;
+EOF
+
+--connection server_2
+--source include/start_slave.inc
+--source include/sync_with_master_gtid.inc
+SELECT * FROM t1 WHERE a >= 30 ORDER BY a;
+
+
+--connection server_1
+DROP TABLE t1;
+
+--connection default
+--enable_reconnect
+--source include/wait_until_connected_again.inc
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_gtid_crash_myisam-master.opt b/mysql-test/suite/rpl/t/rpl_gtid_crash_myisam-master.opt
new file mode 100644
index 00000000..16d8af5b
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_gtid_crash_myisam-master.opt
@@ -0,0 +1 @@
+--loose-skip-stack-trace --skip-core-file --skip-innodb
diff --git a/mysql-test/suite/rpl/t/rpl_gtid_crash_myisam.test b/mysql-test/suite/rpl/t/rpl_gtid_crash_myisam.test
new file mode 100644
index 00000000..faf388f5
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_gtid_crash_myisam.test
@@ -0,0 +1,64 @@
+--source include/have_debug.inc
+# Valgrind does not work well with test that crashes the server
+--source include/not_valgrind.inc
+
+--let $rpl_topology=1->2
+--source include/rpl_init.inc
+
+--echo *** Test crashing master with InnoDB disabled, the binlog gtid state should still be correctly recovered. ***
+
+--connection server_1
+CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=MyISAM;
+--save_master_pos
+
+--connection server_2
+--sync_with_master
+--source include/stop_slave.inc
+CHANGE MASTER TO master_use_gtid=slave_pos;
+--source include/start_slave.inc
+
+--connection server_1
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+--save_master_pos
+
+--connection server_2
+--sync_with_master
+SELECT * FROM t1 ORDER BY a;
+
+--connection server_1
+
+--write_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
+wait
+EOF
+
+FLUSH TABLES;
+SET SESSION debug_dbug="+d,crash_dispatch_command_before";
+--error 2006,2013
+SELECT 1;
+
+--source include/wait_until_disconnected.inc
+
+--append_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
+restart-rpl_gtid_crash.test
+EOF
+
+--connection server_1
+--enable_reconnect
+--source include/wait_until_connected_again.inc
+
+INSERT INTO t1 VALUES (3);
+--save_master_pos
+
+--connection server_2
+--sync_with_master
+SELECT * FROM t1 ORDER BY a;
+
+--connection server_1
+DROP TABLE t1;
+
+--connection default
+--enable_reconnect
+--source include/wait_until_connected_again.inc
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_gtid_delete_domain.test b/mysql-test/suite/rpl/t/rpl_gtid_delete_domain.test
new file mode 100644
index 00000000..5537b6fb
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_gtid_delete_domain.test
@@ -0,0 +1,101 @@
+# In case master's gtid binlog state is divergent from the slave's gtid_slave_pos
+# slave may not be able to connect.
+# For instance when slave is more updated in some of domains, see
+# MDEV-12012 as example, the master's state may require adjustment.
+# In a specific case of an "old" divergent domain, that is there
+# won't be no more event groups from it generated, the states can be
+# made compatible with wiping the problematic domain away. After that slave
+# becomes connectable.
+#
+# Notice that the slave applied gtid state is not really required to
+# be similarly cleaned in order for replication to flow.
+# However this could lead to an expected error when the master
+# resumes binlogging of such domain which the test demonstrate.
+
+--source include/master-slave.inc
+
+--connection master
+# enforce the default domain_id binlogging explicitly
+SET @@SESSION.gtid_domain_id=0;
+CREATE TABLE t (a INT);
+--sync_slave_with_master
+
+--connection slave
+call mtr.add_suppression("connecting slave requested to start from.*which is not in the master's binlog");
+
+--source include/stop_slave.inc
+CHANGE MASTER TO master_use_gtid=slave_pos;
+
+--connection master
+# create extra gtid domains for binlog state
+--let $extra_domain_id=11
+--let $extra_domain_server_id=111
+--let $extra_gtid_seq_no=1
+--eval SET @@SESSION.gtid_domain_id=$extra_domain_id
+--eval SET @@SESSION.server_id=$extra_domain_server_id
+--eval SET @@SESSION.gtid_seq_no=$extra_gtid_seq_no
+INSERT INTO t SET a=1;
+
+#
+# Set up the slave replication state as if slave knows more events from the extra
+# domain.
+#
+--connection slave
+SET @save.gtid_slave_pos=@@global.gtid_slave_pos;
+--eval SET @@global.gtid_slave_pos=concat(@@global.gtid_slave_pos, ",", $extra_domain_id, "-", $extra_domain_server_id, "-", $extra_gtid_seq_no + 1)
+
+# unsuccessful attempt to start slave
+START SLAVE IO_THREAD;
+--let $slave_io_errno=1236
+--source include/wait_for_slave_io_error.inc
+
+--connection master
+# adjust the master binlog state
+FLUSH BINARY LOGS;
+--let $purge_to_binlog= query_get_value(SHOW MASTER STATUS, File, 1)
+--let $purge_binlogs_to=$purge_to_binlog
+--source include/wait_for_purge.inc
+
+# with final removal of the extra domain
+--eval FLUSH BINARY LOGS DELETE_DOMAIN_ID=($extra_domain_id)
+SELECT @@global.gtid_binlog_pos, @@global.gtid_binlog_state;
+
+--connection slave
+SELECT @@global.gtid_slave_pos;
+# start the slave sucessfully
+--let rpl_debug=1
+--source include/start_slave.inc
+--let rpl_debug=0
+
+--connection master
+# but the following gtid from the *extra* domain will break replication
+INSERT INTO t SET a=1;
+
+# take note of the slave io thread error due to being dismissed
+# extra domain at connection to master which tried becoming active;
+# slave is to stop.
+--connection slave
+--let $errno=1236
+--source include/wait_for_slave_io_error.inc
+
+# let's apply the very same medicine
+--connection master
+FLUSH BINARY LOGS;
+--let $purge_to_binlog= query_get_value(SHOW MASTER STATUS, File, 1)
+--eval PURGE BINARY LOGS TO '$purge_to_binlog';
+# with final removal of the extra domain
+--eval FLUSH BINARY LOGS DELETE_DOMAIN_ID=($extra_domain_id)
+
+--connection slave
+--source include/start_slave.inc
+
+#
+# cleanup
+#
+--connection master
+SET @@SESSION.gtid_domain_id=0;
+DROP TABLE t;
+
+sync_slave_with_master;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_gtid_errorhandling.test b/mysql-test/suite/rpl/t/rpl_gtid_errorhandling.test
new file mode 100644
index 00000000..412489b3
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_gtid_errorhandling.test
@@ -0,0 +1,291 @@
+--source include/have_innodb.inc
+--source include/have_debug.inc
+--source include/master-slave.inc
+
+--echo *** Test that we check against incorrect table definition for mysql.gtid_slave_pos ***
+--connection master
+CREATE TABLE t1(a INT PRIMARY KEY) ENGINE=InnoDB;
+call mtr.add_suppression("Incorrect definition of table mysql.gtid_slave_pos:.*");
+--sync_slave_with_master
+
+--connection slave
+--source include/stop_slave.inc
+ALTER TABLE mysql.gtid_slave_pos CHANGE seq_no seq_no VARCHAR(20);
+START SLAVE;
+
+--connection master
+INSERT INTO t1 VALUES (1);
+
+--connection slave
+CALL mtr.add_suppression("Slave: Failed to open mysql.gtid_slave_pos");
+--let $slave_sql_errno=1944
+--source include/wait_for_slave_sql_error.inc
+
+--source include/stop_slave.inc
+ALTER TABLE mysql.gtid_slave_pos CHANGE seq_no seq_no BIGINT UNSIGNED NOT NULL;
+ALTER TABLE mysql.gtid_slave_pos DROP PRIMARY KEY;
+ALTER TABLE mysql.gtid_slave_pos ADD PRIMARY KEY (sub_id, domain_id);
+START SLAVE;
+--let $slave_sql_errno=1944
+--source include/wait_for_slave_sql_error.inc
+
+--source include/stop_slave.inc
+ALTER TABLE mysql.gtid_slave_pos DROP PRIMARY KEY;
+START SLAVE;
+--let $slave_sql_errno=1944
+--source include/wait_for_slave_sql_error.inc
+
+--source include/stop_slave.inc
+ALTER TABLE mysql.gtid_slave_pos ADD PRIMARY KEY (sub_id);
+START SLAVE;
+--let $slave_sql_errno=1944
+--source include/wait_for_slave_sql_error.inc
+
+--source include/stop_slave.inc
+ALTER TABLE mysql.gtid_slave_pos DROP PRIMARY KEY;
+ALTER TABLE mysql.gtid_slave_pos ADD PRIMARY KEY (domain_id, sub_id);
+--source include/start_slave.inc
+
+--connection master
+--sync_slave_with_master
+
+--connection slave
+SELECT * FROM t1;
+
+
+--echo *** Test that setting @@gtid_domain_id or @@gtid_seq_no is not allowed inside a transaction. ***
+BEGIN;
+INSERT INTO t1 VALUES (100);
+--error ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_GTID_DOMAIN_ID_SEQ_NO
+SET SESSION gtid_domain_id= 100;
+--error ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_GTID_DOMAIN_ID_SEQ_NO
+SET SESSION gtid_seq_no= 100;
+SET @old_domain= @@GLOBAL.gtid_domain_id;
+SET GLOBAL gtid_domain_id= 100;
+SELECT @@SESSION.gtid_domain_id;
+SET GLOBAL gtid_domain_id= @old_domain;
+INSERT INTO t1 VALUES (101);
+SELECT * FROM t1 ORDER BY a;
+ROLLBACK;
+SELECT * FROM t1 ORDER BY a;
+
+
+--echo *** Test requesting an explicit GTID position that conflicts with newer GTIDs of our own in the binlog. ***
+--connection slave
+--source include/stop_slave.inc
+
+--connection master
+RESET MASTER;
+# This insert will be GTID 0-1-1
+INSERT INTO t1 VALUES (2);
+# And this will be GTID 0-1-2
+INSERT INTO t1 VALUES (4);
+--source include/save_master_gtid.inc
+
+--connection slave
+SET sql_log_bin = 0;
+INSERT INTO t1 VALUES (2);
+SET sql_log_bin = 1;
+INSERT INTO t1 VALUES (3);
+
+CHANGE MASTER TO master_use_gtid=current_pos;
+# Most not change @@GLOBAL.gtid_slave_pos in the middle of a transaction.
+BEGIN;
+--error ER_CANT_DO_THIS_DURING_AN_TRANSACTION
+SET GLOBAL gtid_slave_pos = "100-100-100";
+INSERT INTO t1 VALUES (100);
+--error ER_CANT_DO_THIS_DURING_AN_TRANSACTION
+SET GLOBAL gtid_slave_pos = "100-100-100";
+ROLLBACK;
+
+# In gtid non-strict mode, we get warnings for setting @@gtid_slave_pos back
+# to earlier than what is in the binlog. In strict mode, we get an error.
+SET GLOBAL gtid_strict_mode= 1;
+--error ER_MASTER_GTID_POS_CONFLICTS_WITH_BINLOG
+SET GLOBAL gtid_slave_pos = "0-1-1";
+--error ER_MASTER_GTID_POS_MISSING_DOMAIN
+SET GLOBAL gtid_slave_pos = "";
+SET GLOBAL gtid_strict_mode= 0;
+SET GLOBAL gtid_slave_pos = "0-1-1";
+SET GLOBAL gtid_slave_pos = "";
+RESET MASTER;
+SET GLOBAL gtid_slave_pos = "0-1-1";
+
+START SLAVE;
+--source include/sync_with_master_gtid.inc
+SELECT * FROM t1 ORDER BY a;
+
+--echo *** MDEV-4688: Empty value of @@GLOBAL.gtid_slave_pos ***
+# The problem was that record_gtid() deleted too much of the in-memory state,
+# leaving the state empty until after commit when we add the newly committed
+# GTID. Test this by forcing an error after the delete of the old data but
+# before the add of new data.
+
+--source include/stop_slave.inc
+
+--connection master
+# This will be GTID 0-1-3
+INSERT INTO t1 VALUES (5);
+--source include/save_master_gtid.inc
+
+--connection slave
+SET @old_dbug= @@GLOBAL.debug_dbug;
+SET GLOBAL debug_dbug="+d,dummy_disable_default_dbug_output";
+SET GLOBAL debug_dbug="+d,gtid_fail_after_record_gtid";
+SET sql_log_bin=0;
+CALL mtr.add_suppression('Got error 131 "Command not supported by the engine" during COMMIT');
+SET sql_log_bin=1;
+START SLAVE;
+--let $slave_sql_errno= 1180
+--source include/wait_for_slave_sql_error.inc
+# The bug was that @@GLOBAL.gtid_slave_pos was empty here.
+SELECT @@GLOBAL.gtid_slave_pos;
+SELECT * FROM t1 ORDER BY a;
+SET GLOBAL debug_dbug= @old_dbug;
+START SLAVE SQL_THREAD;
+--source include/sync_with_master_gtid.inc
+SELECT * FROM t1 ORDER BY a;
+
+
+--echo *** Test slave requesting a GTID that is not present in the master's binlog ***
+--source include/stop_slave.inc
+SET GLOBAL gtid_slave_pos = "0-1-4";
+START SLAVE;
+
+SET sql_log_bin=0;
+CALL mtr.add_suppression("Got fatal error .* from master when reading data from binary log: 'Error: connecting slave requested to start from GTID .*, which is not in the master's binlog'");
+SET sql_log_bin=1;
+--let $slave_io_errno= 1236
+--source include/wait_for_slave_io_error.inc
+--let $status_items= Slave_IO_State, Last_IO_Errno, Last_IO_Error, Using_Gtid
+--source include/show_slave_status.inc
+
+--let $rpl_only_running_threads= 1
+--source include/stop_slave.inc
+SET GLOBAL gtid_slave_pos = "0-1-3";
+START SLAVE;
+--source include/wait_for_slave_to_start.inc
+
+--connection master
+INSERT INTO t1 VALUES (6);
+--source include/save_master_gtid.inc
+
+--connection slave
+--source include/sync_with_master_gtid.inc
+SELECT * FROM t1 ORDER BY a;
+
+
+--echo *** MDEV-4278: Slave does not detect that master is not GTID-aware ***
+
+--connection slave
+--source include/stop_slave.inc
+
+--connection master
+SET @old_dbug= @@global.DEBUG_DBUG;
+SET GLOBAL debug_dbug="+d,simulate_non_gtid_aware_master";
+
+--connection slave
+START SLAVE;
+--let $slave_io_errno= 1233
+--source include/wait_for_slave_io_error.inc
+
+--connection master
+SET GLOBAL debug_dbug= @old_dbug;
+INSERT INTO t1 VALUES (7);
+--save_master_pos
+
+--connection slave
+START SLAVE;
+--sync_with_master
+SET sql_log_bin=0;
+CALL mtr.add_suppression("The slave I/O thread stops because master does not support MariaDB global transaction id");
+SET sql_log_bin=1;
+
+
+--echo *** Test error during record_gtid() (non-xid cases) ***
+
+--connection slave
+--source include/stop_slave.inc
+
+--connection master
+CREATE TABLE t2 (a INT) ENGINE=MyISAM;
+INSERT INTO t2 VALUES (1);
+--save_master_pos
+
+--connection slave
+SET @old_dbug= @@global.DEBUG_DBUG;
+SET GLOBAL debug_dbug="+d,gtid_inject_record_gtid";
+
+START SLAVE;
+--let $slave_sql_errno= 1942
+--source include/wait_for_slave_sql_error.inc
+
+SET GLOBAL debug_dbug= @old_dbug;
+
+START SLAVE SQL_THREAD;
+--sync_with_master
+
+SELECT * FROM t2;
+SET sql_log_bin=0;
+CALL mtr.add_suppression("Slave: Could not update replication slave gtid state");
+SET sql_log_bin=1;
+
+
+--echo *** MDEV-4906: When event apply fails, next SQL thread start erroneously commits the failing GTID to gtid_slave_pos ***
+
+--connection slave
+--source include/stop_slave.inc
+SET sql_log_bin=0;
+DELETE FROM t2;
+SET sql_log_bin=1;
+SET @old_format=@@binlog_format;
+SET GLOBAL binlog_format='row';
+--source include/start_slave.inc
+
+--connection master
+SET @old_format=@@binlog_format;
+SET binlog_format='row';
+--let $gtid_pos1=`SELECT @@GLOBAL.gtid_binlog_pos`
+DELETE FROM t2;
+SET binlog_format=@old_format;
+--save_master_pos
+
+--connection slave
+--let $slave_sql_errno= 1032
+--source include/wait_for_slave_sql_error.inc
+# Disable query to avoid result file update if precise GTID value changes.
+--disable_query_log
+SET @x=@@GLOBAL.gtid_slave_pos;
+eval SELECT IF(@x='$gtid_pos1', "OK", CONCAT("ERROR: expected $gtid_pos1 got ", @x)) AS result;
+--enable_query_log
+
+# The bug was that upon restarting the SQL thread, the GTID for the
+# failing event group was not cleared, so we would update it in the
+# gtid_slave_pos as part of the first rotate event, corrupting the
+# replication.
+STOP SLAVE IO_THREAD;
+START SLAVE;
+--let $slave_sql_errno= 1032
+--source include/wait_for_slave_sql_error.inc
+# Disable query to avoid result file update if precise GTID value changes.
+--disable_query_log
+SET @x=@@GLOBAL.gtid_slave_pos;
+eval SELECT IF(@x='$gtid_pos1', "OK", CONCAT("ERROR: expected $gtid_pos1 got ", @x)) AS result;
+--enable_query_log
+
+STOP SLAVE IO_THREAD;
+SET sql_log_bin=0;
+INSERT INTO t2 VALUES (1);
+CALL mtr.add_suppression("Slave: Can't find record in 't2' Error_code: 1032");
+SET sql_log_bin=1;
+--source include/start_slave.inc
+--sync_with_master
+SET GLOBAL binlog_format=@old_format;
+
+--connection master
+DROP TABLE t1;
+DROP TABLE t2;
+
+call mtr.add_suppression("Can't find record in 't2'");
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_gtid_errorlog.test b/mysql-test/suite/rpl/t/rpl_gtid_errorlog.test
new file mode 100644
index 00000000..ea321062
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_gtid_errorlog.test
@@ -0,0 +1,85 @@
+--source include/have_debug.inc
+--source include/master-slave.inc
+
+connection master;
+SET GLOBAL BINLOG_CHECKSUM=NONE;
+connection slave;
+SET GLOBAL BINLOG_CHECKSUM=NONE;
+
+--echo *** Test MDEV-6120, output of current GTID when a replication error is logged to the errorlog ***
+--connection master
+CREATE TABLE t1(a INT PRIMARY KEY);
+--sync_slave_with_master
+
+--connection slave
+--source include/stop_slave.inc
+CHANGE MASTER TO master_use_gtid=slave_pos;
+
+--connection master
+INSERT INTO t1 VALUES (1);
+SET gtid_seq_no=100;
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+--save_master_pos
+
+--connection slave
+SET sql_log_bin=0;
+INSERT INTO t1 VALUES (2);
+SET sql_log_bin=1;
+
+START SLAVE;
+--let $slave_sql_errno=1062
+--source include/wait_for_slave_sql_error.inc
+
+--source include/stop_slave.inc
+# Skip the problem event from the master.
+SET GLOBAL gtid_slave_pos= "0-1-100";
+--source include/start_slave.inc
+--sync_with_master
+
+SELECT * FROM t1 ORDER BY a;
+
+--connection master
+
+SET @dbug_save= @@debug_dbug;
+SET debug_dbug= '+d,incident_database_resync_on_replace';
+REPLACE INTO t1 VALUES (5);
+SET debug_dbug= @dbug_save;
+--save_master_pos
+
+--connection slave
+--let $slave_sql_errno=1590
+--source include/wait_for_slave_sql_error.inc
+--source include/stop_slave.inc
+SET sql_slave_skip_counter=1;
+--source include/start_slave.inc
+--sync_with_master
+
+SELECT * FROM t1 ORDER BY a;
+
+
+# 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.2.err;
+}
+--let SEARCH_FILE=$log_error_
+--let SEARCH_PATTERN=Slave SQL: Error 'Duplicate entry .* on query\. .*Query: '.*', Gtid 0-1-100, Internal MariaDB error code:|Slave SQL: Could not execute Write_rows.*table test.t1; Duplicate entry.*, Gtid 0-1-100, Internal MariaDB error
+--source include/search_pattern_in_file.inc
+--let SEARCH_PATTERN=Slave SQL: The incident LOST_EVENTS occurred on the master\. Message: <none>, Internal MariaDB error code: 1590
+--source include/search_pattern_in_file.inc
+
+
+--connection master
+DROP TABLE t1;
+
+connection master;
+SET GLOBAL BINLOG_CHECKSUM=default;
+connection slave;
+SET GLOBAL BINLOG_CHECKSUM=default;
+connection master;
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_gtid_excess_initial_delay.test b/mysql-test/suite/rpl/t/rpl_gtid_excess_initial_delay.test
new file mode 100644
index 00000000..6b1eec19
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_gtid_excess_initial_delay.test
@@ -0,0 +1,58 @@
+# ==== Purpose ====
+#
+# Test verifies that when "Master_Delay" is specified on slave with GTIDS there
+# will not be any extra delay initially.
+#
+# ==== Implementation ====
+#
+# Steps:
+# 0 - Stop the slave and execute CHANGE MASTER command with
+# master_delay= 10
+# 1 - On slave introduce a sleep of 15 seconds and check that the
+# Seconds_Behind_Master is within specified master_delay limit. It should
+# not be more that "10" seconds.
+#
+# ==== References ====
+#
+# MDEV-13895: GTID and Master_Delay causes excessive initial delay
+
+--source include/have_binlog_format_mixed.inc
+--source include/master-slave.inc
+
+CREATE TABLE t1 (i INT);
+--sync_slave_with_master
+
+--source include/stop_slave.inc
+CHANGE MASTER TO MASTER_DELAY= 10;
+--source include/start_slave.inc
+
+--connection master
+INSERT INTO t1 VALUES (1);
+--source include/sync_slave_io_with_master.inc
+
+--connection slave
+--let $actual_delay= query_get_value(SHOW SLAVE STATUS, SQL_Delay, 1)
+--let $sleep_time= `SELECT 5 + $actual_delay`
+--echo "Sleeping for $sleep_time"
+--sleep $sleep_time
+
+--let $assert_cond= [SHOW SLAVE STATUS, Seconds_Behind_Master, 1] <= 10
+--let $assert_text= Seconds_Behind_Master should be less than MASTER_DELAY
+--source include/rpl_assert.inc
+
+# The row should be available in table after master_delay=20 seconds.
+--let $assert_text= One row shoule be found in table t1.
+--let $assert_cond= COUNT(*) = 1 FROM t1
+--source include/rpl_assert.inc
+
+--echo "======= Clean up ========"
+STOP SLAVE;
+CHANGE MASTER TO MASTER_DELAY=0;
+START SLAVE;
+
+--connection master
+DROP TABLE t1;
+--sync_slave_with_master
+
+--connection master
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_gtid_glle_no_terminate.test b/mysql-test/suite/rpl/t/rpl_gtid_glle_no_terminate.test
new file mode 100644
index 00000000..f0f38a31
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_gtid_glle_no_terminate.test
@@ -0,0 +1,72 @@
+#
+# Purpose:
+# If a fake Glle event follows a Gtid event, we need to ensure the rest of
+# the group should not terminate at the Glle event. MDEV-28550 revealed that
+# a Glle would terminate the event and upon reconnect, the DDL would be lost.
+#
+# Methodology:
+# Force the primary to send a fake GLLE event after a GTID on a "reconnect"
+# and ensure that both 1) the replica does not error, and 2) the original
+# command within the GTID is executed.
+#
+# References:
+# MDEV-28550: improper handling of replication event group that contains Gtid_log_list_event
+
+--source include/master-slave.inc
+
+# Independent of binlog format
+--source include/have_binlog_format_statement.inc
+
+--connection slave
+--source include/stop_slave.inc
+CHANGE MASTER TO MASTER_USE_GTID=slave_pos;
+
+--echo #
+--echo # Initialize test data
+--connection master
+create table t1 (a int);
+SET @@session.server_id= 3;
+create table t2 (a int);
+--source include/save_master_gtid.inc
+
+--echo #
+--echo # Have the replica "reconnect" and the primary will send Gtid, Glle, DDL
+--connection slave
+eval set global gtid_slave_pos="0-3-1";
+--source include/start_slave.inc
+--source include/sync_with_master_gtid.inc
+
+--echo #
+--echo # Ensure that the replica did not error
+connection slave;
+--source include/sync_with_master_gtid.inc
+let $error= query_get_value(SHOW SLAVE STATUS, Last_SQL_Error, 1);
+--echo Last_SQL_Error = $error
+let $errno= query_get_value(SHOW SLAVE STATUS, Last_SQL_Errno, 1);
+--echo Last_SQL_Errno = $errno
+
+--echo #
+--echo # Ensure that the primary sent a Glle after a Gtid event
+let $binlog_file= query_get_value(SHOW SLAVE STATUS, Relay_Log_File, 1);
+let $binlog_start= $relaylog_start;
+let $binlog_limit=0,10;
+--source include/show_relaylog_events.inc
+
+--echo #
+--echo # Ensure the DDL was executed on the replica
+if (!`SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = 'test' AND table_name = 't2'`)
+{
+ die "t2 should exist on slave";
+}
+
+--echo #
+--echo # Cleanup
+
+--echo # t1 does not make it to the replica
+--connection master
+set sql_log_bin=0;
+DROP TABLE t1;
+set sql_log_bin=1;
+DROP TABLE t2;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_gtid_grouping.test b/mysql-test/suite/rpl/t/rpl_gtid_grouping.test
new file mode 100644
index 00000000..66448c4f
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_gtid_grouping.test
@@ -0,0 +1,97 @@
+# ==== Purpose ====
+#
+# Test verifies that replicated transaction boundaries are set properly
+# at receiving from master time.
+#
+# ==== Implementation ====
+#
+# A. Simulate an unnoticeable loss of Xid event to observe a slave error,
+# then restart slave to recover from the failure.
+# B. Do the same to GTID event.
+#
+# ==== References ====
+#
+# MDEV-27697 slave must recognize incomplete replication event group
+#
+--source include/have_binlog_format_mixed.inc
+--source include/have_innodb.inc
+--source include/have_debug.inc
+--source include/master-slave.inc
+
+--connection slave
+call mtr.add_suppression("Unexpected break of being relay-logged GTID 0-27697-1000");
+call mtr.add_suppression("Relay log write failure: could not queue event from master");
+call mtr.add_suppression("The current group of events starts with a non-GTID");
+
+--source include/stop_slave.inc
+CHANGE MASTER TO MASTER_USE_GTID=slave_pos;
+--source include/start_slave.inc
+
+--connection master
+CREATE TABLE t (a INT) ENGINE=innodb;
+INSERT INTO t VALUES(1);
+save_master_pos;
+
+--echo ### A. Simulate an unnoticeable loss of Xid event
+--sync_slave_with_master
+SET @@global.debug_dbug="+d,slave_discard_xid_for_gtid_0_x_1000";
+
+--connection master
+SET @@gtid_seq_no=1000;
+set @@server_id=27697;
+INSERT INTO t VALUES(1000);
+set @@server_id=default;
+INSERT INTO t VALUES(1001);
+
+--echo ## Prove the error occurs.
+--connection slave
+# ER_SLAVE_RELAY_LOG_WRITE_FAILURE
+--let $slave_io_errno = 1595
+--source include/wait_for_slave_io_error.inc
+## EOP
+
+--echo ## Prove the slave recovers after the simulation condtion is lifted.
+SET @@global.debug_dbug=default;
+--source include/start_slave.inc
+
+--echo ### B. Do the same to GTID event.
+--connection slave
+SET @@global.debug_dbug="+d,slave_discard_gtid_0_x_1002";
+
+--connection master
+SET @@gtid_seq_no=1002;
+set @@server_id=27697;
+INSERT INTO t VALUES(1002);
+set @@server_id=default;
+INSERT INTO t VALUES(1003);
+
+--echo ## Prove the error occurs.
+--connection slave
+# ER_SLAVE_RELAY_LOG_WRITE_FAILURE
+--let $slave_io_errno = 1595
+--source include/wait_for_slave_io_error.inc
+## EOP
+
+--echo ## Prove the slave recovers after the simulation condtion is lifted.
+SET @@global.debug_dbug=default;
+--source include/start_slave.inc
+
+--connection master
+save_master_pos;
+
+--sync_slave_with_master
+## EOP
+
+--let $diff_tables=master:t,slave:t
+--source include/diff_tables.inc
+
+--echo "===== Clean up ====="
+--connection slave
+--source include/stop_slave.inc
+CHANGE MASTER TO MASTER_USE_GTID=no;
+--source include/start_slave.inc
+
+--connection master
+DROP TABLE t;
+SET GLOBAL LOG_WARNINGS=default;
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_gtid_ignored.test b/mysql-test/suite/rpl/t/rpl_gtid_ignored.test
new file mode 100644
index 00000000..3c1324b2
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_gtid_ignored.test
@@ -0,0 +1,141 @@
+--source include/have_innodb.inc
+--source include/have_debug.inc
+--source include/have_debug_sync.inc
+
+--let $rpl_topology=1->2
+--source include/rpl_init.inc
+
+--connection server_1
+ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
+
+SET @old_gtid_strict_mode= @@GLOBAL.gtid_strict_mode;
+SET GLOBAL gtid_strict_mode= 1;
+
+--connection server_2
+--source include/stop_slave.inc
+SET @old_gtid_strict_mode= @@GLOBAL.gtid_strict_mode;
+SET GLOBAL gtid_strict_mode=1;
+CHANGE MASTER TO master_use_gtid=slave_pos;
+--source include/start_slave.inc
+
+--connection server_1
+CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1);
+--save_master_pos
+
+--connection server_2
+--sync_with_master
+
+--echo **** MDEV-4488: GTID position should be updated for events that are ignored due to server id ***
+--source include/stop_slave.inc
+CHANGE MASTER TO ignore_server_ids=(1);
+--source include/start_slave.inc
+
+--connection server_1
+# These inserts should be ignored (not applied) on the slave, but the
+# gtid_slave_pos should still be updated.
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+--save_master_pos
+--let gtid_pos=`SELECT @@GLOBAL.gtid_binlog_pos`
+
+--connection server_2
+--sync_with_master
+--let $wait_condition= SELECT @@GLOBAL.gtid_slave_pos = '$gtid_pos'
+--source include/wait_condition.inc
+--disable_query_log
+eval SELECT IF(@@GLOBAL.gtid_slave_pos = '$gtid_pos', 'OK', CONCAT("ERROR: Expected $gtid_pos got ", @@GLOBAL.gtid_slave_pos)) AS RESULT;
+--enable_query_log
+
+SELECT * FROM t1 ORDER BY a;
+
+--source include/stop_slave.inc
+CHANGE MASTER TO ignore_server_ids=();
+--source include/start_slave.inc
+--sync_with_master
+--disable_query_log
+eval SELECT IF(@@GLOBAL.gtid_slave_pos = '$gtid_pos', 'OK', CONCAT("ERROR: Expected $gtid_pos got ", @@GLOBAL.gtid_slave_pos)) AS RESULT;
+--enable_query_log
+
+SELECT * FROM t1 ORDER BY a;
+
+--connection server_1
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+--let gtid_pos=`SELECT @@GLOBAL.gtid_binlog_pos`
+--save_master_pos
+
+--connection server_2
+--sync_with_master
+--disable_query_log
+eval SELECT IF(@@GLOBAL.gtid_slave_pos = '$gtid_pos', 'OK', CONCAT("ERROR: Expected $gtid_pos got ", @@GLOBAL.gtid_slave_pos)) AS RESULT;
+SELECT * FROM t1 ORDER BY a;
+--enable_query_log
+
+
+--echo *** Test the same thing when IO thread exits before SQL thread reaches end of log. ***
+--connection server_2
+--source include/stop_slave.inc
+SET @old_dbug= @@GLOBAL.debug_dbug;
+SET GLOBAL debug_dbug= "+d,inject_slave_sql_before_apply_event";
+CHANGE MASTER TO ignore_server_ids=(1);
+--source include/start_slave.inc
+
+--connection server_1
+INSERT INTO t1 VALUES (6);
+INSERT INTO t1 VALUES (7);
+--let $master_pos= query_get_value(SHOW MASTER STATUS, Position, 1)
+--let gtid_pos=`SELECT @@GLOBAL.gtid_binlog_pos`
+--save_master_pos
+
+--connection server_2
+# Wait for IO thread to have read all events from master, and for SQL thread to
+# sit in the debug_sync point.
+
+--let $slave_param= Read_Master_Log_Pos
+--let $slave_param_value= $master_pos
+--source include/wait_for_slave_param.inc
+
+# Now stop the IO thread, and let the SQL thread continue. The IO thread
+# should write a Gtid_list event that the SQL thread can use to update the
+# gtid_slave_pos with the GTIDs of the skipped events.
+STOP SLAVE IO_THREAD;
+SET debug_sync = "now SIGNAL continue";
+
+--sync_with_master
+--let $wait_condition= SELECT @@GLOBAL.gtid_slave_pos = '$gtid_pos'
+--source include/wait_condition.inc
+--disable_query_log
+eval SELECT IF(@@GLOBAL.gtid_slave_pos = '$gtid_pos', 'OK', CONCAT("ERROR: Expected $gtid_pos got ", @@GLOBAL.gtid_slave_pos)) AS RESULT;
+--let $slave_pos= query_get_value(SHOW SLAVE STATUS, Exec_Master_Log_Pos, 1)
+eval SELECT IF('$slave_pos' = '$master_pos', 'OK', "ERROR: Expected $master_pos got $slave_pos") AS RESULT;
+--enable_query_log
+
+
+--source include/stop_slave.inc
+CHANGE MASTER TO ignore_server_ids=();
+SET GLOBAL debug_dbug= @old_dbug;
+--source include/start_slave.inc
+
+--connection server_1
+INSERT INTO t1 VALUES (8);
+INSERT INTO t1 VALUES (9);
+--save_master_pos
+
+--connection server_2
+--sync_with_master
+SELECT * FROM t1 ORDER BY a;
+
+# Clean up.
+--connection server_1
+DROP TABLE t1;
+ALTER TABLE mysql.gtid_slave_pos ENGINE=Aria;
+SET GLOBAL gtid_strict_mode= @old_gtid_strict_mode;
+SET debug_sync = "reset";
+
+--connection server_2
+SET GLOBAL gtid_strict_mode= @old_gtid_strict_mode;
+SET debug_sync = "reset";
+
+--source include/rpl_end.inc
+
diff --git a/mysql-test/suite/rpl/t/rpl_gtid_master_promote.cnf b/mysql-test/suite/rpl/t/rpl_gtid_master_promote.cnf
new file mode 100644
index 00000000..4eafa897
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_gtid_master_promote.cnf
@@ -0,0 +1,35 @@
+!include ../my.cnf
+
+[mysqld.1]
+log-slave-updates
+loose-innodb
+
+[mysqld.2]
+log-slave-updates
+skip-slave-start
+loose-innodb
+
+[mysqld.3]
+log-slave-updates
+skip-slave-start
+loose-innodb
+
+[mysqld.4]
+log-slave-updates
+skip-slave-start
+loose-innodb
+
+[mysqld.5]
+log-slave-updates
+skip-slave-start
+loose-innodb
+
+[ENV]
+SERVER_MYPORT_3= @mysqld.3.port
+SERVER_MYSOCK_3= @mysqld.3.socket
+
+SERVER_MYPORT_4= @mysqld.4.port
+SERVER_MYSOCK_4= @mysqld.4.socket
+
+SERVER_MYPORT_5= @mysqld.5.port
+SERVER_MYSOCK_5= @mysqld.5.socket
diff --git a/mysql-test/suite/rpl/t/rpl_gtid_master_promote.test b/mysql-test/suite/rpl/t/rpl_gtid_master_promote.test
new file mode 100644
index 00000000..064c70b1
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_gtid_master_promote.test
@@ -0,0 +1,266 @@
+--source include/have_innodb.inc
+--let $rpl_topology=1->2, 1->3, 1->4, 1->5
+--source include/rpl_init.inc
+
+# Set up a topology with one master and 4 slaves.
+#
+# Replicate some events leaving the four slaves at different points
+# in different domains.
+#
+# Then promote one slave as new master, bringing it ahead of all others
+# using START SLAVE UNTIL master_gtid_pos.
+
+--connection server_1
+ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
+CREATE TABLE t4 (a INT, b INT, PRIMARY KEY (a,b)) Engine=InnoDB;
+
+# Function to extract one GTID from a list.
+delimiter |;
+CREATE FUNCTION extract_gtid(d VARCHAR(100), s VARCHAR(100))
+ RETURNS VARCHAR(100) DETERMINISTIC
+BEGIN
+ SET s= CONCAT(",", s, ",");
+ SET s= SUBSTR(s FROM LOCATE(CONCAT(",", d, "-"), s) + 1);
+ SET s= SUBSTR(s FROM 1 FOR LOCATE(",", s) - 1);
+ RETURN s;
+END|
+delimiter ;|
+
+--save_master_pos
+
+--connection server_2
+--sync_with_master
+--source include/stop_slave.inc
+
+--connection server_3
+--sync_with_master
+--source include/stop_slave.inc
+
+--connection server_4
+--sync_with_master
+--source include/stop_slave.inc
+
+--connection server_5
+--sync_with_master
+--source include/stop_slave.inc
+
+
+# Create three separate replication streams on master server_1.
+#
+# Then use START SLAVE UNTIL to get the different streams interleaved
+# differently spread over multiple binlogs on the different slaves, to
+# test that new master promotion is able to deal with this.
+
+--connection server_1
+
+SET gtid_domain_id= 1;
+CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=InnoDB;
+--let $d1_begin= `SELECT extract_gtid("1", @@GLOBAL.gtid_binlog_pos)`
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t4 VALUES (1, 1);
+--let $d1_mid= `SELECT extract_gtid("1", @@GLOBAL.gtid_binlog_pos)`
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t4 VALUES (1, 3);
+--let $d1_end= `SELECT extract_gtid("1", @@GLOBAL.gtid_binlog_pos)`
+
+SET gtid_domain_id= 2;
+CREATE TABLE t2 (a INT PRIMARY KEY) ENGINE=InnoDB;
+--let $d2_begin= `SELECT extract_gtid("2", @@GLOBAL.gtid_binlog_pos)`
+INSERT INTO t2 VALUES (1);
+INSERT INTO t2 VALUES (2);
+INSERT INTO t4 VALUES (2, 1);
+--let $d2_mid= `SELECT extract_gtid("2", @@GLOBAL.gtid_binlog_pos)`
+INSERT INTO t2 VALUES (3);
+INSERT INTO t2 VALUES (4);
+INSERT INTO t4 VALUES (2, 3);
+--let $d2_end= `SELECT extract_gtid("2", @@GLOBAL.gtid_binlog_pos)`
+
+SET gtid_domain_id= 3;
+CREATE TABLE t3 (a INT PRIMARY KEY) ENGINE=InnoDB;
+--let $d3_begin= `SELECT extract_gtid("3", @@GLOBAL.gtid_binlog_pos)`
+INSERT INTO t3 VALUES (1);
+INSERT INTO t3 VALUES (2);
+INSERT INTO t4 VALUES (3, 1);
+--let $d3_mid= `SELECT extract_gtid("3", @@GLOBAL.gtid_binlog_pos)`
+INSERT INTO t3 VALUES (3);
+INSERT INTO t3 VALUES (4);
+INSERT INTO t4 VALUES (3, 3);
+--let $d3_end= `SELECT extract_gtid("3", @@GLOBAL.gtid_binlog_pos)`
+
+
+# Slave server_2 (that will be promoted to master) is in the middle
+# of each stream.
+--connection server_2
+eval START SLAVE UNTIL master_gtid_pos= "$d1_mid,$d2_mid,$d3_mid";
+
+# The remaining slaves sit at different points each in different domains.
+--connection server_3
+eval START SLAVE UNTIL master_gtid_pos= "$d1_begin,$d2_mid,$d3_end";
+--connection server_4
+eval START SLAVE UNTIL master_gtid_pos= "$d2_begin,$d3_mid,$d1_end";
+--connection server_5
+eval START SLAVE UNTIL master_gtid_pos= "$d3_begin,$d1_mid,$d2_end";
+--connection server_2
+--source include/wait_for_slave_to_stop.inc
+SELECT * FROM t1 ORDER BY a;
+SELECT * FROM t2 ORDER BY a;
+SELECT * FROM t3 ORDER BY a;
+SELECT * FROM t4 ORDER BY a,b;
+--connection server_3
+--source include/wait_for_slave_to_stop.inc
+SELECT * FROM t1 ORDER BY a;
+SELECT * FROM t2 ORDER BY a;
+SELECT * FROM t3 ORDER BY a;
+SELECT * FROM t4 ORDER BY a,b;
+--connection server_4
+--source include/wait_for_slave_to_stop.inc
+SELECT * FROM t1 ORDER BY a;
+SELECT * FROM t2 ORDER BY a;
+SELECT * FROM t3 ORDER BY a;
+SELECT * FROM t4 ORDER BY a,b;
+--connection server_5
+--source include/wait_for_slave_to_stop.inc
+SELECT * FROM t1 ORDER BY a;
+SELECT * FROM t2 ORDER BY a;
+SELECT * FROM t3 ORDER BY a;
+SELECT * FROM t4 ORDER BY a,b;
+
+
+--echo *** Now replicate all extra changes from 3,4,5 to 2, in preparation for making 2 the new master. ***
+
+--connection server_3
+--let $server3_pos= `SELECT @@GLOBAL.gtid_slave_pos`
+--connection server_2
+--replace_result $SERVER_MYPORT_3 SERVER_MYPORT_3
+eval CHANGE MASTER TO master_host = '127.0.0.1', master_port = $SERVER_MYPORT_3;
+--replace_result $server3_pos SERVER3_POS
+eval START SLAVE UNTIL master_gtid_pos = "$server3_pos";
+--source include/wait_for_slave_to_stop.inc
+SELECT * FROM t1 ORDER BY a;
+SELECT * FROM t2 ORDER BY a;
+SELECT * FROM t3 ORDER BY a;
+SELECT * FROM t4 ORDER BY a,b;
+
+--connection server_4
+--let $server4_pos= `SELECT @@GLOBAL.gtid_slave_pos`
+--connection server_2
+--replace_result $SERVER_MYPORT_4 SERVER_MYPORT_4
+eval CHANGE MASTER TO master_host = '127.0.0.1', master_port = $SERVER_MYPORT_4;
+--replace_result $server4_pos SERVER4_POS
+eval START SLAVE UNTIL master_gtid_pos = "$server4_pos";
+--source include/wait_for_slave_to_stop.inc
+SELECT * FROM t1 ORDER BY a;
+SELECT * FROM t2 ORDER BY a;
+SELECT * FROM t3 ORDER BY a;
+SELECT * FROM t4 ORDER BY a,b;
+
+--connection server_5
+--let $server5_pos= `SELECT @@GLOBAL.gtid_slave_pos`
+--connection server_2
+--replace_result $SERVER_MYPORT_5 SERVER_MYPORT_5
+eval CHANGE MASTER TO master_host = '127.0.0.1', master_port = $SERVER_MYPORT_5;
+--replace_result $server5_pos SERVER5_POS
+eval START SLAVE UNTIL master_gtid_pos = "$server5_pos";
+--source include/wait_for_slave_to_stop.inc
+SELECT * FROM t1 ORDER BY a;
+SELECT * FROM t2 ORDER BY a;
+SELECT * FROM t3 ORDER BY a;
+SELECT * FROM t4 ORDER BY a,b;
+
+--echo *** Now make 2 master and point 3,4,5 to the new master 2
+--connection server_2
+SET gtid_domain_id= 1;
+INSERT INTO t1 values (5);
+INSERT INTO t4 values (1,5);
+SET gtid_domain_id= 2;
+INSERT INTO t2 values (5);
+INSERT INTO t4 values (2,5);
+SET gtid_domain_id= 3;
+INSERT INTO t3 values (5);
+INSERT INTO t4 values (3,5);
+
+--connection server_3
+--replace_result $SERVER_MYPORT_2 SERVER_MYPORT_2
+eval CHANGE MASTER TO master_host = '127.0.0.1', master_port = $SERVER_MYPORT_2;
+--source include/start_slave.inc
+--connection server_4
+--replace_result $SERVER_MYPORT_2 SERVER_MYPORT_2
+eval CHANGE MASTER TO master_host = '127.0.0.1', master_port = $SERVER_MYPORT_2;
+--source include/start_slave.inc
+--connection server_5
+--replace_result $SERVER_MYPORT_2 SERVER_MYPORT_2
+eval CHANGE MASTER TO master_host = '127.0.0.1', master_port = $SERVER_MYPORT_2;
+--source include/start_slave.inc
+
+--connection server_2
+--save_master_pos
+
+--connection server_3
+--sync_with_master
+SELECT * FROM t1 ORDER BY a;
+SELECT * FROM t2 ORDER BY a;
+SELECT * FROM t3 ORDER BY a;
+SELECT * FROM t4 ORDER BY a,b;
+--connection server_5
+--sync_with_master
+SELECT * FROM t1 ORDER BY a;
+SELECT * FROM t2 ORDER BY a;
+SELECT * FROM t3 ORDER BY a;
+SELECT * FROM t4 ORDER BY a,b;
+--connection server_5
+--sync_with_master
+SELECT * FROM t1 ORDER BY a;
+SELECT * FROM t2 ORDER BY a;
+SELECT * FROM t3 ORDER BY a;
+SELECT * FROM t4 ORDER BY a,b;
+
+
+--echo *** Now let the old master join up as slave. ***
+--connection server_1
+--replace_result $SERVER_MYPORT_2 SERVER_MYPORT_2
+eval CHANGE MASTER TO master_host = '127.0.0.1', master_port = $SERVER_MYPORT_2,
+ master_user = "root", master_use_gtid = slave_pos, master_demote_to_slave=1;
+--source include/start_slave.inc
+--sync_with_master
+SELECT * FROM t1 ORDER BY a;
+SELECT * FROM t2 ORDER BY a;
+SELECT * FROM t3 ORDER BY a;
+SELECT * FROM t4 ORDER BY a,b;
+
+
+--echo *** Finally move things back and clean up. ***
+--connection server_1
+--source include/stop_slave.inc
+RESET SLAVE ALL;
+
+--connection server_2
+--replace_result $SERVER_MYPORT_1 SERVER_MYPORT_1
+eval CHANGE MASTER TO master_host = '127.0.0.1', master_port = $SERVER_MYPORT_1;
+--source include/start_slave.inc
+--connection server_3
+--source include/stop_slave.inc
+--replace_result $SERVER_MYPORT_1 SERVER_MYPORT_1
+eval CHANGE MASTER TO master_host = '127.0.0.1', master_port = $SERVER_MYPORT_1;
+--source include/start_slave.inc
+--connection server_4
+--source include/stop_slave.inc
+--replace_result $SERVER_MYPORT_1 SERVER_MYPORT_1
+eval CHANGE MASTER TO master_host = '127.0.0.1', master_port = $SERVER_MYPORT_1;
+--source include/start_slave.inc
+--connection server_5
+--source include/stop_slave.inc
+--replace_result $SERVER_MYPORT_1 SERVER_MYPORT_1
+eval CHANGE MASTER TO master_host = '127.0.0.1', master_port = $SERVER_MYPORT_1;
+--source include/start_slave.inc
+
+--connection server_1
+SET gtid_domain_id = 0;
+DROP TABLE t1;
+DROP TABLE t2;
+DROP TABLE t3;
+DROP TABLE t4;
+DROP FUNCTION extract_gtid;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_gtid_mdev4473.cnf b/mysql-test/suite/rpl/t/rpl_gtid_mdev4473.cnf
new file mode 100644
index 00000000..4fe90e6a
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_gtid_mdev4473.cnf
@@ -0,0 +1,18 @@
+!include ../my.cnf
+
+[mysqld.1]
+log-slave-updates
+loose-innodb
+
+[mysqld.2]
+log-slave-updates
+loose-innodb
+
+[mysqld.3]
+log-slave-updates
+loose-innodb
+
+[ENV]
+SERVER_MYPORT_3= @mysqld.3.port
+SERVER_MYSOCK_3= @mysqld.3.socket
+
diff --git a/mysql-test/suite/rpl/t/rpl_gtid_mdev4473.test b/mysql-test/suite/rpl/t/rpl_gtid_mdev4473.test
new file mode 100644
index 00000000..f52e51c2
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_gtid_mdev4473.test
@@ -0,0 +1,72 @@
+--source include/have_innodb.inc
+--source include/have_binlog_format_mixed.inc
+
+--let $rpl_topology=1->2,1->3
+--source include/rpl_init.inc
+
+connection server_1;
+create table t1 (n int);
+insert into t1 values (1);
+insert into t1 values (2);
+save_master_pos;
+
+connection server_3;
+sync_with_master;
+source include/stop_slave.inc;
+source include/wait_for_slave_to_stop.inc;
+
+connection server_2;
+sync_with_master;
+source include/stop_slave.inc;
+source include/wait_for_slave_to_stop.inc;
+reset slave all;
+
+connection server_1;
+--replace_result $SERVER_MYPORT_2 SERVER_MYPORT_2
+eval CHANGE MASTER TO master_host = '127.0.0.1', master_port = $SERVER_MYPORT_2,
+ master_user='root', MASTER_USE_GTID=SLAVE_POS, master_demote_to_slave=1;
+source include/start_slave.inc;
+source include/wait_for_slave_to_start.inc;
+
+connection server_2;
+flush logs;
+insert into t1 values (3);
+insert into t1 values (4);
+flush logs;
+save_master_pos;
+
+connection server_3;
+--replace_result $SERVER_MYPORT_2 SERVER_MYPORT_2
+eval CHANGE MASTER TO master_host = '127.0.0.1', master_port = $SERVER_MYPORT_2,
+ MASTER_USE_GTID=SLAVE_POS;
+source include/start_slave.inc;
+sync_with_master;
+
+select * from t1 order by n;
+source include/show_binary_logs.inc;
+let $binlog_file=LAST;
+source include/show_binlog_events.inc;
+
+connection server_1;
+--sync_with_master
+source include/stop_slave.inc;
+source include/wait_for_slave_to_stop.inc;
+reset slave all;
+
+connection server_2;
+--replace_result $SERVER_MYPORT_1 SERVER_MYPORT_1
+eval CHANGE MASTER TO master_host = '127.0.0.1', master_port = $SERVER_MYPORT_1,
+ master_user = 'root', MASTER_USE_GTID=SLAVE_POS, master_demote_to_slave=1;
+source include/start_slave.inc;
+
+connection server_3;
+source include/stop_slave.inc;
+--replace_result $SERVER_MYPORT_1 SERVER_MYPORT_1
+eval CHANGE MASTER TO master_host = '127.0.0.1', master_port = $SERVER_MYPORT_1,
+ MASTER_USE_GTID=SLAVE_POS;
+source include/start_slave.inc;
+
+connection server_1;
+drop table t1;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_gtid_mdev4474.cnf b/mysql-test/suite/rpl/t/rpl_gtid_mdev4474.cnf
new file mode 100644
index 00000000..2b9e70c5
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_gtid_mdev4474.cnf
@@ -0,0 +1,11 @@
+!include suite/rpl/rpl_1slave_base.cnf
+!include include/default_client.cnf
+
+
+[mysqld.1]
+log-slave-updates
+loose-innodb
+
+[mysqld.2]
+log-slave-updates
+loose-innodb
diff --git a/mysql-test/suite/rpl/t/rpl_gtid_mdev4474.test b/mysql-test/suite/rpl/t/rpl_gtid_mdev4474.test
new file mode 100644
index 00000000..064f7b8a
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_gtid_mdev4474.test
@@ -0,0 +1,72 @@
+--source include/have_innodb.inc
+--source include/have_binlog_format_mixed_or_statement.inc
+--let $rpl_topology=1->2->1
+--source include/rpl_init.inc
+
+--echo #
+--echo # For now we'll only have 1->2 running
+
+--echo #
+--echo # Server 1
+--echo # Stop replication 2->1
+--connection server_1
+--source include/stop_slave.inc
+
+--echo #
+--echo # Server 2
+--echo # Use GTID for replication 1->2
+--connection server_2
+--source include/stop_slave.inc
+change master to master_use_gtid=slave_pos;
+--source include/start_slave.inc
+
+--echo #
+--echo # Create some 0-1-* and 0-2-* events in binlog of server 2
+
+--connection server_1
+create table t1 (i int) engine=InnoDB;
+insert into t1 values (1);
+--save_master_pos
+
+--connection server_2
+--sync_with_master
+create table t2 (i int) engine=InnoDB;
+--save_master_pos
+
+--connection server_1
+insert into t1 values (2);
+--save_master_pos
+
+--connection server_2
+--sync_with_master
+insert into t2 values (1);
+--save_master_pos
+
+--echo #
+--echo # All events are present in the binlog of server 2
+
+--source include/show_binlog_events.inc
+
+--echo #
+--echo # Server 1
+--echo # Start replication 2->1 using GTID,
+
+--connection server_1
+change master to master_use_gtid=slave_pos;
+--source include/start_slave.inc
+--sync_with_master
+
+select * from t1 order by i;
+select * from t2 order by i;
+
+--connection server_2
+select * from t1 order by i;
+select * from t2 order by i;
+
+--connection server_1
+drop table t1;
+
+--connection server_2
+drop table t2;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_gtid_mdev4484.test b/mysql-test/suite/rpl/t/rpl_gtid_mdev4484.test
new file mode 100644
index 00000000..5c17653d
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_gtid_mdev4484.test
@@ -0,0 +1,106 @@
+--source include/have_innodb.inc
+--source include/have_debug.inc
+--source include/master-slave.inc
+
+--connection slave
+--source include/stop_slave.inc
+# Since we inject an error updating mysql.gtid_slave_pos, we will get different
+# output depending on whether it is InnoDB or MyISAM (roll back or no roll
+# back). So fix it to make sure we are consistent, in case an earlier test case
+# left it as InnoDB.
+SET sql_log_bin=0;
+ALTER TABLE mysql.gtid_slave_pos ENGINE=Aria;
+SET sql_log_bin=1;
+--source include/start_slave.inc
+
+--connection master
+CREATE TABLE t1 (i int) ENGINE=InnoDB;
+
+--sync_slave_with_master
+
+--echo *** MDEV-4484, incorrect error handling when entries in gtid_slave_pos not found. ***
+TRUNCATE TABLE mysql.gtid_slave_pos;
+
+--connection master
+INSERT INTO t1 VALUES (1);
+--sync_slave_with_master
+
+# Inject an artificial error deleting entries, and check that the error handling code works.
+--connection slave
+--source include/stop_slave.inc
+SET @old_gtid_cleanup_batch_size= @@GLOBAL.gtid_cleanup_batch_size;
+SET GLOBAL gtid_cleanup_batch_size= 2;
+SET @old_dbug= @@GLOBAL.debug_dbug;
+SET GLOBAL debug_dbug="+d,gtid_slave_pos_simulate_failed_delete";
+SET sql_log_bin= 0;
+CALL mtr.add_suppression("<DEBUG> Error deleting old GTID row");
+SET sql_log_bin= 1;
+--source include/start_slave.inc
+
+--connection master
+--disable_query_log
+let $i = 20;
+while ($i) {
+ eval INSERT INTO t1 VALUES ($i+10);
+ dec $i;
+}
+--enable_query_log
+--save_master_pos
+
+--connection slave
+--sync_with_master
+
+# Now wait for the slave background thread to try to delete old rows and
+# hit the error injection.
+--let _TEST_MYSQLD_ERROR_LOG=$MYSQLTEST_VARDIR/log/mysqld.2.err
+--perl
+ open F, '<', $ENV{'_TEST_MYSQLD_ERROR_LOG'} or die;
+ outer: while (1) {
+ inner: while (<F>) {
+ last outer if /<DEBUG> Error deleting old GTID row/;
+ }
+ # Easy way to do sub-second sleep without extra modules.
+ select(undef, undef, undef, 0.1);
+ }
+EOF
+
+# Since we injected error in the cleanup code, the rows should remain in
+# mysql.gtid_slave_pos. Check that we have at least 20 (more robust against
+# non-deterministic cleanup and future changes than checking for exact number).
+SELECT COUNT(*), MAX(seq_no) INTO @pre_count, @pre_max_seq_no
+ FROM mysql.gtid_slave_pos;
+SELECT IF(@pre_count >= 20, "OK", CONCAT("Error: too few rows seen while errors injected: ", @pre_count));
+SET GLOBAL debug_dbug= @old_dbug;
+
+--connection master
+--disable_query_log
+let $i = 20;
+while ($i) {
+ eval INSERT INTO t1 VALUES ($i+40);
+ dec $i;
+}
+--enable_query_log
+--sync_slave_with_master
+
+--connection slave
+# Now check that 1) rows are being deleted again after removing error
+# injection, and 2) old rows are left that failed their delete while errors
+# where injected (again compensating for non-deterministic deletion).
+# Deletion is async and slightly non-deterministic, so we wait for at
+# least 10 of the 20 new rows to be deleted.
+let $wait_condition=
+ SELECT COUNT(*) <= 20-10
+ FROM mysql.gtid_slave_pos
+ WHERE seq_no > @pre_max_seq_no;
+--source include/wait_condition.inc
+SELECT IF(COUNT(*) >= 1, "OK", CONCAT("Error: too few rows seen after errors no longer injected: ", COUNT(*)))
+ FROM mysql.gtid_slave_pos
+ WHERE seq_no <= @pre_max_seq_no;
+
+# Clean up
+--connection master
+DROP TABLE t1;
+--connection slave
+SET GLOBAL gtid_cleanup_batch_size= @old_gtid_cleanup_batch_size;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_gtid_mdev4485.cnf b/mysql-test/suite/rpl/t/rpl_gtid_mdev4485.cnf
new file mode 100644
index 00000000..fccef215
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_gtid_mdev4485.cnf
@@ -0,0 +1,18 @@
+!include suite/rpl/rpl_1slave_base.cnf
+!include include/default_client.cnf
+
+[mysqld.1]
+log-slave-updates
+gtid-domain-id=1
+
+[mysqld.2]
+log-slave-updates
+gtid-domain-id=2
+
+[mysqld.3]
+log-slave-updates
+gtid-domain-id=3
+
+[ENV]
+SERVER_MYPORT_3= @mysqld.3.port
+SERVER_MYSOCK_3= @mysqld.3.socket
diff --git a/mysql-test/suite/rpl/t/rpl_gtid_mdev4485.test b/mysql-test/suite/rpl/t/rpl_gtid_mdev4485.test
new file mode 100644
index 00000000..6c37ceaf
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_gtid_mdev4485.test
@@ -0,0 +1,41 @@
+--let $rpl_topology= 1->3
+--source include/rpl_init.inc
+
+--echo *** MDEV-4485. Master did not allow slave to connect from the very start (empty GTID pos) if GTIDs from other multi_source master was present ***
+
+--connection server_1
+create table t1 (i int);
+
+--connection server_2
+create table t2 (i int);
+
+--connection server_3
+
+set default_master_connection = 'm2';
+--replace_result $SERVER_MYPORT_2 SERVER_MYPORT_2
+eval change master to master_host='127.0.0.1', master_port=$SERVER_MYPORT_2, master_user='root', master_use_gtid=slave_pos;
+--source include/start_slave.inc
+
+--connection server_2
+insert into t2 values (1);
+--save_master_pos
+
+--connection server_3
+--sync_with_master 0,'m2'
+
+--connection server_1
+drop table t1;
+
+--connection server_2
+drop table t2;
+--save_master_pos
+
+--connection server_3
+--sync_with_master 0,'m2'
+set default_master_connection = 'm2';
+--source include/stop_slave.inc
+RESET SLAVE ALL;
+set default_master_connection = '';
+
+--connection server_1
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_gtid_mdev4820.test b/mysql-test/suite/rpl/t/rpl_gtid_mdev4820.test
new file mode 100644
index 00000000..7f4d851f
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_gtid_mdev4820.test
@@ -0,0 +1,118 @@
+--let $rpl_topology=1->2
+--source include/rpl_init.inc
+
+--connection server_2
+--source include/stop_slave.inc
+SET @slave_old_strict= @@GLOBAL.gtid_strict_mode;
+SET GLOBAL gtid_strict_mode= 1;
+CHANGE MASTER TO master_use_gtid=slave_pos;
+--source include/start_slave.inc
+
+--connection server_1
+SET @master_old_strict= @@GLOBAL.gtid_strict_mode;
+SET GLOBAL gtid_strict_mode= 1;
+CREATE TABLE t1 (a INT PRIMARY KEY);
+INSERT INTO t1 VALUES (1);
+--save_master_pos
+
+--connection server_2
+--sync_with_master
+SELECT * FROM t1 ORDER BY a;
+
+--source include/stop_slave.inc
+
+--connection server_1
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+--let $old_gtid_pos= `SELECT @@GLOBAL.gtid_current_pos`
+RESET MASTER;
+--replace_result $old_gtid_pos OLD_GTID_POS
+eval SET GLOBAL gtid_slave_pos= '$old_gtid_pos';
+
+--connection server_2
+--source include/start_slave.inc
+
+--connection server_1
+INSERT INTO t1 VALUES (4);
+--source include/save_master_gtid.inc
+
+--connection server_2
+SET sql_log_bin= 0;
+CALL mtr.add_suppression("The binlog on the master is missing the GTID");
+SET sql_log_bin= 1;
+--let $slave_io_errno=1236
+--source include/wait_for_slave_io_error.inc
+
+STOP SLAVE SQL_THREAD;
+--replace_result $old_gtid_pos OLD_GTID_POS
+eval SET GLOBAL gtid_slave_pos= '$old_gtid_pos';
+
+--source include/start_slave.inc
+--source include/sync_with_master_gtid.inc
+SELECT * FROM t1 ORDER BY a;
+
+--source include/stop_slave.inc
+RESET SLAVE ALL;
+RESET MASTER;
+SET GLOBAL gtid_slave_pos= '0-2-10';
+
+--connection server_1
+--replace_result $SERVER_MYPORT_2 SERVER_MYPORT_2
+eval CHANGE MASTER TO master_host = '127.0.0.1', master_port = $SERVER_MYPORT_2,
+ master_user= 'root', master_use_gtid=CURRENT_POS;
+START SLAVE;
+
+--connection server_2
+INSERT INTO t1 VALUES (11);
+--save_master_pos
+
+--connection server_1
+SET sql_log_bin= 0;
+CALL mtr.add_suppression("which is not in the master's binlog. Since the master's binlog contains GTIDs with higher sequence numbers, it probably means that the slave has diverged");
+SET sql_log_bin= 1;
+--let $slave_io_errno=1236
+--source include/wait_for_slave_io_error.inc
+
+--connection server_1
+STOP SLAVE SQL_THREAD;
+SET GLOBAL gtid_slave_pos= '0-2-10';
+SET GLOBAL gtid_strict_mode= 0;
+--source include/start_slave.inc
+--sync_with_master
+SELECT * FROM t1 ORDER BY a;
+
+--source include/stop_slave.inc
+RESET SLAVE ALL;
+--let $old_gtid_pos= `SELECT @@GLOBAL.gtid_current_pos`
+INSERT INTO t1 VALUES (12);
+--save_master_pos
+
+--connection server_2
+INSERT INTO t1 VALUES (22);
+--replace_result $SERVER_MYPORT_1 SERVER_MYPORT_1
+eval CHANGE MASTER TO master_host = '127.0.0.1', master_port = $SERVER_MYPORT_1,
+ master_user= 'root', master_use_gtid=CURRENT_POS;
+START SLAVE;
+SET sql_log_bin= 0;
+CALL mtr.add_suppression("which is not in the master's binlog. Since the master's binlog contains GTIDs with higher sequence numbers, it probably means that the slave has diverged");
+SET sql_log_bin= 1;
+--let $slave_io_errno=1236
+--source include/wait_for_slave_io_error.inc
+STOP SLAVE SQL_THREAD;
+SET GLOBAL gtid_strict_mode= 0;
+CHANGE MASTER TO master_use_gtid=SLAVE_POS;
+--replace_result $old_gtid_pos OLD_GTID_POS
+eval SET GLOBAL gtid_slave_pos= '$old_gtid_pos';
+--source include/start_slave.inc
+--sync_with_master
+SELECT * FROM t1 ORDER BY a;
+
+# Clean up.
+--connection server_2
+SET GLOBAL gtid_strict_mode= @slave_old_strict;
+
+--connection server_1
+DROP TABLE t1;
+SET GLOBAL gtid_strict_mode= @master_old_strict;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_gtid_mdev9033.cnf b/mysql-test/suite/rpl/t/rpl_gtid_mdev9033.cnf
new file mode 100644
index 00000000..80b66498
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_gtid_mdev9033.cnf
@@ -0,0 +1,20 @@
+!include ../my.cnf
+
+[mysqld.1]
+log-slave-updates
+loose-innodb
+gtid_domain_id=1
+
+[mysqld.2]
+log-slave-updates
+loose-innodb
+gtid_domain_id=2
+
+[mysqld.3]
+log-slave-updates
+loose-innodb
+gtid_domain_id=3
+
+[ENV]
+SERVER_MYPORT_3= @mysqld.3.port
+SERVER_MYSOCK_3= @mysqld.3.socket
diff --git a/mysql-test/suite/rpl/t/rpl_gtid_mdev9033.test b/mysql-test/suite/rpl/t/rpl_gtid_mdev9033.test
new file mode 100644
index 00000000..76723e1d
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_gtid_mdev9033.test
@@ -0,0 +1,72 @@
+--source include/have_innodb.inc
+--let $rpl_topology=1->2->3
+--source include/rpl_init.inc
+
+--connection server_2
+--source include/stop_slave.inc
+eval CHANGE MASTER TO
+ MASTER_USE_GTID = SLAVE_POS, IGNORE_DOMAIN_IDS = (2,3);
+START SLAVE;
+
+--connection server_3
+--source include/stop_slave.inc
+eval CHANGE MASTER TO
+ MASTER_USE_GTID = SLAVE_POS, IGNORE_DOMAIN_IDS = (2,3);
+START SLAVE;
+
+connection server_1;
+
+CREATE TABLE t1 (a INT PRIMARY KEY, b VARCHAR(10)) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1, "m1");
+INSERT INTO t1 VALUES (2, "m2"), (3, "m3"), (4, "m4");
+
+SET @@session.gtid_domain_id=2;
+--echo # The following should get filetered on slave.
+CREATE TABLE t2 (a INT PRIMARY KEY, b VARCHAR(10)) ENGINE=InnoDB;
+INSERT INTO t2 VALUES (1, "m1");
+INSERT INTO t2 VALUES (2, "m2"), (3, "m3"), (4, "m4");
+
+--source include/save_master_gtid.inc
+
+connection server_2;
+--source include/sync_with_master_gtid.inc
+
+SELECT * FROM t1 ORDER BY a;
+--echo # Only 't1' should have replicated to slaves.
+SHOW TABLES;
+
+--source include/save_master_gtid.inc
+
+connection server_3;
+--source include/sync_with_master_gtid.inc
+
+SELECT * FROM t1 ORDER BY a;
+--echo # Only 't1' should have replicated to slaves.
+SHOW TABLES;
+
+--echo # Cleanup
+--connection server_1
+SET @@session.gtid_domain_id=1;
+DROP TABLE t1;
+SET @@session.gtid_domain_id=2;
+DROP TABLE t2;
+
+--source include/save_master_gtid.inc
+
+--connection server_2
+--source include/sync_with_master_gtid.inc
+
+--source include/save_master_gtid.inc
+
+--connection server_3
+--source include/sync_with_master_gtid.inc
+
+--connection server_2
+STOP SLAVE;
+CHANGE MASTER TO IGNORE_DOMAIN_IDS = ();
+
+--connection server_3
+STOP SLAVE;
+CHANGE MASTER TO IGNORE_DOMAIN_IDS = ();
+
+--echo # End of test.
diff --git a/mysql-test/suite/rpl/t/rpl_gtid_misc.test b/mysql-test/suite/rpl/t/rpl_gtid_misc.test
new file mode 100644
index 00000000..a78b7471
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_gtid_misc.test
@@ -0,0 +1,49 @@
+--source include/master-slave.inc
+
+--echo *** MDEV-6403: Temporary tables lost at STOP SLAVE in GTID mode if master has not rotated binlog since restart ***
+
+--connection master
+CREATE TABLE t1 (a INT PRIMARY KEY);
+--sync_slave_with_master
+
+--connection slave
+--source include/stop_slave.inc
+# Inject a duplicate key error that will make the slave stop in the middle of
+# a sequence of transactions that use a temporary table.
+SET sql_log_bin= 0;
+INSERT INTO t1 VALUES (1);
+SET sql_log_bin= 1;
+
+--connection master
+
+# Make some queries that use a temporary table.
+CREATE TEMPORARY TABLE t2 LIKE t1;
+INSERT INTO t2 VALUE (1);
+INSERT INTO t1 SELECT * FROM t2;
+DROP TEMPORARY TABLE t2;
+--save_master_pos
+
+--connection slave
+START SLAVE;
+--let $slave_sql_errno=1062
+--source include/wait_for_slave_sql_error.inc
+
+# Restart the slave.
+# The bug was that the IO thread would receive again the restart
+# format_description event at the start of the master's binlog, and this
+# event would cause the SQL thread to discard all active temporary tables.
+
+STOP SLAVE IO_THREAD;
+
+SET sql_log_bin= 0;
+DELETE FROM t1 WHERE a=1;
+SET sql_log_bin= 1;
+
+--source include/start_slave.inc
+--sync_with_master
+SELECT * FROM t1 ORDER BY a;
+
+--connection master
+DROP TABLE t1;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_gtid_nobinlog.cnf b/mysql-test/suite/rpl/t/rpl_gtid_nobinlog.cnf
new file mode 100644
index 00000000..0ea0d951
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_gtid_nobinlog.cnf
@@ -0,0 +1,9 @@
+!include ../my.cnf
+
+[mysqld.1]
+log-slave-updates=0
+loose-innodb
+
+[mysqld.2]
+log-slave-updates=0
+loose-innodb
diff --git a/mysql-test/suite/rpl/t/rpl_gtid_nobinlog.test b/mysql-test/suite/rpl/t/rpl_gtid_nobinlog.test
new file mode 100644
index 00000000..e140f335
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_gtid_nobinlog.test
@@ -0,0 +1,65 @@
+--let $rpl_topology=1->2
+--source include/rpl_init.inc
+--source include/have_binlog_format_statement.inc
+
+--connection server_1
+SET @old_strict= @@GLOBAL.gtid_strict_mode;
+SET GLOBAL gtid_strict_mode= 1;
+select @@global.log_slave_updates;
+
+CREATE TABLE t1 (a INT PRIMARY KEY, b INT);
+INSERT INTO t1 VALUES (1, 1);
+INSERT INTO t1 VALUES (2, 1);
+--save_master_pos
+
+--connection server_2
+SET @old_strict= @@GLOBAL.gtid_strict_mode;
+SET GLOBAL gtid_strict_mode= 1;
+select @@global.log_slave_updates;
+
+--sync_with_master
+SELECT * FROM t1 ORDER BY a;
+
+--source include/stop_slave.inc
+
+--connection server_1
+--replace_result $SLAVE_MYPORT SLAVE_PORT
+eval CHANGE MASTER TO master_host = '127.0.0.1', master_port = $SLAVE_MYPORT,
+ master_user = 'root';
+START SLAVE;
+--source include/wait_for_slave_to_start.inc
+
+--connection server_2
+INSERT INTO t1 VALUES (3, 2);
+INSERT INTO t1 VALUES (4, 2);
+--source include/save_master_gtid.inc
+
+--source include/show_binlog_events.inc
+
+--connection server_1
+--source include/sync_with_master_gtid.inc
+
+SELECT * FROM t1 ORDER BY a;
+
+--source include/stop_slave.inc
+RESET SLAVE;
+INSERT INTO t1 VALUES (5, 1);
+INSERT INTO t1 VALUES (6, 1);
+--source include/save_master_gtid.inc
+
+--connection server_2
+--replace_result $MASTER_MYPORT MASTER_PORT
+eval CHANGE MASTER TO master_host = '127.0.0.1', master_port = $MASTER_MYPORT;
+START SLAVE;
+--source include/sync_with_master_gtid.inc
+
+SELECT * FROM t1 ORDER BY a;
+
+# Cleanup.
+SET GLOBAL gtid_strict_mode= @old_strict;
+
+--connection server_1
+SET GLOBAL gtid_strict_mode= @old_strict;
+DROP TABLE t1;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_gtid_reconnect.test b/mysql-test/suite/rpl/t/rpl_gtid_reconnect.test
new file mode 100644
index 00000000..1452d6b0
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_gtid_reconnect.test
@@ -0,0 +1,201 @@
+--let $rpl_topology=1->2
+--source include/rpl_init.inc
+--source include/have_innodb.inc
+--source include/have_debug.inc
+
+
+--connection server_1
+CREATE TABLE t1 (a INT);
+FLUSH LOGS;
+--save_master_pos
+
+--connection server_2
+--sync_with_master
+
+
+# Prepare a string of events and have the slave replicate all of it.
+--connection server_1
+SET gtid_domain_id=10;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+SET gtid_seq_no=100;
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+--save_master_pos
+
+--connection server_2
+--sync_with_master
+--source include/stop_slave.inc
+SELECT * FROM t1 ORDER BY a;
+
+# Now start the slave again, but force a reconnect. There was a bug that this
+# reconnect would cause duplicate events.
+
+--connection server_1
+# Make sure to get rid of any old binlog dump thread so it does not
+# interfere with our DBUG error injection.
+--source include/kill_binlog_dump_threads.inc
+INSERT INTO t1 VALUES (10);
+SET @old_debug= @@GLOBAL.debug_dbug;
+SET GLOBAL debug_dbug="+d,dummy_disable_default_dbug_output";
+SET GLOBAL debug_dbug="+d,gtid_force_reconnect_at_10_1_100";
+--save_master_pos
+
+--connection server_2
+--source include/start_slave.inc
+--sync_with_master
+SELECT * FROM t1 ORDER BY a;
+
+--source include/stop_slave.inc
+TRUNCATE t1;
+RESET MASTER;
+SET GLOBAL gtid_slave_pos= "";
+
+--connection server_1
+SET GLOBAL debug_dbug= @old_debug;
+TRUNCATE t1;
+RESET MASTER;
+
+# A1 B1 A2 B2 A3 B3, slave reached A1 and B3 and stopped. Slave starts,
+# reconnects at A2. There was a bug that B2 would be duplicated.
+
+SET gtid_domain_id=10;
+SET gtid_seq_no=50;
+INSERT INTO t1 VALUES (1);
+SET gtid_domain_id=11;
+INSERT INTO t1 VALUES (11);
+SET gtid_domain_id=10;
+SET gtid_seq_no=100;
+INSERT INTO t1 VALUES (2);
+SET gtid_domain_id=11;
+INSERT INTO t1 VALUES (12);
+SET gtid_domain_id=10;
+INSERT INTO t1 VALUES (3);
+SET gtid_domain_id=11;
+SET gtid_seq_no=200;
+INSERT INTO t1 VALUES (13);
+
+--connection server_2
+START SLAVE UNTIL master_gtid_pos="10-1-50,11-1-200";
+--source include/wait_for_slave_to_stop.inc
+SELECT * FROM t1 ORDER BY a;
+
+--connection server_1
+--source include/kill_binlog_dump_threads.inc
+INSERT INTO t1 VALUES (20);
+SET GLOBAL debug_dbug="+d,dummy_disable_default_dbug_output";
+SET GLOBAL debug_dbug="+d,gtid_force_reconnect_at_10_1_100";
+--save_master_pos
+
+--connection server_2
+--source include/start_slave.inc
+--sync_with_master
+SELECT * FROM t1 ORDER BY a;
+
+--source include/stop_slave.inc
+TRUNCATE t1;
+RESET MASTER;
+SET GLOBAL gtid_slave_pos= "";
+
+--connection server_1
+SET GLOBAL debug_dbug= @old_debug;
+TRUNCATE t1;
+RESET MASTER;
+
+# A1 B1 A2 B2 A3 B3. START SLAVE UNTIL A1,B3, gets reconnect at B2.
+# There was a bug that the UNTIL would be ignored, and A2 would be lost.
+
+--source include/kill_binlog_dump_threads.inc
+SET gtid_domain_id= 9;
+SET gtid_seq_no= 50;
+INSERT INTO t1 VALUES (1);
+SET gtid_domain_id= 10;
+INSERT INTO t1 VALUES (11);
+SET gtid_domain_id= 9;
+INSERT INTO t1 VALUES (2);
+SET gtid_domain_id= 10;
+SET gtid_seq_no= 100;
+INSERT INTO t1 VALUES (12);
+SET gtid_domain_id= 9;
+INSERT INTO t1 VALUES (3);
+SET gtid_domain_id= 10;
+SET gtid_seq_no= 200;
+INSERT INTO t1 VALUES (13);
+SET gtid_domain_id= 10;
+
+SET GLOBAL debug_dbug="+d,dummy_disable_default_dbug_output";
+SET GLOBAL debug_dbug="+d,gtid_force_reconnect_at_10_1_100";
+
+--connection server_2
+START SLAVE UNTIL master_gtid_pos="9-1-50,10-1-200";
+--source include/wait_for_slave_to_stop.inc
+SELECT * FROM t1 ORDER BY a;
+
+--connection server_1
+SET GLOBAL debug_dbug= @old_debug;
+INSERT INTO t1 VALUES (20);
+--save_master_pos
+
+--connection server_2
+--source include/start_slave.inc
+--sync_with_master
+SELECT * FROM t1 ORDER BY a;
+
+
+--echo *** Test when slave IO thread needs to reconnect in the middle of an event group. ***
+--connection server_2
+--source include/stop_slave.inc
+
+TRUNCATE t1;
+RESET MASTER;
+SET GLOBAL gtid_slave_pos= "";
+
+--connection server_1
+SET GLOBAL debug_dbug= @old_debug;
+TRUNCATE t1;
+RESET MASTER;
+
+--source include/kill_binlog_dump_threads.inc
+SET GLOBAL debug_dbug="+d,dummy_disable_default_dbug_output";
+SET GLOBAL debug_dbug="+d,binlog_force_reconnect_after_22_events";
+
+# 4 events for FD, fake rotate, gtid list, binlog checkpoint.
+# 2 events for GTID, create table
+CREATE TABLE t2 (a INT PRIMARY KEY) ENGINE=InnoDB;
+# 3 events for BEGIN/query/COMMIT
+INSERT INTO t2 VALUES (1);
+# 4 events for BEGIN/query/query/COMMIT
+BEGIN;
+INSERT INTO t2 VALUES (10);
+INSERT INTO t2 VALUES (11);
+COMMIT;
+# So this event group starts after 4+2+4+3=13 events. Or 16 in row-based.
+BEGIN;
+INSERT INTO t2 VALUES (20);
+INSERT INTO t2 VALUES (21);
+INSERT INTO t2 VALUES (22);
+INSERT INTO t2 VALUES (23);
+INSERT INTO t2 VALUES (24);
+INSERT INTO t2 VALUES (25);
+INSERT INTO t2 VALUES (26);
+INSERT INTO t2 VALUES (27);
+INSERT INTO t2 VALUES (28);
+INSERT INTO t2 VALUES (29);
+COMMIT;
+--save_master_pos
+
+--connection server_2
+--source include/start_slave.inc
+--sync_with_master
+SELECT * FROM t2 ORDER BY a;
+
+--connection server_1
+SET GLOBAL debug_dbug= @old_debug;
+
+
+# Clean up.
+--connection server_1
+DROP TABLE t1, t2;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_gtid_sort.test b/mysql-test/suite/rpl/t/rpl_gtid_sort.test
new file mode 100644
index 00000000..c31ba877
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_gtid_sort.test
@@ -0,0 +1,77 @@
+--source include/have_innodb.inc
+--let $rpl_topology=1->2
+--source include/rpl_init.inc
+
+--echo *** Test connecting with empty GTID state to start from very beginning of binlog ***
+--connection server_2
+--source include/stop_slave.inc
+RESET MASTER;
+RESET SLAVE;
+SHOW VARIABLES LIKE 'gtid_binlog_pos';
+SHOW VARIABLES LIKE 'gtid_current_pos';
+SHOW VARIABLES LIKE 'gtid_slave_pos';
+SHOW VARIABLES LIKE 'gtid_binlog_state';
+
+--connection server_1
+RESET MASTER;
+FLUSH LOGS;
+CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=InnoDB;
+SET @@SESSION.gtid_domain_id=1;
+INSERT INTO t1 VALUES(1);
+
+SET @@SESSION.gtid_domain_id=99999;
+INSERT INTO t1 VALUES(3);
+
+SET @@SESSION.gtid_domain_id=10;
+INSERT INTO t1 VALUES(4);
+
+SET @@SESSION.gtid_domain_id=100;
+INSERT INTO t1 VALUES(5);
+
+SET @@SESSION.gtid_domain_id=2147483648; # 0x80000000
+INSERT INTO t1 VALUES(6);
+
+SET @@SESSION.gtid_domain_id=4294967295; # 0xFFFFFFFF
+INSERT INTO t1 VALUES(7);
+
+SHOW VARIABLES LIKE 'gtid_binlog_pos';
+SHOW VARIABLES LIKE 'gtid_current_pos';
+SHOW VARIABLES LIKE 'gtid_slave_pos';
+SHOW VARIABLES LIKE 'gtid_binlog_state';
+--save_master_pos
+
+--connection server_2
+SHOW VARIABLES LIKE 'gtid_binlog_pos';
+SHOW VARIABLES LIKE 'gtid_current_pos';
+SHOW VARIABLES LIKE 'gtid_slave_pos';
+SHOW VARIABLES LIKE 'gtid_binlog_state';
+--replace_result $MASTER_MYPORT MASTER_PORT
+eval CHANGE MASTER TO master_host = '127.0.0.1', master_port = $MASTER_MYPORT,
+ MASTER_USE_GTID=SLAVE_POS;
+--source include/start_slave.inc
+--sync_with_master
+SHOW VARIABLES LIKE 'gtid_binlog_pos';
+SHOW VARIABLES LIKE 'gtid_current_pos';
+SHOW VARIABLES LIKE 'gtid_slave_pos';
+SHOW VARIABLES LIKE 'gtid_binlog_state';
+SELECT * FROM t1;
+
+SET @@SESSION.gtid_domain_id=1000;
+INSERT INTO t1 VALUES(8);
+
+SET @@SESSION.gtid_domain_id=89;
+INSERT INTO t1 VALUES(9);
+
+SET @@SESSION.gtid_domain_id=10100000;
+INSERT INTO t1 VALUES(10);
+
+SHOW VARIABLES LIKE 'gtid_binlog_pos';
+SHOW VARIABLES LIKE 'gtid_current_pos';
+SHOW VARIABLES LIKE 'gtid_slave_pos';
+SHOW VARIABLES LIKE 'gtid_binlog_state';
+
+# Clean up.
+--connection server_1
+DROP TABLE t1;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_gtid_startpos.test b/mysql-test/suite/rpl/t/rpl_gtid_startpos.test
new file mode 100644
index 00000000..c7bcc1bb
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_gtid_startpos.test
@@ -0,0 +1,360 @@
+--source include/have_innodb.inc
+--let $rpl_topology=1->2
+--source include/rpl_init.inc
+
+--echo *** Test connecting with empty GTID state to start from very beginning of binlog ***
+--connection server_2
+--source include/stop_slave.inc
+RESET MASTER;
+RESET SLAVE;
+
+--connection server_1
+RESET MASTER;
+# Create an empty binlog file, to check that empty binlog state is handled correctly.
+FLUSH LOGS;
+CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=InnoDB;
+--save_master_pos
+
+--connection server_2
+SET GLOBAL gtid_slave_pos="";
+--replace_result $MASTER_MYPORT MASTER_PORT
+eval CHANGE MASTER TO master_host = '127.0.0.1', master_port = $MASTER_MYPORT,
+ MASTER_USE_GTID=SLAVE_POS;
+--source include/start_slave.inc
+--sync_with_master
+SELECT * FROM t1;
+
+--connection server_1
+INSERT INTO t1 VALUES (1);
+--save_master_pos
+
+--connection server_2
+--sync_with_master
+SELECT * FROM t1;
+--source include/stop_slave.inc
+
+--echo *** Test that master gives error when slave asks for empty gtid pos and binlog files have been purged. ***
+--connection server_1
+FLUSH LOGS;
+INSERT INTO t1 VALUES (2);
+--save_master_pos
+--let $purge_binlogs_to=master-bin.000003
+--source include/wait_for_purge.inc
+--source include/show_binary_logs.inc
+
+--connection server_2
+SET GLOBAL gtid_slave_pos="";
+--replace_result $MASTER_MYPORT MASTER_PORT
+eval CHANGE MASTER TO master_host = '127.0.0.1', master_port = $MASTER_MYPORT,
+ MASTER_USE_GTID=SLAVE_POS;
+START SLAVE;
+--let $slave_io_errno= 1236
+--source include/wait_for_slave_io_error.inc
+--source include/stop_slave.inc
+
+--replace_result $MASTER_MYPORT MASTER_PORT
+eval CHANGE MASTER TO master_host = '127.0.0.1', master_port = $MASTER_MYPORT,
+ MASTER_LOG_FILE="master-bin.000003", MASTER_LOG_POS=4, MASTER_USE_GTID=NO;
+--source include/start_slave.inc
+--sync_with_master
+SELECT * FROM t1 ORDER BY a;
+SET sql_log_bin=0;
+call mtr.add_suppression('Could not find GTID state requested by slave in any binlog files');
+SET sql_log_bin=1;
+
+--echo *** Test that we give warning when explict @@gtid_slave_pos=xxx that conflicts with what is in our binary log ***
+--source include/stop_slave.inc
+
+--connection server_1
+INSERT INTO t1 VALUES(3);
+--source include/save_master_gtid.inc
+
+--connection server_2
+SET GLOBAL gtid_slave_pos='0-1-3';
+--replace_result $MASTER_MYPORT MASTER_PORT
+eval CHANGE MASTER TO master_host = '127.0.0.1', master_port = $MASTER_MYPORT,
+ MASTER_USE_GTID=SLAVE_POS;
+--source include/start_slave.inc
+--source include/sync_with_master_gtid.inc
+SELECT * FROM t1 ORDER by a;
+--source include/stop_slave.inc
+
+--connection server_1
+INSERT INTO t1 VALUES (4);
+--source include/save_master_gtid.inc
+
+--connection server_2
+# Now add some local transactions that conflict with the GTID position
+# being set for @@gtid_slave_pos.
+INSERT INTO t1 VALUES (10);
+DELETE FROM t1 WHERE a=10;
+SET GLOBAL gtid_slave_pos='0-1-4';
+
+# Try again after RESET MASTER to remove the conflicting binlog.
+RESET MASTER;
+SET GLOBAL gtid_slave_pos='0-1-4';
+START SLAVE;
+--source include/sync_with_master_gtid.inc
+SELECT * FROM t1 ORDER by a;
+
+--connection server_1
+DROP TABLE t1;
+--save_master_pos
+
+--connection server_2
+--sync_with_master
+
+
+--echo *** MDEV-4275: I/O thread restart duplicates events in relay log ***
+
+--connection server_2
+--source include/stop_slave.inc
+RESET SLAVE ALL;
+RESET MASTER;
+
+--connection server_1
+RESET MASTER;
+
+--connection server_2
+SET GLOBAL gtid_slave_pos='';
+--replace_result $MASTER_MYPORT MASTER_PORT
+eval CHANGE MASTER TO master_host='127.0.0.1', master_port=$MASTER_MYPORT, master_user='root', master_use_gtid=slave_pos;
+--source include/start_slave.inc
+
+--connection server_1
+CREATE TABLE t1 (a INT PRIMARY KEY);
+INSERT INTO t1 VALUES (1);
+--save_master_pos
+
+--connection server_2
+--sync_with_master
+SELECT * FROM t1;
+
+--source include/stop_slave_io.inc
+START SLAVE IO_THREAD;
+--source include/wait_for_slave_io_to_start.inc
+
+--connection server_1
+INSERT INTO t1 VALUES (2);
+--save_master_pos
+
+--connection server_2
+--sync_with_master
+
+SELECT * FROM t1 ORDER BY a;
+
+
+--echo *** MDEV-4329: GTID_SLAVE_POS='' is not checked for conflicts with binlog ***
+
+# Test starting the slave completely from scratch, deleting all tables and
+# replicating from the start of the master's binlog. This requires RESET
+# MASTER is run on the slave to avoid old junk in the binlog. The bug was
+# that the code did not catch the error of missing RESET MASTER when an
+# empty GTID_SLAVE_POS='' was specified.
+
+--connection server_2
+--source include/stop_slave.inc
+DROP TABLE t1;
+RESET SLAVE;
+SET GLOBAL gtid_slave_pos="";
+RESET MASTER;
+SET GLOBAL gtid_slave_pos="";
+
+--source include/start_slave.inc
+--sync_with_master
+SELECT * FROM t1 ORDER BY a;
+
+
+# Same thing, but this time using SQL_LOG_BIN=0 to avoid polluting the
+# slave binlog.
+
+--connection server_2
+--source include/stop_slave.inc
+SET SQL_LOG_BIN=0;
+DROP TABLE t1;
+SET SQL_LOG_BIN=1;
+RESET SLAVE;
+SET GLOBAL gtid_slave_pos="";
+# Ensure that the slave fails because of missing table to be dropped
+SET @save_slave_ddl_exec_mode=@@global.slave_ddl_exec_mode;
+SET GLOBAL slave_ddl_exec_mode=STRICT;
+
+--source include/start_slave.inc
+--sync_with_master
+SELECT * FROM t1 ORDER BY a;
+
+--echo *** Test that RESET SLAVE clears the Using_Gtid flag. ***
+--source include/stop_slave.inc
+--let $master_use_gtid_option= No
+--source include/reset_slave.inc
+--let $status_items= Using_Gtid
+--source include/show_slave_status.inc
+
+# Starting the slave now reverts to old-style position which defaults to
+# the first non-purged binlog file on the master.
+# This should give error due to table already existing.
+START SLAVE;
+--let $slave_sql_errno= 1050
+--source include/wait_for_slave_sql_error.inc
+
+# Going back to using GTID should fix things.
+STOP SLAVE IO_THREAD;
+CHANGE MASTER TO MASTER_USE_GTID=SLAVE_POS;
+--source include/start_slave.inc
+
+--connection server_1
+INSERT INTO t1 VALUES(3);
+--source include/save_master_gtid.inc
+
+--connection server_2
+--source include/sync_with_master_gtid.inc
+SELECT * FROM t1 ORDER BY a;
+SET SQL_LOG_BIN=0;
+call mtr.add_suppression("Slave: Table 't1' already exists error.* 1050");
+SET SQL_LOG_BIN=1;
+
+
+--echo *** Test reconnecting slave with GTID after purge logs on master. ***
+
+--connection server_1
+FLUSH LOGS;
+INSERT INTO t1 VALUES (4);
+--source include/save_master_gtid.inc
+
+--connection server_2
+--source include/sync_with_master_gtid.inc
+--source include/stop_slave.inc
+
+--connection server_1
+FLUSH LOGS;
+FLUSH LOGS;
+--let $purge_binlogs_to=master-bin.000004
+--source include/wait_for_purge.inc
+--source include/show_binary_logs.inc
+INSERT INTO t1 VALUES (5);
+--source include/save_master_gtid.inc
+
+--connection server_2
+--replace_result $MASTER_MYPORT MASTER_PORT
+eval CHANGE MASTER TO master_host = '127.0.0.1', master_port = $MASTER_MYPORT;
+--source include/start_slave.inc
+--source include/sync_with_master_gtid.inc
+SELECT * FROM t1 ORDER BY a;
+
+
+--echo *** Test modifying binlog on slave and the effect on GTID state. ***
+
+--connection server_2
+--source include/stop_slave.inc
+RESET MASTER;
+SET GLOBAL gtid_slave_pos="";
+
+--connection server_1
+RESET MASTER;
+TRUNCATE TABLE t1;
+INSERT INTO t1 VALUES (10); # Will be GTID 0-1-2
+--source include/save_master_gtid.inc
+
+--connection server_2
+--source include/start_slave.inc
+--source include/sync_with_master_gtid.inc
+
+SELECT * FROM t1;
+--let $value= query_get_value(SHOW SLAVE STATUS, "Using_Gtid", 1)
+eval SELECT '$value' AS Using_Gtid;
+--let $value= query_get_value(SHOW ALL SLAVES STATUS, "Gtid_Slave_Pos", 1)
+eval SELECT '$value' AS Gtid_Slave_Pos;
+
+UPDATE t1 SET a=9 WHERE a=10;
+UPDATE t1 SET a=10 WHERE a=9;
+
+--let $value= query_get_value(SHOW ALL SLAVES STATUS, "Gtid_Slave_Pos", 1)
+eval SELECT '$value' AS Gtid_Slave_Pos;
+
+--source include/stop_slave.inc
+SET GLOBAL gtid_slave_pos='0-1-2';
+RESET MASTER;
+--let $value= query_get_value(SHOW ALL SLAVES STATUS, "Gtid_Slave_Pos", 1)
+eval SELECT '$value' AS Gtid_Slave_Pos;
+SET GLOBAL gtid_slave_pos='0-1-2';
+--source include/start_slave.inc
+--let $value= query_get_value(SHOW ALL SLAVES STATUS, "Gtid_Slave_Pos", 1)
+eval SELECT '$value' AS Gtid_Slave_Pos;
+
+
+--echo *** MDEV-4483: Slave loses traditional master coordinates immediately on CHANGE MASTER TO MASTER_USE_GTID = 1 ***
+--connection server_2
+--source include/stop_slave.inc
+DROP TABLE t1;
+RESET SLAVE ALL;
+CHANGE MASTER TO MASTER_USE_GTID=NO;
+RESET MASTER;
+SET GLOBAL gtid_slave_pos= "";
+
+# Set up old-style replication. The bug was that CHANGE MASTER would clear
+# out the old-style binlog/relaylog coordinates when it should not.
+
+--replace_result $MASTER_MYPORT MASTER_PORT
+eval CHANGE MASTER TO master_host='127.0.0.1', master_port=$MASTER_MYPORT, master_user='root', master_use_gtid=no, master_log_file="", master_log_pos= 4;
+
+--connection server_1
+DROP TABLE t1;
+RESET MASTER;
+
+CREATE TABLE t1 (a INT PRIMARY KEY);
+--save_master_pos
+
+--connection server_2
+--source include/start_slave.inc
+--sync_with_master
+
+--source include/stop_slave.inc
+
+--connection server_1
+INSERT INTO t1 VALUES (1);
+--let $log_file1= query_get_value(SHOW MASTER STATUS, "File", 1)
+--let $log_pos1= query_get_value(SHOW MASTER STATUS, "Position", 1)
+INSERT INTO t1 VALUES (2);
+--let $log_file2= query_get_value(SHOW MASTER STATUS, "File", 1)
+--let $log_pos2= query_get_value(SHOW MASTER STATUS, "Position", 1)
+--save_master_pos
+
+--connection server_2
+# Get the slave to a point where the IO thread has fetched one event ahead
+# of the SQL thread (we want to test that CHANGE MASTER does not mess with
+# existing relay logs).
+--replace_result $log_file1 LOG_FILE1 $log_pos1 LOG_POS1
+eval START SLAVE UNTIL master_log_file='$log_file1', master_log_pos=$log_pos1;
+--source include/wait_for_slave_sql_to_stop.inc
+SELECT * FROM t1;
+--let $slave_param= Read_Master_Log_Pos
+--let $slave_param_value= $log_pos2
+--source include/wait_for_slave_param.inc
+--source include/stop_slave_io.inc
+
+# Test that we can change to GTID and back without loosing our
+# old-style slave position.
+CHANGE MASTER TO master_use_gtid=slave_pos;
+# Unknown GTID, so slave will fail to connect.
+SET GLOBAL gtid_slave_pos="0-42-42";
+SET sql_log_bin=0;
+call mtr.add_suppression("Error: connecting slave requested to start from GTID");
+SET sql_log_bin=1;
+START SLAVE;
+--let $slave_io_errno= 1236
+--source include/wait_for_slave_io_error.inc
+STOP SLAVE SQL_THREAD;
+--source include/wait_for_slave_sql_to_stop.inc
+CHANGE MASTER TO master_use_gtid=no;
+
+--source include/start_slave.inc
+--sync_with_master
+SELECT * FROM t1 ORDER BY a;
+
+# Clean up.
+--connection server_1
+DROP TABLE t1;
+--connection server_2
+set @@global.slave_ddl_exec_mode=@save_slave_ddl_exec_mode;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_gtid_stop_start.cnf b/mysql-test/suite/rpl/t/rpl_gtid_stop_start.cnf
new file mode 100644
index 00000000..c7247a80
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_gtid_stop_start.cnf
@@ -0,0 +1,5 @@
+!include ../my.cnf
+
+[mysqld.2]
+# Needed because depending on load on test machine the master restart can take long.
+master_retry_count = 120
diff --git a/mysql-test/suite/rpl/t/rpl_gtid_stop_start.test b/mysql-test/suite/rpl/t/rpl_gtid_stop_start.test
new file mode 100644
index 00000000..9760d4df
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_gtid_stop_start.test
@@ -0,0 +1,355 @@
+if (`SELECT $PS_PROTOCOL != 0`)
+{
+ --skip Test temporarily disabled for ps-protocol
+}
+--source include/no_valgrind_without_big.inc
+--let $rpl_topology=1->2
+--source include/rpl_init.inc
+--source include/have_innodb.inc
+
+--echo *** Test normal shutdown/restart of slave server configured as a GTID slave. ***
+
+--connection server_1
+CREATE TABLE t1 (a INT PRIMARY KEY);
+INSERT INTO t1 VALUES (1);
+--save_master_pos
+
+--connection server_2
+--sync_with_master
+--source include/stop_slave.inc
+
+--let $status_items= Master_Log_File,Using_Gtid
+--source include/show_slave_status.inc
+
+
+# Now try to restart the slave mysqld server without starting the slave first
+# threads after the CHANGE MASTER.
+# When the slave restarts, it should reconnect using GTID.
+# We test that it really uses GTID by purging on the master the
+# old binlog the slave would need if connecting with old style
+# file name/offset.
+
+--write_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect
+wait
+EOF
+FLUSH LOGS;
+--shutdown_server
+--source include/wait_until_disconnected.inc
+
+--connection server_1
+FLUSH LOGS;
+--let $purge_binlogs_to=master-bin.000002
+--source include/wait_for_purge.inc
+--source include/show_binary_logs.inc
+INSERT INTO t1 VALUES (2);
+FLUSH LOGS;
+INSERT INTO t1 VALUES (3);
+--source include/save_master_gtid.inc
+--source include/show_binary_logs.inc
+
+# Let the slave mysqld server start again.
+--append_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect
+restart: --skip-slave-start=0
+EOF
+
+--connection server_2
+--enable_reconnect
+--source include/wait_until_connected_again.inc
+
+--source include/sync_with_master_gtid.inc
+SELECT * FROM t1 ORDER BY a;
+
+
+--echo *** Test normal shutdown/restart of master server, check binlog state is preserved. ***
+
+--connection server_1
+SET SESSION gtid_domain_id= 1;
+INSERT INTO t1 VALUES (4);
+--replace_column 2 # 4 # 5 #
+SHOW BINLOG EVENTS IN 'master-bin.000003' LIMIT 1,1;
+FLUSH LOGS;
+--replace_column 2 # 4 # 5 # 6 #
+SHOW BINLOG EVENTS IN 'master-bin.000004' LIMIT 1,1;
+
+--write_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
+wait
+EOF
+--shutdown_server
+--source include/wait_until_disconnected.inc
+
+--append_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
+restart
+EOF
+
+--connection default
+--enable_reconnect
+--source include/wait_until_connected_again.inc
+--connection server_1
+--enable_reconnect
+--source include/wait_until_connected_again.inc
+
+--replace_column 2 # 4 # 5 # 6 #
+SHOW BINLOG EVENTS IN 'master-bin.000005' LIMIT 1,1;
+--source include/show_binary_logs.inc
+
+INSERT INTO t1 VALUES(5);
+--source include/save_master_gtid.inc
+
+--connection server_2
+--source include/sync_with_master_gtid.inc
+FLUSH NO_WRITE_TO_BINLOG TABLES;
+SELECT * FROM t1 ORDER BY a;
+
+--echo *** Test that @@gtid_slave_pos and @@gtid_current_pos are correctly loaded even if slave threads have not started. ***
+--let $slave_pos1= `SELECT @@GLOBAL.gtid_slave_pos`
+--let $current_pos1= `SELECT @@GLOBAL.gtid_current_pos`
+
+--write_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect
+wait
+EOF
+--shutdown_server
+--source include/wait_until_disconnected.inc
+
+--append_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect
+restart: --skip-slave-start=1 --skip-log-bin
+EOF
+--enable_reconnect
+--source include/wait_until_connected_again.inc
+--disable_query_log
+eval SET @slave_pos1= "$slave_pos1";
+eval SET @current_pos1= "$current_pos1";
+--enable_query_log
+SET @slave_pos2= @@GLOBAL.gtid_slave_pos;
+SET @current_pos2= @@GLOBAL.gtid_current_pos;
+SELECT IF(@slave_pos1=@slave_pos2, "OK", CONCAT(@slave_pos1, " != ", @slave_pos2));
+SELECT IF(@current_pos1=@current_pos2, "OK", CONCAT(@current_pos1, " != ", @current_pos2));
+
+--connection server_1
+INSERT INTO t1 VALUES (6);
+--save_master_pos
+
+--connection server_2
+--source include/start_slave.inc
+--sync_with_master
+SELECT * FROM t1 ORDER BY a;
+
+
+--echo *** MDEV-4490: Old-style master position points at the last GTID event after slave restart ***
+
+--connection server_1
+INSERT INTO t1 VALUES (7);
+--save_master_pos
+
+--connection server_2
+--sync_with_master
+FLUSH NO_WRITE_TO_BINLOG TABLES;
+SELECT * FROM t1 ORDER BY a;
+
+# Now we restart the slave server. When it restarts, there is nothing new
+# to replicate. Check that the position is nevertheless updated and
+# MASTER_POS_WAIT() works correctly and detects that we are up-to-date.
+
+--write_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect
+wait
+EOF
+--shutdown_server
+--source include/wait_until_disconnected.inc
+
+--append_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect
+restart: --skip-slave-start=0
+EOF
+--enable_reconnect
+--source include/wait_until_connected_again.inc
+
+--source include/wait_for_slave_to_start.inc
+
+--connection server_1
+--save_master_pos
+
+--connection server_2
+--sync_with_master
+SELECT * FROM t1 ORDER BY a;
+
+
+--echo *** MDEV-4486: Allow to start old-style replication even if mysql.gtid_slave_pos is unavailable
+
+--connection server_2
+--source include/stop_slave.inc
+CHANGE MASTER TO master_use_gtid= no;
+--source include/start_slave.inc
+
+--connection server_1
+INSERT INTO t1 VALUES (8);
+--save_master_pos
+
+--connection server_2
+--sync_with_master
+FLUSH NO_WRITE_TO_BINLOG TABLES;
+SELECT * FROM t1 ORDER BY a;
+--source include/stop_slave.inc
+
+SET sql_log_bin= 0;
+ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
+SET sql_log_bin= 1;
+
+--write_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect
+wait
+EOF
+--shutdown_server
+--source include/wait_until_disconnected.inc
+
+--append_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect
+restart: --skip-slave-start=1 --skip-innodb
+EOF
+--enable_reconnect
+--source include/wait_until_connected_again.inc
+
+--error ER_UNKNOWN_STORAGE_ENGINE
+SELECT * FROM mysql.gtid_slave_pos;
+SET sql_log_bin=0;
+call mtr.add_suppression("Failed to load slave replication state from table");
+call mtr.add_suppression("Unable to load replication GTID slave state");
+SET sql_log_bin=1;
+
+--source include/start_slave.inc
+--connection server_1
+INSERT INTO t1 VALUES (9);
+--save_master_pos
+
+--connection server_2
+--sync_with_master
+FLUSH NO_WRITE_TO_BINLOG TABLES;
+SELECT * FROM t1 ORDER BY a;
+
+# Put things back as they were.
+--write_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect
+wait
+EOF
+--shutdown_server
+--source include/wait_until_disconnected.inc
+
+--append_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect
+restart:
+EOF
+--enable_reconnect
+--source include/wait_until_connected_again.inc
+SET sql_log_bin= 0;
+ALTER TABLE mysql.gtid_slave_pos ENGINE=Aria;
+SET sql_log_bin= 1;
+# Do a second restart to get the mysql.gtid_slave_pos table loaded with
+# the right engine.
+--write_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect
+wait
+EOF
+--shutdown_server
+--source include/wait_until_disconnected.inc
+
+--append_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect
+restart:
+EOF
+--enable_reconnect
+--source include/wait_until_connected_again.inc
+
+--source include/start_slave.inc
+
+--connection server_1
+INSERT INTO t1 VALUES (10);
+--save_master_pos
+
+--connection server_2
+--sync_with_master
+--source include/stop_slave.inc
+CHANGE MASTER TO master_use_gtid= slave_pos;
+--source include/start_slave.inc
+
+--echo *** MDEV-4692: mysql.gtid_slave_pos accumulates values for a domain ***
+SELECT domain_id, COUNT(*) FROM mysql.gtid_slave_pos GROUP BY domain_id;
+
+--connection server_1
+INSERT INTO t1 VALUES (11);
+--save_master_pos
+
+--connection server_2
+--sync_with_master
+FLUSH NO_WRITE_TO_BINLOG TABLES;
+SELECT domain_id, COUNT(*) FROM mysql.gtid_slave_pos GROUP BY domain_id;
+
+--write_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect
+wait
+EOF
+--shutdown_server
+--source include/wait_until_disconnected.inc
+
+--append_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect
+restart:
+EOF
+--enable_reconnect
+--source include/wait_until_connected_again.inc
+--source include/start_slave.inc
+
+--connection server_1
+INSERT INTO t1 VALUES (12);
+INSERT INTO t1 VALUES (13);
+--save_master_pos
+
+--connection server_2
+--sync_with_master
+FLUSH NO_WRITE_TO_BINLOG TABLES;
+SELECT domain_id, COUNT(*) FROM mysql.gtid_slave_pos GROUP BY domain_id;
+
+
+--echo *** MDEV-4650: show variables; ERROR 1946 (HY000): Failed to load replication slave GTID position ***
+
+--connection server_2
+SET sql_log_bin=0;
+--let $old_pos= `SELECT @@GLOBAL.gtid_slave_pos`
+RENAME TABLE mysql.gtid_slave_pos TO mysql.old_gtid_slave_pos;
+SET sql_log_bin=1;
+
+--write_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect
+wait
+EOF
+--shutdown_server
+--source include/wait_until_disconnected.inc
+
+# Let the slave mysqld server start again.
+--append_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect
+restart
+EOF
+
+--enable_reconnect
+--source include/wait_until_connected_again.inc
+
+--disable_result_log
+SHOW VARIABLES;
+--enable_result_log
+SHOW VARIABLES LIKE 'gtid_slave_pos';
+--error ER_CANNOT_LOAD_SLAVE_GTID_STATE,ER_NO_SUCH_TABLE
+SET GLOBAL gtid_slave_pos = '0-1-2';
+SHOW WARNINGS;
+
+# Restore things.
+
+SET sql_log_bin=0;
+RENAME TABLE mysql.old_gtid_slave_pos TO mysql.gtid_slave_pos;
+CALL mtr.add_suppression("Failed to load slave replication state from table mysql.gtid_slave_pos");
+SET sql_log_bin=1;
+
+SHOW VARIABLES LIKE 'gtid_slave_pos';
+SET GLOBAL gtid_slave_pos = '0-1-2';
+SHOW VARIABLES LIKE 'gtid_slave_pos';
+
+# Don't let .result file depend on old state of gtid_slave_pos
+--disable_query_log
+--disable_result_log
+eval SET GLOBAL gtid_slave_pos = '$old_pos';
+--enable_query_log
+--enable_result_log
+
+--source include/start_slave.inc
+
+
+--connection server_1
+DROP TABLE t1;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_gtid_strict.test b/mysql-test/suite/rpl/t/rpl_gtid_strict.test
new file mode 100644
index 00000000..56ebba82
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_gtid_strict.test
@@ -0,0 +1,179 @@
+--source include/have_debug.inc
+--source include/have_innodb.inc
+--source include/have_binlog_format_statement.inc
+--let $rpl_topology=1->2
+--source include/rpl_init.inc
+
+--connection server_1
+ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
+SET sql_log_bin= 0;
+call mtr.add_suppression("Error writing file .*errno: 1950");
+
+SET sql_log_bin= 1;
+
+SET @old_gtid_strict_mode= @@GLOBAL.gtid_strict_mode;
+SET GLOBAL gtid_strict_mode= 1;
+--connection server_2
+--source include/stop_slave.inc
+SET @old_gtid_strict_mode= @@GLOBAL.gtid_strict_mode;
+SET GLOBAL gtid_strict_mode=1;
+CHANGE MASTER TO master_use_gtid=slave_pos;
+--source include/start_slave.inc
+
+--connection server_1
+CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1);
+
+--source include/show_binlog_events.inc
+
+SET server_id= 3;
+--error ER_GTID_STRICT_OUT_OF_ORDER
+SET gtid_seq_no= 3;
+SET @old_dbug = @@session.debug_dbug;
+SET SESSION debug_dbug="d,ignore_set_gtid_seq_no_check";
+SET gtid_seq_no= 3;
+SET SESSION debug_dbug=@old_dbug;
+--error ER_GTID_STRICT_OUT_OF_ORDER
+INSERT INTO t1 VALUES (2);
+
+--error ER_GTID_STRICT_OUT_OF_ORDER
+SET gtid_seq_no= 2;
+SET SESSION debug_dbug="d,ignore_set_gtid_seq_no_check";
+SET gtid_seq_no= 2;
+SET SESSION debug_dbug=@old_dbug;
+--error ER_GTID_STRICT_OUT_OF_ORDER
+INSERT INTO t1 VALUES (3);
+SET server_id= 1;
+SET gtid_seq_no= 4;
+INSERT INTO t1 VALUES (4);
+SELECT * FROM t1 ORDER BY 1;
+--source include/show_binlog_events.inc
+
+--echo *** Test non-transactional GTID error (cannot be rolled back). ***
+SET server_id= 3;
+--error ER_GTID_STRICT_OUT_OF_ORDER
+SET gtid_seq_no= 1;
+SET SESSION debug_dbug="d,ignore_set_gtid_seq_no_check";
+SET gtid_seq_no= 1;
+SET SESSION debug_dbug=@old_dbug;
+--error ER_GTID_STRICT_OUT_OF_ORDER
+CREATE TABLE t2 (a INT PRIMARY KEY) ENGINE=MyISAM;
+# The table is still created, DDL cannot be rolled back.
+# Fix it up for replication.
+SET sql_log_bin= 0;
+DROP TABLE t2;
+SET sql_log_bin= 1;
+CREATE TABLE t2 (a INT PRIMARY KEY) ENGINE=MyISAM;
+
+--error ER_GTID_STRICT_OUT_OF_ORDER
+SET gtid_seq_no= 1;
+SET SESSION debug_dbug="d,ignore_set_gtid_seq_no_check";
+SET gtid_seq_no= 1;
+SET SESSION debug_dbug=@old_dbug;
+--error ER_GTID_STRICT_OUT_OF_ORDER
+INSERT INTO t2 VALUES (1);
+# The value is still inserted, cannot be rolled back.
+SET server_id= 1;
+SET gtid_seq_no= 6;
+INSERT INTO t2 VALUES (2);
+SELECT * FROM t2 ORDER BY a;
+--source include/show_binlog_events.inc
+
+
+--echo *** Test that slave stops if it tries to apply a GTID that would create out-of-order binlog GTID sequence numbers. ***
+
+--save_master_pos
+--connection server_2
+--sync_with_master
+
+SELECT * FROM t1 ORDER BY a;
+SELECT * FROM t2 ORDER BY a;
+SET sql_log_bin= 0;
+call mtr.add_suppression("An attempt was made to binlog GTID .* which would create an out-of-order sequence number with existing GTID .*, and gtid strict mode is enabled");
+call mtr.add_suppression("The binlog on the master is missing the GTID [-0-9]+ requested by the slave");
+SET sql_log_bin= 1;
+
+# Create some out-of-order stuff on slave.
+INSERT INTO t1 VALUES (5);
+
+--connection server_1
+INSERT INTO t1 VALUES (6);
+--save_master_pos
+
+--connection server_2
+--let $slave_sql_errno=1950
+--source include/wait_for_slave_sql_error.inc
+STOP SLAVE IO_THREAD;
+SET GLOBAL gtid_strict_mode=0;
+--source include/start_slave.inc
+--sync_with_master
+SET GLOBAL gtid_strict_mode=1;
+SELECT * FROM t1 ORDER BY a;
+
+INSERT INTO t1 VALUES (7);
+--connection server_1
+CREATE TABLE t3 (a INT PRIMARY KEY);
+--save_master_pos
+
+--connection server_2
+--let $slave_sql_errno=1950
+--source include/wait_for_slave_sql_error.inc
+--error ER_NO_SUCH_TABLE
+--query_vertical SHOW CREATE TABLE t3
+STOP SLAVE IO_THREAD;
+SET GLOBAL gtid_strict_mode=0;
+--source include/start_slave.inc
+--sync_with_master
+SET GLOBAL gtid_strict_mode=1;
+--query_vertical SHOW CREATE TABLE t3
+
+INSERT INTO t1 VALUES (8);
+--connection server_1
+INSERT INTO t2 VALUES (3);
+--save_master_pos
+
+--connection server_2
+--let $slave_sql_errno=1950
+--source include/wait_for_slave_sql_error.inc
+SELECT * FROM t2 ORDER BY a;
+STOP SLAVE IO_THREAD;
+SET GLOBAL gtid_strict_mode=0;
+--source include/start_slave.inc
+--sync_with_master
+SET GLOBAL gtid_strict_mode=1;
+SELECT * FROM t2 ORDER BY a;
+
+
+--echo *** Check slave requests starting from a hole on the master. ***
+--connection server_2
+--source include/stop_slave.inc
+
+--connection server_1
+INSERT INTO t1 VALUES (10);
+SET gtid_seq_no= 100;
+INSERT INTO t1 VALUES (11);
+INSERT INTO t1 VALUES (12);
+--save_master_pos
+
+--connection server_2
+SET GLOBAL gtid_slave_pos= "0-1-50";
+START SLAVE;
+--let $slave_io_errno=1236
+--source include/wait_for_slave_io_error.inc
+STOP SLAVE SQL_THREAD;
+SET GLOBAL gtid_strict_mode= 0;
+--source include/start_slave.inc
+--sync_with_master
+
+SELECT * FROM t1 ORDER BY a;
+SET GLOBAL gtid_strict_mode= 1;
+
+
+# Clean up.
+--connection server_1
+DROP TABLE t1, t2, t3;
+SET GLOBAL gtid_strict_mode= @old_gtid_strict_mode;
+--connection server_2
+SET GLOBAL gtid_strict_mode= @old_gtid_strict_mode;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_gtid_until.test b/mysql-test/suite/rpl/t/rpl_gtid_until.test
new file mode 100644
index 00000000..c89cea23
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_gtid_until.test
@@ -0,0 +1,253 @@
+--source include/have_innodb.inc
+--let $rpl_topology=1->2
+--source include/rpl_init.inc
+
+--connection server_2
+--source include/stop_slave.inc
+CHANGE MASTER TO MASTER_USE_GTID=NO;
+--source include/start_slave.inc
+
+--connection server_1
+ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
+# Function to extract one GTID from a list.
+delimiter |;
+CREATE FUNCTION extract_gtid(d VARCHAR(100), s VARCHAR(100))
+ RETURNS VARCHAR(100) DETERMINISTIC
+BEGIN
+ SET s= CONCAT(",", s, ",");
+ SET s= SUBSTR(s FROM LOCATE(CONCAT(",", d, "-"), s) + 1);
+ SET s= SUBSTR(s FROM 1 FOR LOCATE(",", s) - 1);
+ RETURN s;
+END|
+delimiter ;|
+--save_master_pos
+
+--connection server_2
+--sync_with_master
+# Restart SQL thread to pick up ALTER TABLE of mysql.gtid_slave_pos.
+--source include/stop_slave.inc
+--source include/start_slave.inc
+
+# Both replication threads must be stopped for UNTIL master_gtid_pos.
+--error ER_SLAVE_WAS_RUNNING
+START SLAVE UNTIL master_gtid_pos = "";
+--source include/stop_slave_io.inc
+--error ER_SLAVE_WAS_RUNNING
+START SLAVE UNTIL master_gtid_pos = "";
+START SLAVE IO_THREAD;
+--source include/wait_for_slave_io_to_start.inc
+--source include/stop_slave_sql.inc
+--error ER_SLAVE_WAS_RUNNING
+START SLAVE UNTIL master_gtid_pos = "";
+--source include/stop_slave_io.inc
+# UNTIL master_gtid_pos only valid if GTID is used.
+
+--error ER_UNTIL_REQUIRES_USING_GTID
+START SLAVE UNTIL master_gtid_pos = "";
+
+CHANGE MASTER TO master_use_gtid=slave_pos;
+
+--connection server_1
+CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=InnoDB;
+INSERT INTO t1 VALUES(1);
+--let $gtid_pos=`SELECT @@GLOBAL.gtid_binlog_pos`
+INSERT INTO t1 VALUES(2);
+
+--connection server_2
+
+# Test various incorrect syntax for UNTIL master_gtid_pos.
+--error ER_DUPLICATE_GTID_DOMAIN
+START SLAVE UNTIL master_gtid_pos = "0-1-100,1-1-100,2-2-200,1-3-100,4-4-400";
+--error ER_PARSE_ERROR
+START SLAVE UNTIL master_log_file = "master-bin.000001", master_log_pos = 4, master_gtid_pos = "";
+--error ER_BAD_SLAVE_UNTIL_COND
+START SLAVE IO_THREAD UNTIL master_gtid_pos = "";
+--error ER_BAD_SLAVE_UNTIL_COND
+START SLAVE SQL_THREAD UNTIL master_gtid_pos = "";
+
+eval START SLAVE UNTIL master_gtid_pos = '$gtid_pos';
+
+--source include/wait_for_slave_to_stop.inc
+SELECT * FROM t1;
+
+--source include/start_slave.inc
+
+--connection server_1
+--save_master_pos
+
+--connection server_2
+--sync_with_master
+SELECT * FROM t1 ORDER BY a;
+
+# Test showing the UNTIL condition in SHOW SLAVE STATUS.
+--source include/stop_slave.inc
+START SLAVE UNTIL master_gtid_pos = "1-10-100,2-20-200,0-1-300";
+--source include/wait_for_slave_to_start.inc
+--let $status_items= Using_Gtid,Until_Condition
+--source include/show_slave_status.inc
+
+# Clear the UNTIL condition.
+# Note that we need to wait for a transaction to get through from the master.
+# Otherwise the IO thread may still be in get_master_version_and_clock()
+# (wait_for_slave_to_start.inc returns as soon as the IO thread is connected),
+# and we can get test failures from warnings in the log about IO thread being
+# killed in the middle of setting @@gtid_strict_mode or similar (MDEV-7940).
+--connection server_1
+INSERT INTO t1 VALUES (3);
+DELETE FROM t1 WHERE a=3;
+--save_master_pos
+
+--connection server_2
+--sync_with_master
+--source include/stop_slave.inc
+
+
+--echo *** Test UNTIL condition in an earlier binlog than the start GTID. ***
+--connection server_2
+
+--connection server_1
+SET gtid_domain_id = 1;
+INSERT INTO t1 VALUES (3);
+SET gtid_domain_id = 2;
+CREATE TABLE t2 (a INT);
+INSERT INTO t2 VALUES (3);
+--let $d1_point1= `SELECT extract_gtid("1", @@GLOBAL.gtid_binlog_pos)`
+--let $d2_point1= `SELECT extract_gtid("2", @@GLOBAL.gtid_binlog_pos)`
+FLUSH LOGS;
+SET gtid_domain_id = 1;
+INSERT INTO t1 VALUES (4);
+SET gtid_domain_id = 2;
+INSERT INTO t2 VALUES (4);
+FLUSH LOGS;
+SET gtid_domain_id = 1;
+INSERT INTO t1 VALUES (5);
+--let $d1_point2= `SELECT extract_gtid("1", @@GLOBAL.gtid_binlog_pos)`
+--let $d2_point2= `SELECT extract_gtid("2", @@GLOBAL.gtid_binlog_pos)`
+SET gtid_domain_id = 2;
+INSERT INTO t2 VALUES (5);
+FLUSH LOGS;
+SET gtid_domain_id = 1;
+INSERT INTO t1 VALUES (6);
+--let $d1_point3= `SELECT extract_gtid("1", @@GLOBAL.gtid_binlog_pos)`
+--let $d2_point3= `SELECT extract_gtid("2", @@GLOBAL.gtid_binlog_pos)`
+SET gtid_domain_id = 2;
+INSERT INTO t2 VALUES (6);
+SET gtid_domain_id = 0;
+--source include/show_binary_logs.inc
+--save_master_pos
+
+--connection server_2
+# Let the slave reach an middle point in domain 1 and a late point in domain 2.
+eval START SLAVE UNTIL master_gtid_pos='$d1_point2,$d2_point3';
+--source include/wait_for_slave_to_stop.inc
+SELECT * FROM t1 ORDER BY a;
+SELECT * FROM t2 ORDER BY a;
+# Now test starting at a middle point in the binlogs when the stop position in
+# one domain (domain 2) is early.
+eval START SLAVE UNTIL master_gtid_pos='$d1_point3,$d2_point1';
+--source include/wait_for_slave_to_stop.inc
+SELECT * FROM t1 ORDER BY a;
+SELECT * FROM t2 ORDER BY a;
+# Test that one UNTIL domain empty means stop that domain immediately.
+eval START SLAVE UNTIL master_gtid_pos='$d1_point2';
+--source include/wait_for_slave_to_stop.inc
+SELECT * FROM t1 ORDER BY a;
+SELECT * FROM t2 ORDER BY a;
+
+--source include/start_slave.inc
+--sync_with_master
+SELECT * FROM t1 ORDER BY a;
+SELECT * FROM t2 ORDER BY a;
+
+--echo *** Test when the UNTIL position is right at the end of the binlog file prior to the starting position ***
+
+--connection server_2
+--source include/stop_slave.inc
+
+--connection server_1
+FLUSH LOGS;
+SET gtid_domain_id = 1;
+INSERT INTO t1 VALUES (7);
+SET gtid_domain_id = 0;
+--save_master_pos
+
+--connection server_2
+eval START SLAVE UNTIL master_gtid_pos='$d1_point3';
+--source include/wait_for_slave_to_stop.inc
+# This should not show row 7, as we requested stop just before it.
+SELECT * FROM t1 ORDER BY a;
+--source include/start_slave.inc
+--sync_with_master
+SELECT * FROM t1 ORDER BY a;
+
+
+--echo *** Test when UNTIL condition is after a stand-alone event (not a transaction). ***
+
+--connection server_2
+--source include/stop_slave.inc
+
+--connection server_1
+CREATE TABLE t3 (a INT);
+--let $until_condition=`SELECT @@GLOBAL.gtid_binlog_pos`
+DROP TABLE t3;
+--save_master_pos
+
+--connection server_2
+--replace_result $until_condition UNTIL_CONDITION
+eval START SLAVE UNTIL master_gtid_pos='$until_condition';
+--source include/wait_for_slave_to_stop.inc
+SHOW CREATE TABLE t3;
+--source include/start_slave.inc
+--sync_with_master
+
+--echo *** Test UNTIL condition that has not yet been logged. ***
+
+--connection server_2
+--source include/stop_slave.inc
+RESET SLAVE ALL;
+RESET MASTER;
+SET GLOBAL gtid_slave_pos='';
+
+--connection server_1
+# Do it once to compute the right GTID, then throw it away and do it again
+# for the actual test.
+RESET MASTER;
+INSERT INTO t1 VALUES (10);
+INSERT INTO t1 VALUES (11);
+--let $until_condition=`SELECT @@GLOBAL.gtid_binlog_pos`
+INSERT INTO t1 VALUES (12);
+DELETE FROM t1 WHERE a >= 10;
+
+RESET MASTER;
+INSERT INTO t1 VALUES (10);
+
+--connection server_2
+--replace_result $SERVER_MYPORT_1 SERVER_MYPORT_1
+eval CHANGE MASTER TO master_host = '127.0.0.1', master_port = $SERVER_MYPORT_1,
+ master_user = "root", master_use_gtid = slave_pos;
+eval START SLAVE UNTIL master_gtid_pos = '$until_condition';
+--source include/wait_for_slave_to_start.inc
+
+--connection server_1
+INSERT INTO t1 VALUES (11);
+INSERT INTO t1 VALUES (12);
+--save_master_pos
+
+--connection server_2
+# This then should wait until it gets the row (11) and then stop, not
+# yet having the row (12).
+--source include/wait_for_slave_to_stop.inc
+SELECT * FROM t1 ORDER BY a;
+--source include/start_slave.inc
+--sync_with_master
+# And now the row (12) should be there.
+SELECT * FROM t1 ORDER BY a;
+
+
+# Clean up.
+--connection server_1
+DROP TABLE t1;
+DROP TABLE t2;
+DROP FUNCTION extract_gtid;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_heartbeat.test b/mysql-test/suite/rpl/t/rpl_heartbeat.test
new file mode 100644
index 00000000..e4753b7b
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_heartbeat.test
@@ -0,0 +1,175 @@
+# Testing master to slave heartbeat protocol
+#
+# Including:
+# - user interface, grammar, checking the range and warnings about
+# unreasonable values for the heartbeat period;
+# - no rotation of relay log if heartbeat is less that slave_net_timeout
+# - SHOW STATUS like 'Slave_received_heartbeats' action
+# - SHOW STATUS like 'Slave_heartbeat_period' report
+
+-- source include/have_log_bin.inc
+
+connect (master,localhost,root,,test,$MASTER_MYPORT,$MASTER_MYSOCK);
+connect (slave,localhost,root,,test,$SLAVE_MYPORT,$SLAVE_MYSOCK);
+
+connection master;
+reset master;
+
+connection slave;
+set @restore_slave_net_timeout= @@global.slave_net_timeout;
+--disable_warnings
+set @@global.slave_net_timeout= 10;
+--enable_warnings
+
+--enable_prepare_warnings
+###
+### Checking the range
+###
+
+#
+# default period slave_net_timeout/2
+#
+--replace_result $MASTER_MYPORT MASTER_PORT
+eval change master to master_host='127.0.0.1',master_port=$MASTER_MYPORT, master_user='root';
+--query_vertical show status like 'Slave_heartbeat_period';
+
+#
+# the max for the period is ULONG_MAX/1000; an attempt to exceed it is denied
+#
+--replace_result $MASTER_MYPORT MASTER_PORT
+--error ER_SLAVE_HEARTBEAT_VALUE_OUT_OF_RANGE
+eval change master to master_host='127.0.0.1',master_port=$MASTER_MYPORT, master_user='root', master_heartbeat_period= 4294968;
+--query_vertical show status like 'Slave_heartbeat_period';
+
+#
+# the min value for the period is 1 millisecond an attempt to assign a
+# lesser will be warned with treating the value as zero
+#
+connection slave;
+--replace_result $MASTER_MYPORT MASTER_PORT
+### 5.1 mtr does not have --warning ER_SLAVE_HEARTBEAT_VALUE_OUT_OF_RANGE
+eval change master to master_host='127.0.0.1',master_port=$MASTER_MYPORT, master_user='root', master_heartbeat_period= 0.0009999;
+--query_vertical show status like 'Slave_heartbeat_period';
+
+#
+# the actual max and min must be accepted
+#
+--replace_result $MASTER_MYPORT MASTER_PORT
+eval change master to master_host='127.0.0.1',master_port=$MASTER_MYPORT, master_user='root', master_heartbeat_period= 4294967;
+--query_vertical show status like 'Slave_heartbeat_period';
+
+--replace_result $MASTER_MYPORT MASTER_PORT
+eval change master to master_host='127.0.0.1',master_port=$MASTER_MYPORT, master_user='root', master_heartbeat_period= 0.001;
+--query_vertical show status like 'Slave_heartbeat_period';
+
+reset slave;
+
+#
+# A warning if period greater than slave_net_timeout
+#
+set @@global.slave_net_timeout= 5;
+--replace_result $MASTER_MYPORT MASTER_PORT
+eval change master to master_host='127.0.0.1',master_port=$MASTER_MYPORT, master_user='root', master_heartbeat_period= 5.001;
+--query_vertical show status like 'Slave_heartbeat_period';
+
+reset slave;
+
+#
+# A warning if slave_net_timeout is set to less than the current HB period
+#
+set @@global.slave_net_timeout= 5;
+--replace_result $MASTER_MYPORT MASTER_PORT
+eval change master to master_host='127.0.0.1',master_port=$MASTER_MYPORT, master_user='root', master_heartbeat_period= 4;
+--query_vertical show status like 'Slave_heartbeat_period';
+set @@global.slave_net_timeout= 3 /* must be a warning */;
+
+reset slave;
+
+
+###
+### checking no rotation
+###
+
+connection master;
+--disable_warnings
+drop table if exists t1;
+--enable_warnings
+#
+# Even though master_heartbeat_period= 0.5 is 20 times less than
+# @@global.slave_net_timeout= 10 in some circumstances master will
+# not be able to send any heartbeat during the slave's net timeout
+# and slave's relay log will rotate.
+# The probability for such a scenario is pretty small so the following
+# part is almost deterministic.
+#
+
+connection slave;
+set @@global.slave_net_timeout= 10;
+--replace_result $MASTER_MYPORT MASTER_PORT
+# no error this time but rather a warning
+eval change master to master_host='127.0.0.1',master_port=$MASTER_MYPORT, master_user='root', master_heartbeat_period= 0.5;
+--query_vertical show status like 'Slave_heartbeat_period';
+
+start slave;
+
+connection master;
+create table t1 (f1 int);
+
+#connection slave;
+sync_slave_with_master;
+let $slave_param= Relay_Log_File;
+let $slave_param_value= query_get_value(SHOW SLAVE STATUS, Relay_Log_File, 1);
+
+# there is an explicit sleep lasting longer than slave_net_timeout
+# to ensure that nothing will come to slave from master for that period.
+# That would cause reconnecting and relaylog rotation w/o the fix i.e
+# without a heartbeat received.
+
+real_sleep 15;
+
+# check (compare with the previous show's results) that no rotation happened
+source include/check_slave_param.inc;
+
+###
+### SHOW STATUS like 'Slave_heartbeat_period' and 'Slave_received_heartbeats'
+###
+
+--query_vertical show status like 'Slave_heartbeat_period';
+
+#
+# proof that there has been received at least one heartbeat;
+# The exact number of received heartbeat is an indeterministic value
+# and therefore it's not recorded into results.
+#
+
+let $slave_wait_param_counter= 300;
+let $slave_value= query_get_value("SHOW STATUS like 'Slave_received_heartbeats'", Value, 1);
+# Checking the fact that at least one heartbeat is received
+while (!$slave_value)
+{
+ dec $slave_wait_param_counter;
+ if (!$slave_wait_param_counter)
+ {
+ --echo ERROR: failed while waiting for slave parameter $slave_param: $slave_param_value
+ query_vertical show slave status;
+ SHOW STATUS like 'Slave_received_heartbeats';
+ exit;
+ }
+ sleep 0.1;
+ let $slave_value= query_get_value("SHOW STATUS like 'Slave_received_heartbeats'", Value, 1);
+}
+--echo A heartbeat has been received by the slave
+# cleanup
+
+connection master;
+drop table t1;
+
+#connection slave;
+sync_slave_with_master;
+set @@global.slave_net_timeout= @restore_slave_net_timeout;
+
+--disable_prepare_warnings
+
+--source include/stop_slave.inc
+
+--echo End of tests
diff --git a/mysql-test/suite/rpl/t/rpl_heartbeat_2slaves.cnf b/mysql-test/suite/rpl/t/rpl_heartbeat_2slaves.cnf
new file mode 100644
index 00000000..f24de9ab
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_heartbeat_2slaves.cnf
@@ -0,0 +1,12 @@
+!include ../my.cnf
+
+[mysqld.1]
+log-slave-updates
+
+[mysqld.2]
+log-slave-updates
+
+[mysqld.3]
+
+[ENV]
+SERVER_MYPORT_3= @mysqld.3.port
diff --git a/mysql-test/suite/rpl/t/rpl_heartbeat_2slaves.test b/mysql-test/suite/rpl/t/rpl_heartbeat_2slaves.test
new file mode 100644
index 00000000..e0fdf668
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_heartbeat_2slaves.test
@@ -0,0 +1,124 @@
+#############################################################
+# Author: Serge Kozlov <Serge.Kozlov@Sun.COM>
+# Date: 02/19/2009
+# Purpose: Testing heartbeat for schema
+# 1 master and 2 slaves
+#############################################################
+--let $rpl_topology= 1->2,1->3
+--source include/rpl_init.inc
+
+--let $rpl_connection_name= master
+--let $rpl_server_number= 1
+--source include/rpl_connect.inc
+
+--let $rpl_connection_name= slave_1
+--let $rpl_server_number= 2
+--source include/rpl_connect.inc
+
+--let $rpl_connection_name= slave_2
+--let $rpl_server_number= 3
+--source include/rpl_connect.inc
+
+#
+# Set different heartbeat periods for slaves
+#
+--connection slave_1
+--source include/stop_slave.inc
+CHANGE MASTER TO MASTER_HEARTBEAT_PERIOD = 0.1;
+--source include/start_slave.inc
+--connection slave_2
+--source include/stop_slave.inc
+CHANGE MASTER TO MASTER_HEARTBEAT_PERIOD = 1;
+--source include/start_slave.inc
+
+#
+# Testing heartbeat for one master and two slaves
+#
+
+# Check that heartbeat events sent to both slaves with correct periods
+--connection slave_1
+let $status_var= slave_received_heartbeats;
+let $status_var_value= query_get_value(SHOW STATUS LIKE 'slave_received_heartbeats', Value, 1);
+let $status_var_comparsion= >;
+--source include/wait_for_status_var.inc
+--echo Slave has received heartbeat event
+--connection slave_2
+let $status_var= slave_received_heartbeats;
+let $status_var_value= query_get_value(SHOW STATUS LIKE 'slave_received_heartbeats', Value, 1);
+let $status_var_comparsion= >;
+--source include/wait_for_status_var.inc
+--let $assert_cond= [slave_1:SHOW STATUS LIKE "slave_received_heartbeats", Value, 1] > [slave_2:SHOW STATUS LIKE "slave_received_heartbeats", Value, 1]
+--let $assert_text= slave_1 should have received more heartbeats than slave_2
+--source include/assert.inc
+--echo
+
+# Create topology master->slave_2->slave_1 and check that slave_1
+# receives heartbeat while slave_2 gets data.
+
+# slave_2 was started w/o --log-slave-updates because slave_2 should
+# not send data from master to slave_1
+
+--source include/rpl_stop_slaves.inc
+--let $rpl_topology= 1->3->2
+--source include/rpl_change_topology.inc
+--source include/rpl_start_slaves.inc
+--connection slave_1
+--source include/stop_slave.inc
+CHANGE MASTER TO MASTER_HEARTBEAT_PERIOD=0.1;
+--source include/start_slave.inc
+
+# Check heartbeat for new replication channel slave_2->slave
+let $status_var= slave_received_heartbeats;
+let $status_var_value= query_get_value(SHOW STATUS LIKE 'slave_received_heartbeats', Value, 1);
+let $status_var_comparsion= >;
+--source include/wait_for_status_var.inc
+--echo slave_1 has received heartbeat event
+--connection master
+CREATE TABLE t1 (a INT PRIMARY KEY, b VARCHAR(10), c LONGTEXT);
+INSERT INTO t1 VALUES (1, 'on master', '');
+SHOW TABLES;
+--sync_slave_with_master slave_2
+SHOW TABLES;
+let $slave_2_pos_before= query_get_value(SHOW SLAVE STATUS, Read_Master_Log_Pos, 1);
+--sync_slave_with_master slave_1
+SHOW TABLES;
+--connection master
+--echo creating updates on master and send to slave_2 during 5 second
+# Generate events on master and send to slave_2 during 5 second
+let $i= 1;
+let $j= 1;
+let $k= 1;
+--disable_query_log
+while ($i) {
+ eval SET @c_text=REPEAT('1234567890', $j);
+ eval UPDATE t1 SET a=$j, c=@c_text;
+ --connection slave_2
+ let $slave_2_pos= query_get_value(SHOW SLAVE STATUS, Read_Master_Log_Pos, 1);
+ if (`SELECT ($k*($slave_2_pos - $slave_2_pos_before)) > 0`) {
+ --connection slave_1
+ let $slave_1_rcvd_heartbeats_before= query_get_value(SHOW STATUS LIKE 'slave_received_heartbeats', Value, 1);
+ let $k= 0;
+ let $time_before = `SELECT NOW()`;
+ }
+ if (`SELECT ((1-$k)*TIMESTAMPDIFF(SECOND,'$time_before',NOW())) > 5`) {
+ let $i= 0;
+ }
+ --connection master
+ inc $j;
+ sleep 0.1;
+}
+--enable_query_log
+--connection slave_1
+--let $assert_cond= [SHOW STATUS LIKE "slave_received_heartbeats", Value, 1] > $slave_1_rcvd_heartbeats_before
+--let $assert_text= slave_1 should have received heartbeats
+--source include/assert.inc
+--echo
+
+#
+# Clean up
+#
+--echo *** Clean up ***
+--connection master
+DROP TABLE t1;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_heartbeat_basic.cnf b/mysql-test/suite/rpl/t/rpl_heartbeat_basic.cnf
new file mode 100644
index 00000000..a4a291bc
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_heartbeat_basic.cnf
@@ -0,0 +1,7 @@
+!include ../my.cnf
+
+[mysqld.1]
+log-slave-updates
+
+[mysqld.2]
+log-slave-updates
diff --git a/mysql-test/suite/rpl/t/rpl_heartbeat_basic.test b/mysql-test/suite/rpl/t/rpl_heartbeat_basic.test
new file mode 100644
index 00000000..d6d14e02
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_heartbeat_basic.test
@@ -0,0 +1,575 @@
+#############################################################
+# Author: Serge Kozlov <Serge.Kozlov@Sun.COM>
+# Date: 02/19/2009
+# Purpose: Testing basic functionality of heartbeat.
+# Description:
+# * Testing different values for slave_heartbeat_period.
+# * How to affect various statements to slave_heartbeat_period
+# * Various states of slave and heartbeat
+# * Various states of master and heartbeat
+# * Circular replication
+#############################################################
+--source include/master-slave.inc
+#
+# The test runs long and does not have any specifics to
+# binlog_format. It is chosen therefore to run with MIXED mode
+# in order to not slow down much `make test'.
+#
+--source include/have_binlog_format_mixed.inc
+--echo
+
+--enable_prepare_warnings
+
+# Set number of retries to connect to master
+let $connect_retry= 20;
+
+--echo *** Preparing ***
+--connection slave
+--source include/stop_slave.inc
+RESET SLAVE;
+SET @restore_slave_net_timeout=@@global.slave_net_timeout;
+let $slave_heartbeat_timeout= query_get_value(SHOW GLOBAL STATUS LIKE 'slave_heartbeat_period', Value, 1);
+--disable_query_log
+eval SET @restore_slave_heartbeat_timeout=$slave_heartbeat_timeout;
+--enable_query_log
+
+--connection master
+RESET MASTER;
+SET @restore_slave_net_timeout=@@global.slave_net_timeout;
+--echo
+
+#
+# Test slave_heartbeat_period
+#
+
+--connection slave
+
+# Default value of slave_heartbeat_timeout = slave_net_timeout/2
+--echo *** Default value ***
+--replace_result $MASTER_MYPORT MASTER_PORT
+eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=$MASTER_MYPORT, MASTER_USER='root';
+let $slave_net_timeout= query_get_value(SHOW VARIABLES LIKE 'slave_net_timeout', Value, 1);
+let $slave_heartbeat_timeout= query_get_value(SHOW GLOBAL STATUS LIKE 'slave_heartbeat_period', Value, 1);
+let $result= query_get_value(SELECT $slave_net_timeout/$slave_heartbeat_timeout AS Result, Result, 1);
+--echo slave_net_timeout/slave_heartbeat_timeout=$result
+--source include/reset_slave.inc
+--echo
+
+# Reset slave set slave_heartbeat_timeout = slave_net_timeout/2
+--echo *** Reset slave affect ***
+--disable_warnings
+SET @@global.slave_net_timeout=30;
+--enable_warnings
+--replace_result $MASTER_MYPORT MASTER_PORT
+eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=$MASTER_MYPORT, MASTER_USER='root', MASTER_CONNECT_RETRY=$connect_retry, MASTER_HEARTBEAT_PERIOD=5;
+--source include/reset_slave.inc
+SHOW GLOBAL STATUS LIKE 'slave_heartbeat_period';
+--echo
+
+# Check default value of slave_heartbeat_timeout if slave_net_timeout is changed
+--echo *** Default value if slave_net_timeout changed ***
+--disable_warnings
+SET @@global.slave_net_timeout=50;
+--enable_warnings
+--replace_result $MASTER_MYPORT MASTER_PORT
+eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=$MASTER_MYPORT, MASTER_USER='root', MASTER_CONNECT_RETRY=$connect_retry;
+SHOW GLOBAL STATUS LIKE 'slave_heartbeat_period';
+SET @@global.slave_net_timeout=@restore_slave_net_timeout;
+--source include/reset_slave.inc
+--echo
+
+# Set slave_net_timeout less than current value of slave_heartbeat_period
+--echo *** Warning if updated slave_net_timeout < slave_heartbeat_timeout ***
+let $slave_heartbeat_timeout= query_get_value(SHOW GLOBAL STATUS LIKE 'slave_heartbeat_period', Value, 1);
+--replace_result $slave_heartbeat_timeout SLAVE_HEARTBEAT_TIMEOUT
+eval SET @@global.slave_net_timeout=FLOOR($slave_heartbeat_timeout)-1;
+SET @@global.slave_net_timeout=@restore_slave_net_timeout;
+RESET SLAVE;
+--echo
+
+# Set value of slave_heartbeat_period greater than slave_net_timeout
+--echo *** Warning if updated slave_heartbeat_timeout > slave_net_timeout ***
+let $slave_net_timeout= query_get_value(SHOW VARIABLES LIKE 'slave_net_timeout', Value, 1);
+inc $slave_net_timeout;
+--replace_result $MASTER_MYPORT MASTER_PORT $slave_net_timeout SLAVE_NET_TIMEOUT
+eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=$MASTER_MYPORT, MASTER_USER='root', MASTER_CONNECT_RETRY=$connect_retry, MASTER_HEARTBEAT_PERIOD=$slave_net_timeout;
+RESET SLAVE;
+--echo
+
+# Changing of slave_net_timeout shouldn't affect to current value of slave_heartbeat_period
+--echo *** CHANGE MASTER statement only updates slave_heartbeat_period ***
+--disable_warnings
+SET @@global.slave_net_timeout=20;
+--enable_warnings
+--replace_result $MASTER_MYPORT MASTER_PORT
+eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=$MASTER_MYPORT, MASTER_USER='root', MASTER_CONNECT_RETRY=$connect_retry, MASTER_HEARTBEAT_PERIOD=5;
+SHOW VARIABLES LIKE 'slave_net_timeout';
+SHOW GLOBAL STATUS LIKE 'slave_heartbeat_period';
+SET @@global.slave_net_timeout=2*@@global.slave_net_timeout;
+SHOW VARIABLES LIKE 'slave_net_timeout';
+SHOW GLOBAL STATUS LIKE 'slave_heartbeat_period';
+SET @@global.slave_net_timeout=@restore_slave_net_timeout;
+RESET SLAVE;
+--echo
+
+# Master value of slave_net_timeout shouldn't affect to slave's slave_heartbeat_period
+--echo *** Update slave_net_timeout on master ***
+--connection master
+--disable_warnings
+SET @@global.slave_net_timeout=500;
+--enable_warnings
+--connection slave
+SET @@global.slave_net_timeout=200;
+RESET SLAVE;
+--replace_result $MASTER_MYPORT MASTER_PORT
+eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=$MASTER_MYPORT, MASTER_USER='root', MASTER_CONNECT_RETRY=$connect_retry;
+--source include/start_slave.inc
+--connection master
+--sync_slave_with_master
+SHOW VARIABLES LIKE 'slave_net_timeout';
+SHOW GLOBAL STATUS LIKE 'slave_heartbeat_period';
+SET @@global.slave_net_timeout=@restore_slave_net_timeout;
+--source include/stop_slave.inc
+RESET SLAVE;
+--connection master
+SET @@global.slave_net_timeout=@restore_slave_net_timeout;
+--echo
+
+# Start/stop slave shouldn't change slave_heartbeat_period
+--echo *** Start/stop slave ***
+--connection slave
+--disable_warnings
+SET @@global.slave_net_timeout=100;
+--enable_warnings
+--replace_result $MASTER_MYPORT MASTER_PORT
+eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=$MASTER_MYPORT, MASTER_USER='root', MASTER_CONNECT_RETRY=$connect_retry, MASTER_HEARTBEAT_PERIOD=20;
+--source include/start_slave.inc
+--connection master
+--sync_slave_with_master
+SHOW GLOBAL STATUS LIKE 'slave_heartbeat_period';
+--source include/stop_slave.inc
+SHOW GLOBAL STATUS LIKE 'slave_heartbeat_period';
+--echo
+
+# Reload slave shouldn't change slave_heartbeat_period
+--echo *** Reload slave ***
+--connection slave
+--disable_warnings
+SET @@global.slave_net_timeout=50;
+--enable_warnings
+--replace_result $MASTER_MYPORT MASTER_PORT
+eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=$MASTER_MYPORT, MASTER_USER='root', MASTER_CONNECT_RETRY=$connect_retry, MASTER_HEARTBEAT_PERIOD=30;
+--let $rpl_server_number= 2
+--source include/rpl_restart_server.inc
+SHOW GLOBAL STATUS LIKE 'slave_heartbeat_period';
+SET @restore_slave_net_timeout=@@global.slave_net_timeout;
+--echo
+
+# Disable heartbeat
+--echo *** Disable heartbeat ***
+--replace_result $MASTER_MYPORT MASTER_PORT
+eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=$MASTER_MYPORT, MASTER_USER='root', MASTER_CONNECT_RETRY=$connect_retry, MASTER_HEARTBEAT_PERIOD=0;
+SHOW GLOBAL STATUS LIKE 'slave_heartbeat_period';
+SHOW STATUS LIKE 'slave_received_heartbeats';
+--source include/start_slave.inc
+--connection master
+--sync_slave_with_master
+--sleep 2
+SHOW GLOBAL STATUS LIKE 'slave_heartbeat_period';
+SHOW STATUS LIKE 'slave_received_heartbeats';
+--source include/stop_slave.inc
+SHOW GLOBAL STATUS LIKE 'slave_heartbeat_period';
+SHOW STATUS LIKE 'slave_received_heartbeats';
+RESET SLAVE;
+let $slave_heartbeat_timeout= query_get_value(SHOW GLOBAL STATUS LIKE 'slave_heartbeat_period', Value, 1);
+--replace_result $slave_heartbeat_timeout SLAVE_HEARTBEAT_TIMEOUT
+--eval SELECT $slave_heartbeat_timeout = 0 AS Result
+--echo
+
+#
+# Check limits for slave_heartbeat_timeout
+#
+
+--echo *** Min slave_heartbeat_timeout ***
+--replace_result $MASTER_MYPORT MASTER_PORT
+eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=$MASTER_MYPORT, MASTER_USER='root', MASTER_CONNECT_RETRY=$connect_retry, MASTER_HEARTBEAT_PERIOD=0.001;
+SHOW GLOBAL STATUS LIKE 'slave_heartbeat_period';
+RESET SLAVE;
+--replace_result $MASTER_MYPORT MASTER_PORT
+eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=$MASTER_MYPORT, MASTER_USER='root', MASTER_CONNECT_RETRY=$connect_retry, MASTER_HEARTBEAT_PERIOD=0.0009;
+SHOW GLOBAL STATUS LIKE 'slave_heartbeat_period';
+RESET SLAVE;
+--echo
+
+--echo *** Max slave_heartbeat_timeout ***
+--replace_result $MASTER_MYPORT MASTER_PORT
+eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=$MASTER_MYPORT, MASTER_USER='root', MASTER_CONNECT_RETRY=$connect_retry, MASTER_HEARTBEAT_PERIOD=4294967;
+SHOW GLOBAL STATUS LIKE 'slave_heartbeat_period';
+RESET SLAVE;
+--replace_result $MASTER_MYPORT MASTER_PORT
+--error ER_SLAVE_HEARTBEAT_VALUE_OUT_OF_RANGE
+eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=$MASTER_MYPORT, MASTER_USER='root', MASTER_CONNECT_RETRY=$connect_retry, MASTER_HEARTBEAT_PERIOD=4294968;
+RESET SLAVE;
+# Check double size of max allowed value for master_heartbeat_period
+--replace_result $MASTER_MYPORT MASTER_PORT
+--error ER_SLAVE_HEARTBEAT_VALUE_OUT_OF_RANGE
+eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=$MASTER_MYPORT, MASTER_USER='root', MASTER_CONNECT_RETRY=$connect_retry, MASTER_HEARTBEAT_PERIOD=8589935;
+RESET SLAVE;
+# Check 2^32
+--replace_result $MASTER_MYPORT MASTER_PORT
+--error ER_SLAVE_HEARTBEAT_VALUE_OUT_OF_RANGE
+eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=$MASTER_MYPORT, MASTER_USER='root', MASTER_CONNECT_RETRY=$connect_retry, MASTER_HEARTBEAT_PERIOD=4294967296;
+RESET SLAVE;
+--echo
+
+--echo *** Misc incorrect values ***
+--replace_result $MASTER_MYPORT MASTER_PORT
+--error ER_PARSE_ERROR
+eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=$MASTER_MYPORT, MASTER_USER='root', MASTER_CONNECT_RETRY=$connect_retry, MASTER_HEARTBEAT_PERIOD='-1';
+RESET SLAVE;
+--replace_result $MASTER_MYPORT MASTER_PORT
+--error ER_PARSE_ERROR
+eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=$MASTER_MYPORT, MASTER_USER='root', MASTER_CONNECT_RETRY=$connect_retry, MASTER_HEARTBEAT_PERIOD='123abc';
+RESET SLAVE;
+--replace_result $MASTER_MYPORT MASTER_PORT
+--error ER_PARSE_ERROR
+eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=$MASTER_MYPORT, MASTER_USER='root', MASTER_CONNECT_RETRY=$connect_retry, MASTER_HEARTBEAT_PERIOD='';
+RESET SLAVE;
+--echo
+
+#
+# Testing heartbeat
+#
+
+# Check received heartbeat events for running slave
+--echo *** Running slave ***
+--replace_result $MASTER_MYPORT MASTER_PORT
+eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=$MASTER_MYPORT, MASTER_USER='root', MASTER_CONNECT_RETRY=$connect_retry, MASTER_HEARTBEAT_PERIOD=0.1;
+--source include/start_slave.inc
+--connection master
+--sync_slave_with_master
+let $status_var_value= query_get_value(SHOW STATUS LIKE 'slave_received_heartbeats', Value, 1);
+let $status_var= slave_received_heartbeats;
+let $status_var_comparsion= >;
+--source include/wait_for_status_var.inc
+--echo Heartbeat event received
+--echo
+
+# Check received heartbeat events for stopped slave
+--echo *** Stopped slave ***
+--source include/stop_slave.inc
+let $rcvd_heartbeats_before= query_get_value(SHOW STATUS LIKE 'slave_received_heartbeats', Value, 1);
+sleep 2;
+let $rcvd_heartbeats_after= query_get_value(SHOW STATUS LIKE 'slave_received_heartbeats', Value, 1);
+let $result= query_get_value(SELECT ($rcvd_heartbeats_after - $rcvd_heartbeats_before) AS Result, Result, 1);
+--echo Number of received heartbeat events while slave stopped: $result
+--echo
+
+# Check received heartbeat events for started slave
+--echo *** Started slave ***
+--source include/start_slave.inc
+let $status_var_value= query_get_value(SHOW STATUS LIKE 'slave_received_heartbeats', Value, 1);
+--source include/wait_for_status_var.inc
+--echo Heartbeat event received
+--echo
+
+# Check received heartbeat events for stopped IO thread
+--echo *** Stopped IO thread ***
+--source include/stop_slave_io.inc
+let $rcvd_heartbeats_before= query_get_value(SHOW STATUS LIKE 'slave_received_heartbeats', Value, 1);
+sleep 2;
+let $rcvd_heartbeats_after= query_get_value(SHOW STATUS LIKE 'slave_received_heartbeats', Value, 1);
+let $result= query_get_value(SELECT ($rcvd_heartbeats_after - $rcvd_heartbeats_before) AS Result, Result, 1);
+--echo Number of received heartbeat events while io thread stopped: $result
+--echo
+
+# Check received heartbeat events for started IO thread
+--echo *** Started IO thread ***
+START SLAVE IO_THREAD;
+--source include/wait_for_slave_io_to_start.inc
+let $status_var_value= query_get_value(SHOW STATUS LIKE 'slave_received_heartbeats', Value, 1);
+--source include/wait_for_status_var.inc
+--echo Heartbeat event received
+--echo
+
+# Check received heartbeat events for stopped SQL thread
+--echo *** Stopped SQL thread ***
+--source include/stop_slave_sql.inc
+let $rcvd_heartbeats_before= query_get_value(SHOW STATUS LIKE 'slave_received_heartbeats', Value, 1);
+sleep 2;
+let $rcvd_heartbeats_after= query_get_value(SHOW STATUS LIKE 'slave_received_heartbeats', Value, 1);
+let $result= query_get_value(SELECT ($rcvd_heartbeats_after - $rcvd_heartbeats_before) > 0 AS Result, Result, 1);
+--echo Heartbeat events are received while sql thread stopped (1 means 'yes'): $result
+--echo
+
+# Check received heartbeat events for started SQL thread
+--echo *** Started SQL thread ***
+START SLAVE SQL_THREAD;
+--source include/wait_for_slave_sql_to_start.inc
+let $status_var_value= query_get_value(SHOW STATUS LIKE 'slave_received_heartbeats', Value, 1);
+--source include/wait_for_status_var.inc
+--echo Heartbeat event received
+--echo
+
+# Check received heartbeat event for stopped SQL thread by error
+--echo *** Stopped SQL thread by error ***
+--connection master
+CREATE TABLE t1 (a INT PRIMARY KEY, b VARCHAR(10), c LONGTEXT);
+--sync_slave_with_master
+INSERT INTO t1 VALUES (1, 'on slave', NULL);
+--connection master
+INSERT INTO t1 VALUES (1, 'on master', NULL);
+--connection slave
+set sql_log_bin= 0;
+call mtr.add_suppression("Slave SQL.*Duplicate entry .1. for key .PRIMARY.. on query.* error.* 1062");
+call mtr.add_suppression("Slave SQL.*Request to stop slave SQL Thread received while applying a group that has non-transactional changes; waiting for completion of the group");
+set sql_log_bin= 1;
+let $slave_errno= ER_DUP_ENTRY
+--source include/wait_for_slave_sql_error.inc
+let $rcvd_heartbeats_before= query_get_value(SHOW STATUS LIKE 'slave_received_heartbeats', Value, 1);
+sleep 4;
+let $rcvd_heartbeats_after= query_get_value(SHOW STATUS LIKE 'slave_received_heartbeats', Value, 1);
+let $result= query_get_value(SELECT ($rcvd_heartbeats_after - $rcvd_heartbeats_before) > 0 AS Result, Result, 1);
+--echo Heartbeat events are received while sql thread stopped (1 means 'yes'): $result
+--source include/stop_slave.inc
+set sql_log_bin= 0;
+DROP TABLE t1;
+set sql_log_bin= 1;
+--echo
+
+# Check received heartbeat events while master send events to slave
+--echo *** Master send to slave ***
+--connection master
+# Create the event that will update table t1 every second
+DELIMITER |;
+CREATE EVENT e1
+ ON SCHEDULE EVERY 1 SECOND
+ DO
+ BEGIN
+ UPDATE test.t1 SET a = a + 1 WHERE a < 10;
+ END|
+DELIMITER ;|
+--connection slave
+--source include/reset_slave.inc
+--replace_result $MASTER_MYPORT MASTER_PORT
+eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=$MASTER_MYPORT, MASTER_USER='root', MASTER_CONNECT_RETRY=$connect_retry, MASTER_HEARTBEAT_PERIOD=5;
+--source include/start_slave.inc
+--connection master
+# Enable scheduler
+SET @@global.event_scheduler=1;
+
+--sync_slave_with_master
+let $rcvd_heartbeats_before= query_get_value(SHOW STATUS LIKE 'slave_received_heartbeats', Value, 1);
+
+--connection master
+
+# Whether or not to send a heartbeat is decided on the master, based on
+# whether the binlog was updated during the period or not.
+# Even with the 1-second event, we cannot make the master to write binary
+# logs (or execute SQL) in a timely manner. We can only check that they
+# were executed in a timely manner, and if they were not, neutralize the
+# heartbeat check on the slave.
+# We will wait for 5 events, and keep checking 'Binlog_commits' on master.
+# Time interval between consequent events will be measured.
+# We can only expect that no heartbeats have been sent if the interval
+# between events never exceeded MASTER_HEARTBEAT_PERIOD.
+# If it has exceeded the value at least once, the slave can legitimately
+# receive a heartbeat (but we cannot require it, because the delay
+# could have occurred somewhere else, e.g. upon checking the status).
+# So, if the delay is detected, we will signal slave to ignore possible
+# heartbeats.
+
+let $possible_heartbeats= 0;
+let $commits_to_wait= 5;
+while ($commits_to_wait)
+{
+ let $tm= `SELECT UNIX_TIMESTAMP(NOW(3))`;
+ let $binlog_commits= query_get_value(SHOW STATUS LIKE 'Binlog_commits', Value, 1);
+ let $wait_condition= SELECT VARIABLE_VALUE > $binlog_commits FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME= 'BINLOG_COMMITS';
+ --source include/wait_condition.inc
+ dec $commits_to_wait;
+ if (`SELECT UNIX_TIMESTAMP(NOW(3)) > $tm + 5`)
+ {
+ let $possible_heartbeats= 1;
+ let $commits_to_wait= 0;
+ }
+}
+
+--connection slave
+let $rcvd_heartbeats_after= query_get_value(SHOW STATUS LIKE 'slave_received_heartbeats', Value, 1);
+let $result= `SELECT CASE WHEN $possible_heartbeats THEN 'TRUE' WHEN $rcvd_heartbeats_after - $rcvd_heartbeats_before > 0 THEN 'FALSE' ELSE 'TRUE' END`;
+--echo Received heartbeats meet expectations: $result
+--connection master
+DELETE FROM t1;
+DROP EVENT e1;
+--sync_slave_with_master
+--echo
+
+# Check received heartbeat events while logs flushed on slave
+--echo *** Flush logs on slave ***
+STOP SLAVE;
+--source include/reset_slave.inc
+set sql_log_bin= 0;
+DROP TABLE t1;
+set sql_log_bin= 1;
+--connection master
+DROP TABLE t1;
+RESET MASTER;
+--connection slave
+--replace_result $MASTER_MYPORT MASTER_PORT
+eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=$MASTER_MYPORT, MASTER_USER='root', MASTER_CONNECT_RETRY=$connect_retry, MASTER_HEARTBEAT_PERIOD=0.5;
+let $slave_param_comparison= =;
+--source include/start_slave.inc
+let $rcvd_heartbeats_before= query_get_value(SHOW STATUS LIKE 'slave_received_heartbeats', Value, 1);
+# Flush logs every 0.1 second during 5 sec
+--disable_query_log
+let $i=100;
+while ($i) {
+ FLUSH LOGS;
+ dec $i;
+ sleep 0.1;
+}
+--enable_query_log
+let $rcvd_heartbeats_after= query_get_value(SHOW STATUS LIKE 'slave_received_heartbeats', Value, 1);
+let $result= query_get_value(SELECT ($rcvd_heartbeats_after - $rcvd_heartbeats_before) > 0 AS Result, Result, 1);
+--echo Heartbeat events are received while rotation of relay logs (1 means 'yes'): $result
+--echo
+
+# Use compressed protocol between master and slave
+--echo *** Compressed protocol ***
+--connection master
+SET @@global.slave_compressed_protocol=1;
+--connection slave
+--source include/stop_slave.inc
+--source include/reset_slave.inc
+SET @@global.slave_compressed_protocol=1;
+--replace_result $MASTER_MYPORT MASTER_PORT
+eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=$MASTER_MYPORT, MASTER_USER='root', MASTER_CONNECT_RETRY=$connect_retry, MASTER_HEARTBEAT_PERIOD=0.1;
+--source include/start_slave.inc
+let $status_var_value= query_get_value(SHOW STATUS LIKE 'slave_received_heartbeats', Value, 1);
+let $status_var= slave_received_heartbeats;
+let $status_var_comparsion= >;
+--source include/wait_for_status_var.inc
+--echo Heartbeat event received
+SET @@global.slave_compressed_protocol=0;
+--connection master
+SET @@global.slave_compressed_protocol=0;
+--echo
+
+
+# Check received heartbeat events after reset of master
+--echo *** Reset master ***
+--connection slave
+STOP SLAVE;
+--source include/reset_slave.inc
+--replace_result $MASTER_MYPORT MASTER_PORT
+eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=$MASTER_MYPORT, MASTER_USER='root', MASTER_CONNECT_RETRY=$connect_retry, MASTER_HEARTBEAT_PERIOD=0.1;
+--source include/start_slave.inc
+let $rcvd_heartbeats_before= query_get_value(SHOW STATUS LIKE 'slave_received_heartbeats', Value, 1);
+--connection master
+RESET MASTER;
+--enable_query_log
+--sync_slave_with_master
+--sleep 2
+let $rcvd_heartbeats_after= query_get_value(SHOW STATUS LIKE 'slave_received_heartbeats', Value, 1);
+let $result= query_get_value(SELECT ($rcvd_heartbeats_after - $rcvd_heartbeats_before) > 0 AS Result, Result, 1);
+--echo Heartbeat events are received after reset of master (1 means 'yes'): $result
+--echo
+
+# Reloaded master should restore heartbeat
+--echo *** Reload master ***
+--connection slave
+STOP SLAVE;
+--source include/reset_slave.inc
+--replace_result $MASTER_MYPORT MASTER_PORT
+eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=$MASTER_MYPORT, MASTER_USER='root', MASTER_CONNECT_RETRY=$connect_retry, MASTER_HEARTBEAT_PERIOD=0.1;
+--source include/start_slave.inc
+# Wait until slave_received_heartbeats will be incremented
+let $status_var_value= query_get_value(SHOW STATUS LIKE 'slave_received_heartbeats', Value, 1);
+let $status_var= slave_received_heartbeats;
+let $status_var_comparsion= >;
+--source include/wait_for_status_var.inc
+--echo Heartbeat event received
+--let $rpl_server_number= 1
+--source include/rpl_restart_server.inc
+# make sure IO thread has re-connected
+# due to slow valgrind env the following wait_for_status may time out
+--let $rpl_allow_error= 1
+--source include/wait_for_slave_io_to_start.inc
+# Wait until slave_received_heartbeats will be incremented
+let $status_var_value= query_get_value(SHOW STATUS LIKE 'slave_received_heartbeats', Value, 1);
+let $status_var= slave_received_heartbeats;
+let $status_var_comparsion= >;
+--source include/wait_for_status_var.inc
+--echo Heartbeat event received
+--echo
+
+# Circular replication: demonstrating bidirectional hearbeat flow
+--echo *** Circular replication ***
+# Configure circular replication
+--source include/rpl_reset.inc
+--source include/stop_slave.inc
+--let $rpl_topology= 1->2->1
+--source include/rpl_change_topology.inc
+
+#--connection slave
+#--source include/stop_slave.inc
+#let $slave_binlog= query_get_value(SHOW MASTER STATUS, File, 1);
+--connection master
+#--replace_result $SLAVE_MYPORT SLAVE_PORT $slave_binlog SLAVE_BINLOG
+#eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=$SLAVE_MYPORT, MASTER_USER='root', MASTER_CONNECT_RETRY=$connect_retry, MASTER_HEARTBEAT_PERIOD=1, MASTER_LOG_FILE='$slave_binlog';
+
+# BUG#12403008 RPL_HEARTBEAT_BASIC FAILS SPORADICALLY ON PUSHBUILD
+# MASTER_HEARTBEAT_PERIOD had the default value (slave_net_timeout/2)
+# so wait on "Heartbeat event received on master", that only waits for
+# 1 minute, sometimes timeout before heartbeat arrives.
+CHANGE MASTER TO MASTER_HEARTBEAT_PERIOD=1;
+--source include/start_slave.inc
+
+# Insert data on master and on slave and make sure that it replicated for both directions
+CREATE TABLE t1 (a INT PRIMARY KEY, b VARCHAR(10));
+INSERT INTO t1 VALUES(1, 'on master');
+--save_master_pos
+--connection slave
+## set slave period 1/10 of master's
+CHANGE MASTER TO MASTER_HEARTBEAT_PERIOD=0.1;
+--source include/start_slave.inc
+--sync_with_master
+INSERT INTO t1 VALUES(2, 'on slave');
+--sync_slave_with_master master
+SELECT * FROM t1 ORDER BY a;
+let $master_rcvd_heartbeats_before= query_get_value(SHOW STATUS LIKE 'slave_received_heartbeats', Value, 1);
+--connection slave
+SELECT * FROM t1 ORDER BY a;
+
+# Wait for heartbeat event on master
+--connection master
+let $status_var= slave_received_heartbeats;
+let $status_var_value= query_get_value(SHOW STATUS LIKE 'slave_received_heartbeats', Value, 1);
+let $status_var_comparsion= >;
+--source include/wait_for_status_var.inc
+--echo Heartbeat event received on master
+
+# Wait heartbeat events on slave
+--connection slave
+let $status_var= slave_received_heartbeats;
+let $status_var_value= query_get_value(SHOW STATUS LIKE 'slave_received_heartbeats', Value, 1);
+let $status_var_comparsion= >;
+--source include/wait_for_status_var.inc
+--echo Heartbeat event received on slave
+let $slave_rcvd_heartbeats= query_get_value(SHOW STATUS LIKE 'slave_received_heartbeats', Value, 1);
+
+#
+# Clean up and restore system variables
+#
+--echo *** Clean up ***
+--connection master
+#--source include/stop_slave.inc
+DROP TABLE t1;
+--sync_slave_with_master
+SET @@global.slave_net_timeout=@restore_slave_net_timeout;
+
+--disable_prepare_warnings
+
+#--let $rpl_only_running_threads= 1
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_heartbeat_debug.test b/mysql-test/suite/rpl/t/rpl_heartbeat_debug.test
new file mode 100644
index 00000000..bd66a249
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_heartbeat_debug.test
@@ -0,0 +1,52 @@
+# Testing master to slave heartbeat protocol, test cases that need debug build.
+
+--source include/have_debug.inc
+--source include/master-slave.inc
+
+connection slave;
+--source include/stop_slave.inc
+set @restore_slave_net_timeout= @@global.slave_net_timeout;
+--disable_warnings
+set @@global.slave_net_timeout= 10;
+--enable_warnings
+
+###
+### Checking the range
+###
+
+#
+# default period slave_net_timeout/2
+#
+--query_vertical show status like 'Slave_heartbeat_period';
+SET @saved_dbug= @@GLOBAL.debug_dbug;
+SET GLOBAL debug_dbug="+d,simulate_slave_heartbeat_network_error";
+CALL mtr.add_suppression('SET @master_heartbeat_period to master failed with error');
+CALL mtr.add_suppression('Master command COM_REGISTER_SLAVE failed: failed registering on master, reconnecting to try again');
+--source include/start_slave.inc
+
+
+connection master;
+--disable_warnings
+drop table if exists t1;
+--enable_warnings
+
+CREATE TABLE t1 (a INT PRIMARY KEY);
+INSERT INTO t1 VALUES (1);
+
+sync_slave_with_master;
+
+--connection slave
+SELECT * FROM t1;
+
+connection master;
+drop table t1;
+
+connection slave;
+--source include/stop_slave.inc
+--disable_warnings
+SET GLOBAL debug_dbug=@saved_dbug;
+set @@global.slave_net_timeout= @restore_slave_net_timeout;
+--enable_warnings
+--source include/start_slave.inc
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_heartbeat_ssl.test b/mysql-test/suite/rpl/t/rpl_heartbeat_ssl.test
new file mode 100644
index 00000000..2c41fdee
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_heartbeat_ssl.test
@@ -0,0 +1,57 @@
+#############################################################
+# Author: Serge Kozlov <Serge.Kozlov@Sun.COM>
+# Date: 02/19/2009
+# Purpose: Testing basic functionality of heartbeat over SSL
+#############################################################
+--source include/have_ssl_communication.inc
+--source include/master-slave.inc
+--echo
+
+#
+# Testing heartbeat over SSL
+#
+
+# Heartbeat over SSL
+--echo *** Heartbeat over SSL ***
+--connection master
+let $master_binlog= query_get_value(SHOW MASTER STATUS, File, 1);
+--connection slave
+--source include/stop_slave.inc
+RESET SLAVE;
+# Connect to master with SSL
+--replace_result $MASTER_MYPORT MASTER_PORT $MYSQL_TEST_DIR MYSQL_TEST_DIR $master_binlog MASTER_BINLOG
+eval CHANGE MASTER TO
+ MASTER_HOST='127.0.0.1',
+ MASTER_PORT=$MASTER_MYPORT,
+ MASTER_USER='root',
+ MASTER_HEARTBEAT_PERIOD=0.1,
+ MASTER_LOG_FILE='$master_binlog',
+ MASTER_SSL=1,
+ MASTER_SSL_CA='$MYSQL_TEST_DIR/std_data/cacert.pem',
+ MASTER_SSL_CERT='$MYSQL_TEST_DIR/std_data/client-cert.pem',
+ MASTER_SSL_KEY='$MYSQL_TEST_DIR/std_data/client-key.pem',
+ MASTER_USE_GTID=NO;
+--source include/start_slave.inc
+# Check SSL state of slave
+let $slave_ssl_status= query_get_value(SHOW SLAVE STATUS, Master_SSL_Allowed, 1);
+--echo Master_SSL_Allowed: $slave_ssl_status
+# Wait until hearbeat event will received
+let $status_var_value= query_get_value(SHOW STATUS LIKE 'slave_received_heartbeats', Value, 1);
+let $status_var= slave_received_heartbeats;
+let $status_var_comparsion= >;
+--source include/wait_for_status_var.inc
+--echo Heartbeat event has received
+--echo
+
+#
+# Clean up
+#
+--echo *** Clean up ***
+--source include/stop_slave.inc
+CHANGE MASTER TO
+ MASTER_SSL=0,
+ MASTER_SSL_CA='',
+ MASTER_SSL_CERT='',
+ MASTER_SSL_KEY='';
+--let $rpl_only_running_threads= 1
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_hrtime.test b/mysql-test/suite/rpl/t/rpl_hrtime.test
new file mode 100644
index 00000000..98b08abe
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_hrtime.test
@@ -0,0 +1,7 @@
+--source include/have_binlog_format_mixed_or_statement.inc
+
+--source suite/rpl/include/hrtime.inc
+
+let $MYSQLD_DATADIR= `select @@datadir`;
+--exec $MYSQL_BINLOG --short-form $MYSQLD_DATADIR/master-bin.000001
+
diff --git a/mysql-test/suite/rpl/t/rpl_hrtime_row.test b/mysql-test/suite/rpl/t/rpl_hrtime_row.test
new file mode 100644
index 00000000..e1d49f53
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_hrtime_row.test
@@ -0,0 +1,3 @@
+--source include/have_binlog_format_row.inc
+--source suite/rpl/include/hrtime.inc
+
diff --git a/mysql-test/suite/rpl/t/rpl_idempotency.test b/mysql-test/suite/rpl/t/rpl_idempotency.test
new file mode 100644
index 00000000..12dec236
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_idempotency.test
@@ -0,0 +1,107 @@
+# Testing various forms of idempotency for replication that should
+# work the same way under statement based as under row based.
+
+source include/master-slave.inc;
+
+# Add suppression for expected warning(s) in slaves error log
+call mtr.add_suppression("Slave SQL.*Can.t find record in .t[12].* error.* 1032");
+call mtr.add_suppression("Slave SQL.*Cannot delete or update a parent row: a foreign key constraint fails .* error.* 1451");
+call mtr.add_suppression("Slave SQL.*Cannot add or update a child row: a foreign key constraint fails .* error.* 1452");
+call mtr.add_suppression("Slave SQL.*Could not execute Write_rows event on table test.* Duplicate entry .1. for key .PRIMARY.* error.* 1062");
+call mtr.add_suppression("Can't find record in 't1'");
+call mtr.add_suppression("Can't find record in 't2'");
+
+connection master;
+CREATE TABLE t1 (a INT PRIMARY KEY);
+CREATE TABLE t2 (a INT);
+INSERT INTO t1 VALUES (-1),(-2),(-3);
+INSERT INTO t2 VALUES (-1),(-2),(-3);
+sync_slave_with_master;
+
+SET @old_slave_exec_mode= @@global.slave_exec_mode;
+SET @@global.slave_exec_mode= IDEMPOTENT;
+
+# A delete for a row that does not exist, the statement is
+# deliberately written to be idempotent for statement-based
+# replication as well. We test this towards both a table with a
+# primary key and without a primary key.
+
+connection slave;
+DELETE FROM t1 WHERE a = -2;
+DELETE FROM t2 WHERE a = -2;
+connection master;
+DELETE FROM t1 WHERE a = -2;
+DELETE FROM t2 WHERE a = -2;
+SELECT * FROM t1 ORDER BY a;
+SELECT * FROM t2 ORDER BY a;
+sync_slave_with_master;
+SELECT * FROM t1 ORDER BY a;
+SELECT * FROM t2 ORDER BY a;
+--source include/check_slave_no_error.inc
+
+# An insert of a row that already exists. Since we are replacing the
+# row if it already exists, the most apropriate representation is
+# INSERT IGNORE. We only test this towards a table with a primary key,
+# since the other case does not make sense.
+
+INSERT IGNORE INTO t1 VALUES (-2);
+connection master;
+INSERT IGNORE INTO t1 VALUES (-2);
+SELECT * FROM t1 ORDER BY a;
+sync_slave_with_master;
+SELECT * FROM t1 ORDER BY a;
+--source include/check_slave_no_error.inc
+
+
+# BUG#19958: RBR idempotency issue for UPDATE and DELETE
+
+# Statement-based and row-based replication have different behaviour
+# when updating a row with an explicit WHERE-clause that matches
+# exactly one row (or no row at all). For statement-based replication,
+# the statement is idempotent since the first time it is executed, it
+# will update exactly one row, and the second time it will not update
+# any row at all. This was not the case for row-based replication, so
+# we test under both row-based and statement-based replication both
+# for tables with and without primary keys.
+
+connection slave;
+UPDATE t1 SET a = 1 WHERE a = -1;
+UPDATE t2 SET a = 1 WHERE a = -1;
+connection master;
+UPDATE t1 SET a = 1 WHERE a = -1;
+UPDATE t2 SET a = 1 WHERE a = -1;
+SELECT * FROM t1 ORDER BY a;
+SELECT * FROM t2 ORDER BY a;
+sync_slave_with_master;
+SELECT * FROM t1 ORDER BY a;
+SELECT * FROM t2 ORDER BY a;
+--source include/check_slave_no_error.inc
+
+connection slave;
+drop table t1, t2;
+
+connection master;
+DROP TABLE t1, t2;
+sync_slave_with_master;
+--source include/check_slave_no_error.inc
+create database d;
+create database e;
+
+connection master;
+create database d;
+create database if not exists e;
+
+sync_slave_with_master;
+--source include/check_slave_no_error.inc
+drop database d;
+drop database e;
+
+connection master;
+drop database d;
+drop database if exists e;
+sync_slave_with_master;
+--source include/check_slave_no_error.inc
+
+SET @@global.slave_exec_mode= @old_slave_exec_mode;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_ignore_grant-slave.opt b/mysql-test/suite/rpl/t/rpl_ignore_grant-slave.opt
new file mode 100644
index 00000000..e931bfbd
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_ignore_grant-slave.opt
@@ -0,0 +1 @@
+--replicate-wild-ignore-table=mysql.%
diff --git a/mysql-test/suite/rpl/t/rpl_ignore_grant.test b/mysql-test/suite/rpl/t/rpl_ignore_grant.test
new file mode 100644
index 00000000..58457c14
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_ignore_grant.test
@@ -0,0 +1,55 @@
+# Test that GRANT is not replicated to the slave
+# when --replicate-wild-ignore-table=mysql.%
+# In BUG#980, this test would _randomly_ fail.
+
+source include/master-slave.inc;
+
+# do not be influenced by other tests.
+connection master;
+set sql_mode="";
+delete from mysql.user where user=_binary'rpl_ignore_grant';
+delete from mysql.db where user=_binary'rpl_ignore_grant';
+flush privileges;
+--sync_slave_with_master
+set sql_mode="";
+# as these DELETE were not replicated, we need to do them manually on the
+# slave.
+delete from mysql.user where user=_binary'rpl_ignore_grant';
+delete from mysql.db where user=_binary'rpl_ignore_grant';
+flush privileges;
+
+# test non-replication of GRANT
+connection master;
+grant select on *.* to rpl_ignore_grant@localhost;
+grant drop on test.* to rpl_ignore_grant@localhost;
+show grants for rpl_ignore_grant@localhost;
+--sync_slave_with_master
+--error 1141 #("no such grant for user")
+show grants for rpl_ignore_grant@localhost;
+# check it another way
+select count(*) from mysql.user where user=_binary'rpl_ignore_grant';
+select count(*) from mysql.db where user=_binary'rpl_ignore_grant';
+
+# test non-replication of SET PASSWORD
+# first force creation of the user on slave (because as the user does not exist
+# on slave, the SET PASSWORD may be replicated but silently do nothing; this is
+# not what we want; we want it to be not-replicated).
+grant select on *.* to rpl_ignore_grant@localhost;
+connection master;
+set password for rpl_ignore_grant@localhost=password("does it work?");
+--sync_slave_with_master
+select password<>_binary'' from mysql.user where user=_binary'rpl_ignore_grant';
+
+# clear what we have done, to not influence other tests.
+connection master;
+delete from mysql.user where user=_binary'rpl_ignore_grant';
+delete from mysql.db where user=_binary'rpl_ignore_grant';
+flush privileges;
+--sync_slave_with_master
+delete from mysql.user where user=_binary'rpl_ignore_grant';
+delete from mysql.db where user=_binary'rpl_ignore_grant';
+flush privileges;
+
+connection master;
+# End of 4.1 tests
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_ignore_revoke-slave.opt b/mysql-test/suite/rpl/t/rpl_ignore_revoke-slave.opt
new file mode 100644
index 00000000..e931bfbd
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_ignore_revoke-slave.opt
@@ -0,0 +1 @@
+--replicate-wild-ignore-table=mysql.%
diff --git a/mysql-test/suite/rpl/t/rpl_ignore_revoke.test b/mysql-test/suite/rpl/t/rpl_ignore_revoke.test
new file mode 100644
index 00000000..db20e807
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_ignore_revoke.test
@@ -0,0 +1,52 @@
+# test verifies that REVOKE must not be replicated when
+# slave server starts with --replicate-wild-ignore-table=mysql.%
+# the option is set in rpl_ignore_revoke-slave.opt
+# The first part of BUG#9483 for GRANT is checked by
+# existed specific rpl_ignore_grant test case (BUG#980)
+
+
+source include/master-slave.inc;
+
+### CLEAN-UP: create an account and manually duplicate it on the slave
+
+connection master;
+grant select on *.* to 'user_foo'@'%' identified by 'user_foopass';
+revoke select on *.* from 'user_foo'@'%';
+select select_priv from mysql.user where user='user_foo' /* master:must be N */;
+
+sync_slave_with_master;
+#connection slave;
+grant select on *.* to 'user_foo'@'%' identified by 'user_foopass';
+revoke select on *.* from 'user_foo'@'%';
+select select_priv from mysql.user where user='user_foo' /* slave:must be N */;
+
+
+### TEST
+
+#connection slave;
+grant select on *.* to 'user_foo'@'%' identified by 'user_foopass';
+select select_priv from mysql.user where user='user_foo' /* slave:must be Y */;
+
+connection master;
+revoke select on *.* from 'user_foo';
+select select_priv from mysql.user where user='user_foo' /* master:must be N */;
+
+sync_slave_with_master;
+#connection slave;
+select select_priv from mysql.user where user='user_foo' /* slave:must get Y */;
+
+### CLEAN-UP
+
+connection slave;
+--disable_abort_on_error
+revoke select on *.* FROM 'user_foo';
+--enable_abort_on_error
+
+connection master;
+delete from mysql.user where user="user_foo";
+sync_slave_with_master;
+
+# Since changes to mysql.* are ignored, the revoke need to
+# be done on slave as well
+delete from mysql.user where user="user_foo";
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_ignore_table-slave.opt b/mysql-test/suite/rpl/t/rpl_ignore_table-slave.opt
new file mode 100644
index 00000000..3aabbb2e
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_ignore_table-slave.opt
@@ -0,0 +1 @@
+--replicate-ignore-table=test.t1 --replicate-ignore-table=test.t2 --replicate-ignore-table=test.t3 --replicate-wild-ignore-table=%.tmptbl%
diff --git a/mysql-test/suite/rpl/t/rpl_ignore_table.test b/mysql-test/suite/rpl/t/rpl_ignore_table.test
new file mode 100644
index 00000000..b78ad90a
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_ignore_table.test
@@ -0,0 +1,198 @@
+let collation=utf8mb3_unicode_ci;
+source include/have_collation.inc;
+source include/master-slave.inc;
+
+call mtr.add_suppression("Can't find record in 't.'");
+call mtr.add_suppression("Can't find record in 'global_priv'");
+call mtr.add_suppression("Can't find record in 'tables_priv'");
+
+#
+# BUG#16487
+#
+# Requirement:
+# Multi-updates on ignored tables should not fail even if the slave does
+# not have the ignored tables.
+#
+# Note table t1, t2, and t3 are ignored in the option file to this test.
+#
+
+--echo **** Test case for BUG#16487 ****
+connection master;
+CREATE TABLE test.t4 (a int);
+CREATE TABLE test.t1 (a int);
+
+# Expect: The row must *not* by updated on slave, since t1 is ignored
+UPDATE test.t4 NATURAL JOIN test.t1 SET t1.a=5;
+
+sync_slave_with_master;
+SELECT * FROM t4;
+
+# Cleanup
+connection master;
+DROP TABLE t1;
+DROP TABLE t4;
+
+sync_slave_with_master;
+
+
+#
+# Bug#25482 GRANT statements are not replicated if
+# you use "replicate-ignore-table"
+#
+
+--echo **** Test case for BUG#25482 ****
+--echo **** Adding GRANTS on master ****
+
+connection master;
+create table test.t1(a int);
+create table test.t4(a int);
+
+set sql_mode="";
+# Simple user that should not replicate
+GRANT SELECT ON test.t1 TO mysqltest1@localhost;
+
+# Partial replicate
+GRANT INSERT ON test.t4 TO mysqltest2@localhost;
+GRANT select, update, insert, references on t1
+ to mysqltest2@localhost;
+
+# Partial replicate 2
+GRANT SELECT ON test.* TO mysqltest3@localhost;
+GRANT INSERT ON test.t4 TO mysqltest3@localhost;
+GRANT select(a), update(a), insert(a), references(a) on t4
+ to mysqltest3@localhost;
+
+# Create another database and table
+create database mysqltest2;
+create table mysqltest2.t2 (id int);
+# Create a grant that should replicate
+GRANT SELECT ON mysqltest2.t2 TO mysqltest4@localhost IDENTIFIED BY 'pass';
+
+# Create a grant manually
+insert into mysql.global_priv (user, host) values ("mysqltest5", "somehost");
+
+# Partial replicate 3 with *.*
+GRANT SELECT ON *.* TO mysqltest6@localhost;
+GRANT INSERT ON *.* TO mysqltest6@localhost;
+GRANT INSERT ON test.* TO mysqltest6@localhost;
+GRANT INSERT ON test.t1 TO mysqltest6@localhost;
+
+--sorted_result
+show grants for mysqltest1@localhost;
+--sorted_result
+show grants for mysqltest2@localhost;
+--sorted_result
+show grants for mysqltest3@localhost;
+--sorted_result
+show grants for mysqltest4@localhost;
+--sorted_result
+show grants for mysqltest6@localhost;
+
+flush privileges;
+show grants for mysqltest5@somehost;
+
+set sql_mode="";
+sync_slave_with_master;
+
+--echo **** Checking grants on slave ****
+
+# Check that grants are replicated to slave
+--sorted_result
+show grants for mysqltest2@localhost;
+--sorted_result
+show grants for mysqltest3@localhost;
+--sorted_result
+show grants for mysqltest4@localhost;
+--sorted_result
+show grants for mysqltest5@somehost;
+--sorted_result
+show grants for mysqltest6@localhost;
+
+# mysqltest1 should not be on slave
+--error 1141
+show grants for mysqltest1@localhost;
+
+--echo **** Revoking grants on master ****
+connection master;
+REVOKE SELECT ON test.t1 FROM mysqltest1@localhost;
+REVOKE SELECT ON mysqltest2.t2 FROM mysqltest4@localhost;
+REVOKE select(a) on t4
+ from mysqltest3@localhost;
+
+--sorted_result
+show grants for mysqltest1@localhost;
+--sorted_result
+show grants for mysqltest3@localhost;
+--sorted_result
+show grants for mysqltest4@localhost;
+
+sync_slave_with_master;
+
+--echo **** Checking grants on slave ****
+
+# mysqltest1 should not be on slave
+--error 1141
+show grants for mysqltest1@localhost;
+show grants for mysqltest3@localhost;
+show grants for mysqltest4@localhost;
+
+# Cleanup
+# connection slave;
+# BUG31552 changes idempotency is not default any longer
+# In order the following `delete from mysql.user',
+# where mysqltest1 does not exist on slave,
+# to succeed on slave the mode is temporarily changed
+set global slave_exec_mode='IDEMPOTENT';
+call mtr.add_suppression("Slave SQL.*Could not execute Delete_rows event on table mysql.* error.* 1032");
+
+connection master;
+drop table t1, mysqltest2.t2;
+drop table t4;
+drop database mysqltest2;
+delete from mysql.user where user like "mysqltest%";
+delete from mysql.db where user like "mysqltest%";
+#
+# BUG 27606 causes failure to replicate this statement
+# move it to slave instead
+#delete from mysql.tables_priv where user like "mysqltest%";
+delete from mysql.columns_priv where user like "mysqltest%";
+
+sync_slave_with_master;
+# bug#31552: do not restore the mode here but later in order
+# to succeed with yet the following delete from mysql.tables_priv
+
+#BUG27606
+delete from mysql.tables_priv where user like "mysqltest%";
+
+connection master;
+
+#BUG27606
+delete from mysql.tables_priv where user like "mysqltest%";
+
+#
+# bug#22877 replication character sets get out of sync
+# using replicate-wild-ignore-table
+#
+connection master;
+--disable_warnings
+DROP TABLE IF EXISTS t5;
+--enable_warnings
+CREATE TABLE t5 (
+ word varchar(50) collate utf8_unicode_ci NOT NULL default ''
+) DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
+SET @@session.character_set_client=33,@@session.collation_connection=192;
+CREATE TEMPORARY TABLE tmptbl504451f4258$1 (id INT NOT NULL) ENGINE=MEMORY;
+INSERT INTO t5 (word) VALUES ('TEST’');
+SELECT HEX(word) FROM t5;
+sync_slave_with_master;
+set @@global.slave_exec_mode= default; # bug#31552 comments above
+connection slave;
+SELECT HEX(word) FROM t5;
+--error 1146
+SELECT * FROM tmptbl504451f4258$1;
+connection master;
+DROP TABLE t5;
+flush privileges;
+sync_slave_with_master;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_ignore_table_update-slave.opt b/mysql-test/suite/rpl/t/rpl_ignore_table_update-slave.opt
new file mode 100644
index 00000000..177f89e0
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_ignore_table_update-slave.opt
@@ -0,0 +1 @@
+--replicate-ignore-table=test.mysqltest_foo
diff --git a/mysql-test/suite/rpl/t/rpl_ignore_table_update.test b/mysql-test/suite/rpl/t/rpl_ignore_table_update.test
new file mode 100644
index 00000000..6591dbbc
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_ignore_table_update.test
@@ -0,0 +1,35 @@
+# This one assumes we are ignoring updates on table mysqltest_foo, but doing
+# the ones on all other tables
+
+source include/master-slave.inc;
+connection slave;
+
+#
+# For this test we must be in the test database
+#
+use test;
+
+--disable_warnings
+drop table if exists mysqltest_foo;
+drop table if exists mysqltest_bar;
+--enable_warnings
+
+create table mysqltest_foo (n int);
+insert into mysqltest_foo values(4);
+connection master;
+use test;
+create table mysqltest_foo (n int);
+insert into mysqltest_foo values(5);
+create table mysqltest_bar (m int);
+insert into mysqltest_bar values(15);
+create table t1 (k int);
+insert into t1 values(55);
+--sync_slave_with_master
+select mysqltest_foo.n,mysqltest_bar.m,t1.k from mysqltest_foo,mysqltest_bar,t1;
+connection master;
+drop table mysqltest_foo,mysqltest_bar,t1;
+--sync_slave_with_master
+drop table mysqltest_foo,mysqltest_bar,t1;
+
+# End of 4.1 tests
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_incident.test b/mysql-test/suite/rpl/t/rpl_incident.test
new file mode 100644
index 00000000..75d28d6a
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_incident.test
@@ -0,0 +1,61 @@
+#
+# This include file is used by more than one test suite
+# (currently rpl and binlog_encryption).
+# Please check all dependent tests after modifying it
+#
+
+--source include/have_debug.inc
+--source include/master-slave.inc
+
+SET @old_binlog_checksum=@@binlog_checksum;
+SET GLOBAL BINLOG_CHECKSUM=none;
+connection slave;
+SET @old_binlog_checksum=@@binlog_checksum;
+SET GLOBAL BINLOG_CHECKSUM=none;
+connection master;
+
+--echo **** On Master ****
+CREATE TABLE t1 (a INT);
+
+INSERT INTO t1 VALUES (1),(2),(3);
+SELECT * FROM t1;
+
+set @saved_dbug = @@global.debug_dbug;
+SET GLOBAL debug_dbug= '+d,incident_database_resync_on_replace,*';
+
+# This will generate an incident log event and store it in the binary
+# log before the replace statement.
+REPLACE INTO t1 VALUES (4);
+--save_master_pos
+SELECT * FROM t1;
+
+set @@global.debug_dbug = @saved_dbug;
+
+connection slave;
+# Wait until SQL thread stops with error LOST_EVENT on master
+call mtr.add_suppression("Slave SQL.*The incident LOST_EVENTS occurred on the master.* 1590");
+let $slave_sql_errno= 1590;
+let $show_slave_sql_error= 1;
+source include/wait_for_slave_sql_error.inc;
+
+# The 4 should not be inserted into the table, since the incident log
+# event should have stop the slave.
+--echo **** On Slave ****
+SELECT * FROM t1;
+
+SET GLOBAL SQL_SLAVE_SKIP_COUNTER=1;
+START SLAVE;
+--sync_with_master
+
+# Now, we should have inserted the row into the table and the slave
+# should be running. We should also have rotated to a new binary log.
+
+SELECT * FROM t1;
+source include/check_slave_is_running.inc;
+
+connection master;
+SET GLOBAL BINLOG_CHECKSUM=@old_binlog_checksum;
+DROP TABLE t1;
+--sync_slave_with_master
+SET GLOBAL BINLOG_CHECKSUM=@old_binlog_checksum;
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_incompatible_heartbeat.test b/mysql-test/suite/rpl/t/rpl_incompatible_heartbeat.test
new file mode 100644
index 00000000..104debe7
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_incompatible_heartbeat.test
@@ -0,0 +1,44 @@
+# ==== Purpose ====
+#
+# Test verifies that slave IO thread can process heartbeat events with log_pos
+# values higher than UINT32_MAX.
+#
+# ==== Implementation ====
+#
+# Steps:
+# 0 - Stop slave threads. Configure a small master_heartbeat_period.
+# 1 - Using debug points, simulate a huge binlog offset higher than
+# UINT32_MAX on master.
+# 2 - Start the slave and observe that slave IO thread is able to process
+# the offset received through heartbeat event.
+#
+# ==== References ====
+#
+# MDEV-16146: MariaDB slave stops with incompatible heartbeat
+#
+--source include/have_debug.inc
+--source include/have_innodb.inc
+--source include/have_binlog_format_mixed.inc
+# Test simulates binarylog offsets higher than UINT32_MAX
+--source include/have_64bit.inc
+--source include/master-slave.inc
+
+--connection master
+SET @saved_dbug = @@GLOBAL.debug_dbug;
+SET @@global.debug_dbug= 'd,simulate_pos_4G';
+
+--connection slave
+--source include/stop_slave.inc
+CHANGE MASTER TO MASTER_HEARTBEAT_PERIOD=0.001;
+--source include/start_slave.inc
+
+--connection master
+sleep 1;
+SET @@GLOBAL.debug_dbug = @saved_dbug;
+--sync_slave_with_master
+
+--connection master
+CREATE TABLE t (f INT) ENGINE=INNODB;
+INSERT INTO t VALUES (10);
+DROP TABLE t;
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_init_slave-slave.opt b/mysql-test/suite/rpl/t/rpl_init_slave-slave.opt
new file mode 100644
index 00000000..337e8a60
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_init_slave-slave.opt
@@ -0,0 +1 @@
+--init-slave="set global max_connections=500"
diff --git a/mysql-test/suite/rpl/t/rpl_init_slave.test b/mysql-test/suite/rpl/t/rpl_init_slave.test
new file mode 100644
index 00000000..1803b146
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_init_slave.test
@@ -0,0 +1,34 @@
+source include/master-slave.inc;
+
+#
+# Test of init_slave variable
+#
+
+set global max_connections=151;
+
+connection slave;
+source include/stop_slave.inc;
+source include/start_slave.inc;
+
+connection master;
+sync_slave_with_master;
+show variables like 'init_slave';
+show variables like 'max_connections';
+reset master;
+connection master;
+show variables like 'init_slave';
+show variables like 'max_connections';
+sync_slave_with_master;
+# Save variable value
+set @my_global_init_connect= @@global.init_connect;
+set global init_connect="set @c=1";
+show variables like 'init_connect';
+connection master;
+sync_slave_with_master;
+
+# Restore changed global variable
+set global init_connect= @my_global_init_connect;
+set global max_connections= default;
+
+# End of 4.1 tests
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_init_slave_errors.test b/mysql-test/suite/rpl/t/rpl_init_slave_errors.test
new file mode 100644
index 00000000..46673ea4
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_init_slave_errors.test
@@ -0,0 +1,96 @@
+#
+# This include file is used by more than one test suite
+# (currently rpl and binlog_encryption).
+# Please check all dependent tests after modifying it
+#
+
+######################################################################
+# Some errors that cause the slave SQL thread to stop are not shown in
+# the Slave_SQL_Error column of "SHOW SLAVE STATUS". Instead, the error
+# is only in the server's error log.
+#
+# Two failures and their respective reporting are verified:
+#
+# 1 - Failures during slave thread initialization
+# 2 - Failures while processing queries passed through the init_slave
+# option.
+#
+# In order to check the first type of failure, we inject a fault in the
+# SQL/IO Threads through SET GLOBAL debug.
+#
+# To check the second type, we set @@global.init_slave to an invalid
+# command thus preventing the initialization of the SQL Thread.
+#
+# Obs:
+# 1 - Note that testing failures while initializing the relay log position
+# is hard as the same function is called before the code reaches the point
+# that we want to test.
+#
+# 2 - This test does not target failures that are reported while applying
+# events such as duplicate keys, errors while reading the relay-log.bin*,
+# etc. Such errors are already checked on other tests.
+######################################################################
+
+######################################################################
+# Configuring the Environment
+######################################################################
+source include/have_debug.inc;
+source include/have_log_bin.inc;
+source include/master-slave.inc;
+
+connection slave;
+
+--disable_warnings
+stop slave;
+--enable_warnings
+reset slave;
+
+######################################################################
+# Injecting faults in the threads' initialization
+######################################################################
+connection slave;
+
+# Set debug flags on slave to force errors to occur
+set @saved_dbug = @@global.debug_dbug;
+SET GLOBAL debug_dbug= "d,simulate_io_slave_error_on_init,simulate_sql_slave_error_on_init";
+
+start slave;
+
+#
+# slave is going to stop because of emulated failures
+# but there won't be any crashes nor asserts hit.
+#
+# 1593 = ER_SLAVE_FATAL_ERROR
+--let $slave_sql_errno= 1593
+--let $show_slave_sql_error= 1
+--source include/wait_for_slave_sql_error.inc
+
+call mtr.add_suppression("Failed during slave.* thread initialization");
+
+set @@global.debug_dbug = @saved_dbug;
+
+######################################################################
+# Injecting faults in the init_slave option
+######################################################################
+connection slave;
+
+reset slave;
+
+SET GLOBAL init_slave= "garbage";
+
+start slave;
+# 1064 = ER_PARSE_ERROR
+--let $slave_sql_errno= 1064
+--let $show_slave_sql_error= 1
+--source include/wait_for_slave_sql_error.inc
+
+######################################################################
+# Clean up
+######################################################################
+SET GLOBAL init_slave= "";
+
+# Clean up Last_SQL_Error
+--source include/stop_slave_io.inc
+RESET SLAVE;
+--let $rpl_only_running_threads= 1
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_innodb-master.opt b/mysql-test/suite/rpl/t/rpl_innodb-master.opt
new file mode 100644
index 00000000..e27ee9b2
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_innodb-master.opt
@@ -0,0 +1 @@
+--loose-innodb-autoinc-lock-mode=0
diff --git a/mysql-test/suite/rpl/t/rpl_innodb_bug28430-master.opt b/mysql-test/suite/rpl/t/rpl_innodb_bug28430-master.opt
new file mode 100644
index 00000000..e27ee9b2
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_innodb_bug28430-master.opt
@@ -0,0 +1 @@
+--loose-innodb-autoinc-lock-mode=0
diff --git a/mysql-test/suite/rpl/t/rpl_innodb_bug28430-slave.opt b/mysql-test/suite/rpl/t/rpl_innodb_bug28430-slave.opt
new file mode 100644
index 00000000..e27ee9b2
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_innodb_bug28430-slave.opt
@@ -0,0 +1 @@
+--loose-innodb-autoinc-lock-mode=0
diff --git a/mysql-test/suite/rpl/t/rpl_innodb_bug28430.test b/mysql-test/suite/rpl/t/rpl_innodb_bug28430.test
new file mode 100644
index 00000000..0b8fb751
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_innodb_bug28430.test
@@ -0,0 +1,163 @@
+--source include/big_test.inc
+--source include/have_innodb.inc
+--source include/have_partition.inc
+--source include/have_binlog_format_mixed_or_row.inc
+--source include/master-slave.inc
+
+# Set the default connection to 'master'
+--enable_prepare_warnings
+--vertical_results
+
+let $engine_type= 'innodb';
+
+######## Creat Table Section #########
+use test;
+
+eval CREATE TABLE test.regular_tbl(id MEDIUMINT NOT NULL AUTO_INCREMENT,
+ dt TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON
+ UPDATE CURRENT_TIMESTAMP, user CHAR(255), uuidf LONGBLOB,
+ fkid MEDIUMINT, filler VARCHAR(255),
+ PRIMARY KEY(id)) ENGINE=$engine_type;
+
+eval CREATE TABLE test.bykey_tbl(id MEDIUMINT NOT NULL AUTO_INCREMENT,
+ dt TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE
+ CURRENT_TIMESTAMP, user CHAR(255), uuidf LONGBLOB,
+ fkid MEDIUMINT, filler VARCHAR(255),
+ PRIMARY KEY(id)) ENGINE=$engine_type
+ PARTITION BY KEY(id) partitions 5;
+
+eval CREATE TABLE test.byrange_tbl(id MEDIUMINT NOT NULL AUTO_INCREMENT,
+ dt TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE
+ CURRENT_TIMESTAMP, user CHAR(255), uuidf LONGBLOB,
+ fkid MEDIUMINT, filler VARCHAR(255),
+ PRIMARY KEY(id)) ENGINE=$engine_type
+ PARTITION BY RANGE(id)
+ SUBPARTITION BY hash(id) subpartitions 2
+ (PARTITION pa1 values less than (10),
+ PARTITION pa2 values less than (20),
+ PARTITION pa3 values less than (30),
+ PARTITION pa4 values less than (40),
+ PARTITION pa5 values less than (50),
+ PARTITION pa6 values less than (60),
+ PARTITION pa7 values less than (70),
+ PARTITION pa8 values less than (80),
+ PARTITION pa9 values less than (90),
+ PARTITION pa10 values less than (100),
+ PARTITION pa11 values less than MAXVALUE);
+
+######## Create SPs, Functions, Views and Triggers Section ##############
+
+delimiter |;
+CREATE PROCEDURE test.proc_norm()
+BEGIN
+ DECLARE ins_count INT DEFAULT 1000;
+ DECLARE del_count INT;
+ DECLARE cur_user VARCHAR(255);
+ DECLARE local_uuid VARCHAR(255);
+ DECLARE local_time TIMESTAMP;
+
+ SET local_time= NOW();
+ SET cur_user= CURRENT_USER();
+ SET local_uuid= UUID();
+
+ WHILE ins_count > 0 DO
+ INSERT INTO test.regular_tbl VALUES (NULL, NOW(), USER() , UUID(),
+ ins_count,'Going to test MBR for MySQL');
+ SET ins_count = ins_count - 1;
+ END WHILE;
+
+ SELECT MAX(id) FROM test.regular_tbl INTO del_count;
+ WHILE del_count > 0 DO
+ DELETE FROM test.regular_tbl WHERE id = del_count;
+ SET del_count = del_count - 2;
+ END WHILE;
+END|
+
+CREATE PROCEDURE test.proc_bykey()
+BEGIN
+ DECLARE ins_count INT DEFAULT 1000;
+ DECLARE del_count INT;
+ DECLARE cur_user VARCHAR(255);
+ DECLARE local_uuid VARCHAR(255);
+ DECLARE local_time TIMESTAMP;
+
+ SET local_time= NOW();
+ SET cur_user= CURRENT_USER();
+ SET local_uuid= UUID();
+
+ WHILE ins_count > 0 DO
+ INSERT INTO test.bykey_tbl VALUES (NULL, NOW(), USER() , UUID(),
+ ins_count,'Going to test MBR for MySQL');
+ SET ins_count = ins_count - 1;
+ END WHILE;
+
+ SELECT MAX(id) FROM test.bykey_tbl INTO del_count;
+ WHILE del_count > 0 DO
+ DELETE FROM test.bykey_tbl WHERE id = del_count;
+ SET del_count = del_count - 2;
+ END WHILE;
+END|
+
+CREATE PROCEDURE test.proc_byrange()
+BEGIN
+ DECLARE ins_count INT DEFAULT 1000;
+ DECLARE del_count INT;
+ DECLARE cur_user VARCHAR(255);
+ DECLARE local_uuid VARCHAR(255);
+ DECLARE local_time TIMESTAMP;
+
+ SET local_time= NOW();
+ SET cur_user = CURRENT_USER();
+ SET local_uuid=UUID();
+
+ WHILE ins_count > 0 DO
+ INSERT INTO test.byrange_tbl VALUES (NULL, NOW(), USER(), UUID(),
+ ins_count,'Going to test MBR for MySQL');
+ SET ins_count = ins_count - 1;
+ END WHILE;
+
+ SELECT MAX(id) FROM test.byrange_tbl INTO del_count;
+ WHILE del_count > 0 DO
+ DELETE FROM test.byrange_tbl WHERE id = del_count;
+ SET del_count = del_count - 2;
+ END WHILE;
+END|
+
+delimiter ;|
+
+############ Finish Setup Section ###################
+
+
+############ Test Section ###################
+
+begin;
+CALL test.proc_norm();
+commit;
+SELECT count(*) as "Master regular" FROM test.regular_tbl;
+begin;
+CALL test.proc_bykey();
+commit;
+SELECT count(*) as "Master bykey" FROM test.bykey_tbl;
+begin;
+CALL test.proc_byrange();
+commit;
+SELECT count(*) as "Master byrange" FROM test.byrange_tbl;
+
+--sync_slave_with_master
+connection slave;
+show create table test.byrange_tbl;
+SELECT count(*) "Slave norm" FROM test.regular_tbl;
+SELECT count(*) "Slave bykey" FROM test.bykey_tbl;
+SELECT count(*) "Slave byrange" FROM test.byrange_tbl;
+
+###### CLEAN UP SECTION ##############
+--disable_prepare_warnings
+connection master;
+DROP PROCEDURE test.proc_norm;
+DROP PROCEDURE test.proc_bykey;
+DROP PROCEDURE test.proc_byrange;
+DROP TABLE test.regular_tbl;
+DROP TABLE test.bykey_tbl;
+DROP TABLE test.byrange_tbl;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_innodb_bug30888.opt b/mysql-test/suite/rpl/t/rpl_innodb_bug30888.opt
new file mode 100644
index 00000000..e6685732
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_innodb_bug30888.opt
@@ -0,0 +1 @@
+--innodb-flush-log-at-trx-commit=2
diff --git a/mysql-test/suite/rpl/t/rpl_innodb_bug30888.test b/mysql-test/suite/rpl/t/rpl_innodb_bug30888.test
new file mode 100644
index 00000000..a18b0998
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_innodb_bug30888.test
@@ -0,0 +1,67 @@
+--source include/have_innodb.inc
+--source include/have_binlog_format_mixed_or_row.inc
+--source include/master-slave.inc
+
+# Set the default connection to 'master'
+
+--vertical_results
+
+#let $engine_type= 'myisam';
+let $engine_type= 'innodb';
+
+######## Creat Table Section #########
+use test;
+
+eval CREATE TABLE test.regular_tbl(id MEDIUMINT NOT NULL AUTO_INCREMENT,
+ dt TIMESTAMP, user CHAR(255), uuidf LONGBLOB,
+ fkid MEDIUMINT, filler VARCHAR(255),
+ PRIMARY KEY(id)) ENGINE=$engine_type;
+
+######## Create SPs, Functions, Views and Triggers Section ##############
+
+--enable_prepare_warnings
+delimiter |;
+CREATE PROCEDURE test.proc_norm()
+BEGIN
+ DECLARE ins_count INT DEFAULT 1000;
+ DECLARE del_count INT;
+ DECLARE cur_user VARCHAR(255);
+ DECLARE local_uuid VARCHAR(255);
+ DECLARE local_time TIMESTAMP;
+
+ SET local_time= NOW();
+ SET cur_user= CURRENT_USER();
+ SET local_uuid= UUID();
+
+ WHILE ins_count > 0 DO
+ INSERT INTO test.regular_tbl VALUES (NULL, NOW(), USER() , UUID(),
+ ins_count,'Going to test MBR for MySQL');
+ SET ins_count = ins_count - 1;
+ END WHILE;
+
+ SELECT MAX(id) FROM test.regular_tbl INTO del_count;
+ WHILE del_count > 0 DO
+ DELETE FROM test.regular_tbl WHERE id = del_count;
+ SET del_count = del_count - 2;
+ END WHILE;
+END|
+
+delimiter ;|
+--disable_prepare_warnings
+############ Finish Setup Section ###################
+
+
+############ Test Section ###################
+
+CALL test.proc_norm();
+
+--sync_slave_with_master
+
+###### CLEAN UP SECTION ##############
+
+connection master;
+DROP PROCEDURE test.proc_norm;
+DROP TABLE test.regular_tbl;
+
+--source include/rpl_end.inc
+
diff --git a/mysql-test/suite/rpl/t/rpl_innodb_mixed_ddl.test b/mysql-test/suite/rpl/t/rpl_innodb_mixed_ddl.test
new file mode 100644
index 00000000..5147e67c
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_innodb_mixed_ddl.test
@@ -0,0 +1,9 @@
+#########################################
+# Purpose: testing the replication in mixed mode
+# Requirements: define binlog format for mysqld as in example below:
+# ./mysql-test-run.pl --mysqld=--binlog-format=mixed
+#########################################
+--source include/have_binlog_format_mixed.inc
+--source include/have_innodb.inc
+let $engine_type= innodb;
+--source suite/rpl/include/rpl_mixed_ddl.inc
diff --git a/mysql-test/suite/rpl/t/rpl_innodb_mixed_dml.test b/mysql-test/suite/rpl/t/rpl_innodb_mixed_dml.test
new file mode 100644
index 00000000..d04ced0f
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_innodb_mixed_dml.test
@@ -0,0 +1,9 @@
+#########################################
+# Purpose: testing the replication in mixed mode
+# Requirements: define binlog format for mysqld as in example below:
+# ./mysql-test-run.pl --mysqld=--binlog-format=mixed
+#########################################
+--source include/have_binlog_format_mixed.inc
+--source include/have_innodb.inc
+let $engine_type= innodb;
+--source suite/rpl/include/rpl_mixed_dml.inc
diff --git a/mysql-test/suite/rpl/t/rpl_insert.test b/mysql-test/suite/rpl/t/rpl_insert.test
new file mode 100644
index 00000000..48814508
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_insert.test
@@ -0,0 +1,45 @@
+--echo #
+--echo # Bug#20821: INSERT DELAYED fails to write some rows to binlog
+--echo #
+
+--source include/not_embedded.inc
+--source include/not_windows.inc
+--source include/master-slave.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_warnings
+CREATE SCHEMA IF NOT EXISTS mysqlslap;
+USE mysqlslap;
+--enable_warnings
+
+CREATE TABLE t1 (id INT, name VARCHAR(64)) ENGINE=MyISAM;
+
+sync_slave_with_master;
+connection master;
+
+let $query = "INSERT DELAYED INTO t1 VALUES (1, 'Dr. No'), (2, 'From Russia With Love'), (3, 'Goldfinger'), (4, 'Thunderball'), (5, 'You Only Live Twice')";
+--exec $MYSQL_SLAP --silent --concurrency=5 --iterations=200 --query=$query --delimiter=";"
+
+# Wait until all the 5000 inserts has been inserted into the table
+let $wait_condition= SELECT COUNT(*) = 5000 FROM mysqlslap.t1;
+source include/wait_condition.inc;
+SELECT COUNT(*) FROM mysqlslap.t1;
+
+connection slave;
+# Wait until all the 5000 inserts has been inserted into the table
+let $wait_condition= SELECT COUNT(*) = 5000 FROM mysqlslap.t1;
+source include/wait_condition.inc;
+SELECT COUNT(*) FROM mysqlslap.t1;
+
+--echo #
+--echo # Cleanup
+--echo #
+
+connection master;
+USE test;
+DROP SCHEMA mysqlslap;
+sync_slave_with_master;
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_insert_delayed.test b/mysql-test/suite/rpl/t/rpl_insert_delayed.test
new file mode 100644
index 00000000..6a88899f
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_insert_delayed.test
@@ -0,0 +1,5 @@
+--source include/not_embedded.inc
+--source include/not_windows.inc
+--source include/master-slave.inc
+--source include/rpl_insert_delayed.test
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_insert_id.test b/mysql-test/suite/rpl/t/rpl_insert_id.test
new file mode 100644
index 00000000..c9d84049
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_insert_id.test
@@ -0,0 +1,6 @@
+#################################
+# Wrapper for rpl_insert_id.test#
+#################################
+-- source include/have_innodb.inc
+let $engine_type=myisam;
+-- source include/rpl_insert_id.test
diff --git a/mysql-test/suite/rpl/t/rpl_insert_id_pk.test b/mysql-test/suite/rpl/t/rpl_insert_id_pk.test
new file mode 100644
index 00000000..d9ba2a2b
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_insert_id_pk.test
@@ -0,0 +1,6 @@
+#################################
+# Wrapper for rpl_insert_id.test#
+#################################
+-- source include/have_innodb.inc
+let $engine_type=innodb;
+-- source include/rpl_insert_id_pk.test
diff --git a/mysql-test/suite/rpl/t/rpl_insert_ignore.test b/mysql-test/suite/rpl/t/rpl_insert_ignore.test
new file mode 100644
index 00000000..2940ad16
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_insert_ignore.test
@@ -0,0 +1,15 @@
+#####################################
+# Wrapper for rpl_insert_ignore.test#
+#####################################
+-- source include/have_innodb.inc
+-- source include/master-slave.inc
+
+call mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT");
+
+-- let $engine_type=innodb
+-- source include/rpl_insert_ignore.test
+
+-- let $engine_type=myisam
+-- source include/rpl_insert_ignore.test
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_invoked_features-master.opt b/mysql-test/suite/rpl/t/rpl_invoked_features-master.opt
new file mode 100644
index 00000000..96f0ce3f
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_invoked_features-master.opt
@@ -0,0 +1 @@
+--default-storage-engine=MyISAM
diff --git a/mysql-test/suite/rpl/t/rpl_invoked_features.test b/mysql-test/suite/rpl/t/rpl_invoked_features.test
new file mode 100644
index 00000000..91391cf8
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_invoked_features.test
@@ -0,0 +1,311 @@
+#########################################
+# Author: Serge Kozlov skozlov@mysql.com
+# Date: 04/25/2007
+# Purpose: Testing Invocation and Invoked
+# Features for Replication.
+#########################################
+
+--source include/have_innodb.inc
+--source include/master-slave.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_warnings/--enable_warnings added before/after query
+# if one uses UUID() function because we need to avoid warnings
+# for STATEMENT binlog format
+
+# Non-transactional engine
+--let $engine_type= myisam
+
+# Transactional engine
+--let $engine_type2= innodb
+
+
+#
+# Clean up
+#
+
+USE test;
+--disable_warnings
+DROP VIEW IF EXISTS v1,v11;
+DROP TABLE IF EXISTS t1,t2,t3,t11,t12,t13;
+DROP PROCEDURE IF EXISTS p1;
+DROP PROCEDURE IF EXISTS p11;
+DROP FUNCTION IF EXISTS f1;
+DROP FUNCTION IF EXISTS f2;
+DROP EVENT IF EXISTS e1;
+DROP EVENT IF EXISTS e11;
+--enable_warnings
+
+
+#
+# Prepare objects (tables etc)
+#
+
+# Create tables
+
+--echo
+eval CREATE TABLE t1 (a INT NOT NULL PRIMARY KEY, b INT, c VARCHAR(64)) ENGINE=$engine_type;
+INSERT INTO t1 VALUES (1,1,'1');
+--disable_warnings
+INSERT INTO t1 VALUES (2,2,UUID());
+--enable_warnings
+eval CREATE TABLE t2 (a INT UNIQUE, b INT, c VARCHAR(64)) ENGINE=$engine_type;
+INSERT INTO t2 VALUES (1,1,'1');
+--disable_warnings
+INSERT INTO t2 VALUES (2,2,UUID());
+--enable_warnings
+
+eval CREATE TABLE t11 (a INT NOT NULL PRIMARY KEY, b INT, c VARCHAR(64)) ENGINE=$engine_type2;
+INSERT INTO t11 VALUES (1,1,'1');
+--disable_warnings
+INSERT INTO t11 VALUES (2,2,UUID());
+--enable_warnings
+eval CREATE TABLE t12 (a INT UNIQUE, b INT, c VARCHAR(64)) ENGINE=$engine_type2;
+INSERT INTO t12 VALUES (1,1,'1');
+--disable_warnings
+INSERT INTO t12 VALUES (2,2,UUID());
+--enable_warnings
+
+# Create invoked features
+--echo
+# Create view for tables t1,t11
+CREATE VIEW v1 AS SELECT * FROM t1;
+CREATE VIEW v11 AS SELECT * FROM t11;
+
+# Create triggers for t1,t11
+DELIMITER |;
+
+CREATE TRIGGER t1_tr1 BEFORE INSERT ON t1 FOR EACH ROW
+BEGIN
+ INSERT INTO t2 VALUES (NEW.a, NEW.b, NEW.c);
+ INSERT INTO t3 VALUES (NEW.a, NEW.b, NEW.c);
+END|
+
+CREATE TRIGGER t1_tr2 BEFORE UPDATE ON t1 FOR EACH ROW
+BEGIN
+ UPDATE t2 SET c = '';
+ UPDATE t3 SET c = '';
+END|
+
+CREATE TRIGGER t11_tr1 BEFORE INSERT ON t11 FOR EACH ROW
+BEGIN
+ INSERT INTO t12 VALUES (NEW.a, NEW.b, NEW.c);
+ INSERT INTO t13 VALUES (NEW.a, NEW.b, NEW.c);
+END|
+
+CREATE TRIGGER t11_tr2 BEFORE UPDATE ON t11 FOR EACH ROW
+BEGIN
+ UPDATE t12 SET c = '';
+ UPDATE t13 SET c = '';
+END|
+
+# Create events which will run every 1 sec
+CREATE EVENT e1 ON SCHEDULE EVERY 1 SECOND DISABLE DO
+BEGIN
+ ALTER EVENT e1 DISABLE;
+ CALL p1(10, '');
+END|
+
+CREATE EVENT e11 ON SCHEDULE EVERY 1 SECOND DISABLE DO
+BEGIN
+ ALTER EVENT e11 DISABLE;
+ CALL p11(10, '');
+END|
+
+# Create functions and procedures used for events
+CREATE FUNCTION f1 (x INT) RETURNS VARCHAR(64)
+BEGIN
+ IF x > 5 THEN
+ RETURN UUID();
+ END IF;
+ RETURN '';
+END|
+
+CREATE FUNCTION f2 (x INT) RETURNS VARCHAR(64)
+BEGIN
+ RETURN f1(x);
+END|
+
+CREATE PROCEDURE p1 (IN x INT, IN y VARCHAR(64))
+BEGIN
+ INSERT IGNORE INTO t1 VALUES (x,x,y);
+END|
+
+CREATE PROCEDURE p11 (IN x INT, IN y VARCHAR(64))
+BEGIN
+ INSERT IGNORE INTO t11 VALUES (x,x,y);
+END|
+
+DELIMITER ;|
+
+
+#
+# Start test case
+#
+
+# Do some actions for non-transactional tables
+--echo
+CREATE TABLE t3 SELECT * FROM v1;
+INSERT INTO t1 VALUES (3,3,'');
+UPDATE t1 SET c='2' WHERE a = 1;
+--disable_warnings
+INSERT INTO t1 VALUES(4,4,f1(4));
+--enable_warnings
+INSERT INTO t1 VALUES (100,100,'');
+--disable_warnings
+CALL p1(5, UUID());
+--enable_warnings
+INSERT INTO t1 VALUES (101,101,'');
+--disable_warnings
+INSERT INTO t1 VALUES(6,6,f1(6));
+--enable_warnings
+INSERT INTO t1 VALUES (102,102,'');
+--disable_warnings
+INSERT INTO t1 VALUES(7,7,f2(7));
+--enable_warnings
+INSERT INTO t1 VALUES (103,103,'');
+
+# Do some actions for transactional tables
+--echo
+--disable_warnings
+CREATE TABLE t13 SELECT * FROM v11;
+INSERT INTO t11 VALUES (3,3,'');
+UPDATE t11 SET c='2' WHERE a = 1;
+INSERT INTO t11 VALUES(4,4,f1(4));
+INSERT INTO t11 VALUES (100,100,'');
+CALL p11(5, UUID());
+INSERT INTO t11 VALUES (101,101,'');
+INSERT INTO t11 VALUES(6,6,f1(6));
+INSERT INTO t11 VALUES (102,102,'');
+INSERT INTO t11 VALUES(7,7,f2(7));
+INSERT INTO t11 VALUES (103,103,'');
+--enable_warnings
+
+# Scheduler is on
+--echo
+# Temporally events fire sequentally due Bug#29020.
+SET GLOBAL EVENT_SCHEDULER = on;
+# Wait while events will executed
+ALTER EVENT e1 ENABLE;
+let $wait_condition= SELECT COUNT(*) = 1 FROM t1 WHERE t1.a = 10;
+--source include/wait_condition.inc
+ALTER EVENT e11 ENABLE;
+let $wait_condition= SELECT COUNT(*) = 1 FROM t11 WHERE t11.a = 10;
+--source include/wait_condition.inc
+SET GLOBAL EVENT_SCHEDULER = off;
+
+# Check original objects
+--echo
+--sorted_result
+SHOW TABLES LIKE 't%';
+--sorted_result
+SELECT table_name FROM information_schema.views WHERE table_schema='test';
+--sorted_result
+SELECT trigger_name, event_manipulation, event_object_table FROM information_schema.triggers WHERE trigger_schema='test';
+--sorted_result
+SELECT routine_type, routine_name FROM information_schema.routines WHERE routine_schema='test';
+--sorted_result
+SELECT event_name, status FROM information_schema.events WHERE event_schema='test';
+
+# Check original data
+--echo
+SELECT COUNT(*) FROM t1;
+SELECT a,b FROM t1 ORDER BY a;
+SELECT COUNT(*) FROM t2;
+SELECT a,b FROM t2 ORDER BY a;
+SELECT COUNT(*) FROM t3;
+SELECT a,b FROM t3 ORDER BY a;
+SELECT a,b FROM v1 ORDER BY a;
+SELECT COUNT(*) FROM t11;
+SELECT a,b FROM t11 ORDER BY a;
+SELECT COUNT(*) FROM t12;
+SELECT a,b FROM t12 ORDER BY a;
+SELECT COUNT(*) FROM t13;
+SELECT a,b FROM t13 ORDER BY a;
+SELECT a,b FROM v11 ORDER BY a;
+
+--sync_slave_with_master slave
+
+# Check replicated objects
+--echo
+--sorted_result
+SHOW TABLES LIKE 't%';
+--sorted_result
+SELECT table_name FROM information_schema.views WHERE table_schema='test';
+--sorted_result
+SELECT trigger_name, event_manipulation, event_object_table FROM information_schema.triggers WHERE trigger_schema='test';
+--sorted_result
+SELECT routine_type, routine_name FROM information_schema.routines WHERE routine_schema='test';
+--sorted_result
+SELECT event_name, status FROM information_schema.events WHERE event_schema='test';
+
+# Check replicated data
+--echo
+SELECT COUNT(*) FROM t1;
+SELECT a,b FROM t1 ORDER BY a;
+SELECT COUNT(*) FROM t2;
+SELECT a,b FROM t2 ORDER BY a;
+SELECT COUNT(*) FROM t3;
+SELECT a,b FROM t3 ORDER BY a;
+SELECT a,b FROM v1 ORDER BY a;
+SELECT COUNT(*) FROM t11;
+SELECT a,b FROM t11 ORDER BY a;
+SELECT COUNT(*) FROM t12;
+SELECT a,b FROM t12 ORDER BY a;
+SELECT COUNT(*) FROM t13;
+SELECT a,b FROM t13 ORDER BY a;
+SELECT a,b FROM v11 ORDER BY a;
+
+# Remove UUID() before comparing and sort tables
+
+--connection master
+--echo
+UPDATE t1 SET c='';
+UPDATE t2 SET c='';
+UPDATE t3 SET c='';
+--disable_warnings
+UPDATE t11 SET c='';
+--enable_warnings
+UPDATE t12 SET c='';
+UPDATE t13 SET c='';
+
+ALTER TABLE t3 ORDER BY a;
+ALTER TABLE t13 ORDER BY a;
+
+--sync_slave_with_master slave
+
+# Compare a data from master and slave
+--echo
+--exec $MYSQL_DUMP --compact --order-by-primary --skip-extended-insert --no-create-info test > $MYSQLTEST_VARDIR/tmp/rpl_invoked_features_master.sql
+--exec $MYSQL_DUMP_SLAVE --compact --order-by-primary --skip-extended-insert --no-create-info test > $MYSQLTEST_VARDIR/tmp/rpl_invoked_features_slave.sql
+--diff_files $MYSQLTEST_VARDIR/tmp/rpl_invoked_features_master.sql $MYSQLTEST_VARDIR/tmp/rpl_invoked_features_slave.sql
+
+
+#
+# Clean up
+#
+
+# Remove dumps
+--echo
+--remove_file $MYSQLTEST_VARDIR/tmp/rpl_invoked_features_master.sql
+--remove_file $MYSQLTEST_VARDIR/tmp/rpl_invoked_features_slave.sql
+
+# Remove tables,views,procedures,functions
+--connection master
+--echo
+DROP VIEW IF EXISTS v1,v11;
+DROP TABLE IF EXISTS t1,t2,t3,t11,t12,t13;
+DROP PROCEDURE IF EXISTS p1;
+DROP PROCEDURE IF EXISTS p11;
+DROP FUNCTION IF EXISTS f1;
+DROP FUNCTION IF EXISTS f2;
+DROP EVENT IF EXISTS e1;
+DROP EVENT IF EXISTS e11;
+
+--sync_slave_with_master slave
+
+# End 5.1 test case
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_iodku.test b/mysql-test/suite/rpl/t/rpl_iodku.test
new file mode 100644
index 00000000..815b927c
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_iodku.test
@@ -0,0 +1,50 @@
+--source include/have_innodb.inc
+--source include/master-slave.inc
+
+if (`select @@binlog_format = "statement"`)
+{
+ call mtr.add_suppression("Unsafe statement written to the binary log using statement");
+}
+
+## MDEV-28310 loss of binlog event for multi-record IODKU
+# Check that the duplicate key error does not cause
+# loss of replication event for IODKU that specifies values
+# for at least two unique columns per record.
+# "Implicit" NULL value of the auto-increment column also counts.
+
+CREATE TABLE t1 (id INT PRIMARY KEY AUTO_INCREMENT, a INT, b INT, c INT,
+ UNIQUE (a), UNIQUE (b)) ENGINE=innodb;
+INSERT INTO t1 (`a`,`c`) VALUES (1,1), (2,1) ON DUPLICATE KEY UPDATE c = 1;
+--echo # UNSAFE
+# because of two keys involved: a UK and PK even though implicitly via auto-inc
+INSERT INTO t1 (`a`,`c`) VALUES (3, 1),(2,1), (1,1) ON DUPLICATE KEY UPDATE c = a * 10 + VALUES(c);
+SELECT * from t1;
+
+--sync_slave_with_master
+--let $diff_tables = master:t1,slave:t1
+--source include/diff_tables.inc
+
+## MDEV-21810 MBR: Unexpected "Unsafe statement" warning for unsafe IODKU
+# Unnecessary unsafe statement warning is not error-logged anymore.
+
+
+--connection master
+CREATE OR REPLACE TABLE t1 (a INT, b INT, c INT, UNIQUE (a), UNIQUE (b)) ENGINE=innodb;
+INSERT INTO t1 VALUES (1,10,1);
+--echo # eligable for the statement format run unsafe warning
+INSERT INTO t1 VALUES (2,20,2) ON DUPLICATE KEY UPDATE c = 100;
+--echo # not eligable: no warning in the statement format run
+INSERT INTO t1 (`a`,`c`) VALUES (3, 1) ON DUPLICATE KEY UPDATE c = 99;
+SELECT * from t1;
+
+--sync_slave_with_master
+--let $diff_tables = master:t1,slave:t1
+--source include/diff_tables.inc
+
+# Cleanup
+--connection master
+DROP TABLE t1;
+--sync_slave_with_master
+
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_ip_mix.cnf b/mysql-test/suite/rpl/t/rpl_ip_mix.cnf
new file mode 100644
index 00000000..00e2637d
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_ip_mix.cnf
@@ -0,0 +1,56 @@
+# Use default setting for mysqld processes
+!include include/default_mysqld.cnf
+!include include/default_client.cnf
+
+[mysqld.1]
+
+# Run the master.sh script before starting this process
+#!run-master-sh
+
+log-bin= master-bin
+
+loose-innodb
+
+skip-name-resolve
+bind-address= ::
+
+
+[mysqld.2]
+# Run the slave.sh script before starting this process
+#!run-slave-sh
+
+# Append <testname>-slave.opt file to the list of argument used when
+# starting the mysqld
+#!use-slave-opt
+
+log-bin= slave-bin
+relay-log= slave-relay-bin
+
+init-rpl-role= slave
+log-slave-updates
+master-retry-count= 10
+
+# Values reported by slave when it connect to master
+# and shows up in SHOW SLAVE STATUS;
+report-host= localhost
+report-port= @mysqld.2.port
+report-user= root
+
+skip-slave-start
+skip-name-resolve
+bind-address= 0.0.0.0
+
+# Directory where slaves find the dumps generated by "load data"
+# on the server. The path need to have constant length otherwise
+# test results will vary, thus a relative path is used.
+slave-load-tmpdir= ../../tmp
+
+loose-innodb
+
+[ENV]
+MASTER_MYPORT= @mysqld.1.port
+MASTER_MYSOCK= @mysqld.1.socket
+
+SLAVE_MYPORT= @mysqld.2.port
+SLAVE_MYSOCK= @mysqld.2.socket
+
diff --git a/mysql-test/suite/rpl/t/rpl_ip_mix.test b/mysql-test/suite/rpl/t/rpl_ip_mix.test
new file mode 100644
index 00000000..63c5fa92
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_ip_mix.test
@@ -0,0 +1,48 @@
+# Test of ipv6 format, especially "change master host=..."
+# Options: --skip-name-resolve, master: --bind-address=::, slave: --bind-address=0.0.0.0
+# (see corresponding cnf file)
+#
+--source include/check_ipv6.inc
+--source include/have_log_bin.inc
+
+let $IPv6= ::1;
+--echo #################### IP: $IPv6 ###########################
+--source include/rpl_ip_mix.inc
+
+let $IPv6= ::1/128;
+#--echo #################### IP: $IPv6 ###########################
+#--source include/rpl_ip_mix.inc
+
+let $IPv6= 0000:0000:0000:0000:0000:0000:0000:0001;
+--echo #################### IP: $IPv6 ###########################
+--source include/rpl_ip_mix.inc
+
+let $IPv6= 0:0:0:0:0:0:0:1;
+--echo #################### IP: $IPv6 ###########################
+--source include/rpl_ip_mix.inc
+
+let $IPv6= ::1;
+--echo #################### IP: $IPv6 mix #######################
+connect (master,$IPv6,root,,test,$MASTER_MYPORT);
+connect (slave,127.0.0.1,root,,test,$SLAVE_MYPORT);
+connection master;
+reset master;
+source include/show_master_status.inc;
+connection slave;
+reset slave;
+let $master_host= query_get_value(SHOW SLAVE STATUS, Master_Host, 1);
+--echo Master-Host: $master_host
+eval change master to master_host='$IPv6';
+let $master_host= query_get_value(SHOW SLAVE STATUS, Master_Host, 1);
+--echo Master-Host: $master_host
+eval change master to master_host='127.0.0.1';
+let $master_host= query_get_value(SHOW SLAVE STATUS, Master_Host, 1);
+--echo Master-Host: $master_host
+eval change master to master_host='0:0:0:0:0:0:0:1';
+let $master_host= query_get_value(SHOW SLAVE STATUS, Master_Host, 1);
+--echo Master-Host: $master_host
+
+# clean up
+CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_USER='root';
+--connection slave
+reset slave all;
diff --git a/mysql-test/suite/rpl/t/rpl_ip_mix2.cnf b/mysql-test/suite/rpl/t/rpl_ip_mix2.cnf
new file mode 100644
index 00000000..306df437
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_ip_mix2.cnf
@@ -0,0 +1,56 @@
+# Use default setting for mysqld processes
+!include include/default_mysqld.cnf
+!include include/default_client.cnf
+
+[mysqld.1]
+
+# Run the master.sh script before starting this process
+#!run-master-sh
+
+log-bin= master-bin
+
+loose-innodb
+
+skip-name-resolve
+bind-address= 0.0.0.0
+
+
+[mysqld.2]
+# Run the slave.sh script before starting this process
+#!run-slave-sh
+
+# Append <testname>-slave.opt file to the list of argument used when
+# starting the mysqld
+#!use-slave-opt
+
+log-bin= slave-bin
+relay-log= slave-relay-bin
+
+init-rpl-role= slave
+log-slave-updates
+master-retry-count= 10
+
+# Values reported by slave when it connect to master
+# and shows up in SHOW SLAVE STATUS;
+report-host= localhost
+report-port= @mysqld.2.port
+report-user= root
+
+skip-slave-start
+skip-name-resolve
+bind-address= ::
+
+# Directory where slaves find the dumps generated by "load data"
+# on the server. The path need to have constant length otherwise
+# test results will vary, thus a relative path is used.
+slave-load-tmpdir= ../../tmp
+
+loose-innodb
+
+[ENV]
+MASTER_MYPORT= @mysqld.1.port
+MASTER_MYSOCK= @mysqld.1.socket
+
+SLAVE_MYPORT= @mysqld.2.port
+SLAVE_MYSOCK= @mysqld.2.socket
+
diff --git a/mysql-test/suite/rpl/t/rpl_ip_mix2.test b/mysql-test/suite/rpl/t/rpl_ip_mix2.test
new file mode 100644
index 00000000..3fff54e5
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_ip_mix2.test
@@ -0,0 +1,49 @@
+# Test of ipv6 format, especially "change master host=..."
+# Options: --skip-name-resolve, master: --bind-address=0.0.0.0, slave: --bind-address=::
+# (see corresponding cnf file)
+#
+--source include/check_ipv6.inc
+--source include/have_log_bin.inc
+
+let $IPv6= ::1;
+--echo #################### IP: $IPv6 ###########################
+--source include/rpl_ip_mix2.inc
+
+let $IPv6= ::1/128;
+#--echo #################### IP: $IPv6 ###########################
+#--source include/rpl_ip_mix2.inc
+
+let $IPv6= 0000:0000:0000:0000:0000:0000:0000:0001;
+--echo #################### IP: $IPv6 ###########################
+--source include/rpl_ip_mix2.inc
+
+let $IPv6= 0:0:0:0:0:0:0:1;
+--echo #################### IP: $IPv6 ###########################
+--source include/rpl_ip_mix2.inc
+
+let $IPv6= ::1;
+--echo #################### IP: $IPv6 mix #######################
+connect (master,127.0.0.1,root,,test,$MASTER_MYPORT);
+connect (slave,$IPv6,root,,test,$SLAVE_MYPORT);
+connection master;
+reset master;
+source include/show_master_status.inc;
+save_master_pos;
+connection slave;
+reset slave;
+let $master_host= query_get_value(SHOW SLAVE STATUS, Master_Host, 1);
+--echo Master-Host: $master_host
+eval change master to master_host='$IPv6';
+let $master_host= query_get_value(SHOW SLAVE STATUS, Master_Host, 1);
+--echo Master-Host: $master_host
+eval change master to master_host='127.0.0.1';
+let $master_host= query_get_value(SHOW SLAVE STATUS, Master_Host, 1);
+--echo Master-Host: $master_host
+eval change master to master_host='0:0:0:0:0:0:0:1';
+let $master_host= query_get_value(SHOW SLAVE STATUS, Master_Host, 1);
+--echo Master-Host: $master_host
+
+# clean up
+CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_USER='root';
+connection slave;
+reset slave all;
diff --git a/mysql-test/suite/rpl/t/rpl_ipv4_as_ipv6.cnf b/mysql-test/suite/rpl/t/rpl_ipv4_as_ipv6.cnf
new file mode 100644
index 00000000..b646a408
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_ipv4_as_ipv6.cnf
@@ -0,0 +1,56 @@
+# Use default setting for mysqld processes
+!include include/default_mysqld.cnf
+!include include/default_client.cnf
+
+[mysqld.1]
+
+# Run the master.sh script before starting this process
+#!run-master-sh
+
+log-bin= master-bin
+
+loose-innodb
+
+skip-name-resolve
+bind-address= 0.0.0.0
+
+
+[mysqld.2]
+# Run the slave.sh script before starting this process
+#!run-slave-sh
+
+# Append <testname>-slave.opt file to the list of argument used when
+# starting the mysqld
+#!use-slave-opt
+
+log-bin= slave-bin
+relay-log= slave-relay-bin
+
+init-rpl-role= slave
+log-slave-updates
+master-retry-count= 10
+
+# Values reported by slave when it connect to master
+# and shows up in SHOW SLAVE STATUS;
+report-host= localhost
+report-port= @mysqld.2.port
+report-user= root
+
+skip-slave-start
+skip-name-resolve
+bind-address= 0.0.0.0
+
+# Directory where slaves find the dumps generated by "load data"
+# on the server. The path need to have constant length otherwise
+# test results will vary, thus a relative path is used.
+slave-load-tmpdir= ../../tmp
+
+loose-innodb
+
+[ENV]
+MASTER_MYPORT= @mysqld.1.port
+MASTER_MYSOCK= @mysqld.1.socket
+
+SLAVE_MYPORT= @mysqld.2.port
+SLAVE_MYSOCK= @mysqld.2.socket
+
diff --git a/mysql-test/suite/rpl/t/rpl_ipv4_as_ipv6.test b/mysql-test/suite/rpl/t/rpl_ipv4_as_ipv6.test
new file mode 100644
index 00000000..d17b32c3
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_ipv4_as_ipv6.test
@@ -0,0 +1,63 @@
+# Test of ipv4 (127.0.0.1) in ipv6 format, especially "change master host=..."
+# Options: --skip-name-resolve, --bind-address=0.0.0.0 (see corresponding cnf file)
+# for master and slave
+#
+--source include/have_ipv4_mapped.inc
+--source include/have_log_bin.inc
+
+let $IPv6= 127.0.0.1;
+--echo #################### IP: $IPv6 ###########################
+--source include/rpl_ipv6.inc
+
+let $IPv6= 0:0:0:0:0:FFFF:127.0.0.1;
+--echo #################### IP: $IPv6 ###########################
+--source include/rpl_ipv6.inc
+
+let $IPv6= 0000:0000:0000:0000:0000:FFFF:127.0.0.1;
+--echo #################### IP: $IPv6 ###########################
+--source include/rpl_ipv6.inc
+
+let $IPv6= 0:0000:0000:0:0000:FFFF:127.0.0.1;
+--echo #################### IP: $IPv6 ###########################
+--source include/rpl_ipv6.inc
+
+let $IPv6= 0::0000:FFFF:127.0.0.1;
+--echo #################### IP: $IPv6 ###########################
+--source include/rpl_ipv6.inc
+
+#let $IPv6= 0:0:0:0:0:FFFF:127.0.0.1/96;
+#--echo #################### IP: $IPv6 ###########################
+#--source include/rpl_ipv6.inc
+
+let $IPv6= ::FFFF:127.0.0.1;
+--echo #################### IP: $IPv6 ###########################
+--source include/rpl_ipv6.inc
+
+#let $IPv6= ::FFFF:127.0.0.1/96;
+#--echo #################### IP: $IPv6 ###########################
+#--source include/rpl_ipv6.inc
+
+let $IPv6= ::FFFF:127.0.0.1;
+--echo #################### IP: $IPv6 ###########################
+connect (master,127.0.0.1,root,,test,$MASTER_MYPORT);
+connect (slave,127.0.0.1,root,,test,$SLAVE_MYPORT);
+connection master;
+reset master;
+source include/show_master_status.inc;
+save_master_pos;
+connection slave;
+reset slave;
+let $master_host= query_get_value(SHOW SLAVE STATUS, Master_Host, 1);
+--echo Master-Host: $master_host
+eval change master to master_host='$IPv6';
+let $master_host= query_get_value(SHOW SLAVE STATUS, Master_Host, 1);
+--echo Master-Host: $master_host
+eval change master to master_host='127.0.0.1';
+let $master_host= query_get_value(SHOW SLAVE STATUS, Master_Host, 1);
+--echo Master-Host: $master_host
+eval change master to master_host='0:0000:0000:0:0000:FFFF:127.0.0.1';
+let $master_host= query_get_value(SHOW SLAVE STATUS, Master_Host, 1);
+--echo Master-Host: $master_host
+
+# clean up
+CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_USER='root';
diff --git a/mysql-test/suite/rpl/t/rpl_ipv6.cnf b/mysql-test/suite/rpl/t/rpl_ipv6.cnf
new file mode 100644
index 00000000..6bf97a94
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_ipv6.cnf
@@ -0,0 +1,56 @@
+# Use default setting for mysqld processes
+!include include/default_mysqld.cnf
+!include include/default_client.cnf
+
+[mysqld.1]
+
+# Run the master.sh script before starting this process
+#!run-master-sh
+
+log-bin= master-bin
+
+loose-innodb
+
+skip-name-resolve
+bind-address= *
+
+
+[mysqld.2]
+# Run the slave.sh script before starting this process
+#!run-slave-sh
+
+# Append <testname>-slave.opt file to the list of argument used when
+# starting the mysqld
+#!use-slave-opt
+
+log-bin= slave-bin
+relay-log= slave-relay-bin
+
+init-rpl-role= slave
+log-slave-updates
+master-retry-count= 10
+
+# Values reported by slave when it connect to master
+# and shows up in SHOW SLAVE STATUS;
+report-host= localhost
+report-port= @mysqld.2.port
+report-user= root
+
+skip-slave-start
+skip-name-resolve
+bind-address= *
+
+# Directory where slaves find the dumps generated by "load data"
+# on the server. The path need to have constant length otherwise
+# test results will vary, thus a relative path is used.
+slave-load-tmpdir= ../../tmp
+
+loose-innodb
+
+[ENV]
+MASTER_MYPORT= @mysqld.1.port
+MASTER_MYSOCK= @mysqld.1.socket
+
+SLAVE_MYPORT= @mysqld.2.port
+SLAVE_MYSOCK= @mysqld.2.socket
+
diff --git a/mysql-test/suite/rpl/t/rpl_ipv6.test b/mysql-test/suite/rpl/t/rpl_ipv6.test
new file mode 100644
index 00000000..f3795832
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_ipv6.test
@@ -0,0 +1,49 @@
+# Test of ipv6 format, especially "change master host=..."
+# Options: --skip-name-resolve, --bind-address=:: (see corresponding cnf file)
+# for master and slave.
+#
+--source include/check_ipv6.inc
+# Can't be tested with windows due to mixed format like 0::0000:FFFF:127.0.0.1
+--source include/not_windows.inc
+--source include/have_log_bin.inc
+
+let $IPv6= ::1;
+--echo #################### IP: $IPv6 ###########################
+--source include/rpl_ipv6.inc
+
+let $IPv6= ::1/128;
+#--echo #################### IP: $IPv6 ###########################
+#--source include/rpl_ipv6.inc
+
+let $IPv6= 0000:0000:0000:0000:0000:0000:0000:0001;
+--echo #################### IP: $IPv6 ###########################
+--source include/rpl_ipv6.inc
+
+let $IPv6= 0:0:0:0:0:0:0:1;
+--echo #################### IP: $IPv6 ###########################
+--source include/rpl_ipv6.inc
+
+let $IPv6= ::1;
+--echo #################### IP: $IPv6 mix #######################
+connect (master,127.0.0.1,root,,test,$MASTER_MYPORT);
+connect (slave,127.0.0.1,root,,test,$SLAVE_MYPORT);
+connection master;
+reset master;
+source include/show_master_status.inc;
+save_master_pos;
+connection slave;
+reset slave;
+let $master_host= query_get_value(SHOW SLAVE STATUS, Master_Host, 1);
+--echo Master-Host: $master_host
+eval change master to master_host='$IPv6';
+let $master_host= query_get_value(SHOW SLAVE STATUS, Master_Host, 1);
+--echo Master-Host: $master_host
+eval change master to master_host='127.0.0.1';
+let $master_host= query_get_value(SHOW SLAVE STATUS, Master_Host, 1);
+--echo Master-Host: $master_host
+eval change master to master_host='0:0:0:0:0:0:0:1';
+let $master_host= query_get_value(SHOW SLAVE STATUS, Master_Host, 1);
+--echo Master-Host: $master_host
+
+# clean up
+CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_USER='root';
diff --git a/mysql-test/suite/rpl/t/rpl_killed_ddl-master.opt b/mysql-test/suite/rpl/t/rpl_killed_ddl-master.opt
new file mode 100644
index 00000000..dcc136e1
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_killed_ddl-master.opt
@@ -0,0 +1 @@
+--loose-debug-dbug=d,debug_lock_before_query_log_event
diff --git a/mysql-test/suite/rpl/t/rpl_killed_ddl.test b/mysql-test/suite/rpl/t/rpl_killed_ddl.test
new file mode 100644
index 00000000..6415b3e8
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_killed_ddl.test
@@ -0,0 +1,349 @@
+# ==== Purpose ====
+#
+# This test check if DDL statements are correctly binlogged when the
+# thread is killed
+#
+# ==== Method ====
+#
+# Start a DDL query and kill it, check if the error code of the binlog
+# event is correct.
+#
+# DDL statements tested:
+# CREATE/ALTER/RENAME/DROP DATABASE
+# CREATE/ALTER/DROP EVENT
+# CREATE/ALTER/DROP FUNCTION
+# CREATE/ALTER/DROP PROCEDURE
+# CREATE/ALTER/DROP SERVER
+# CREATE/ALTER/RENAME/DROP TABLE
+# CREATE/DROP TRIGGER
+# CREATE/ALTER/DROP VIEW
+#
+# ==== Bugs =====
+#
+# BUG#37145
+#
+# ==== TODO ====
+#
+# There are some part of the test are temporarily disabled because of
+# the following bugs, please enable then once they get fixed:
+# - BUG#22473427
+# - Bug#22587377
+
+# Temporarily disabled on Windows due to bug #47638
+--source include/not_windows.inc
+
+source include/have_debug.inc;
+source include/master-slave.inc;
+
+# Use the DBUG_SYNC_POINT to make sure the thread running the DDL is
+# waiting before creating the query log event
+
+let $debug_lock= "debug_lock.before_query_log_event";
+
+######## INITIALIZATION ########
+
+disable_warnings;
+DROP DATABASE IF EXISTS d1;
+DROP DATABASE IF EXISTS d2;
+DROP DATABASE IF EXISTS d3;
+DROP DATABASE IF EXISTS d4;
+DROP EVENT IF EXISTS e1;
+DROP EVENT IF EXISTS e2;
+DROP EVENT IF EXISTS e3;
+DROP EVENT IF EXISTS e4;
+DROP FUNCTION IF EXISTS f1;
+DROP FUNCTION IF EXISTS f2;
+DROP FUNCTION IF EXISTS f3;
+DROP FUNCTION IF EXISTS f4;
+DROP SERVER IF EXISTS s1;
+DROP SERVER IF EXISTS s2;
+DROP SERVER IF EXISTS s3;
+DROP SERVER IF EXISTS s4;
+DROP TABLE IF EXISTS t1;
+DROP TABLE IF EXISTS t2;
+DROP TABLE IF EXISTS t3;
+DROP TABLE IF EXISTS t4;
+DROP PROCEDURE IF EXISTS p1;
+DROP PROCEDURE IF EXISTS p2;
+DROP PROCEDURE IF EXISTS p3;
+DROP PROCEDURE IF EXISTS p4;
+DROP TRIGGER IF EXISTS tr1;
+DROP TRIGGER IF EXISTS tr2;
+DROP TRIGGER IF EXISTS tr3;
+DROP TRIGGER IF EXISTS tr4;
+enable_warnings;
+
+CREATE DATABASE d1;
+
+CREATE EVENT e1
+ ON SCHEDULE AT CURRENT_TIMESTAMP + INTERVAL 1 DAY
+ DO INSERT INTO test.t1 VALUES (1);
+
+CREATE FUNCTION f1 () RETURNS INT DETERMINISTIC
+ RETURN 1;
+
+DELIMITER //;
+CREATE PROCEDURE p1 (OUT rows_cnt INT)
+ BEGIN
+ SELECT COUNT(*) INTO rows_cnt FROM t1;
+ END;
+ //
+DELIMITER ;//
+
+CREATE SERVER s1
+FOREIGN DATA WRAPPER mysql
+OPTIONS (USER 'user1', HOST '192.168.1.106', DATABASE 'test');
+
+CREATE TABLE t1 (a int);
+CREATE TABLE t3 (a int);
+
+DELIMITER //;
+CREATE TRIGGER tr1 BEFORE INSERT ON t1
+ FOR EACH ROW BEGIN
+ DELETE FROM t4 WHERE a=NEW.a;
+ END;
+ //
+DELIMITER ;//
+
+CREATE INDEX i1 ON t1 (a);
+
+CREATE VIEW v1 AS SELECT a FROM t1 WHERE a < 100;
+
+sync_slave_with_master;
+
+connection master1;
+let $connection_name= master1;
+let $connection_id= `SELECT CONNECTION_ID()`;
+
+connection master;
+
+# This will block the execution of a statement at the DBUG_SYNC_POINT
+# with given lock name
+if ($debug_lock)
+{
+ disable_query_log;
+ disable_result_log;
+ eval SELECT IS_FREE_LOCK($debug_lock);
+ eval SELECT GET_LOCK($debug_lock, 10);
+ eval SELECT IS_FREE_LOCK($debug_lock);
+ enable_query_log;
+ enable_result_log;
+}
+
+######## START TEST ########
+
+connection master1;
+
+disable_warnings;
+
+######## DATABASE ########
+
+let $rpl_diff_statement= SELECT schema_name FROM information_schema.schemata
+ WHERE schema_name LIKE \'d%\' ORDER BY schema_name;
+
+send CREATE DATABASE d2;
+source include/kill_query_and_diff_master_slave.inc;
+
+send ALTER DATABASE d1
+ DEFAULT CHARACTER SET = 'utf8';
+source include/kill_query_and_diff_master_slave.inc;
+
+send DROP DATABASE d1;
+source include/kill_query_and_diff_master_slave.inc;
+
+send DROP DATABASE IF EXISTS d2;
+source include/kill_query_and_diff_master_slave.inc;
+
+######## EVENT ########
+
+let $rpl_diff_statement= SELECT event_name, event_body, execute_at
+ FROM information_schema.events where event_name like \'e%\'
+ ORDER BY event_name;
+
+send CREATE EVENT e2
+ ON SCHEDULE AT CURRENT_TIMESTAMP + INTERVAL 1 DAY
+ DO INSERT INTO test.t1 VALUES (2);
+source include/kill_query_and_diff_master_slave.inc;
+
+# Temporarily disabled,see Bug#22587377-RPL.RPL_KILLED_DDL
+# FAILS SPORADICALLY ON PB2 IN 5.5 AND 5.6
+#send ALTER EVENT e1
+# ON SCHEDULE AT CURRENT_TIMESTAMP + INTERVAL 2 DAY;
+#source include/kill_query_and_diff_master_slave.inc;
+
+send DROP EVENT e1;
+source include/kill_query_and_diff_master_slave.inc;
+
+send DROP EVENT IF EXISTS e2;
+source include/kill_query_and_diff_master_slave.inc;
+
+######## FUNCTION ########
+
+--let $rpl_diff_statement= SHOW FUNCTION STATUS LIKE \'f%\'
+
+send CREATE FUNCTION f2 () RETURNS INT DETERMINISTIC
+ RETURN 1;
+source include/kill_query_and_diff_master_slave.inc;
+
+send ALTER FUNCTION f1 SQL SECURITY INVOKER;
+source include/kill_query_and_diff_master_slave.inc;
+
+# function f1 probably does not exist because the ALTER query was
+# killed
+send DROP FUNCTION f1;
+source include/kill_query_and_diff_master_slave.inc;
+
+# function f2 probably does not exist because the CREATE query was
+# killed
+send DROP FUNCTION IF EXISTS f2;
+source include/kill_query_and_diff_master_slave.inc;
+
+######## PROCEDURE ########
+
+--let $rpl_diff_statement= SHOW PROCEDURE STATUS LIKE \'p%\'
+
+DELIMITER //;
+send CREATE PROCEDURE p2 (OUT rows_cnt INT)
+ BEGIN
+ SELECT COUNT(*) INTO rows_cnt FROM t2;
+ END;
+ //
+DELIMITER ;//
+source include/kill_query_and_diff_master_slave.inc;
+
+send ALTER PROCEDURE p1 SQL SECURITY INVOKER COMMENT 'return rows_cnt of table t1';
+source include/kill_query_and_diff_master_slave.inc;
+
+send DROP PROCEDURE p1;
+source include/kill_query_and_diff_master_slave.inc;
+
+send DROP PROCEDURE IF EXISTS p2;
+source include/kill_query_and_diff_master_slave.inc;
+
+######## TABLE ########
+
+--let $rpl_diff_statement= SHOW TABLES LIKE \'t%\'
+
+send CREATE TABLE t2 (b int);
+source include/kill_query_and_diff_master_slave.inc;
+
+send ALTER TABLE t1 ADD (d int);
+source include/kill_query_and_diff_master_slave.inc;
+
+send RENAME TABLE t3 TO t4;
+source include/kill_query_and_diff_master_slave.inc;
+
+######## INDEX ########
+
+--let $rpl_diff_statement= SHOW INDEX FROM t1
+
+send CREATE INDEX i2 on t1 (a);
+source include/kill_query_and_diff_master_slave.inc;
+
+send DROP INDEX i1 on t1;
+source include/kill_query_and_diff_master_slave.inc;
+
+
+######## SERVER ########
+
+# Temporarily disabled, see Bug #22473427 - DROP SERVER FAILS
+# AFTER ALTER SERVER+KILL QUERY
+
+# --let $rpl_diff_statement= SELECT * FROM mysql.servers WHERE Server_name like \'s%\'
+
+# send CREATE SERVER s2
+# FOREIGN DATA WRAPPER mysql
+# OPTIONS (USER 'user2', HOST '192.168.1.108', DATABASE 'test');
+# source include/kill_query_and_diff_master_slave.inc;
+
+# send ALTER SERVER s1
+# OPTIONS (DATABASE 'test1');
+# source include/kill_query_and_diff_master_slave.inc;
+
+# send DROP SERVER s1;
+# source include/kill_query_and_diff_master_slave.inc;
+
+# send DROP SERVER IF EXIST s1;
+# source include/kill_query_and_diff_master_slave.inc;
+
+######## TRIGGER ########
+
+# Make sure table t4 exists
+connection master;
+CREATE TABLE IF NOT EXISTS t4 (a int);
+connection master1;
+
+--let $rpl_diff_statement= SHOW TRIGGERS LIKE \'v%\'
+
+DELIMITER //;
+send CREATE TRIGGER tr2 BEFORE INSERT ON t4
+ FOR EACH ROW BEGIN
+ DELETE FROM t1 WHERE a=NEW.a;
+ END;
+ //
+DELIMITER ;//
+source include/kill_query_and_diff_master_slave.inc;
+
+send DROP TRIGGER tr1;
+source include/kill_query_and_diff_master_slave.inc;
+
+send DROP TRIGGER IF EXISTS tr2;
+source include/kill_query_and_diff_master_slave.inc;
+
+######## VIEW ########
+
+--let $rpl_diff_statement= SHOW TABLES LIKE \'v%\'
+
+send CREATE VIEW v2 AS SELECT a FROM t1 WHERE a > 100;
+source include/kill_query_and_diff_master_slave.inc;
+
+send DROP VIEW v1;
+source include/kill_query_and_diff_master_slave.inc;
+
+send DROP VIEW IF EXISTS v2;
+source include/kill_query_and_diff_master_slave.inc;
+
+######## DROP TABLE ########
+
+--let $rpl_diff_statement= SHOW TABLES LIKE \'t%\'
+
+send DROP TABLE t1;
+source include/kill_query_and_diff_master_slave.inc;
+
+send DROP TABLE IF EXISTS t2;
+source include/kill_query_and_diff_master_slave.inc;
+
+######## CLEAN UP ########
+
+connection master;
+
+# The DROP statements above are killed during the process, so they
+# does not make sure the objects are dropped.
+
+disable_warnings;
+DROP DATABASE IF EXISTS d1;
+DROP DATABASE IF EXISTS d2;
+DROP DATABASE IF EXISTS d3;
+DROP DATABASE IF EXISTS d4;
+DROP EVENT IF EXISTS e1;
+DROP EVENT IF EXISTS e2;
+DROP EVENT IF EXISTS e3;
+DROP EVENT IF EXISTS e4;
+DROP FUNCTION IF EXISTS f1;
+DROP FUNCTION IF EXISTS f2;
+DROP FUNCTION IF EXISTS f3;
+DROP FUNCTION IF EXISTS f4;
+DROP SERVER IF EXISTS s1;
+DROP SERVER IF EXISTS s2;
+DROP SERVER IF EXISTS s3;
+DROP SERVER IF EXISTS s4;
+DROP TABLE IF EXISTS t1;
+DROP TABLE IF EXISTS t2;
+DROP TABLE IF EXISTS t3;
+DROP TABLE IF EXISTS t4;
+DROP PROCEDURE IF EXISTS p1;
+DROP PROCEDURE IF EXISTS p2;
+DROP PROCEDURE IF EXISTS p3;
+DROP PROCEDURE IF EXISTS p4;
+enable_warnings;
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_known_bugs_detection-master.opt b/mysql-test/suite/rpl/t/rpl_known_bugs_detection-master.opt
new file mode 100644
index 00000000..d4ba386a
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_known_bugs_detection-master.opt
@@ -0,0 +1 @@
+--loose-debug=d,pretend_version_50034_in_binlog
diff --git a/mysql-test/suite/rpl/t/rpl_known_bugs_detection.test b/mysql-test/suite/rpl/t/rpl_known_bugs_detection.test
new file mode 100644
index 00000000..5ea056d5
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_known_bugs_detection.test
@@ -0,0 +1,76 @@
+# Test to see if slave can detect certain known bugs present
+# on the master, and appropriately decides to stop
+# (assuming the bug is fixed in the slave, slave cannot of course
+# imitate the bug, so it has to stop).
+
+call mtr.add_suppression("Unsafe statement written to the binary log using statement format");
+
+source include/have_debug.inc;
+# because of pretend_version_50034_in_binlog the test can't run with checksum
+source include/have_binlog_checksum_off.inc;
+
+# Currently only statement-based-specific bugs are here
+-- source include/have_binlog_format_statement.inc
+
+source include/master-slave.inc;
+
+# testcase with INSERT SELECT
+connection master;
+CREATE TABLE t1 (
+ id bigint(20) unsigned NOT NULL auto_increment,
+ field_1 int(10) unsigned NOT NULL,
+ field_2 varchar(255) NOT NULL,
+ field_3 varchar(255) NOT NULL,
+ PRIMARY KEY (id),
+ UNIQUE KEY field_1 (field_1, field_2)
+);
+CREATE TABLE t2 (
+ field_a int(10) unsigned NOT NULL,
+ field_b varchar(255) NOT NULL,
+ field_c varchar(255) NOT NULL
+);
+INSERT INTO t2 (field_a, field_b, field_c) VALUES (1, 'a', '1a');
+INSERT INTO t2 (field_a, field_b, field_c) VALUES (2, 'b', '2b');
+INSERT INTO t2 (field_a, field_b, field_c) VALUES (3, 'c', '3c');
+INSERT INTO t2 (field_a, field_b, field_c) VALUES (4, 'd', '4d');
+INSERT INTO t2 (field_a, field_b, field_c) VALUES (5, 'e', '5e');
+sync_slave_with_master;
+connection master;
+# Updating table t1 based on values from table t2
+INSERT INTO t1 (field_1, field_2, field_3)
+SELECT t2.field_a, t2.field_b, t2.field_c
+FROM t2
+ON DUPLICATE KEY UPDATE
+t1.field_3 = t2.field_c;
+# Inserting new record into t2
+INSERT INTO t2 (field_a, field_b, field_c) VALUES (6, 'f', '6f');
+# Updating t1 again
+INSERT INTO t1 (field_1, field_2, field_3)
+SELECT t2.field_a, t2.field_b, t2.field_c
+FROM t2
+ON DUPLICATE KEY UPDATE
+t1.field_3 = t2.field_c;
+SELECT * FROM t1;
+connection slave;
+
+# show the error message
+#1105 = ER_UNKNOWN_ERROR
+--let $slave_sql_errno= 1105
+--let $show_slave_sql_error= 1
+--source include/wait_for_slave_sql_error.inc
+
+# show that it was not replicated
+SELECT * FROM t1;
+connection master;
+
+# clean up
+drop table t1, t2;
+connection slave;
+drop table t1, t2;
+# clear error message in sql thread
+--source include/stop_slave_io.inc
+RESET SLAVE;
+
+# End of 5.0 tests
+--let $rpl_only_running_threads= 1
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_lcase_tblnames_rewrite_db-slave.opt b/mysql-test/suite/rpl/t/rpl_lcase_tblnames_rewrite_db-slave.opt
new file mode 100644
index 00000000..0031a57a
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_lcase_tblnames_rewrite_db-slave.opt
@@ -0,0 +1 @@
+--lower-case-table-names=1 "--replicate-rewrite-db=b37656->bug37656"
diff --git a/mysql-test/suite/rpl/t/rpl_lcase_tblnames_rewrite_db.test b/mysql-test/suite/rpl/t/rpl_lcase_tblnames_rewrite_db.test
new file mode 100644
index 00000000..a27a50d0
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_lcase_tblnames_rewrite_db.test
@@ -0,0 +1,60 @@
+# BUG#37656
+#
+# DESCRIPTION
+#
+#
+# This test case is tests whether replication works properly when
+# slave is configured with --lower-case-table-names=1 and replication
+# rewrite rules are in effect.
+#
+# It checks four issues:
+#
+# (i) master contains capitalized table name
+#
+# (ii) slave contains lowered case table name
+#
+# (iii) master and slave tables do not differ
+#
+-- source include/not_windows.inc
+-- source include/master-slave.inc
+
+SET SQL_LOG_BIN=0;
+CREATE DATABASE B37656;
+SET SQL_LOG_BIN=1;
+
+-- connection slave
+CREATE DATABASE BUG37656;
+
+-- echo ### action: show that database on slave is created in lowercase
+SHOW DATABASES LIKE '%37656';
+
+-- connection master
+USE B37656;
+CREATE TABLE T1 (a int);
+INSERT INTO T1 VALUES (1);
+
+-- echo ### assertion: master contains capitalized case table
+SHOW TABLES;
+
+-- sync_slave_with_master
+
+use bug37656;
+
+-- echo ### assertion: slave contains lowered case table
+SHOW TABLES;
+
+-- echo ### assertion: master and slave tables do not differ
+let $diff_tables= master:B37656.T1, slave:bug37656.t1;
+
+-- source include/diff_tables.inc
+
+-- connection master
+SET SQL_LOG_BIN=0;
+DROP DATABASE B37656;
+SET SQL_LOG_BIN=1;
+SHOW DATABASES LIKE '%37656';
+
+-- connection slave
+DROP DATABASE BUG37656;
+SHOW DATABASES LIKE '%37656';
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_loaddata.test b/mysql-test/suite/rpl/t/rpl_loaddata.test
new file mode 100644
index 00000000..9f0ba95a
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_loaddata.test
@@ -0,0 +1,4 @@
+-- source include/have_binlog_format_statement.inc
+
+let $engine_type=MyISAM;
+-- source include/rpl_loaddata.test
diff --git a/mysql-test/suite/rpl/t/rpl_loaddata_charset.test b/mysql-test/suite/rpl/t/rpl_loaddata_charset.test
new file mode 100644
index 00000000..bb87ee95
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_loaddata_charset.test
@@ -0,0 +1,49 @@
+#
+# Check LOAD DATA + character sets + replication
+#
+source include/master-slave.inc;
+
+#
+# Bug#15126 character_set_database is not replicated
+# (LOAD DATA INFILE need it)
+#
+connection master;
+create table t1 (a varchar(10) character set utf8);
+load data infile '../../std_data/loaddata6.dat' into table t1;
+set @@character_set_database=koi8r;
+load data infile '../../std_data/loaddata6.dat' into table t1;
+set @@character_set_database=DEFAULT;
+load data infile '../../std_data/loaddata6.dat' into table t1;
+load data infile '../../std_data/loaddata6.dat' into table t1;
+load data infile '../../std_data/loaddata6.dat' into table t1;
+set @@character_set_database=koi8r;
+load data infile '../../std_data/loaddata6.dat' into table t1;
+set @@character_set_database=DEFAULT;
+load data infile '../../std_data/loaddata6.dat' into table t1 character set koi8r;
+
+select hex(a) from t1;
+
+sync_slave_with_master;
+
+select hex(a) from t1;
+connection master;
+drop table t1;
+sync_slave_with_master;
+
+#
+# Bug#45516
+# When slave SQL thread executing LOAD DATA command, the
+# thd->variables.collation_database was not set properly to the default
+# database charset
+#
+
+echo -------------test bug#45516------------------;
+
+# LOAD DATA INFILE
+let $LOAD_LOCAL=1;
+source include/rpl_loaddata_charset.inc;
+
+# LOAD DATA LOCAL INFILE
+let $LOAD_LOCAL=0;
+source include/rpl_loaddata_charset.inc;
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_loaddata_fatal-slave.opt b/mysql-test/suite/rpl/t/rpl_loaddata_fatal-slave.opt
new file mode 100644
index 00000000..9c846c79
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_loaddata_fatal-slave.opt
@@ -0,0 +1 @@
+--loose-debug=+d,LOAD_DATA_INFILE_has_fatal_error
diff --git a/mysql-test/suite/rpl/t/rpl_loaddata_fatal.test b/mysql-test/suite/rpl/t/rpl_loaddata_fatal.test
new file mode 100644
index 00000000..4e87d6de
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_loaddata_fatal.test
@@ -0,0 +1,27 @@
+source include/have_binlog_format_statement.inc;
+source include/have_debug.inc;
+source include/master-slave.inc;
+
+# We do this little stunt to make sure that the slave has started
+# before we stop it again.
+connection master;
+CREATE TABLE t1 (a INT, b INT);
+INSERT INTO t1 VALUES (1,10);
+sync_slave_with_master;
+
+# Now we feed it a load data infile, which should make it stop with a
+# fatal error.
+connection master;
+LOAD DATA INFILE '../../std_data/rpl_loaddata.dat' INTO TABLE t1;
+
+connection slave;
+call mtr.add_suppression("Slave SQL.*Fatal error: Not enough memory, error.* 1593");
+let $slave_sql_errno= 1593;
+let $show_slave_sql_error= 1;
+source include/wait_for_slave_sql_error_and_skip.inc;
+
+connection master;
+DROP TABLE t1;
+sync_slave_with_master;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_loaddata_local.test b/mysql-test/suite/rpl/t/rpl_loaddata_local.test
new file mode 100644
index 00000000..01f5607b
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_loaddata_local.test
@@ -0,0 +1,244 @@
+#
+# This include file is used by more than one test suite
+# (currently rpl and binlog_encryption).
+# Please check all dependent tests after modifying it
+#
+
+# See if "LOAD DATA LOCAL INFILE" is well replicated
+# (LOAD DATA LOCAL INFILE is not written to the binlog
+# the same way as LOAD DATA INFILE : Append_blocks are smaller).
+# In MySQL 4.0 <4.0.12 there were 2 bugs with LOAD DATA LOCAL INFILE :
+# - the loaded file was not written entirely to the master's binlog,
+# only the first 4KB, 8KB or 16KB usually.
+# - the loaded file's first line was not written entirely to the
+# master's binlog (1st char was absent)
+source include/master-slave.inc;
+
+create table t1(a int);
+let $1=10000;
+disable_query_log;
+set SQL_LOG_BIN=0;
+while ($1)
+{
+ insert into t1 values(1);
+ dec $1;
+}
+set SQL_LOG_BIN=1;
+enable_query_log;
+let $MYSQLD_DATADIR= `select @@datadir`;
+--replace_result $MYSQLD_DATADIR MYSQLD_DATADIR
+--disable_ps2_protocol
+eval select * into outfile '$MYSQLD_DATADIR/rpl_loaddatalocal.select_outfile' from t1;
+--enable_ps2_protocol
+#This will generate a 20KB file, now test LOAD DATA LOCAL
+truncate table t1;
+--replace_result $MYSQLD_DATADIR MYSQLD_DATADIR
+eval load data local infile '$MYSQLD_DATADIR/rpl_loaddatalocal.select_outfile' into table t1;
+--remove_file $MYSQLD_DATADIR/rpl_loaddatalocal.select_outfile
+sync_slave_with_master;
+select a,count(*) from t1 group by a;
+connection master;
+drop table t1;
+sync_slave_with_master;
+
+# End of 4.1 tests
+
+#
+# Now let us test how well we replicate LOAD DATA LOCAL in situation when
+# we met duplicates in tables to which we are adding rows.
+# (It supposed that LOAD DATA LOCAL ignores such errors)
+#
+connection master;
+create table t1(a int);
+insert into t1 values (1), (2), (2), (3);
+--replace_result $MYSQLD_DATADIR MYSQLD_DATADIR
+--disable_ps2_protocol
+eval select * into outfile '$MYSQLD_DATADIR/rpl_loaddatalocal.select_outfile' from t1;
+--enable_ps2_protocol
+drop table t1;
+create table t1(a int primary key);
+--replace_result $MYSQLD_DATADIR MYSQLD_DATADIR
+eval load data local infile '$MYSQLD_DATADIR/rpl_loaddatalocal.select_outfile' into table t1;
+--remove_file $MYSQLD_DATADIR/rpl_loaddatalocal.select_outfile
+SELECT * FROM t1 ORDER BY a;
+save_master_pos;
+connection slave;
+sync_with_master;
+SELECT * FROM t1 ORDER BY a;
+connection master;
+drop table t1;
+save_master_pos;
+connection slave;
+sync_with_master;
+
+
+#
+# Bug22504 load data infile sql statement in replication architecture get error
+#
+--echo ==== Bug22504 Initialize ====
+
+--connection master
+
+SET sql_mode='ignore_space';
+CREATE TABLE t1(a int);
+insert into t1 values (1), (2), (3), (4);
+--replace_result $MYSQLD_DATADIR MYSQLD_DATADIR
+--disable_ps2_protocol
+eval select * into outfile '$MYSQLD_DATADIR/rpl_loaddatalocal.select_outfile' from t1;
+--enable_ps2_protocol
+truncate table t1;
+--replace_result $MYSQLD_DATADIR MYSQLD_DATADIR
+eval load data local infile '$MYSQLD_DATADIR/rpl_loaddatalocal.select_outfile' into table t1;
+--remove_file $MYSQLD_DATADIR/rpl_loaddatalocal.select_outfile
+SELECT * FROM t1 ORDER BY a;
+
+sync_slave_with_master;
+SELECT * FROM t1 ORDER BY a;
+
+--echo ==== Clean up ====
+
+connection master;
+DROP TABLE t1;
+
+sync_slave_with_master;
+
+--echo
+--echo Bug #43746:
+--echo "return wrong query string when parse 'load data infile' sql statement"
+--echo
+
+connection master;
+let $MYSQLD_DATADIR= `select @@datadir`;
+SELECT @@SESSION.sql_mode INTO @old_mode;
+
+SET sql_mode='ignore_space';
+
+CREATE TABLE t1(a int);
+INSERT INTO t1 VALUES (1), (2), (3), (4);
+
+--replace_result $MYSQLD_DATADIR MYSQLD_DATADIR
+--disable_ps2_protocol
+eval SELECT * INTO OUTFILE '$MYSQLD_DATADIR/bug43746.sql' FROM t1;
+--enable_ps2_protocol
+TRUNCATE TABLE t1;
+
+--replace_result $MYSQLD_DATADIR MYSQLD_DATADIR
+eval LOAD DATA LOCAL INFILE '$MYSQLD_DATADIR/bug43746.sql' INTO TABLE t1;
+
+--replace_result $MYSQLD_DATADIR MYSQLD_DATADIR
+eval LOAD/* look mum, with comments in weird places! */DATA/* oh hai */LOCAL INFILE '$MYSQLD_DATADIR/bug43746.sql'/* we are */INTO/* from the internets */TABLE t1;
+
+--replace_result $MYSQLD_DATADIR MYSQLD_DATADIR
+eval LOAD DATA/*!10000 LOCAL */INFILE '$MYSQLD_DATADIR/bug43746.sql' INTO TABLE t1;
+
+--replace_result $MYSQLD_DATADIR MYSQLD_DATADIR
+eval LOAD DATA LOCAL INFILE '$MYSQLD_DATADIR/bug43746.sql' /*!10000 INTO */ TABLE t1;
+
+--replace_result $MYSQLD_DATADIR MYSQLD_DATADIR
+eval LOAD DATA LOCAL INFILE '$MYSQLD_DATADIR/bug43746.sql' /*!10000 INTO TABLE */ t1;
+
+--replace_result $MYSQLD_DATADIR MYSQLD_DATADIR
+eval LOAD DATA /*!10000 LOCAL INFILE '$MYSQLD_DATADIR/bug43746.sql' INTO TABLE */ t1;
+
+--replace_result $MYSQLD_DATADIR MYSQLD_DATADIR
+eval LOAD DATA/*!10000 LOCAL */INFILE '$MYSQLD_DATADIR/bug43746.sql'/*!10000 INTO*/TABLE t1;
+
+--replace_result $MYSQLD_DATADIR MYSQLD_DATADIR
+eval LOAD DATA/*!10000 LOCAL */INFILE '$MYSQLD_DATADIR/bug43746.sql'/* empty */INTO TABLE t1;
+
+--replace_result $MYSQLD_DATADIR MYSQLD_DATADIR
+eval LOAD DATA/*!10000 LOCAL */INFILE '$MYSQLD_DATADIR/bug43746.sql' INTO/* empty */TABLE t1;
+
+--replace_result $MYSQLD_DATADIR MYSQLD_DATADIR
+eval LOAD/*!999999 special comments that do not expand */DATA/*!999999 code from the future */LOCAL INFILE '$MYSQLD_DATADIR/bug43746.sql'/*!999999 have flux capacitor */INTO/*!999999 will travel */TABLE t1;
+
+SET sql_mode='PIPES_AS_CONCAT,ANSI_QUOTES,NO_KEY_OPTIONS,NO_TABLE_OPTIONS,NO_FIELD_OPTIONS,STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER';
+
+--replace_result $MYSQLD_DATADIR MYSQLD_DATADIR
+eval LOAD DATA LOCAL INFILE '$MYSQLD_DATADIR/bug43746.sql' INTO TABLE t1;
+
+sync_slave_with_master;
+
+--echo
+--echo Bug #59267:
+--echo "LOAD DATA LOCAL INFILE not executed on slave with SBR"
+--echo
+
+connection master;
+
+--replace_result $MYSQLD_DATADIR MYSQLD_DATADIR
+--disable_ps2_protocol
+eval SELECT * INTO OUTFILE '$MYSQLD_DATADIR/bug59267.sql' FROM t1;
+--enable_ps2_protocol
+TRUNCATE TABLE t1;
+
+--replace_result $MYSQLD_DATADIR MYSQLD_DATADIR
+eval LOAD DATA LOCAL INFILE '$MYSQLD_DATADIR/bug59267.sql' INTO TABLE t1;
+
+SELECT 'Master', COUNT(*) FROM t1;
+
+--sync_slave_with_master
+SELECT 'Slave', COUNT(*) FROM t1;
+
+# cleanup
+connection master;
+
+--remove_file $MYSQLD_DATADIR/bug43746.sql
+--remove_file $MYSQLD_DATADIR/bug59267.sql
+
+DROP TABLE t1;
+SET SESSION sql_mode=@old_mode;
+
+sync_slave_with_master;
+
+connection master;
+
+--echo
+--echo Bug #60580/#11902767:
+--echo "statement improperly replicated crashes slave sql thread"
+--echo
+
+connection master;
+let $MYSQLD_DATADIR= `select @@datadir`;
+
+CREATE TABLE t1(f1 INT, f2 INT);
+CREATE TABLE t2(f1 INT, f2 TIMESTAMP);
+
+INSERT INTO t2 VALUES(1, '2011-03-22 21:01:28');
+INSERT INTO t2 VALUES(2, '2011-03-21 21:01:28');
+INSERT INTO t2 VALUES(3, '2011-03-20 21:01:28');
+
+CREATE TABLE t3 AS SELECT * FROM t2;
+
+CREATE VIEW v1 AS SELECT * FROM t2
+ WHERE f1 IN (SELECT f1 FROM t3 WHERE (t3.f2 IS NULL));
+
+--replace_result $MYSQLD_DATADIR MYSQLD_DATADIR
+--disable_ps2_protocol
+eval SELECT 1 INTO OUTFILE '$MYSQLD_DATADIR/bug60580.csv' FROM DUAL;
+--enable_ps2_protocol
+
+--replace_result $MYSQLD_DATADIR MYSQLD_DATADIR
+eval LOAD DATA LOCAL INFILE '$MYSQLD_DATADIR/bug60580.csv' INTO TABLE t1 (@f1) SET f2 = (SELECT f1 FROM v1 WHERE f1=@f1);
+
+SELECT * FROM t1;
+
+sleep 1;
+
+sync_slave_with_master;
+
+SELECT * FROM t1;
+
+--remove_file $MYSQLD_DATADIR/bug60580.csv
+
+connection master;
+
+DROP VIEW v1;
+DROP TABLE t1, t2, t3;
+
+sync_slave_with_master;
+
+connection master;
+--source include/rpl_end.inc
+
+--echo # End of 5.1 tests
diff --git a/mysql-test/suite/rpl/t/rpl_loaddata_m-master.opt b/mysql-test/suite/rpl/t/rpl_loaddata_m-master.opt
new file mode 100644
index 00000000..9d4a8f0b
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_loaddata_m-master.opt
@@ -0,0 +1 @@
+--binlog_ignore_db=test
diff --git a/mysql-test/suite/rpl/t/rpl_loaddata_m.test b/mysql-test/suite/rpl/t/rpl_loaddata_m.test
new file mode 100644
index 00000000..b9dffa3f
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_loaddata_m.test
@@ -0,0 +1,51 @@
+# See if the master logs LOAD DATA INFILE correctly when binlog_*_db rules
+# exist.
+# This is for BUG#1100 (LOAD DATA INFILE was half-logged).
+######################################################
+# Change Author: JBM
+# Change Date: 2005-12-22
+# Change: Test rewritten to remove show binlog events
+# and to test the option better + Cleanup
+######################################################
+-- source include/master-slave.inc
+
+--disable_warnings
+drop database if exists mysqltest;
+--enable_warnings
+
+connection master;
+# 'test' database should be ignored by the slave
+USE test;
+CREATE TABLE t1(a INT, b INT, UNIQUE(b));
+LOAD DATA INFILE '../../std_data/rpl_loaddata.dat' INTO TABLE test.t1;
+SELECT COUNT(*) FROM test.t1;
+
+# 'mysqltest' database should NOT be ignored by the slave
+CREATE DATABASE mysqltest;
+USE mysqltest;
+CREATE TABLE t1(a INT, b INT, UNIQUE(b));
+LOAD DATA INFILE '../../std_data/rpl_loaddata.dat' INTO TABLE mysqltest.t1;
+SELECT COUNT(*) FROM mysqltest.t1;
+
+# Now lets check the slave to see what we have :-)
+sync_slave_with_master;
+
+SHOW DATABASES;
+
+USE test;
+SHOW TABLES;
+
+USE mysqltest;
+SHOW TABLES;
+SELECT COUNT(*) FROM mysqltest.t1;
+
+#show binlog events;
+
+# Cleanup
+connection master;
+DROP DATABASE mysqltest;
+DROP TABLE IF EXISTS test.t1;
+sync_slave_with_master;
+
+# End of test
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_loaddata_map-master.opt b/mysql-test/suite/rpl/t/rpl_loaddata_map-master.opt
new file mode 100644
index 00000000..5fdeb855
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_loaddata_map-master.opt
@@ -0,0 +1 @@
+--read_buffer_size=12K --max_allowed_packet=8K --net-buffer-length=8K
diff --git a/mysql-test/suite/rpl/t/rpl_loaddata_map-slave.opt b/mysql-test/suite/rpl/t/rpl_loaddata_map-slave.opt
new file mode 100644
index 00000000..7d404fae
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_loaddata_map-slave.opt
@@ -0,0 +1 @@
+--max_allowed_packet=8K --net-buffer-length=8K
diff --git a/mysql-test/suite/rpl/t/rpl_loaddata_map.test b/mysql-test/suite/rpl/t/rpl_loaddata_map.test
new file mode 100644
index 00000000..0df424aa
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_loaddata_map.test
@@ -0,0 +1,74 @@
+# ==== Purpose ====
+#
+# check replication of load data with the server parameters subjected to
+# read_buffer_size > max_allowed_packet
+#
+# ==== Implementation ====
+#
+# Insert many rows into t1, write t1 to file.
+# Load the file into t2.
+# See that t2 came out as expected on slave.
+#
+# ==== Related Bugs ====
+#
+# BUG#30435 loading large LOAD DATA INFILE breaks slave with
+# read_buffer_size set on master
+# BUG#33413 show binlog events fails if binlog has event size of close
+# to max_allowed_packet
+
+source include/have_binlog_format_statement.inc;
+source include/master-slave.inc;
+
+
+--echo ==== Create a big file ====
+
+# We turn off binlogging to avoid too much noise in the binlog. t1 is
+# just an auxiliary construction anyways, it is not needed on the
+# slave.
+
+--disable_query_log
+SET @@sql_log_bin= 0;
+
+let $rows= 5000;
+create table t1 (id int not null primary key auto_increment);
+
+while($rows)
+{
+ eval insert into t1 values (null);
+ dec $rows;
+}
+--disable_ps2_protocol
+eval select * into outfile '$MYSQLTEST_VARDIR/tmp/bug30435_5k.txt' from t1;
+--enable_ps2_protocol
+
+DROP TABLE t1;
+SET @@sql_log_bin= 1;
+--enable_query_log
+
+
+--echo ==== Load our big file into a table ====
+create table t2 (id int not null primary key auto_increment);
+
+select @@session.read_buffer_size - @@session.max_allowed_packet > 0 ;
+
+--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
+eval load data infile '$MYSQLTEST_VARDIR/tmp/bug30435_5k.txt' into table t2;
+select count(*) from t2 /* 5 000 */;
+
+# the binlog will show fragmented Append_block events
+source include/show_binlog_events.inc;
+
+
+--echo ==== Verify results on slave ====
+
+sync_slave_with_master;
+select count(*) from t2 /* 5 000 */;
+
+
+--echo ==== Clean up ====
+
+connection master;
+drop table t2;
+sync_slave_with_master;
+remove_file $MYSQLTEST_VARDIR/tmp/bug30435_5k.txt;
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_loaddata_s-slave.opt b/mysql-test/suite/rpl/t/rpl_loaddata_s-slave.opt
new file mode 100644
index 00000000..9d4a8f0b
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_loaddata_s-slave.opt
@@ -0,0 +1 @@
+--binlog_ignore_db=test
diff --git a/mysql-test/suite/rpl/t/rpl_loaddata_s.test b/mysql-test/suite/rpl/t/rpl_loaddata_s.test
new file mode 100644
index 00000000..21167968
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_loaddata_s.test
@@ -0,0 +1,27 @@
+# See if the slave logs (in its own binlog, with --log-slave-updates) a
+# replicated LOAD DATA INFILE correctly when it has binlog_*_db rules.
+# This is for BUG#1100 (LOAD DATA INFILE was half-logged).
+
+-- source include/have_binlog_format_mixed_or_statement.inc
+-- source include/master-slave.inc
+
+connection slave;
+# Not sure why we connect to slave and then try to reset master, but I will leave it [JBM]
+reset master;
+
+connection master;
+# 'test' is the current database
+create table test.t1(a int, b int, unique(b));
+load data infile '../../std_data/rpl_loaddata.dat' into table test.t1;
+
+# Test logging on slave;
+
+sync_slave_with_master;
+select count(*) from test.t1; # check that LOAD was replicated
+source include/show_binlog_events.inc;
+
+# Cleanup
+connection master;
+drop table test.t1;
+sync_slave_with_master;
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_loaddata_simple.test b/mysql-test/suite/rpl/t/rpl_loaddata_simple.test
new file mode 100644
index 00000000..a09d3fee
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_loaddata_simple.test
@@ -0,0 +1,15 @@
+--source include/master-slave.inc
+
+CREATE TABLE t1 (word CHAR(20) NOT NULL);
+LOAD DATA INFILE '../../std_data/words.dat' INTO TABLE t1;
+SELECT * FROM t1 ORDER BY word;
+sync_slave_with_master;
+
+# Check
+SELECT * FROM t1 ORDER BY word;
+
+# Cleanup
+connection master;
+drop table t1;
+sync_slave_with_master;
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_loaddata_symlink-master.opt b/mysql-test/suite/rpl/t/rpl_loaddata_symlink-master.opt
new file mode 100644
index 00000000..719832a2
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_loaddata_symlink-master.opt
@@ -0,0 +1 @@
+--secure-file-priv=$MYSQLTEST_VARDIR/std_data_master_link
diff --git a/mysql-test/suite/rpl/t/rpl_loaddata_symlink-master.sh b/mysql-test/suite/rpl/t/rpl_loaddata_symlink-master.sh
new file mode 100644
index 00000000..e5bb3e61
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_loaddata_symlink-master.sh
@@ -0,0 +1,2 @@
+rm -f $MYSQLTEST_VARDIR/std_data_master_link
+ln -s $MYSQLTEST_VARDIR/std_data $MYSQLTEST_VARDIR/std_data_master_link
diff --git a/mysql-test/suite/rpl/t/rpl_loaddata_symlink-slave.opt b/mysql-test/suite/rpl/t/rpl_loaddata_symlink-slave.opt
new file mode 100644
index 00000000..a112e81a
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_loaddata_symlink-slave.opt
@@ -0,0 +1 @@
+--slave-load-tmpdir=$MYSQLTEST_VARDIR/std_data_slave_link
diff --git a/mysql-test/suite/rpl/t/rpl_loaddata_symlink-slave.sh b/mysql-test/suite/rpl/t/rpl_loaddata_symlink-slave.sh
new file mode 100644
index 00000000..7a0c0bb3
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_loaddata_symlink-slave.sh
@@ -0,0 +1,2 @@
+rm -f $MYSQLTEST_VARDIR/std_data_slave_link
+ln -s $MYSQLTEST_VARDIR/std_data $MYSQLTEST_VARDIR/std_data_slave_link
diff --git a/mysql-test/suite/rpl/t/rpl_loaddata_symlink.test b/mysql-test/suite/rpl/t/rpl_loaddata_symlink.test
new file mode 100644
index 00000000..e5ee400d
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_loaddata_symlink.test
@@ -0,0 +1,22 @@
+#
+# BUG#43913
+# This test verifies if loading data infile will work fine
+# if the path of the load data file is a symbolic link.
+#
+--source include/not_windows.inc
+--source include/have_binlog_format_statement.inc
+--source include/master-slave.inc
+
+create table t1(a int not null auto_increment, b int, primary key(a) );
+load data infile '../../std_data/rpl_loaddata.dat' into table t1;
+select * from t1;
+
+sync_slave_with_master;
+connection slave;
+select * from t1;
+
+connection master;
+drop table t1;
+sync_slave_with_master;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_loadfile.test b/mysql-test/suite/rpl/t/rpl_loadfile.test
new file mode 100644
index 00000000..a49b3c30
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_loadfile.test
@@ -0,0 +1,122 @@
+#
+# This include file is used by more than one test suite
+# (currently rpl and binlog_encryption).
+# Please check all dependent tests after modifying it
+#
+
+#############################################################################
+# Original Author: JBM #
+# Original Date: Aug/18/2005 #
+#############################################################################
+# TEST: To test the LOAD_FILE() in rbr #
+#############################################################################
+# Change Author: JBM
+# Change Date: 2006-01-16
+##########
+
+# Includes
+-- source include/have_binlog_format_mixed_or_row.inc
+-- source include/master-slave.inc
+
+-- source suite/rpl/include/rpl_loadfile.test
+
+# BUG#39701: Mixed binlog format does not switch to row mode on LOAD_FILE
+#
+# DESCRIPTION
+#
+# Problem: when using load_file string function and mixed binlogging format
+# there was no switch to row based binlogging format. This leads
+# to scenarios on which the slave replicates the statement and it
+# will try to load the file from local file system, which in most
+# likely it will not exist.
+#
+# Solution:
+# Marking this function as unsafe for statement format, makes the
+# statement using it to be logged in row based format. As such, data
+# replicated from the master, becomes the content of the loaded file.
+# Consequently, the slave receives the necessary data to complete
+# the load_file instruction correctly.
+#
+# IMPLEMENTATION
+#
+# The test is implemented as follows:
+#
+# On Master,
+# i) write to file the desired content.
+# ii) create table and stored procedure with load_file
+# iii) stop slave
+# iii) execute load_file
+# iv) remove file
+#
+# On Slave,
+# v) start slave
+# vi) sync it with master so that it gets the updates from binlog (which
+# should have bin logged in row format).
+#
+# If the the binlog format does not change to row, then the assertion
+# done in the following step fails. This happens because tables differ
+# since the file does not exist anymore, meaning that when slave
+# attempts to execute LOAD_FILE statement it inserts NULL on table
+# instead of the same contents that the master loaded when it executed
+# the procedure (which was executed when file existed).
+#
+# vii) assert that the contents of master and slave
+# table are the same
+
+--source include/rpl_reset.inc
+
+connection master;
+let $file= $MYSQLTEST_VARDIR/tmp/bug_39701.data;
+
+--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
+--disable_ps2_protocol
+--eval SELECT repeat('x',20) INTO OUTFILE '$file'
+--enable_ps2_protocol
+
+disable_warnings;
+DROP TABLE IF EXISTS t1;
+enable_warnings;
+
+CREATE TABLE t1 (t text);
+DELIMITER |;
+CREATE PROCEDURE p(file varchar(4096))
+ BEGIN
+ INSERT INTO t1 VALUES (LOAD_FILE(file));
+ END|
+DELIMITER ;|
+
+# stop slave before issuing the load_file on master
+connection slave;
+source include/stop_slave.inc;
+
+connection master;
+
+# test: check that logging falls back to rbr.
+--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
+--eval CALL p('$file')
+
+# test: remove the file from the filesystem and assert that slave still
+# gets the loaded file
+remove_file $file;
+
+# now that the file is removed it is safe (regarding what we want to test)
+# to start slave
+connection slave;
+source include/start_slave.inc;
+
+connection master;
+sync_slave_with_master;
+
+# assertion: assert that the slave got the updates even
+# if the file was removed before the slave started,
+# meaning that contents were indeed transfered
+# through binlog (in row format)
+let $diff_tables= master:t1, slave:t1;
+source include/diff_tables.inc;
+
+# CLEAN UP
+--connection master
+DROP TABLE t1;
+DROP PROCEDURE p;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_locale.test b/mysql-test/suite/rpl/t/rpl_locale.test
new file mode 100644
index 00000000..0d6692dd
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_locale.test
@@ -0,0 +1,25 @@
+# Replication of locale variables
+
+source include/master-slave.inc;
+
+#
+# Bug#22645 LC_TIME_NAMES: Statement not replicated
+#
+connection master;
+create table t1 (s1 char(10));
+set lc_time_names= 'de_DE';
+insert into t1 values (date_format('2001-01-01','%W'));
+set lc_time_names= 'en_US';
+insert into t1 values (date_format('2001-01-01','%W'));
+select * from t1;
+sync_slave_with_master;
+connection slave;
+select * from t1;
+connection master;
+drop table t1;
+sync_slave_with_master;
+
+# End of 4.1 tests
+
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_log_pos.test b/mysql-test/suite/rpl/t/rpl_log_pos.test
new file mode 100644
index 00000000..1504cba0
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_log_pos.test
@@ -0,0 +1,57 @@
+##########
+# Change Author: JBM
+# Change Date: 2006-01-16
+##########
+
+#
+# Testing of setting slave to wrong log position with master_log_pos
+#
+
+# Passes with rbr no problem, removed statement include [jbm]
+
+source include/master-slave.inc;
+
+#
+# Add an event to get some information into the log we can try to parse
+#
+let $read_pos= query_get_value(SHOW MASTER STATUS, Position, 1);
+create table if not exists t1 (n int);
+drop table t1;
+
+call mtr.add_suppression ("Slave I/O: Got fatal error 1236 from master when reading data from binary");
+call mtr.add_suppression ("Error in Log_event::read_log_event");
+source include/show_master_status.inc;
+sync_slave_with_master;
+source include/stop_slave.inc;
+
+let $wrong_log_pos= `SELECT $read_pos+2`;
+--replace_result $wrong_log_pos MASTER_LOG_POS
+eval change master to master_log_pos=$wrong_log_pos, master_use_gtid=no;
+start slave;
+let $slave_io_errno= 1236;
+--let $show_slave_io_error= 1
+# Mask line numbers
+--let $slave_io_error_replace= / at [0-9]*/ at XXX/
+source include/wait_for_slave_io_error.inc;
+source include/stop_slave_sql.inc;
+--enable_warnings
+
+connection master;
+source include/show_master_status.inc;
+create table if not exists t1 (n int);
+drop table if exists t1;
+create table t1 (n int);
+insert into t1 values (1),(2),(3);
+save_master_pos;
+connection slave;
+--replace_result 4 MASTER_LOG_POS
+change master to master_log_pos=4, master_use_gtid=no;
+start slave;
+sync_with_master;
+select * from t1 ORDER BY n;
+connection master;
+drop table t1;
+sync_slave_with_master;
+
+--echo End of 5.0 tests
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_lost_events_on_rotate.test b/mysql-test/suite/rpl/t/rpl_lost_events_on_rotate.test
new file mode 100644
index 00000000..8c4baafe
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_lost_events_on_rotate.test
@@ -0,0 +1,52 @@
+#
+# Whenever the mysql_binlog_send method (dump thread) reaches the
+# end of file when reading events from the binlog, before checking
+# if it should wait for more events, there was a test to check if
+# the file being read was still active, i.e, it was the last known
+# binlog. However, it was possible that something was written to
+# the binary log and then a rotation would happen, after EOF was
+# detected and before the check for active was performed. In this
+# case, the end of the binary log would not be read by the dump
+# thread, and this would cause the slave to lose updates.
+#
+# This test verifies that the problem has been fixed. It waits
+# during this window while forcing a rotation in the binlog.
+#
+--source include/have_debug.inc
+--source include/have_debug_sync.inc
+--source include/master-slave.inc
+
+--connection master
+
+SET @debug_saved= @@GLOBAL.DEBUG_DBUG;
+
+CREATE TABLE t (i INT);
+
+# When reaching the EOF the dump thread will wait before deciding if
+# it should move to a new binlong file.
+SET GLOBAL DEBUG_DBUG= "d,wait_after_binlog_EOF";
+
+INSERT INTO t VALUES (1);
+
+--sleep 1
+
+# A insert and a rotate happens before the decision
+INSERT INTO t VALUES (2);
+FLUSH LOGS;
+
+SET DEBUG_SYNC= 'now SIGNAL signal.rotate_finished';
+
+--sync_slave_with_master
+
+# All the rows should be sent to the slave.
+--let $diff_tables=master:t,slave:t
+--source include/diff_tables.inc
+
+##Clean up
+--connection master
+
+SET @@GLOBAL.DEBUG_DBUG= @debug_saved;
+SET DEBUG_SYNC= 'RESET';
+
+DROP TABLE t;
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_manual_change_index_file.test b/mysql-test/suite/rpl/t/rpl_manual_change_index_file.test
new file mode 100644
index 00000000..a3da34ec
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_manual_change_index_file.test
@@ -0,0 +1,114 @@
+source include/master-slave.inc;
+
+connection slave;
+source include/stop_slave.inc;
+CHANGE MASTER TO MASTER_USE_GTID=NO;
+source include/start_slave.inc;
+connection master;
+
+#
+# BUG#28421 Infinite loop on slave relay logs
+#
+# That, manually deleteing one or more entries from 'master-bin.index', will
+# cause master infinitely loop to send one binlog file.
+#
+# Manually changing index file is a illegal action, so when this happen, we
+# send a fatal error to slave and close the dump session.
+
+FLUSH LOGS;
+# Now, 2 entries in index file.
+# ./master-bin.000001
+# ./master-bin.000002
+
+CREATE TABLE t1(c1 INT);
+# Now, the current dump file(master-bin.000002) is the second line of index
+# file
+sync_slave_with_master;
+# Now, all events has been replicate to slave. As current dump file
+# (master-bin.000002) is the last binlog file, so master is waiting for new
+# events.
+
+connection master;
+# Delete './master-bin.000001' from index file.
+let $MYSQLD_DATADIR= `SELECT @@DATADIR`;
+let TRUNCATE_FILE= $MYSQLD_DATADIR/master-bin.index;
+source include/truncate_file.inc;
+
+if (`SELECT CONVERT(@@VERSION_COMPILE_OS USING latin1) NOT IN ('Win32', 'Win64', 'Windows')`)
+{
+append_file $MYSQLD_DATADIR/master-bin.index;
+./master-bin.000002
+EOF
+sleep 0.00000001;
+}
+
+if (`SELECT CONVERT(@@VERSION_COMPILE_OS USING latin1) IN ('Win32', 'Win64', 'Windows')`)
+{
+append_file $MYSQLD_DATADIR/master-bin.index;
+.\master-bin.000002
+EOF
+sleep 0.00000001;
+}
+
+# Now, only 1 entry in index file. ./master-bin.000002
+
+# Generate master-bin.000003, but it is in the second line.
+FLUSH LOGS;
+# Now, 2 entries in index file.
+# ./master-bin.000002
+# ./master-bin.000003
+
+# Now, master know that new binlog file(master-bin.000003) has been generated.
+# It expects that the new binlog file is in third line of index file, but
+# there is no third line in index file. It is so strange that master sends an
+# error to slave.
+call mtr.add_suppression('Got fatal error 1236 from master when reading data from binary log: .*could not find next log');
+connection slave;
+# 1236 = ER_MASTER_FATAL_ERROR_READING_BINLOG
+--let $slave_io_errno= 1236
+--let $show_slave_io_error= 1
+# Mask line numbers
+--let $slave_io_error_replace= / at [0-9]*/ at XXX/ /the first event '(\.|master-bin.000001)'/the first event 'FILE'/
+--source include/wait_for_slave_io_error.inc
+
+connection master;
+
+source include/truncate_file.inc;
+
+if (`SELECT CONVERT(@@VERSION_COMPILE_OS USING latin1) NOT IN ('Win32', 'Win64', 'Windows')`)
+{
+append_file $MYSQLD_DATADIR/master-bin.index;
+./master-bin.000001
+./master-bin.000002
+./master-bin.000003
+EOF
+sleep 0.00000001;
+}
+
+if (`SELECT CONVERT(@@VERSION_COMPILE_OS USING latin1) IN ('Win32', 'Win64', 'Windows')`)
+{
+append_file $MYSQLD_DATADIR/master-bin.index;
+.\master-bin.000001
+.\master-bin.000002
+.\master-bin.000003
+EOF
+sleep 0.00000001;
+}
+
+CREATE TABLE t2(c1 INT);
+FLUSH LOGS;
+CREATE TABLE t3(c1 INT);
+FLUSH LOGS;
+CREATE TABLE t4(c1 INT);
+
+connection slave;
+START SLAVE IO_THREAD;
+source include/wait_for_slave_io_to_start.inc;
+
+connection master;
+sync_slave_with_master;
+SHOW TABLES;
+
+connection master;
+DROP TABLE t1, t2, t3, t4;
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_many_optimize.test b/mysql-test/suite/rpl/t/rpl_many_optimize.test
new file mode 100644
index 00000000..d5e9f69b
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_many_optimize.test
@@ -0,0 +1,23 @@
+# Test for BUG#7658 "optimize crashes slave thread (1 in 1000)]"
+
+source include/master-slave.inc;
+
+create table t1 (a int not null auto_increment primary key, b int, key(b));
+INSERT INTO t1 (a) VALUES (1),(2);
+# Now many OPTIMIZE to test if we crash (BUG#7658)
+let $1=300;
+disable_query_log;
+disable_result_log;
+while ($1)
+{
+ eval OPTIMIZE TABLE t1;
+ dec $1;
+}
+enable_result_log;
+enable_query_log;
+drop table t1;
+# Bug was that slave segfaulted after ~ a hundred of OPTIMIZE (or ANALYZE)
+sync_slave_with_master;
+
+# End of 4.1 tests
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_mariadb_slave_capability.test b/mysql-test/suite/rpl/t/rpl_mariadb_slave_capability.test
new file mode 100644
index 00000000..d49851cc
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_mariadb_slave_capability.test
@@ -0,0 +1,167 @@
+--source include/have_debug.inc
+--source include/have_debug_sync.inc
+--source include/have_binlog_format_row.inc
+--source include/have_innodb.inc
+--source include/master-slave.inc
+
+connection master;
+set @old_master_binlog_checksum= @@global.binlog_checksum;
+
+# MDEV-4475: Cannot replicate to old server when binlog contains
+# empty Gtid_list event
+#
+# Test this by binlog rotation before we log any GTIDs.
+connection slave;
+
+# Need to stop/start the master without GTID before setting debug_dbug
+--source include/stop_slave.inc
+CHANGE MASTER TO MASTER_USE_GTID=NO;
+--source include/start_slave.inc
+
+--source include/stop_slave.inc
+--echo # Test slave with no capability gets dummy event, which is ignored.
+set @old_dbug= @@global.debug_dbug;
+SET @@global.debug_dbug='+d,simulate_slave_capability_none';
+--source include/start_slave.inc
+
+connection master;
+FLUSH LOGS;
+CREATE TABLE t1 (a INT PRIMARY KEY);
+INSERT INTO t1 VALUES (0);
+sync_slave_with_master;
+
+connection master;
+# Add a dummy event just to have something to sync_slave_with_master on.
+# Otherwise we occasionally get different $relaylog_start, depending on
+# whether Format_description_log_event was written to relay log or not
+# at the time of SHOW SLAVE STATUS.
+ALTER TABLE t1 ORDER BY a;
+sync_slave_with_master;
+connection slave;
+let $relaylog_start= query_get_value(SHOW SLAVE STATUS, Relay_Log_Pos, 1);
+
+connection master;
+SET SESSION binlog_annotate_row_events = ON;
+let $binlog_file= query_get_value(SHOW MASTER STATUS, File, 1);
+let $binlog_start= query_get_value(SHOW MASTER STATUS, Position, 1);
+# A short event, to test when we need to use user_var_event for dummy event.
+DELETE FROM t1;
+INSERT INTO t1 /* A comment just to make the annotate event sufficiently long that the dummy event will need to get padded with spaces so that we can test that this works */ VALUES(1);
+let $binlog_limit= 0, 10;
+--source include/show_binlog_events.inc
+sync_slave_with_master;
+connection slave;
+
+SELECT * FROM t1;
+let $binlog_file= query_get_value(SHOW SLAVE STATUS, Relay_Log_File, 1);
+let $binlog_start= $relaylog_start;
+let $binlog_limit=0,10;
+--source include/show_relaylog_events.inc
+set @@global.debug_dbug= @old_dbug;
+
+--echo # Test dummy event is checksummed correctly.
+
+connection master;
+set @@global.binlog_checksum = CRC32;
+--source include/wait_for_binlog_checkpoint.inc
+TRUNCATE t1;
+let $binlog_file= query_get_value(SHOW MASTER STATUS, File, 1);
+let $binlog_start= query_get_value(SHOW MASTER STATUS, Position, 1);
+INSERT INTO t1 VALUES(2);
+let $binlog_limit= 0, 5;
+--source include/show_binlog_events.inc
+sync_slave_with_master;
+connection slave;
+
+SELECT * FROM t1;
+let $binlog_file= query_get_value(SHOW SLAVE STATUS, Relay_Log_File, 1);
+let $binlog_start= 0;
+let $binlog_limit=7,5;
+--source include/show_relaylog_events.inc
+
+
+--echo *** MDEV-5754: MySQL 5.5 slaves cannot replicate from MariaDB 10.0 ***
+
+# The problem was that for a group commit, we get commit id into the
+# GTID event, and there was a bug in the code that replaces GTID with
+# dummy that failed when commit id was present.
+#
+# So setup a group commit in InnoDB.
+
+--connection master
+CREATE TABLE t2 (a INT PRIMARY KEY) 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 t2 VALUES(100);
+let $binlog_file= query_get_value(SHOW MASTER STATUS, File, 1);
+let $binlog_start= query_get_value(SHOW MASTER STATUS, Position, 1);
+
+--connect (con1,127.0.0.1,root,,test,$SERVER_MYPORT_1,)
+SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued1 WAIT_FOR master_cont1';
+send INSERT INTO t2 VALUES (1);
+
+--connection master
+SET debug_sync='now WAIT_FOR master_queued1';
+
+--connect (con2,127.0.0.1,root,,test,$SERVER_MYPORT_1,)
+SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued2';
+send INSERT INTO t2 VALUES (2);
+
+--connection master
+SET debug_sync='now WAIT_FOR master_queued2';
+SET debug_sync='now SIGNAL master_cont1';
+
+--connection con1
+REAP;
+SET debug_sync='RESET';
+--connection con2
+REAP;
+SET debug_sync='RESET';
+--connection master
+SET debug_sync='RESET';
+let $binlog_limit= 0, 10;
+--source include/show_binlog_events.inc
+--save_master_pos
+
+--connection slave
+--sync_with_master
+SELECT * FROM t2 ORDER BY a;
+
+
+--echo # Test that slave which cannot tolerate holes in binlog stream but
+--echo # knows the event does not get dummy event
+
+--source include/stop_slave.inc
+SET @@global.debug_dbug='+d,simulate_slave_capability_old_53';
+--source include/start_slave.inc
+connection master;
+ALTER TABLE t1 ORDER BY a;
+sync_slave_with_master;
+connection slave;
+let $relaylog_start= query_get_value(SHOW SLAVE STATUS, Relay_Log_Pos, 1);
+
+connection master;
+let $binlog_file= query_get_value(SHOW MASTER STATUS, File, 1);
+let $binlog_start= query_get_value(SHOW MASTER STATUS, Position, 1);
+UPDATE t1 SET a = 3;
+let $binlog_limit= 0, 5;
+--source include/show_binlog_events.inc
+sync_slave_with_master;
+connection slave;
+
+SELECT * FROM t1;
+let $binlog_file= query_get_value(SHOW SLAVE STATUS, Relay_Log_File, 1);
+let $binlog_start= $relaylog_start;
+let $binlog_limit=0,5;
+--source include/show_relaylog_events.inc
+
+select @@global.log_slave_updates;
+select @@global.replicate_annotate_row_events;
+
+--echo Clean up.
+connection master;
+set @@global.binlog_checksum = @old_master_binlog_checksum;
+DROP TABLE t1, t2;
+sync_slave_with_master;
+set @@global.debug_dbug= @old_dbug;
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_mark_optimize_tbl_ddl.test b/mysql-test/suite/rpl/t/rpl_mark_optimize_tbl_ddl.test
new file mode 100644
index 00000000..6d66e3fd
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_mark_optimize_tbl_ddl.test
@@ -0,0 +1,142 @@
+# ==== Purpose ====
+#
+# Test verifies that there is no deadlock or assertion in
+# slave_parallel_mode=optimistic configuration while applying admin command
+# like 'OPTIMIZE TABLE', 'REPAIR TABLE' and 'ANALYZE TABLE'.
+#
+# ==== Implementation ====
+#
+# Steps:
+# 0 - Create a table, execute OPTIMIZE TABLE command on the table followed
+# by some DMLS.
+# 1 - No assert should happen on slave server.
+# 2 - Assert that 'OPTIMIZE TABLE', 'REPAIR TABLE' and 'ANALYZE TABLE' are
+# marked as 'DDL' in the binary log.
+#
+# ==== References ====
+#
+# MDEV-17515: GTID Replication in optimistic mode deadlock
+#
+--source include/have_partition.inc
+--source include/have_innodb.inc
+--let $rpl_topology=1->2
+--source include/rpl_init.inc
+
+--connection server_1
+FLUSH TABLES;
+ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
+
+--connection server_2
+SET @save_slave_parallel_threads= @@GLOBAL.slave_parallel_threads;
+SET @save_slave_parallel_mode= @@GLOBAL.slave_parallel_mode;
+--source include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=2;
+SET GLOBAL slave_parallel_mode=optimistic;
+--source include/start_slave.inc
+
+--connection server_1
+CREATE TABLE t1(a INT) ENGINE=INNODB;
+OPTIMIZE TABLE t1;
+INSERT INTO t1 VALUES(1);
+INSERT INTO t1 SELECT 1+a FROM t1;
+INSERT INTO t1 SELECT 2+a FROM t1;
+--save_master_pos
+
+--connection server_2
+--sync_with_master
+
+--echo #
+--echo # Verify that following admin commands are marked as ddl
+--echo # 'OPTIMIZE TABLE', 'REPAIR TABLE' and 'ANALYZE TABLE'
+--echo #
+--connection server_1
+
+OPTIMIZE TABLE t1;
+--let optimize_gtid= `SELECT @@GLOBAL.gtid_binlog_pos`
+
+REPAIR TABLE t1;
+--let repair_gtid= `SELECT @@GLOBAL.gtid_binlog_pos`
+
+ANALYZE TABLE t1;
+--let analyze_gtid= `SELECT @@GLOBAL.gtid_binlog_pos`
+
+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= GTID $optimize_gtid ddl
+--let SEARCH_FILE= $MYSQLTEST_VARDIR/tmp/mysqlbinlog.out
+--source include/search_pattern_in_file.inc
+
+--let SEARCH_PATTERN= GTID $repair_gtid ddl
+--let SEARCH_FILE= $MYSQLTEST_VARDIR/tmp/mysqlbinlog.out
+--source include/search_pattern_in_file.inc
+
+--let SEARCH_PATTERN= GTID $analyze_gtid ddl
+--let SEARCH_FILE= $MYSQLTEST_VARDIR/tmp/mysqlbinlog.out
+--source include/search_pattern_in_file.inc
+
+--echo #
+--echo # Clean up
+--echo #
+DROP TABLE t1;
+--remove_file $MYSQLTEST_VARDIR/tmp/mysqlbinlog.out
+--save_master_pos
+
+--connection server_2
+--sync_with_master
+FLUSH LOGS;
+
+--echo #
+--echo # Check that ALTER TABLE commands with ANALYZE, OPTIMIZE and REPAIR on
+--echo # partitions will be marked as DDL in binary log.
+--echo #
+--connection server_1
+CREATE TABLE t1(id INT) PARTITION BY RANGE (id) (PARTITION p0 VALUES LESS THAN (100),
+ PARTITION pmax VALUES LESS THAN (MAXVALUE));
+INSERT INTO t1 VALUES (1), (10), (100), (1000);
+
+ALTER TABLE t1 ANALYZE PARTITION p0;
+--let analyze_gtid= `SELECT @@GLOBAL.gtid_binlog_pos`
+
+ALTER TABLE t1 OPTIMIZE PARTITION p0;
+--let optimize_gtid= `SELECT @@GLOBAL.gtid_binlog_pos`
+
+ALTER TABLE t1 REPAIR PARTITION p0;
+--let repair_gtid= `SELECT @@GLOBAL.gtid_binlog_pos`
+
+let $binlog_file= query_get_value(SHOW MASTER STATUS, File, 1);
+FLUSH LOGS;
+
+--exec $MYSQL_BINLOG $MYSQLD_DATADIR/$binlog_file > $MYSQLTEST_VARDIR/tmp/mysqlbinlog.out
+
+--let SEARCH_PATTERN= GTID $analyze_gtid ddl
+--let SEARCH_FILE= $MYSQLTEST_VARDIR/tmp/mysqlbinlog.out
+--source include/search_pattern_in_file.inc
+
+--let SEARCH_PATTERN= GTID $optimize_gtid ddl
+--let SEARCH_FILE= $MYSQLTEST_VARDIR/tmp/mysqlbinlog.out
+--source include/search_pattern_in_file.inc
+
+--let SEARCH_PATTERN= GTID $repair_gtid ddl
+--let SEARCH_FILE= $MYSQLTEST_VARDIR/tmp/mysqlbinlog.out
+--source include/search_pattern_in_file.inc
+
+--echo #
+--echo # Clean up
+--echo #
+DROP TABLE t1;
+--remove_file $MYSQLTEST_VARDIR/tmp/mysqlbinlog.out
+--save_master_pos
+
+--connection server_2
+--sync_with_master
+
+--source include/stop_slave.inc
+SET GLOBAL slave_parallel_threads= @save_slave_parallel_threads;
+SET GLOBAL slave_parallel_mode= @save_slave_parallel_mode;
+--source include/start_slave.inc
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_master_pos_wait.test b/mysql-test/suite/rpl/t/rpl_master_pos_wait.test
new file mode 100644
index 00000000..437d8412
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_master_pos_wait.test
@@ -0,0 +1,79 @@
+# See if master_pos_wait(,,timeout)
+# Terminates with "timeout expired" (-1)
+source include/master-slave.inc;
+sync_slave_with_master;
+# Ask for a master log that has certainly not been reached yet
+# timeout= 2 seconds
+select master_pos_wait('master-bin.999999',0,2);
+explain extended select master_pos_wait('master-bin.999999',0,2);
+# Testcase for bug 651 (master_pos_wait() hangs if slave idle and STOP SLAVE).
+send select master_pos_wait('master-bin.999999',0);
+connection slave1;
+stop slave sql_thread;
+--source include/wait_for_slave_sql_to_stop.inc
+connection slave;
+reap;
+
+#
+# bug#26622 MASTER_POS_WAIT does not work as documented
+#
+
+connection master;
+echo "*** must be empty ***";
+query_vertical show slave status;
+
+echo "*** must be NULL ***";
+select master_pos_wait('foo', 98);
+
+# End of 4.1 tests
+
+
+--echo *** MDEV-7130: MASTER_POS_WAIT(log_name,log_pos,timeout,"connection_name") hangs, does not respect the timeout ***
+
+--connection slave
+--source include/stop_slave.inc
+reset slave all;
+--replace_result $MASTER_MYPORT MASTER_MYPORT
+eval change master 'my_slave' to master_port=$MASTER_MYPORT, master_host='127.0.0.1', master_user='root';
+set default_master_connection = 'my_slave';
+--source include/start_slave.inc
+
+--echo # Call without connection name -- works (expected -1)
+select master_pos_wait('master-bin.000001',1000000,1);
+
+set default_master_connection = '';
+
+--echo # Call for non-existing anonymous connection -- works (expected NULL)
+select master_pos_wait('master-bin.000001',1000000,1);
+
+--echo # Call with a valid connection name -- hangs before MDEV-7130 fix (expected -1)
+select master_pos_wait('master-bin.000001',1000000,1,"my_slave");
+
+STOP SLAVE 'my_slave';
+RESET SLAVE 'my_slave' ALL;
+
+--replace_result $MASTER_MYPORT MASTER_MYPORT
+eval change master to master_port=$MASTER_MYPORT, master_host='127.0.0.1', master_user='root';
+
+# End of 10.0 tests
+
+--echo #
+--echo # Start of 10.3 tests
+--echo #
+
+--echo #
+--echo # MDEV-13965 Parameter data type control for Item_longlong_func
+--echo #
+
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT MASTER_POS_WAIT('x',1,ROW(1,1));
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT MASTER_POS_WAIT('x',1,1,ROW(1,1));
+
+--echo #
+--echo # End of 10.3 tests
+--echo #
+
+
+--let $rpl_only_running_threads= 1
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_mdev-11092.opt b/mysql-test/suite/rpl/t/rpl_mdev-11092.opt
new file mode 100644
index 00000000..7f1d270d
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_mdev-11092.opt
@@ -0,0 +1 @@
+--binlog_checksum=1 --binlog-annotate-row-events=1
diff --git a/mysql-test/suite/rpl/t/rpl_mdev-11092.test b/mysql-test/suite/rpl/t/rpl_mdev-11092.test
new file mode 100644
index 00000000..fa8a685b
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_mdev-11092.test
@@ -0,0 +1,543 @@
+--source include/have_debug.inc
+--source include/have_innodb.inc
+--source include/not_embedded.inc
+--source include/not_windows.inc
+--source include/have_binlog_format_row.inc
+--source include/master-slave.inc
+
+########################################################################################
+call mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT");
+call mtr.add_suppression("Slave SQL: The incident LOST_EVENTS occurred on the master. .*");
+call mtr.add_suppression("Write to binary log failed: Multi-row statements required more than .max_binlog_stmt_cache_size.* ");
+call mtr.add_suppression("Write to binary log failed: Multi-statement transaction required more than .max_binlog_cache_size.* ");
+call mtr.add_suppression("Incident event write to the binary log file failed");
+call mtr.add_suppression("handlerton rollback failed");
+
+let $old_max_binlog_cache_size= query_get_value(SHOW VARIABLES LIKE "max_binlog_cache_size", Value, 1);
+let $old_binlog_cache_size= query_get_value(SHOW VARIABLES LIKE "binlog_cache_size", Value, 1);
+let $old_max_binlog_stmt_cache_size= query_get_value(SHOW VARIABLES LIKE "max_binlog_stmt_cache_size", Value, 1);
+let $old_binlog_stmt_cache_size= query_get_value(SHOW VARIABLES LIKE "binlog_stmt_cache_size", Value, 1);
+
+--echo "*********** Annotate Event write failure **************"
+
+SET GLOBAL max_binlog_cache_size = 4096;
+SET GLOBAL binlog_cache_size = 4096;
+SET GLOBAL max_binlog_stmt_cache_size = 4096;
+SET GLOBAL binlog_stmt_cache_size = 4096;
+disconnect master;
+connect (master,127.0.0.1,root,,test,$MASTER_MYPORT,);
+
+CREATE TABLE t1(a INT PRIMARY KEY, data VARCHAR(30000)) ENGINE=MYISAM;
+
+let $data = `select concat('"', repeat('a',2000), '"')`;
+
+connection master;
+
+# Insert a huge row into MyISAM table. The row will be inserted in engine and a
+# request to write to binary log will be initiated. Since row annotations are
+# enabled the size of the annotate event itself will exceed the
+# "max_binlog_stmt_cache_size". This will result in ER_STMT_CACHE_FULL error
+# and an incident event will be written to the binary log as row update in
+# engine cannot be undone.
+
+--echo "#######################################################################"
+--echo "# Test Case1: Annotate event write failure for MyISAM #"
+--echo "#######################################################################"
+
+--disable_query_log
+--let $old_gtid_binlog_pos= query_get_value(SHOW VARIABLES LIKE 'gtid_binlog_pos', Value, 1)
+--error ER_STMT_CACHE_FULL
+eval INSERT INTO t1 (a, data) VALUES (2,
+ CONCAT($data, $data, $data, $data, $data, $data));
+--enable_query_log
+
+--let $new_gtid_binlog_pos= query_get_value(SHOW VARIABLES LIKE 'gtid_binlog_pos', Value, 1)
+--echo # Validating update was not binlogged..
+if(`SELECT strcmp("$old_gtid_binlog_pos","$new_gtid_binlog_pos") != 0`)
+{
+ --die Binlog GTID position should have been unchanged after failed update
+}
+--echo # ..success
+
+--echo # Validating that the inserted data was saved on the master..
+if(`SELECT COUNT(*)!=1 FROM t1`)
+{
+ --die The insertion should have saved on a non-transactional table
+}
+--echo # ..success
+
+--connection slave
+# Incident event
+# 1590=ER_SLAVE_INCIDENT
+--let $slave_sql_errno= 1590
+--source include/wait_for_slave_sql_error_and_skip.inc
+
+--echo # Validating that the insert was not replicated to the slave..
+if(`SELECT COUNT(*) FROM t1`)
+{
+ --die The insertion should not have replicated to the slave
+}
+--echo # ..success
+
+# MDEV-21087
+# Insert two huge rows in to transaction cache. Have data such that first row
+# fits inside the binary log cache. While writing the annotate event for the
+# second row the binary log cache size will exceed "max_binlog_cache_size".
+# Hence this statement cannot be written to binary log. As DMLs in Innodb can
+# be safely rolled back only an error will be reported. Slave will continue to
+# work.
+
+--echo "#######################################################################"
+--echo "# Test Case2: Annotate event write failure for INNODB #"
+--echo "#######################################################################"
+
+--connection master
+CREATE TABLE t2(a INT PRIMARY KEY, data VARCHAR(30000)) ENGINE=INNODB;
+--disable_query_log
+--let $old_gtid_binlog_pos= query_get_value(SHOW VARIABLES LIKE 'gtid_binlog_pos', Value, 1)
+BEGIN;
+eval INSERT INTO t2 (a, data) VALUES (1, CONCAT($data, $data));
+--error ER_TRANS_CACHE_FULL
+eval INSERT INTO t2 (a, data) VALUES (2, CONCAT($data, $data));
+COMMIT;
+--enable_query_log
+
+--let $new_gtid_binlog_pos= query_get_value(SHOW VARIABLES LIKE 'gtid_binlog_pos', Value, 1)
+--echo # Validating binlog GTID position progressed from first insert..
+if(`SELECT strcmp("$old_gtid_binlog_pos","$new_gtid_binlog_pos") = 0`)
+{
+ --die Binlog GTID position should have updated
+}
+--echo # ..success
+
+--echo # Validating that only the first insert into t2 saved..
+if(`SELECT COUNT(*)!=1 FROM t2`)
+{
+ --die Only one row should exist in t2 from the first insert, the second should have rolled back
+}
+--echo # ..success
+--source include/save_master_gtid.inc
+
+--connection slave
+--source include/sync_with_master_gtid.inc
+--echo # Validating the first insert into t2 replicated to slave..
+--let $diff_tables= master:test.t2,slave:test.t2
+--source include/diff_tables.inc
+--echo # ..success
+
+# Testing mixed engine UPDATE statement scenario. In the following multi
+# update query 'ha_update_row' will be invoked for t1 (myisam) table. This
+# intern invokes binlog_write_table_map() function call. While writing a huge
+# annotate event binary log cache size will exceed max_binlog_cache_size.
+# Writing to binary log fails. Since non transactional changes cannot be
+# rolled back incident event will be written to binary log.
+
+--echo "#######################################################################"
+--echo "# Test Case3: Annotate event write failure for mixed engine UPDATE #"
+--echo "#######################################################################"
+
+--connection master
+let $new_data = `select concat('"', repeat('b',2000), '"')`;
+--let $old_gtid_binlog_pos= query_get_value(SHOW VARIABLES LIKE 'gtid_binlog_pos', Value, 1)
+--disable_query_log
+--error ER_STMT_CACHE_FULL
+eval UPDATE t1,t2 SET t1.data="Hello", t2.data=CONCAT($new_data,$new_data,$new_data,$new_data,$new_data);
+--enable_query_log
+
+--let $new_gtid_binlog_pos= query_get_value(SHOW VARIABLES LIKE 'gtid_binlog_pos', Value, 1)
+--echo # Validating update was not binlogged..
+if(`SELECT strcmp("$old_gtid_binlog_pos","$new_gtid_binlog_pos") != 0`)
+{
+ --die Binlog GTID position should have been unchanged after failed update
+}
+--echo # ..success
+
+--echo # Validating non-transactional part of update saved..
+if(`SELECT COUNT(*)!=1 from t1 where data="Hello"`)
+{
+ --die Non-transactional part of update should have saved
+}
+--echo # ..success
+
+--echo # Validating transactional part of update was rolled back..
+if(`SELECT COUNT(*) from t2 where data LIKE "b%"`)
+{
+ --die Transactional part of update should have been rolled back
+}
+--echo # ..success
+
+--source include/save_master_gtid.inc
+
+--connection slave
+
+# Incident event
+# 1590=ER_SLAVE_INCIDENT
+--let $slave_sql_errno= 1590
+--source include/wait_for_slave_sql_error_and_skip.inc
+
+--echo # Validating the rolled-back multi-engine update did not replicate to slave at all..
+if(`SELECT COUNT(*) from t1 where data="Hello"`)
+{
+ --die Non-transactional part of update should not have replicated
+}
+if(`SELECT COUNT(*) from t2 where data LIKE "b%"`)
+{
+ --die Transactional part of update should not have replicated
+}
+--echo # ..success
+
+--connection master
+
+--echo "****** Clean up *******"
+--replace_result $old_max_binlog_cache_size ORIGINAL_VALUE
+--eval SET GLOBAL max_binlog_cache_size= $old_max_binlog_cache_size
+--replace_result $old_binlog_cache_size ORIGINAL_VALUE
+--eval SET GLOBAL binlog_cache_size= $old_binlog_cache_size
+--replace_result $old_max_binlog_stmt_cache_size ORIGINAL_VALUE
+--eval SET GLOBAL max_binlog_stmt_cache_size= $old_max_binlog_stmt_cache_size
+--replace_result $old_binlog_stmt_cache_size ORIGINAL_VALUE
+--eval SET GLOBAL binlog_stmt_cache_size= $old_binlog_stmt_cache_size
+
+DROP TABLE t1,t2;
+
+--echo "*********** TABLE MAP Event write failure **************"
+
+--let $debug_save= `SELECT @@GLOBAL.debug_dbug`
+CREATE TABLE tm (f INT) ENGINE=MYISAM;
+CREATE TABLE ti (f INT) ENGINE=INNODB;
+INSERT INTO tm VALUES (10);
+INSERT INTO ti VALUES (20);
+--sync_slave_with_master
+
+--echo "#######################################################################"
+--echo "# Test Case4: Table_map event write failure for trans engine UPDATE #"
+--echo "#######################################################################"
+--echo # Transaction should be rolled back without writing incident event
+--connection master
+--let $old_gtid_binlog_pos= query_get_value(SHOW VARIABLES LIKE 'gtid_binlog_pos', Value, 1)
+SET debug_dbug="+d,table_map_write_error";
+--error ER_TRANS_CACHE_FULL
+UPDATE ti, tm set ti.f=30;
+
+--let $new_gtid_binlog_pos= query_get_value(SHOW VARIABLES LIKE 'gtid_binlog_pos', Value, 1)
+--echo # Validating update was not binlogged..
+if(`SELECT strcmp("$old_gtid_binlog_pos","$new_gtid_binlog_pos") != 0`)
+{
+ --die Binlog GTID position should have been unchanged after failed update
+}
+--echo # ..success
+
+--echo # Validating update was rolled back from storage engines..
+if(`SELECT COUNT(*) FROM ti WHERE f=130`)
+{
+ --die Update for InnoDB table should not have saved
+}
+--echo # ..success
+
+--source include/save_master_gtid.inc
+
+--connection slave
+--source include/sync_with_master_gtid.inc
+
+--echo "#######################################################################"
+--echo "# Test Case5: Table_map event write failure for mixed engine UPDATE #"
+--echo "#######################################################################"
+--connection master
+--let $old_gtid_binlog_pos= query_get_value(SHOW VARIABLES LIKE 'gtid_binlog_pos', Value, 1)
+--echo # In case of mixed engines if non trans table is updated write INCIDENT event
+--error ER_TRANS_CACHE_FULL
+UPDATE ti,tm SET tm.f=88, ti.f=120;
+
+--let $new_gtid_binlog_pos= query_get_value(SHOW VARIABLES LIKE 'gtid_binlog_pos', Value, 1)
+--echo # Validating update was not binlogged..
+if(`SELECT strcmp("$old_gtid_binlog_pos","$new_gtid_binlog_pos") != 0`)
+{
+ --die Binlog GTID position should have been unchanged after failed update
+}
+--echo # ..success
+
+--echo # Validating that only the non-transactional update saved on master..
+if(`SELECT COUNT(*)!=1 FROM tm WHERE f=88`)
+{
+ --die Update for MyISAM table should have saved
+}
+if(`SELECT COUNT(*) FROM ti WHERE f=120`)
+{
+ --die Update for InnoDB table should not have saved
+}
+--echo # ..success
+
+
+--connection slave
+# Incident event
+# 1590=ER_SLAVE_INCIDENT
+--let $slave_sql_errno= 1590
+--source include/wait_for_slave_sql_error_and_skip.inc
+
+--echo # Validating that neither of the updates replicated to slave..
+if(`SELECT COUNT(*) FROM tm WHERE f=88`)
+{
+ --die Update for MyISAM table should not have replicated to slave
+}
+if(`SELECT COUNT(*) FROM ti WHERE f=120`)
+{
+ --die Update for InnoDB table should not have replicated to slave
+}
+--echo # ..success
+
+--echo "#######################################################################"
+--echo "# Test Case6: Committing a transaction consisting of two updates:
+--echo "# S1) Update transactional table
+--echo "# S2) Update transactional table
+--echo "# with a table_map event write failure on the second event should
+--echo "# roll-back only the second update without incident
+--echo "#######################################################################"
+--connection master
+--let $old_gtid_binlog_pos= query_get_value(SHOW VARIABLES LIKE 'gtid_binlog_pos', Value, 1)
+
+SET debug_dbug="";
+BEGIN;
+# successful update
+UPDATE ti, tm set ti.f=40;
+SET debug_dbug="+d,table_map_write_error";
+--error ER_TRANS_CACHE_FULL
+UPDATE ti, tm set ti.f=50;
+COMMIT;
+
+--let $new_gtid_binlog_pos= query_get_value(SHOW VARIABLES LIKE 'gtid_binlog_pos', Value, 1)
+--echo # Validating binlog GTID position progressed from first update..
+if(`SELECT strcmp("$old_gtid_binlog_pos","$new_gtid_binlog_pos") = 0`)
+{
+ --die Binlog GTID position should have updated
+}
+--echo # ..success
+
+--echo # Validating the first update saved..
+if(`SELECT COUNT(*)!=1 FROM ti WHERE f=40`)
+{
+ --die The first update should have saved because it was transactional
+}
+--echo # ..and that the second update did not save..
+if(`SELECT COUNT(*) FROM ti WHERE f=50`)
+{
+ --die The second update should have rolled back because it failed
+}
+--echo # ..success
+
+--echo # Validating that only the first update replicated to slave without incident
+--connection master
+--source include/save_master_gtid.inc
+--connection slave
+--source include/sync_with_master_gtid.inc
+--let $diff_tables= master:test.ti,slave:test.ti
+--source include/diff_tables.inc
+
+
+--echo "#######################################################################"
+--echo "# Test Case7: Rolling back a transaction consisting of two updates:
+--echo "# S1) Update transactional table
+--echo "# S2) Update transactional table
+--echo "# with a table_map event write failure on the second event should
+--echo "# roll-back both updates without incident
+--echo "#######################################################################"
+--connection master
+--let $old_gtid_binlog_pos= query_get_value(SHOW VARIABLES LIKE 'gtid_binlog_pos', Value, 1)
+
+SET debug_dbug="";
+BEGIN;
+# successful update
+UPDATE ti, tm set ti.f=60;
+SET debug_dbug="+d,table_map_write_error";
+--error ER_TRANS_CACHE_FULL
+UPDATE ti, tm set ti.f=70;
+ROLLBACK;
+
+--let $new_gtid_binlog_pos= query_get_value(SHOW VARIABLES LIKE 'gtid_binlog_pos', Value, 1)
+--echo # Validating update was not binlogged..
+if(`SELECT strcmp("$old_gtid_binlog_pos","$new_gtid_binlog_pos") != 0`)
+{
+ --die Binlog GTID position should have been unchanged after failed update
+}
+--echo # ..success
+
+--echo # Validating that neither update saved on master..
+if(`SELECT COUNT(*) FROM ti WHERE f=60`)
+{
+ --die The first update should not have saved
+}
+if(`SELECT COUNT(*) FROM ti WHERE f=70`)
+{
+ --die The second update should not have saved
+}
+--echo # ..success
+
+--echo # Validating the transaction did not replicate to the slave
+--connection master
+--source include/save_master_gtid.inc
+
+--connection slave
+--source include/sync_with_master_gtid.inc
+--let $diff_tables= master:test.ti,slave:test.ti
+--source include/diff_tables.inc
+
+
+--echo "#######################################################################"
+--echo "# Test Case8: Committing a transaction consisting of two updates:
+--echo "# S1) Update transactional table
+--echo "# S2) Update mixed trans/non-trans tables
+--echo "# with a table_map event write failure on the second event should
+--echo "# roll-back only the second update with incident
+--echo "#######################################################################"
+--connection master
+--let $old_gtid_binlog_pos= query_get_value(SHOW VARIABLES LIKE 'gtid_binlog_pos', Value, 1)
+
+BEGIN;
+# successful update
+SET debug_dbug="";
+UPDATE ti, tm set ti.f=80;
+SET debug_dbug="+d,table_map_write_error";
+--error ER_TRANS_CACHE_FULL
+UPDATE ti, tm set ti.f=90,tm.f=99;
+COMMIT;
+
+--let $new_gtid_binlog_pos= query_get_value(SHOW VARIABLES LIKE 'gtid_binlog_pos', Value, 1)
+--echo # Validating binlog GTID position progressed from first update..
+if(`SELECT strcmp("$old_gtid_binlog_pos","$new_gtid_binlog_pos") = 0`)
+{
+ --die Binlog GTID position should have updated
+}
+--echo # ..success
+
+--echo # Validating the first update saved..
+if(`SELECT COUNT(*)!=1 FROM ti WHERE f=80`)
+{
+ --die The first update should have saved because it was transactional
+}
+--echo # ..and the transactional part of the second update did not save..
+if(`SELECT COUNT(*) FROM ti WHERE f=90`)
+{
+ --die The transactional part of the second update should have rolled back because it failed
+}
+--echo # ..whereas the non-trans part of the second update did save..
+if(`SELECT COUNT(*)!=1 FROM tm WHERE f=99`)
+{
+ --die The non-trans part from the second update should have saved
+}
+--echo # ..success
+
+--echo # Validating that the incident propagated to the slave
+--connection slave
+# Incident event
+# 1590=ER_SLAVE_INCIDENT
+--let $slave_sql_errno= 1590
+--source include/wait_for_slave_sql_error_and_skip.inc
+
+--echo # Validating that the first update replicated to the slave..
+if(`SELECT COUNT(*)!=1 FROM ti WHERE f=80`)
+{
+ --die The first update should have replicated because it was transactional
+}
+--echo # ..and neither part of the second update replicated..
+if(`SELECT COUNT(*) FROM ti WHERE f=90`)
+{
+ --die The trans part from the second update should not have replicated because it was rolled back
+}
+if(`SELECT COUNT(*) FROM tm WHERE f=99`)
+{
+ --die The non-trans part from the second update should not have replicated because it was not binlogged
+}
+--echo # ..success
+
+
+--echo "#######################################################################"
+--echo "# Test Case9: Rolling back a transaction consisting of two updates:
+--echo "# S1) Update transactional table
+--echo "# S2) Update mixed trans/non-trans tables
+--echo "# with a table_map event write failure on the second event should
+--echo "# roll-back both transactional updates, preserve the non-transactional
+--echo "# update on the master (only), and write an incident event
+--echo "#######################################################################"
+--connection master
+--let $old_gtid_binlog_pos= query_get_value(SHOW VARIABLES LIKE 'gtid_binlog_pos', Value, 1)
+
+SET debug_dbug="";
+BEGIN;
+# successful update
+UPDATE ti, tm set ti.f=100;
+SET debug_dbug="+d,table_map_write_error";
+--error ER_TRANS_CACHE_FULL
+UPDATE ti, tm set ti.f=110,tm.f=111;
+ROLLBACK;
+
+--let $new_gtid_binlog_pos= query_get_value(SHOW VARIABLES LIKE 'gtid_binlog_pos', Value, 1)
+--echo # Validating update was not binlogged..
+if(`SELECT strcmp("$old_gtid_binlog_pos","$new_gtid_binlog_pos") != 0`)
+{
+ --die Binlog GTID position should have been unchanged after failed update
+}
+--echo # ..success
+
+--echo # Validating trans updates rollback, but the non-trans update stays..
+if(`SELECT COUNT(*) FROM ti WHERE f=100`)
+{
+ --die The first update should not have saved
+}
+if(`SELECT COUNT(*) FROM ti WHERE f=110`)
+{
+ --die The transactional part of the second update should not have saved
+}
+if(`SELECT COUNT(*)!=1 FROM tm WHERE f=111`)
+{
+ --die The non-trans part of the second update should have saved
+}
+--echo # ..success
+
+--echo # Validating that the incident propagated to the slave
+--connection slave
+# Incident event
+# 1590=ER_SLAVE_INCIDENT
+--let $slave_sql_errno= 1590
+--source include/wait_for_slave_sql_error_and_skip.inc
+
+--echo # Validating that none of the updates replicated to the slave
+--let $diff_tables= master:test.ti,slave:test.ti
+--source include/diff_tables.inc
+if(`SELECT COUNT(*) FROM tm WHERE f=111`)
+{
+ --die The non-trans part from the second update should not have replicated because it was not binlogged
+}
+--echo # ..success
+
+
+--echo "#######################################################################"
+--echo "# Test Case10: If an incident event fails to write, a specific error
+--echo "# should be logged
+--echo "#
+--echo "# Note: This test case is the same as test case 5, with the caveat of
+--echo "# the incident event failing to write.
+--echo "#######################################################################"
+
+--connection master
+SET debug_dbug="d,table_map_write_error,incident_event_write_error";
+--error ER_TRANS_CACHE_FULL
+UPDATE ti, tm set ti.f=120, tm.f=122;
+
+--echo # Validate error message indicating incident event failed to write
+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_PATTERN= Incident event write to the binary log file failed
+--let SEARCH_FILE= $log_error_
+--source include/search_pattern_in_file.inc
+
+
+--connection master
+--echo "******** Clean Up **********"
+--eval SET GLOBAL debug_dbug = '$debug_save'
+DROP TABLE tm,ti;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_mdev10863.test b/mysql-test/suite/rpl/t/rpl_mdev10863.test
new file mode 100644
index 00000000..73062df8
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_mdev10863.test
@@ -0,0 +1,105 @@
+--source include/have_innodb.inc
+--let $rpl_topology=1->2
+--source include/rpl_init.inc
+
+# Test various aspects of parallel replication.
+
+--connection server_2
+SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads;
+--source include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=10;
+SET @old_max_relay= @@GLOBAL.max_relay_log_size;
+SET GLOBAL max_relay_log_size = 4096;
+CHANGE MASTER TO master_use_gtid=slave_pos;
+--source include/start_slave.inc
+
+--connection server_1
+ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
+CREATE TABLE t1 (a int PRIMARY KEY, b VARCHAR(100)) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1, "a");
+--save_master_pos
+
+--connection server_2
+--sync_with_master
+
+--echo *** Create a long transaction that will span a relay log file. ***
+--connection server_1
+
+# Add some transactions in separate domains, that will cause the need to
+# have a multi-valued restart position in the relay log for the SQL thread.
+SET @old_domain= @@gtid_domain_id;
+SET gtid_domain_id=10;
+INSERT INTO t1 VALUES (10000, "domain 10");
+SET gtid_domain_id=20;
+INSERT INTO t1 VALUES (20000, "domain 20");
+SET gtid_domain_id=@old_domain;
+
+BEGIN;
+--echo [lots of inserts omitted]
+--disable_query_log
+--let $count = 500
+while ($count) {
+ eval INSERT INTO t1 VALUES (1000+$count, REPEAT("hulubulu??!?", 8));
+ dec $count;
+}
+--enable_query_log
+COMMIT;
+
+--save_master_pos
+
+--connection server_2
+--sync_with_master
+
+--connection server_1
+# Now do another one, to make the inuse_relaylog proceed to somewhere inside
+# the first large transaction.
+
+BEGIN;
+--echo [lots of inserts omitted]
+--disable_query_log
+--let $count = 500
+while ($count) {
+ eval INSERT INTO t1 VALUES (2000+$count, REPEAT("hulubulu??!?", 8));
+ dec $count;
+}
+--enable_query_log
+COMMIT;
+
+--save_master_pos
+
+--connection server_2
+--sync_with_master
+
+
+# Stop and restart the SQL thread only.
+# The bug was that the SQL thread would restart at the start
+# of a relay log file, which could be in the middle of an event group.
+# This way, part of that event group could be wrongly re-applied.
+
+--source include/stop_slave_sql.inc
+START SLAVE SQL_THREAD;
+--source include/wait_for_slave_to_start.inc
+
+
+--connection server_1
+INSERT INTO t1 VALUES (100000, "More stuffs.");
+INSERT INTO t1 VALUES (100001, "And even more");
+--save_master_pos
+
+--connection server_2
+--sync_with_master
+SELECT * FROM t1 WHERE a >= 100000 ORDER BY a;
+
+
+# Clean up.
+--connection server_2
+--source include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=@old_parallel_threads;
+SET GLOBAL max_relay_log_size= @old_max_relay;
+--source include/start_slave.inc
+
+--connection server_1
+ALTER TABLE mysql.gtid_slave_pos ENGINE=Aria;
+DROP TABLE t1;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_mdev12179.test b/mysql-test/suite/rpl/t/rpl_mdev12179.test
new file mode 100644
index 00000000..aa0d0521
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_mdev12179.test
@@ -0,0 +1,319 @@
+--source include/no_valgrind_without_big.inc
+--source include/have_innodb.inc
+--let $rpl_topology=1->2
+--source include/rpl_init.inc
+
+--connection server_2
+call mtr.add_suppression("The automatically created table.*name may not be entirely in lowercase");
+
+--error ER_SLAVE_MUST_STOP
+SET GLOBAL gtid_pos_auto_engines="innodb";
+--source include/stop_slave.inc
+CHANGE MASTER TO master_use_gtid=slave_pos;
+
+# Test the @@gtid_pos_auto_engines sysvar.
+SELECT @@gtid_pos_auto_engines;
+--error ER_INCORRECT_GLOBAL_LOCAL_VAR
+SELECT @@SESSION.gtid_pos_auto_engines;
+--error ER_WRONG_VALUE_FOR_VAR
+SET GLOBAL gtid_pos_auto_engines= NULL;
+SET GLOBAL gtid_pos_auto_engines="innodb";
+SELECT @@gtid_pos_auto_engines;
+SET GLOBAL gtid_pos_auto_engines="myisam,innodb";
+SELECT @@gtid_pos_auto_engines;
+SET GLOBAL gtid_pos_auto_engines="innodb,myisam";
+SELECT @@gtid_pos_auto_engines;
+SET GLOBAL gtid_pos_auto_engines="innodb,innodb,myisam,innodb,myisam,myisam,innodb";
+SELECT @@gtid_pos_auto_engines;
+SET GLOBAL gtid_pos_auto_engines=DEFAULT;
+SELECT @@gtid_pos_auto_engines;
+SET GLOBAL gtid_pos_auto_engines="";
+SELECT @@gtid_pos_auto_engines;
+
+--source include/start_slave.inc
+
+--connection server_1
+CREATE TABLE t1 (a INT PRIMARY KEY);
+INSERT INTO t1 VALUES (1);
+SELECT * FROM t1 ORDER BY a;
+--save_master_pos
+
+--connection server_2
+--sync_with_master
+SELECT * FROM t1 ORDER BY a;
+--source include/stop_slave.inc
+SET sql_log_bin=0;
+# Reset storage engine for mysql.gtid_slave_pos in case an earlier test
+# might have changed it to InnoDB.
+ALTER TABLE mysql.gtid_slave_pos ENGINE=Aria;
+CREATE TABLE mysql.gtid_slave_pos_innodb LIKE mysql.gtid_slave_pos;
+ALTER TABLE mysql.gtid_slave_pos_innodb ENGINE=InnoDB;
+INSERT INTO mysql.gtid_slave_pos_innodb SELECT * FROM mysql.gtid_slave_pos;
+TRUNCATE mysql.gtid_slave_pos;
+SET sql_log_bin=1;
+
+# Restart the slave mysqld server, and verify that the GTID position is
+# read correctly from the new mysql.gtid_slave_pos_innodb table.
+
+--write_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect
+wait
+EOF
+--shutdown_server
+--source include/wait_until_disconnected.inc
+
+--connection server_1
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+SELECT * FROM t1 ORDER BY a;
+--source include/save_master_gtid.inc
+
+# Let the slave mysqld server start again.
+# As we are restarting, also take the opportunity to test --gtid-pos-auto-engines
+--echo *** Restart server with --gtid-pos-auto-engines=innodb,myisam ***
+--append_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect
+restart: --skip-slave-start=0 --gtid-pos-auto-engines=innodb,myisam
+EOF
+
+--connection server_2
+--enable_reconnect
+--source include/wait_until_connected_again.inc
+
+--source include/sync_with_master_gtid.inc
+SELECT * FROM t1 ORDER BY a;
+
+--echo *** Verify no new gtid_slave_pos* tables are created ***
+SELECT table_name, engine FROM information_schema.tables
+ WHERE table_schema='mysql' AND table_name LIKE 'gtid_slave_pos%'
+ ORDER BY table_name;
+
+SELECT @@gtid_pos_auto_engines;
+--source include/stop_slave.inc
+SET sql_log_bin=0;
+INSERT INTO mysql.gtid_slave_pos_innodb SELECT * FROM mysql.gtid_slave_pos;
+DROP TABLE mysql.gtid_slave_pos;
+RENAME TABLE mysql.gtid_slave_pos_innodb TO mysql.gtid_slave_pos;
+SET sql_log_bin=1;
+
+--write_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect
+wait
+EOF
+--shutdown_server
+--source include/wait_until_disconnected.inc
+
+--connection server_1
+CREATE TABLE t2 (a INT PRIMARY KEY) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (4);
+INSERT INTO t2 VALUES (1);
+SELECT * FROM t1 ORDER BY a;
+SELECT * FROM t2 ORDER BY a;
+--source include/save_master_gtid.inc
+
+--echo *** Restart server with --gtid-pos-auto-engines=myisam,innodb ***
+--append_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect
+restart: --skip-slave-start=0 --gtid-pos-auto-engines=myisam,innodb
+EOF
+
+--connection server_2
+--enable_reconnect
+--source include/wait_until_connected_again.inc
+
+--source include/sync_with_master_gtid.inc
+SELECT * FROM t1 ORDER BY a;
+SELECT * FROM t2 ORDER BY a;
+
+--echo *** Verify that no new gtid_slave_pos* tables are auto-created ***
+SELECT table_name, engine FROM information_schema.tables
+ WHERE table_schema='mysql' AND table_name LIKE 'gtid_slave_pos%'
+ ORDER BY table_name;
+
+
+--source include/stop_slave.inc
+SET sql_log_bin=0;
+ALTER TABLE mysql.gtid_slave_pos ENGINE=Aria;
+SET sql_log_bin=1;
+
+--write_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect
+wait
+EOF
+--shutdown_server
+--source include/wait_until_disconnected.inc
+
+--connection server_1
+INSERT INTO t1 VALUES (5);
+INSERT INTO t2 VALUES (2);
+SELECT * FROM t1 ORDER BY a;
+SELECT * FROM t2 ORDER BY a;
+--source include/save_master_gtid.inc
+
+--append_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect
+--echo *** Restart server with --gtid-pos-auto-engines=innodb ***
+restart: --skip-slave-start=0 --gtid-pos-auto-engines=innodb
+EOF
+
+--connection server_2
+--enable_reconnect
+--source include/wait_until_connected_again.inc
+
+--source include/sync_with_master_gtid.inc
+SELECT * FROM t1 ORDER BY a;
+SELECT * FROM t2 ORDER BY a;
+
+--echo *** Verify that mysql.gtid_slave_pos_InnoDB is auto-created ***
+# Note, the create happens asynchronously, so wait for it.
+let $wait_condition=
+ SELECT EXISTS (SELECT * FROM information_schema.tables
+ WHERE table_schema='mysql' AND table_name='gtid_slave_pos_InnoDB');
+--source include/wait_condition.inc
+# MDEV-15373 lowercases 'table_name' to satisfy --lower-case-table-names options
+SELECT lower(table_name), engine FROM information_schema.tables
+ WHERE table_schema='mysql' AND table_name LIKE 'gtid_slave_pos%'
+ ORDER BY table_name;
+
+
+--source include/stop_slave.inc
+SET sql_log_bin=0;
+INSERT INTO mysql.gtid_slave_pos SELECT * FROM mysql.gtid_slave_pos_InnoDB;
+DROP TABLE mysql.gtid_slave_pos_InnoDB;
+SET sql_log_bin=1;
+
+--write_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect
+wait
+EOF
+--shutdown_server
+--source include/wait_until_disconnected.inc
+
+--connection server_1
+INSERT INTO t1 VALUES (6);
+INSERT INTO t2 VALUES (3);
+SELECT * FROM t1 ORDER BY a;
+SELECT * FROM t2 ORDER BY a;
+--source include/save_master_gtid.inc
+
+--echo *** Restart server without --gtid-pos-auto-engines ***
+--append_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect
+restart: --skip-slave-start=0
+EOF
+
+--connection server_2
+--enable_reconnect
+--source include/wait_until_connected_again.inc
+
+--source include/sync_with_master_gtid.inc
+SELECT * FROM t1 ORDER BY a;
+SELECT * FROM t2 ORDER BY a;
+
+--echo *** Verify that no mysql.gtid_slave_pos* table is auto-created ***
+SELECT table_name, engine FROM information_schema.tables
+ WHERE table_schema='mysql' AND table_name LIKE 'gtid_slave_pos%'
+ ORDER BY table_name;
+SELECT domain_id, max(seq_no) FROM mysql.gtid_slave_pos GROUP BY domain_id;
+
+--source include/stop_slave.inc
+SET GLOBAL gtid_pos_auto_engines="innodb";
+--source include/start_slave.inc
+
+--connection server_1
+INSERT INTO t1 VALUES (7);
+INSERT INTO t2 VALUES (4);
+SELECT * FROM t1 ORDER BY a;
+SELECT * FROM t2 ORDER BY a;
+--source include/save_master_gtid.inc
+
+--connection server_2
+--source include/sync_with_master_gtid.inc
+SELECT * FROM t1 ORDER BY a;
+SELECT * FROM t2 ORDER BY a;
+
+--echo *** Verify that mysql.gtid_slave_pos_InnoDB is auto-created ***
+let $wait_condition=
+ SELECT EXISTS (SELECT * FROM information_schema.tables
+ WHERE table_schema='mysql' AND table_name='gtid_slave_pos_InnoDB');
+--source include/wait_condition.inc
+SELECT lower(table_name), engine FROM information_schema.tables
+ WHERE table_schema='mysql' AND table_name LIKE 'gtid_slave_pos%'
+ ORDER BY table_name;
+SELECT domain_id, max(seq_no) FROM mysql.gtid_slave_pos GROUP BY domain_id;
+
+# Check that the auto-created InnoDB table starts being used without
+# needing slave restart. The auto-create happens asynchronously, so it
+# is non-deterministic when it will start being used. But we can wait
+# for it to happen.
+
+--let $count=300
+--let $done=0
+--let $old_silent= $keep_include_silent
+--let $keep_include_silent= 1
+--disable_query_log
+while (!$done)
+{
+ --connection server_1
+ INSERT INTO t2(a) SELECT 1+MAX(a) FROM t2;
+ --source include/save_master_gtid.inc
+
+ --connection server_2
+ --source include/sync_with_master_gtid.inc
+ --let $done=`SELECT COUNT(*) > 0 FROM mysql.gtid_slave_pos_InnoDB`
+ if (!$done)
+ {
+ dec $count;
+ if (!$count)
+ {
+ SELECT * FROM mysql.gtid_slave_pos_InnoDB;
+ --die Timeout waiting for mysql.gtid_slave_pos_InnoDB to be used
+ }
+ real_sleep 0.1;
+ }
+}
+--enable_query_log
+--let $keep_include_silent=$old_silent
+# Note that at this point, the contents of table t2, as well as the GTID
+# position, is non-deterministic.
+
+# MDEV-15373 engine gtid_slave_pos table name disobeys lower-case-table-names
+# This snippet verifies that engine gtid_slave_pos table is found,
+# its data are up-to-date.
+--write_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect
+wait
+EOF
+--connection server_2
+--shutdown_server
+--source include/wait_until_disconnected.inc
+
+--echo *** Restart the slave server to prove 'gtid_slave_pos_innodb' autodiscovery ***
+--append_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect
+restart: --skip-slave-start=0
+EOF
+
+--connection server_2
+--enable_reconnect
+--enable_prepare_warnings
+--source include/wait_until_connected_again.inc
+SELECT max(seq_no) FROM mysql.gtid_slave_pos_InnoDB into @seq_no;
+--disable_prepare_warnings
+
+--connection server_1
+INSERT INTO t2(a) SELECT 1+MAX(a) FROM t2;
+--source include/save_master_gtid.inc
+
+--connection server_2
+--source include/sync_with_master_gtid.inc
+if (`SELECT max(seq_no) <> @seq_no + 1 FROM mysql.gtid_slave_pos_InnoDB`)
+{
+ SELECT * FROM mysql.gtid_slave_pos_InnoDB;
+ --die Inconsistent table
+}
+#
+# end of MDEV-15373
+
+#--connection server_2
+--source include/stop_slave.inc
+SET GLOBAL gtid_pos_auto_engines="";
+SET sql_log_bin=0;
+DROP TABLE mysql.gtid_slave_pos_InnoDB;
+SET sql_log_bin=1;
+--source include/start_slave.inc
+
+--connection server_1
+DROP TABLE t1, t2;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_mdev359.test b/mysql-test/suite/rpl/t/rpl_mdev359.test
new file mode 100644
index 00000000..5b02ecd7
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_mdev359.test
@@ -0,0 +1,31 @@
+--source include/not_embedded.inc
+--source include/have_debug_sync.inc
+--source include/have_binlog_format_mixed_or_statement.inc
+--source include/master-slave.inc
+
+# MDEV-359: There was a server crash when the code first checks if semisync
+# is enabled without lock, then if so takes the lock and tests again.
+# If semisync was disabled in-between the first and the second test, an
+# assert was incorrectly made that referenced a NULL pointer.
+#
+# This tests uses debug_sync to pause one thread at the critical point in
+# the code, disable the semisync, and then continue the paused thread.
+
+CREATE TABLE t1 (a INT) ENGINE=MyISAM;
+SET GLOBAL rpl_semi_sync_master_enabled = ON;
+--connection master1
+SET DEBUG_SYNC = "rpl_semisync_master_commit_trx_before_lock SIGNAL m1_ready WAIT_FOR m1_cont";
+--send
+INSERT INTO t1 SELECT * FROM t1;
+--connection master
+SET DEBUG_SYNC= "now WAIT_FOR m1_ready";
+SET GLOBAL rpl_semi_sync_master_enabled = OFF;
+SET DEBUG_SYNC= "now SIGNAL m1_cont";
+--connection master1
+--reap
+
+connection master;
+DROP TABLE t1;
+SET DEBUG_SYNC= "RESET";
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_mdev382.test b/mysql-test/suite/rpl/t/rpl_mdev382.test
new file mode 100644
index 00000000..84e3c849
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_mdev382.test
@@ -0,0 +1,264 @@
+--source include/not_windows.inc #unix shell escaping used for mysqlbinlog
+--source include/have_innodb.inc
+--source include/have_binlog_format_statement.inc
+--source include/master-slave.inc
+
+# MDEV-382: multiple SQL injections in replication code.
+
+# Test previous SQL injection attack against binlog for SAVEPOINT statement.
+# The test would cause syntax error on slave due to improper quoting of
+# the savepoint name.
+connection master;
+create table t1 (a int primary key) engine=innodb;
+create table t2 (a int primary key) engine=myisam;
+
+begin;
+insert into t1 values (1);
+SET sql_mode = 'ANSI_QUOTES';
+savepoint `a``; create database couldbebadthingshere; savepoint ``dummy`;
+insert into t1 values (2);
+insert into t2 values (1);
+SET sql_mode = '';
+rollback to savepoint `a``; create database couldbebadthingshere; savepoint ``dummy`;
+insert into t1 values (3);
+commit;
+
+--source include/show_binlog_events2.inc
+
+# This failed due to syntax error in query when the bug was not fixed.
+sync_slave_with_master;
+connection slave;
+
+# Test some more combinations of ANSI_QUOTES and sql_quote_show_create
+connection master;
+let $binlog_start= query_get_value(SHOW MASTER STATUS, Position, 1);
+BEGIN;
+insert into t1 values(10);
+set sql_mode = 'ANSI_QUOTES';
+set sql_quote_show_create = 1;
+savepoint a;
+insert into t1 values(11);
+savepoint "a""a";
+insert into t1 values(12);
+set sql_quote_show_create = 0;
+savepoint b;
+insert into t1 values(13);
+savepoint "b""b";
+insert into t1 values(14);
+set sql_mode = '';
+set sql_quote_show_create = 1;
+savepoint c;
+insert into t1 values(15);
+savepoint `c``c`;
+insert into t1 values(16);
+set sql_quote_show_create = 0;
+savepoint d;
+insert into t1 values(17);
+savepoint `d``d`;
+insert into t1 values(18);
+COMMIT;
+set sql_quote_show_create = 1;
+
+--source include/show_binlog_events2.inc
+
+--echo *** Test correct USE statement in SHOW BINLOG EVENTS ***
+connection master;
+let $binlog_start= query_get_value(SHOW MASTER STATUS, Position, 1);
+set sql_mode = 'ANSI_QUOTES';
+CREATE DATABASE "db1`; select 'oops!'";
+use "db1`; select 'oops!'";
+CREATE TABLE t1 (a INT PRIMARY KEY) engine=MyISAM;
+INSERT INTO t1 VALUES (1);
+set sql_mode = '';
+INSERT INTO t1 VALUES (2);
+set sql_mode = 'ANSI_QUOTES';
+--source include/show_binlog_events2.inc
+set sql_mode = '';
+set sql_quote_show_create = 0;
+--source include/show_binlog_events2.inc
+set sql_quote_show_create = 1;
+--source include/show_binlog_events2.inc
+DROP TABLE t1;
+
+use test;
+
+--echo ***Test LOAD DATA INFILE with various identifiers that need correct quoting ***
+
+--let $load_file= $MYSQLTEST_VARDIR/tmp/f'le.txt
+--write_file $load_file
+'fo\\o','bar'
+EOF
+
+use `db1``; select 'oops!'`;
+let $binlog_start= query_get_value(SHOW MASTER STATUS, Position, 1);
+set timestamp=1000000000;
+CREATE TABLE `t``1` (`a``1` VARCHAR(4) PRIMARY KEY, `b``2` VARCHAR(3),
+ `c``3` VARCHAR(7));
+--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
+eval LOAD DATA INFILE '$MYSQLTEST_VARDIR/tmp/f''le.txt' INTO TABLE `t``1`
+ FIELDS TERMINATED BY ',' ESCAPED BY '\\\\' ENCLOSED BY ''''
+ LINES TERMINATED BY '\\n'
+ (`a``1`, @`b```) SET `b``2` = @`b```, `c``3` = concat('|', "b""a'z", "!");
+
+SELECT * FROM `t``1`;
+# Also test when code prefixes table name with database.
+truncate `t``1`;
+use test;
+--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
+eval LOAD DATA INFILE '$MYSQLTEST_VARDIR/tmp/f''le.txt'
+ INTO TABLE `db1``; select 'oops!'`.`t``1`
+ FIELDS TERMINATED BY ',' ESCAPED BY '\\\\' ENCLOSED BY ''''
+ LINES TERMINATED BY '\\n'
+ (`a``1`, `b``2`) SET `c``3` = concat('|', "b""a'z", "!");
+SELECT * FROM `db1``; select 'oops!'`.`t``1`;
+let $pos2= query_get_value(SHOW MASTER STATUS, Position, 1);
+
+--source include/show_binlog_events2.inc
+let $MYSQLD_DATADIR= `select @@datadir`;
+--replace_regex /LOCAL INFILE '.*SQL_LOAD.*' INTO/LOCAL INFILE '<name>' INTO/
+--exec $MYSQL_BINLOG --short-form --start-position=$binlog_start --stop-position=$pos2 $MYSQLD_DATADIR/master-bin.000001
+
+sync_slave_with_master;
+connection slave;
+SELECT * FROM `db1``; select 'oops!'`.`t``1`;
+connection master;
+
+DROP TABLE `db1``; select 'oops!'`.`t``1`;
+--remove_file $load_file
+
+connection master;
+drop table t1,t2;
+
+
+--echo *** Test truncation of long SET expression in LOAD DATA ***
+CREATE TABLE t1 (a INT PRIMARY KEY, b VARCHAR(1000));
+--let $load_file= $MYSQLTEST_VARDIR/tmp/file.txt
+--write_file $load_file
+1,X
+2,A
+EOF
+
+let $binlog_start= query_get_value(SHOW MASTER STATUS, Position, 1);
+# The bug was that the SET expression was truncated to 256 bytes, so test with
+# an expression longer than that.
+--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
+eval LOAD DATA INFILE '$load_file' INTO TABLE t1
+ FIELDS TERMINATED BY ','
+ (a, @b) SET b = CONCAT(@b, '| 123456789A123456789B123456789C123456789D123456789E123456789F123456789G123456789H123456789I123456789J123456789K123456789L123456789M123456789N123456789O123456789P123456789Q123456789R123456789123456789T123456789U123456789V123456789W123456789X123456789Y123456789Z123456789|', @b);
+
+SELECT * FROM t1 ORDER BY a;
+--source include/show_binlog_events2.inc
+
+sync_slave_with_master;
+connection slave;
+SELECT * FROM t1 ORDER BY a;
+
+connection master;
+--remove_file $load_file
+DROP TABLE t1;
+
+
+--echo *** Test user variables whose names require correct quoting ***
+use `db1``; select 'oops!'`;
+let $binlog_start= query_get_value(SHOW MASTER STATUS, Position, 1);
+CREATE TABLE t1 (a1 BIGINT PRIMARY KEY, a2 BIGINT, a3 BIGINT, a4 BIGINT UNSIGNED, b DOUBLE, c DECIMAL(65,10), d VARCHAR(100));
+INSERT INTO t1 VALUES (-9223372036854775808,42,9223372036854775807,18446744073709551615,-1234560123456789e110, -1234501234567890123456789012345678901234567890123456789.0123456789, REPEAT("x", 100));
+SELECT @`a``1`:=a1, @`a``2`:=a2, @`a``3`:=a3, @`a``4`:=a4, @`b```:=b, @```c`:=c, @```d```:=d FROM t1;
+INSERT INTO t1 VALUES (@`a``1`+1, @`a``2`*100, @`a``3`-1, @`a``4`-1, @`b```/2, @```c`, substr(@```d```, 2, 98));
+let $pos2= query_get_value(SHOW MASTER STATUS, Position, 1);
+
+--source include/show_binlog_events2.inc
+
+--exec $MYSQL_BINLOG --short-form --start-position=$binlog_start --stop-position=$pos2 $MYSQLD_DATADIR/master-bin.000001
+
+sync_slave_with_master;
+connection slave;
+SELECT * FROM `db1``; select 'oops!'`.t1 ORDER BY a1;
+
+connection master;
+DROP TABLE t1;
+
+--echo *** Test correct quoting in foreign key error message ***
+use `db1``; select 'oops!'`;
+CREATE TABLE `t``1` ( `a``` INT PRIMARY KEY) ENGINE=innodb;
+CREATE TABLE `t``2` ( `b``` INT PRIMARY KEY, `c``` INT NOT NULL,
+ FOREIGN KEY fk (`c```) REFERENCES `t``1`(`a```)) ENGINE=innodb;
+--error ER_TRUNCATE_ILLEGAL_FK
+TRUNCATE `t``1`;
+DROP TABLE `t``2`;
+DROP TABLE `t``1`;
+
+
+--echo *** Test correct quoting of DELETE FROM statement binlogged for HEAP table that is emptied due to server restart
+
+# Let's keep the slave stopped during master restart, to avoid any potential
+# races between slave reconnect and master restart.
+connection slave;
+--source include/stop_slave.inc
+
+connection master;
+CREATE TABLE `db1``; select 'oops!'`.`t``1` (`a``` INT PRIMARY KEY) ENGINE=heap;
+INSERT INTO `db1``; select 'oops!'`.`t``1` VALUES (1), (2), (5);
+SELECT * FROM `db1``; select 'oops!'`.`t``1` ORDER BY 1;
+
+# Restart the master mysqld.
+# This will cause an implicit truncation of the memory-based table, which will
+# cause logging of an explicit DELETE FROM to binlog.
+--write_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
+wait-rpl_mdev382.test
+EOF
+
+--shutdown_server
+
+--append_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
+restart-rpl_mdev382.test
+EOF
+
+connection default;
+--enable_reconnect
+--source include/wait_until_connected_again.inc
+# rpl_end.inc needs to use the connection server_1
+connection server_1;
+--enable_reconnect
+--source include/wait_until_connected_again.inc
+connection master;
+--enable_reconnect
+--source include/wait_until_connected_again.inc
+set timestamp=1000000000;
+
+--echo # The table should be empty on the master.
+let $binlog_file= master-bin.000002;
+let $binlog_start= query_get_value(SHOW MASTER STATUS, Position, 1);
+SELECT * FROM `db1``; select 'oops!'`.`t``1`;
+
+--echo # The DELETE statement should be correctly quoted
+--source include/show_binlog_events2.inc
+
+connection slave;
+--source include/start_slave.inc
+
+connection master;
+sync_slave_with_master;
+connection slave;
+--echo # The table should be empty on the slave also.
+SELECT * FROM `db1``; select 'oops!'`.`t``1`;
+
+connection master;
+DROP TABLE `db1``; select 'oops!'`.`t``1`;
+sync_slave_with_master;
+
+
+connection master;
+use test;
+DROP DATABASE `db1``; select 'oops!'`;
+
+--echo *** Test correct quoting of mysqlbinlog --rewrite-db option ***
+CREATE TABLE t1 (a INT PRIMARY KEY);
+let $binlog_start= query_get_value(SHOW MASTER STATUS, Position, 1);
+INSERT INTO t1 VALUES(1);
+--source include/show_binlog_events2.inc
+let $pos2= query_get_value(SHOW MASTER STATUS, Position, 1);
+--exec $MYSQL_BINLOG --short-form --start-position=$binlog_start --stop-position=$pos2 --rewrite-db='test->ts`et' $MYSQLD_DATADIR/master-bin.000002
+DROP TABLE t1;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_mdev6020.test b/mysql-test/suite/rpl/t/rpl_mdev6020.test
new file mode 100644
index 00000000..06f03be1
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_mdev6020.test
@@ -0,0 +1,69 @@
+--source include/have_innodb.inc
+--source include/have_partition.inc
+--source include/have_binlog_format_mixed_or_row.inc
+--source include/master-slave.inc
+--connection slave
+--source include/stop_slave.inc
+
+--connection master
+--let $datadir= `SELECT @@datadir`
+
+--let $rpl_server_number= 1
+--source include/rpl_stop_server.inc
+
+--remove_file $datadir/master-bin.000001
+--remove_file $datadir/master-bin.state
+--copy_file $MYSQL_TEST_DIR/std_data/mdev6020-mysql-bin.000001 $datadir/master-bin.000001
+
+--let $rpl_server_number= 1
+--source include/rpl_start_server.inc
+
+--source include/wait_until_connected_again.inc
+
+--connection slave
+SET SQL_LOG_BIN=0;
+ALTER TABLE mysql.gtid_slave_pos ENGINE = InnoDB;
+SET SQL_LOG_BIN=1;
+SET @old_engine= @@GLOBAL.default_storage_engine;
+SET GLOBAL default_storage_engine=InnoDB;
+SET @old_parallel= @@GLOBAL.slave_parallel_threads;
+SET GLOBAL slave_parallel_threads=12;
+--replace_result $SERVER_MYPORT_1 SERVER_MYPORT_1
+eval CHANGE MASTER TO master_host='127.0.0.1', master_port=$SERVER_MYPORT_1, master_user='root', master_log_file='master-bin.000001', master_log_pos=4, master_use_gtid=no;
+--source include/start_slave.inc
+
+--connection master
+SET SQL_LOG_BIN=0;
+ALTER TABLE mysql.gtid_slave_pos ENGINE = InnoDB;
+SET SQL_LOG_BIN=1;
+--save_master_pos
+
+--connection slave
+--sync_with_master
+
+SELECT @@gtid_slave_pos;
+CHECKSUM TABLE table0_int_autoinc, table0_key_pk_parts_2_int_autoinc, table100_int_autoinc, table100_key_pk_parts_2_int_autoinc, table10_int_autoinc, table10_key_pk_parts_2_int_autoinc, table1_int_autoinc, table1_key_pk_parts_2_int_autoinc, table2_int_autoinc, table2_key_pk_parts_2_int_autoinc;
+
+--source include/stop_slave.inc
+
+
+SET GLOBAL default_storage_engine= @old_engine;
+SET GLOBAL slave_parallel_threads=@old_parallel;
+SET sql_log_bin=0;
+DROP TABLE table0_int_autoinc;
+DROP TABLE table0_key_pk_parts_2_int_autoinc;
+DROP TABLE table100_int_autoinc;
+DROP TABLE table100_key_pk_parts_2_int_autoinc;
+DROP TABLE table10_int_autoinc;
+DROP TABLE table10_key_pk_parts_2_int_autoinc;
+DROP TABLE table1_int_autoinc;
+DROP TABLE table1_key_pk_parts_2_int_autoinc;
+DROP TABLE table2_int_autoinc;
+DROP TABLE table2_key_pk_parts_2_int_autoinc;
+SET sql_log_bin=1;
+
+--source include/start_slave.inc
+
+--connection master
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_mdev6386-slave.opt b/mysql-test/suite/rpl/t/rpl_mdev6386-slave.opt
new file mode 100644
index 00000000..a5d959ae
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_mdev6386-slave.opt
@@ -0,0 +1 @@
+--disable-log-slave-updates
diff --git a/mysql-test/suite/rpl/t/rpl_mdev6386.test b/mysql-test/suite/rpl/t/rpl_mdev6386.test
new file mode 100644
index 00000000..f969d656
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_mdev6386.test
@@ -0,0 +1,70 @@
+--source include/have_innodb.inc
+--source include/master-slave.inc
+
+--connection master
+ALTER TABLE mysql.gtid_slave_pos ENGINE = InnoDB;
+CREATE TABLE t1 (a INT PRIMARY KEY, b INT) Engine=InnoDB;
+--sync_slave_with_master
+
+--connection slave
+--source include/stop_slave.inc
+# Provoke a duplicate key error on replication.
+SET sql_log_bin= 0;
+CALL mtr.add_suppression("Commit failed due to failure of an earlier commit on which this one depends");
+INSERT INTO t1 VALUES (1, 2);
+SET sql_log_bin= 1;
+--echo Contents on slave before:
+SELECT * FROM t1 ORDER BY a;
+
+SET @old_parallel= @@GLOBAL.slave_parallel_threads;
+SET GLOBAL slave_parallel_threads=8;
+
+--connection master
+
+CREATE TEMPORARY TABLE t2 LIKE t1;
+INSERT INTO t2 VALUE (1, 1);
+INSERT INTO t2 VALUE (2, 1);
+INSERT INTO t2 VALUE (3, 1);
+INSERT INTO t2 VALUE (4, 1);
+INSERT INTO t2 VALUE (5, 1);
+INSERT INTO t1 SELECT * FROM t2;
+DROP TEMPORARY TABLE t2;
+INSERT INTO t1 VALUE (6, 3);
+--source include/save_master_gtid.inc
+--echo Contents on master:
+SELECT * FROM t1 ORDER BY a;
+
+--connection slave
+START SLAVE;
+# The slave will stop with a duplicate key error.
+# The bug was 1) that the next DROP TEMPORARY TABLE would be allowed to run
+# anyway, and 2) that then record_gtid() would get an error during commit
+# (since the prior commit failed), and this error was not correctly handled,
+# which caused an assertion about closing tables while a statement was still
+# active.
+--let $slave_sql_errno=1062
+--source include/wait_for_slave_sql_error.inc
+
+STOP SLAVE IO_THREAD;
+--echo Contents on slave on slave error:
+SELECT * FROM t1 ORDER BY a;
+
+# Resolve the duplicate key error so replication can be resumed.
+SET sql_log_bin= 0;
+DELETE FROM t1 WHERE a=1;
+SET sql_log_bin= 1;
+
+--source include/start_slave.inc
+--source include/sync_with_master_gtid.inc
+--echo Contents on slave after:
+SELECT * FROM t1 ORDER BY a;
+
+--connection master
+DROP TABLE t1;
+
+--connection slave
+--source include/stop_slave.inc
+SET GLOBAL slave_parallel_threads= @old_parallel;
+--source include/start_slave.inc
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_mdev8193.test b/mysql-test/suite/rpl/t/rpl_mdev8193.test
new file mode 100644
index 00000000..dcad3e5f
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_mdev8193.test
@@ -0,0 +1,56 @@
+--source include/have_binlog_format_statement.inc
+--source include/master-slave.inc
+
+--connection slave
+
+--source include/stop_slave_sql.inc
+
+--connection master
+
+CALL mtr.add_suppression("Statement is unsafe because it uses a system function that may return a different value on the slave");
+create table t1 (i int);
+insert into t1 values (1),(2);
+insert into t1 values (3),(4);
+# This sleep() helps trigger the failure more reliably.
+insert into t1 select i+20+0*sleep(1) from t1 where i=1;
+flush logs;
+insert into t1 values (5),(6);
+insert into t1 values (7),(8);
+insert into t1 values (9),(10);
+
+--let $master_file = query_get_value(show master status,File,1)
+--let $master_pos = query_get_value(show master status,Position,1)
+
+insert into t1 values (11),(12);
+insert into t1 values (13),(14);
+insert into t1 values (15),(16);
+
+--connection slave
+
+set global slave_parallel_threads = 1;
+--replace_result $master_file MASTER_FILE $master_pos MASTER_POS
+eval start slave until master_log_file='$master_file', master_log_pos=$master_pos;
+
+--let $show_statement = SHOW SLAVE STATUS
+--let $field = Slave_SQL_Running
+--let $condition = = 'No'
+--let $wait_timeout = 10
+
+--source include/wait_show_condition.inc
+
+if (`select COUNT(*) > 11 from t1`)
+{
+ query_vertical show slave status;
+ SELECT * FROM t1;
+ die "Wrong number of rows in the table";
+}
+
+drop table t1;
+--source include/stop_slave_io.inc
+set global slave_parallel_threads = DEFAULT;
+
+--connection master
+drop table t1;
+
+--let $rpl_only_running_threads= 1
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_mdev_17614.test b/mysql-test/suite/rpl/t/rpl_mdev_17614.test
new file mode 100644
index 00000000..8d91944a
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_mdev_17614.test
@@ -0,0 +1,172 @@
+source include/have_debug.inc;
+source include/have_innodb.inc;
+-- source include/have_binlog_format_statement.inc
+source include/master-slave.inc;
+# MDEV-17614 INSERT on dup key update is replication unsafe
+#
+# The following cases are tested below:
+# 1. 2 unique key, replication is UNSAFE
+# 2. 2 unique key, with one auto increment key and implicit value to it.
+# It is UNSAFE because autoinc column values of being inserted records
+# are revealed dynamically, so unknown at the binlog-format decision time
+# and hence this pessimistic expectation
+# 3. 2 unique keys
+# A. insert is only in 1 unique key, still all colums are specified => UNSAFE
+# B. both unique keys are specified => UNSAFE
+# C. only one unique key is specified => SAFE (motivated by MDEV-28310)
+# 4. 2 unique key, with one auto increment key(but user gives auto inc value) =>
+# UNSAFE to replicate
+
+--echo # Case 1: UNSAFE
+call mtr.add_suppression("Unsafe statement written to the binary log using statement format");
+CREATE TABLE t1 (a INT NOT NULL PRIMARY KEY , b INT,
+UNIQUE(b), c int) engine=innodb;
+sync_slave_with_master;
+connection master;
+INSERT INTO t1 VALUES (1, 1, 1);
+BEGIN;
+INSERT INTO t1 VALUES (2, 1, 2) ON DUPLICATE KEY UPDATE b=VALUES(b), c=VALUES(c);
+ --connection master1
+ INSERT INTO t1 VALUES(2, 2, 3) ON DUPLICATE KEY UPDATE b=VALUES(b), c=VALUES(c);
+--connection master
+COMMIT;
+SELECT * FROM t1;
+--connection slave
+# show the error message
+--let $slave_sql_errno= 1062
+--let $show_slave_sql_error= 1
+--source include/wait_for_slave_sql_error.inc
+--echo #Different value from server
+SELECT * FROM t1;
+
+# restart replication for the next testcase
+stop slave;
+--source include/wait_for_slave_to_stop.inc
+--source include/reset_slave.inc
+connection master;
+reset master;
+drop table t1;
+connection slave;
+start slave;
+--source include/wait_for_slave_to_start.inc
+
+--echo # Case 2: UNSAFE
+--connection master
+CREATE TABLE t1 (a INT NOT NULL PRIMARY KEY auto_increment, b INT,
+UNIQUE(b), c int) engine=innodb;
+sync_slave_with_master;
+connection master;
+INSERT INTO t1 VALUES (default, 1, 1);
+BEGIN;
+INSERT INTO t1 VALUES (default, 1, 2) ON DUPLICATE KEY UPDATE b=VALUES(b), c=VALUES(c);
+ --connection master1
+ INSERT INTO t1 VALUES(default, 2, 3) ON DUPLICATE KEY UPDATE b=VALUES(b), c=VALUES(c);
+--connection master
+COMMIT;
+SELECT * FROM t1;
+--sync_slave_with_master
+--echo #same data as master
+SELECT * FROM t1;
+
+connection master;
+drop table t1;
+--sync_slave_with_master
+
+--echo # Case 3A: UNSAFE
+--connection master
+CREATE TABLE t1 (a INT NOT NULL PRIMARY KEY, b INT,
+UNIQUE(b), c int, d int ) engine=innodb;
+sync_slave_with_master;
+connection master;
+INSERT INTO t1 VALUES (1, 1, 1, 1);
+BEGIN;
+INSERT INTO t1 VALUES (2, NULL, 2, 2) ON DUPLICATE KEY UPDATE b=VALUES(b), c=VALUES(c);
+ --connection master1
+ INSERT INTO t1 VALUES(3, NULL, 2, 3) ON DUPLICATE KEY UPDATE b=VALUES(b), c=VALUES(c);
+--connection master
+COMMIT;
+SELECT * FROM t1;
+--sync_slave_with_master
+--echo #same data as master
+SELECT * FROM t1;
+connection master;
+drop table t1;
+--sync_slave_with_master
+
+--echo # Case 3B: UNSAFE - all column specified.
+--connection master
+CREATE TABLE t1 (a INT NOT NULL PRIMARY KEY, b INT,
+UNIQUE(b), c int, d int ) engine=innodb;
+sync_slave_with_master;
+connection master;
+INSERT INTO t1 VALUES (1, 1, 1, 1);
+BEGIN;
+INSERT INTO t1 VALUES (2, NULL, 2, 2) ON DUPLICATE KEY UPDATE c=VALUES(c);
+ --connection master1
+ INSERT INTO t1 VALUES(3, NULL, 2, 3) ON DUPLICATE KEY UPDATE c=VALUES(c);
+--connection master
+COMMIT;
+SELECT * FROM t1;
+--sync_slave_with_master
+--echo #same data as master
+SELECT * FROM t1;
+connection master;
+drop table t1;
+--sync_slave_with_master
+
+
+--echo # Case 3C: SAFE - only one unique key (PK) specified.
+--connection master
+CREATE TABLE t1 (a INT NOT NULL PRIMARY KEY, b INT,
+UNIQUE(b), c int, d int ) engine=innodb;
+sync_slave_with_master;
+connection master;
+INSERT INTO t1 VALUES (1, 1, 1, 1);
+BEGIN;
+INSERT INTO t1 (`a`, `c`, `d`) VALUES (2, 2, 2) ON DUPLICATE KEY UPDATE c=99;
+ --connection master1
+ INSERT INTO t1 (`a`, `c`, `d`) VALUES(3, 2, 3) ON DUPLICATE KEY UPDATE c=100;
+--connection master
+COMMIT;
+SELECT * FROM t1;
+--sync_slave_with_master
+--echo #same data as master
+SELECT * FROM t1;
+connection master;
+drop table t1;
+--sync_slave_with_master
+
+--echo # Case 4: UNSAFE
+--connection master
+CREATE TABLE t1 (a INT NOT NULL PRIMARY KEY auto_increment, b INT,
+UNIQUE(b), c int) engine=innodb;
+sync_slave_with_master;
+connection master;
+INSERT INTO t1 VALUES (1, 1, 1);
+BEGIN;
+INSERT INTO t1 VALUES (2, 1, 2) ON DUPLICATE KEY UPDATE b=VALUES(b), c=VALUES(c);
+ --connection master1
+ INSERT INTO t1 VALUES(2, 2, 3) ON DUPLICATE KEY UPDATE b=VALUES(b), c=VALUES(c);
+--connection master
+COMMIT;
+SELECT * FROM t1;
+--connection slave
+# show the error message
+--let $slave_sql_errno= 1062
+--let $show_slave_sql_error= 1
+--source include/wait_for_slave_sql_error.inc
+--echo #Different value from server
+SELECT * FROM t1;
+
+# restart replication for the next testcase
+stop slave;
+--source include/wait_for_slave_to_stop.inc
+--source include/reset_slave.inc
+connection master;
+reset master;
+drop table t1;
+connection slave;
+start slave;
+--source include/wait_for_slave_to_start.inc
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_misc_functions-slave.sh b/mysql-test/suite/rpl/t/rpl_misc_functions-slave.sh
new file mode 100644
index 00000000..8ce79797
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_misc_functions-slave.sh
@@ -0,0 +1 @@
+rm -f $MYSQLTEST_VARDIR/master-data/test/rpl_misc_functions.outfile
diff --git a/mysql-test/suite/rpl/t/rpl_misc_functions.test b/mysql-test/suite/rpl/t/rpl_misc_functions.test
new file mode 100644
index 00000000..b9d65844
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_misc_functions.test
@@ -0,0 +1,133 @@
+#
+# Test of replicating some difficult functions
+#
+source include/master-slave.inc;
+
+CALL mtr.add_suppression('Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT');
+
+create table t1(id int, i int, r1 int, r2 int, p varchar(100));
+insert into t1 values(1, connection_id(), 0, 0, "");
+# don't put rand and password in the same query, to see if they replicate
+# independently
+# Pure rand test
+--disable_warnings
+insert into t1 values(2, 0, rand()*1000, rand()*1000, "");
+--enable_warnings
+# change the rand suite on the master (we do this because otherwise password()
+# benefits from the fact that the above rand() is well replicated :
+# it picks the same sequence element, which hides a possible bug in password() replication.
+set sql_log_bin=0;
+insert into t1 values(6, 0, rand(), rand(), "");
+delete from t1 where id=6;
+set sql_log_bin=1;
+# Pure password test
+insert into t1 values(3, 0, 0, 0, password('does_this_work?'));
+# "altogether now"
+--disable_warnings
+insert into t1 values(4, connection_id(), rand()*1000, rand()*1000, password('does_this_still_work?'));
+--enable_warnings
+--disable_ps2_protocol
+select * into outfile 'rpl_misc_functions.outfile' from t1;
+--enable_ps2_protocol
+let $MYSQLD_DATADIR= `select @@datadir`;
+sync_slave_with_master;
+create temporary table t2 like t1;
+# read the values from the master table
+--replace_result $MYSQLD_DATADIR MYSQLD_DATADIR
+eval load data local infile '$MYSQLD_DATADIR/test/rpl_misc_functions.outfile' into table t2;
+# compare them with the replica; the SELECT below should return no row
+select * from t1, t2 where (t1.id=t2.id) and not(t1.i=t2.i and t1.r1=t2.r1 and t1.r2=t2.r2 and t1.p=t2.p);
+
+connection master;
+drop table t1;
+
+# End of 4.1 tests
+
+#
+# BUG#25543 test calling rand() multiple times on the master in
+# a stored procedure.
+#
+
+--disable_warnings
+DROP TABLE IF EXISTS t1;
+--enable_warnings
+
+CREATE TABLE t1 (id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
+ col_a DOUBLE DEFAULT NULL);
+
+DELIMITER |;
+
+# Use a SP that calls rand() multiple times
+CREATE PROCEDURE test_replication_sp1()
+BEGIN
+ INSERT INTO t1 (col_a) VALUES (rand()), (rand());
+ INSERT INTO t1 (col_a) VALUES (rand());
+END|
+
+# Use a SP that calls another SP to call rand() multiple times
+CREATE PROCEDURE test_replication_sp2()
+BEGIN
+ CALL test_replication_sp1();
+ CALL test_replication_sp1();
+END|
+
+# Use a SF that calls rand() multiple times
+CREATE FUNCTION test_replication_sf() RETURNS DOUBLE DETERMINISTIC
+BEGIN
+ RETURN (rand() + rand());
+END|
+
+DELIMITER ;|
+
+# Exercise the functions and procedures then compare the results on
+# the master to those on the slave.
+--disable_warnings
+CALL test_replication_sp1();
+CALL test_replication_sp2();
+INSERT INTO t1 (col_a) VALUES (test_replication_sf());
+INSERT INTO t1 (col_a) VALUES (test_replication_sf());
+INSERT INTO t1 (col_a) VALUES (test_replication_sf());
+--enable_warnings
+
+--sync_slave_with_master
+
+--enable_prepare_warnings
+# Dump table on slave
+--disable_ps2_protocol
+select * from t1 into outfile "../../tmp/t1_slave.txt";
+--disable_prepare_warnings
+--enable_ps2_protocol
+
+# Load data from slave into temp table on master
+connection master;
+--disable_warnings
+create temporary table t1_slave select * from t1 where 1=0;
+--enable_warnings
+load data infile '../../tmp/t1_slave.txt' into table t1_slave;
+--remove_file $MYSQLTEST_VARDIR/tmp/t1_slave.txt
+
+# Compare master and slave temp table, use subtraction
+# for floating point comparison of "double"
+select count(*) into @aux from t1 join t1_slave using (id)
+where ABS(t1.col_a - t1_slave.col_a) < 0.0000001 ;
+SELECT @aux;
+if (`SELECT @aux <> 12 OR @aux IS NULL`)
+{
+ --echo # ERROR: We expected to get count(*) = 12.
+ SELECT id, col_a FROM t1;
+ SELECT id, col_a FROM t1_slave;
+ --echo # abort
+ exit;
+}
+
+# Cleanup
+connection master;
+DROP TABLE t1, t1_slave;
+DROP PROCEDURE test_replication_sp1;
+DROP PROCEDURE test_replication_sp2;
+DROP FUNCTION test_replication_sf;
+--remove_file $MYSQLD_DATADIR/test/rpl_misc_functions.outfile
+--sync_slave_with_master
+
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_mix_found_rows.test b/mysql-test/suite/rpl/t/rpl_mix_found_rows.test
new file mode 100644
index 00000000..af206c55
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_mix_found_rows.test
@@ -0,0 +1,152 @@
+source include/have_binlog_format_mixed.inc;
+source include/master-slave.inc;
+
+# It is not possible to replicate FOUND_ROWS() using statement-based
+# replication, but there is a workaround that stores the result of
+# FOUND_ROWS() into a user variable and then replicates this instead.
+#
+# The purpose of this test case is to test that the workaround works
+# properly even when inside stored programs (i.e., stored routines and
+# triggers).
+
+--echo ==== Initialize ====
+
+connection master;
+CREATE TABLE t1 (a INT);
+CREATE TABLE logtbl (sect INT, test INT, count INT);
+
+INSERT INTO t1 VALUES (1),(2),(3);
+INSERT INTO t1 SELECT 2*a+3 FROM t1;
+INSERT INTO t1 SELECT 2*a+3 FROM t1;
+INSERT INTO t1 SELECT 2*a+3 FROM t1;
+INSERT INTO t1 SELECT 2*a+3 FROM t1;
+INSERT INTO t1 SELECT 2*a+3 FROM t1;
+INSERT INTO t1 SELECT 2*a+3 FROM t1;
+
+--echo ==== Checking a procedure ====
+
+connection master;
+
+# We will now check some stuff that will not work in statement-based
+# replication, but which should cause the binary log to switch to
+# row-based logging.
+
+--delimiter $$
+CREATE PROCEDURE just_log(sect INT, test INT) BEGIN
+ INSERT INTO logtbl VALUES (sect,test,FOUND_ROWS());
+END $$
+--delimiter ;
+sync_slave_with_master;
+
+connection master1;
+SELECT SQL_CALC_FOUND_ROWS * FROM t1 WHERE a > 5 ORDER BY a LIMIT 1;
+CALL just_log(1,1);
+
+connection master;
+SELECT SQL_CALC_FOUND_ROWS * FROM t1 WHERE a > 5 ORDER BY a LIMIT 1;
+CALL just_log(1,2);
+
+connection master1;
+SELECT SQL_CALC_FOUND_ROWS * FROM t1 WHERE a < 5 ORDER BY a LIMIT 1;
+CALL just_log(1,3);
+sync_slave_with_master;
+
+connection master;
+SELECT SQL_CALC_FOUND_ROWS * FROM t1 WHERE a > 5 ORDER BY a LIMIT 1;
+CALL just_log(1,4);
+sync_slave_with_master;
+
+connection master;
+SELECT * FROM logtbl WHERE sect = 1 ORDER BY sect,test;
+sync_slave_with_master;
+SELECT * FROM logtbl WHERE sect = 1 ORDER BY sect,test;
+
+--echo ==== Checking a stored function ====
+connection master;
+--delimiter $$
+CREATE FUNCTION log_rows(sect INT, test INT)
+ RETURNS INT
+BEGIN
+ DECLARE found_rows INT;
+ SELECT FOUND_ROWS() INTO found_rows;
+ INSERT INTO logtbl VALUES(sect,test,found_rows);
+ RETURN found_rows;
+END $$
+--delimiter ;
+
+SELECT SQL_CALC_FOUND_ROWS * FROM t1 WHERE a < 5 ORDER BY a LIMIT 1;
+--disable_ps2_protocol
+SELECT log_rows(2,1), log_rows(2,2);
+--enable_ps2_protocol
+
+CREATE TABLE t2 (a INT, b INT);
+
+# Trying with referencing FOUND_ROWS() directly in the trigger.
+
+--delimiter $$
+CREATE TRIGGER t2_tr BEFORE INSERT ON t2 FOR EACH ROW
+BEGIN
+ INSERT INTO logtbl VALUES (NEW.a, NEW.b, FOUND_ROWS());
+END $$
+--delimiter ;
+
+SELECT SQL_CALC_FOUND_ROWS * FROM t1 WHERE a < 5 ORDER BY a LIMIT 1;
+INSERT INTO t2 VALUES (2,3), (2,4);
+
+# Referencing FOUND_ROWS() indirectly.
+
+DROP TRIGGER t2_tr;
+
+--delimiter $$
+CREATE TRIGGER t2_tr BEFORE INSERT ON t2 FOR EACH ROW
+BEGIN
+ DECLARE dummy INT;
+ SELECT log_rows(NEW.a, NEW.b) INTO dummy;
+END $$
+--delimiter ;
+
+SELECT SQL_CALC_FOUND_ROWS * FROM t1 WHERE a > 5 ORDER BY a LIMIT 1;
+INSERT INTO t2 VALUES (2,5), (2,6);
+
+# Putting FOUND_ROWS() even lower in the call chain.
+
+connection master;
+DROP TRIGGER t2_tr;
+
+--delimiter $$
+CREATE PROCEDURE log_me_inner(sect INT, test INT)
+BEGIN
+ DECLARE dummy INT;
+ SELECT log_rows(sect, test) INTO dummy;
+ SELECT log_rows(sect, test+1) INTO dummy;
+END $$
+
+CREATE PROCEDURE log_me(sect INT, test INT)
+BEGIN
+ CALL log_me_inner(sect,test);
+END $$
+--delimiter ;
+
+--delimiter $$
+CREATE TRIGGER t2_tr BEFORE INSERT ON t2 FOR EACH ROW
+BEGIN
+ CALL log_me(NEW.a, NEW.b);
+END $$
+--delimiter ;
+
+SELECT SQL_CALC_FOUND_ROWS * FROM t1 WHERE a > 5 ORDER BY a LIMIT 1;
+INSERT INTO t2 VALUES (2,5), (2,6);
+
+SELECT * FROM logtbl WHERE sect = 2 ORDER BY sect,test;
+sync_slave_with_master;
+SELECT * FROM logtbl WHERE sect = 2 ORDER BY sect,test;
+
+connection master;
+DROP TABLE t1, t2, logtbl;
+DROP PROCEDURE just_log;
+DROP PROCEDURE log_me;
+DROP PROCEDURE log_me_inner;
+DROP FUNCTION log_rows;
+sync_slave_with_master;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_mixed_binlog_max_cache_size.test b/mysql-test/suite/rpl/t/rpl_mixed_binlog_max_cache_size.test
new file mode 100644
index 00000000..c4c89d90
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_mixed_binlog_max_cache_size.test
@@ -0,0 +1,8 @@
+--source include/have_innodb.inc
+--source include/not_embedded.inc
+--source include/not_windows.inc
+--source include/have_binlog_format_mixed.inc
+--source include/master-slave.inc
+
+--source include/rpl_binlog_max_cache_size.test
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_mixed_bit_pk.test b/mysql-test/suite/rpl/t/rpl_mixed_bit_pk.test
new file mode 100644
index 00000000..226a82de
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_mixed_bit_pk.test
@@ -0,0 +1,83 @@
+#
+# BUG
+# ---
+# BUG#39753: Replication failure on MIXED + bit + myisam + no PK
+#
+# Description
+# -----------
+# Simple statements against a bit column cause failure in mixed-mode
+# replication.
+#
+# Implementation is as follows:
+# i) A table with two bit fields is created. One of them is a key.
+# ii) A record is inserted without specifying the key value.
+# iii) The record is deleted using a where clause that matches it.
+# iv) repeat i-iii) for bit key that has different size, generating
+# different extra bits values
+# v) The slave is synchronized with master
+# vi) The table is dropped on master and the slave is re-synchronized
+# with master.
+#
+# Step v) made the bug evident before the patch, as the slave would
+# fail to find the correspondent row in its database (although it did
+# the insert in step ii) ).
+#
+# Obs
+# ---
+# This test is based on the "how to repeat" section from the bug report.
+#
+#
+
+--source include/master-slave.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_warnings
+# setup
+
+DROP TABLE IF EXISTS t1,t2,t3,t4,t5,t6,t7,t8;
+CREATE TABLE t1 (`bit_key` bit, `bit` bit, key (`bit_key` )) ENGINE=MyISAM;
+CREATE TABLE t2 (`bit_key` bit(4), `bit` bit, key (`bit_key` )) ENGINE=MyISAM;
+CREATE TABLE t3 (`bit_key` bit(7), `bit` bit, key (`bit_key` )) ENGINE=MyISAM;
+CREATE TABLE t4 (`bit_key` bit(8), `bit` bit, key (`bit_key` )) ENGINE=MyISAM;
+CREATE TABLE t5 (`bit_key` bit(9), `bit` bit, key (`bit_key` )) ENGINE=MyISAM;
+CREATE TABLE t6 (`bit_key` bit(14), `bit` bit, key (`bit_key` )) ENGINE=MyISAM;
+CREATE TABLE t7 (`bit_key` bit(15), `bit` bit, key (`bit_key` )) ENGINE=MyISAM;
+CREATE TABLE t8 (`bit_key` bit(16), `bit` bit, key (`bit_key` )) ENGINE=MyISAM;
+
+# insert and delete
+INSERT INTO `t1` ( `bit` ) VALUES ( 0 );
+DELETE FROM `t1` WHERE `bit` < 2 LIMIT 4;
+
+INSERT INTO `t2` ( `bit` ) VALUES ( 0 );
+DELETE FROM `t2` WHERE `bit` < 2 LIMIT 4;
+
+INSERT INTO `t3` ( `bit` ) VALUES ( 0 );
+DELETE FROM `t3` WHERE `bit` < 2 LIMIT 4;
+
+INSERT INTO `t4` ( `bit` ) VALUES ( 0 );
+DELETE FROM `t4` WHERE `bit` < 2 LIMIT 4;
+
+INSERT INTO `t5` ( `bit` ) VALUES ( 0 );
+DELETE FROM `t5` WHERE `bit` < 2 LIMIT 4;
+
+INSERT INTO `t6` ( `bit` ) VALUES ( 0 );
+DELETE FROM `t6` WHERE `bit` < 2 LIMIT 4;
+
+INSERT INTO `t7` ( `bit` ) VALUES ( 0 );
+DELETE FROM `t7` WHERE `bit` < 2 LIMIT 4;
+
+INSERT INTO `t8` ( `bit` ) VALUES ( 0 );
+DELETE FROM `t8` WHERE `bit` < 2 LIMIT 4;
+
+
+--enable_warnings
+sync_slave_with_master;
+
+# clean up
+connection master;
+DROP TABLE t1, t2, t3, t4, t5, t6, t7, t8;
+sync_slave_with_master;
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_mixed_ddl_dml.test b/mysql-test/suite/rpl/t/rpl_mixed_ddl_dml.test
new file mode 100644
index 00000000..f4a1615a
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_mixed_ddl_dml.test
@@ -0,0 +1,51 @@
+# Mixed DDL-DML (CREATE ... SELECT ...) statements can only be
+# replicated properly in statement-based replication.
+# Currently statement based due to bug 12345
+--source include/have_binlog_format_mixed_or_statement.inc
+
+source include/master-slave.inc;
+
+# Test replication of auto_increment
+
+create table t1 (n int auto_increment primary key);
+set insert_id = 2000;
+insert into t1 values (NULL),(NULL),(NULL);
+sync_slave_with_master;
+select * from t1;
+connection master;
+--replace_result $SLAVE_MYPORT 9999
+show slave hosts;
+drop table t1;
+sync_slave_with_master;
+stop slave;
+--source include/wait_for_slave_to_stop.inc
+connection master;
+
+# Test replication of timestamp
+
+create table t2(id int auto_increment primary key, created datetime);
+SET TIME_ZONE= '+03:00';
+set timestamp=12345;
+insert into t2 set created=now();
+select * from t2;
+
+# Test replication of CREATE .. LIKE (Bug #2557)
+
+create table t3 like t2;
+create temporary table t4 like t2;
+create table t5 select * from t4;
+save_master_pos;
+connection slave;
+start slave;
+--source include/wait_for_slave_to_start.inc
+sync_with_master;
+select * from t2;
+show create table t3;
+show create table t5;
+connection master;
+drop table t2,t3,t5;
+drop temporary table t4;
+sync_slave_with_master;
+
+# End of 4.1 tests
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_mixed_drop_create_temp_table.test b/mysql-test/suite/rpl/t/rpl_mixed_drop_create_temp_table.test
new file mode 100644
index 00000000..e707bb99
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_mixed_drop_create_temp_table.test
@@ -0,0 +1,12 @@
+###################################################################################
+# This test cases evaluates the mixture of non-transactional and transcational
+# tables. Specifically when drop temporary tables and create temporary tables
+# are used.
+###################################################################################
+--source include/big_test.inc
+--source include/have_binlog_format_mixed.inc
+--source include/have_innodb.inc
+--source include/master-slave.inc
+
+--source include/rpl_drop_create_temp_table.test
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_mixed_implicit_commit_binlog.test b/mysql-test/suite/rpl/t/rpl_mixed_implicit_commit_binlog.test
new file mode 100644
index 00000000..8e40295e
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_mixed_implicit_commit_binlog.test
@@ -0,0 +1,12 @@
+################################################################################
+# Check file include/rpl_implicit_commit_binlog.test
+################################################################################
+--source include/have_udf.inc
+--source include/have_binlog_format_mixed.inc
+--source include/have_innodb.inc
+--source include/master-slave.inc
+
+--let $engine=Innodb
+set session default_storage_engine=innodb;
+--source include/rpl_implicit_commit_binlog.test
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_mixed_mixing_engines.test b/mysql-test/suite/rpl/t/rpl_mixed_mixing_engines.test
new file mode 100644
index 00000000..ddc7757f
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_mixed_mixing_engines.test
@@ -0,0 +1,14 @@
+###################################################################################
+# This test cases evaluates the mixture of non-transactional and transcational
+# tables. For further details, please, read WL#2687 and WL#5072.
+###################################################################################
+--source include/have_binlog_format_mixed.inc
+--source include/have_innodb.inc
+# MDEV-31790 FIXME: This test is extremely slow
+--source include/not_msan.inc
+--source include/master-slave.inc
+
+let $engine_type=Innodb;
+let $database_name=test;
+--source include/rpl_mixing_engines.test
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_mixed_row_innodb-master.opt b/mysql-test/suite/rpl/t/rpl_mixed_row_innodb-master.opt
new file mode 100644
index 00000000..96f0ce3f
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_mixed_row_innodb-master.opt
@@ -0,0 +1 @@
+--default-storage-engine=MyISAM
diff --git a/mysql-test/suite/rpl/t/rpl_multi_delete-slave.opt b/mysql-test/suite/rpl/t/rpl_multi_delete-slave.opt
new file mode 100644
index 00000000..c98fe0b0
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_multi_delete-slave.opt
@@ -0,0 +1 @@
+--replicate-wild-do-table=test.%
diff --git a/mysql-test/suite/rpl/t/rpl_multi_delete.test b/mysql-test/suite/rpl/t/rpl_multi_delete.test
new file mode 100644
index 00000000..80acf9c8
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_multi_delete.test
@@ -0,0 +1,25 @@
+source include/master-slave.inc;
+create table t1 (a int primary key);
+create table t2 (a int);
+
+insert into t1 values (1);
+insert into t2 values (1);
+
+
+delete t1.* from t1, t2 where t1.a = t2.a;
+
+save_master_pos;
+select * from t1;
+select * from t2;
+
+connection slave;
+sync_with_master;
+select * from t1;
+select * from t2;
+
+connection master;
+drop table t1,t2;
+sync_slave_with_master;
+
+# End of 4.1 tests
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_multi_delete2-slave.opt b/mysql-test/suite/rpl/t/rpl_multi_delete2-slave.opt
new file mode 100644
index 00000000..0febb289
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_multi_delete2-slave.opt
@@ -0,0 +1 @@
+"--replicate-rewrite-db=mysqltest_from->mysqltest_to" --replicate-do-table=mysqltest_to.a
diff --git a/mysql-test/suite/rpl/t/rpl_multi_delete2.test b/mysql-test/suite/rpl/t/rpl_multi_delete2.test
new file mode 100644
index 00000000..7dc7ca41
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_multi_delete2.test
@@ -0,0 +1,67 @@
+#multi delete replication bugs
+
+
+source include/master-slave.inc;
+
+#BUG#11139 - improper wild-table and table rules
+#checking for multi deletes with an alias
+
+connection master;
+set sql_log_bin=0;
+create database mysqltest_from;
+set sql_log_bin=1;
+
+connection slave;
+create database mysqltest_to;
+
+
+connection master;
+use mysqltest_from;
+--disable_warnings
+drop table if exists a;
+--enable_warnings
+CREATE TABLE a (i INT);
+INSERT INTO a VALUES(1);
+DELETE alias FROM a alias WHERE alias.i=1;
+SELECT * FROM a;
+insert into a values(2),(3);
+delete alias FROM a alias where alias.i=2;
+select * from a;
+sync_slave_with_master;
+
+use mysqltest_to;
+select * from a;
+
+# BUG#3461
+connection master;
+create table t1 (a int primary key);
+create table t2 (a int);
+
+insert into t1 values (1);
+insert into t2 values (1);
+
+delete t1.* from t1, t2 where t1.a = t2.a;
+
+save_master_pos;
+select * from t1;
+select * from t2;
+
+connection slave;
+# BUG#3461 would cause sync to fail
+sync_with_master;
+error 1146;
+select * from t1;
+error 1146;
+select * from t2;
+
+# cleanup
+connection master;
+set sql_log_bin=0;
+drop database mysqltest_from;
+set sql_log_bin=1;
+connection slave;
+drop database mysqltest_to;
+
+# End of 4.1 tests
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_multi_engine.test b/mysql-test/suite/rpl/t/rpl_multi_engine.test
new file mode 100644
index 00000000..704c0935
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_multi_engine.test
@@ -0,0 +1,102 @@
+# See if replication between MyISAM, MEMORY and InnoDB works.
+
+-- source include/master-slave.inc
+
+connection slave;
+-- source include/have_innodb.inc
+
+connection master;
+-- source include/have_innodb.inc
+--disable_warnings
+drop table if exists t1;
+--enable_warnings
+
+CREATE TABLE t1 (id MEDIUMINT NOT NULL, b1 BIT(8), vc
+VARCHAR(255), bc CHAR(255), d DECIMAL(10,4) DEFAULT 0, f FLOAT DEFAULT
+0, total BIGINT UNSIGNED, y YEAR, t TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
+ON UPDATE CURRENT_TIMESTAMP,PRIMARY KEY(id));
+
+sync_slave_with_master;
+
+# MyISAM to MyISAM then InnoDB then MEMORY
+
+connection master;
+alter table t1 engine=myisam;
+show create table t1;
+sync_slave_with_master;
+
+connection slave;
+alter table t1 engine=myisam;
+show create table t1;
+
+--source include/rpl_multi_engine.inc
+
+connection slave;
+alter table t1 engine=innodb;
+show create table t1;
+
+--source include/rpl_multi_engine.inc
+
+connection slave;
+alter table t1 engine=memory;
+show create table t1;
+
+--source include/rpl_multi_engine.inc
+
+# MEMORY to ...
+
+connection master;
+alter table t1 engine=memory;
+show create table t1;
+sync_slave_with_master;
+
+connection slave;
+alter table t1 engine=myisam;
+show create table t1;
+
+--source include/rpl_multi_engine.inc
+
+connection slave;
+alter table t1 engine=innodb;
+show create table t1;
+
+--source include/rpl_multi_engine.inc
+
+connection slave;
+alter table t1 engine=memory;
+show create table t1;
+
+--source include/rpl_multi_engine.inc
+
+# InnoDB to ...
+
+connection master;
+alter table t1 engine=innodb;
+show create table t1;
+sync_slave_with_master;
+
+connection slave;
+alter table t1 engine=myisam;
+show create table t1;
+
+--source include/rpl_multi_engine.inc
+
+connection slave;
+alter table t1 engine=innodb;
+show create table t1;
+
+--source include/rpl_multi_engine.inc
+
+connection slave;
+alter table t1 engine=memory;
+show create table t1;
+
+--source include/rpl_multi_engine.inc
+
+# cleanup
+connection master;
+DROP TABLE t1;
+sync_slave_with_master;
+
+# End of 5.1 test case
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_multi_update.test b/mysql-test/suite/rpl/t/rpl_multi_update.test
new file mode 100644
index 00000000..3927ed69
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_multi_update.test
@@ -0,0 +1,2 @@
+let $engine_type=MyISAM;
+-- source include/rpl_multi_update.test
diff --git a/mysql-test/suite/rpl/t/rpl_multi_update2-slave.opt b/mysql-test/suite/rpl/t/rpl_multi_update2-slave.opt
new file mode 100644
index 00000000..17d4171a
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_multi_update2-slave.opt
@@ -0,0 +1 @@
+--replicate-ignore-table=nothing.sensible
diff --git a/mysql-test/suite/rpl/t/rpl_multi_update2.test b/mysql-test/suite/rpl/t/rpl_multi_update2.test
new file mode 100644
index 00000000..d2368f20
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_multi_update2.test
@@ -0,0 +1,9 @@
+#######################################################
+# Wrapper for rpl_multi_update2.test to allow multi #
+# Engines to reuse test code. By JBM 2006-02-15 #
+#######################################################
+--source include/master-slave.inc
+call mtr.add_suppression('Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT');
+let $engine_type=MyISAM;
+--source include/rpl_multi_update2.test
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_multi_update3.test b/mysql-test/suite/rpl/t/rpl_multi_update3.test
new file mode 100644
index 00000000..0a15e9aa
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_multi_update3.test
@@ -0,0 +1,9 @@
+#######################################################
+# Wrapper for rpl_multi_update3.test to allow multi #
+# Engines to reuse test code. By JBM 2006-02-15 #
+#######################################################
+--source include/master-slave.inc
+call mtr.add_suppression('Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT.');
+let $engine_type=MyISAM;
+-- source include/rpl_multi_update3.test
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_multi_update4-slave.opt b/mysql-test/suite/rpl/t/rpl_multi_update4-slave.opt
new file mode 100644
index 00000000..fea27db4
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_multi_update4-slave.opt
@@ -0,0 +1 @@
+--replicate-wild-do-table=d1.%
diff --git a/mysql-test/suite/rpl/t/rpl_multi_update4.test b/mysql-test/suite/rpl/t/rpl_multi_update4.test
new file mode 100644
index 00000000..8f069b9c
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_multi_update4.test
@@ -0,0 +1,46 @@
+# Let's verify that multi-update is not always skipped by slave if
+# some replicate-* rules exist.
+# (BUG#15699)
+
+source include/master-slave.inc;
+
+### Clean-up
+
+connection master;
+--disable_warnings
+drop database if exists d1;
+drop database if exists d2;
+
+connection slave;
+drop database if exists d2;
+--enable_warnings
+
+### Do on master
+
+connection master;
+create database d1; # accepted by slave
+create table d1.t0 (id int);
+create database d2; # ignored by slave
+use d2;
+create table t1 (id int);
+create table t2 (id int);
+insert into t1 values (1), (2), (3), (4), (5);
+insert into t2 select id + 3 from t1;
+# a problematic query which must be filter out by slave
+update t1 join t2 using (id) set t1.id = 0;
+insert into d1.t0 values (0); # replication works
+
+### Check on slave
+
+sync_slave_with_master;
+use d1;
+select * from t0 where id=0; # must find
+
+### Clean-up
+connection master;
+drop database d1;
+drop database d2;
+sync_slave_with_master;
+
+# End of test
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_mysql57_stm_temporal_round.test b/mysql-test/suite/rpl/t/rpl_mysql57_stm_temporal_round.test
new file mode 100644
index 00000000..34001382
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_mysql57_stm_temporal_round.test
@@ -0,0 +1,58 @@
+--source include/have_binlog_format_statement.inc
+
+--echo #
+--echo # MDEV-8894 Inserting fractional seconds into MySQL 5.6 master breaks consistency on MariaDB 10 slave
+--echo #
+
+--source include/have_innodb.inc
+--source include/master-slave.inc
+
+--connection slave
+CREATE TABLE t1 (id SERIAL, a DATETIME(3));
+--source include/stop_slave.inc
+
+--connection master
+--let $datadir= `SELECT @@datadir`
+
+--let $rpl_server_number= 1
+--source include/rpl_stop_server.inc
+
+--remove_file $datadir/master-bin.000001
+
+#
+# Simulate MySQL 5.7.x master
+#
+# mysql-5.7.11-stm-temporal-round-binlog.000001 was recorded against a
+# table with this structure:
+#CREATE TABLE t1 (id SERIAL, a DATETIME(3));
+# (note, the CREATE statement is not inside the binary log)
+#
+# using this command line:
+# mysqld --log-bin --binlog-format=statement
+# with the following single SQL statement:
+#
+#INSERT INTO t1 (a) VALUES ('2001-01-01 00:00:00.999999');
+#
+
+--copy_file $MYSQL_TEST_DIR/std_data/rpl/mysql-5.7.11-stm-temporal-round-binlog.000001 $datadir/master-bin.000001
+
+--let $rpl_server_number= 1
+--source include/rpl_start_server.inc
+
+--source include/wait_until_connected_again.inc
+
+--connection slave
+--replace_result $SERVER_MYPORT_1 SERVER_MYPORT_1
+eval CHANGE MASTER TO master_host='127.0.0.1', master_port=$SERVER_MYPORT_1, master_user='root', master_log_file='master-bin.000001', master_log_pos=4, master_use_gtid=no;
+
+--source include/start_slave.inc
+
+--connection master
+--sync_slave_with_master
+SELECT * FROM t1 ORDER BY id;
+
+--source include/stop_slave.inc
+DROP TABLE t1;
+
+--let $rpl_only_running_threads= 1
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_mysql80_stm_temporal_round.test b/mysql-test/suite/rpl/t/rpl_mysql80_stm_temporal_round.test
new file mode 100644
index 00000000..551764ac
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_mysql80_stm_temporal_round.test
@@ -0,0 +1,62 @@
+--source include/have_binlog_format_statement.inc
+
+--echo #
+--echo # MDEV-8894 Inserting fractional seconds into MySQL 5.6 master breaks consistency on MariaDB 10 slave
+--echo #
+
+--source include/have_innodb.inc
+--source include/master-slave.inc
+
+--connection slave
+CREATE TABLE t1 (id SERIAL, a DATETIME(3));
+--source include/stop_slave.inc
+
+--connection master
+--let $datadir= `SELECT @@datadir`
+
+--let $rpl_server_number= 1
+--source include/rpl_stop_server.inc
+
+--remove_file $datadir/master-bin.000001
+
+#
+# Simulate MySQL 8.0.x master
+#
+# mysql-8.0.13-stm-temporal-round-binlog.000001 was recorded against a
+# table with this structure:
+#CREATE TABLE t1 (id SERIAL, a DATETIME(3));
+# (note, the CREATE statement is not inside the binary log)
+#
+# using this command line:
+# mysqld --log-bin --binlog-format=statement --server-id=1 --character-set-server=latin1
+# with the following SQL script:
+#
+#SET NAMES latin1 COLLATE latin1_swedish_ci;
+#SET sql_mode='';
+#INSERT INTO t1 (a) VALUES ('2001-01-01 00:00:00.999999');
+#SET sql_mode=TIME_TRUNCATE_FRACTIONAL;
+#INSERT INTO t1 (a) VALUES ('2001-01-01 00:00:00.999999');
+#
+
+--copy_file $MYSQL_TEST_DIR/std_data/rpl/mysql-8.0.13-stm-temporal-round-binlog.000001 $datadir/master-bin.000001
+
+--let $rpl_server_number= 1
+--source include/rpl_start_server.inc
+
+--source include/wait_until_connected_again.inc
+
+--connection slave
+--replace_result $SERVER_MYPORT_1 SERVER_MYPORT_1
+eval CHANGE MASTER TO master_host='127.0.0.1', master_port=$SERVER_MYPORT_1, master_user='root', master_log_file='master-bin.000001', master_log_pos=4, master_use_gtid=no;
+
+--source include/start_slave.inc
+
+--connection master
+--sync_slave_with_master
+SELECT * FROM t1 ORDER BY id;
+
+--source include/stop_slave.inc
+DROP TABLE t1;
+
+--let $rpl_only_running_threads= 1
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_mysql_manager_race_condition-slave.opt b/mysql-test/suite/rpl/t/rpl_mysql_manager_race_condition-slave.opt
new file mode 100644
index 00000000..d127ef62
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_mysql_manager_race_condition-slave.opt
@@ -0,0 +1 @@
+--gtid-cleanup-batch-size=1
diff --git a/mysql-test/suite/rpl/t/rpl_mysql_manager_race_condition.test b/mysql-test/suite/rpl/t/rpl_mysql_manager_race_condition.test
new file mode 100644
index 00000000..751da315
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_mysql_manager_race_condition.test
@@ -0,0 +1,67 @@
+#
+# Purpose:
+# This test ensures that, during mysqld initialization, the mysql handle
+# manager starts before the binlog background thread. This is because the
+# binlog background thread uses the mysql handle manager, and if the background
+# thread tries to submit a job to the handle manager before it is
+# initialized/started, mysqld can crash (the actual behavior is undefined).
+# This race condition lead to the problem described in MDEV-26473.
+#
+# Methodology:
+# This test ensures that the binlog background thread cannot be started
+# before the mysql manager is started. Specifically, it forces a path in
+# the binlog background thread to call mysql_manager_submit() by reducing
+# --gtid-cleanup-batch-size to be 1 (which submits a job to delete unused rows
+# from the mysql.gtid_slave_pos* tables). With this path forced, the main
+# mysqld thread is suspended just before its handle manager initialization to
+# allow time for the binlog thread to call mysql_manager_submit. The fix
+# associated with this test should enforce that the binlog background thread is
+# not created before the handle manager is initialized.
+#
+# References:
+# MDEV-26473 mysqld got exception 0xc0000005 (rpl_slave_state/rpl_load_gtid_slave_state)
+#
+
+--source include/have_debug.inc
+--source include/master-slave.inc
+
+# The race condition discovered from MDEV-26473 is binlog format independent.
+# We use ROW format though because it was used by the reporter.
+--source include/have_binlog_format_row.inc
+
+--connection master
+
+--echo # Create a GTID event so the binlog background thread will submit a
+--echo # mysql handler job the next time mysqld is restarted.
+create table t1 (a int);
+--source include/save_master_gtid.inc
+
+--connection slave
+--source include/sync_with_master_gtid.inc
+
+--echo # Set a debug point that forces the main mysqld thread to sleep before
+--echo # anything is initialized for the mysql handle manager
+--let $rpl_server_parameters=--debug_dbug="+d,delay_start_handle_manager"
+
+
+--echo # Restart the slave mysqld instance so it re-initializes with the
+--echo # binlog background thread submitting a mysql handler job and the
+--echo # mysql handler initialization suspending for a second. Without the fix
+--echo # associated with this test/patch, the following restart will error
+--echo # with a failed assertion.
+--source include/rpl_restart_server.inc
+--source include/start_slave.inc
+
+
+--echo #
+--echo # Cleanup
+--echo #
+
+--connection master
+drop table t1;
+--source include/save_master_gtid.inc
+
+--connection slave
+--source include/sync_with_master_gtid.inc
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_mysql_upgrade.test b/mysql-test/suite/rpl/t/rpl_mysql_upgrade.test
new file mode 100644
index 00000000..f44c883e
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_mysql_upgrade.test
@@ -0,0 +1,80 @@
+#############################################################################
+# BUG#43579 mysql_upgrade tries to alter log tables on replicated database
+# Master and slave should be upgraded separately. All statements executed by
+# mysql_upgrade will not be binlogged. --write-binlog and --skip-write-binlog
+# options are added into mysql_upgrade. These options control whether sql
+# statements are binlogged or not.
+#############################################################################
+--source include/have_innodb.inc
+--source include/mysql_upgrade_preparation.inc
+--source include/master-slave.inc
+
+call mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT");
+call mtr.add_suppression("table or database name 'mysqltest-1'");
+
+connection master;
+--disable_warnings
+CREATE DATABASE `mysqltest-1`;
+--enable_warnings
+sync_slave_with_master;
+
+connection master;
+let $before_position= query_get_value(SHOW MASTER STATUS, Position, 1);
+
+#With '--force' option, mysql_upgrade always executes all sql statements for upgrading.
+--exec $MYSQL_UPGRADE --skip-verbose --force --user=root > $MYSQLTEST_VARDIR/log/mysql_upgrade.log 2>&1
+sync_slave_with_master;
+
+connection master;
+let $after_position= query_get_value(SHOW MASTER STATUS, Position, 1);
+
+if ($before_position == $after_position)
+{
+ echo Master position is not changed;
+}
+
+# Some log events of the mysql_upgrade previously caused errors on slave,
+# however with MDEV-4851 this should be ok, so we test it:
+connection slave;
+SET @old_general_log_state = @@global.general_log;
+SET @old_slow_log_state = @@global.slow_query_log;
+SET @old_log_output = @@global.log_output;
+SET GLOBAL general_log = 'ON';
+SET GLOBAL slow_query_log = 'ON';
+SET GLOBAL log_output = 'FILE';
+
+connection master;
+#With '--force' option, mysql_upgrade always executes all sql statements for upgrading.
+ALTER TABLE mysql.slow_log DROP COLUMN thread_id, DROP COLUMN rows_affected;
+DROP DATABASE `mysqltest-1`;
+sync_slave_with_master;
+
+connection slave;
+SHOW CREATE TABLE mysql.slow_log;
+connection master;
+--exec $MYSQL_UPGRADE --skip-verbose --write-binlog --force --user=root > $MYSQLTEST_VARDIR/log/mysql_upgrade.log 2>&1
+
+let $datadir= `select @@datadir`;
+remove_file $datadir/mysql_upgrade_info;
+
+connection master;
+let $after_file= query_get_value(SHOW MASTER STATUS, File, 1);
+let $after_position= query_get_value(SHOW MASTER STATUS, Position, 1);
+
+if ($before_position != $after_position)
+{
+ echo Master position has been changed;
+}
+
+sync_slave_with_master;
+connection slave;
+SHOW CREATE TABLE mysql.slow_log;
+SET GLOBAL general_log = 'OFF';
+SET GLOBAL slow_query_log = 'OFF';
+truncate mysql.slow_log;
+truncate mysql.general_log;
+SET GLOBAL general_log = @old_general_log_state;
+SET GLOBAL slow_query_log = @old_slow_log_state;
+SET GLOBAL log_output = @old_log_output;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_mysqlbinlog_slave_consistency.test b/mysql-test/suite/rpl/t/rpl_mysqlbinlog_slave_consistency.test
new file mode 100644
index 00000000..d2918e3a
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_mysqlbinlog_slave_consistency.test
@@ -0,0 +1,401 @@
+#
+# Purpose:
+#
+# This test ensures the mariadb-binlog command line tool filters events
+# by domain id (via --do-domain-ids and --ignore-domain-ids) and server id (via
+# --ignore-server-ids) in the same way that a replica server does.
+#
+#
+# Methodology:
+#
+# This test validates that the domain and server id filtering logic of
+# mariadb-binlog matches that of a replica server. In particular, it validates
+# a mariadb-binlog replay of a master's binary log is consistent with a
+# replica's state which is configured using the same filtering configuration.
+#
+# It uses a repeatable process to allow for multiple test cases that span
+# different filtering configurations. First, a master is seeded with an initial
+# set of SQL statements with varying domain and server ids. Then, a set of
+# filtering parameters supported by both mariadb-binlog and replica
+# capabilities are defined. The replica is configured using these parameters
+# and run it until it has processed all events from the primary server; it is
+# stopped afterward. For mariadb-binlog validation, the binary log of the
+# primary server is copied to a different location for later replay. The
+# primary is then reset to its initial state (i.e. the tables are dropped and
+# the logs are reset). The mariadb-binlog tool is then used to replay the
+# copied binary log file back onto the clean primary server under the same
+# filtering conditions as the replica. At this point, the data on the primary
+# and replica should be exactly the same because the filtering conditions were
+# the same, and all existing tables on both servers are compared using.
+# checksums.
+#
+#
+# References:
+#
+# MDEV-20119: Implement the --do-domain-ids, --ignore-domain-ids, and
+# --ignore-server-ids options for mysqlbinlog
+#
+--source include/master-slave.inc
+
+--connection slave
+SET sql_log_bin=0;
+call mtr.add_suppression("Slave: An attempt was made.*");
+call mtr.add_suppression("Both DO_DOMAIN_IDS & IGNORE_DOMAIN_IDS lists can't be non-empty at the same time");
+SET sql_log_bin=1;
+
+--source include/stop_slave.inc
+
+--connection master
+RESET MASTER;
+
+# Save old state
+let $ORIG_GTID_DOMAIN_ID = `select @@session.gtid_domain_id`;
+let $ORIG_SERVER_ID = `select @@session.server_id`;
+
+--connection slave
+--source include/start_slave.inc
+
+# Initial tests do not use strict mode
+--let $strict_mode=0
+--let $slave_sql_errno=0
+
+--echo #
+--echo #
+--echo # Test Case 1: Base case to ensure that mariadb-binlog and replica
+--echo # are consistent without any filtering
+--echo #
+--let $do_domain_ids=
+--let $ignore_domain_ids=
+--let $ignore_server_ids=
+--let $stop_position=
+--let $start_position=
+--source include/mysqlbinlog_slave_consistency.inc
+
+--echo #
+--echo #
+--echo # Test Case 2: Ensure filtering by a single id in --do-domain-ids is
+--echo # consistent between mariadb-binlog and replica
+--echo #
+--let $do_domain_ids=0
+--let $ignore_domain_ids=
+--let $ignore_server_ids=
+--let $stop_position=
+--let $start_position=
+--source include/mysqlbinlog_slave_consistency.inc
+
+--echo #
+--echo #
+--echo # Test Case 3: Ensure filtering by multiple ids in --do-domain-ids is
+--echo # consistent between mariadb-binlog and replica
+--echo #
+--let $do_domain_ids=0,1
+--let $ignore_domain_ids=
+--let $ignore_server_ids=
+--let $stop_position=
+--let $start_position=
+--source include/mysqlbinlog_slave_consistency.inc
+
+--echo #
+--echo # Test Case 4: Ensure filtering by a single id in --ignore-domain-ids
+--echo # is consistent between mariadb-binlog and replica
+--echo #
+--let $do_domain_ids=
+--let $ignore_domain_ids=0
+--let $ignore_server_ids=
+--let $stop_position=
+--let $start_position=
+--source include/mysqlbinlog_slave_consistency.inc
+
+--echo #
+--echo #
+--echo # Test Case 5: Ensure filtering by multiple ids in --ignore-domain-ids
+--echo # is consistent between mariadb-binlog and replica
+--echo #
+--let $do_domain_ids=
+--let $ignore_domain_ids=0,1
+--let $ignore_server_ids=
+--let $stop_position=
+--let $start_position=
+--source include/mysqlbinlog_slave_consistency.inc
+
+--echo #
+--echo # Test Case 6: Ensure filtering by a single id in --ignore-server-ids
+--echo # is consistent between mariadb-binlog and replica
+--echo #
+--let $do_domain_ids=
+--let $ignore_domain_ids=
+--let $ignore_server_ids=1
+--let $stop_position=
+--let $start_position=
+--source include/mysqlbinlog_slave_consistency.inc
+
+--echo #
+--echo #
+--echo # Test Case 7: Ensure filtering by multiple ids in --ignore-server-ids
+--echo # is consistent between mariadb-binlog and replica
+--echo #
+--let $do_domain_ids=
+--let $ignore_domain_ids=
+--let $ignore_server_ids=0,1
+--let $stop_position=
+--let $start_position=
+--source include/mysqlbinlog_slave_consistency.inc
+
+--echo #
+--echo #
+--echo # Test Case 8: Ensure stop position consistency
+--echo #
+--let $do_domain_ids=
+--let $ignore_domain_ids=
+--let $ignore_server_ids=
+--let $stop_position=1-1-2
+--let $start_position=
+--source include/mysqlbinlog_slave_consistency.inc
+
+--echo #
+--echo #
+--echo # Test Case 9: Ensure start position consistency
+--echo #
+--let $do_domain_ids=
+--let $ignore_domain_ids=
+--let $ignore_server_ids=
+--let $stop_position=
+--let $start_position=1-4-2
+--source include/mysqlbinlog_slave_consistency.inc
+
+--echo #
+--echo #
+--echo # Test Case 10: Ensure consistency when filtering by both
+--echo # --do-domain-ids and --ignore-server-ids
+--echo #
+--let $do_domain_ids=0
+--let $ignore_domain_ids=
+--let $ignore_server_ids=1
+--let $stop_position=
+--let $start_position=
+--source include/mysqlbinlog_slave_consistency.inc
+
+--echo #
+--echo #
+--echo # Test Case 11: Ensure consistency when filtering by both
+--echo # --ignore-domain-ids and --ignore-server-ids
+--echo #
+--let $do_domain_ids=
+--let $ignore_domain_ids=1,2
+--let $ignore_server_ids=1
+--let $stop_position=
+--let $start_position=
+--source include/mysqlbinlog_slave_consistency.inc
+
+--echo #
+--echo #
+--echo # Test Case 12: Ensure consistency when filtering by
+--echo # --do-domain-ids with a stop position
+--echo #
+--let $do_domain_ids=0
+--let $ignore_domain_ids=
+--let $ignore_server_ids=
+--let $stop_position=0-1-4
+--let $start_position=
+--source include/mysqlbinlog_slave_consistency.inc
+
+--echo #
+--echo #
+--echo # Test Case 13: Ensure consistency when filtering by
+--echo # --ignore-domain-ids with a stop position
+--echo #
+--let $do_domain_ids=
+--let $ignore_domain_ids=0
+--let $ignore_server_ids=
+--let $stop_position=0-1-4
+--let $start_position=
+--source include/mysqlbinlog_slave_consistency.inc
+
+--echo #
+--echo #
+--echo # Test Case 14: Ensure consistency when filtering by
+--echo # --ignore-server-ids with a stop position
+--echo #
+--let $do_domain_ids=
+--let $ignore_domain_ids=
+--let $ignore_server_ids=3
+--let $stop_position=0-1-4
+--let $start_position=
+--source include/mysqlbinlog_slave_consistency.inc
+
+--echo #
+--echo #
+--echo # Test Case 15: Ensure consistency when filtering by
+--echo # --do-domain-ids with a start position
+--echo #
+--let $do_domain_ids=2
+--let $ignore_domain_ids=
+--let $ignore_server_ids=
+--let $stop_position=
+--let $start_position=1-1-2
+--source include/mysqlbinlog_slave_consistency.inc
+
+--echo #
+--echo #
+--echo # Test Case 16: Ensure consistency when filtering by
+--echo # --ignore-domain-ids with a start position
+--echo #
+--let $do_domain_ids=
+--let $ignore_domain_ids=0
+--let $ignore_server_ids=
+--let $stop_position=
+--let $start_position=0-1-1
+--source include/mysqlbinlog_slave_consistency.inc
+
+--echo #
+--echo #
+--echo # Test Case 17: Ensure consistency when filtering by
+--echo # --ignore-server-ids with a start position
+--echo #
+--let $do_domain_ids=
+--let $ignore_domain_ids=
+--let $ignore_server_ids=1
+--let $stop_position=
+--let $start_position=0-1-1
+--source include/mysqlbinlog_slave_consistency.inc
+
+--echo #
+--echo #
+--echo # Test Case 18: Ensure consistency when filtering by
+--echo # --do-domain-ids with both a start position and stop position that
+--echo # all have the same domain id
+--echo #
+--let $do_domain_ids=0
+--let $ignore_domain_ids=
+--let $ignore_server_ids=
+--let $stop_position=0-3-3
+--let $start_position=0-1-1
+--source include/mysqlbinlog_slave_consistency.inc
+
+--echo #
+--echo #
+--echo # Test Case 19: Ensure consistency when filtering by
+--echo # --do-domain-ids with both a start position and stop position that
+--echo # have differing domain ids. Due to the implicit filtering in stop
+--echo # position, the result should be empty (no tables replicated).
+--echo #
+--let $do_domain_ids=1
+--let $ignore_domain_ids=
+--let $ignore_server_ids=
+--let $stop_position=0-3-3
+--let $start_position=0-1-1
+--source include/mysqlbinlog_slave_consistency.inc
+
+--echo #
+--echo #
+--echo # Test Case 20: Ensure consistency when filtering by
+--echo # --ignore-domain-ids with both a start position and stop position that
+--echo # all have the same domain id. The result set should be empty due to
+--echo # implicit filtering from stop position and ignoring that same domain.
+--echo #
+--let $do_domain_ids=
+--let $ignore_domain_ids=0
+--let $ignore_server_ids=
+--let $stop_position=0-3-3
+--let $start_position=0-1-1
+--source include/mysqlbinlog_slave_consistency.inc
+
+--echo #
+--echo #
+--echo # Test Case 21: Ensure consistency when filtering by
+--echo # --ignore-domain-ids with both a start position and stop position that
+--echo # have differing domain ids. The ignore domain ids should take no
+--echo # effect due to the implicit filtering by stop position, i.e. the
+--echo # specified domain to ignore is already being filtered.
+--echo #
+--let $do_domain_ids=
+--let $ignore_domain_ids=1
+--let $ignore_server_ids=
+--let $stop_position=0-3-3
+--let $start_position=0-1-1
+--source include/mysqlbinlog_slave_consistency.inc
+
+--echo #
+--echo #
+--echo # Test Case 22: Ensure consistency when filtering by
+--echo # --ignore-server-ids with both a start position and stop position.
+--echo #
+--let $do_domain_ids=
+--let $ignore_domain_ids=
+--let $ignore_server_ids=3
+--let $stop_position=0-3-3
+--let $start_position=0-1-0
+--source include/mysqlbinlog_slave_consistency.inc
+
+--echo #
+--echo #
+--echo # Test Case 23: Out of order GTIDs from domains or servers which are
+--echo # filtered out should not error
+--echo #
+--let $strict_mode=1
+--let $strict_mode_err=0
+--let $slave_sql_errno=0
+--let $do_domain_ids=0
+--let $ignore_domain_ids=
+--let $ignore_server_ids=3
+--let $stop_position=
+--let $start_position=
+--source include/mysqlbinlog_slave_consistency.inc
+
+--echo #
+--echo #
+--echo # Test Case 24: Out of order GTIDs from included domains should error
+--echo #
+--let $strict_mode=1
+--let $strict_mode_err=1
+--let $slave_sql_errno=1950
+--let $do_domain_ids=1
+--let $ignore_domain_ids=
+--let $ignore_server_ids=
+--let $stop_position=
+--let $start_position=
+--source include/mysqlbinlog_slave_consistency.inc
+
+--echo #
+--echo #
+--echo # Test Case 25: Out of order GTIDs from included servers should error
+--echo #
+--let $strict_mode=1
+--let $strict_mode_err=1
+--let $slave_sql_errno=1950
+--let $do_domain_ids=
+--let $ignore_domain_ids=
+--let $ignore_server_ids=1
+--let $stop_position=
+--let $start_position=
+--source include/mysqlbinlog_slave_consistency.inc
+
+--echo #
+--echo #
+--echo # Test Case 26: Neither mysqlbinlog nor CHANGE MASTER TO should allow
+--echo # both do domain ids and ignore domain ids to be set together
+--echo #
+--connection slave
+--source include/stop_slave.inc
+
+--error 1201
+CHANGE MASTER TO MASTER_USE_GTID=slave_pos, DO_DOMAIN_IDS=(0), IGNORE_DOMAIN_IDS=(1);
+
+--let $MYSQLD_DATADIR=`select @@datadir`
+--let BINLOG_FILENAME= query_get_value(SHOW BINARY LOGS, Log_name, 1)
+--let BINLOG_FILE_PARAM= $MYSQLD_DATADIR/$BINLOG_FILENAME.orig
+--error 1
+--exec $MYSQL_BINLOG $MYSQLD_DATADIR/$BINLOG_FILENAME --do-domain-ids=0 --ignore-domain-ids=1
+
+RESET MASTER;
+set global gtid_slave_pos="";
+CHANGE MASTER TO MASTER_USE_GTID=slave_pos, DO_DOMAIN_IDS=(), IGNORE_DOMAIN_IDS=();
+--source include/start_slave.inc
+
+# Cleanup
+--connection master
+RESET MASTER;
+
+--source include/rpl_end.inc
+
+--echo # End of tests (rpl.rpl_mysqlbinlog_slave_consistency)
diff --git a/mysql-test/suite/rpl/t/rpl_name_const.test b/mysql-test/suite/rpl/t/rpl_name_const.test
new file mode 100644
index 00000000..074bc148
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_name_const.test
@@ -0,0 +1,45 @@
+# ==== Purpose ====
+#
+# Test that aliases of variables in binary log aren't ignored with NAME_CONST.
+#
+# ==== Method ====
+#
+# Create a procedure with aliases of variables, then replicate it to slave.
+# BUG#35515 Aliases of variables in binary log are ignored with NAME_CONST.
+#
+
+source include/master-slave.inc;
+
+--echo ==== Initialize ====
+
+--connection master
+
+create table t1 (id int);
+
+--echo ==== create a procedure that has a column aliase in a subquery ====
+--disable_warnings
+drop procedure if exists test_procedure;
+--enable_warnings
+delimiter $$;
+create procedure test_procedure(_id int)
+begin
+insert into t1 (id)
+select a.id
+from
+( select _id as id ) a;
+end;$$
+delimiter ;$$
+
+--echo ==== enable the binary log, then call the procedure ====
+call test_procedure(1234);
+
+
+sync_slave_with_master;
+select * from t1 order by id;
+
+--echo ==== Clean up ====
+
+connection master;
+drop table t1;
+drop procedure test_procedure;
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_non_direct_mixed_mixing_engines.test b/mysql-test/suite/rpl/t/rpl_non_direct_mixed_mixing_engines.test
new file mode 100644
index 00000000..d6b278ca
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_non_direct_mixed_mixing_engines.test
@@ -0,0 +1,17 @@
+###################################################################################
+# This test cases evaluates the mixture of non-transactional and transcational
+# tables. For further details, please, read WL#2687 and WL#5072.
+###################################################################################
+--source include/have_binlog_format_mixed.inc
+--source include/have_innodb.inc
+# MDEV-31790 FIXME: This test is extremely slow
+--source include/not_msan.inc
+--source include/master-slave.inc
+
+--disable_query_log
+SET SESSION binlog_direct_non_transactional_updates = OFF;
+--enable_query_log
+let $engine_type=Innodb;
+let $database_name=test;
+--source include/rpl_mixing_engines.test
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_non_direct_row_mixing_engines.test b/mysql-test/suite/rpl/t/rpl_non_direct_row_mixing_engines.test
new file mode 100644
index 00000000..0161a609
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_non_direct_row_mixing_engines.test
@@ -0,0 +1,19 @@
+###################################################################################
+# This test cases evaluates the mixture of non-transactional and transcational
+# tables. For further details, please, read WL#2687 and WL#5072.
+###################################################################################
+--source include/have_binlog_format_row.inc
+--source include/have_innodb.inc
+# MDEV-31790 FIXME: This test is extremely slow
+--source include/not_msan.inc
+--source include/master-slave.inc
+
+--disable_query_log
+SET SESSION binlog_direct_non_transactional_updates = OFF;
+--enable_query_log
+let $engine_type=Innodb;
+let $database_name=test;
+--source include/rpl_mixing_engines.test
+
+--diff_files suite/rpl/r/rpl_non_direct_row_mixing_engines.result suite/rpl/r/rpl_row_mixing_engines.result
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_non_direct_stm_mixing_engines.test b/mysql-test/suite/rpl/t/rpl_non_direct_stm_mixing_engines.test
new file mode 100644
index 00000000..99443707
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_non_direct_stm_mixing_engines.test
@@ -0,0 +1,17 @@
+###################################################################################
+# This test cases evaluates the mixture of non-transactional and transcational
+# tables. For further details, please, read WL#2687 and WL#5072.
+###################################################################################
+--source include/have_binlog_format_statement.inc
+--source include/have_innodb.inc
+# MDEV-31790 FIXME: This test is extremely slow
+--source include/not_msan.inc
+--source include/master-slave.inc
+
+--disable_query_log
+SET SESSION binlog_direct_non_transactional_updates = OFF;
+--enable_query_log
+let $engine_type=Innodb;
+let $database_name=test;
+--source include/rpl_mixing_engines.test
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_nondeterministic_functions.test b/mysql-test/suite/rpl/t/rpl_nondeterministic_functions.test
new file mode 100644
index 00000000..a174445f
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_nondeterministic_functions.test
@@ -0,0 +1,58 @@
+# ==== Purpose ====
+#
+# Test that nondeterministic system functions are correctly replicated.
+#
+# (Some functions are only correctly replicated if binlog_format=MIXED
+# or ROW. See binlog_unsafe.test for a test that those variables are
+# indeed unsafe.)
+#
+# ==== Implementation ====
+#
+# We insert the values of each unsafe function into a table. Then we
+# replicate and check that the table is identical on slave.
+#
+# ==== Related bugs ====
+#
+# BUG#47995
+
+--source include/master-slave.inc
+
+CALL mtr.add_suppression('Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT');
+
+CREATE TABLE t1 (a VARCHAR(1000));
+
+# We replicate the connection_id in the query_log_event
+INSERT INTO t1 VALUES (CONNECTION_ID());
+--connection master1
+INSERT INTO t1 VALUES (CONNECTION_ID());
+
+# We replicate the TIMESTAMP variable, so the following functions that
+# are affected by the TIMESTAMP variable should be safe to replicate.
+INSERT INTO t1 VALUES
+ (CURDATE()),
+ (CURRENT_DATE()),
+ (CURRENT_TIME()),
+ (CURRENT_TIMESTAMP()),
+ (CURTIME()),
+ (LOCALTIME()),
+ (LOCALTIMESTAMP()),
+ (NOW()),
+ (UNIX_TIMESTAMP()),
+ (UTC_DATE()),
+ (UTC_TIME()),
+ (UTC_TIMESTAMP());
+
+# We replicate the random seed in a rand_log_event
+--disable_warnings
+INSERT INTO t1 VALUES (RAND());
+--enable_warnings
+# We replicate the last_insert_id in an intvar_log_event
+INSERT INTO t1 VALUES (LAST_INSERT_ID());
+
+--sync_slave_with_master
+--let $diff_tables= master:t1, slave:t1
+--source include/diff_tables.inc
+
+--connection master
+DROP TABLE t1;
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_not_null_innodb.test b/mysql-test/suite/rpl/t/rpl_not_null_innodb.test
new file mode 100644
index 00000000..0e67cd36
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_not_null_innodb.test
@@ -0,0 +1,20 @@
+#################################################################################
+# This test checks if the replication between "null" fields to either "null"
+# fields or "not null" fields works properly. In the first case, the execution
+# should work fine. In the second case, it may fail according to the sql_mode
+# being used.
+#
+# The test is devided in three main parts:
+#
+# 1 - NULL --> NULL (no failures)
+# 2 - NULL --> NOT NULL ( sql-mode = STRICT and failures)
+# 3 - NULL --> NOT NULL ( sql-mode != STRICT and no failures)
+#
+#################################################################################
+--source include/have_innodb.inc
+--source include/have_binlog_format_row.inc
+--source include/master-slave.inc
+
+let $engine=Innodb;
+--source include/rpl_not_null.test
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_not_null_myisam.test b/mysql-test/suite/rpl/t/rpl_not_null_myisam.test
new file mode 100644
index 00000000..718761d6
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_not_null_myisam.test
@@ -0,0 +1,19 @@
+#################################################################################
+# This test checks if the replication between "null" fields to either "null"
+# fields or "not null" fields works properly. In the first case, the execution
+# should work fine. In the second case, it may fail according to the sql_mode
+# being used.
+#
+# The test is devided in three main parts:
+#
+# 1 - NULL --> NULL (no failures)
+# 2 - NULL --> NOT NULL ( sql-mode = STRICT and failures)
+# 3 - NULL --> NOT NULL ( sql-mode != STRICT and no failures)
+#
+#################################################################################
+--source include/have_binlog_format_row.inc
+--source include/master-slave.inc
+
+let $engine=MyISAM;
+--source include/rpl_not_null.test
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_old_decimal.test b/mysql-test/suite/rpl/t/rpl_old_decimal.test
new file mode 100644
index 00000000..79fd2754
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_old_decimal.test
@@ -0,0 +1,25 @@
+--source include/have_binlog_format_row.inc
+--source include/master-slave.inc
+
+
+--connection slave
+CREATE TABLE t1dec102 (a DECIMAL(10,2));
+
+--connection master
+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);
+
+--let $slave_sql_errno=1677
+--let $show_slave_sql_error= 1
+call mtr.add_suppression("Slave SQL.*Column 0 of table .* cannot be converted from type.* Error_code: 1677");
+--source include/wait_for_slave_sql_error_and_skip.inc
+
+--connection master
+DROP TABLE t1dec102;
+--sync_slave_with_master
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_old_master.test b/mysql-test/suite/rpl/t/rpl_old_master.test
new file mode 100644
index 00000000..6faa8212
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_old_master.test
@@ -0,0 +1,57 @@
+# Test replicating off old master.
+# We simulate old master by copying in pre-generated binlog files from earlier
+# server versions.
+
+--source include/have_innodb.inc
+--source include/master-slave.inc
+
+--connection slave
+--source include/stop_slave.inc
+
+--connection master
+--let $datadir= `SELECT @@datadir`
+
+--let $rpl_server_number= 1
+--source include/rpl_stop_server.inc
+
+--remove_file $datadir/master-bin.000001
+--copy_file $MYSQL_TEST_DIR/std_data/mariadb-5.5-binlog.000001 $datadir/master-bin.000001
+
+--let $rpl_server_number= 1
+--source include/rpl_start_server.inc
+
+--source include/wait_until_connected_again.inc
+
+--connection slave
+SET @old_parallel= @@GLOBAL.slave_parallel_threads;
+SET GLOBAL slave_parallel_threads=10;
+--replace_result $SERVER_MYPORT_1 SERVER_MYPORT_1
+eval CHANGE MASTER TO master_host='127.0.0.1', master_port=$SERVER_MYPORT_1, master_user='root', master_log_file='master-bin.000001', master_log_pos=4, master_use_gtid=no;
+
+# Block execution yet when the blocked query timestamp has been already accounted
+FLUSH TABLES WITH READ LOCK;
+--source include/start_slave.inc
+--let $slave_param = Seconds_Behind_Master
+--let $slave_param_value = 1
+--let $slave_param_comparison= >=
+--source include/wait_for_slave_param.inc
+UNLOCK TABLES;
+
+--connection master
+CREATE TABLE t2 (a INT PRIMARY KEY) ENGINE=InnoDB;
+INSERT INTO t2 VALUES (1);
+--save_master_pos
+
+--connection slave
+--sync_with_master
+SELECT * FROM t1 ORDER BY a;
+SELECT * FROM t2;
+
+--source include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=@old_parallel;
+DROP TABLE t1;
+--source include/start_slave.inc
+
+--connection master
+DROP TABLE t2;
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_old_master_29078-master.opt b/mysql-test/suite/rpl/t/rpl_old_master_29078-master.opt
new file mode 100644
index 00000000..3efc6fb8
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_old_master_29078-master.opt
@@ -0,0 +1 @@
+--version=10.5.99
diff --git a/mysql-test/suite/rpl/t/rpl_old_master_29078.test b/mysql-test/suite/rpl/t/rpl_old_master_29078.test
new file mode 100644
index 00000000..98db6188
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_old_master_29078.test
@@ -0,0 +1,53 @@
+--echo #
+--echo # MDEV-29078 For old binary logs explicit_defaults_for_timestamp presumed to be OFF, server value ignored
+--echo #
+
+--source include/have_binlog_format_mixed.inc
+--source include/master-slave.inc
+
+--connection slave
+--source include/stop_slave.inc
+
+--connection master
+--let $datadir= `SELECT @@datadir`
+
+flush binary logs;
+create table t2 (a timestamp);
+
+--save_master_pos
+
+--remove_file $datadir/master-bin.000001
+--copy_file $MYSQL_TEST_DIR/std_data/mdev29078-mysql-bin.000001 $datadir/master-bin.000001
+
+--exec $MYSQL_BINLOG --short-form $datadir/master-bin.000001
+
+--connection slave
+
+set global explicit_defaults_for_timestamp=0;
+--let $master_use_gtid_option= No
+--source include/reset_slave.inc
+
+--source include/start_slave.inc
+--sync_with_master
+show create table t1;
+show create table t2;
+set time_zone='+2:00';
+select * from t1;
+drop table t1;
+--source include/stop_slave.inc
+
+set global explicit_defaults_for_timestamp=1;
+--let $master_use_gtid_option= No
+--source include/reset_slave.inc
+
+--source include/start_slave.inc
+--sync_with_master
+show create table t1;
+show create table t2;
+select * from t1;
+drop table t1;
+
+--connection master
+drop table t2;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_optimize.test b/mysql-test/suite/rpl/t/rpl_optimize.test
new file mode 100644
index 00000000..bb960d4e
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_optimize.test
@@ -0,0 +1,65 @@
+# Test for BUG#1858 "OPTIMIZE TABLE done by a client
+# thread stops the slave SQL thread".
+# You can replace OPTIMIZE by REPAIR.
+#####################################
+# Change Author: JBM
+# Change Date: 2006-02-09
+# OPTIMIZE for memory tables. If and when
+# it does support for Disk Data, a new
+# version of this test will be need.
+#####################################
+# Slow test, don't run during staging part
+-- source include/not_staging.inc
+-- source include/master-slave.inc
+
+--disable_warnings
+drop tables if exists t1;
+--enable_warnings
+
+disable_query_log;
+call mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT");
+enable_query_log;
+
+create table t1 (a int not null auto_increment primary key, b int, key(b));
+INSERT INTO t1 (a) VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10);
+--disable_warnings
+INSERT INTO t1 (a) SELECT null FROM t1;
+INSERT INTO t1 (a) SELECT null FROM t1;
+INSERT INTO t1 (a) SELECT null FROM t1;
+INSERT INTO t1 (a) SELECT null FROM t1;
+INSERT INTO t1 (a) SELECT null FROM t1;
+INSERT INTO t1 (a) SELECT null FROM t1;
+INSERT INTO t1 (a) SELECT null FROM t1;
+INSERT INTO t1 (a) SELECT null FROM t1;
+INSERT INTO t1 (a) SELECT null FROM t1;
+INSERT INTO t1 (a) SELECT null FROM t1;
+INSERT INTO t1 (a) SELECT null FROM t1;
+INSERT INTO t1 (a) SELECT null FROM t1;
+INSERT INTO t1 (a) SELECT null FROM t1;
+--enable_warnings
+save_master_pos;
+# a few updates to force OPTIMIZE to do something
+--disable_warnings
+update t1 set b=(a/2*rand());
+delete from t1 order by b limit 10000;
+--enable_warnings
+
+connection slave;
+sync_with_master;
+optimize table t1;
+connection master;
+save_master_pos;
+connection slave;
+# Bug was that when the INSERT terminated on slave,
+# the slave SQL thread got killed by OPTIMIZE.
+sync_with_master; # won't work if slave SQL thread stopped
+
+connection master; # cleanup
+drop table t1;
+sync_slave_with_master;
+
+# If the machine is so fast that slave syncs before OPTIMIZE
+# starts, this test will demonstrate nothing but will pass.
+
+# End of 4.1 tests
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_packet-master.opt b/mysql-test/suite/rpl/t/rpl_packet-master.opt
new file mode 100644
index 00000000..412bc079
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_packet-master.opt
@@ -0,0 +1 @@
+--max_allowed_packet=1024 --net_buffer_length=1024
diff --git a/mysql-test/suite/rpl/t/rpl_packet-slave.opt b/mysql-test/suite/rpl/t/rpl_packet-slave.opt
new file mode 100644
index 00000000..1aed7d07
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_packet-slave.opt
@@ -0,0 +1 @@
+--max_allowed_packet=1024 --net_buffer_length=1024 --slave_max_allowed_packet=1024
diff --git a/mysql-test/suite/rpl/t/rpl_packet.test b/mysql-test/suite/rpl/t/rpl_packet.test
new file mode 100644
index 00000000..cbde486b
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_packet.test
@@ -0,0 +1,184 @@
+#
+# This include file is used by more than one test suite
+# (currently rpl and binlog_encryption).
+# Please check all dependent tests after modifying it
+#
+
+# ==== Purpose ====
+#
+# Check replication protocol packet size handling
+#
+# ==== Related bugs ====
+# Bug#19402 SQL close to the size of the max_allowed_packet fails on slave
+# BUG#23755: Replicated event larger that max_allowed_packet infinitely re-transmits
+# BUG#42914: No LAST_IO_ERROR for max_allowed_packet errors
+# BUG#55322: SHOW BINLOG EVENTS increases @@SESSION.MAX_ALLOWED_PACKET
+
+# max-out size db name
+source include/have_binlog_format_row.inc;
+source include/master-slave.inc;
+
+call mtr.add_suppression("Slave I/O: Got a packet bigger than 'slave_max_allowed_packet' bytes, .*error.* 1153");
+call mtr.add_suppression("Log entry on master is longer than slave_max_allowed_packet");
+let $db= DB_NAME_OF_MAX_LENGTH_AKA_NAME_LEN_64_BYTES_____________________;
+disable_warnings;
+eval drop database if exists $db;
+enable_warnings;
+eval create database $db;
+
+connection master;
+let $old_max_allowed_packet= `SELECT @@global.max_allowed_packet`;
+let $old_net_buffer_length= `SELECT @@global.net_buffer_length`;
+let $old_slave_max_allowed_packet= `SELECT @@global.slave_max_allowed_packet`;
+SET @@global.max_allowed_packet=1024;
+SET @@global.net_buffer_length=1024;
+
+sync_slave_with_master;
+# Restart slave for setting to take effect
+source include/stop_slave.inc;
+source include/start_slave.inc;
+
+# Reconnect to master for new setting to take effect
+disconnect master;
+
+# alas, can't use eval here; if db name changed apply the change here
+connect (master,localhost,root,,DB_NAME_OF_MAX_LENGTH_AKA_NAME_LEN_64_BYTES_____________________);
+
+connection master;
+select @@net_buffer_length, @@max_allowed_packet;
+
+create table `t1` (`f1` LONGTEXT) ENGINE=MyISAM;
+
+INSERT INTO `t1`(`f1`) VALUES ('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa1023');
+sync_slave_with_master;
+
+eval select count(*) from `$db`.`t1` /* must be 1 */;
+
+SHOW STATUS LIKE 'Slave_running';
+select * from information_schema.session_status where variable_name= 'SLAVE_RUNNING';
+connection master;
+eval drop database $db;
+sync_slave_with_master;
+
+#
+# Bug #23755: Replicated event larger that max_allowed_packet infinitely re-transmits
+#
+# Check that a situation when the size of event on the master is greater than
+# max_allowed_packet on the slave does not lead to infinite re-transmits.
+
+connection master;
+
+# Change the max packet size on master
+
+SET @@global.max_allowed_packet=4096;
+SET @@global.net_buffer_length=4096;
+
+# Restart slave for new setting to take effect
+connection slave;
+source include/stop_slave.inc;
+source include/start_slave.inc;
+
+# Reconnect to master for new setting to take effect
+disconnect master;
+connect (master, localhost, root);
+connection master;
+
+CREATE TABLE `t1` (`f1` LONGTEXT) ENGINE=MyISAM;
+
+sync_slave_with_master;
+
+connection master;
+
+INSERT INTO `t1`(`f1`) VALUES ('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa2048');
+
+
+#
+# Bug#42914: The slave I/O thread must stop after trying to read the above
+# event, However there is no Last_IO_Error report.
+#
+
+# The slave I/O thread must stop after trying to read the above event
+connection slave;
+# 1153 = ER_NET_PACKET_TOO_LARGE
+--let $slave_io_errno= 1153
+--let $show_slave_io_error= 1
+--source include/wait_for_slave_io_error.inc
+
+# TODO: this is needed because of BUG#55790. Remove once that is fixed.
+--source include/stop_slave_sql.inc
+
+#
+# Bug#42914: On the master, if a binary log event is larger than
+# max_allowed_packet, the error message ER_MASTER_FATAL_ERROR_READING_BINLOG
+# is sent to a slave when it requests a dump from the master, thus leading the
+# I/O thread to stop. However, there is no Last_IO_Error reported.
+#
+
+--let $rpl_only_running_threads= 1
+--source include/rpl_reset.inc
+--connection master
+DROP TABLE t1;
+--sync_slave_with_master
+
+
+connection master;
+CREATE TABLE t1 (f1 int PRIMARY KEY, f2 LONGTEXT, f3 LONGTEXT) ENGINE=MyISAM;
+sync_slave_with_master;
+
+connection master;
+INSERT INTO t1(f1, f2, f3) VALUES(1, REPEAT('a', @@global.max_allowed_packet), REPEAT('b', @@global.max_allowed_packet));
+
+connection slave;
+# The slave I/O thread must stop after receiving
+# 1153 = ER_NET_PACKET_TOO_LARGE
+--let $slave_io_errno= 1153
+--let $show_slave_io_error= 1
+--source include/wait_for_slave_io_error.inc
+
+# Remove the bad binlog and clear error status on slave.
+STOP SLAVE;
+RESET SLAVE;
+--connection master
+RESET MASTER;
+
+
+#
+# BUG#55322: SHOW BINLOG EVENTS increases @@SESSION.MAX_ALLOWED_PACKET
+#
+# In BUG#55322, @@session.max_allowed_packet increased each time SHOW
+# BINLOG EVENTS was issued. To verify that this bug is fixed, we
+# execute SHOW BINLOG EVENTS twice and check that max_allowed_packet
+# never changes. We turn off the result log because we don't care
+# about the contents of the binlog.
+
+--disable_result_log
+SET @max_allowed_packet_0= @@session.max_allowed_packet;
+SHOW BINLOG EVENTS;
+SET @max_allowed_packet_1= @@session.max_allowed_packet;
+SHOW BINLOG EVENTS;
+SET @max_allowed_packet_2= @@session.max_allowed_packet;
+--enable_result_log
+if (`SELECT NOT(@max_allowed_packet_0 = @max_allowed_packet_1 AND @max_allowed_packet_1 = @max_allowed_packet_2)`)
+{
+ --echo ERROR: max_allowed_packet changed after executing SHOW BINLOG EVENTS
+ --source include/show_rpl_debug_info.inc
+ SELECT @max_allowed_packet_0, @max_allowed_packet_1, @max_allowed_packet_2;
+ --die @max_allowed_packet changed after executing SHOW BINLOG EVENTS
+}
+
+
+--echo ==== clean up ====
+connection master;
+DROP TABLE t1;
+eval SET @@global.max_allowed_packet= $old_max_allowed_packet;
+eval SET @@global.net_buffer_length= $old_net_buffer_length;
+eval SET @@global.slave_max_allowed_packet= $old_slave_max_allowed_packet;
+# slave is stopped
+connection slave;
+DROP TABLE t1;
+
+# Clear Last_IO_Error
+RESET SLAVE;
+
+--source include/rpl_end.inc
+# End of tests
diff --git a/mysql-test/suite/rpl/t/rpl_parallel2.test b/mysql-test/suite/rpl/t/rpl_parallel2.test
new file mode 100644
index 00000000..8934b15e
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_parallel2.test
@@ -0,0 +1,230 @@
+--source include/have_debug.inc
+--source include/have_innodb.inc
+--source include/have_binlog_format_statement.inc
+--let $rpl_topology=1->2
+--source include/rpl_init.inc
+
+--echo *** MDEV-5509: Incorrect value for Seconds_Behind_Master if parallel replication ***
+
+--connection server_2
+SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads;
+set @old_parallel_mode= @@GLOBAL.slave_parallel_mode;
+--source include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=5;
+set global slave_parallel_mode= optimistic;
+--source include/start_slave.inc
+
+--connection server_1
+CREATE TABLE t1 (a INT PRIMARY KEY, b INT);
+CALL mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement is unsafe because it uses a system function that may return a different value on the slave");
+--save_master_pos
+
+--connection server_2
+--sync_with_master
+
+--connection server_1
+INSERT INTO t1 VALUES (1,sleep(2));
+--save_master_pos
+
+--connection server_2
+--sync_with_master
+
+# The slave position (which --sync_with_master waits for) is updated just
+# before the Seconds_Behind_Master. So we have to wait for the zero status
+# to appear, otherwise there is a small window between --sync_with_master
+# and SHOW SLAVE STATUS where we can see a non-zero value.
+--let $slave_param= Seconds_Behind_Master
+--let $slave_param_value= 0
+--source include/wait_for_slave_param.inc
+--echo Seconds_Behind_Master should be zero here because the slave is fully caught up and idle.
+--let $status_items= Seconds_Behind_Master
+--source include/show_slave_status.inc
+
+
+--echo *** MDEV-8294: Inconsistent behavior of slave parallel threads at runtime ***
+
+--connection server_1
+INSERT INTO t1 VALUES (10,0);
+# Force a duplicate key error on the slave.
+SET sql_log_bin= 0;
+DELETE FROM t1 WHERE a=10;
+SET sql_log_bin= 1;
+INSERT INTO t1 VALUES (10,0);
+--save_master_pos
+SELECT * FROM t1 WHERE a >= 10 ORDER BY a;
+
+--connection server_2
+--let $slave_sql_errno= 1062
+--source include/wait_for_slave_sql_error.inc
+
+# At this point, the worker threads should have stopped also.
+--let $wait_condition= SELECT COUNT(*)=0 FROM information_schema.processlist WHERE User = "system user" AND State = "Waiting for work from SQL thread";
+--source include/wait_condition.inc
+
+# Check that the pool can still be resized, but remains inactive as no slave
+# SQL thread is running.
+SET GLOBAL slave_parallel_threads=8;
+--let $wait_condition= SELECT COUNT(*)=0 FROM information_schema.processlist WHERE User = "system user" AND State = "Waiting for work from SQL thread";
+--source include/wait_condition.inc
+
+STOP SLAVE;
+# At this point, the worker threads should have stopped.
+--let $wait_condition= SELECT COUNT(*)=0 FROM information_schema.processlist WHERE User = "system user" AND State = "Waiting for work from SQL thread";
+--source include/wait_condition.inc
+
+
+SET GLOBAL sql_slave_skip_counter= 1;
+--source include/start_slave.inc
+# At this point, the worker threads should have been spawned.
+--let $wait_condition= SELECT COUNT(*)=8 FROM information_schema.processlist WHERE User = "system user" AND State = "Waiting for work from SQL thread";
+--source include/wait_condition.inc
+--sync_with_master
+SELECT * FROM t1 WHERE a >= 10 ORDER BY a;
+
+
+--echo *** MDEV-7818: Deadlock occurring with parallel replication and FTWRL ***
+
+--connection server_1
+CREATE TABLE t2 (a INT PRIMARY KEY, b INT) ENGINE=InnoDB;
+INSERT INTO t2 VALUES (1,0), (2,0), (3,0);
+--save_master_pos
+
+--connection server_2
+--sync_with_master
+--source include/stop_slave.inc
+
+--connection server_1
+# Create a group commit with two transactions, will be used to provoke the
+# problematic thread interaction with FTWRL on the slave.
+SET @old_dbug= @@SESSION.debug_dbug;
+SET @commit_id= 4242;
+SET SESSION debug_dbug="+d,binlog_force_commit_id";
+
+BEGIN;
+UPDATE t2 SET b=b+1 WHERE a=2;
+COMMIT;
+
+BEGIN;
+INSERT INTO t2 VALUES (4,10);
+COMMIT;
+
+SET SESSION debug_dbug= @old_dbug;
+
+INSERT INTO t2 VALUES (5,0);
+INSERT INTO t2 VALUES (6,0);
+INSERT INTO t2 VALUES (7,0);
+INSERT INTO t2 VALUES (8,0);
+INSERT INTO t2 VALUES (9,0);
+INSERT INTO t2 VALUES (10,0);
+INSERT INTO t2 VALUES (11,0);
+INSERT INTO t2 VALUES (12,0);
+INSERT INTO t2 VALUES (13,0);
+INSERT INTO t2 VALUES (14,0);
+INSERT INTO t2 VALUES (15,0);
+INSERT INTO t2 VALUES (16,0);
+INSERT INTO t2 VALUES (17,0);
+INSERT INTO t2 VALUES (18,0);
+INSERT INTO t2 VALUES (19,0);
+--save_master_pos
+
+--connection server_2
+
+--connect (s1, 127.0.0.1, root,, test, $SLAVE_MYPORT,)
+# Block one transaction on a row lock.
+BEGIN;
+SELECT * FROM t2 WHERE a=2 FOR UPDATE;
+
+--connection server_2
+
+# Wait for slave thread of the other transaction to have the commit lock.
+--source include/start_slave.inc
+--let $wait_condition= SELECT COUNT(*) > 0 FROM information_schema.processlist WHERE state = "Waiting for prior transaction to commit"
+--source include/wait_condition.inc
+
+--connect (s2, 127.0.0.1, root,, test, $SLAVE_MYPORT,)
+send FLUSH TABLES WITH READ LOCK;
+# The bug was that at this point we were deadlocked.
+# The FTWRL command would wait forever for T2 to commit.
+# T2 would wait for T1 to commit first, but T1 is waiting for
+# the global read lock to be released.
+
+--connection s1
+# Release the lock that blocs T1 from replicating.
+COMMIT;
+
+--connection s1
+send STOP SLAVE;
+
+--connection s2
+reap;
+
+--connection server_1
+SELECT * FROM t2 ORDER BY a;
+
+--connection s2
+UNLOCK TABLES;
+
+SELECT "after UNLOCK TABLES" as state;
+
+--connection s1
+reap;
+
+SELECT "after reap of STOP SLAVE" as state;
+
+--connection server_2
+--source include/wait_for_slave_to_stop.inc
+--source include/start_slave.inc
+--sync_with_master
+
+SELECT * FROM t2 ORDER BY a;
+
+
+
+--echo *** MDEV-8318: Assertion `!pool->busy' failed in pool_mark_busy(rpl_parallel_thread_pool*) on concurrent FTWRL ***
+
+--connection server_1
+LOCK TABLE t2 WRITE;
+
+
+--connect (m1,localhost,root,,test)
+--connection m1
+--let $cid=`SELECT CONNECTION_ID()`
+send FLUSH TABLES WITH READ LOCK;
+
+--connect (m2,localhost,root,,test)
+# We cannot force the race with DEBUG_SYNC, because the race does not
+# exist after fixing the bug. At best we could force a debug sync to
+# time out, which is effectively just a sleep.
+# So just put a small sleep here; it is enough to trigger the bug in
+# most run before the bug fix, and the code should work correctly
+# however the thread scheduling happens.
+--sleep 0.1
+send FLUSH TABLES WITH READ LOCK;
+
+--connection server_1
+--replace_result $cid CID
+eval KILL QUERY $cid;
+
+--connection m1
+--error ER_QUERY_INTERRUPTED
+reap;
+
+--connection server_1
+UNLOCK TABLES;
+
+--connection m2
+reap;
+UNLOCK TABLES;
+
+
+# Clean up.
+--connection server_2
+--source include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=@old_parallel_threads;
+set global slave_parallel_mode= @old_parallel_mode;
+--source include/start_slave.inc
+
+--connection server_1
+DROP TABLE t1, t2;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_parallel_29322.test b/mysql-test/suite/rpl/t/rpl_parallel_29322.test
new file mode 100644
index 00000000..67596059
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_parallel_29322.test
@@ -0,0 +1,64 @@
+--echo #
+--echo # MDEV-29322 ASAN use-after-free options_written_to_bin_log
+--echo #
+
+# The tests verify that at query execution slave parallel workers successfully
+# find a correct options_written_to_bin_log value associated with the query.
+# There are three test branches, A and B take care of different server version
+# binlogs. The homogeneous binlog case of C. branch is also for how-to-reproduce
+# the bug, may need few --repeat :s though.
+
+--source include/have_binlog_format_mixed.inc
+--source include/master-slave.inc
+
+--echo # A. set the master and slave explicit_defaults_for_timestamp values crisscross to (1,0)
+--let $same_version_binlogs=0
+
+--connection master
+# Configure master and slave with different values of the following variable:
+set @sav.explicit_defaults_for_timestamp = @@session.explicit_defaults_for_timestamp;
+set @@session.explicit_defaults_for_timestamp = 1;
+--connection slave
+# slave must produce the master version of the table definition and its data
+set @sav.explicit_defaults_for_timestamp = @@global.explicit_defaults_for_timestamp;
+set global explicit_defaults_for_timestamp = 0;
+# the global var gets changed in the included file
+set @sav.slave_parallel_workers = @@global.slave_parallel_workers;
+--source include/stop_slave.inc
+set @@global.slave_parallel_workers = 1;
+--source include/start_slave.inc
+
+--source suite/rpl/include/rpl_parallel_29322.inc
+
+--echo # B. alternate the master and slave vars' values to (0,1)
+
+--connection master
+# Configure master and slave with different values of the following variable:
+set @@session.explicit_defaults_for_timestamp = 0;
+--connection slave
+# slave must produce the master version of the table definition and its data
+set @@global.explicit_defaults_for_timestamp = 1;
+
+--source suite/rpl/include/rpl_parallel_29322.inc
+
+
+--echo # C. the bug case on the same version binlogs also to demo on the patch's base
+--let $same_version_binlogs=1
+# with more workers the bug shows more likeky on the patch's base slave.
+--source include/stop_slave.inc
+set @@global.slave_parallel_workers = 4;
+--source include/start_slave.inc
+
+--source suite/rpl/include/rpl_parallel_29322.inc
+
+# cleanup
+--connection master
+set @@session.explicit_defaults_for_timestamp = @sav.explicit_defaults_for_timestamp;
+--connection slave
+set @@global.explicit_defaults_for_timestamp = @sav.explicit_defaults_for_timestamp;
+--source include/stop_slave.inc
+set @@global.slave_parallel_workers = @sav.slave_parallel_workers;
+--source include/start_slave.inc
+
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_parallel_analyze.test b/mysql-test/suite/rpl/t/rpl_parallel_analyze.test
new file mode 100644
index 00000000..921c6f02
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_parallel_analyze.test
@@ -0,0 +1,84 @@
+# The test file is created to prove fixes to
+# MDEV-30323 Some DDLs like ANALYZE can complete on parallel slave out of order
+# Debug-sync tests aiming at parallel replication of ADMIN commands
+# are welcome here.
+
+--source include/have_innodb.inc
+--source include/have_debug_sync.inc
+--source include/master-slave.inc
+
+--echo # Initialize
+--connection slave
+ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
+
+--echo # Setup data
+--connection master
+CREATE TABLE t1 (a int PRIMARY KEY) ENGINE=InnoDB;
+CREATE TABLE ta (a int);
+--let $pre_load_gtid=`SELECT @@last_gtid`
+--source include/save_master_gtid.inc
+
+--connection slave
+--source include/sync_with_master_gtid.inc
+
+--source suite/rpl/include/create_or_drop_sync_func.inc
+
+# configure MDEV-30323 slave
+--source include/stop_slave.inc
+SET @old_parallel_threads =@@GLOBAL.slave_parallel_threads;
+SET @old_parallel_mode =@@GLOBAL.slave_parallel_mode;
+SET @old_gtid_strict_mode =@@GLOBAL.gtid_strict_mode;
+SET GLOBAL slave_parallel_threads=10;
+SET GLOBAL slave_parallel_mode=conservative;
+SET GLOBAL gtid_strict_mode=ON;
+--source include/start_slave.inc
+
+# MDEV-30323 setup needs two group of events the first of which is a DML
+# and ANALYZE is the 2nd.
+# The latter is made to race in slave execution over the DML thanks
+# to a DML latency simulation.
+# In the fixed case the race-over should not be a problem: ultimately
+# ANALYZE must wait for its turn to update slave@@global.gtid_binlog_pos.
+# Otherwise the reported OOO error must be issued.
+
+--connection master
+SET @old_format= @@SESSION.binlog_format;
+SET binlog_format=statement;
+INSERT INTO t1 VALUES (foo(1, 'rpl_parallel_after_mark_start_commit WAIT_FOR sig_go', ''));
+
+ANALYZE TABLE ta;
+--source include/save_master_gtid.inc
+
+--connection slave
+--let $wait_condition= SELECT COUNT(*) = 1 FROM information_schema.processlist WHERE state = "Waiting for prior transaction to commit"
+--source include/wait_condition.inc
+
+SELECT info FROM information_schema.processlist WHERE state = "Waiting for prior transaction to commit";
+if (`select strcmp(@@global.gtid_binlog_pos, '$pre_load_gtid') <> 0 or strcmp(@@global.gtid_slave_pos, '$pre_load_gtid') <> 0`)
+{
+ --let $bs=`SELECT @@global.gtid_binlog_pos`
+ --let $es=`SELECT @@global.gtid_slave_pos`
+ --echo Mismatch between expected $pre_load_gtid state and the actual binlog state " @@global.gtid_binlog_pos = $bs or/and slave execution state @@global.gtid_slave_pos = $es.
+ --die
+}
+
+set @@debug_sync="now signal sig_go";
+--source include/sync_with_master_gtid.inc
+
+--echo # Cleanup
+--connection master
+DROP TABLE t1,ta;
+--let $create_or_drop=drop
+--source suite/rpl/include/create_or_drop_sync_func.inc
+
+--source include/save_master_gtid.inc
+
+--connection slave
+--source include/sync_with_master_gtid.inc
+--source include/stop_slave.inc
+SET @@GLOBAL.slave_parallel_threads=@old_parallel_threads;
+SET @@GLOBAL.slave_parallel_mode =@old_parallel_mode;
+SET @@GLOBAL.gtid_strict_mode =@old_gtid_strict_mode;
+--source include/start_slave.inc
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_parallel_analyze_table_hang.test b/mysql-test/suite/rpl/t/rpl_parallel_analyze_table_hang.test
new file mode 100644
index 00000000..62a7501c
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_parallel_analyze_table_hang.test
@@ -0,0 +1,73 @@
+--echo *** MDEV-7888: ANALYZE TABLE does wakeup_subsequent_commits(), causing wrong binlog order and parallel replication hang ***
+--source include/have_innodb.inc
+--source include/have_debug.inc
+--source include/have_debug_sync.inc
+--source include/master-slave.inc
+
+--connection server_2
+SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads;
+SET @old_parallel_mode=@@GLOBAL.slave_parallel_mode;
+--source include/stop_slave.inc
+SET GLOBAL slave_parallel_mode='conservative';
+SET GLOBAL slave_parallel_threads=10;
+CHANGE MASTER TO master_use_gtid=slave_pos;
+--source include/start_slave.inc
+
+--connection server_1
+ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
+CREATE TABLE t2 (a int PRIMARY KEY) ENGINE=InnoDB;
+CREATE TABLE t3 (a INT PRIMARY KEY, b INT) ENGINE=InnoDB;
+--save_master_pos
+
+--connection server_2
+--sync_with_master
+--source include/stop_slave.inc
+SET @old_dbug= @@GLOBAL.debug_dbug;
+SET GLOBAL debug_dbug= '+d,inject_analyze_table_sleep';
+
+--connection server_1
+# Inject two group commits. The bug was that ANALYZE TABLE would call
+# wakeup_subsequent_commits() too early, allowing the following transaction
+# in the same group to run ahead and binlog and free the GCO. Then we get
+# wrong binlog order and later access freed GCO, which causes lost wakeup
+# of following GCO and thus replication hang.
+# We injected a small sleep in ANALYZE to make the race easier to hit (this
+# can only cause false negatives in versions with the bug, not false positives,
+# so sleep is ok here. And it's in general not possible to trigger reliably
+# the race with debug_sync, since the bugfix makes the race impossible).
+
+SET @old_dbug= @@SESSION.debug_dbug;
+SET SESSION debug_dbug="+d,binlog_force_commit_id";
+
+# Group commit with cid=10000, two event groups.
+SET @commit_id= 10000;
+ANALYZE TABLE t2;
+INSERT INTO t3 VALUES (120, 0);
+
+# Group commit with cid=10001, one event group.
+SET @commit_id= 10001;
+INSERT INTO t3 VALUES (121, 0);
+
+SET SESSION debug_dbug=@old_dbug;
+
+SELECT * FROM t3 WHERE a >= 120 ORDER BY a;
+--source include/save_master_gtid.inc
+
+--connection server_2
+--source include/start_slave.inc
+--source include/sync_with_master_gtid.inc
+
+SELECT * FROM t3 WHERE a >= 120 ORDER BY a;
+
+# Clean up.
+--source include/stop_slave.inc
+SET GLOBAL debug_dbug= @old_dbug;
+SET GLOBAL slave_parallel_threads=@old_parallel_threads;
+SET GLOBAL slave_parallel_mode=@old_parallel_mode;
+--source include/start_slave.inc
+
+--connection server_1
+DROP TABLE t2,t3;
+
+--source include/rpl_end.inc
+
diff --git a/mysql-test/suite/rpl/t/rpl_parallel_autoinc.test b/mysql-test/suite/rpl/t/rpl_parallel_autoinc.test
new file mode 100644
index 00000000..0e96b4df
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_parallel_autoinc.test
@@ -0,0 +1,140 @@
+--source include/have_binlog_format_statement.inc
+--source include/have_innodb.inc
+--source include/master-slave.inc
+
+--echo MDEV-31482: Lock wait timeout with INSERT-SELECT, autoinc, and statement-based replication
+
+# The scenario is transactions T1, T2, T3:
+#
+# T1 is waiting for T3 on an autoinc lock
+# T2 is waiting for T1 to commit
+# T3 is waiting on a normal row lock held by T2
+#
+# This caused a hang until innodb_lock_wait_timeout, because autoinc
+# locks were not reported to the in-order parallel replication, so T3
+# was not deadlock killed.
+
+--let $lock_wait_timeout=20
+
+--let $rpl_connection_name= slave2
+--let $rpl_server_number= 2
+--source include/rpl_connect.inc
+
+--let $rpl_connection_name= slave3
+--let $rpl_server_number= 2
+--source include/rpl_connect.inc
+
+--connection master
+ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
+
+# A table as destination for INSERT-SELECT
+CREATE TABLE t1 (a INT PRIMARY KEY AUTO_INCREMENT, b INT, c INT, INDEX (c)) ENGINE=InnoDB;
+INSERT INTO t1 (b,c) VALUES (0, 1), (0, 1), (0, 2), (0,3), (0, 5), (0, 7), (0, 8);
+
+# A table as source for INSERT-SELECT.
+CREATE TABLE t2 (a INT PRIMARY KEY, b INT) ENGINE=InnoDB;
+INSERT INTO t2 VALUES (10,1), (20,2), (30,3), (40,4), (50,5);
+
+# A table to help order slave worker threads to setup the desired scenario.
+CREATE TABLE t3 (a VARCHAR(20) PRIMARY KEY, b INT) ENGINE=InnoDB;
+INSERT INTO t3 VALUES ('row for T1', 0), ('row for T2', 0), ('row for T3', 0);
+--source include/save_master_gtid.inc
+
+--connection slave
+--source include/sync_with_master_gtid.inc
+--source include/stop_slave.inc
+--let $save_innodb_lock_wait_timeout= `SELECT @@global.innodb_lock_wait_timeout`
+--let $save_slave_parallel_threads= `SELECT @@global.slave_parallel_threads`
+--let $save_slave_parallel_mode= `SELECT @@global.slave_parallel_mode`
+set @@global.slave_parallel_threads= 3;
+set @@global.slave_parallel_mode= OPTIMISTIC;
+eval set @@global.innodb_lock_wait_timeout= $lock_wait_timeout;
+
+--connection master
+# Transaction T1.
+BEGIN;
+UPDATE t3 SET b=b+1 where a="row for T1";
+INSERT INTO t1(b, c) SELECT 1, t2.b FROM t2 WHERE a=10;
+COMMIT;
+
+# Transaction T2.
+DELETE FROM t1 WHERE c >= 4 and c < 6;
+
+# Transaction T3.
+BEGIN;
+UPDATE t3 SET b=b+1 where a="row for T3";
+INSERT INTO t1(b, c) SELECT 3, t2.b FROM t2 WHERE a >= 20 AND a <= 40;
+COMMIT;
+
+--source include/save_master_gtid.inc
+
+--connection slave1
+# Temporarily block T1 to create the scheduling that triggers the bug.
+BEGIN;
+SELECT * FROM t3 WHERE a="row for T1" FOR UPDATE;
+
+--connection slave2
+# Temporarily block T3 from starting (so T2 can reach commit).
+BEGIN;
+SELECT * FROM t3 WHERE a="row for T3" FOR UPDATE;
+
+--connection slave3
+# This critical step blocks T3 after it has inserted its first row,
+# and thus taken the auto-increment lock, but before it has reached
+# the point where it gets a row lock wait on T2. Even though
+# auto-increment lock waits were not reported due to the bug,
+# transitive lock waits (T1 waits on autoinc of T3 which waits on row
+# on T2) _were_ reported as T1 waiting on T2, and thus a deadlock kill
+# happened and the bug was not triggered.
+BEGIN;
+DELETE FROM t2 WHERE a=30;
+
+--connection slave
+--source include/start_slave.inc
+
+# First let T2 complete until it is waiting for T1 to commit.
+--let $wait_condition= SELECT count(*)=1 FROM information_schema.processlist WHERE state='Waiting for prior transaction to commit' and command LIKE 'Slave_worker';
+--source include/wait_condition.inc
+
+# Then let T3 reach the point where it has obtained the autoinc lock,
+# but it is not yet waiting for a row lock held by T2.
+--connection slave2
+ROLLBACK;
+--let $wait_condition= SELECT count(*)=1 FROM information_schema.processlist WHERE state='Sending data' and info LIKE 'INSERT INTO t1(b, c) SELECT 3, t2.b%' and time_ms > 500 and command LIKE 'Slave_worker';
+--source include/wait_condition.inc
+
+# Now let T1 continue, while T3 is holding the autoinc lock but before
+# it is waiting for T2. Wait a short while to give the hang a chance to
+# happen; T1 needs to get to request the autoinc lock before we let T3
+# continue. (There's a small chance the sleep will be too small, which will
+# let the test occasionally pass on non-fixed server).
+--connection slave1
+ROLLBACK;
+--sleep 0.5
+
+# Now let T3 continue; the bug was that this lead to an undetected
+# deadlock that remained until innodb lock wait timeout.
+--connection slave3
+ROLLBACK;
+
+--connection slave
+--let $slave_timeout= `SELECT $lock_wait_timeout/2`
+--source include/sync_with_master_gtid.inc
+--let $slave_timeout=
+SELECT * FROM t1 ORDER BY a;
+SELECT * FROM t2 ORDER BY a;
+SELECT * FROM t3 ORDER BY a;
+
+# Cleanup.
+--connection master
+CALL mtr.add_suppression("Unsafe statement written to the binary log using statement format");
+DROP TABLE t1, t2, t3;
+
+--connection slave
+--source include/stop_slave.inc
+eval SET @@global.slave_parallel_threads= $save_slave_parallel_threads;
+eval SET @@global.slave_parallel_mode= $save_slave_parallel_mode;
+eval SET @@global.innodb_lock_wait_timeout= $save_innodb_lock_wait_timeout;
+--source include/start_slave.inc
+SELECT @@GLOBAL.innodb_autoinc_lock_mode;
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_parallel_charset.test b/mysql-test/suite/rpl/t/rpl_parallel_charset.test
new file mode 100644
index 00000000..3e0f4913
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_parallel_charset.test
@@ -0,0 +1,56 @@
+--source include/have_binlog_format_statement.inc
+--let $rpl_topology=1->2
+--source include/rpl_init.inc
+
+--echo *** MDEV-6156: Parallel replication incorrectly caches charset between worker threads ***
+
+--connection server_2
+SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads;
+--source include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=5;
+--source include/start_slave.inc
+
+--connection server_1
+CREATE TABLE t1 (a INT PRIMARY KEY, b VARCHAR(100) CHARACTER SET utf8);
+SHOW CREATE TABLE t1;
+SET character_set_client=latin1;
+INSERT INTO t1 VALUES (1, 'Rødgrød med fløde 1');
+INSERT INTO t1 VALUES (2, 'Rødgrød med fløde 2');
+INSERT INTO t1 VALUES (3, 'Rødgrød med fløde 3');
+INSERT INTO t1 VALUES (4, 'Rødgrød med fløde 4');
+INSERT INTO t1 VALUES (5, 'Rødgrød med fløde 5');
+INSERT INTO t1 VALUES (6, 'Rødgrød med fløde 6');
+INSERT INTO t1 VALUES (7, 'Rødgrød med fløde 7');
+INSERT INTO t1 VALUES (8, 'Rødgrød med fløde 8');
+INSERT INTO t1 VALUES (9, 'Rødgrød med fløde 9');
+INSERT INTO t1 VALUES (10, 'Rødgrød med fløde 10');
+SET character_set_client=utf8;
+INSERT INTO t1 VALUES (11, 'Rødgrød med fløde 1');
+INSERT INTO t1 VALUES (12, 'Rødgrød med fløde 2');
+INSERT INTO t1 VALUES (13, 'Rødgrød med fløde 3');
+INSERT INTO t1 VALUES (14, 'Rødgrød med fløde 4');
+INSERT INTO t1 VALUES (15, 'Rødgrød med fløde 5');
+INSERT INTO t1 VALUES (16, 'Rødgrød med fløde 6');
+INSERT INTO t1 VALUES (17, 'Rødgrød med fløde 7');
+INSERT INTO t1 VALUES (18, 'Rødgrød med fløde 8');
+INSERT INTO t1 VALUES (19, 'Rødgrød med fløde 9');
+INSERT INTO t1 VALUES (20, 'Rødgrød med fløde 10');
+SET character_set_results=utf8;
+SELECT * FROM t1 ORDER BY a;
+--save_master_pos
+
+--connection server_2
+--sync_with_master
+SET character_set_results=utf8;
+SELECT * FROM t1 ORDER BY a;
+
+
+--connection server_2
+--source include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=@old_parallel_threads;
+--source include/start_slave.inc
+
+--connection server_1
+DROP TABLE t1;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_parallel_conflicts.test b/mysql-test/suite/rpl/t/rpl_parallel_conflicts.test
new file mode 100644
index 00000000..0ba6a2b2
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_parallel_conflicts.test
@@ -0,0 +1,269 @@
+--source include/have_innodb.inc
+--source include/have_debug.inc
+--source include/have_debug_sync.inc
+--source include/master-slave.inc
+
+--echo *** MDEV-7847: "Slave worker thread retried transaction 10 time(s) in vain, giving up", followed by replication hanging ***
+--echo *** MDEV-7882: Excessive transaction retry in parallel replication ***
+
+--connection server_1
+ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
+CREATE TABLE t7 (a int PRIMARY KEY, b INT) ENGINE=InnoDB;
+CREATE TABLE t8 (a int PRIMARY KEY, b INT) ENGINE=InnoDB;
+--save_master_pos
+
+--connection server_2
+--sync_with_master
+--source include/stop_slave.inc
+SET @old_mode= @@GLOBAL.slave_parallel_mode;
+SET GLOBAL slave_parallel_mode='conservative';
+SET @old_threads= @@GLOBAL.slave_parallel_threads;
+SET GLOBAL slave_parallel_threads=40;
+SET @old_transaction_retries= @@GLOBAL.slave_transaction_retries;
+SET GLOBAL slave_transaction_retries=5;
+
+# Using dbug error injection, we artificially create event groups with a lot of
+# conflicting transactions in each event group. The bugs were originally seen
+# "in the wild" with transactions that did not conflict on the master, and only
+# conflicted very rarely on the slave (maybe some edge case with InnoDB btree
+# page splits or something like that). The event groups here loosely reflect
+# the structure of the original failure's group commits.
+
+
+--connection server_1
+INSERT INTO t7 VALUES (1,1), (2,2), (3,3), (4,4), (5,5);
+SET @old_dbug= @@SESSION.debug_dbug;
+SET @commit_id= 42;
+SET SESSION debug_dbug="+d,binlog_force_commit_id";
+INSERT INTO t8 VALUES (1,1);
+INSERT INTO t8 VALUES (2,2);
+INSERT INTO t8 VALUES (3,3);
+INSERT INTO t8 VALUES (4,4);
+INSERT INTO t8 VALUES (5,5);
+INSERT INTO t8 VALUES (6,6);
+INSERT INTO t8 VALUES (7,7);
+INSERT INTO t8 VALUES (8,8);
+
+UPDATE t7 SET b=9 WHERE a=3;
+UPDATE t7 SET b=10 WHERE a=3;
+UPDATE t7 SET b=11 WHERE a=3;
+
+INSERT INTO t8 VALUES (12,12);
+INSERT INTO t8 VALUES (13,13);
+
+UPDATE t7 SET b=14 WHERE a=3;
+UPDATE t7 SET b=15 WHERE a=3;
+
+INSERT INTO t8 VALUES (16,16);
+
+UPDATE t7 SET b=17 WHERE a=3;
+
+INSERT INTO t8 VALUES (18,18);
+INSERT INTO t8 VALUES (19,19);
+
+UPDATE t7 SET b=20 WHERE a=3;
+
+INSERT INTO t8 VALUES (21,21);
+
+UPDATE t7 SET b=22 WHERE a=3;
+
+INSERT INTO t8 VALUES (23,24);
+INSERT INTO t8 VALUES (24,24);
+
+UPDATE t7 SET b=25 WHERE a=3;
+
+INSERT INTO t8 VALUES (26,26);
+
+UPDATE t7 SET b=27 WHERE a=3;
+
+BEGIN;
+INSERT INTO t8 VALUES (28,28);
+INSERT INTO t8 VALUES (29,28), (30,28);
+INSERT INTO t8 VALUES (31,28);
+INSERT INTO t8 VALUES (32,28);
+INSERT INTO t8 VALUES (33,28);
+INSERT INTO t8 VALUES (34,28);
+INSERT INTO t8 VALUES (35,28);
+INSERT INTO t8 VALUES (36,28);
+INSERT INTO t8 VALUES (37,28);
+INSERT INTO t8 VALUES (38,28);
+INSERT INTO t8 VALUES (39,28);
+INSERT INTO t8 VALUES (40,28);
+INSERT INTO t8 VALUES (41,28);
+INSERT INTO t8 VALUES (42,28);
+COMMIT;
+
+
+SET @commit_id=43;
+INSERT INTO t8 VALUES (43,43);
+INSERT INTO t8 VALUES (44,44);
+
+UPDATE t7 SET b=45 WHERE a=3;
+
+INSERT INTO t8 VALUES (46,46);
+INSERT INTO t8 VALUES (47,47);
+
+UPDATE t7 SET b=48 WHERE a=3;
+
+INSERT INTO t8 VALUES (49,49);
+INSERT INTO t8 VALUES (50,50);
+
+
+SET @commit_id=44;
+INSERT INTO t8 VALUES (51,51);
+INSERT INTO t8 VALUES (52,52);
+
+UPDATE t7 SET b=53 WHERE a=3;
+
+INSERT INTO t8 VALUES (54,54);
+INSERT INTO t8 VALUES (55,55);
+
+UPDATE t7 SET b=56 WHERE a=3;
+
+INSERT INTO t8 VALUES (57,57);
+
+UPDATE t7 SET b=58 WHERE a=3;
+
+INSERT INTO t8 VALUES (58,58);
+INSERT INTO t8 VALUES (59,59);
+INSERT INTO t8 VALUES (60,60);
+INSERT INTO t8 VALUES (61,61);
+
+UPDATE t7 SET b=62 WHERE a=3;
+
+INSERT INTO t8 VALUES (63,63);
+INSERT INTO t8 VALUES (64,64);
+INSERT INTO t8 VALUES (65,65);
+INSERT INTO t8 VALUES (66,66);
+
+UPDATE t7 SET b=67 WHERE a=3;
+
+INSERT INTO t8 VALUES (68,68);
+
+UPDATE t7 SET b=69 WHERE a=3;
+UPDATE t7 SET b=70 WHERE a=3;
+UPDATE t7 SET b=71 WHERE a=3;
+
+INSERT INTO t8 VALUES (72,72);
+
+UPDATE t7 SET b=73 WHERE a=3;
+UPDATE t7 SET b=74 WHERE a=3;
+UPDATE t7 SET b=75 WHERE a=3;
+UPDATE t7 SET b=76 WHERE a=3;
+
+INSERT INTO t8 VALUES (77,77);
+
+UPDATE t7 SET b=78 WHERE a=3;
+
+INSERT INTO t8 VALUES (79,79);
+
+UPDATE t7 SET b=80 WHERE a=3;
+
+INSERT INTO t8 VALUES (81,81);
+
+UPDATE t7 SET b=82 WHERE a=3;
+
+INSERT INTO t8 VALUES (83,83);
+
+UPDATE t7 SET b=84 WHERE a=3;
+
+
+SET @commit_id=45;
+INSERT INTO t8 VALUES (85,85);
+UPDATE t7 SET b=86 WHERE a=3;
+INSERT INTO t8 VALUES (87,87);
+
+
+SET @commit_id=46;
+INSERT INTO t8 VALUES (88,88);
+INSERT INTO t8 VALUES (89,89);
+INSERT INTO t8 VALUES (90,90);
+
+SET SESSION debug_dbug=@old_dbug;
+
+INSERT INTO t8 VALUES (91,91);
+INSERT INTO t8 VALUES (92,92);
+INSERT INTO t8 VALUES (93,93);
+INSERT INTO t8 VALUES (94,94);
+INSERT INTO t8 VALUES (95,95);
+INSERT INTO t8 VALUES (96,96);
+INSERT INTO t8 VALUES (97,97);
+INSERT INTO t8 VALUES (98,98);
+INSERT INTO t8 VALUES (99,99);
+
+
+SELECT * FROM t7 ORDER BY a;
+SELECT * FROM t8 ORDER BY a;
+--source include/save_master_gtid.inc
+
+
+--connection server_2
+--source include/start_slave.inc
+--source include/sync_with_master_gtid.inc
+SELECT * FROM t7 ORDER BY a;
+SELECT * FROM t8 ORDER BY a;
+
+--echo *** MDEV-8302: Duplicate key with parallel replication ***
+
+--connection server_2
+--source include/stop_slave.inc
+/* Inject a small sleep which makes the race easier to hit. */
+SET @old_dbug=@@GLOBAL.debug_dbug;
+SET GLOBAL debug_dbug="+d,inject_mdev8302";
+
+
+--connection server_1
+INSERT INTO t7 VALUES (100,1), (101,2), (102,3), (103,4), (104,5);
+
+# Artificially create a bunch of group commits with conflicting transactions.
+# The bug happened when T1 and T2 was in one group commit, and T3 was in the
+# following group commit. T2 is a DELETE of a row with same primary key as a
+# row that T3 inserts. T1 and T2 can conflict, causing T2 to be deadlock
+# killed after starting to commit. The bug was that T2 could roll back before
+# doing unmark_start_commit(); this could allow T3 to run before the retry
+# of T2, causing duplicate key violation.
+
+SET @old_dbug= @@SESSION.debug_dbug;
+SET @commit_id= 20000;
+SET SESSION debug_dbug="+d,binlog_force_commit_id";
+
+--let $n = 100
+--disable_query_log
+while ($n)
+{
+ eval UPDATE t7 SET b=b+1 WHERE a=100+($n MOD 5);
+ eval DELETE FROM t7 WHERE a=100+($n MOD 5);
+
+ SET @commit_id = @commit_id + 1;
+ eval INSERT INTO t7 VALUES (100+($n MOD 5), $n);
+ SET @commit_id = @commit_id + 1;
+ dec $n;
+}
+--enable_query_log
+SET SESSION debug_dbug=@old_dbug;
+
+
+SELECT * FROM t7 ORDER BY a;
+--source include/save_master_gtid.inc
+
+
+--connection server_2
+--source include/start_slave.inc
+--source include/sync_with_master_gtid.inc
+SELECT * FROM t7 ORDER BY a;
+
+--source include/stop_slave.inc
+SET GLOBAL debug_dbug=@old_dbug;
+SET GLOBAL slave_parallel_mode=@old_mode;
+SET GLOBAL slave_parallel_threads=@old_threads;
+SET GLOBAL slave_transaction_retries=@old_transaction_retries;
+
+# Clean up.
+--source include/start_slave.inc
+SET DEBUG_SYNC= 'RESET';
+
+--connection server_1
+DROP TABLE t7,t8;
+SET DEBUG_SYNC= 'RESET';
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_parallel_deadlock_corrupt_binlog.test b/mysql-test/suite/rpl/t/rpl_parallel_deadlock_corrupt_binlog.test
new file mode 100644
index 00000000..592ffd3b
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_parallel_deadlock_corrupt_binlog.test
@@ -0,0 +1,80 @@
+--echo *** MDEV-7335: Potential parallel slave deadlock with specific binlog corruption ***
+--source include/have_innodb.inc
+--source include/have_debug.inc
+--source include/have_debug_sync.inc
+--source include/master-slave.inc
+
+--connection server_2
+--source include/stop_slave.inc
+SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads;
+SET GLOBAL slave_parallel_threads=10;
+CHANGE MASTER TO master_use_gtid=slave_pos;
+--source include/start_slave.inc
+
+--connection server_1
+ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
+CREATE TABLE t2 (a int PRIMARY KEY) ENGINE=InnoDB;
+--save_master_pos
+
+--connection server_2
+--sync_with_master
+--source include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=1;
+SET @old_dbug= @@GLOBAL.debug_dbug;
+SET GLOBAL debug_dbug="+d,slave_discard_xid_for_gtid_0_x_1000";
+CALL mtr.add_suppression("Unexpected break of being relay-logged GTID");
+
+--connection server_1
+INSERT INTO t2 VALUES (101);
+INSERT INTO t2 VALUES (102);
+INSERT INTO t2 VALUES (103);
+INSERT INTO t2 VALUES (104);
+INSERT INTO t2 VALUES (105);
+# Inject a partial event group (missing XID at the end). The bug was that such
+# partial group was not handled appropriately, leading to server deadlock.
+SET gtid_seq_no=1000;
+INSERT INTO t2 VALUES (106);
+INSERT INTO t2 VALUES (107);
+INSERT INTO t2 VALUES (108);
+INSERT INTO t2 VALUES (109);
+INSERT INTO t2 VALUES (110);
+INSERT INTO t2 VALUES (111);
+INSERT INTO t2 VALUES (112);
+INSERT INTO t2 VALUES (113);
+INSERT INTO t2 VALUES (114);
+INSERT INTO t2 VALUES (115);
+INSERT INTO t2 VALUES (116);
+INSERT INTO t2 VALUES (117);
+INSERT INTO t2 VALUES (118);
+INSERT INTO t2 VALUES (119);
+INSERT INTO t2 VALUES (120);
+INSERT INTO t2 VALUES (121);
+INSERT INTO t2 VALUES (122);
+INSERT INTO t2 VALUES (123);
+INSERT INTO t2 VALUES (124);
+INSERT INTO t2 VALUES (125);
+INSERT INTO t2 VALUES (126);
+INSERT INTO t2 VALUES (127);
+INSERT INTO t2 VALUES (128);
+INSERT INTO t2 VALUES (129);
+INSERT INTO t2 VALUES (130);
+--source include/save_master_gtid.inc
+
+--connection server_2
+--source include/start_slave.inc
+--source include/sync_with_master_gtid.inc
+# The partial event group (a=106) should be rolled back and thus missing.
+SELECT * FROM t2 WHERE a >= 100 ORDER BY a;
+
+# Cleanup
+--source include/stop_slave.inc
+SET GLOBAL debug_dbug=@old_dbug;
+SET GLOBAL slave_parallel_threads=@old_parallel_threads;
+--source include/start_slave.inc
+SET DEBUG_SYNC= 'RESET';
+
+--connection server_1
+DROP TABLE t2;
+SET DEBUG_SYNC= 'RESET';
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_parallel_deadlock_victim.test b/mysql-test/suite/rpl/t/rpl_parallel_deadlock_victim.test
new file mode 100644
index 00000000..ab634d29
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_parallel_deadlock_victim.test
@@ -0,0 +1,86 @@
+--source include/have_innodb.inc
+--source include/have_debug.inc
+--source include/master-slave.inc
+
+
+--echo MDEV-31655: Parallel replication deadlock victim preference code erroneously removed
+# The problem was that InnoDB would choose the wrong deadlock victim.
+# Create a lot of transactions that can cause deadlocks, and use error
+# injection to check that the first transactions in each group is never
+# selected as deadlock victim.
+--let $rows= 10
+--let $transactions= 5
+--let $gcos= 10
+
+--connection server_1
+ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
+CREATE TABLE t1 (a INT PRIMARY KEY, b INT) ENGINE=InnoDB;
+BEGIN;
+--disable_query_log
+--let $i= 0
+while ($i < 10) {
+ eval INSERT INTO t1 VALUES ($i, 0);
+ inc $i;
+}
+--enable_query_log
+COMMIT;
+--source include/save_master_gtid.inc
+
+--connection server_2
+--source include/sync_with_master_gtid.inc
+--source include/stop_slave.inc
+SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads;
+SET @old_parallel_mode=@@GLOBAL.slave_parallel_mode;
+eval set @@global.slave_parallel_threads= $transactions;
+set @@global.slave_parallel_mode= conservative;
+SET @old_dbug= @@GLOBAL.debug_dbug;
+# This error injection will allow no retries for GTIDs divisible by 1000.
+SET GLOBAL debug_dbug= "+d,rpl_mdev31655_zero_retries";
+
+--connection server_1
+SET @old_dbug= @@SESSION.debug_dbug;
+SET SESSION debug_dbug="+d,binlog_force_commit_id";
+
+--let $j= 1
+while ($j <= $gcos) {
+ eval SET @commit_id= $j+1000;
+ --let $i= 0
+ while ($i < $transactions) {
+ --disable_query_log
+ eval SET SESSION gtid_seq_no= 1000 + 1000*$j + $i;
+ BEGIN;
+ --let $k= 0
+ while ($k < $rows) {
+ eval UPDATE t1 SET b=b+1 WHERE a=(($i+$k) MOD $rows);
+ inc $k;
+ }
+ COMMIT;
+ --enable_query_log
+ inc $i;
+ }
+ inc $j;
+}
+
+SET SESSION debug_dbug= @old_dbug;
+SELECT COUNT(*), SUM(a*100*b) FROM t1;
+
+--source include/save_master_gtid.inc
+
+--connection server_2
+--source include/start_slave.inc
+--source include/sync_with_master_gtid.inc
+SET GLOBAL debug_dbug= @old_dbug;
+SELECT COUNT(*), SUM(a*100*b) FROM t1;
+
+
+# Clean up.
+--connection server_2
+--source include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=@old_parallel_threads;
+SET GLOBAL slave_parallel_mode=@old_parallel_mode;
+--source include/start_slave.inc
+
+--connection server_1
+DROP TABLE t1;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_parallel_deadlock_victim2.test b/mysql-test/suite/rpl/t/rpl_parallel_deadlock_victim2.test
new file mode 100644
index 00000000..522cec18
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_parallel_deadlock_victim2.test
@@ -0,0 +1,83 @@
+--source include/master-slave.inc
+--source include/have_innodb.inc
+--source include/have_debug.inc
+--source include/have_binlog_format_statement.inc
+
+--connection master
+ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
+CREATE TABLE t1(a INT) ENGINE=INNODB;
+INSERT INTO t1 VALUES(1);
+--source include/save_master_gtid.inc
+
+--connection slave
+--source include/sync_with_master_gtid.inc
+--source include/stop_slave.inc
+--let $save_transaction_retries= `SELECT @@global.slave_transaction_retries`
+--let $save_slave_parallel_threads= `SELECT @@global.slave_parallel_threads`
+--let $save_slave_parallel_mode= `SELECT @@global.slave_parallel_mode`
+set @@global.slave_parallel_threads= 2;
+set @@global.slave_parallel_mode= OPTIMISTIC;
+set @@global.slave_transaction_retries= 2;
+
+--echo *** MDEV-28776: rpl.rpl_mark_optimize_tbl_ddl fails with timeout on sync_with_master
+# This was a failure where a transaction T1 could deadlock multiple times
+# with T2, eventually exceeding the default --slave-transaction-retries=10.
+# Root cause was MDEV-31655, causing InnoDB to wrongly choose T1 as deadlock
+# victim over T2. If thread scheduling is right, it was possible for T1 to
+# repeatedly deadlock, roll back, and have time to grab an S lock again before
+# T2 woke up and got its waiting X lock, thus repeating the same deadlock over
+# and over.
+# Once the bug is fixed, it is not possible to re-create the same execution
+# and thread scheduling. Instead we inject small sleeps in a way that
+# triggered the problem when the bug was there, to demonstrate that the
+# problem no longer occurs.
+
+--connection master
+# T1
+SET @@gtid_seq_no= 100;
+INSERT INTO t1 SELECT 1+a FROM t1;
+# T2
+SET @@gtid_seq_no= 200;
+INSERT INTO t1 SELECT 2+a FROM t1;
+
+SELECT * FROM t1 ORDER BY a;
+--source include/save_master_gtid.inc
+
+--connection slave
+SET @save_dbug= @@GLOBAL.debug_dbug;
+
+# Inject various delays to hint thread scheduling to happen in the way that
+# triggered MDEV-28776.
+
+# Small delay starting T1 so it will be the youngest trx and be chosen over
+# T2 as the deadlock victim by default in InnoDB.
+SET GLOBAL debug_dbug="+d,rpl_parallel_delay_gtid_0_x_100_start";
+
+# Small delay before taking insert X lock to give time for both T1 and T2 to
+# get the S lock first and cause a deadlock.
+SET GLOBAL debug_dbug="+d,rpl_write_record_small_sleep_gtid_100_200";
+
+# Small delay after T2's wait on the X lock, to give time for T1 retry to
+# re-aquire the T1 S lock first.
+SET GLOBAL debug_dbug="+d,small_sleep_after_lock_wait";
+
+# Delay deadlock kill of T2.
+SET GLOBAL debug_dbug="+d,rpl_delay_deadlock_kill";
+
+--source include/start_slave.inc
+--source include/sync_with_master_gtid.inc
+SET GLOBAL debug_dbug= @save_dbug;
+SELECT * FROM t1 ORDER BY a;
+
+# Cleanup.
+--connection slave
+--source include/stop_slave.inc
+eval SET @@global.slave_parallel_threads= $save_slave_parallel_threads;
+eval SET @@global.slave_parallel_mode= $save_slave_parallel_mode;
+eval SET @@global.slave_transaction_retries= $save_transaction_retries;
+--source include/start_slave.inc
+
+--connection master
+DROP TABLE t1;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_parallel_domain.test b/mysql-test/suite/rpl/t/rpl_parallel_domain.test
new file mode 100644
index 00000000..eda08cc2
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_parallel_domain.test
@@ -0,0 +1,87 @@
+# Test should work with both conservative and optimistic modes
+
+--source include/have_innodb.inc
+--source include/have_debug.inc
+--source include/have_debug_sync.inc
+--source include/master-slave.inc
+
+# Test various aspects of parallel replication.
+
+--connection server_2
+SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads;
+--error ER_SLAVE_MUST_STOP
+SET GLOBAL slave_parallel_threads=10;
+--source include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=10;
+
+# Check that we do not spawn any worker threads when no slave is running.
+SELECT IF(COUNT(*) < 10, "OK", CONCAT("Found too many system user processes: ", COUNT(*))) FROM information_schema.processlist WHERE user = "system user";
+
+CHANGE MASTER TO master_use_gtid=slave_pos;
+--source include/start_slave.inc
+
+# Check that worker threads get spawned when slave starts.
+SELECT IF(COUNT(*) >= 10, "OK", CONCAT("Found too few system user processes: ", COUNT(*))) FROM information_schema.processlist WHERE user = "system user";
+# ... and that worker threads get removed when slave stops.
+--source include/stop_slave.inc
+SELECT IF(COUNT(*) < 10, "OK", CONCAT("Found too many system user processes: ", COUNT(*))) FROM information_schema.processlist WHERE user = "system user";
+--source include/start_slave.inc
+SELECT IF(COUNT(*) >= 10, "OK", CONCAT("Found too few system user processes: ", COUNT(*))) FROM information_schema.processlist WHERE user = "system user";
+
+--echo *** Test long-running query in domain 1 can run in parallel with short queries in domain 0 ***
+
+--connection server_1
+ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
+CREATE TABLE t1 (a int PRIMARY KEY) ENGINE=MyISAM;
+CREATE TABLE t2 (a int PRIMARY KEY) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t2 VALUES (1);
+--save_master_pos
+
+--connection server_2
+--sync_with_master
+
+# Block the table t1 to simulate a replicated query taking a long time.
+--connect (con_temp1,127.0.0.1,root,,test,$SERVER_MYPORT_2,)
+LOCK TABLE t1 WRITE;
+
+--connection server_1
+SET gtid_domain_id=1;
+# This query will be blocked on the slave until UNLOCK TABLES.
+INSERT INTO t1 VALUES (2);
+SET gtid_domain_id=0;
+# These t2 queries can be replicated in parallel with the prior t1 query, as
+# they are in a separate replication domain.
+INSERT INTO t2 VALUES (2);
+INSERT INTO t2 VALUES (3);
+BEGIN;
+INSERT INTO t2 VALUES (4);
+INSERT INTO t2 VALUES (5);
+COMMIT;
+INSERT INTO t2 VALUES (6);
+
+--connection server_2
+--let $wait_condition= SELECT COUNT(*) = 6 FROM t2
+--source include/wait_condition.inc
+
+SELECT * FROM t2 ORDER by a;
+
+--connection con_temp1
+SELECT * FROM t1;
+UNLOCK TABLES;
+
+--connection server_2
+--let $wait_condition= SELECT COUNT(*) = 2 FROM t1
+--source include/wait_condition.inc
+
+SELECT * FROM t1 ORDER BY a;
+
+# Clean up.
+--connection server_2
+--source include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=@old_parallel_threads;
+--source include/start_slave.inc
+
+--connection server_1
+DROP TABLE t1,t2;
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_parallel_domain_slave_single_grp.test b/mysql-test/suite/rpl/t/rpl_parallel_domain_slave_single_grp.test
new file mode 100644
index 00000000..856efd06
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_parallel_domain_slave_single_grp.test
@@ -0,0 +1,128 @@
+# Test is independent of slave_parallel_mode
+--echo *** Test two transactions in different domains committed in opposite order on slave but in a single group commit. ***
+
+--source include/have_innodb.inc
+--source include/have_debug.inc
+--source include/have_debug_sync.inc
+--source include/master-slave.inc
+
+# Test various aspects of parallel replication.
+
+--connection server_2
+SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads;
+--source include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=10;
+CHANGE MASTER TO master_use_gtid=slave_pos;
+--source include/start_slave.inc
+
+--connection server_1
+ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
+CREATE TABLE t1 (a int PRIMARY KEY) ENGINE=MyISAM;
+CREATE TABLE t2 (a int PRIMARY KEY) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t2 VALUES (1);
+--save_master_pos
+
+--connection server_2
+--sync_with_master
+--source include/stop_slave.inc
+
+--connection server_1
+# Use a stored function to inject a debug_sync into the appropriate THD.
+# The function does nothing on the master, and on the slave it injects the
+# desired debug_sync action(s).
+SET sql_log_bin=0;
+--delimiter ||
+CREATE FUNCTION foo(x INT, d1 VARCHAR(500), d2 VARCHAR(500))
+ RETURNS INT DETERMINISTIC
+ BEGIN
+ RETURN x;
+ END
+||
+--delimiter ;
+SET sql_log_bin=1;
+
+SET @old_format= @@SESSION.binlog_format;
+SET binlog_format='statement';
+SET gtid_domain_id=1;
+INSERT INTO t2 VALUES (foo(10,
+ 'commit_before_enqueue SIGNAL ready1 WAIT_FOR cont1',
+ 'commit_after_release_LOCK_prepare_ordered SIGNAL ready2'));
+
+--connection server_2
+FLUSH LOGS;
+--source include/wait_for_binlog_checkpoint.inc
+SET sql_log_bin=0;
+--delimiter ||
+CREATE FUNCTION foo(x INT, d1 VARCHAR(500), d2 VARCHAR(500))
+ RETURNS INT DETERMINISTIC
+ BEGIN
+ IF d1 != '' THEN
+ SET debug_sync = d1;
+ END IF;
+ IF d2 != '' THEN
+ SET debug_sync = d2;
+ END IF;
+ RETURN x;
+ END
+||
+--delimiter ;
+SET sql_log_bin=1;
+SET @old_format=@@GLOBAL.binlog_format;
+SET GLOBAL binlog_format=statement;
+# We need to restart all parallel threads for the new global setting to
+# be copied to the session-level values.
+SET GLOBAL slave_parallel_threads=0;
+SET GLOBAL slave_parallel_threads=10;
+--source include/start_slave.inc
+
+# First make sure the first insert is ready to commit, but not queued yet.
+SET debug_sync='now WAIT_FOR ready1';
+
+--connection server_1
+SET gtid_domain_id=2;
+INSERT INTO t2 VALUES (foo(11,
+ 'commit_before_enqueue SIGNAL ready3 WAIT_FOR cont3',
+ 'commit_after_release_LOCK_prepare_ordered SIGNAL ready4 WAIT_FOR cont4'));
+SET gtid_domain_id=0;
+SELECT * FROM t2 WHERE a >= 10 ORDER BY a;
+
+--connection server_2
+# Now wait for the second insert to queue itself as the leader, and then
+# wait for more commits to queue up.
+SET debug_sync='now WAIT_FOR ready3';
+SET debug_sync='now SIGNAL cont3';
+SET debug_sync='now WAIT_FOR ready4';
+# Now allow the first insert to queue up to participate in group commit.
+SET debug_sync='now SIGNAL cont1';
+SET debug_sync='now WAIT_FOR ready2';
+# Finally allow the second insert to proceed and do the group commit.
+SET debug_sync='now SIGNAL cont4';
+
+--let $wait_condition= SELECT COUNT(*) = 2 FROM t2 WHERE a >= 10
+--source include/wait_condition.inc
+SELECT * FROM t2 WHERE a >= 10 ORDER BY a;
+# The two INSERT transactions should have been committed in opposite order,
+# but in the same group commit (seen by precense of cid=# in the SHOW
+# BINLOG output).
+--let $binlog_file= slave-bin.000002
+--source include/show_binlog_events.inc
+FLUSH LOGS;
+--source include/wait_for_binlog_checkpoint.inc
+
+
+# Clean up.
+--connection server_2
+--source include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=@old_parallel_threads;
+--source include/start_slave.inc
+SET DEBUG_SYNC= 'RESET';
+SET GLOBAL binlog_format=@old_format;
+
+--connection server_1
+DROP function foo;
+DROP TABLE t1,t2;
+SET DEBUG_SYNC= 'RESET';
+SET GLOBAL binlog_format=@old_format;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_parallel_free_deferred_event.test b/mysql-test/suite/rpl/t/rpl_parallel_free_deferred_event.test
new file mode 100644
index 00000000..41f372ed
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_parallel_free_deferred_event.test
@@ -0,0 +1,67 @@
+--echo *** MDEV-5788 Incorrect free of rgi->deferred_events in parallel replication ***
+
+--source include/have_innodb.inc
+--source include/master-slave.inc
+
+--connection server_2
+--source include/stop_slave.inc
+CHANGE MASTER TO master_use_gtid=slave_pos;
+--source include/start_slave.inc
+
+--connection server_1
+ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
+CREATE TABLE t3 (a INT PRIMARY KEY, b INT) ENGINE=InnoDB;
+--save_master_pos
+
+--connection server_2
+--sync_with_master
+SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads;
+# Use just two worker threads, so we are sure to get the rpl_group_info added
+# to the free list, which is what triggered the bug.
+--source include/stop_slave.inc
+SET GLOBAL replicate_ignore_table="test.t3";
+SET GLOBAL slave_parallel_threads=2;
+--source include/start_slave.inc
+
+--connection server_1
+INSERT INTO t3 VALUES (100, rand());
+INSERT INTO t3 VALUES (101, rand());
+--save_master_pos
+
+--connection server_2
+--sync_with_master
+
+--connection server_1
+INSERT INTO t3 VALUES (102, rand());
+INSERT INTO t3 VALUES (103, rand());
+INSERT INTO t3 VALUES (104, rand());
+INSERT INTO t3 VALUES (105, rand());
+--save_master_pos
+
+--connection server_2
+--sync_with_master
+--source include/stop_slave.inc
+SET GLOBAL replicate_ignore_table="";
+--source include/start_slave.inc
+
+--connection server_1
+INSERT INTO t3 VALUES (106, rand());
+INSERT INTO t3 VALUES (107, rand());
+--save_master_pos
+
+--connection server_2
+--sync_with_master
+--replace_column 2 #
+SELECT * FROM t3 WHERE a >= 100 ORDER BY a;
+
+
+# Clean up.
+--connection server_2
+--source include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=@old_parallel_threads;
+--source include/start_slave.inc
+
+--connection server_1
+DROP TABLE t3;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_parallel_ftwrl.test b/mysql-test/suite/rpl/t/rpl_parallel_ftwrl.test
new file mode 100644
index 00000000..308fcd0b
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_parallel_ftwrl.test
@@ -0,0 +1,143 @@
+--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/master-slave.inc
+
+--connection slave
+--source include/stop_slave.inc
+SET @old_parallel_threads= @@GLOBAL.slave_parallel_threads;
+SET GLOBAL slave_parallel_threads=3;
+SET @old_parallel_mode= @@GLOBAL.slave_parallel_mode;
+SET GLOBAL slave_parallel_mode=aggressive;
+SET @old_dbug= @@GLOBAL.debug_dbug;
+CHANGE MASTER TO master_use_gtid=slave_pos;
+--source include/start_slave.inc
+
+--echo *** MDEV-31509: Lost data with FTWRL and STOP SLAVE
+# The bug was as follows:
+# 1. Event groups T1 and T2 are queued but not started yet.
+# 2. FLUSH TABLE WITH READ LOCKS starts, sets rpl_parallel_entry::pause_sub_id
+# 3. T2 Sees pause_sub_id, goes to wait for the pause to complete.
+# 4. FTWRL completes, UNLOCK TABLES is run.
+# 5. STOP SLAVE is run, sets rpl_parallel_entry::stop_sub_id.
+# 6. T2 wakes up after FTWRL pause, only now sets
+# rpl_parallel_entry::largest_started_sub_id. This is the bug,
+# largest_started_sub_id is set too late here.
+# 7. T1 starts, it sees stop_sub_id<T1, so T1 is skipped due to STOP SLAVE.
+# 8. T2 continues, its check for stop_sub_id was before STOP SLAVE. So T2 is
+# wrongly applied, silently losing transaction T1.
+
+
+--connection master
+ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
+CREATE TABLE t1 (a INT PRIMARY KEY, b INT) ENGINE=InnoDB;
+CREATE TABLE t2 (a INT PRIMARY KEY, b INT) ENGINE=MyISAM;
+INSERT INTO t1 VALUES (0,0);
+INSERT INTO t2 VALUES (0,0);
+--source include/save_master_gtid.inc
+
+--connection slave
+--source include/sync_with_master_gtid.inc
+
+--connection slave
+--echo *** Arrange for T1 to delay before entering GCO wait.
+SET GLOBAL debug_dbug="+d,gco_wait_delay_gtid_0_x_99";
+--echo *** Arrange for T2 to wait for FTWRL to start.
+SET GLOBAL debug_dbug="+d,hold_worker_on_schedule";
+--echo *** Arrange for T2 to delay wakeup from FTWRL pause.
+SET GLOBAL debug_dbug="+d,delay_ftwrl_wait_gtid_0_x_100";
+
+--connection master
+--echo *** Event group T1
+SET SESSION gtid_seq_no=99;
+INSERT INTO t1 VALUES (1,1);
+
+--connection slave
+--echo *** 1a. Wait for T1 to be queued.
+SET debug_sync="now WAIT_FOR gco_wait_paused";
+
+--connection master
+--echo *** Event group T2
+SET SESSION gtid_seq_no=100;
+INSERT INTO t2 VALUES (2,2);
+
+--connection slave
+--echo *** 1b. Wait for T2 to be queued.
+SET debug_sync= "now WAIT_FOR reached_pause";
+
+--connection slave1
+--echo *** 2. Run FTWRL
+SET GLOBAL debug_dbug= "+d,pause_for_ftwrl_wait";
+send FLUSH TABLES WITH READ LOCK;
+
+--connection slave
+SET debug_sync= "now WAIT_FOR pause_ftwrl_waiting";
+
+--echo *** 3. Wait for T2 to be waiting for FTWRL pause
+SET debug_sync= "now SIGNAL continue_worker";
+--let $wait_condition= SELECT count(*) = 1 FROM information_schema.processlist WHERE state LIKE "%Waiting due to global read lock%" and command="Slave_worker";
+--source include/wait_condition.inc
+
+--echo *** 4. FTWRL completes, UNLOCK TABLES.
+SET debug_sync="now SIGNAL pause_ftwrl_cont";
+
+--connection slave1
+reap;
+UNLOCK TABLES;
+
+--connection slave
+--echo *** T2 is now ready to proceed after FTWRL pause, but did not wake up yet.
+SET debug_sync="now WAIT_FOR pause_wait_started";
+
+--echo *** 5. STOP SLAVE is run.
+--connection slave1
+SET GLOBAL debug_dbug="+d,rpl_parallel_wait_for_done_trigger";
+send STOP SLAVE;
+
+--connection slave
+SET debug_sync="now WAIT_FOR wait_for_done_waiting";
+
+--echo *** 5. T2 wakes up after FTWRL pause, reaches wait_for_prior_commit().
+SET debug_sync="now SIGNAL pause_wait_continue";
+--let $wait_condition= SELECT count(*) = 1 FROM information_schema.processlist WHERE state LIKE "%Waiting for prior transaction to commit%" and command="Slave_worker";
+--source include/wait_condition.inc
+
+--echo *** 6. T1 starts.
+SET debug_sync="now SIGNAL gco_wait_cont";
+
+--connection slave1
+reap;
+
+--connection slave
+--source include/wait_for_slave_to_stop.inc
+
+--connection master
+SELECT * FROM t1 ORDER BY a;
+SELECT * FROM t2 ORDER BY a;
+--source include/save_master_gtid.inc
+
+--connection slave
+--source include/start_slave.inc
+--source include/sync_with_master_gtid.inc
+
+# The bug here was that T2 was errorneously replicated while T1 was
+# being skipped due to STOP SLAVE. So the @@gtid_slave_pos was at T2,
+# but we were missing the data from T1.
+SELECT @@GLOBAL.gtid_slave_pos;
+SELECT * FROM t1 ORDER BY a;
+SELECT * FROM t2 ORDER BY a;
+
+--echo *** Clean up.
+--connection slave
+--source include/stop_slave.inc
+SET DEBUG_SYNC= "RESET";
+SET GLOBAL slave_parallel_threads= @old_parallel_threads;
+SET GLOBAL slave_parallel_mode= @old_parallel_mode;
+SET GLOBAL debug_dbug=@old_dbug;
+--source include/start_slave.inc
+
+--connection master
+DROP TABLE t1, t2;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_parallel_gco_wait_kill.test b/mysql-test/suite/rpl/t/rpl_parallel_gco_wait_kill.test
new file mode 100644
index 00000000..c5d2b85c
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_parallel_gco_wait_kill.test
@@ -0,0 +1,369 @@
+--echo *** Test killing thread that is waiting to start transaction until previous transaction commits ***
+
+--source include/have_innodb.inc
+--source include/have_debug.inc
+--source include/have_debug_sync.inc
+--source include/have_binlog_format_statement.inc
+--source include/master-slave.inc
+
+--connection server_2
+SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads;
+SET @old_parallel_mode= @@GLOBAL.slave_parallel_mode;
+--source include/stop_slave.inc
+SET sql_log_bin=0;
+CALL mtr.add_suppression("Query execution was interrupted");
+CALL mtr.add_suppression("Slave: Connection was killed");
+CALL mtr.add_suppression("Commit failed due to failure of an earlier commit on which this one depends");
+SET sql_log_bin=1;
+SET GLOBAL slave_parallel_threads=10;
+SET GLOBAL slave_parallel_mode= 'conservative';
+CHANGE MASTER TO master_use_gtid=slave_pos;
+--source include/start_slave.inc
+
+--connection server_1
+--connect (con_temp3,127.0.0.1,root,,test,$SERVER_MYPORT_1,)
+--connect (con_temp4,127.0.0.1,root,,test,$SERVER_MYPORT_1,)
+--connect (con_temp5,127.0.0.1,root,,test,$SERVER_MYPORT_1,)
+ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
+CREATE TABLE t3 (a INT PRIMARY KEY, b 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 t3 VALUES(100, 100);
+--save_master_pos
+
+--connection server_2
+--sync_with_master
+
+--connection server_1
+# Use a stored function to inject a debug_sync into the appropriate THD.
+# The function does nothing on the master, and on the slave it injects the
+# desired debug_sync action(s).
+SET sql_log_bin=0;
+--delimiter ||
+CREATE FUNCTION foo(x INT, d1 VARCHAR(500), d2 VARCHAR(500))
+ RETURNS INT DETERMINISTIC
+ BEGIN
+ RETURN x;
+ END
+||
+--delimiter ;
+SET sql_log_bin=1;
+
+--connection server_2
+SET sql_log_bin=0;
+--delimiter ||
+CREATE FUNCTION foo(x INT, d1 VARCHAR(500), d2 VARCHAR(500))
+ RETURNS INT DETERMINISTIC
+ BEGIN
+ IF d1 != '' THEN
+ SET debug_sync = d1;
+ END IF;
+ IF d2 != '' THEN
+ SET debug_sync = d2;
+ END IF;
+ RETURN x;
+ END
+||
+--delimiter ;
+SET sql_log_bin=1;
+# We need to restart all parallel threads for the new global setting to
+# be copied to the session-level values.
+--source include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=0;
+SET GLOBAL slave_parallel_threads=4;
+--source include/start_slave.inc
+
+
+# We set up four transactions T1, T2, T3, and T4 on the master. T2, T3, and T4
+# can run in parallel with each other (same group commit and commit id),
+# but not in parallel with T1.
+#
+# We use four worker threads, each Ti will be queued on each their own
+# worker thread. We will delay T1 commit, T3 will wait for T1 to begin
+# commit before it can start. We will kill T3 during this wait, and
+# check that everything works correctly.
+#
+# It is rather tricky to get the correct thread id of the worker to kill.
+# We start by injecting four dummy transactions in a debug_sync-controlled
+# manner to be able to get known thread ids for the workers in a pool with
+# just 4 worker threads. Then we let in each of the real test transactions
+# T1-T4 one at a time in a way which allows us to know which transaction
+# ends up with which thread id.
+
+--connection server_1
+SET gtid_domain_id=2;
+BEGIN;
+# This debug_sync will linger on and be used to control T4 later.
+INSERT INTO t3 VALUES (70, foo(70,
+ 'rpl_parallel_start_waiting_for_prior SIGNAL t4_waiting', ''));
+INSERT INTO t3 VALUES (60, foo(60,
+ 'ha_write_row_end SIGNAL d2_query WAIT_FOR d2_cont2',
+ 'rpl_parallel_end_of_group SIGNAL d2_done WAIT_FOR d2_cont'));
+COMMIT;
+SET gtid_domain_id=0;
+
+--connection server_2
+SET debug_sync='now WAIT_FOR d2_query';
+--let $d2_thd_id= `SELECT ID FROM INFORMATION_SCHEMA.PROCESSLIST WHERE INFO LIKE '%foo(60%' AND INFO NOT LIKE '%LIKE%'`
+
+--connection server_1
+SET gtid_domain_id=1;
+BEGIN;
+# These debug_sync's will linger on and be used to control T3 later.
+INSERT INTO t3 VALUES (61, foo(61,
+ 'rpl_parallel_start_waiting_for_prior SIGNAL t3_waiting',
+ 'rpl_parallel_start_waiting_for_prior_killed SIGNAL t3_killed'));
+INSERT INTO t3 VALUES (62, foo(62,
+ 'ha_write_row_end SIGNAL d1_query WAIT_FOR d1_cont2',
+ 'rpl_parallel_end_of_group SIGNAL d1_done WAIT_FOR d1_cont'));
+COMMIT;
+SET gtid_domain_id=0;
+
+--connection server_2
+SET debug_sync='now WAIT_FOR d1_query';
+--let $d1_thd_id= `SELECT ID FROM INFORMATION_SCHEMA.PROCESSLIST WHERE INFO LIKE '%foo(62%' AND INFO NOT LIKE '%LIKE%'`
+
+--connection server_1
+SET gtid_domain_id=0;
+INSERT INTO t3 VALUES (63, foo(63,
+ 'ha_write_row_end SIGNAL d0_query WAIT_FOR d0_cont2',
+ 'rpl_parallel_end_of_group SIGNAL d0_done WAIT_FOR d0_cont'));
+
+--connection server_2
+SET debug_sync='now WAIT_FOR d0_query';
+--let $d0_thd_id= `SELECT ID FROM INFORMATION_SCHEMA.PROCESSLIST WHERE INFO LIKE '%foo(63%' AND INFO NOT LIKE '%LIKE%'`
+
+--connection server_1
+SET gtid_domain_id=3;
+BEGIN;
+# These debug_sync's will linger on and be used to control T2 later.
+INSERT INTO t3 VALUES (68, foo(68,
+ 'rpl_parallel_start_waiting_for_prior SIGNAL t2_waiting', ''));
+INSERT INTO t3 VALUES (69, foo(69,
+ 'ha_write_row_end SIGNAL d3_query WAIT_FOR d3_cont2',
+ 'rpl_parallel_end_of_group SIGNAL d3_done WAIT_FOR d3_cont'));
+COMMIT;
+SET gtid_domain_id=0;
+
+--connection server_2
+SET debug_sync='now WAIT_FOR d3_query';
+--let $d3_thd_id= `SELECT ID FROM INFORMATION_SCHEMA.PROCESSLIST WHERE INFO LIKE '%foo(69%' AND INFO NOT LIKE '%LIKE%'`
+
+SET debug_sync='now SIGNAL d2_cont2';
+SET debug_sync='now WAIT_FOR d2_done';
+SET debug_sync='now SIGNAL d1_cont2';
+SET debug_sync='now WAIT_FOR d1_done';
+SET debug_sync='now SIGNAL d0_cont2';
+SET debug_sync='now WAIT_FOR d0_done';
+SET debug_sync='now SIGNAL d3_cont2';
+SET debug_sync='now WAIT_FOR d3_done';
+
+# Now prepare the real transactions T1, T2, T3, T4 on the master.
+
+--connection con_temp3
+# Create transaction T1.
+INSERT INTO t3 VALUES (64, foo(64,
+ 'rpl_parallel_before_mark_start_commit SIGNAL t1_waiting WAIT_FOR t1_cont', ''));
+
+# Create transaction T2, as a group commit leader on the master.
+SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued2 WAIT_FOR master_cont2';
+send INSERT INTO t3 VALUES (65, foo(65, '', ''));
+
+--connection server_1
+SET debug_sync='now WAIT_FOR master_queued2';
+
+--connection con_temp4
+# Create transaction T3, participating in T2's group commit.
+SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued3';
+send INSERT INTO t3 VALUES (66, foo(66, '', ''));
+
+--connection server_1
+SET debug_sync='now WAIT_FOR master_queued3';
+
+--connection con_temp5
+# Create transaction T4, participating in group commit with T2 and T3.
+SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued4';
+send INSERT INTO t3 VALUES (67, foo(67, '', ''));
+
+--connection server_1
+SET debug_sync='now WAIT_FOR master_queued4';
+SET debug_sync='now SIGNAL master_cont2';
+
+--connection con_temp3
+REAP;
+--connection con_temp4
+REAP;
+--connection con_temp5
+REAP;
+
+--connection server_1
+SELECT * FROM t3 WHERE a >= 60 ORDER BY a;
+SET debug_sync='RESET';
+
+--connection server_2
+# Now we have the four transactions pending for replication on the slave.
+# Let them be queued for our three worker threads in a controlled fashion.
+# We put them at a stage where T1 is delayed and T3 is waiting for T1 to
+# commit before T3 can start. Then we kill T3.
+
+# Make the worker D0 free, and wait for T1 to be queued in it.
+SET debug_sync='now SIGNAL d0_cont';
+SET debug_sync='now WAIT_FOR t1_waiting';
+
+# Make the worker D3 free, and wait for T2 to be queued in it.
+SET debug_sync='now SIGNAL d3_cont';
+SET debug_sync='now WAIT_FOR t2_waiting';
+
+# Now release worker D1, and wait for T3 to be queued in it.
+# T3 will wait for T1 to commit before it can start.
+SET debug_sync='now SIGNAL d1_cont';
+SET debug_sync='now WAIT_FOR t3_waiting';
+
+# Release worker D2. Wait for T4 to be queued, so we are sure it has
+# received the debug_sync signal (else we might overwrite it with the
+# next debug_sync).
+SET debug_sync='now SIGNAL d2_cont';
+SET debug_sync='now WAIT_FOR t4_waiting';
+
+# Now we kill the waiting transaction T3 in worker D1.
+--replace_result $d1_thd_id THD_ID
+eval KILL $d1_thd_id;
+
+# Wait until T3 has reacted on the kill.
+SET debug_sync='now WAIT_FOR t3_killed';
+
+# Now we can allow T1 to proceed.
+SET debug_sync='now SIGNAL t1_cont';
+
+--let $slave_sql_errno= 1317,1927,1964
+--source include/wait_for_slave_sql_error.inc
+STOP SLAVE IO_THREAD;
+# Since T2, T3, and T4 run in parallel, we can not be sure if T2 will have time
+# to commit or not before the stop. However, T1 should commit, and T3/T4 may
+# not have committed. (After slave restart we check that all become committed
+# eventually).
+SELECT * FROM t3 WHERE a >= 60 AND a != 65 ORDER BY a;
+
+# Now we have to disable the debug_sync statements, so they do not trigger
+# when the events are retried.
+SET debug_sync='RESET';
+SET GLOBAL slave_parallel_threads=0;
+SET GLOBAL slave_parallel_threads=10;
+SET sql_log_bin=0;
+DROP FUNCTION foo;
+--delimiter ||
+CREATE FUNCTION foo(x INT, d1 VARCHAR(500), d2 VARCHAR(500))
+ RETURNS INT DETERMINISTIC
+ BEGIN
+ RETURN x;
+ END
+||
+--delimiter ;
+SET sql_log_bin=1;
+
+--connection server_1
+UPDATE t3 SET b=b+1 WHERE a=60;
+--save_master_pos
+
+--connection server_2
+--source include/start_slave.inc
+--sync_with_master
+SELECT * FROM t3 WHERE a >= 60 ORDER BY a;
+# Restore the foo() function.
+SET sql_log_bin=0;
+DROP FUNCTION foo;
+--delimiter ||
+CREATE FUNCTION foo(x INT, d1 VARCHAR(500), d2 VARCHAR(500))
+ RETURNS INT DETERMINISTIC
+ BEGIN
+ IF d1 != '' THEN
+ SET debug_sync = d1;
+ END IF;
+ IF d2 != '' THEN
+ SET debug_sync = d2;
+ END IF;
+ RETURN x;
+ END
+||
+--delimiter ;
+SET sql_log_bin=1;
+
+--connection server_2
+# Respawn all worker threads to clear any left-over debug_sync or other stuff.
+--source include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=0;
+SET GLOBAL slave_parallel_threads=10;
+--source include/start_slave.inc
+
+--echo *** 5. Test killing thread that is waiting for queue of max length to shorten ***
+
+# Find the thread id of the driver SQL thread that we want to kill.
+--let $wait_condition= SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE LIKE '%Slave has read all relay log%'
+--source include/wait_condition.inc
+--let $thd_id= `SELECT ID FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE LIKE '%Slave has read all relay log%'`
+SET @old_max_queued= @@GLOBAL.slave_parallel_max_queued;
+SET GLOBAL slave_parallel_max_queued=9000;
+
+--connection server_1
+--let bigstring= `SELECT REPEAT('x', 10000)`
+# Create an event that will wait to be signalled.
+INSERT INTO t3 VALUES (80, foo(0,
+ 'ha_write_row_end SIGNAL query_waiting WAIT_FOR query_cont', ''));
+
+--connection server_2
+SET debug_sync='now WAIT_FOR query_waiting';
+# Inject that the SQL driver thread will signal `wait_queue_ready' to debug_sync
+# as it goes to wait for the event queue to become smaller than the value of
+# @@slave_parallel_max_queued.
+SET @old_dbug= @@GLOBAL.debug_dbug;
+SET GLOBAL debug_dbug="+d,rpl_parallel_wait_queue_max";
+
+--connection server_1
+--disable_query_log
+# Create an event that will fill up the queue.
+# The Xid event at the end of the event group will have to wait for the Query
+# event with the INSERT to drain so the queue becomes shorter. However that in
+# turn waits for the prior event group to continue.
+eval INSERT INTO t3 VALUES (81, LENGTH('$bigstring'));
+--enable_query_log
+SELECT * FROM t3 WHERE a >= 80 ORDER BY a;
+
+--connection server_2
+SET debug_sync='now WAIT_FOR wait_queue_ready';
+
+--replace_result $thd_id THD_ID
+eval KILL $thd_id;
+
+SET debug_sync='now WAIT_FOR wait_queue_killed';
+SET debug_sync='now SIGNAL query_cont';
+
+--let $slave_sql_errno= 1317,1927,1964
+--source include/wait_for_slave_sql_error.inc
+STOP SLAVE IO_THREAD;
+
+SET GLOBAL debug_dbug=@old_dbug;
+SET GLOBAL slave_parallel_max_queued= @old_max_queued;
+
+--connection server_1
+INSERT INTO t3 VALUES (82,0);
+--save_master_pos
+
+--connection server_2
+SET debug_sync='RESET';
+--source include/start_slave.inc
+--sync_with_master
+SELECT * FROM t3 WHERE a >= 80 ORDER BY a;
+
+--connection server_2
+--source include/stop_slave.inc
+SET GLOBAL slave_parallel_mode=@old_parallel_mode;
+SET GLOBAL slave_parallel_threads=@old_parallel_threads;
+--source include/start_slave.inc
+SET DEBUG_SYNC= 'RESET';
+
+--connection server_1
+DROP function foo;
+DROP TABLE t3;
+SET DEBUG_SYNC= 'RESET';
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_parallel_gtid_slave_pos_update_fail.test b/mysql-test/suite/rpl/t/rpl_parallel_gtid_slave_pos_update_fail.test
new file mode 100644
index 00000000..da1a07d3
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_parallel_gtid_slave_pos_update_fail.test
@@ -0,0 +1,98 @@
+# MDEV-6549, failing to update gtid_slave_pos for a transaction that was retried.
+
+# The problem was that when a transaction updates the mysql.gtid_slave_pos
+# table, it clears the flag that marks that there is a GTID position that
+# needs to be updated. Then, if the transaction got killed after that due
+# to a deadlock, the subsequent retry would fail to notice that the GTID needs
+# to be recorded in gtid_slave_pos.
+#
+# (In the original bug report, the symptom was an assertion; this was however
+# just a side effect of the missing update of gtid_slave_pos, which also
+# happened to cause a missing clear of OPTION_GTID_BEGIN).
+--source include/have_innodb.inc
+--source include/have_debug.inc
+--source include/have_debug_sync.inc
+# Must use statement-based binlogging. Otherwise the transaction will not be
+# binlogged at all, as it modifies no rows.
+--source include/have_binlog_format_statement.inc
+--source include/master-slave.inc
+
+--connection server_2
+SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads;
+--source include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=10;
+CHANGE MASTER TO master_use_gtid=slave_pos;
+--source include/start_slave.inc
+
+--connection server_1
+ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
+CREATE TABLE t4 (a INT PRIMARY KEY, b INT, KEY b_idx(b)) ENGINE=InnoDB;
+INSERT INTO t4 VALUES (1,NULL), (2,2), (3,NULL), (4,4), (5, NULL), (6, 6);
+--connect (con1,127.0.0.1,root,,test,$SERVER_MYPORT_1,)
+--connect (con2,127.0.0.1,root,,test,$SERVER_MYPORT_1,)
+--save_master_pos
+
+--connection server_2
+--sync_with_master
+--source include/stop_slave.inc
+
+# Create two transactions that can run in parallel on the slave but cause
+# a deadlock if the second runs before the first.
+--connection con1
+SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued1 WAIT_FOR master_cont1';
+send UPDATE t4 SET b=NULL WHERE a=6;
+--connection server_1
+SET debug_sync='now WAIT_FOR master_queued1';
+
+--connection con2
+SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued2';
+send DELETE FROM t4 WHERE b <= 1;
+
+--connection server_1
+SET debug_sync='now WAIT_FOR master_queued2';
+SET debug_sync='now SIGNAL master_cont1';
+
+--connection con1
+REAP;
+--connection con2
+REAP;
+SET debug_sync='RESET';
+--save_master_pos
+--let $last_gtid= `SELECT @@last_gtid`
+
+--connection server_2
+# Disable the usual skip of gap locks for transactions that are run in
+# parallel, using DBUG. This allows the deadlock to occur, and this in turn
+# triggers a retry of the second transaction, and the code that was buggy and
+# caused the gtid_slave_pos update to be skipped in the retry.
+SET @old_dbug= @@GLOBAL.debug_dbug;
+SET GLOBAL debug_dbug="+d,disable_thd_need_ordering_with";
+--source include/start_slave.inc
+--sync_with_master
+SET GLOBAL debug_dbug=@old_dbug;
+
+SELECT * FROM t4 ORDER BY a;
+# Check that the GTID of the second transaction was correctly recorded in
+# gtid_slave_pos, in the variable as well as in the table.
+--replace_result $last_gtid GTID
+eval SET @last_gtid= '$last_gtid';
+SELECT IF(@@gtid_slave_pos LIKE CONCAT('%',@last_gtid,'%'), "GTID found ok",
+ CONCAT("GTID ", @last_gtid, " not found in gtid_slave_pos=", @@gtid_slave_pos))
+ AS result;
+SELECT "ROW FOUND" AS `Is the row found?`
+ FROM mysql.gtid_slave_pos
+ WHERE CONCAT(domain_id, "-", server_id, "-", seq_no) = @last_gtid;
+
+# Clean up.
+--connection server_2
+--source include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=@old_parallel_threads;
+--source include/start_slave.inc
+SET DEBUG_SYNC= 'RESET';
+
+--connection server_1
+DROP TABLE t4;
+SET DEBUG_SYNC= 'RESET';
+--disconnect con1
+--disconnect con2
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_parallel_ignore_error_on_rotate.test b/mysql-test/suite/rpl/t/rpl_parallel_ignore_error_on_rotate.test
new file mode 100644
index 00000000..2fab9f80
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_parallel_ignore_error_on_rotate.test
@@ -0,0 +1,96 @@
+--echo *** MDEV-6551: Some replication errors are ignored if slave_parallel_threads > 0 ***
+
+--source include/have_innodb.inc
+--source include/have_binlog_format_statement.inc
+--source include/master-slave.inc
+
+--connection server_2
+--source include/stop_slave.inc
+SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads;
+SET @old_parallel_mode=@@GLOBAL.slave_parallel_mode;
+SET GLOBAL slave_parallel_threads=1;
+CHANGE MASTER TO master_use_gtid=slave_pos;
+CALL mtr.add_suppression("Commit failed due to failure of an earlier commit on which this one depends");
+--source include/start_slave.inc
+
+--connection server_1
+ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
+CREATE TABLE t2 (a int PRIMARY KEY) ENGINE=InnoDB;
+SET gtid_domain_id=1;
+INSERT INTO t2 VALUES (1);
+SET gtid_domain_id=0;
+SET gtid_domain_id=2;
+INSERT INTO t2 VALUES (2);
+SET gtid_domain_id=0;
+INSERT INTO t2 VALUES (31);
+--let $gtid1= `SELECT @@LAST_GTID`
+--source include/save_master_gtid.inc
+
+--connection server_2
+--source include/sync_with_master_gtid.inc
+--source include/stop_slave.inc
+SET GLOBAL slave_parallel_threads= 0;
+--source include/start_slave.inc
+
+# Force a duplicate key error on the slave.
+SET sql_log_bin= 0;
+INSERT INTO t2 VALUES (32);
+SET sql_log_bin= 1;
+
+--connection server_1
+INSERT INTO t2 VALUES (32);
+--let $gtid2= `SELECT @@LAST_GTID`
+# Rotate the binlog; the bug is triggered when the master binlog file changes
+# after the event group that causes the duplicate key error.
+FLUSH LOGS;
+INSERT INTO t2 VALUES (33);
+INSERT INTO t2 VALUES (34);
+SELECT * FROM t2 WHERE a >= 30 ORDER BY a;
+--source include/save_master_gtid.inc
+
+--connection server_2
+--let $slave_sql_errno= 1062
+--source include/wait_for_slave_sql_error.inc
+
+--connection server_2
+--source include/stop_slave_io.inc
+SET GLOBAL slave_parallel_threads=10;
+START SLAVE;
+
+--let $slave_sql_errno= 1062
+--source include/wait_for_slave_sql_error.inc
+
+# Note: IO thread is still running at this point.
+# The bug seems to have been that restarting the SQL thread after an error with
+# the IO thread still running, somehow picks up a later relay log position and
+# thus ends up skipping the failing event, rather than re-executing.
+
+START SLAVE SQL_THREAD;
+--let $slave_sql_errno= 1062
+--source include/wait_for_slave_sql_error.inc
+
+SELECT * FROM t2 WHERE a >= 30 ORDER BY a;
+
+# Skip the duplicate error, so we can proceed.
+--error ER_SLAVE_SKIP_NOT_IN_GTID
+SET sql_slave_skip_counter= 1;
+--source include/stop_slave_io.inc
+--disable_query_log
+eval SET GLOBAL gtid_slave_pos = REPLACE(@@gtid_slave_pos, "$gtid1", "$gtid2");
+--enable_query_log
+--source include/start_slave.inc
+--source include/sync_with_master_gtid.inc
+
+SELECT * FROM t2 WHERE a >= 30 ORDER BY a;
+
+# Clean up.
+--connection server_2
+--source include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=@old_parallel_threads;
+SET GLOBAL slave_parallel_mode=@old_parallel_mode;
+--source include/start_slave.inc
+
+--connection server_1
+DROP TABLE t2;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_parallel_ignored_errors.test b/mysql-test/suite/rpl/t/rpl_parallel_ignored_errors.test
new file mode 100644
index 00000000..493385f1
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_parallel_ignored_errors.test
@@ -0,0 +1,115 @@
+# ==== Purpose ====
+#
+# Test verifies that, in parallel replication, transaction failure notification
+# is propagated to all the workers. Workers should abort the execution of
+# transaction event groups, whose event positions are higher than the failing
+# transaction group.
+#
+# ==== Implementation ====
+#
+# Steps:
+# 0 - Create a table t1 on master which has a primary key. Enable parallel
+# replication on slave with slave_parallel_mode='optimistic' and
+# slave_parallel_threads=3.
+# 1 - On slave start a transaction and execute a local INSERT statement
+# which will insert value 32. This is done to block the INSERT coming
+# from master.
+# 2 - On master execute an INSERT statement with value 32, so that it is
+# blocked on slave.
+# 3 - On slave enable a debug sync point such that it holds the worker thread
+# execution as soon as work is scheduled to it.
+# 4 - INSERT value 33 on master. It will be held on slave by other worker
+# thread due to debug simulation.
+# 5 - INSERT value 34 on master.
+# 6 - On slave, enusre that INSERT 34 has reached a state where it waits for
+# its prior transactions to commit.
+# 7 - Commit the local INSERT 32 on slave server so that first worker will
+# error out.
+# 8 - Now send a continue signal to second worker processing 33. It should
+# wakeup and propagate the error to INSERT 34.
+# 9 - Upon slave stop due to error, check that no rows are found after the
+# failed INSERT 32.
+#
+# ==== References ====
+#
+# MDEV-20645: Replication consistency is broken as workers miss the error
+# notification from an earlier failed group.
+#
+
+--source include/have_innodb.inc
+--source include/have_debug.inc
+--source include/have_debug_sync.inc
+--source include/have_binlog_format_statement.inc
+--source include/master-slave.inc
+
+--enable_connect_log
+--connection server_2
+--source include/stop_slave.inc
+SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads;
+SET @old_parallel_mode=@@GLOBAL.slave_parallel_mode;
+SET @old_debug= @@GLOBAL.debug_dbug;
+SET GLOBAL slave_parallel_mode='optimistic';
+SET GLOBAL slave_parallel_threads= 3;
+CHANGE MASTER TO master_use_gtid=slave_pos;
+CALL mtr.add_suppression("Commit failed due to failure of an earlier commit on which this one depends");
+--source include/start_slave.inc
+
+--connection server_1
+ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
+CREATE TABLE t1 (a int PRIMARY KEY) 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 t1 VALUES(1);
+--source include/save_master_gtid.inc
+
+--connection server_2
+--source include/sync_with_master_gtid.inc
+
+--connect (con_temp2,127.0.0.1,root,,test,$SERVER_MYPORT_2,)
+BEGIN;
+INSERT INTO t1 VALUES (32);
+
+--connection server_1
+INSERT INTO t1 VALUES (32);
+
+--connection server_2
+--let $wait_condition= SELECT COUNT(*) = 1 FROM information_schema.processlist WHERE info like "INSERT INTO t1 VALUES (32)"
+--source include/wait_condition.inc
+SET GLOBAL debug_dbug="+d,hold_worker_on_schedule";
+SET debug_sync="debug_sync_action SIGNAL reached_pause WAIT_FOR continue_worker";
+
+--connection server_1
+SET gtid_seq_no=100;
+INSERT INTO t1 VALUES (33);
+
+--connection server_2
+SET debug_sync='now WAIT_FOR reached_pause';
+
+--connection server_1
+INSERT INTO t1 VALUES (34);
+
+--connection server_2
+--let $wait_condition= SELECT COUNT(*) = 1 FROM information_schema.processlist WHERE state like "Waiting for prior transaction to commit"
+--source include/wait_condition.inc
+--connection con_temp2
+COMMIT;
+
+# Clean up.
+--connection server_2
+--source include/stop_slave.inc
+--let $assert_cond= COUNT(*) = 0 FROM t1 WHERE a>32
+--let $assert_text= table t1 should have zero rows where a>32
+--source include/assert.inc
+SELECT * FROM t1 WHERE a>32;
+DELETE FROM t1 WHERE a=32;
+
+SET GLOBAL slave_parallel_threads=@old_parallel_threads;
+SET GLOBAL slave_parallel_mode=@old_parallel_mode;
+SET GLOBAL debug_dbug=@old_debug;
+SET DEBUG_SYNC= 'RESET';
+--source include/start_slave.inc
+
+--connection server_1
+DROP TABLE t1;
+--disable_connect_log
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_parallel_incorrect_relay_pos.test b/mysql-test/suite/rpl/t/rpl_parallel_incorrect_relay_pos.test
new file mode 100644
index 00000000..e0226d94
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_parallel_incorrect_relay_pos.test
@@ -0,0 +1 @@
+--source include/rpl_parallel_incorrect_relay_pos.inc
diff --git a/mysql-test/suite/rpl/t/rpl_parallel_innodb_lock_conflict.test b/mysql-test/suite/rpl/t/rpl_parallel_innodb_lock_conflict.test
new file mode 100644
index 00000000..90304937
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_parallel_innodb_lock_conflict.test
@@ -0,0 +1,107 @@
+--echo ***MDEV-5914: Parallel replication deadlock due to InnoDB lock conflicts ***
+
+--source include/have_innodb.inc
+--source include/have_debug.inc
+--source include/have_debug_sync.inc
+--source include/master-slave.inc
+
+--connection server_2
+SET sql_log_bin=0;
+CALL mtr.add_suppression("Commit failed due to failure of an earlier commit on which this one depends");
+SET sql_log_bin=1;
+SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads;
+--source include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=10;
+CHANGE MASTER TO master_use_gtid=slave_pos;
+
+--connection server_1
+ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
+CREATE TABLE t4 (a INT PRIMARY KEY, b INT, KEY b_idx(b)) ENGINE=InnoDB;
+INSERT INTO t4 VALUES (1,NULL), (2,2), (3,NULL), (4,4), (5, NULL), (6, 6);
+--connect (con1,127.0.0.1,root,,test,$SERVER_MYPORT_1,)
+--connect (con2,127.0.0.1,root,,test,$SERVER_MYPORT_1,)
+
+# Create a group commit with UPDATE and DELETE, in that order.
+# The bug was that while the UPDATE's row lock does not block the DELETE, the
+# DELETE's gap lock _does_ block the UPDATE. This could cause a deadlock
+# on the slave.
+--connection con1
+SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued1 WAIT_FOR master_cont1';
+send UPDATE t4 SET b=NULL WHERE a=6;
+--connection server_1
+SET debug_sync='now WAIT_FOR master_queued1';
+
+--connection con2
+SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued2';
+send DELETE FROM t4 WHERE b <= 3;
+
+--connection server_1
+SET debug_sync='now WAIT_FOR master_queued2';
+SET debug_sync='now SIGNAL master_cont1';
+
+--connection con1
+REAP;
+--connection con2
+REAP;
+SET debug_sync='RESET';
+--save_master_pos
+
+--connection server_2
+--source include/start_slave.inc
+--sync_with_master
+--source include/stop_slave.inc
+
+SELECT * FROM t4 ORDER BY a;
+
+
+# Another example, this one with INSERT vs. DELETE
+--connection server_1
+DELETE FROM t4;
+INSERT INTO t4 VALUES (1,NULL), (2,2), (3,NULL), (4,4), (5, NULL), (6, 6);
+
+# Create a group commit with INSERT and DELETE, in that order.
+# The bug was that while the INSERT's insert intention lock does not block
+# the DELETE, the DELETE's gap lock _does_ block the INSERT. This could cause
+# a deadlock on the slave.
+--connection con1
+SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued1 WAIT_FOR master_cont1';
+send INSERT INTO t4 VALUES (7, NULL);
+--connection server_1
+SET debug_sync='now WAIT_FOR master_queued1';
+
+--connection con2
+SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued2';
+send DELETE FROM t4 WHERE b <= 3;
+
+--connection server_1
+SET debug_sync='now WAIT_FOR master_queued2';
+SET debug_sync='now SIGNAL master_cont1';
+
+--connection con1
+REAP;
+--connection con2
+REAP;
+SET debug_sync='RESET';
+--save_master_pos
+
+--connection server_2
+--source include/start_slave.inc
+--sync_with_master
+--source include/stop_slave.inc
+
+SELECT * FROM t4 ORDER BY a;
+
+
+# Clean up.
+--connection server_2
+SET GLOBAL slave_parallel_threads=@old_parallel_threads;
+--source include/start_slave.inc
+SET DEBUG_SYNC= 'RESET';
+
+--connection server_1
+--disconnect con1
+--disconnect con2
+DROP TABLE t4;
+SET DEBUG_SYNC= 'RESET';
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_parallel_kill.test b/mysql-test/suite/rpl/t/rpl_parallel_kill.test
new file mode 100644
index 00000000..563b0aa6
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_parallel_kill.test
@@ -0,0 +1,15 @@
+--source include/master-slave.inc
+--source include/have_innodb.inc
+--source include/have_debug.inc
+--source include/have_binlog_format_row.inc
+
+--source include/mdev-31448_conservative.inc
+
+--let $killed_trx_commits=1
+--source include/mdev-31448_optimistic.inc
+--let $killed_trx_commits=0
+--source include/mdev-31448_optimistic.inc
+
+
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_parallel_mdev6589.test b/mysql-test/suite/rpl/t/rpl_parallel_mdev6589.test
new file mode 100644
index 00000000..3a5af7bd
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_parallel_mdev6589.test
@@ -0,0 +1,132 @@
+--source include/have_innodb.inc
+--source include/have_debug.inc
+--source include/have_debug_sync.inc
+--source include/master-slave.inc
+
+--connection server_2
+SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads;
+--source include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=10;
+--source include/start_slave.inc
+
+
+--echo *** MDEV-6589: Incorrect relay log start position when restarting SQL thread after error in parallel replication ***
+
+--connection server_1
+ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
+CREATE TABLE t1 (a int PRIMARY KEY) ENGINE=MyISAM;
+CREATE TABLE t2 (a int PRIMARY KEY) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t2 VALUES (1);
+--save_master_pos
+
+--connection server_2
+--sync_with_master
+SELECT * FROM t1;
+SELECT * FROM t2;
+
+# Block one domain, which we will later cause to give an error. And let some
+# other domains proceed so we can check that after restart, the slave is able
+# to correctly restart each domain in a separate position.
+
+--connect (con_temp1,127.0.0.1,root,,test,$SERVER_MYPORT_2,)
+SET sql_log_bin=0;
+BEGIN;
+INSERT INTO t2 VALUES (5);
+
+--connection server_1
+SET gtid_domain_id=0;
+INSERT INTO t1 VALUES (2);
+INSERT INTO t2 VALUES (3);
+FLUSH LOGS;
+INSERT INTO t1 VALUES (4);
+
+SET gtid_domain_id=1;
+# This query will be blocked on the slave, and later give a duplicate key error.
+INSERT INTO t2 VALUES (5);
+
+SET gtid_domain_id=0;
+INSERT INTO t1 VALUES (6);
+INSERT INTO t1 VALUES (7);
+
+SET gtid_domain_id=2;
+INSERT INTO t2 VALUES (8);
+INSERT INTO t1 VALUES (9);
+FLUSH LOGS;
+
+SET gtid_domain_id=3;
+INSERT INTO t2 VALUES (10);
+INSERT INTO t1 VALUES (11);
+
+# These cannot be replicated before the error, as a prior commit is blocked.
+SET gtid_domain_id=1;
+INSERT INTO t1 VALUES (12);
+INSERT INTO t2 VALUES (13);
+
+SET gtid_domain_id=0;
+INSERT INTO t2 VALUES (14);
+FLUSH LOGS;
+
+SET gtid_domain_id=3;
+INSERT INTO t2 VALUES (15);
+
+SET gtid_domain_id=2;
+INSERT INTO t2 VALUES (16);
+
+SET gtid_domain_id=0;
+INSERT INTO t1 VALUES (17);
+SET @gtid0 = @@last_gtid;
+SET gtid_domain_id=2;
+INSERT INTO t1 VALUES (18);
+SET @gtid2 = @@last_gtid;
+SET gtid_domain_id=3;
+INSERT INTO t1 VALUES (19);
+SET @gtid3 = @@last_gtid;
+--let $wait_pos= `SELECT CONCAT(@gtid0, ",", @gtid2, ",", @gtid3)`
+
+SELECT * FROM t1 ORDER BY a;
+SELECT * FROM t2 ORDER BY a;
+--source include/save_master_gtid.inc
+
+
+--connection server_2
+# First wait for domains 0, 2, and 3 to complete.
+--replace_result $wait_pos WAIT_POS
+eval SELECT MASTER_GTID_WAIT('$wait_pos');
+
+# Then release the row lock, and wait for the domain 1 to fail with
+# duplicate key error.
+--connection con_temp1
+COMMIT;
+CALL mtr.add_suppression("Commit failed due to failure of an earlier commit on which this one depends");
+SET sql_log_bin=1;
+
+--connection server_2
+--let $slave_sql_errno= 1062
+--source include/wait_for_slave_sql_error.inc
+
+SELECT * FROM t1 ORDER BY a;
+SELECT * FROM t2 ORDER BY a;
+
+SET sql_log_bin=0;
+DELETE FROM t2 WHERE a=5;
+SET sql_log_bin=1;
+--source include/start_slave.inc
+--source include/sync_with_master_gtid.inc
+
+SELECT * FROM t1 ORDER BY a;
+SELECT * FROM t2 ORDER BY a;
+
+
+# Clean up.
+--connection server_2
+--source include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=@old_parallel_threads;
+--source include/start_slave.inc
+SET DEBUG_SYNC= 'RESET';
+
+--connection server_1
+DROP TABLE t1,t2;
+SET DEBUG_SYNC= 'RESET';
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_parallel_missed_error_handling.test b/mysql-test/suite/rpl/t/rpl_parallel_missed_error_handling.test
new file mode 100644
index 00000000..33b1bcb1
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_parallel_missed_error_handling.test
@@ -0,0 +1,87 @@
+--echo *** MDEV-5921: In parallel replication, an error is not correctly signalled to the next transaction ***
+
+--source include/have_innodb.inc
+--source include/have_debug.inc
+--source include/have_debug_sync.inc
+--source include/master-slave.inc
+
+--connection server_2
+--source include/stop_slave.inc
+SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads;
+SET GLOBAL slave_parallel_threads=10;
+CHANGE MASTER TO master_use_gtid=slave_pos;
+CALL mtr.add_suppression("Commit failed due to failure of an earlier commit on which this one depends");
+--source include/start_slave.inc
+
+--connection server_1
+ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
+CREATE TABLE t3 (a INT PRIMARY KEY, b INT) ENGINE=InnoDB;
+--save_master_pos
+
+--connection server_2
+--sync_with_master
+
+--connection server_1
+INSERT INTO t3 VALUES (110, 1);
+--save_master_pos
+
+--connection server_2
+--sync_with_master
+SELECT * FROM t3 WHERE a >= 110 ORDER BY a;
+# Inject a duplicate key error.
+SET sql_log_bin=0;
+INSERT INTO t3 VALUES (111, 666);
+SET sql_log_bin=1;
+
+--connection server_1
+
+# Create a group commit with two inserts, the first one conflicts with a row on the slave
+--connect (con1,127.0.0.1,root,,test,$SERVER_MYPORT_1,)
+SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued1 WAIT_FOR master_cont1';
+send INSERT INTO t3 VALUES (111, 2);
+--connection server_1
+SET debug_sync='now WAIT_FOR master_queued1';
+
+--connect (con2,127.0.0.1,root,,test,$SERVER_MYPORT_1,)
+SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued2';
+send INSERT INTO t3 VALUES (112, 3);
+
+--connection server_1
+SET debug_sync='now WAIT_FOR master_queued2';
+SET debug_sync='now SIGNAL master_cont1';
+
+--connection con1
+REAP;
+--connection con2
+REAP;
+SET debug_sync='RESET';
+--save_master_pos
+
+--connection server_2
+--let $slave_sql_errno= 1062
+--source include/wait_for_slave_sql_error.inc
+--source include/wait_for_slave_sql_to_stop.inc
+# We should not see the row (112,3) here, it should be rolled back due to
+# error signal from the prior transaction.
+SELECT * FROM t3 WHERE a >= 110 ORDER BY a;
+SET sql_log_bin=0;
+DELETE FROM t3 WHERE a=111 AND b=666;
+SET sql_log_bin=1;
+START SLAVE SQL_THREAD;
+--sync_with_master
+SELECT * FROM t3 WHERE a >= 110 ORDER BY a;
+
+# Clean up.
+--connection server_2
+--source include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=@old_parallel_threads;
+--source include/start_slave.inc
+SET DEBUG_SYNC= 'RESET';
+
+--connection server_1
+--disconnect con1
+--disconnect con2
+DROP TABLE t3;
+SET DEBUG_SYNC= 'RESET';
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_parallel_mode.test b/mysql-test/suite/rpl/t/rpl_parallel_mode.test
new file mode 100644
index 00000000..67104069
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_parallel_mode.test
@@ -0,0 +1,87 @@
+--echo *** MDEV-6676 - test syntax of @@slave_parallel_mode ***
+
+--source include/have_innodb.inc
+--source include/have_debug.inc
+--source include/master-slave.inc
+
+--connection server_2
+--source include/stop_slave.inc
+SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads;
+SET @old_parallel_mode=@@GLOBAL.slave_parallel_mode;
+SET GLOBAL slave_parallel_threads=10;
+CHANGE MASTER TO master_use_gtid=slave_pos;
+--source include/start_slave.inc
+
+--connection server_1
+ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
+CREATE TABLE t2 (a int PRIMARY KEY) ENGINE=InnoDB;
+--save_master_pos
+
+--connection server_2
+--sync_with_master
+
+--let $status_items= Parallel_Mode
+--source include/show_slave_status.inc
+--source include/stop_slave.inc
+SET GLOBAL slave_parallel_mode='aggressive';
+--let $status_items= Parallel_Mode
+--source include/show_slave_status.inc
+SET GLOBAL slave_parallel_mode='conservative';
+--let $status_items= Parallel_Mode
+--source include/show_slave_status.inc
+
+--echo *** MDEV-6676 - test that empty parallel_mode does not replicate in parallel ***
+--connection server_1
+INSERT INTO t2 VALUES (1040);
+--source include/save_master_gtid.inc
+
+--connection server_2
+SET GLOBAL slave_parallel_mode='none';
+# Test that we do not use parallel apply, by injecting an unconditional
+# crash in the parallel apply code.
+SET @old_dbug= @@GLOBAL.debug_dbug;
+SET GLOBAL debug_dbug="+d,slave_crash_if_parallel_apply";
+--source include/start_slave.inc
+--source include/sync_with_master_gtid.inc
+SELECT * FROM t2 WHERE a >= 1040 ORDER BY a;
+--source include/stop_slave.inc
+SET GLOBAL debug_dbug=@old_dbug;
+
+
+--echo *** MDEV-6676 - test disabling domain-based parallel replication ***
+--connection server_1
+# Let's do a bunch of transactions that will conflict if run out-of-order in
+# domain-based parallel replication mode.
+SET gtid_domain_id = 1;
+INSERT INTO t2 VALUES (1041);
+INSERT INTO t2 VALUES (1042);
+INSERT INTO t2 VALUES (1043);
+INSERT INTO t2 VALUES (1044);
+INSERT INTO t2 VALUES (1045);
+INSERT INTO t2 VALUES (1046);
+DELETE FROM t2 WHERE a >= 1041;
+SET gtid_domain_id = 2;
+INSERT INTO t2 VALUES (1041);
+INSERT INTO t2 VALUES (1042);
+INSERT INTO t2 VALUES (1043);
+INSERT INTO t2 VALUES (1044);
+INSERT INTO t2 VALUES (1045);
+INSERT INTO t2 VALUES (1046);
+SET gtid_domain_id = 0;
+--source include/save_master_gtid.inc
+--connection server_2
+SET GLOBAL slave_parallel_mode=minimal;
+--source include/start_slave.inc
+--source include/sync_with_master_gtid.inc
+SELECT * FROM t2 WHERE a >= 1040 ORDER BY a;
+
+# Cleanup
+--source include/stop_slave.inc
+SET GLOBAL debug_dbug=@old_dbug;
+SET GLOBAL slave_parallel_threads=@old_parallel_threads;
+SET GLOBAL slave_parallel_mode=@old_parallel_mode;
+--source include/start_slave.inc
+
+--connection server_1
+DROP TABLE t2;
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_parallel_multilevel.cnf b/mysql-test/suite/rpl/t/rpl_parallel_multilevel.cnf
new file mode 100644
index 00000000..3ff94e45
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_parallel_multilevel.cnf
@@ -0,0 +1,24 @@
+!include ../my.cnf
+
+[mysqld.1]
+log-slave-updates
+loose-innodb
+
+[mysqld.2]
+log-slave-updates
+loose-innodb
+
+[mysqld.3]
+log-slave-updates
+loose-innodb
+
+[mysqld.4]
+log-slave-updates
+loose-innodb
+
+[ENV]
+SERVER_MYPORT_3= @mysqld.3.port
+SERVER_MYSOCK_3= @mysqld.3.socket
+
+SERVER_MYPORT_4= @mysqld.4.port
+SERVER_MYSOCK_4= @mysqld.4.socket
diff --git a/mysql-test/suite/rpl/t/rpl_parallel_multilevel.test b/mysql-test/suite/rpl/t/rpl_parallel_multilevel.test
new file mode 100644
index 00000000..168b7ea5
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_parallel_multilevel.test
@@ -0,0 +1,284 @@
+--source include/have_innodb.inc
+--source include/have_debug_sync.inc
+--let $rpl_topology=1->2->3->4
+--source include/rpl_init.inc
+
+# Test parallel replication with a multi-level replication hierarchy.
+
+--connection server_1
+ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
+CREATE TABLE t1 (a int PRIMARY KEY, b INT) ENGINE=InnoDB;
+--save_master_pos
+
+--connection server_2
+--sync_with_master
+--save_master_pos
+SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads;
+--source include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=10;
+CHANGE MASTER TO master_use_gtid=slave_pos;
+SET @old_parallel_mode=@@GLOBAL.slave_parallel_mode;
+SET GLOBAL slave_parallel_mode='optimistic';
+
+
+--connection server_3
+--sync_with_master
+--save_master_pos
+SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads;
+--source include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=10;
+CHANGE MASTER TO master_use_gtid=slave_pos;
+SET @old_parallel_mode=@@GLOBAL.slave_parallel_mode;
+SET GLOBAL slave_parallel_mode='optimistic';
+
+
+--connection server_4
+--sync_with_master
+SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads;
+--source include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=10;
+CHANGE MASTER TO master_use_gtid=slave_pos;
+SET @old_parallel_mode=@@GLOBAL.slave_parallel_mode;
+SET GLOBAL slave_parallel_mode='optimistic';
+
+
+--echo *** MDEV-6676: Test that @@skip_parallel_replication is preserved in slave binlog ***
+--connection server_1
+
+INSERT INTO t1 VALUES(1,1);
+BEGIN;
+INSERT INTO t1 VALUES(2,1);
+INSERT INTO t1 VALUES(3,1);
+COMMIT;
+# Do a lot of updates on same row in sequence. These would be likely to cause
+# conflicts and rollbacks in optimistic parallel replication, but we disable
+# that by enabling @@skip_parallel_replication. We can test that the flag is
+# preserved down the replication hierarchy by checking that no slave retries
+# are made.
+SET SESSION skip_parallel_replication=1;
+UPDATE t1 SET b=b+1 WHERE a=2;
+UPDATE t1 SET b=b+1 WHERE a=2;
+UPDATE t1 SET b=b+1 WHERE a=2;
+UPDATE t1 SET b=b+1 WHERE a=2;
+UPDATE t1 SET b=b+1 WHERE a=2;
+UPDATE t1 SET b=b+1 WHERE a=2;
+UPDATE t1 SET b=b+1 WHERE a=2;
+UPDATE t1 SET b=b+1 WHERE a=2;
+UPDATE t1 SET b=b+1 WHERE a=2;
+UPDATE t1 SET b=b+1 WHERE a=2;
+SET SESSION skip_parallel_replication=0;
+SELECT * FROM t1 ORDER BY a;
+--source include/save_master_gtid.inc
+
+--connection server_2
+--let $retry1= query_get_value(SHOW STATUS LIKE 'Slave_retried_transactions', Value, 1)
+--source include/start_slave.inc
+--source include/sync_with_master_gtid.inc
+SELECT * FROM t1 ORDER BY a;
+--let $retry2= query_get_value(SHOW STATUS LIKE 'Slave_retried_transactions', Value, 1)
+--disable_query_log
+eval SELECT IF($retry1=$retry2, "Ok, no retry",
+ CONCAT("ERROR: ", $retry2-$retry1, " retries during replication (was ",
+ $retry1, " now ", $retry2, ")")) AS status;
+--enable_query_log
+
+--connection server_3
+--let $retry1= query_get_value(SHOW STATUS LIKE 'Slave_retried_transactions', Value, 1)
+--source include/start_slave.inc
+--source include/sync_with_master_gtid.inc
+SELECT * FROM t1 ORDER BY a;
+--let $retry2= query_get_value(SHOW STATUS LIKE 'Slave_retried_transactions', Value, 1)
+--disable_query_log
+eval SELECT IF($retry1=$retry2, "Ok, no retry",
+ CONCAT("ERROR: ", $retry2-$retry1, " retries during replication (was ",
+ $retry1, " now ", $retry2, ")")) AS status;
+--enable_query_log
+
+--connection server_4
+--let $retry1= query_get_value(SHOW STATUS LIKE 'Slave_retried_transactions', Value, 1)
+--source include/start_slave.inc
+--source include/sync_with_master_gtid.inc
+SELECT * FROM t1 ORDER BY a;
+--let $retry2= query_get_value(SHOW STATUS LIKE 'Slave_retried_transactions', Value, 1)
+--disable_query_log
+eval SELECT IF($retry1=$retry2, "Ok, no retry",
+ CONCAT("ERROR: ", $retry2-$retry1, " retries during replication (was ",
+ $retry1, " now ", $retry2, ")")) AS status;
+--enable_query_log
+
+
+--echo *** MDEV-6676: Test that the FL_WAITED flag in GTID is preserved in slave binlog ***
+
+--connection server_2
+--source include/stop_slave.inc
+CHANGE MASTER TO master_use_gtid=slave_pos;
+SET GLOBAL slave_parallel_mode='optimistic';
+
+
+--connection server_3
+--source include/stop_slave.inc
+CHANGE MASTER TO master_use_gtid=slave_pos;
+SET GLOBAL slave_parallel_mode='optimistic';
+
+
+--connection server_4
+--source include/stop_slave.inc
+CHANGE MASTER TO master_use_gtid=slave_pos;
+SET GLOBAL slave_parallel_mode='optimistic';
+
+--connection server_1
+# Do a lot of updates on same row in sequence. Ensure that all of these but the
+# first have to do a lock wait on the master, setting FL_WAITED in the GTID
+# event. This should cause all slaves to not attempt to run those updates in
+# parallel with prior events, so that no retries are made.
+
+BEGIN;
+UPDATE t1 SET b=b+1 WHERE a=2;
+
+--connect (con_temp1,127.0.0.1,root,,test,$SERVER_MYPORT_1,)
+SET debug_sync="thd_report_wait_for SIGNAL waiting1";
+send UPDATE t1 SET b=b+1 WHERE a=2;
+--connection server_1
+SET debug_sync="now WAIT_FOR waiting1";
+
+--connect (con_temp2,127.0.0.1,root,,test,$SERVER_MYPORT_1,)
+SET debug_sync="thd_report_wait_for SIGNAL waiting2";
+send UPDATE t1 SET b=b+1 WHERE a=2;
+--connection server_1
+SET debug_sync="now WAIT_FOR waiting2";
+
+--connect (con_temp3,127.0.0.1,root,,test,$SERVER_MYPORT_1,)
+SET debug_sync="thd_report_wait_for SIGNAL waiting3";
+send UPDATE t1 SET b=b+1 WHERE a=2;
+--connection server_1
+SET debug_sync="now WAIT_FOR waiting3";
+
+--connect (con_temp4,127.0.0.1,root,,test,$SERVER_MYPORT_1,)
+SET debug_sync="thd_report_wait_for SIGNAL waiting4";
+send UPDATE t1 SET b=b+1 WHERE a=2;
+--connection server_1
+SET debug_sync="now WAIT_FOR waiting4";
+
+--connect (con_temp5,127.0.0.1,root,,test,$SERVER_MYPORT_1,)
+SET debug_sync="thd_report_wait_for SIGNAL waiting5";
+send UPDATE t1 SET b=b+1 WHERE a=2;
+--connection server_1
+SET debug_sync="now WAIT_FOR waiting5";
+
+--connect (con_temp6,127.0.0.1,root,,test,$SERVER_MYPORT_1,)
+SET debug_sync="thd_report_wait_for SIGNAL waiting6";
+send UPDATE t1 SET b=b+1 WHERE a=2;
+--connection server_1
+SET debug_sync="now WAIT_FOR waiting6";
+
+--connect (con_temp7,127.0.0.1,root,,test,$SERVER_MYPORT_1,)
+SET debug_sync="thd_report_wait_for SIGNAL waiting7";
+send UPDATE t1 SET b=b+1 WHERE a=2;
+--connection server_1
+SET debug_sync="now WAIT_FOR waiting7";
+
+--connect (con_temp8,127.0.0.1,root,,test,$SERVER_MYPORT_1,)
+SET debug_sync="thd_report_wait_for SIGNAL waiting8";
+send UPDATE t1 SET b=b+1 WHERE a=2;
+--connection server_1
+SET debug_sync="now WAIT_FOR waiting8";
+
+COMMIT;
+SET debug_sync="RESET";
+
+--connection con_temp1
+reap;
+
+COMMIT;
+--connection con_temp2
+reap;
+
+COMMIT;
+--connection con_temp3
+reap;
+
+COMMIT;
+--connection con_temp4
+reap;
+
+COMMIT;
+--connection con_temp5
+reap;
+
+COMMIT;
+--connection con_temp6
+reap;
+
+COMMIT;
+--connection con_temp7
+reap;
+
+COMMIT;
+--connection con_temp8
+reap;
+
+--connection server_1
+SELECT * FROM t1 ORDER BY a;
+--source include/save_master_gtid.inc
+
+--connection server_2
+--let $retry1= query_get_value(SHOW STATUS LIKE 'Slave_retried_transactions', Value, 1)
+--source include/start_slave.inc
+--source include/sync_with_master_gtid.inc
+SELECT * FROM t1 ORDER BY a;
+--let $retry2= query_get_value(SHOW STATUS LIKE 'Slave_retried_transactions', Value, 1)
+--disable_query_log
+eval SELECT IF($retry1=$retry2, "Ok, no retry",
+ CONCAT("ERROR: ", $retry2-$retry1, " retries during replication (was ",
+ $retry1, " now ", $retry2, ")")) AS status;
+--enable_query_log
+
+--connection server_3
+--let $retry1= query_get_value(SHOW STATUS LIKE 'Slave_retried_transactions', Value, 1)
+--source include/start_slave.inc
+--source include/sync_with_master_gtid.inc
+SELECT * FROM t1 ORDER BY a;
+--let $retry2= query_get_value(SHOW STATUS LIKE 'Slave_retried_transactions', Value, 1)
+--disable_query_log
+eval SELECT IF($retry1=$retry2, "Ok, no retry",
+ CONCAT("ERROR: ", $retry2-$retry1, " retries during replication (was ",
+ $retry1, " now ", $retry2, ")")) AS status;
+--enable_query_log
+
+--connection server_4
+--let $retry1= query_get_value(SHOW STATUS LIKE 'Slave_retried_transactions', Value, 1)
+--source include/start_slave.inc
+--source include/sync_with_master_gtid.inc
+SELECT * FROM t1 ORDER BY a;
+--let $retry2= query_get_value(SHOW STATUS LIKE 'Slave_retried_transactions', Value, 1)
+--disable_query_log
+eval SELECT IF($retry1=$retry2, "Ok, no retry",
+ CONCAT("ERROR: ", $retry2-$retry1, " retries during replication (was ",
+ $retry1, " now ", $retry2, ")")) AS status;
+--enable_query_log
+
+
+# Clean up
+
+--connection server_2
+--source include/stop_slave.inc
+SET GLOBAL slave_parallel_mode=@old_parallel_mode;
+SET GLOBAL slave_parallel_threads=@old_parallel_threads;
+--source include/start_slave.inc
+
+--connection server_3
+--source include/stop_slave.inc
+SET GLOBAL slave_parallel_mode=@old_parallel_mode;
+SET GLOBAL slave_parallel_threads=@old_parallel_threads;
+--source include/start_slave.inc
+
+--connection server_4
+--source include/stop_slave.inc
+SET GLOBAL slave_parallel_mode=@old_parallel_mode;
+SET GLOBAL slave_parallel_threads=@old_parallel_threads;
+--source include/start_slave.inc
+
+--connection server_1
+DROP TABLE t1;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_parallel_multilevel2.cnf b/mysql-test/suite/rpl/t/rpl_parallel_multilevel2.cnf
new file mode 100644
index 00000000..4e1d3878
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_parallel_multilevel2.cnf
@@ -0,0 +1,17 @@
+!include ../my.cnf
+
+[mysqld.1]
+log-slave-updates
+loose-innodb
+
+[mysqld.2]
+log-slave-updates
+loose-innodb
+
+[mysqld.3]
+log-slave-updates
+loose-innodb
+
+[ENV]
+SERVER_MYPORT_3= @mysqld.3.port
+SERVER_MYSOCK_3= @mysqld.3.socket
diff --git a/mysql-test/suite/rpl/t/rpl_parallel_multilevel2.test b/mysql-test/suite/rpl/t/rpl_parallel_multilevel2.test
new file mode 100644
index 00000000..da8a996f
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_parallel_multilevel2.test
@@ -0,0 +1,78 @@
+--source include/have_innodb.inc
+--let $rpl_topology=1->2->3
+--source include/rpl_init.inc
+
+--echo *** MDEV-7668: Intermediate master groups CREATE with INSERT, causing parallel replication failure ***
+
+--connection server_1
+SET @old_updates= @@GLOBAL.binlog_direct_non_transactional_updates;
+SET GLOBAL binlog_direct_non_transactional_updates=OFF;
+SET SESSION binlog_direct_non_transactional_updates=OFF;
+ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
+CREATE TABLE t1 (a int PRIMARY KEY, b INT) ENGINE=InnoDB;
+--save_master_pos
+
+--connection server_2
+--sync_with_master
+--save_master_pos
+--source include/stop_slave.inc
+SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads;
+SET GLOBAL slave_parallel_threads=10;
+SET @old_commit_count=@@GLOBAL.binlog_commit_wait_count;
+SET GLOBAL binlog_commit_wait_count=2;
+SET @old_commit_usec=@@GLOBAL.binlog_commit_wait_usec;
+SET GLOBAL binlog_commit_wait_usec=2000000;
+SET @old_updates= @@GLOBAL.binlog_direct_non_transactional_updates;
+SET GLOBAL binlog_direct_non_transactional_updates=OFF;
+SET SESSION binlog_direct_non_transactional_updates=OFF;
+
+--connection server_3
+--sync_with_master
+--save_master_pos
+SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads;
+--source include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=10;
+
+
+--connection server_1
+
+BEGIN;
+CREATE TEMPORARY TABLE t2 (a INT PRIMARY KEY) ENGINE=MEMORY;
+COMMIT;
+INSERT INTO t2 VALUES (1);
+INSERT INTO t1 SELECT a, a*10 FROM t2;
+DROP TABLE t2;
+--source include/save_master_gtid.inc
+
+--connection server_2
+--source include/start_slave.inc
+--source include/sync_with_master_gtid.inc
+SELECT * FROM t1 ORDER BY a;
+
+--connection server_3
+--source include/start_slave.inc
+--source include/sync_with_master_gtid.inc
+SELECT * FROM t1 ORDER BY a;
+
+
+# Clean up
+
+--connection server_2
+--source include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=@old_parallel_threads;
+SET GLOBAL binlog_commit_wait_count=@old_commit_count;
+SET GLOBAL binlog_commit_wait_usec=@old_commit_usec;
+SET GLOBAL binlog_direct_non_transactional_updates= @old_updates;
+--source include/start_slave.inc
+
+--connection server_3
+--source include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=@old_parallel_threads;
+--source include/start_slave.inc
+
+--connection server_1
+SET GLOBAL binlog_direct_non_transactional_updates= @old_updates;
+CALL mtr.add_suppression("Statement accesses nontransactional table as well as transactional or temporary table");
+DROP TABLE t1;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_parallel_no_log_slave_updates-slave.opt b/mysql-test/suite/rpl/t/rpl_parallel_no_log_slave_updates-slave.opt
new file mode 100644
index 00000000..acd68493
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_parallel_no_log_slave_updates-slave.opt
@@ -0,0 +1 @@
+--log-slave-updates=0
diff --git a/mysql-test/suite/rpl/t/rpl_parallel_no_log_slave_updates.test b/mysql-test/suite/rpl/t/rpl_parallel_no_log_slave_updates.test
new file mode 100644
index 00000000..2e4c5795
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_parallel_no_log_slave_updates.test
@@ -0,0 +1,205 @@
+--source include/have_innodb.inc
+--source include/have_debug.inc
+--source include/have_debug_sync.inc
+--source include/have_binlog_format_statement.inc
+--let $rpl_topology=1->2
+--source include/rpl_init.inc
+
+--echo *** Test killing transaction waiting in commit for previous transaction to commit, when not using 2-phase commit ***
+
+--connection server_2
+SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads;
+--source include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=10;
+CHANGE MASTER TO master_use_gtid=slave_pos;
+--source include/start_slave.inc
+
+--connection server_1
+ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
+# Use a stored function to inject a debug_sync into the appropriate THD.
+# The function does nothing on the master, and on the slave it injects the
+# desired debug_sync action(s).
+SET sql_log_bin=0;
+--delimiter ||
+CREATE FUNCTION foo(x INT, d1 VARCHAR(500), d2 VARCHAR(500))
+ RETURNS INT DETERMINISTIC
+ BEGIN
+ RETURN x;
+ END
+||
+--delimiter ;
+SET sql_log_bin=1;
+CREATE TABLE t3 (a INT PRIMARY KEY, b INT) ENGINE=InnoDB;
+--save_master_pos
+
+--connection server_2
+SET sql_log_bin=0;
+--delimiter ||
+CREATE FUNCTION foo(x INT, d1 VARCHAR(500), d2 VARCHAR(500))
+ RETURNS INT DETERMINISTIC
+ BEGIN
+ IF d1 != '' THEN
+ SET debug_sync = d1;
+ END IF;
+ IF d2 != '' THEN
+ SET debug_sync = d2;
+ END IF;
+ RETURN x;
+ END
+||
+--delimiter ;
+SET sql_log_bin=1;
+--sync_with_master
+
+
+# Set up three transactions on the master that will be group-committed
+# together so they can be replicated in parallel on the slave.
+--connect (con_temp3,127.0.0.1,root,,test,$SERVER_MYPORT_1,)
+SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued1 WAIT_FOR master_cont1';
+SET binlog_format=statement;
+
+SET debug_dbug='+d,row_ins_row_level';
+send INSERT INTO t3 VALUES (31, foo(31,
+ 'ha_commit_one_phase WAIT_FOR t2_waiting',
+ 'commit_one_phase_2 SIGNAL t1_ready WAIT_FOR t1_cont'));
+
+--connection server_1
+SET debug_sync='now WAIT_FOR master_queued1';
+
+--connect (con_temp4,127.0.0.1,root,,test,$SERVER_MYPORT_1,)
+SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued2';
+SET binlog_format=statement;
+SET debug_dbug='+d,row_ins_row_level';
+BEGIN;
+# This insert is just so we can get T2 to wait while a query is running that we
+# can see in SHOW PROCESSLIST so we can get its thread_id to kill later.
+INSERT INTO t3 VALUES (32, foo(32,
+ 'ha_write_row_end SIGNAL t2_query WAIT_FOR t2_cont',
+ ''));
+# This insert sets up debug_sync points so that T2 will tell when it is at its
+# wait point where we want to kill it - and when it has been killed.
+INSERT INTO t3 VALUES (33, foo(33,
+ 'wait_for_prior_commit_waiting SIGNAL t2_waiting',
+ 'wait_for_prior_commit_killed SIGNAL t2_killed'));
+send COMMIT;
+
+--connection server_1
+SET debug_sync='now WAIT_FOR master_queued2';
+
+--connect (con_temp5,127.0.0.1,root,,test,$SERVER_MYPORT_1,)
+SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued3';
+SET binlog_format=statement;
+SET debug_dbug='+d,row_ins_row_level';
+send INSERT INTO t3 VALUES (34, foo(34,
+ '',
+ ''));
+
+--connection server_1
+SET debug_sync='now WAIT_FOR master_queued3';
+SET debug_sync='now SIGNAL master_cont1';
+
+--connection con_temp3
+REAP;
+--connection con_temp4
+REAP;
+--connection con_temp5
+REAP;
+
+--connection server_1
+SELECT * FROM t3 WHERE a >= 30 ORDER BY a;
+
+--connection server_2
+SET sql_log_bin=0;
+CALL mtr.add_suppression("Query execution was interrupted");
+CALL mtr.add_suppression("Commit failed due to failure of an earlier commit on which this one depends");
+CALL mtr.add_suppression("Slave: Connection was killed");
+SET sql_log_bin=1;
+# Wait until T2 is inside executing its insert of 32, then find it in SHOW
+# PROCESSLIST to know its thread id for KILL later.
+SET debug_sync='now WAIT_FOR t2_query';
+--let $thd_id= `SELECT ID FROM INFORMATION_SCHEMA.PROCESSLIST WHERE INFO LIKE '%foo(32%' AND INFO NOT LIKE '%LIKE%'`
+SET debug_sync='now SIGNAL t2_cont';
+
+# Wait until T2 has entered its wait for T1 to commit, and T1 has
+# progressed into its commit phase.
+SET debug_sync='now WAIT_FOR t1_ready';
+
+# Now kill the transaction T2.
+--replace_result $thd_id THD_ID
+eval KILL $thd_id;
+
+# Wait until T2 has reacted on the kill.
+SET debug_sync='now WAIT_FOR t2_killed';
+
+# Now we can allow T1 to proceed.
+SET debug_sync='now SIGNAL t1_cont';
+
+--let $slave_sql_errno= 1317,1927,1963
+--source include/wait_for_slave_sql_error.inc
+STOP SLAVE IO_THREAD;
+SELECT * FROM t3 WHERE a >= 30 ORDER BY a;
+
+# Now we have to disable the debug_sync statements, so they do not trigger
+# when the events are retried.
+SET GLOBAL slave_parallel_threads=0;
+SET GLOBAL slave_parallel_threads=10;
+SET sql_log_bin=0;
+DROP FUNCTION foo;
+--delimiter ||
+CREATE FUNCTION foo(x INT, d1 VARCHAR(500), d2 VARCHAR(500))
+ RETURNS INT DETERMINISTIC
+ BEGIN
+ RETURN x;
+ END
+||
+--delimiter ;
+SET sql_log_bin=1;
+
+--connection server_1
+INSERT INTO t3 VALUES (39,0);
+--save_master_pos
+
+--connection server_2
+--source include/start_slave.inc
+--sync_with_master
+SELECT * FROM t3 WHERE a >= 30 ORDER BY a;
+# Restore the foo() function.
+SET sql_log_bin=0;
+DROP FUNCTION foo;
+--delimiter ||
+CREATE FUNCTION foo(x INT, d1 VARCHAR(500), d2 VARCHAR(500))
+ RETURNS INT DETERMINISTIC
+ BEGIN
+ IF d1 != '' THEN
+ SET debug_sync = d1;
+ END IF;
+ IF d2 != '' THEN
+ SET debug_sync = d2;
+ END IF;
+ RETURN x;
+ END
+||
+--delimiter ;
+SET sql_log_bin=1;
+
+
+--connection server_2
+# Respawn all worker threads to clear any left-over debug_sync or other stuff.
+--source include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=0;
+SET GLOBAL slave_parallel_threads=10;
+--source include/start_slave.inc
+
+
+--connection server_2
+--source include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=@old_parallel_threads;
+SET debug_sync = 'reset';
+--source include/start_slave.inc
+
+--connection server_1
+DROP function foo;
+DROP TABLE t3;
+SET debug_sync = 'reset';
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_parallel_optimistic.test b/mysql-test/suite/rpl/t/rpl_parallel_optimistic.test
new file mode 100644
index 00000000..f5e48282
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_parallel_optimistic.test
@@ -0,0 +1,583 @@
+--source include/have_innodb.inc
+--source include/have_debug.inc
+--source include/have_debug_sync.inc
+--let $rpl_topology=1->2
+--source include/rpl_init.inc
+
+call mtr.add_suppression("Deadlock found when trying to get lock; try restarting transaction");
+call mtr.add_suppression("Can't find record in 't1'");
+call mtr.add_suppression("Can't find record in 't2'");
+
+--connection server_1
+ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
+CREATE TABLE t1 (a int PRIMARY KEY, b INT) ENGINE=InnoDB;
+--save_master_pos
+
+--connection server_2
+--sync_with_master
+SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads;
+--source include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=10;
+CHANGE MASTER TO master_use_gtid=slave_pos;
+SET @old_parallel_mode=@@GLOBAL.slave_parallel_mode;
+SET GLOBAL slave_parallel_mode='optimistic';
+# Run the first part of the test with high batch size and see that
+# old rows remain in the table.
+SET @old_gtid_cleanup_batch_size= @@GLOBAL.gtid_cleanup_batch_size;
+SET GLOBAL gtid_cleanup_batch_size= 1000000;
+
+
+--connection server_1
+
+INSERT INTO t1 VALUES(1,1);
+BEGIN;
+INSERT INTO t1 VALUES(2,1);
+INSERT INTO t1 VALUES(3,1);
+COMMIT;
+
+# Do a bunch of INSERT/DELETE on the same rows, bound to conflict.
+# We will get a lot of rollbacks, probably, but they should be handled without
+# any visible errors.
+
+DELETE FROM t1 WHERE a=2;
+INSERT INTO t1 VALUES (2,2);
+DELETE FROM t1 WHERE a=2;
+INSERT INTO t1 VALUES (2,3);
+DELETE FROM t1 WHERE a=2;
+INSERT INTO t1 VALUES (2,4);
+DELETE FROM t1 WHERE a=2;
+INSERT INTO t1 VALUES (2,5);
+
+DELETE FROM t1 WHERE a=3;
+INSERT INTO t1 VALUES(3,2);
+DELETE FROM t1 WHERE a=1;
+INSERT INTO t1 VALUES(1,2);
+DELETE FROM t1 WHERE a=3;
+INSERT INTO t1 VALUES(3,3);
+
+DELETE FROM t1 WHERE a=2;
+INSERT INTO t1 VALUES (2,6);
+--source include/save_master_gtid.inc
+SELECT * FROM t1 ORDER BY a;
+
+--connection server_2
+--source include/start_slave.inc
+--source include/sync_with_master_gtid.inc
+SELECT * FROM t1 ORDER BY a;
+#SHOW STATUS LIKE 'Slave_retried_transactions';
+
+
+--echo *** Test a bunch of non-transactional/DDL event groups. ***
+
+--connection server_2
+--source include/stop_slave.inc
+
+--connection server_1
+
+INSERT INTO t1 VALUES (4,4);
+INSERT INTO t1 VALUES (5,5);
+CREATE TABLE t2 (a INT PRIMARY KEY) ENGINE=InnoDB;
+INSERT INTO t2 VALUES (1);
+CREATE TABLE t3 (a INT PRIMARY KEY) ENGINE=MyISAM;
+ALTER TABLE t2 ADD b INT;
+INSERT INTO t2 VALUES (2,2);
+ALTER TABLE t2 DROP b;
+INSERT INTO t2 VALUES (3);
+ALTER TABLE t2 ADD c INT;
+INSERT INTO t2 VALUES (4,5);
+INSERT INTO t2 VALUES (5,5);
+INSERT INTO t3 VALUES (1);
+UPDATE t2 SET c=NULL WHERE a=4;
+ALTER TABLE t2 ADD UNIQUE (c);
+INSERT INTO t2 VALUES (6,6);
+UPDATE t2 SET c=c+100 WHERE a=2;
+INSERT INTO t3(a) VALUES (2);
+DELETE FROM t3 WHERE a=2;
+INSERT INTO t3(a) VALUES (2);
+DELETE FROM t3 WHERE a=2;
+ALTER TABLE t3 CHANGE a c INT NOT NULL;
+INSERT INTO t3(c) VALUES (2);
+DELETE FROM t3 WHERE c=2;
+INSERT INTO t3 SELECT a+200 FROM t2;
+DELETE FROM t3 WHERE c >= 200;
+INSERT INTO t3 SELECT a+200 FROM t2;
+--source include/save_master_gtid.inc
+SELECT * FROM t1 ORDER BY a;
+SELECT * FROM t2 ORDER BY a;
+SELECT * FROM t3 ORDER BY c;
+
+--connection server_2
+--source include/start_slave.inc
+--source include/sync_with_master_gtid.inc
+SELECT * FROM t1 ORDER BY a;
+SELECT * FROM t2 ORDER BY a;
+SELECT * FROM t3 ORDER BY c;
+# Check that we have a bunch of old rows left-over - they were not deleted
+# due to high @@gtid_cleanup_batch_size. Then set a low
+# @@gtid_cleanup_batch_size so we can test that rows start being deleted.
+SELECT IF(COUNT(*) >= 30, "OK", CONCAT("Error: too few old rows found: ", COUNT(*)))
+ FROM mysql.gtid_slave_pos;
+SET GLOBAL gtid_cleanup_batch_size=1;
+
+
+--echo *** Test @@skip_parallel_replication. ***
+
+--connection server_2
+--source include/stop_slave.inc
+--let $retry1= query_get_value(SHOW STATUS LIKE 'Slave_retried_transactions', Value, 1)
+
+--connection server_1
+# We do a bunch of conflicting transactions on the master with
+# skip_parallel_replication set to true, and check that we do not
+# get any retries on the slave.
+
+UPDATE t1 SET b=10 WHERE a=3;
+SET SESSION skip_parallel_replication=1;
+UPDATE t1 SET b=20 WHERE a=3;
+UPDATE t1 SET b=30 WHERE a=3;
+UPDATE t1 SET b=50 WHERE a=3;
+UPDATE t1 SET b=80 WHERE a=3;
+UPDATE t1 SET b=130 WHERE a=3;
+UPDATE t1 SET b=210 WHERE a=3;
+UPDATE t1 SET b=340 WHERE a=3;
+UPDATE t1 SET b=550 WHERE a=3;
+UPDATE t1 SET b=890 WHERE a=3;
+SET SESSION skip_parallel_replication=0;
+SELECT * FROM t1 ORDER BY a;
+--source include/save_master_gtid.inc
+
+--connection server_2
+--source include/start_slave.inc
+--source include/sync_with_master_gtid.inc
+SELECT * FROM t1 ORDER BY a;
+--let $retry2= query_get_value(SHOW STATUS LIKE 'Slave_retried_transactions', Value, 1)
+--disable_query_log
+eval SELECT IF($retry1=$retry2, "Ok, no retry",
+ CONCAT("ERROR: ", $retry2-$retry1, " retries during replication (was ",
+ $retry1, " now ", $retry2, ")")) AS status;
+--enable_query_log
+
+
+--echo *** Test that we do not replicate in parallel transactions that had row lock waits on the master ***
+
+--connection server_2
+--source include/stop_slave.inc
+--let $retry1= query_get_value(SHOW STATUS LIKE 'Slave_retried_transactions', Value, 1)
+
+--connection server_1
+# Setup a bunch of transactions that all needed to wait.
+--connect (m1,127.0.0.1,root,,test,$SERVER_MYPORT_1,)
+--connect (m2,127.0.0.1,root,,test,$SERVER_MYPORT_1,)
+--connect (m3,127.0.0.1,root,,test,$SERVER_MYPORT_1,)
+--connect (m4,127.0.0.1,root,,test,$SERVER_MYPORT_1,)
+--connect (m5,127.0.0.1,root,,test,$SERVER_MYPORT_1,)
+--connect (m6,127.0.0.1,root,,test,$SERVER_MYPORT_1,)
+--connect (m7,127.0.0.1,root,,test,$SERVER_MYPORT_1,)
+--connect (m8,127.0.0.1,root,,test,$SERVER_MYPORT_1,)
+
+--connection default
+BEGIN; UPDATE t1 SET b=b+1 WHERE a=3;
+
+--connection m1
+SET debug_sync='thd_report_wait_for SIGNAL waiting1';
+send UPDATE t1 SET b=1001 WHERE a=3;
+--connection default
+SET debug_sync='now WAIT_FOR waiting1';
+
+--connection m2
+BEGIN;
+UPDATE t1 SET b=1002 WHERE a=5;
+SET debug_sync='thd_report_wait_for SIGNAL waiting2';
+send UPDATE t1 SET b=102 WHERE a=3;
+--connection default
+SET debug_sync='now WAIT_FOR waiting2';
+
+UPDATE t1 SET b=1000 WHERE a=1;
+--connection m3
+SET debug_sync='thd_report_wait_for SIGNAL waiting3';
+send UPDATE t1 SET b=1003 WHERE a=5;
+--connection default
+SET debug_sync='now WAIT_FOR waiting3';
+
+--connection m4
+SET debug_sync='thd_report_wait_for SIGNAL waiting4';
+send UPDATE t1 SET b=1004 WHERE a=3;
+--connection default
+SET debug_sync='now WAIT_FOR waiting4';
+
+--connection m5
+SET debug_sync='thd_report_wait_for SIGNAL waiting5';
+send UPDATE t1 SET b=1005 WHERE a=5;
+--connection default
+SET debug_sync='now WAIT_FOR waiting5';
+
+--connection m6
+SET debug_sync='thd_report_wait_for SIGNAL waiting6';
+send UPDATE t1 SET b=1006 WHERE a=1;
+--connection default
+SET debug_sync='now WAIT_FOR waiting6';
+
+--connection m7
+SET debug_sync='thd_report_wait_for SIGNAL waiting7';
+send UPDATE t1 SET b=1007 WHERE a=5;
+--connection default
+SET debug_sync='now WAIT_FOR waiting7';
+
+--connection m8
+SET debug_sync='thd_report_wait_for SIGNAL waiting8';
+send UPDATE t1 SET b=1008 WHERE a=3;
+--connection default
+SET debug_sync='now WAIT_FOR waiting8';
+
+--connection default
+COMMIT;
+--connection m1
+REAP;
+--connection m2
+REAP;
+COMMIT;
+--connection m3
+REAP;
+--connection m4
+REAP;
+--connection m5
+REAP;
+--connection m6
+REAP;
+--connection m7
+REAP;
+--connection m8
+REAP;
+--connection default
+SET debug_sync='RESET';
+SELECT * FROM t1 ORDER BY a;
+--source include/save_master_gtid.inc
+
+--connection server_2
+--source include/start_slave.inc
+--source include/sync_with_master_gtid.inc
+SELECT * FROM t1 ORDER BY a;
+--let $retry2= query_get_value(SHOW STATUS LIKE 'Slave_retried_transactions', Value, 1)
+--disable_query_log
+eval SELECT IF($retry1=$retry2, "Ok, no retry",
+ CONCAT("ERROR: ", $retry2-$retry1, " retries during replication (was ",
+ $retry1, " now ", $retry2, ")")) AS status;
+--enable_query_log
+
+
+--echo *** Test that we replicate correctly when using READ COMMITTED and binlog_format=MIXED on the slave ***
+
+--connection server_2
+--source include/stop_slave.inc
+SET @old_format= @@GLOBAL.binlog_format;
+# Use MIXED format; we cannot binlog ROW events on slave in STATEMENT format.
+SET GLOBAL binlog_format= MIXED;
+SET @old_isolation= @@GLOBAL.tx_isolation;
+SET GLOBAL TRANSACTION ISOLATION LEVEL READ COMMITTED;
+# Reset the worker threads to make the new settings take effect.
+SET GLOBAL slave_parallel_threads=0;
+SET GLOBAL slave_parallel_threads=10;
+
+--connection server_1
+DROP TABLE t1, t2;
+CREATE TABLE t1 (a int PRIMARY KEY, b INT) ENGINE=InnoDB;
+CREATE TABLE t2 (a int PRIMARY KEY, b INT) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1,0), (2,0), (3,0);
+INSERT INTO t2 VALUES (1,0), (2,0);
+INSERT INTO t1 SELECT 4, COUNT(*) FROM t2;
+INSERT INTO t2 SELECT 4, COUNT(*) FROM t1;
+
+INSERT INTO t1 SELECT 5, COUNT(*) FROM t2;
+INSERT INTO t2 SELECT 5, COUNT(*) FROM t1;
+
+INSERT INTO t2 SELECT 6, COUNT(*) FROM t1;
+INSERT INTO t1 SELECT 6, COUNT(*) FROM t2;
+
+INSERT INTO t1 SELECT 7, COUNT(*) FROM t2;
+INSERT INTO t2 SELECT 7, COUNT(*) FROM t1;
+
+INSERT INTO t2 SELECT 8, COUNT(*) FROM t1;
+INSERT INTO t1 SELECT 8, COUNT(*) FROM t2;
+
+INSERT INTO t2 SELECT 9, COUNT(*) FROM t1;
+INSERT INTO t1 SELECT 9, COUNT(*) FROM t2;
+
+INSERT INTO t1 SELECT 10, COUNT(*) FROM t2;
+INSERT INTO t2 SELECT 10, COUNT(*) FROM t1;
+
+SELECT * FROM t1 ORDER BY a;
+SELECT * FROM t2 ORDER BY a;
+--source include/save_master_gtid.inc
+
+--connection server_2
+--source include/start_slave.inc
+--source include/sync_with_master_gtid.inc
+SELECT * FROM t1 ORDER BY a;
+SELECT * FROM t2 ORDER BY a;
+
+--source include/stop_slave.inc
+SET GLOBAL binlog_format= @old_format;
+SET GLOBAL tx_isolation= @old_isolation;
+--source include/start_slave.inc
+
+
+--echo *** MDEV-7888: ANALYZE TABLE does wakeup_subsequent_commits(), causing wrong binlog order and parallel replication hang ***
+
+--connection server_1
+DROP TABLE t1, t2, t3;
+CREATE TABLE t1 (a INT PRIMARY KEY, b INT) ENGINE=InnoDB;
+CREATE TABLE t2 (a INT PRIMARY KEY, b INT) ENGINE=InnoDB;
+CREATE TABLE t3 (a INT PRIMARY KEY, b INT) ENGINE=MyISAM;
+INSERT INTO t2 VALUES (1,1), (2,1), (3,1), (4,1), (5,1);
+--source include/save_master_gtid.inc
+
+--connection server_2
+--source include/sync_with_master_gtid.inc
+--source include/stop_slave.inc
+SET @old_debug= @@GLOBAL.debug_dbug;
+SET GLOBAL debug_dbug= '+d,inject_analyze_table_sleep';
+
+--connection server_1
+# The bug was that ANALYZE TABLE would call
+# wakeup_subsequent_commits() too early, allowing the following
+# transaction in the same group to run ahead and binlog and free the
+# GCO. Then we get wrong binlog order and later access freed GCO,
+# which causes lost wakeup of following GCO and thus replication hang.
+# We injected a small sleep in ANALYZE to make the race easier to hit (this
+# can only cause false negatives in versions with the bug, not false positives,
+# so sleep is ok here. And it's in general not possible to trigger reliably
+# the race with debug_sync, since the bugfix makes the race impossible).
+
+ALTER TABLE t2 COMMENT "123abc";
+ANALYZE TABLE t2;
+INSERT INTO t1 VALUES (1,2);
+INSERT INTO t1 VALUES (2,2);
+INSERT INTO t1 VALUES (3,2);
+INSERT INTO t1 VALUES (4,2);
+INSERT INTO t3 VALUES (1,3);
+ALTER TABLE t2 COMMENT "hello, world";
+BEGIN;
+INSERT INTO t1 VALUES (5,4);
+INSERT INTO t1 VALUES (6,4);
+INSERT INTO t1 VALUES (7,4);
+INSERT INTO t1 VALUES (8,4);
+INSERT INTO t1 VALUES (9,4);
+INSERT INTO t1 VALUES (10,4);
+INSERT INTO t1 VALUES (11,4);
+INSERT INTO t1 VALUES (12,4);
+INSERT INTO t1 VALUES (13,4);
+INSERT INTO t1 VALUES (14,4);
+INSERT INTO t1 VALUES (15,4);
+INSERT INTO t1 VALUES (16,4);
+INSERT INTO t1 VALUES (17,4);
+INSERT INTO t1 VALUES (18,4);
+INSERT INTO t1 VALUES (19,4);
+INSERT INTO t1 VALUES (20,4);
+COMMIT;
+INSERT INTO t1 VALUES (21,5);
+INSERT INTO t1 VALUES (22,5);
+
+SELECT * FROM t1 ORDER BY a;
+SELECT * FROM t2 ORDER BY a;
+SELECT * FROM t3 ORDER BY a;
+--source include/save_master_gtid.inc
+
+--connection server_2
+--source include/start_slave.inc
+--source include/sync_with_master_gtid.inc
+
+SELECT * FROM t1 ORDER BY a;
+SELECT * FROM t2 ORDER BY a;
+SELECT * FROM t3 ORDER BY a;
+
+--source include/stop_slave.inc
+SET GLOBAL debug_dbug= @old_debug;
+--source include/start_slave.inc
+
+--echo *** MDEV-7929: record_gtid() for non-transactional event group calls wakeup_subsequent_commits() too early, causing slave hang. ***
+
+--connection server_2
+--source include/stop_slave.inc
+SET @old_dbug= @@GLOBAL.debug_dbug;
+# The bug was that record_gtid(), when there is no existing transaction from
+# a DML event being replicated, would commit its own transaction. This wrongly
+# caused wakeup_subsequent_commits(), with similar consequences as MDEV-7888
+# above. We simulate this condition with a small sleep in record_gtid() for
+# a specific ANALYZE that we binlog with server id 100.
+SET GLOBAL debug_dbug= '+d,inject_record_gtid_serverid_100_sleep';
+
+--connection server_1
+
+ALTER TABLE t3 COMMENT "DDL statement 1";
+INSERT INTO t1 VALUES (30,0);
+INSERT INTO t1 VALUES (31,0);
+INSERT INTO t1 VALUES (32,0);
+INSERT INTO t1 VALUES (33,0);
+INSERT INTO t1 VALUES (34,0);
+INSERT INTO t1 VALUES (35,0);
+INSERT INTO t1 VALUES (36,0);
+SET @old_server_id= @@SESSION.server_id;
+SET SESSION server_id= 100;
+ANALYZE TABLE t2;
+SET SESSION server_id= @old_server_id;
+INSERT INTO t1 VALUES (37,0);
+ALTER TABLE t3 COMMENT "DDL statement 2";
+INSERT INTO t1 VALUES (38,0);
+INSERT INTO t1 VALUES (39,0);
+ALTER TABLE t3 COMMENT "DDL statement 3";
+
+SELECT * FROM t1 WHERE a >= 30 ORDER BY a;
+
+--source include/save_master_gtid.inc
+
+
+--connection server_2
+--source include/start_slave.inc
+--source include/sync_with_master_gtid.inc
+SELECT * FROM t1 WHERE a >= 30 ORDER BY a;
+
+
+--source include/stop_slave.inc
+SET GLOBAL debug_dbug= @old_debug;
+--source include/start_slave.inc
+
+
+--echo *** MDEV-8113: ALTER TABLE causes slave hang in optimistic parallel replication ***
+
+--connection server_2
+--source include/stop_slave.inc
+
+--connection server_1
+ALTER TABLE t2 ADD c INT;
+INSERT INTO t2 (a,b) VALUES (50, 0);
+INSERT INTO t2 (a,b) VALUES (51, 1);
+INSERT INTO t2 (a,b) VALUES (52, 2);
+INSERT INTO t2 (a,b) VALUES (53, 3);
+INSERT INTO t2 (a,b) VALUES (54, 4);
+INSERT INTO t2 (a,b) VALUES (55, 5);
+INSERT INTO t2 (a,b) VALUES (56, 6);
+INSERT INTO t2 (a,b) VALUES (57, 7);
+INSERT INTO t2 (a,b) VALUES (58, 8);
+INSERT INTO t2 (a,b) VALUES (59, 9);
+ALTER TABLE t2 DROP COLUMN c;
+SELECT * FROM t2 WHERE a >= 50 ORDER BY a;
+--source include/save_master_gtid.inc
+
+--connection server_2
+--source include/start_slave.inc
+--source include/sync_with_master_gtid.inc
+SELECT * FROM t2 WHERE a >= 50 ORDER BY a;
+
+
+--echo *** MDEV-8075: DROP TEMPORARY TABLE not marked as ddl, causing optimistic parallel replication to fail ***
+
+--connection server_2
+--source include/stop_slave.inc
+
+--connection server_1
+INSERT INTO t1 VALUES (40, 10);
+CREATE TEMPORARY TABLE t1 (a INT PRIMARY KEY) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (41);
+BEGIN;
+INSERT INTO t2 SELECT a, 20 FROM t1;
+DROP TEMPORARY TABLE t1;
+COMMIT;
+INSERT INTO t1 VALUES (42, 10);
+--source include/save_master_gtid.inc
+SELECT * FROM t1 WHERE a >= 40 ORDER BY a;
+SELECT * FROM t2 WHERE a >= 40 ORDER BY a;
+
+--connection server_2
+--source include/start_slave.inc
+--source include/sync_with_master_gtid.inc
+SELECT * FROM t1 WHERE a >= 40 ORDER BY a;
+SELECT * FROM t2 WHERE a >= 40 ORDER BY a;
+
+# partial cleanup to reuse the tables by following tests
+--connection server_1
+DELETE FROM t1;
+DELETE FROM t2;
+--source include/save_master_gtid.inc
+
+--connection server_2
+--source include/sync_with_master_gtid.inc
+
+#
+# MDEV-13577 optimistic parallel slave errors out to error log unnecessary
+#
+
+# The 1st of the following two trx:s a blocker on slave
+--connection server_2
+set global log_warnings=2;
+BEGIN;
+INSERT INTO t1 SET a=1;
+
+--connection server_1
+SET @save.binlog_format=@@session.binlog_format;
+SET @@SESSION.binlog_format=row;
+
+BEGIN;
+ INSERT INTO t1 SET a=1;
+ INSERT INTO t2 SET a=1;
+COMMIT;
+
+# This transaction is going to win optimistical race with above INSERT
+# on slave while being depend on it. That means it will face a kind of temporary error
+# and then will retry to succeed.
+BEGIN;
+ DELETE FROM t2;
+COMMIT;
+
+# First make sure DELETE raced indeed to get stuck at retrying stage
+# where it runs "realistically" now. There is nomore optimistic error
+# in the errorlog, which is downgraded to the warning level (when
+# --log-warnings > 1), see above suppression.
+--connection server_2
+--let $wait_condition= SELECT COUNT(*) = 1 FROM information_schema.processlist WHERE state = "Waiting for prior transaction to commit"
+--source include/wait_condition.inc
+
+# Next release the 1st trx to commit.
+--connection server_2
+ROLLBACK;
+
+# MDEV-13577 local cleanup:
+--connection server_1
+SET @@SESSION.binlog_format= @save.binlog_format;
+DELETE FROM t1;
+DELETE FROM t2;
+--source include/save_master_gtid.inc
+
+--connection server_2
+--source include/sync_with_master_gtid.inc
+
+#
+# Clean up.
+#
+--connection server_2
+--source include/stop_slave.inc
+set global log_warnings=default;
+SET GLOBAL slave_parallel_mode=@old_parallel_mode;
+SET GLOBAL slave_parallel_threads=@old_parallel_threads;
+--source include/start_slave.inc
+
+--connection server_1
+DROP TABLE t1, t2, t3;
+--source include/save_master_gtid.inc
+
+--connection server_2
+--source include/sync_with_master_gtid.inc
+# Check that old rows are deleted from mysql.gtid_slave_pos.
+# Deletion is asynchronous, so use wait_condition.inc.
+# Also, there is a small amount of non-determinism in the deletion of old
+# rows, so it is not guaranteed that there can never be more than
+# @@gtid_cleanup_batch_size rows in the table; so allow a bit of slack
+# here.
+let $wait_condition=
+ SELECT COUNT(*) <= 5*@@GLOBAL.gtid_cleanup_batch_size
+ FROM mysql.gtid_slave_pos;
+--source include/wait_condition.inc
+eval $wait_condition;
+SET GLOBAL gtid_cleanup_batch_size= @old_gtid_cleanup_batch_size;
+
+--connection server_1
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_parallel_optimistic_error_stop.test b/mysql-test/suite/rpl/t/rpl_parallel_optimistic_error_stop.test
new file mode 100644
index 00000000..27f38d47
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_parallel_optimistic_error_stop.test
@@ -0,0 +1,180 @@
+--source include/have_innodb.inc
+--source include/have_debug.inc
+--source include/have_debug_sync.inc
+--let $rpl_topology=1->2
+--source include/rpl_init.inc
+
+call mtr.add_suppression("Slave: Commit failed due to failure of an earlier commit");
+call mtr.add_suppression("Slave: Duplicate entry '99'");
+
+--connection server_1
+ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
+CREATE TABLE t1 (a int PRIMARY KEY, b INT) ENGINE=InnoDB;
+INSERT INTO t1 VALUES(1,1); # hit a dup entry on slave
+INSERT INTO t1 VALUES(2,1); # races to "win" the last exit
+INSERT INTO t1 VALUES(3,1);
+INSERT INTO t1 VALUES(4,1); # make W3 race over W1
+--save_master_pos
+
+--connection server_2
+--sync_with_master
+SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads;
+--source include/stop_slave.inc
+SET @old_debug_dbug = @@global.debug_dbug;
+# In a group of W1,W2,W3 of the same batch W2 simulates slowness.
+SET @@global.debug_dbug = "d,hold_worker2_favor_worker3";
+SET GLOBAL slave_parallel_threads=4;
+CHANGE MASTER TO master_use_gtid=slave_pos;
+SET @old_parallel_mode=@@GLOBAL.slave_parallel_mode;
+SET GLOBAL slave_parallel_mode='optimistic';
+
+# MDEV-30780 optimistic parallel slave hangs after hit an error
+# Test workers hang scenario to prove it's no more neither
+# out-of-order access to the active gco list.
+#
+# The test provides how to reproduce on the OLD version, false by default.
+# That branch approximates the original hang with an assert that
+# confirms the OLD version indeed could access already reclaimed gco.
+--let $old_version_regression=0
+
+
+--connection server_1
+
+# Let W1,W2,W3,W4 parallel workers that are going to execute
+# the following transaction.
+# W1 holds on with the 1st statement
+# then crashes W3 with the 2nd into retry,
+# finally hits with the 3rd a dup entry, on slave.
+SET @@gtid_seq_no = 2001;
+BEGIN;
+ UPDATE t1 SET b = 11 WHERE a = 4;
+ UPDATE t1 SET b = 11 WHERE a = 3;
+ UPDATE t1 SET a = 99 WHERE a = 1;
+COMMIT;
+# In the buggy version W2 races to "win" the exit last (of W1..3)
+# and by that to access last a gco struct, garbage-collected.
+UPDATE t1 SET b = 2 WHERE a = 2;
+# W3 garbage-collects the gco struct in the buggy version.
+UPDATE t1 SET b = 3 WHERE a = 3;
+# W4 resides in following "singleton" batch to a W2 replacement
+# in the buggy version to allow W3 reclaim the batch's gco.
+DROP TABLE IF EXISTS phantom_1;
+
+--source include/save_master_gtid.inc
+
+--connect (slave_local_0, 127.0.0.1, root,, test, $SLAVE_MYPORT,)
+begin;
+ UPDATE t1 set b = 11 where a = 4;
+--connect (slave_local_1, 127.0.0.1, root,, test, $SLAVE_MYPORT,)
+begin;
+ INSERT INTO t1 VALUES (99, 11);
+
+--connect (slave_local_2, 127.0.0.1, root,, test, $SLAVE_MYPORT,)
+begin;
+ UPDATE t1 SET b = 12 WHERE a = 2;
+
+--connect (slave_local_3, 127.0.0.1, root,, test, $SLAVE_MYPORT,)
+begin;
+ UPDATE t1 SET b = 13 WHERE a = 3;
+
+--connection server_2
+--source include/start_slave.inc
+
+--echo # W4 is waiting to start its DROP
+
+--let $wait_condition= SELECT count(*) = 1 FROM information_schema.processlist WHERE state LIKE "Waiting for prior transaction to start commit%"
+--source include/wait_condition.inc
+
+--connection slave_local_3
+# make W3 to set E.cc <- 1
+ rollback;
+--let $wait_condition= SELECT count(*) = 1 FROM information_schema.processlist WHERE state LIKE "Waiting for prior transaction to commit%"
+--source include/wait_condition.inc
+
+--connection slave_local_0
+# make W3 into retry and delay it to let W1 hit a dupicate error first,
+# see 'commit' by slave_local_1.
+ rollback;
+--let $wait_condition= SELECT count(*) = 1 FROM information_schema.processlist WHERE state LIKE "debug sync point: now"
+--source include/wait_condition.inc
+SELECT count(*) = 0 as "W3 undid its commit state" FROM information_schema.processlist WHERE state LIKE "Waiting for prior transaction to commit%";
+
+
+--connection slave_local_2
+ rollback;
+# wait for W2 to start committing E.cc <- 2
+--let $wait_condition= SELECT count(*) = 1 FROM information_schema.processlist WHERE state like "Waiting for prior transaction to commit"
+--source include/wait_condition.inc
+
+--connection slave_local_1
+
+# W1 errors out
+# A. to alert W3
+# B. W3 will *not* wake up W4 in the fixed version, having to wait for W2 demise.
+# C. W2 will notify W3 that releases W4 as it would do in normal cases.
+commit;
+
+if (!$old_version_regression)
+{
+# A. In the fixed version show-processlist W4 is still in the ordered waiting
+SELECT COUNT(*) = 1 as "W4 remains with the same status" FROM information_schema.processlist WHERE state LIKE "Waiting for prior transaction to start commit%";
+--let $status= query_get_value("show slave status", Slave_SQL_Running, 1)
+--echo # Slave_SQL_Running YES = $status
+
+# B. In the fixed version W3 is waiting for W2,...
+--let $wait_condition= SELECT count(*) = 1 as "W4 is waiting" FROM information_schema.processlist WHERE state LIKE "Waiting for prior transaction to commit%"
+--source include/wait_condition.inc
+--echo # while W2 is held back ...
+--let $wait_condition= SELECT count(*) = 1 as "W2 simulates slowness" FROM information_schema.processlist WHERE state LIKE "debug sync point: now"
+--source include/wait_condition.inc
+
+# C. # ...until NOW.
+SET DEBUG_SYNC = 'now SIGNAL cont_worker2';
+
+}
+
+# To reproduce the hang on the OLD version ...
+if ($old_version_regression)
+{
+ # replace the actual fixes block with checking W3,W4 have actually committed,
+ # followed by signaling to W2 like on behalf of W4 which would end up in the hang.
+ --let $wait_condition= SELECT COUNT(*) = 0 as "W4 has moved on" FROM information_schema.processlist WHERE state like "Waiting for prior transaction to start commit"
+ --source include/wait_condition.inc
+ --let $wait_condition= SELECT count(*) = 0 as "W3 does not wait on W2" FROM information_schema.processlist WHERE state LIKE "Waiting for prior transaction to commit%"
+--source include/wait_condition.inc
+
+ --let $wait_condition= SELECT count(*) = 1 as "W2 simulates slowness" FROM information_schema.processlist WHERE state LIKE "debug sync point: now"
+ --source include/wait_condition.inc
+
+ # Like above, but signaling is done after W4 is done to violate the commit order
+ # that must fire a debug assert.
+ SET DEBUG_SYNC = 'now SIGNAL cont_worker2';
+}
+
+--let $slave_sql_errno= 1062
+--source include/wait_for_slave_sql_error.inc
+
+# Restore the slave data and resume with replication
+DELETE FROM t1 WHERE a=99;
+--source include/start_slave.inc
+--source include/sync_with_master_gtid.inc
+
+#
+# Clean up.
+#
+--connection server_2
+--source include/stop_slave.inc
+SET GLOBAL slave_parallel_mode=@old_parallel_mode;
+SET GLOBAL slave_parallel_threads=@old_parallel_threads;
+SET @@global.debug_dbug = @old_debug_dbug;
+SET debug_sync = RESET;
+--source include/start_slave.inc
+
+--connection server_1
+DROP TABLE t1;
+--source include/save_master_gtid.inc
+
+--connection server_2
+--source include/sync_with_master_gtid.inc
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_parallel_optimistic_nobinlog.cnf b/mysql-test/suite/rpl/t/rpl_parallel_optimistic_nobinlog.cnf
new file mode 100644
index 00000000..b85a84f6
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_parallel_optimistic_nobinlog.cnf
@@ -0,0 +1,10 @@
+!include ../my.cnf
+
+[mysqld.1]
+log-slave-updates=0
+loose-innodb
+
+[mysqld.2]
+slave-transaction-retries=100
+log-slave-updates=0
+loose-innodb
diff --git a/mysql-test/suite/rpl/t/rpl_parallel_optimistic_nobinlog.test b/mysql-test/suite/rpl/t/rpl_parallel_optimistic_nobinlog.test
new file mode 100644
index 00000000..ee0de499
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_parallel_optimistic_nobinlog.test
@@ -0,0 +1,77 @@
+--source include/have_innodb.inc
+--source include/have_binlog_format_statement.inc
+--let $rpl_topology=1->2
+--source include/rpl_init.inc
+
+--connection server_1
+ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
+CREATE TABLE t1 (a int PRIMARY KEY, b INT) ENGINE=InnoDB;
+CREATE TABLE t2 (a int PRIMARY KEY, b INT) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1,0), (2,0), (3,0);
+INSERT INTO t2 VALUES (1,0), (2,0);
+--save_master_pos
+
+
+--connection server_2
+--sync_with_master
+SET @old_isolation= @@GLOBAL.tx_isolation;
+SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads;
+--source include/stop_slave.inc
+SET GLOBAL TRANSACTION ISOLATION LEVEL READ COMMITTED;
+SET GLOBAL slave_parallel_threads=10;
+CHANGE MASTER TO master_use_gtid=slave_pos;
+SET @old_parallel_mode=@@GLOBAL.slave_parallel_mode;
+SET GLOBAL slave_parallel_mode='aggressive';
+
+
+--echo *** Test that we replicate correctly when using READ COMMITTED and --log-slave-updates=0 on the slave ***
+
+--connection server_1
+
+INSERT INTO t1 SELECT 4, COUNT(*) FROM t2;
+INSERT INTO t2 SELECT 4, COUNT(*) FROM t1;
+
+INSERT INTO t1 SELECT 5, COUNT(*) FROM t2;
+INSERT INTO t2 SELECT 5, COUNT(*) FROM t1;
+
+INSERT INTO t2 SELECT 6, COUNT(*) FROM t1;
+INSERT INTO t1 SELECT 6, COUNT(*) FROM t2;
+
+INSERT INTO t1 SELECT 7, COUNT(*) FROM t2;
+INSERT INTO t2 SELECT 7, COUNT(*) FROM t1;
+
+INSERT INTO t2 SELECT 8, COUNT(*) FROM t1;
+INSERT INTO t1 SELECT 8, COUNT(*) FROM t2;
+
+INSERT INTO t2 SELECT 9, COUNT(*) FROM t1;
+INSERT INTO t1 SELECT 9, COUNT(*) FROM t2;
+
+INSERT INTO t1 SELECT 10, COUNT(*) FROM t2;
+INSERT INTO t2 SELECT 10, COUNT(*) FROM t1;
+
+SELECT * FROM t1 ORDER BY a;
+SELECT * FROM t2 ORDER BY a;
+--source include/save_master_gtid.inc
+
+--connection server_2
+--source include/start_slave.inc
+--source include/sync_with_master_gtid.inc
+SELECT * FROM t1 ORDER BY a;
+SELECT * FROM t2 ORDER BY a;
+
+
+--connection server_2
+--source include/stop_slave.inc
+SET GLOBAL tx_isolation= @old_isolation;
+SET GLOBAL slave_parallel_mode=@old_parallel_mode;
+SET GLOBAL slave_parallel_threads=@old_parallel_threads;
+--source include/start_slave.inc
+
+--connection server_1
+DROP TABLE t1, t2;
+
+--connection server_2
+call mtr.add_suppression("Deadlock found when trying to get lock.*");
+
+--source include/rpl_end.inc
+
diff --git a/mysql-test/suite/rpl/t/rpl_parallel_optimistic_until.test b/mysql-test/suite/rpl/t/rpl_parallel_optimistic_until.test
new file mode 100644
index 00000000..0797e8bf
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_parallel_optimistic_until.test
@@ -0,0 +1,486 @@
+--source include/have_innodb.inc
+--source include/have_debug.inc
+--source include/have_debug_sync.inc
+--source include/master-slave.inc
+# Format is restricted because the test expects a specific result of
+# relay-logging that splits a transaction into two different files.
+--source include/have_binlog_format_row.inc
+
+#
+# MDEV-15152 Optimistic parallel slave doesn't cope well with START SLAVE UNTIL
+#
+--connection slave
+--source include/stop_slave.inc
+RESET MASTER;
+RESET SLAVE;
+
+--connection master
+RESET MASTER;
+CREATE TABLE t1 (a int primary key, b text) ENGINE=InnoDB;
+--let $a0 = 25
+--eval INSERT INTO t1 SET a=$a0, b='trx0'
+# Memorize the position for replication restart from it
+--let $pos_trx0 = query_get_value(SHOW MASTER STATUS, Position, 1)
+
+--connection slave
+--source include/start_slave.inc
+
+--connection master
+# --connection slave
+--sync_slave_with_master
+--source include/stop_slave.inc
+ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
+SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads;
+SET GLOBAL slave_parallel_threads=2;
+SET @old_parallel_mode=@@GLOBAL.slave_parallel_mode;
+SET GLOBAL slave_parallel_mode='optimistic';
+
+# Run the slave in the following modes one by one.
+#
+# 1. the until position is set in the middle of trx2
+# below $pos_trx0 of the last exec position in the first file
+# 2. and above $pos_trx0
+# In either case trx2 must commit before slave stops.
+# 3. the until postion is inside trx1
+# 4. RELAY log until inside trx1
+# 5. RELAY log until inside a "big" trx
+# 6. RELAY log until inside a trx within a sequence of relay logs
+#
+# Execution flaw for Until_Master_Pos cases follows as:
+# create the transaction trx1, trx2
+# logged at the beginning of two subsequent binlog files.
+# Set the until position to at the middle of the 2rd transaction.
+# Engage the optimistic scheduler while having trx1 execution blocked.
+# Lift the block after trx2 has reached waiting its order to commit.
+# *Proof 1*
+# Observe that the slave applier stops at a correct position.
+# In the bug condition it would stop prematurely having the stop position
+# in the first file, therefore trx2 not committed.
+# Specifically, an internal transaction position until makes the applier to run
+# beyond it to commit commit the current transaction.
+# *Proof 2*
+# Observe the following START SLAVE resumes OK.
+#
+# Auxiliary third trx3 on master is just for triggering the actual stop
+# (whihc is a legacy UNTIL's property).
+# trx0 is to produce a specific value of the last executed binlog file:pos
+# to emulate the bug condition.
+#
+# Intermediate checks via SELECT are supposed to succeed
+# with putting out value 1.
+#
+# NOTE: Relay log until tests have to use explicit log names and position
+# which may require to adjust with future changes to event formats etc.
+#
+
+--connection slave
+SET @old_max_relay_log_size = @@global.max_relay_log_size;
+SET @@global.max_relay_log_size=4096;
+
+--connection master
+# trx1
+--let $a=1
+BEGIN;
+while (`SELECT $a < $a0`)
+{
+ --eval INSERT INTO t1 SET a=$a, b='trx1'
+--inc $a
+}
+COMMIT;
+--let $fil_1 = query_get_value(SHOW MASTER STATUS, File, 1)
+--let $pos_trx1 = query_get_value(SHOW MASTER STATUS, Position, 1)
+
+FLUSH LOGS;
+
+# $pos_0 the offset of the first event of trx2 in new file
+--let $pos_0=query_get_value(SHOW MASTER STATUS, Position, 1)
+# trx2
+--let $a=$a0
+BEGIN;
+--eval UPDATE t1 SET b='trx2_0' WHERE a = $a
+--eval UPDATE t1 SET b='trx2' WHERE a = $a
+COMMIT;
+--let $fil_2=query_get_value(SHOW MASTER STATUS, File, 1)
+--let $pos_trx2=query_get_value(SHOW MASTER STATUS, Position, 1)
+
+# trx3
+--let $a=$a0
+--inc $a
+--eval INSERT INTO t1 SET a=$a,b='trx3'
+--let $pos_trx3=query_get_value(SHOW MASTER STATUS, Position, 1)
+--let $a=
+
+
+--echo *** case 1 UNTIL inside trx2
+
+--connection slave1
+# Blocker to hold off EXEC_MASTER_LOG_POS advance
+BEGIN;
+ --eval INSERT INTO t1 SET a= 1
+--connection slave
+--let $pos_until=`SELECT $pos_trx0 - 1`
+--replace_result $pos_0 <pos_0> $pos_until <pos_until> $pos_trx2 <pos_trx2>
+--eval SELECT $pos_0 <= $pos_until AND $pos_until < $pos_trx2 as "pos_until < trx0 and is within trx2"
+CHANGE MASTER TO MASTER_USE_GTID=no;
+--replace_result $fil_2 file_2 $pos_until <pos_until>
+--eval START SLAVE UNTIL MASTER_LOG_FILE = '$fil_2', MASTER_LOG_POS = $pos_until
+
+--let $wait_condition= SELECT COUNT(*) > 0 FROM information_schema.processlist WHERE state = "Waiting for prior transaction to commit"
+--source include/wait_condition.inc
+
+--connection slave1
+# unblock to see the slave applier stops at $until
+ROLLBACK;
+
+--echo Proof 1: Correct stop
+--connection slave
+--source include/wait_for_slave_sql_to_stop.inc
+--let $file_stop= query_get_value(SHOW SLAVE STATUS, Relay_Master_Log_File, 1)
+--let $pos_stop= query_get_value(SHOW SLAVE STATUS, Exec_Master_Log_Pos, 1)
+if (`SELECT "$file_stop" != "$fil_2" OR $pos_stop < $pos_until`)
+{
+ --echo *** ERROR: Slave stopped at $file_stop:$pos_stop which is not $fil_2:$pos_until.
+ --die
+}
+--eval SELECT count(*) = 1 as 'trx2 is committed' FROM t1 WHERE b = 'trx2'
+--eval SELECT count(*) = 0 as 'trx3 is not committed' FROM t1 WHERE b = 'trx3'
+
+--echo Proof 2: Resume works out
+--source include/start_slave.inc
+--connection master
+--sync_slave_with_master
+
+
+--echo *** case 2 UNTIL inside trx2
+
+--connection slave
+--eval DELETE FROM t1 WHERE a <> $a0
+--eval UPDATE t1 SET b='trx0' WHERE a = $a0
+
+--connection slave1
+# Blocker to hold off EXEC_MASTER_LOG_POS advance
+BEGIN;
+ --eval INSERT INTO t1 SET a= 1
+
+--connection slave
+--source include/stop_slave.inc
+
+--let $pos_until=`SELECT $pos_trx2 - 1`
+--replace_result $pos_trx0 <pos_0> $pos_until <pos_until> $pos_trx2 <pos_trx2>
+--eval SELECT $pos_trx0 <= $pos_until AND $pos_until < $pos_trx2 as "pos_until >= trx0 and is within trx2"
+--replace_result $fil_1 file_1 $pos_trx0 <pos_trx0>
+--eval CHANGE MASTER TO MASTER_LOG_FILE = '$fil_1', MASTER_LOG_POS = $pos_trx0, MASTER_USE_GTID=no
+--replace_result $fil_2 file_2 $pos_until <pos_until>
+--eval START SLAVE UNTIL MASTER_LOG_FILE = '$fil_2', MASTER_LOG_POS = $pos_until
+
+--let $wait_condition= SELECT COUNT(*) > 0 FROM information_schema.processlist WHERE state = "Waiting for prior transaction to commit"
+--source include/wait_condition.inc
+
+--connection slave1
+# unblock to see the slave applier stops at $until
+ROLLBACK;
+
+--echo Proof 1: Correct stop
+--connection slave
+--source include/wait_for_slave_sql_to_stop.inc
+--let $file_stop= query_get_value(SHOW SLAVE STATUS, Relay_Master_Log_File, 1)
+--let $pos_stop= query_get_value(SHOW SLAVE STATUS, Exec_Master_Log_Pos, 1)
+if (`SELECT "$file_stop" != "$fil_2" OR $pos_stop < $pos_until`)
+{
+ --echo *** ERROR: Slave stopped at $file_stop:$pos_stop which is not $fil_2:$pos_until.
+ --die
+}
+--eval SELECT count(*) = 1 as 'trx2 is committed' FROM t1 WHERE b = 'trx2'
+--eval SELECT count(*) = 0 as 'trx3 is not committed' FROM t1 WHERE b = 'trx3'
+
+--echo Proof 2: Resume works out
+--source include/start_slave.inc
+--connection master
+--sync_slave_with_master
+
+
+--echo *** case 3 UNTIL inside trx1
+
+--connection slave
+--eval DELETE FROM t1 WHERE a <> $a0
+--eval UPDATE t1 SET b='trx0' WHERE a = $a0
+
+
+--connection slave1
+# Blocker to hold off EXEC_MASTER_LOG_POS advance
+BEGIN;
+ --eval INSERT INTO t1 SET a= 1; # block trx1
+
+--connection slave
+--source include/stop_slave.inc
+
+--let $pos_until=`SELECT $pos_0 - 1`
+--replace_result $pos_0 <pos_0> $pos_until <pos_until> $pos_trx2 <pos_trx2>
+--eval SELECT $pos_until < $pos_0 as "pos_until before trx2 start position"
+--replace_result $fil_1 file_1 $pos_trx0 <pos_trx0>
+--eval CHANGE MASTER TO MASTER_LOG_FILE = '$fil_1', MASTER_LOG_POS = $pos_trx0, MASTER_USE_GTID=no
+--replace_result $fil_2 file_2 $pos_until <pos_until>
+--eval START SLAVE UNTIL MASTER_LOG_FILE = '$fil_2', MASTER_LOG_POS = $pos_until
+
+--connection slave1
+# unblock to see the slave applier stops at $until
+ROLLBACK;
+
+--echo Proof 1: Correct stop
+--connection slave
+--source include/wait_for_slave_sql_to_stop.inc
+--let $file_stop= query_get_value(SHOW SLAVE STATUS, Relay_Master_Log_File, 1)
+--let $pos_stop= query_get_value(SHOW SLAVE STATUS, Exec_Master_Log_Pos, 1)
+if (`SELECT "$file_stop" != "$fil_2" OR $pos_stop < $pos_until`)
+{
+ --echo *** ERROR: Slave stopped at $file_stop:$pos_stop which is not $fil_2:$pos_until.
+ --die
+}
+--eval SELECT count(*) = $a0-1 as 'trx1 is committed' FROM t1 WHERE b = 'trx1'
+--eval SELECT count(*) = 0 as 'trx2 is not committed' FROM t1 WHERE b = 'trx2'
+
+--echo Proof 2: Resume works out
+--source include/start_slave.inc
+--connection master
+--sync_slave_with_master
+
+
+--echo *** case 4 Relay-log UNTIL inside trx1
+
+--connection slave
+--eval DELETE FROM t1 WHERE a <> $a0
+--eval UPDATE t1 SET b='trx0' WHERE a = $a0
+
+--connection slave1
+# Blocker to hold off EXEC_MASTER_LOG_POS advance
+BEGIN;
+ --eval INSERT INTO t1 SET a= 1; # block trx1
+
+--connection slave
+--source include/stop_slave.inc
+--replace_result $fil_1 file_1 $pos_trx0 <pos_trx0>
+--eval CHANGE MASTER TO MASTER_LOG_FILE = '$fil_1', MASTER_LOG_POS = $pos_trx0, MASTER_USE_GTID=no
+START SLAVE IO_THREAD;
+--source include/wait_for_slave_io_to_start.inc
+
+# The following test sets the stop coordinate to inside the first event
+# of a relay log that holds events of a transaction started in an earlier log.
+# Peek the stop position in the middle of trx1, not even on a event boundary.
+--let $pos_until=255
+--let $file_rl=slave-relay-bin.000003
+--let $binlog_file=$file_rl
+
+# Wait for the IO thread to write the trx1 to the relaylog before querying it.
+# (wait_for_slave_param.inc isn't flexible enough, so do it manually.)
+--let $continue= 1
+--let $count=600
+while ($continue)
+{
+ --let $cur_file= query_get_value(SHOW SLAVE STATUS, 'Master_Log_File', 1)
+ --let $cur_pos= query_get_value(SHOW SLAVE STATUS, 'Read_Master_Log_Pos', 1)
+ --let $continue= `SELECT '$cur_file' = '$fil_1' AND $cur_pos < $pos_trx1`
+ if ($continue)
+ {
+ --dec $count
+ if (!$count)
+ {
+ --echo **** ERROR: timeout waiting for Read_Master_Log_Pos($cur_pos) >= $pos_trx1 (file='$cur_file') ****"
+ --die Timeout waiting for IO thread to write master events to the relaylog
+ }
+ --sleep 0.1
+ }
+}
+
+--let $pos_xid=508
+--let $info= query_get_value(SHOW RELAYLOG EVENTS IN '$file_rl' FROM $pos_xid LIMIT 1, Info, 1)
+
+if (`SELECT "$info" NOT LIKE "COMMIT /* xid=% */" OR $pos_xid < $pos_until`)
+{
+ --echo *** Unexpected offset. Refine it to point to the correct XID event!
+ --die
+}
+
+--replace_result $file_rl file_2 $pos_until <pos_until>
+--eval START SLAVE UNTIL RELAY_LOG_FILE = '$file_rl', RELAY_LOG_POS = $pos_until
+
+--connection slave1
+# unblock to see the slave applier stops at $until
+ROLLBACK;
+
+--echo Proof 1: Correct stop
+--connection slave
+--source include/wait_for_slave_sql_to_stop.inc
+--let $file_stop= query_get_value(SHOW SLAVE STATUS, Relay_Log_File, 1)
+--let $pos_stop= query_get_value(SHOW SLAVE STATUS, Relay_Log_Pos, 1)
+if (`SELECT strcmp("$file_rl","$file_stop") > -1`)
+{
+ --echo *** ERROR: Slave stopped at $file_stop:$pos_stop which is not $file_rl:$pos_until.
+ --die
+}
+
+--eval SELECT count(*) = $a0-1 as 'trx1 is committed' FROM t1 WHERE b = 'trx1'
+--eval SELECT count(*) = 0 as 'trx2 is not committed' FROM t1 WHERE b = 'trx2'
+
+--echo Proof 2: Resume works out
+--source include/start_slave.inc
+--connection master
+--sync_slave_with_master
+
+
+
+--echo *** case 5 Relay-log UNTIL inside a "big" trx that spawns few relay logs
+
+--connection master
+CREATE TABLE t2 (a TEXT) ENGINE=InnoDB;
+FLUSH LOGS;
+
+--sync_slave_with_master
+--let $file_stop= query_get_value(SHOW SLAVE STATUS, Relay_Log_File, 1)
+--let $pos_stop= query_get_value(SHOW SLAVE STATUS, Relay_Log_Pos, 1)
+--let $records=`SELECT floor(4*@@global.max_relay_log_size / 1024) + 1`
+
+--connection slave
+--source include/stop_slave.inc
+
+--connection master
+# trx4
+BEGIN;
+--let $i=$records
+while ($i)
+{
+ INSERT INTO t2 SET a=repeat('a',1024);
+
+--dec $i
+}
+COMMIT;
+
+# slave will stop there:
+--let $file_trx4 = query_get_value(SHOW MASTER STATUS, File, 1)
+--let $pos_trx4 = query_get_value(SHOW MASTER STATUS, Position, 1)
+
+# trx5
+INSERT INTO t2 SET a='a';
+--let $pos_trx5 = query_get_value(SHOW MASTER STATUS, Position, 1)
+
+--connection slave
+START SLAVE IO_THREAD;
+--source include/wait_for_slave_io_to_start.inc
+
+# Set position inside the transaction though the value
+# specified is beyond that relay log file.
+# The coordianate may point to in a different event in future changes
+# but should not move away from inside this big group of events.
+# So we don't test which event in the transaction it points to.
+--let $pos_until= 4500
+--let $file_rl= slave-relay-bin.000010
+
+--replace_result $file_rl file_2 $pos_until <pos_until>
+--eval START SLAVE UNTIL RELAY_LOG_FILE = '$file_rl', RELAY_LOG_POS = $pos_until
+
+--echo Proof 1: Correct stop
+--connection slave
+--source include/wait_for_slave_sql_to_stop.inc
+--let $file_stop= query_get_value(SHOW SLAVE STATUS, Relay_Master_Log_File, 1)
+--let $pos_stop= query_get_value(SHOW SLAVE STATUS, Exec_Master_Log_Pos, 1)
+# It's showed the actual stop occurred before trx5
+if (`SELECT strcmp("$file_trx4", "$file_stop") <> 0 OR $pos_stop >= $pos_trx5 OR count(*) <> $records FROM t2`)
+{
+ --echo *** ERROR: Slave stopped at *binlog* $file_stop:$pos_stop which is not $file_trx4:$pos_trx4.
+ --die
+}
+
+--echo Proof 2: Resume works out
+--source include/start_slave.inc
+--connection master
+--sync_slave_with_master
+
+--let $diff_tables=master:t2,slave:t2
+--source include/diff_tables.inc
+
+
+
+--echo *** case 6 Relay-log UNTIL inside a small trx inside a sequence of relay logs
+
+--connection slave
+--source include/stop_slave.inc
+
+--connection master
+# trx6
+--let $records=`SELECT count(*) FROM t2`
+while ($records)
+{
+ BEGIN;
+ DELETE FROM t2 LIMIT 1;
+ COMMIT;
+--dec $records
+}
+COMMIT;
+
+--connection slave
+START SLAVE IO_THREAD;
+--source include/wait_for_slave_io_to_start.inc
+
+--connection master
+--source include/sync_slave_io_with_master.inc
+
+--connection slave
+# The relay-log coordinate is not at an event boundary and
+# also may change across the server version.
+# The test makes its best to check its coherance.
+--let $pos_until= 3130
+--let $file_rl= slave-relay-bin.000018
+
+--let $pos_gtid = 2987
+--let $info= query_get_value(SHOW RELAYLOG EVENTS IN '$file_rl' FROM $pos_gtid LIMIT 1, Info, 1)
+
+if (`SELECT "$info" != "BEGIN GTID 0-1-23"`)
+{
+ --echo *** Unexpected offset. Refine it to point to the correct GTID!
+ --die
+}
+--let $pos_event = 3120
+--let $type= query_get_value(SHOW RELAYLOG EVENTS IN '$file_rl' FROM $pos_event LIMIT 1, Event_type, 1)
+if (`SELECT "$type" != "Delete_rows_v1"`)
+{
+ --echo *** Unexpected offset. Refine it to point to the expected event!
+ --die
+}
+
+--replace_result $file_rl file_2 $pos_until <pos_until>
+--eval START SLAVE UNTIL RELAY_LOG_FILE = '$file_rl', RELAY_LOG_POS = $pos_until
+
+--echo Proof 1: Correct stop
+--connection slave
+--source include/wait_for_slave_sql_to_stop.inc
+--let $file_stop= query_get_value(SHOW SLAVE STATUS, Relay_Log_File, 1)
+--let $pos_stop= query_get_value(SHOW SLAVE STATUS, Relay_Log_Pos, 1)
+if (`SELECT strcmp("$file_stop", "$file_rl") = -1 OR
+ strcmp("$file_stop", "$file_rl") = 0 AND $pos_stop < $pos_until`)
+{
+ --echo *** ERROR: Slave stopped at *relay* $file_stop:$pos_stop which is not $file_rl:$pos_until.
+ --die
+}
+
+--echo Proof 2: Resume works out
+--source include/start_slave.inc
+--connection master
+--sync_slave_with_master
+
+--let $diff_tables=master:t2,slave:t2
+--source include/diff_tables.inc
+
+#
+# Clean up.
+#
+--connection slave
+--source include/stop_slave.inc
+SET GLOBAL max_relay_log_size=@old_max_relay_log_size;
+SET GLOBAL slave_parallel_mode=@old_parallel_mode;
+SET GLOBAL slave_parallel_threads=@old_parallel_threads;
+--source include/start_slave.inc
+
+--connection master
+DROP TABLE t1, t2;
+
+--sync_slave_with_master
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_parallel_optimistic_xa.test b/mysql-test/suite/rpl/t/rpl_parallel_optimistic_xa.test
new file mode 100644
index 00000000..35c22d1e
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_parallel_optimistic_xa.test
@@ -0,0 +1,235 @@
+# The tests verify concurrent execution of replicated (MDEV-742)
+# XA transactions in the parallel optimistic mode.
+
+--source include/have_innodb.inc
+--source include/have_perfschema.inc
+--source include/master-slave.inc
+
+# Tests' global declarations
+--let $trx = _trx_
+
+call mtr.add_suppression("Deadlock found when trying to get lock; try restarting transaction");
+call mtr.add_suppression("WSREP: handlerton rollback failed");
+#call mtr.add_suppression("Can't find record in 't1'");
+CREATE VIEW v_processlist as SELECT * FROM performance_schema.threads where type = 'FOREGROUND';
+
+--connection master
+ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
+--save_master_pos
+
+# Prepare to restart slave into optimistic parallel mode
+--connection slave
+--sync_with_master
+--source include/stop_slave.inc
+SET @old_parallel_threads = @@GLOBAL.slave_parallel_threads;
+SET @@global.slave_parallel_threads = 7;
+SET @old_parallel_mode = @@GLOBAL.slave_parallel_mode;
+SET @@global.slave_parallel_mode ='optimistic';
+# Run the first part of the test with high batch size and see that
+# old rows remain in the table.
+SET @old_gtid_cleanup_batch_size = @@GLOBAL.gtid_cleanup_batch_size;
+SET @@global.gtid_cleanup_batch_size = 1000000;
+
+CHANGE MASTER TO master_use_gtid=slave_pos;
+
+# LOAD GENERATOR creates XA:s interleaved in binlog when they are from
+# different connections. All the following block XA:s of the same connection
+# update the same data which challenges slave optimistic scheduler's correctness.
+# Slave must eventually apply such load, and correctly (checked).
+
+--connection master
+CREATE TABLE t0 (a int, b INT) ENGINE=InnoDB;
+CREATE TABLE t1 (a int PRIMARY KEY, b INT) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1, 0);
+
+
+# I. Logging some sequence of XA:s by one connection.
+#
+# The slave applier's task is to successfully execute a series of
+# Prepare and Complete parts of a sequence of XA:s
+
+--let $trx_num = 300
+--let $i = $trx_num
+--let $conn = master
+--disable_query_log
+while($i > 0)
+{
+ # 'decision' to commit 0, or rollback 1
+ --let $decision = `SELECT $i % 2`
+ --eval XA START '$conn$trx$i'
+ --eval UPDATE t1 SET b = 1 - 2 * $decision WHERE a = 1
+ --eval XA END '$conn$trx$i'
+ --let $one_phase = `SELECT IF(floor(rand()*10)%2, "ONE PHASE", 0)`
+ if (!$one_phase)
+ {
+ --eval XA PREPARE '$conn$trx$i'
+ --let $one_phase =
+ }
+
+ --let $term = COMMIT
+ if ($decision)
+ {
+ --let $term = ROLLBACK
+ --let $one_phase =
+ }
+ --eval XA $term '$conn$trx$i' $one_phase
+
+ --dec $i
+}
+--enable_query_log
+--source include/save_master_gtid.inc
+
+--connection slave
+--source include/start_slave.inc
+--source include/sync_with_master_gtid.inc
+--source include/stop_slave.inc
+
+
+# II. Logging XS:s from multiple connections in random interweaving manner:
+#
+# in a loop ($i) per connection
+# arrange an inner ($k) loop where
+# start and prepare an XA;
+# decide whether to terminate it and then continue to loop innerly
+# OR disconnect to break the inner loop;
+# the disconnected one's XA is taken care by 'master' connection
+#
+# Effectively binlog must collect a well mixed XA- prepared and terminated
+# groups for slave to handle.
+
+--connection master
+# Total # of connections
+--let $conn_num=53
+
+--let $i = $conn_num
+--disable_query_log
+while($i > 0)
+{
+ --connect (master_conn$i, 127.0.0.1,root,,test,$MASTER_MYPORT,)
+--dec $i
+}
+--enable_query_log
+
+--let $i = $conn_num
+while($i > 0)
+{
+ --let $conn_i = conn$i
+ # $i2 indexes the current connection's "own" row
+ --let $i2 = `SELECT $i + 2`
+--disable_query_log
+ --connection master_conn$i
+--enable_query_log
+ --disable_query_log
+ --let $i_conn_id = `SELECT connection_id()`
+
+ --let $decision = 0
+ # the row id of the last connection that committed its XA
+ --let $c_max = 1
+ --let $k = 0
+ while ($decision < 3)
+ {
+ --inc $k
+ --eval XA START '$conn_i$trx$k'
+ # UPDATE depends on previously *committed* transactions
+ --eval UPDATE t1 SET b = b + $k + 1 WHERE a = $c_max
+ if (`SELECT $k % 2 = 1`)
+ {
+ --eval REPLACE INTO t1 VALUES ($i2, $k)
+ }
+ if (`SELECT $k % 2 = 0`)
+ {
+ --eval DELETE FROM t1 WHERE a = $i2
+ }
+ CREATE TEMPORARY TABLE tmp LIKE t0;
+ --eval INSERT INTO tmp SET a=$i, b= $k
+ INSERT INTO t0 SELECT * FROM tmp;
+ DROP TEMPORARY TABLE tmp;
+ --eval XA END '$conn_i$trx$k'
+
+ --let $term = COMMIT
+ --let $decision = `SELECT (floor(rand()*10 % 10) + ($i+$k)) % 4`
+ if ($decision == 1)
+ {
+ --let $term = ROLLBACK
+ }
+ if ($decision < 2)
+ {
+ --eval XA PREPARE '$conn_i$trx$k'
+ --eval XA $term '$conn_i$trx$k'
+ # Iteration counter is taken care *now*
+ }
+ if ($decision == 2)
+ {
+ --eval XA COMMIT '$conn_i$trx$k' ONE PHASE
+ }
+ }
+
+ # $decision = 3
+ --eval XA PREPARE '$conn_i$trx$k'
+ # disconnect now
+ --disconnect master_conn$i
+ --connection master
+
+ --let $wait_condition= SELECT count(*) = 0 FROM v_processlist WHERE PROCESSLIST_ID = $i_conn_id
+ --source include/wait_condition.inc
+
+ --disable_query_log
+ --let $decision = `SELECT ($i+$k) % 2`
+ --let $term = COMMIT
+ if ($decision == 1)
+ {
+ --let $term = ROLLBACK
+ }
+ --eval XA $term '$conn_i$trx$k'
+ --let $c_max = $i2
+
+--dec $i
+}
+--enable_query_log
+--source include/save_master_gtid.inc
+
+--connection slave
+--source include/start_slave.inc
+--source include/sync_with_master_gtid.inc
+
+#
+# Overall consistency check
+#
+--let $diff_tables= master:t0, slave:t0
+--source include/diff_tables.inc
+--let $diff_tables= master:t1, slave:t1
+--source include/diff_tables.inc
+
+
+#
+# Clean up.
+#
+--connection slave
+--source include/stop_slave.inc
+set global log_warnings=default;
+SET GLOBAL slave_parallel_mode=@old_parallel_mode;
+SET GLOBAL slave_parallel_threads=@old_parallel_threads;
+--source include/start_slave.inc
+
+--connection master
+DROP VIEW v_processlist;
+DROP TABLE t0, t1;
+--source include/save_master_gtid.inc
+
+--connection slave
+--source include/sync_with_master_gtid.inc
+# Check that old rows are deleted from mysql.gtid_slave_pos.
+# Deletion is asynchronous, so use wait_condition.inc.
+# Also, there is a small amount of non-determinism in the deletion of old
+# rows, so it is not guaranteed that there can never be more than
+# @@gtid_cleanup_batch_size rows in the table; so allow a bit of slack
+# here.
+let $wait_condition=
+ SELECT COUNT(*) <= 5*@@GLOBAL.gtid_cleanup_batch_size
+ FROM mysql.gtid_slave_pos;
+--source include/wait_condition.inc
+eval $wait_condition;
+SET GLOBAL gtid_cleanup_batch_size= @old_gtid_cleanup_batch_size;
+
+--connection master
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_parallel_optimistic_xa_lsu_off-slave.opt b/mysql-test/suite/rpl/t/rpl_parallel_optimistic_xa_lsu_off-slave.opt
new file mode 100644
index 00000000..88cf77fd
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_parallel_optimistic_xa_lsu_off-slave.opt
@@ -0,0 +1 @@
+--log-slave-updates=OFF
diff --git a/mysql-test/suite/rpl/t/rpl_parallel_optimistic_xa_lsu_off.test b/mysql-test/suite/rpl/t/rpl_parallel_optimistic_xa_lsu_off.test
new file mode 100644
index 00000000..f82b522e
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_parallel_optimistic_xa_lsu_off.test
@@ -0,0 +1,2 @@
+# --log-slave-updates OFF version of rpl_parallel_optimistic_xa
+--source rpl_parallel_optimistic_xa.test
diff --git a/mysql-test/suite/rpl/t/rpl_parallel_partial_binlog_trans.test b/mysql-test/suite/rpl/t/rpl_parallel_partial_binlog_trans.test
new file mode 100644
index 00000000..72479252
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_parallel_partial_binlog_trans.test
@@ -0,0 +1,71 @@
+--echo *** MDEV_6435: Incorrect error handling when query binlogged partially on master with "killed" error ***
+
+--source include/have_innodb.inc
+--source include/have_debug.inc
+--source include/have_debug_sync.inc
+--source include/have_binlog_format_statement.inc
+--source include/master-slave.inc
+
+--connection server_2
+--source include/stop_slave.inc
+SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads;
+SET GLOBAL slave_parallel_threads=1;
+CHANGE MASTER TO master_use_gtid=slave_pos;
+--source include/start_slave.inc
+
+--connection server_1
+ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
+CREATE TABLE t6 (a INT) ENGINE=MyISAM;
+CREATE TRIGGER tr AFTER INSERT ON t6 FOR EACH ROW SET @a = 1;
+--connect (con1,127.0.0.1,root,,test,$SERVER_MYPORT_1,)
+
+--connection con1
+--let $conid = `SELECT CONNECTION_ID()`
+SET debug_sync='sp_head_execute_before_loop SIGNAL ready WAIT_FOR cont';
+send INSERT INTO t6 VALUES (1), (2), (3);
+
+--connection server_1
+SET debug_sync='now WAIT_FOR ready';
+--replace_result $conid CONID
+eval KILL QUERY $conid;
+SET debug_sync='now SIGNAL cont';
+
+--connection con1
+--error ER_QUERY_INTERRUPTED
+--reap
+SET debug_sync='RESET';
+--let $after_error_gtid_pos= `SELECT @@gtid_binlog_pos`
+
+--connection server_1
+SET debug_sync='RESET';
+
+--connection server_2
+--let $slave_sql_errno= 1317
+--source include/wait_for_slave_sql_error.inc
+STOP SLAVE IO_THREAD;
+--replace_result $after_error_gtid_pos AFTER_ERROR_GTID_POS
+eval SET GLOBAL gtid_slave_pos= '$after_error_gtid_pos';
+--source include/start_slave.inc
+
+--connection server_1
+INSERT INTO t6 VALUES (4);
+SELECT * FROM t6 ORDER BY a;
+--save_master_pos
+
+--connection server_2
+--sync_with_master
+SELECT * FROM t6 ORDER BY a;
+
+# Clean up.
+--connection server_2
+--source include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=@old_parallel_threads;
+--source include/start_slave.inc
+SET DEBUG_SYNC= 'RESET';
+
+--connection server_1
+DROP TABLE t6;
+SET DEBUG_SYNC= 'RESET';
+--disconnect con1
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_parallel_partition.test b/mysql-test/suite/rpl/t/rpl_parallel_partition.test
new file mode 100644
index 00000000..ea6c5dca
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_parallel_partition.test
@@ -0,0 +1,81 @@
+--source include/have_partition.inc
+--source include/have_innodb.inc
+--source include/have_debug.inc
+--source include/master-slave.inc
+
+--connection server_2
+SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads;
+--source include/stop_slave.inc
+SET @old_dbug= @@GLOBAL.debug_dbug;
+SET GLOBAL debug_dbug="+d,inject_wakeup_subsequent_commits_sleep";
+SET GLOBAL slave_parallel_threads=8;
+
+--echo *** MDEV-8147: Assertion `m_lock_type == 2' failed in handler::ha_close() during parallel replication ***
+--connection server_1
+CREATE TABLE E (
+ pk INTEGER AUTO_INCREMENT,
+ col_int_nokey INTEGER /*! NULL */,
+ col_int_key INTEGER /*! NULL */,
+
+ col_date_key DATE /*! NULL */,
+ col_date_nokey DATE /*! NULL */,
+
+ col_time_key TIME /*! NULL */,
+ col_time_nokey TIME /*! NULL */,
+
+ col_datetime_key DATETIME /*! NULL */,
+ col_datetime_nokey DATETIME /*! NULL */,
+
+ col_varchar_key VARCHAR(1) /*! NULL */,
+ col_varchar_nokey VARCHAR(1) /*! NULL */,
+
+ PRIMARY KEY (pk),
+ KEY (col_int_key),
+ KEY (col_date_key),
+ KEY (col_time_key),
+ KEY (col_datetime_key),
+ KEY (col_varchar_key, col_int_key)
+ ) ENGINE=InnoDB;
+
+ALTER TABLE `E` PARTITION BY KEY() PARTITIONS 5;
+ALTER TABLE `E` REMOVE PARTITIONING;
+--write_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
+wait
+EOF
+--shutdown_server
+--source include/wait_until_disconnected.inc
+--connection default
+--source include/wait_until_disconnected.inc
+--append_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
+restart:
+EOF
+--enable_reconnect
+--source include/wait_until_connected_again.inc
+--connection server_1
+--enable_reconnect
+--source include/wait_until_connected_again.inc
+CREATE TABLE t1 (a INT PRIMARY KEY);
+--save_master_pos
+
+--connection server_2
+--source include/start_slave.inc
+--sync_with_master
+
+# Re-spawn worker threads to clear dbug injection.
+--source include/stop_slave.inc
+SET GLOBAL debug_dbug=@old_dbug;
+SET GLOBAL slave_parallel_threads=0;
+SET GLOBAL slave_parallel_threads=8;
+--source include/start_slave.inc
+
+
+# Clean up.
+--connection server_2
+--source include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=@old_parallel_threads;
+--source include/start_slave.inc
+
+--connection server_1
+DROP TABLE `E`;
+DROP TABLE t1;
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_parallel_record_gtid_wakeup.test b/mysql-test/suite/rpl/t/rpl_parallel_record_gtid_wakeup.test
new file mode 100644
index 00000000..0f94d8f9
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_parallel_record_gtid_wakeup.test
@@ -0,0 +1,72 @@
+--echo *** MDEV-7929: record_gtid() for non-transactional event group calls wakeup_subsequent_commits() too early, causing slave hang. ***
+
+--source include/have_innodb.inc
+--source include/have_debug.inc
+--source include/have_debug_sync.inc
+--source include/master-slave.inc
+
+--connection server_2
+SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads;
+--source include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=10;
+CHANGE MASTER TO master_use_gtid=slave_pos;
+--source include/start_slave.inc
+
+--connection server_1
+ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
+CREATE TABLE t1 (a int PRIMARY KEY) ENGINE=MyISAM;
+CREATE TABLE t3 (a INT PRIMARY KEY, b INT) ENGINE=InnoDB;
+--save_master_pos
+
+--connection server_2
+--sync_with_master
+--source include/stop_slave.inc
+SET @old_dbug= @@GLOBAL.debug_dbug;
+SET GLOBAL debug_dbug= '+d,inject_record_gtid_serverid_100_sleep';
+
+--connection server_1
+# Inject two group commits. The bug was that record_gtid for a
+# non-transactional event group would commit its own transaction, which would
+# cause ha_commit_trans() to call wakeup_subsequent_commits() too early. This
+# in turn lead to access to freed group_commit_orderer object, losing a wakeup
+# and causing slave threads to hang.
+# We inject a small sleep in the corresponding record_gtid() to make the race
+# easier to hit.
+
+SET @old_dbug= @@SESSION.debug_dbug;
+SET SESSION debug_dbug="+d,binlog_force_commit_id";
+
+# Group commit with cid=10010, two event groups.
+SET @old_server_id= @@SESSION.server_id;
+SET SESSION server_id= 100;
+SET @commit_id= 10010;
+ALTER TABLE t1 COMMENT "Hulubulu!";
+SET SESSION server_id= @old_server_id;
+INSERT INTO t3 VALUES (130, 0);
+
+# Group commit with cid=10011, one event group.
+SET @commit_id= 10011;
+INSERT INTO t3 VALUES (131, 0);
+
+SET SESSION debug_dbug=@old_dbug;
+
+SELECT * FROM t3 WHERE a >= 130 ORDER BY a;
+--source include/save_master_gtid.inc
+
+--connection server_2
+--source include/start_slave.inc
+--source include/sync_with_master_gtid.inc
+
+SELECT * FROM t3 WHERE a >= 130 ORDER BY a;
+
+# Clean up.
+--source include/stop_slave.inc
+SET GLOBAL debug_dbug= @old_dbug;
+SET GLOBAL slave_parallel_threads=@old_parallel_threads;
+--source include/start_slave.inc
+
+--connection server_1
+DROP TABLE t1,t3;
+
+--source include/rpl_end.inc
+
diff --git a/mysql-test/suite/rpl/t/rpl_parallel_retry.test b/mysql-test/suite/rpl/t/rpl_parallel_retry.test
new file mode 100644
index 00000000..8b2affed
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_parallel_retry.test
@@ -0,0 +1,514 @@
+--source include/have_innodb.inc
+--source include/have_perfschema.inc
+--source include/have_debug.inc
+--source include/have_debug_sync.inc
+--let $rpl_topology=1->2
+--source include/rpl_init.inc
+
+--echo *** Test retry of transactions that fail to replicate due to deadlock or similar temporary error. ***
+
+--connection server_1
+ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
+CREATE TABLE t1 (a int PRIMARY KEY, b INT) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1,1);
+--save_master_pos
+
+# Use a stored function to inject a debug_sync into the appropriate THD.
+# The function does nothing on the master, and on the slave it injects the
+# desired debug_sync action(s).
+SET sql_log_bin=0;
+--delimiter ||
+CREATE FUNCTION foo(x INT, d1 VARCHAR(500), d2 VARCHAR(500))
+ RETURNS INT DETERMINISTIC
+ BEGIN
+ RETURN x;
+ END
+||
+--delimiter ;
+SET sql_log_bin=1;
+
+--connection server_2
+SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads;
+--source include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=5;
+--source include/start_slave.inc
+--sync_with_master
+SET sql_log_bin=0;
+--delimiter ||
+CREATE FUNCTION foo(x INT, d1 VARCHAR(500), d2 VARCHAR(500))
+ RETURNS INT DETERMINISTIC
+ BEGIN
+ IF d1 != '' THEN
+ SET debug_sync = d1;
+ END IF;
+ IF d2 != '' THEN
+ SET debug_sync = d2;
+ END IF;
+ RETURN x;
+ END
+||
+--delimiter ;
+SET sql_log_bin=1;
+--source include/stop_slave.inc
+
+--connection server_1
+SET gtid_seq_no = 100;
+BEGIN;
+INSERT INTO t1 VALUES (2,1);
+UPDATE t1 SET b=b+1 WHERE a=1;
+INSERT INTO t1 VALUES (3,1);
+COMMIT;
+SELECT * FROM t1 ORDER BY a;
+--save_master_pos
+
+--connection server_2
+SET @old_dbug= @@GLOBAL.debug_dbug;
+SET GLOBAL debug_dbug="+d,rpl_parallel_simulate_temp_err_gtid_0_x_100";
+let $old_retry= query_get_value(SHOW STATUS LIKE 'Slave_retried_transactions', Value, 1);
+--source include/start_slave.inc
+--sync_with_master
+SET GLOBAL debug_dbug=@old_dbug;
+let $new_retry= query_get_value(SHOW STATUS LIKE 'Slave_retried_transactions', Value, 1);
+let $ps_value= query_get_value(select last_trans_retry_count from
+ performance_schema.replication_applier_status_by_worker where
+ last_trans_retry_count > 0, last_trans_retry_count, 1);
+let $assert_text= Performance Schema retries should match with actual retries;
+let $assert_cond= "$ps_value" = $new_retry - $old_retry;
+source include/assert.inc;
+
+
+SELECT * FROM t1 ORDER BY a;
+
+
+--echo *** Test that double retry works when the first retry also fails with temp error ***
+--source include/stop_slave.inc
+
+--connection server_1
+SET gtid_seq_no = 100;
+SET @old_server_id = @@server_id;
+SET server_id = 10;
+BEGIN;
+INSERT INTO t1 VALUES (4,1);
+UPDATE t1 SET b=b+1 WHERE a=1;
+INSERT INTO t1 VALUES (5,1);
+INSERT INTO t1 VALUES (6,1);
+COMMIT;
+SET server_id = @old_server_id;
+SELECT * FROM t1 ORDER BY a;
+--save_master_pos
+
+--connection server_2
+SET @old_dbug= @@GLOBAL.debug_dbug;
+SET GLOBAL debug_dbug="+d,rpl_parallel_simulate_temp_err_gtid_0_x_100,rpl_parallel_simulate_double_temp_err_gtid_0_x_100";
+let $old_retry= query_get_value(SHOW STATUS LIKE 'Slave_retried_transactions', Value, 1);
+--source include/start_slave.inc
+--sync_with_master
+SET GLOBAL debug_dbug=@old_dbug;
+let $new_retry= query_get_value(SHOW STATUS LIKE 'Slave_retried_transactions', Value, 1);
+let $ps_value= query_get_value(select last_trans_retry_count from
+ performance_schema.replication_applier_status_by_worker where
+ last_trans_retry_count > 0, last_trans_retry_count, 1);
+let $assert_text= Performance Schema retries should match with actual retries;
+let $assert_cond= "$ps_value" = $new_retry - $old_retry;
+source include/assert.inc;
+
+SELECT * FROM t1 ORDER BY a;
+
+
+--echo *** Test too many retries, eventually causing failure. ***
+--source include/stop_slave.inc
+
+--connection server_1
+SET gtid_seq_no = 100;
+SET @old_server_id = @@server_id;
+SET server_id = 11;
+BEGIN;
+INSERT INTO t1 VALUES (7,1);
+UPDATE t1 SET b=b+1 WHERE a=1;
+INSERT INTO t1 VALUES (8,1);
+INSERT INTO t1 VALUES (9,1);
+COMMIT;
+SET server_id = @old_server_id;
+SELECT * FROM t1 ORDER BY a;
+--save_master_pos
+
+--connection server_2
+SET sql_log_bin=0;
+CALL mtr.add_suppression("Slave worker thread retried transaction 10 time\\(s\\) in vain, giving up");
+CALL mtr.add_suppression("Slave: Deadlock found when trying to get lock; try restarting transaction");
+CALL mtr.add_suppression("Slave worker thread retried transaction .* in vain, giving up");
+SET sql_log_bin=1;
+
+SET @old_dbug= @@GLOBAL.debug_dbug;
+SET GLOBAL debug_dbug="+d,rpl_parallel_simulate_temp_err_gtid_0_x_100,rpl_parallel_simulate_infinite_temp_err_gtid_0_x_100";
+let $old_retry= query_get_value(SHOW STATUS LIKE 'Slave_retried_transactions', Value, 1);
+START SLAVE;
+--let $slave_sql_errno= 1213
+--source include/wait_for_slave_sql_error.inc
+SET GLOBAL debug_dbug=@old_dbug;
+let $new_retry= query_get_value(SHOW STATUS LIKE 'Slave_retried_transactions', Value, 1);
+--disable_query_log
+eval SELECT $new_retry - $old_retry AS retries;
+--enable_query_log
+let $ps_value= query_get_value(select last_trans_retry_count from
+ performance_schema.replication_applier_status_by_worker where
+ last_trans_retry_count > 0, last_trans_retry_count, 1);
+let $assert_text= Performance Schema retries should match with actual retries;
+let $assert_cond= "$ps_value" = $new_retry - $old_retry;
+source include/assert.inc;
+
+SELECT * FROM t1 ORDER BY a;
+STOP SLAVE IO_THREAD;
+--source include/start_slave.inc
+--sync_with_master
+SELECT * FROM t1 ORDER BY a;
+
+--echo *** Test retry of event group that spans multiple relay log files. ***
+
+--connection server_1
+CREATE TABLE t2 (a int PRIMARY KEY, b BLOB) ENGINE=InnoDB;
+INSERT INTO t2 VALUES (1,"Hulubullu");
+--save_master_pos
+
+--connection server_2
+--sync_with_master
+--source include/stop_slave.inc
+SET @old_max= @@GLOBAL.max_relay_log_size;
+SET GLOBAL max_relay_log_size=4096;
+
+--connection server_1
+--let $big= `SELECT REPEAT("*", 5000)`
+SET gtid_seq_no = 100;
+SET @old_server_id = @@server_id;
+SET server_id = 12;
+BEGIN;
+--disable_query_log
+eval INSERT INTO t2 VALUES (2, CONCAT("Hello ", "$big"));
+eval INSERT INTO t2 VALUES (3, CONCAT("Long data: ", "$big"));
+--enable_query_log
+INSERT INTO t1 VALUES (10, 4);
+COMMIT;
+SET server_id = @old_server_id;
+SELECT * FROM t1 WHERE a >= 10 ORDER BY a;
+SELECT a, LENGTH(b) FROM t2 ORDER BY a;
+--save_master_pos
+
+--connection server_2
+SET @old_dbug= @@GLOBAL.debug_dbug;
+SET GLOBAL debug_dbug="+d,rpl_parallel_simulate_temp_err_gtid_0_x_100";
+let $old_retry= query_get_value(SHOW STATUS LIKE 'Slave_retried_transactions', Value, 1);
+--source include/start_slave.inc
+--sync_with_master
+SET GLOBAL debug_dbug=@old_dbug;
+let $new_retry= query_get_value(SHOW STATUS LIKE 'Slave_retried_transactions', Value, 1);
+let $ps_value= query_get_value(select last_trans_retry_count from
+ performance_schema.replication_applier_status_by_worker where
+ last_trans_retry_count > 0, last_trans_retry_count, 1);
+let $assert_text= Performance Schema retries should match with actual retries;
+let $assert_cond= "$ps_value" = $new_retry - $old_retry;
+source include/assert.inc;
+
+SELECT * FROM t1 WHERE a >= 10 ORDER BY a;
+SELECT a, LENGTH(b) FROM t2 ORDER BY a;
+
+--connection server_1
+INSERT INTO t1 VALUES (11,11);
+--disable_query_log
+eval INSERT INTO t2 VALUES (4, "$big");
+--enable_query_log
+--save_master_pos
+
+--connection server_2
+--sync_with_master
+SELECT * FROM t1 WHERE a >= 10 ORDER BY a;
+SELECT a, LENGTH(b) FROM t2 ORDER BY a;
+SET GLOBAL max_relay_log_size=@old_max;
+
+
+--echo *** MDEV-7065: Incorrect relay log position in parallel replication after retry of transaction ***
+
+--connection server_2
+--source include/stop_slave.inc
+
+--connection server_1
+BEGIN;
+INSERT INTO t1 VALUES (100, 0);
+INSERT INTO t1 VALUES (101, 0);
+INSERT INTO t1 VALUES (102, 0);
+INSERT INTO t1 VALUES (103, 0);
+COMMIT;
+SELECT * FROM t1 WHERE a >= 100 ORDER BY a;
+--save_master_pos
+
+--connection server_2
+# Inject a DBUG error insert to cause the XID event of the single transaction
+# from the master to fail with a deadlock error and be retried.
+# The bug was that the retry of the XID would leave the relay log position
+# incorrect (off by the size of XID event).
+SET @old_dbug= @@GLOBAL.debug_dbug;
+SET GLOBAL debug_dbug="+d,rpl_parallel_simulate_temp_err_xid";
+let $old_retry= query_get_value(SHOW STATUS LIKE 'Slave_retried_transactions', Value, 1);
+--source include/start_slave.inc
+--sync_with_master
+SET GLOBAL debug_dbug=@old_dbug;
+let $new_retry= query_get_value(SHOW STATUS LIKE 'Slave_retried_transactions', Value, 1);
+let $ps_value= query_get_value(select last_trans_retry_count from
+ performance_schema.replication_applier_status_by_worker where
+ last_trans_retry_count > 0, last_trans_retry_count, 1);
+let $assert_text= Performance Schema retries should match with actual retries;
+let $assert_cond= "$ps_value" = $new_retry - $old_retry;
+source include/assert.inc;
+
+SELECT * FROM t1 WHERE a >= 100 ORDER BY a;
+# Stop the SQL thread. When the bug was there to give the incorrect relay log
+# position, the restart of the SQL thread would read garbage data from the
+# middle of an event and fail with relay log IO error.
+--source include/stop_slave_sql.inc
+
+--connection server_1
+INSERT INTO t1 VALUES (104, 1);
+INSERT INTO t1 VALUES (105, 1);
+INSERT INTO t1 VALUES (106, 1);
+INSERT INTO t1 VALUES (107, 1);
+INSERT INTO t1 VALUES (108, 1);
+INSERT INTO t1 VALUES (109, 1);
+--save_master_pos
+
+--connection server_2
+--source include/start_slave.inc
+--sync_with_master
+SELECT * FROM t1 WHERE a >= 100 ORDER BY a;
+
+
+--echo *** MDEV-6917: Parallel replication: "Commit failed due to failure of an earlier commit on which this one depends", but no prior failure seen **
+
+--connection server_1
+CREATE TABLE t3 (a INT PRIMARY KEY, b INT, KEY b_idx(b)) ENGINE=InnoDB;
+INSERT INTO t3 VALUES (1,NULL), (2,2), (3,NULL), (4,4), (5, NULL), (6, 6);
+CREATE TABLE t4 (a INT PRIMARY KEY, b 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 t4 VALUES(100, 100);
+
+# We need statement binlog format to be able to inject debug_sync statements
+# on the slave with calls to foo().
+SET @old_format= @@SESSION.binlog_format;
+SET binlog_format='statement';
+--save_master_pos
+
+--connection server_2
+--sync_with_master
+--source include/stop_slave.inc
+CHANGE MASTER TO master_use_gtid=no;
+
+--connection server_1
+
+# Create a group commit with three transactions T1, T2, T3.
+# T2 will block T1 on the slave where we will make it run first, so it will be
+# deadlock killed.
+# The bug was that in this case, T3 was signalled to fail due to T2 failing,
+# even though the retry of T2 was later successful.
+
+--connect (con1,127.0.0.1,root,,test,$SERVER_MYPORT_1,)
+SET @old_format= @@SESSION.binlog_format;
+SET binlog_format='statement';
+BEGIN;
+INSERT INTO t4 VALUES (10, foo(1, 'before_execute_sql_command WAIT_FOR t1_start', ''));
+UPDATE t3 SET b=NULL WHERE a=6;
+SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued1 WAIT_FOR master_cont1';
+send COMMIT;
+--connection server_1
+SET debug_sync='now WAIT_FOR master_queued1';
+
+--connect (con2,127.0.0.1,root,,test,$SERVER_MYPORT_1,)
+SET @old_format= @@SESSION.binlog_format;
+SET binlog_format='statement';
+BEGIN;
+INSERT INTO t4 VALUES (20, foo(2, 'group_commit_waiting_for_prior SIGNAL t2_waiting', ''));
+DELETE FROM t3 WHERE b <= 3;
+SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued2';
+send COMMIT;
+
+--connection server_1
+SET debug_sync='now WAIT_FOR master_queued2';
+
+--connect (con3,127.0.0.1,root,,test,$SERVER_MYPORT_1,)
+SET @old_format= @@SESSION.binlog_format;
+SET binlog_format='statement';
+BEGIN;
+INSERT INTO t4 VALUES (30, foo(3, 'before_execute_sql_command WAIT_FOR t3_start', 'group_commit_waiting_for_prior SIGNAL t3_waiting'));
+INSERT INTO t3 VALUES (7,7);
+SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued3';
+send COMMIT;
+
+--connection server_1
+SET debug_sync='now WAIT_FOR master_queued3';
+SET debug_sync='now SIGNAL master_cont1';
+
+--connection con1
+REAP;
+SET binlog_format=@old_format;
+--connection con2
+REAP;
+SET binlog_format=@old_format;
+--connection con3
+REAP;
+SET debug_sync='RESET';
+SET binlog_format=@old_format;
+
+--connection server_1
+--save_master_pos
+SELECT * FROM t3 ORDER BY a;
+
+
+--connection server_2
+let $old_retry= query_get_value(SHOW STATUS LIKE 'Slave_retried_transactions', Value, 1);
+SET @old_dbug=@@GLOBAL.debug_dbug;
+SET GLOBAL debug_dbug="+d,thd_need_ordering_with_force";
+--source include/start_slave.inc
+# First, wait for T2 to complete up to where it is waiting for T1 to group
+# commit for both of them. This will set locks that will block T1, causing
+# a deadlock kill and retry of T2. T1 and T3 are still blocked at the start
+# of each their SQL statements.
+SET debug_sync='now WAIT_FOR t2_waiting';
+# Now let T3 move on until the point where it is itself ready to commit.
+SET debug_sync='now SIGNAL t3_start';
+SET debug_sync='now WAIT_FOR t3_waiting';
+# Now T2 and T3 are set up, so we can let T1 proceed.
+SET debug_sync='now SIGNAL t1_start';
+# Now we can wait for the slave to catch up.
+# We should see T2 being deadlock killed and retried.
+# The bug was that T2 deadlock kill would cause T3 to fail due to failure
+# of an earlier commit. This is wrong as T2 did not fail, it was only
+# retried.
+--sync_with_master
+SET GLOBAL debug_dbug=@old_dbug;
+SET debug_sync='RESET';
+let $new_retry= query_get_value(SHOW STATUS LIKE 'Slave_retried_transactions', Value, 1);
+let $ps_value= query_get_value(select last_trans_retry_count from
+ performance_schema.replication_applier_status_by_worker where
+ last_trans_retry_count > 0, last_trans_retry_count, 1);
+let $assert_text= Performance Schema retries should match with actual retries;
+let $assert_cond= "$ps_value" = $new_retry - $old_retry;
+source include/assert.inc;
+SELECT * FROM t3 ORDER BY a;
+
+
+--connection server_1
+SET binlog_format=@old_format;
+
+
+# Clean up of the above part.
+--connection server_2
+--source include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=@old_parallel_threads;
+--source include/start_slave.inc
+
+--connection server_1
+DROP TABLE t1, t2, t3, t4;
+DROP function foo;
+
+--sync_slave_with_master server_2
+
+#
+# MDEV-12746 rpl.rpl_parallel_optimistic_nobinlog fails committing out of order at retry
+#
+
+--connection server_1
+CREATE TABLE t1 (a int PRIMARY KEY, b 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 t1 VALUES(100, 100);
+
+# Replicate create-t1 and prepare to re-start slave in optimistic mode
+--sync_slave_with_master server_2
+--source include/stop_slave.inc
+SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads;
+SET @@GLOBAL.slave_parallel_threads=5;
+SET @old_parallel_mode=@@GLOBAL.slave_parallel_mode;
+SET @@GLOBAL.slave_parallel_mode='aggressive';
+SET @old_lock_wait_timeout=@@GLOBAL.innodb_lock_wait_timeout;
+SET @@GLOBAL.innodb_lock_wait_timeout=2;
+SET @old_slave_transaction_retries=@@GLOBAL.slave_transaction_retries;
+SET @@GLOBAL.slave_transaction_retries=1;
+
+--echo # Spoilers on the slave side causing temporary errors
+--connect (spoiler_21,127.0.0.1,root,,test,$SLAVE_MYPORT)
+BEGIN;
+ INSERT INTO t1 SET a=1,b=2;
+
+--connect (spoiler_22,127.0.0.1,root,,test,$SLAVE_MYPORT)
+BEGIN;
+ INSERT INTO t1 SET a=2,b=2;
+
+--echo # Master payload
+--connection server_1
+SET @@SESSION.GTID_SEQ_NO=1000;
+INSERT INTO t1 SET a=1,b=1;
+SET @@SESSION.GTID_SEQ_NO=1001;
+INSERT INTO t1 SET a=2,b=1;
+
+--echo # Start slave whose both appliers is destined to being blocked
+--connection server_2
+SET @old_dbug= @@GLOBAL.debug_dbug;
+SET @@GLOBAL.debug_dbug="+d,rpl_parallel_simulate_wait_at_retry";
+--source include/start_slave.inc
+
+--echo # Make sure both workers are waiting at their sync points
+--let $wait_condition= SELECT count(*)=2 FROM information_schema.processlist WHERE state LIKE '%debug sync point%';
+--source include/wait_condition.inc
+
+
+--echo # Signal to the 1st to proceed after it has reached termination state
+SET @@DEBUG_SYNC='now SIGNAL proceed_by_1000';
+--connection spoiler_21
+ROLLBACK;
+
+--let $wait_condition= SELECT count(*)=1 FROM information_schema.processlist WHERE state LIKE '%debug sync point%';
+--source include/wait_condition.inc
+
+--echo # Release the 2nd worker to proceed
+--connection spoiler_22
+ROLLBACK;
+--connection server_2
+SET @@DEBUG_SYNC='now SIGNAL proceed_by_1001';
+
+--echo # observe how it all ends
+if (`SELECT count(*) = 1 FROM t1 WHERE a = 1`)
+{
+ --echo "*** Unexpected commit by the first Worker ***"
+ SELECT * from t1;
+ --die
+}
+
+--echo # Wait for the workers to go home and check the result of applying
+--let $wait_condition=SELECT count(*) = 0 FROM information_schema.processlist WHERE command = 'Slave_worker'
+--source include/wait_condition.inc
+if (`SELECT count(*) = 1 FROM t1 WHERE a = 2`)
+{
+ --echo
+ --echo "*** Error: congrats, you hit MDEV-12746 issue. ***"
+ --echo
+ --die
+}
+--echo # which is OK
+
+#
+# Clean up
+#
+--connection server_2
+--source include/stop_slave.inc
+SET @@GLOBAL.slave_parallel_threads=@old_parallel_threads;
+SET @@GLOBAL.slave_parallel_mode=@old_parallel_mode;
+SET @@GLOBAL.innodb_lock_wait_timeout=@old_lock_wait_timeout;
+SET @@GLOBAL.slave_transaction_retries=@old_slave_transaction_retries;
+SET @@GLOBAL.debug_dbug=@old_dbug;
+SET debug_sync='RESET';
+--source include/start_slave.inc
+
+--connection server_1
+DROP TABLE t1;
+
+--sync_slave_with_master server_2
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_parallel_retry_deadlock.test b/mysql-test/suite/rpl/t/rpl_parallel_retry_deadlock.test
new file mode 100644
index 00000000..54ac859b
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_parallel_retry_deadlock.test
@@ -0,0 +1,281 @@
+--echo *** MDEV-7326 Server deadlock in connection with parallel replication ***
+--source include/have_innodb.inc
+--source include/have_debug.inc
+--source include/have_debug_sync.inc
+--source include/master-slave.inc
+
+--connection server_2
+SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads;
+SET @old_parallel_mode=@@GLOBAL.slave_parallel_mode;
+--source include/stop_slave.inc
+# Test assumes that 'conservative' mode is in effect. i.e
+# Do not start parallel execution of this event group until all prior groups
+# have reached the commit phase. Refer 'rpl_parallel_start_waiting_for_prior'
+# debug simumation.
+SET GLOBAL slave_parallel_mode='conservative';
+SET GLOBAL slave_parallel_threads=10;
+CHANGE MASTER TO master_use_gtid=slave_pos;
+--source include/start_slave.inc
+
+--connection server_1
+ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
+CREATE TABLE t1 (a int PRIMARY KEY) ENGINE=MyISAM;
+CREATE TABLE t2 (a int PRIMARY KEY) ENGINE=InnoDB;
+CREATE TABLE t6 (a INT) ENGINE=MyISAM;
+--save_master_pos
+
+--connection server_2
+--sync_with_master
+
+--connection server_1
+# Use a stored function to inject a debug_sync into the appropriate THD.
+# The function does nothing on the master, and on the slave it injects the
+# desired debug_sync action(s).
+SET sql_log_bin=0;
+--delimiter ||
+CREATE FUNCTION foo(x INT, d1 VARCHAR(500), d2 VARCHAR(500))
+ RETURNS INT DETERMINISTIC
+ BEGIN
+ RETURN x;
+ END
+||
+--delimiter ;
+SET sql_log_bin=1;
+
+--connection server_2
+SET sql_log_bin=0;
+--delimiter ||
+CREATE FUNCTION foo(x INT, d1 VARCHAR(500), d2 VARCHAR(500))
+ RETURNS INT DETERMINISTIC
+ BEGIN
+ IF d1 != '' THEN
+ SET debug_sync = d1;
+ END IF;
+ IF d2 != '' THEN
+ SET debug_sync = d2;
+ END IF;
+ RETURN x;
+ END
+||
+--delimiter ;
+SET sql_log_bin=1;
+
+# We use three transactions, each in a separate group commit.
+# T1 does mark_start_commit(), then gets a deadlock error.
+# T2 wakes up and starts running
+# T1 does unmark_start_commit()
+# T3 goes to wait for T2 to start its commit
+# T2 does mark_start_commit()
+# The bug was that at this point, T3 got deadlocked. Because T1 has unmarked(),
+# T3 did not yet see the count_committing_event_groups reach its target value
+# yet. But when T1 later re-did mark_start_commit(), it failed to send a wakeup
+# to T3.
+
+--connection server_2
+--source include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=0;
+SET GLOBAL slave_parallel_threads=3;
+SET GLOBAL debug_dbug="+d,rpl_parallel_simulate_temp_err_xid";
+--source include/start_slave.inc
+
+--connection server_1
+SET @old_format= @@SESSION.binlog_format;
+SET binlog_format= STATEMENT;
+# This debug_sync will linger on and be used to control T3 later.
+INSERT INTO t1 VALUES (foo(50,
+ "rpl_parallel_start_waiting_for_prior SIGNAL t3_ready",
+ "rpl_parallel_end_of_group SIGNAL prep_ready WAIT_FOR prep_cont"));
+--save_master_pos
+--connection server_2
+# Wait for the debug_sync point for T3 to be set. But let the preparation
+# transaction remain hanging, so that T1 and T2 will be scheduled for the
+# remaining two worker threads.
+SET DEBUG_SYNC= "now WAIT_FOR prep_ready";
+
+--connection server_1
+INSERT INTO t2 VALUES (foo(50,
+ "rpl_parallel_simulate_temp_err_xid SIGNAL t1_ready1 WAIT_FOR t1_cont1",
+ "rpl_parallel_retry_after_unmark SIGNAL t1_ready2 WAIT_FOR t1_cont2"));
+--save_master_pos
+
+--connection server_2
+SET DEBUG_SYNC= "now WAIT_FOR t1_ready1";
+# T1 has now done mark_start_commit(). It will later do a rollback and retry.
+
+--connection server_1
+# Use a MyISAM table for T2 and T3, so they do not trigger the
+# rpl_parallel_simulate_temp_err_xid DBUG insertion on XID event.
+INSERT INTO t1 VALUES (foo(51,
+ "rpl_parallel_before_mark_start_commit SIGNAL t2_ready1 WAIT_FOR t2_cont1",
+ "rpl_parallel_after_mark_start_commit SIGNAL t2_ready2"));
+
+--connection server_2
+SET DEBUG_SYNC= "now WAIT_FOR t2_ready1";
+# T2 has now started running, but has not yet done mark_start_commit()
+SET DEBUG_SYNC= "now SIGNAL t1_cont1";
+SET DEBUG_SYNC= "now WAIT_FOR t1_ready2";
+# T1 has now done unmark_start_commit() in preparation for its retry.
+
+--connection server_1
+INSERT INTO t1 VALUES (52);
+SET BINLOG_FORMAT= @old_format;
+SELECT * FROM t2 WHERE a>=50 ORDER BY a;
+SELECT * FROM t1 WHERE a>=50 ORDER BY a;
+
+--connection server_2
+# Let the preparation transaction complete, so that the same worker thread
+# can continue with the transaction T3.
+SET DEBUG_SYNC= "now SIGNAL prep_cont";
+SET DEBUG_SYNC= "now WAIT_FOR t3_ready";
+# T3 has now gone to wait for T2 to start committing
+SET DEBUG_SYNC= "now SIGNAL t2_cont1";
+SET DEBUG_SYNC= "now WAIT_FOR t2_ready2";
+# T2 has now done mark_start_commit().
+# Let things run, and check that T3 does not get deadlocked.
+SET DEBUG_SYNC= "now SIGNAL t1_cont2";
+--sync_with_master
+
+--connection server_1
+--save_master_pos
+--connection server_2
+--sync_with_master
+SELECT * FROM t2 WHERE a>=50 ORDER BY a;
+SELECT * FROM t1 WHERE a>=50 ORDER BY a;
+SET DEBUG_SYNC="reset";
+
+# Re-spawn the worker threads to remove any DBUG injections or DEBUG_SYNC.
+--source include/stop_slave.inc
+SET GLOBAL debug_dbug=@old_dbug;
+SET GLOBAL slave_parallel_mode=@old_parallel_mode;
+SET GLOBAL slave_parallel_threads=0;
+SET GLOBAL slave_parallel_threads=10;
+--source include/start_slave.inc
+
+
+--echo *** MDEV-7326 Server deadlock in connection with parallel replication ***
+# Similar to the previous test, but with T2 and T3 in the same GCO.
+# We use three transactions, T1 in one group commit and T2/T3 in another.
+# T1 does mark_start_commit(), then gets a deadlock error.
+# T2 wakes up and starts running
+# T1 does unmark_start_commit()
+# T3 goes to wait for T1 to start its commit
+# T2 does mark_start_commit()
+# The bug was that at this point, T3 got deadlocked. T2 increments the
+# count_committing_event_groups but does not signal T3, as they are in
+# the same GCO. Then later when T1 increments, it would also not signal
+# T3, because now the count_committing_event_groups is not equal to the
+# wait_count of T3 (it is one larger).
+
+--connect (con_temp3,127.0.0.1,root,,test,$SERVER_MYPORT_1,)
+--connect (con_temp4,127.0.0.1,root,,test,$SERVER_MYPORT_1,)
+
+--connection server_2
+--source include/stop_slave.inc
+SET @old_parallel_mode= @@GLOBAL.slave_parallel_mode;
+SET GLOBAL slave_parallel_mode='conservative';
+SET GLOBAL slave_parallel_threads=0;
+SET GLOBAL slave_parallel_threads=3;
+SET GLOBAL debug_dbug="+d,rpl_parallel_simulate_temp_err_xid";
+--source include/start_slave.inc
+
+--connection server_1
+SET @old_format= @@SESSION.binlog_format;
+SET binlog_format= STATEMENT;
+# This debug_sync will linger on and be used to control T3 later.
+INSERT INTO t1 VALUES (foo(60,
+ "rpl_parallel_start_waiting_for_prior SIGNAL t3_ready",
+ "rpl_parallel_end_of_group SIGNAL prep_ready WAIT_FOR prep_cont"));
+--save_master_pos
+--connection server_2
+# Wait for the debug_sync point for T3 to be set. But let the preparation
+# transaction remain hanging, so that T1 and T2 will be scheduled for the
+# remaining two worker threads.
+SET DEBUG_SYNC= "now WAIT_FOR prep_ready";
+
+--connection server_1
+INSERT INTO t2 VALUES (foo(60,
+ "rpl_parallel_simulate_temp_err_xid SIGNAL t1_ready1 WAIT_FOR t1_cont1",
+ "rpl_parallel_retry_after_unmark SIGNAL t1_ready2 WAIT_FOR t1_cont2"));
+--save_master_pos
+
+--connection server_2
+SET DEBUG_SYNC= "now WAIT_FOR t1_ready1";
+# T1 has now done mark_start_commit(). It will later do a rollback and retry.
+
+# Do T2 and T3 in a single group commit.
+# Use a MyISAM table for T2 and T3, so they do not trigger the
+# rpl_parallel_simulate_temp_err_xid DBUG insertion on XID event.
+--connection con_temp3
+SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued1 WAIT_FOR master_cont1';
+SET binlog_format=statement;
+send INSERT INTO t1 VALUES (foo(61,
+ "rpl_parallel_before_mark_start_commit SIGNAL t2_ready1 WAIT_FOR t2_cont1",
+ "rpl_parallel_after_mark_start_commit SIGNAL t2_ready2"));
+
+--connection server_1
+SET debug_sync='now WAIT_FOR master_queued1';
+
+--connection con_temp4
+SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued2';
+send INSERT INTO t6 VALUES (62);
+
+--connection server_1
+SET debug_sync='now WAIT_FOR master_queued2';
+SET debug_sync='now SIGNAL master_cont1';
+
+--connection con_temp3
+REAP;
+--connection con_temp4
+REAP;
+
+--connection server_1
+SET debug_sync='RESET';
+SET BINLOG_FORMAT= @old_format;
+SELECT * FROM t2 WHERE a>=60 ORDER BY a;
+SELECT * FROM t1 WHERE a>=60 ORDER BY a;
+SELECT * FROM t6 WHERE a>=60 ORDER BY a;
+
+--connection server_2
+SET DEBUG_SYNC= "now WAIT_FOR t2_ready1";
+# T2 has now started running, but has not yet done mark_start_commit()
+SET DEBUG_SYNC= "now SIGNAL t1_cont1";
+SET DEBUG_SYNC= "now WAIT_FOR t1_ready2";
+# T1 has now done unmark_start_commit() in preparation for its retry.
+
+--connection server_2
+# Let the preparation transaction complete, so that the same worker thread
+# can continue with the transaction T3.
+SET DEBUG_SYNC= "now SIGNAL prep_cont";
+SET DEBUG_SYNC= "now WAIT_FOR t3_ready";
+# T3 has now gone to wait for T2 to start committing
+SET DEBUG_SYNC= "now SIGNAL t2_cont1";
+SET DEBUG_SYNC= "now WAIT_FOR t2_ready2";
+# T2 has now done mark_start_commit().
+# Let things run, and check that T3 does not get deadlocked.
+SET DEBUG_SYNC= "now SIGNAL t1_cont2";
+--sync_with_master
+
+--connection server_1
+--save_master_pos
+--connection server_2
+--sync_with_master
+SELECT * FROM t2 WHERE a>=60 ORDER BY a;
+SELECT * FROM t1 WHERE a>=60 ORDER BY a;
+SELECT * FROM t6 WHERE a>=60 ORDER BY a;
+SET DEBUG_SYNC="reset";
+
+# Clean up.
+--source include/stop_slave.inc
+SET GLOBAL debug_dbug=@old_dbug;
+SET GLOBAL slave_parallel_mode=@old_parallel_mode;
+SET GLOBAL slave_parallel_threads=@old_parallel_threads;
+--source include/start_slave.inc
+
+--connection server_1
+DROP function foo;
+DROP TABLE t1,t2,t6;
+--disconnect con_temp3
+--disconnect con_temp4
+SET DEBUG_SYNC= 'RESET';
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_parallel_rollback_assert.test b/mysql-test/suite/rpl/t/rpl_parallel_rollback_assert.test
new file mode 100644
index 00000000..eec331b3
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_parallel_rollback_assert.test
@@ -0,0 +1,62 @@
+--echo *** MDEV-8725: Assertion on ROLLBACK statement in the binary log ***
+--source include/have_innodb.inc
+--source include/master-slave.inc
+
+--connection server_2
+SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads;
+--source include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=10;
+CHANGE MASTER TO master_use_gtid=slave_pos;
+--source include/start_slave.inc
+
+--connection server_1
+ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
+CREATE TABLE t1 (a int PRIMARY KEY) ENGINE=MyISAM;
+CREATE TABLE t2 (a int PRIMARY KEY) ENGINE=InnoDB;
+--save_master_pos
+
+--connection server_2
+--sync_with_master
+
+--connection server_1
+# Inject an event group terminated by ROLLBACK, by mixing MyISAM and InnoDB
+# in a transaction. The bug was an assertion on the ROLLBACK due to
+# mark_start_commit() being already called.
+--disable_warnings
+BEGIN;
+INSERT INTO t2 VALUES (2000);
+INSERT INTO t1 VALUES (2000);
+INSERT INTO t2 VALUES (2001);
+ROLLBACK;
+--enable_warnings
+SELECT * FROM t1 WHERE a>=2000 ORDER BY a;
+SELECT * FROM t2 WHERE a>=2000 ORDER BY a;
+--source include/save_master_gtid.inc
+
+--connection server_2
+--source include/sync_with_master_gtid.inc
+
+--connection server_1
+INSERT INTO t2 VALUES (2020);
+--source include/save_master_gtid.inc
+
+--connection server_2
+--source include/sync_with_master_gtid.inc
+SELECT * FROM t2 WHERE a>=2000 ORDER BY a;
+let $rows_in_t1= `SELECT COUNT(*) FROM t1 WHERE a>=2000 ORDER BY a`;
+if ($rows_in_t1 == 0)
+{
+--query_vertical SHOW SLAVE STATUS
+}
+SELECT * FROM t1 WHERE a>=2000 ORDER BY a;
+
+# Clean up.
+--source include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=@old_parallel_threads;
+--source include/start_slave.inc
+
+--connection server_1
+DROP TABLE t1,t2;
+
+--source include/rpl_end.inc
+
diff --git a/mysql-test/suite/rpl/t/rpl_parallel_sbm-slave.opt b/mysql-test/suite/rpl/t/rpl_parallel_sbm-slave.opt
new file mode 100644
index 00000000..c3407cde
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_parallel_sbm-slave.opt
@@ -0,0 +1 @@
+--slave-parallel-threads=2
diff --git a/mysql-test/suite/rpl/t/rpl_parallel_sbm.test b/mysql-test/suite/rpl/t/rpl_parallel_sbm.test
new file mode 100644
index 00000000..58c0db15
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_parallel_sbm.test
@@ -0,0 +1,218 @@
+#
+# Ensure that Seconds_Behind_Master works correctly on the parallel replica.
+#
+--source include/master-slave.inc
+--source include/have_log_bin.inc
+--source include/have_debug.inc
+
+--echo #
+--echo # MDEV-29639: Seconds_Behind_Master is incorrect for Delayed, Parallel Replicas
+--echo #
+
+# This test ensures that after a delayed parallel slave has idled, i.e.
+# executed everything in its relay log, the next event group that the SQL
+# thread reads from the relay log will immediately be used in the
+# Seconds_Behind_Master. In particular, it ensures that the calculation for
+# Seconds_Behind_Master is based on the timestamp of the new transaction,
+# rather than the last committed transaction.
+#
+
+--connection slave
+--source include/stop_slave.inc
+--let $save_dbug= `SELECT @@GLOBAL.debug_dbug`
+--let $save_parallel_mode= `SELECT @@GLOBAL.slave_parallel_mode`
+set @@GLOBAL.debug_dbug= "d,negate_clock_diff_with_master";
+set @@GLOBAL.slave_parallel_mode= CONSERVATIVE;
+--let $master_delay= 3
+--eval change master to master_delay=$master_delay, master_use_gtid=Slave_Pos
+--source include/start_slave.inc
+
+--connection master
+--let insert_ctr= 0
+create table t1 (a int);
+create table t2 (a int);
+--source include/sync_slave_sql_with_master.inc
+
+--echo #
+--echo # Pt 1) Ensure SBM is updated immediately upon arrival of the next event
+
+--connection master
+--echo # Sleep 2 to allow a buffer between events for SBM check
+sleep 2;
+
+--let $ts_trx_before_ins= `SELECT UNIX_TIMESTAMP()`
+--eval insert into t1 values ($insert_ctr)
+--inc $insert_ctr
+--source include/save_master_gtid.inc
+
+--connection slave
+
+--echo # Waiting for transaction to arrive on slave and begin SQL Delay..
+--let $wait_condition= SELECT count(*) FROM information_schema.processlist WHERE state LIKE 'Waiting until MASTER_DELAY seconds after master executed event';
+--source include/wait_condition.inc
+
+--echo # Validating SBM is updated on event arrival..
+--let $sbm_trx1_arrive= query_get_value(SHOW SLAVE STATUS, Seconds_Behind_Master, 1)
+--let $seconds_since_idling= `SELECT UNIX_TIMESTAMP() - $ts_trx_before_ins`
+if (`SELECT $sbm_trx1_arrive > ($seconds_since_idling + 1)`)
+{
+ --echo # SBM was $sbm_trx1_arrive yet shouldn't have been larger than $seconds_since_idling + 1 (for possible negative clock_diff_with_master)
+ --die Seconds_Behind_Master should reset after idling
+}
+--echo # ..done
+
+
+--echo # MDEV-32265. At time of STOP SLAVE, if the SQL Thread is currently
+--echo # delaying a transaction; then when the reciprocal START SLAVE occurs,
+--echo # if the event is still to be delayed, SBM should resume accordingly
+
+--source include/stop_slave.inc
+--source include/start_slave.inc
+
+--connection slave
+--echo # Waiting for replica to resume the delay for the transaction
+--let $wait_condition= SELECT count(*) FROM information_schema.processlist WHERE state LIKE 'Waiting until MASTER_DELAY seconds after master executed event';
+--source include/wait_condition.inc
+
+--echo # Sleeping 1s to increment SBM
+sleep 1;
+
+--echo # Ensuring Seconds_Behind_Master increases after sleeping..
+--let $sbm_trx1_after_1s_sleep= query_get_value(SHOW SLAVE STATUS, Seconds_Behind_Master, 1)
+if (`SELECT $sbm_trx1_after_1s_sleep <= $sbm_trx1_arrive`)
+{
+ --echo # ..failed
+ --die Seconds_Behind_Master did not increase after sleeping, but should have
+}
+--echo # ..done
+
+--source include/sync_with_master_gtid.inc
+
+--echo #
+--echo # Pt 2) If the worker threads have not entered an idle state, ensure
+--echo # following events do not update SBM
+
+--connection slave
+LOCK TABLES t1 WRITE;
+
+--connection master
+--echo # Sleep 2 to allow a buffer between events for SBM check
+sleep 2;
+--let $ts_trxpt2_before_ins= `SELECT UNIX_TIMESTAMP()`
+--eval insert into t1 values ($insert_ctr)
+--inc $insert_ctr
+--echo # Sleep 3 to create gap between events
+sleep 3;
+--eval insert into t1 values ($insert_ctr)
+--inc $insert_ctr
+--let $ts_trx_after_ins= `SELECT UNIX_TIMESTAMP()`
+--source include/save_master_pos.inc
+
+--connection slave
+--echo # Wait for first transaction to complete SQL delay and begin execution..
+--let $wait_condition= SELECT count(*) FROM information_schema.processlist WHERE state LIKE 'Waiting for table metadata lock%' AND command LIKE 'Slave_Worker';
+--source include/wait_condition.inc
+
+--echo # Validate SBM calculation doesn't use the second transaction because worker threads shouldn't have gone idle..
+--let $sbm_after_trx_no_idle= query_get_value(SHOW SLAVE STATUS, Seconds_Behind_Master, 1)
+--let $timestamp_trxpt2_arrive= `SELECT UNIX_TIMESTAMP()`
+if (`SELECT $sbm_after_trx_no_idle < $timestamp_trxpt2_arrive - $ts_trx_after_ins - 1`)
+{
+ --let $cmpv= `SELECT $timestamp_trxpt2_arrive - $ts_trx_after_ins`
+ --echo # SBM $sbm_after_trx_no_idle was more recent than time since last transaction ($cmpv seconds)
+ --die Seconds_Behind_Master should not have used second transaction timestamp
+}
+--let $seconds_since_idling= `SELECT ($timestamp_trxpt2_arrive - $ts_trxpt2_before_ins)`
+--echo # ..and that SBM wasn't calculated using prior committed transactions
+if (`SELECT $sbm_after_trx_no_idle > ($seconds_since_idling + 1)`)
+{
+ --echo # SBM was $sbm_after_trx_no_idle yet shouldn't have been larger than $seconds_since_idling + 1 (for possible negative clock_diff_with_master)
+ --die Seconds_Behind_Master calculation should not have used prior committed transaction
+}
+--echo # ..done
+
+--connection slave
+UNLOCK TABLES;
+--source include/sync_with_master.inc
+
+--echo # Cleanup
+--source include/stop_slave.inc
+--eval CHANGE MASTER TO master_delay=0
+--source include/start_slave.inc
+
+
+--echo #
+--echo # MDEV-30619: Parallel Slave SQL Thread Can Update Seconds_Behind_Master with Active Workers
+--echo #
+
+# This test ensures that a parallel slave will not update
+# Seconds_Behind_Master after the SQL Thread has idled if the worker threads
+# are still executing events. To test this, two events are executed on the
+# primary with $sleep seconds in-between them. Once the second event begins
+# execution on the replica, Seconds_Behind_Master is queried to ensure it
+# reflects the value of the first transaction, rather than the second.
+
+--connection slave
+--echo # Ensure the replica is fully idle before starting transactions
+--let $wait_condition= SELECT count(*) FROM information_schema.processlist WHERE state LIKE 'Slave has read all relay log%';
+--source include/wait_condition.inc
+--let $wait_condition= SELECT count(*)=2 FROM information_schema.processlist WHERE state LIKE 'Waiting for work from SQL thread';
+--source include/wait_condition.inc
+
+--echo # Lock t1 on slave so the first received transaction does not complete/commit
+LOCK TABLES t1 WRITE;
+
+--connection master
+--let $ts_t1_before_master_ins= `SELECT UNIX_TIMESTAMP()`
+--eval insert into t1 values ($insert_ctr)
+--inc $insert_ctr
+--source include/save_master_gtid.inc
+
+--connection slave
+--echo # Waiting for first transaction to begin..
+--let $wait_condition= SELECT count(*) FROM information_schema.processlist WHERE state LIKE 'Waiting for table metadata lock';
+--source include/wait_condition.inc
+
+--let $sbm_1= query_get_value(SHOW SLAVE STATUS, Seconds_Behind_Master, 1)
+
+--connection master
+--let $sleep = 2
+--echo # Sleep $sleep sec to create a gap between events
+sleep $sleep;
+INSERT INTO t2 VALUES (1);
+--source include/save_master_gtid.inc
+
+--connection slave
+--echo # Waiting for second transaction to begin..
+--let $wait_condition= SELECT count(*) FROM information_schema.processlist WHERE state LIKE 'Waiting for prior transaction to start commit%';
+--source include/wait_condition.inc
+
+--let $sbm_2= query_get_value(SHOW SLAVE STATUS, Seconds_Behind_Master, 1)
+
+if (`SELECT $sbm_1 + $sleep > $sbm_2`)
+{
+ --echo # Seconds_Behind_Masters: $sbm_1 $sbm_2_0
+ --die Two successive Seconds_Behind_Master timestamps must be separated by the sleep parameter value or greater
+}
+
+--connection slave
+UNLOCK TABLES;
+--source include/sync_with_master_gtid.inc
+
+
+--echo #
+--echo # Cleanup
+
+--connection master
+DROP TABLE t1, t2;
+--source include/save_master_gtid.inc
+
+--connection slave
+--source include/sync_with_master_gtid.inc
+--source include/stop_slave.inc
+--eval set @@GLOBAL.debug_dbug= "$save_dbug"
+--evalp set @@GLOBAL.slave_parallel_mode= "$save_parallel_mode"
+--source include/start_slave.inc
+
+--source include/rpl_end.inc
+--echo # End of rpl_parallel_sbm.test
diff --git a/mysql-test/suite/rpl/t/rpl_parallel_seq.test b/mysql-test/suite/rpl/t/rpl_parallel_seq.test
new file mode 100644
index 00000000..b1b15412
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_parallel_seq.test
@@ -0,0 +1,198 @@
+--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/master-slave.inc
+
+--connection slave
+--source include/stop_slave.inc
+ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
+
+--echo # MDEV-29621 the sequence engine binlog_row_image-full events
+--echo # MDL-deadlock on the parallel slave.
+--connection master
+CREATE SEQUENCE s1;
+SET @@session.binlog_row_image=FULL;
+SET @@session.debug_dbug="+d,binlog_force_commit_id";
+SET @commit_id=7;
+SET @@gtid_seq_no=100;
+--disable_ps2_protocol
+SELECT NEXT VALUE FOR s1;
+--enable_ps2_protocol
+INSERT INTO s1 VALUES(2, 1, 10, 1, 2, 1, 1, 0);
+SET @@session.debug_dbug="";
+
+--connection slave
+--let $slave_parallel_threads=`select @@global.slave_parallel_threads`
+--let $slave_parallel_mode=`select @@global.slave_parallel_mode`
+SET @@global.slave_parallel_threads=2;
+SET @@global.slave_parallel_mode=optimistic;
+SET @@global.debug_dbug="+d,hold_worker_on_schedule";
+--source include/start_slave.inc
+
+--let $wait_condition= SELECT count(*) = 1 FROM information_schema.processlist WHERE state LIKE "Waiting for prior transaction to start commit"
+--source include/wait_condition.inc
+SET DEBUG_SYNC = 'now SIGNAL continue_worker';
+
+--connection master
+DROP SEQUENCE s1;
+--sync_slave_with_master
+--source include/stop_slave.inc
+
+--echo # Simulate buggy 10.3.36 master to prove the parallel applier
+--echo # does not deadlock now at replaying the above master load.
+--connection master
+--let $datadir= `SELECT @@datadir`
+
+--let $rpl_server_number= 1
+--source include/rpl_stop_server.inc
+
+--remove_file $datadir/master-bin.000001
+--copy_file $MYSQL_TEST_DIR/std_data/rpl/master-bin-seq_10.3.36.000001 $datadir/master-bin.000001
+
+--let $rpl_server_number= 1
+--source include/rpl_start_server.inc
+
+--source include/wait_until_connected_again.inc
+--save_master_pos
+
+--connection slave
+RESET MASTER;
+SET @@global.gtid_slave_pos="";
+
+--replace_result $SERVER_MYPORT_1 SERVER_MYPORT_1
+eval CHANGE MASTER TO master_host='127.0.0.1', master_port=$SERVER_MYPORT_1, master_user='root', master_use_gtid=slave_pos;
+
+START SLAVE UNTIL MASTER_GTID_POS='0-1-102';
+
+--let $wait_condition= SELECT count(*) = 1 FROM information_schema.processlist WHERE state LIKE "Waiting for prior transaction to commit"
+--source include/wait_condition.inc
+SET DEBUG_SYNC = 'now SIGNAL continue_worker';
+
+--echo # Normal stop is expected
+--source include/wait_for_slave_to_stop.inc
+
+--echo # MDEV-31077 ALTER SEQUENCE may end up in optimistic parallel slave binlog out-of-order
+--echo # The test proves ALTER-SEQUENCE binlogs first before the following transaction does so.
+
+--connection slave
+--source include/stop_slave.inc
+RESET MASTER;
+SET @@global.gtid_slave_pos="";
+--connection master
+RESET MASTER;
+
+# Load from master
+CREATE TABLE ti (a INT) ENGINE=innodb;
+CREATE SEQUENCE s2 ENGINE=innodb;
+--source include/save_master_gtid.inc
+
+--connection slave
+--source include/start_slave.inc
+--source include/sync_with_master_gtid.inc
+--source include/stop_slave.inc
+--let $rpl_server_number= 2
+--source include/rpl_restart_server.inc
+# upon restart
+SET @@global.slave_parallel_threads=2;
+SET @@global.slave_parallel_mode=optimistic;
+SET @@global.debug_dbug="+d,hold_worker_on_schedule";
+--let $slave_gtid_strict_mode=`select @@global.gtid_strict_mode`
+SET @@global.gtid_strict_mode=1;
+
+--connection master
+SET @@gtid_seq_no=100;
+ALTER SEQUENCE s2 restart with 1;
+INSERT INTO ti SET a=1;
+--source include/save_master_gtid.inc
+SELECT @@global.gtid_binlog_state "Master gtid state";
+
+--connection slave
+# The following FT complicates the opening table time with committing
+# an internal transaction. The rest of the test also proves
+# MDEV-31503 "branch" of the OOO error is fixed.
+SET STATEMENT sql_log_bin=0 FOR FLUSH TABLES;
+--source include/start_slave.inc
+
+--let $wait_condition= SELECT count(*) = 1 FROM information_schema.processlist WHERE state LIKE "Waiting for prior transaction to commit"
+--source include/wait_condition.inc
+
+SELECT @@global.gtid_binlog_state, @@global.gtid_slave_pos as "no 100,101 yet in both";
+
+# DEBUG_DBUG extension point of hold_worker_on_schedule is reused
+# (gets deployed) in Sql_cmd_alter_sequence::execute.
+SET DEBUG_SYNC = 'now SIGNAL continue_worker';
+
+--echo # Normal sync with master proves the fixes correct
+--source include/sync_with_master_gtid.inc
+
+SELECT @@global.gtid_binlog_state, @@global.gtid_slave_pos as "all through 101 have been committed";
+
+# MDEV-31792 Assertion in MDL_context::acquire_lock upon parallel replication of CREATE SEQUENCE
+
+--let $iter = 3
+while ($iter)
+{
+--connection slave
+if (`select $iter > 1`)
+{
+ flush tables with read lock;
+}
+if (`select $iter = 1`)
+{
+ BEGIN /* slave local Trx */;
+ select count(*) from s3;
+}
+
+--connection master
+CREATE OR REPLACE SEQUENCE s3 ENGINE=innodb;
+# select may return non-deterministically, don't print its result
+SELECT NEXT VALUE FOR s3 into @tmpvar;
+--source include/save_master_gtid.inc
+
+--connection slave
+--let $wait_condition= SELECT count(*) = 1 FROM information_schema.processlist WHERE state LIKE "Waiting for prior transaction to start commit%"
+--source include/wait_condition.inc
+
+if (`select $iter > 1`)
+{
+ unlock tables;
+}
+if (`select $iter = 1`)
+{
+--connection slave
+rollback /* Trx */;
+}
+
+
+--source include/sync_with_master_gtid.inc
+
+--dec $iter
+}
+
+
+#
+# MDEV-29621/MDEV-31077/MDEV-31792 clean up.
+#
+--connection slave
+--source include/stop_slave.inc
+
+SET debug_sync = RESET;
+--eval SET @@global.slave_parallel_threads= $slave_parallel_threads
+--eval SET @@global.slave_parallel_mode= $slave_parallel_mode
+ SET @@global.debug_dbug = "";
+--eval SET @@global.gtid_strict_mode=$slave_gtid_strict_mode
+--source include/start_slave.inc
+
+--connection master
+# MDEV-32593 Assertion failure upon CREATE SEQUENCE
+BEGIN;
+INSERT INTO ti SET a=32593;
+CREATE SEQUENCE s4;
+
+DROP SEQUENCE s2,s3,s4;
+DROP TABLE ti;
+
+--sync_slave_with_master
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_parallel_show_binlog_events_purge_logs.test b/mysql-test/suite/rpl/t/rpl_parallel_show_binlog_events_purge_logs.test
new file mode 100644
index 00000000..cddc9286
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_parallel_show_binlog_events_purge_logs.test
@@ -0,0 +1,38 @@
+#
+# This include file is used by more than one test suite
+# (currently rpl and binlog_encryption).
+# Please check all dependent tests after modifying it
+#
+
+# BUG#13979418: SHOW BINLOG EVENTS MAY CRASH THE SERVER
+#
+# The function mysql_show_binlog_events has a local stack variable
+# 'LOG_INFO linfo;', which is assigned to thd->current_linfo, however
+# this variable goes out of scope and is destroyed before clean
+# thd->current_linfo.
+#
+# This test case runs SHOW BINLOG EVENTS and FLUSH LOGS to make sure
+# that with the fix local variable linfo is valid along all
+# mysql_show_binlog_events function scope.
+#
+--source include/have_debug.inc
+--source include/have_debug_sync.inc
+--source include/master-slave.inc
+
+--connection slave
+SET DEBUG_SYNC= 'after_show_binlog_events SIGNAL on_show_binlog_events WAIT_FOR end';
+--send SHOW BINLOG EVENTS
+
+--connection slave1
+SET DEBUG_SYNC= 'now WAIT_FOR on_show_binlog_events';
+FLUSH LOGS;
+SET DEBUG_SYNC= 'now SIGNAL end';
+
+--connection slave
+--disable_result_log
+--reap
+--enable_result_log
+SET DEBUG_SYNC= 'RESET';
+
+--connection master
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_parallel_single_grpcmt.test b/mysql-test/suite/rpl/t/rpl_parallel_single_grpcmt.test
new file mode 100644
index 00000000..cf4c547b
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_parallel_single_grpcmt.test
@@ -0,0 +1,170 @@
+--echo *** Test that group-committed transactions on the master can replicate in parallel on the slave. ***
+
+--source include/have_innodb.inc
+--source include/have_debug.inc
+--source include/have_debug_sync.inc
+--source include/have_binlog_format_statement.inc
+--source include/master-slave.inc
+
+# Test various aspects of parallel replication.
+
+--connection server_1
+# The function does nothing on the master, and on the slave it injects the
+# desired debug_sync action(s).
+SET sql_log_bin=0;
+--delimiter ||
+CREATE FUNCTION foo(x INT, d1 VARCHAR(500), d2 VARCHAR(500))
+ RETURNS INT DETERMINISTIC
+ BEGIN
+ RETURN x;
+ END
+||
+--delimiter ;
+SET sql_log_bin=1;
+
+--connection server_2
+--source include/stop_slave.inc
+SET sql_log_bin=0;
+--delimiter ||
+CREATE FUNCTION foo(x INT, d1 VARCHAR(500), d2 VARCHAR(500))
+ RETURNS INT DETERMINISTIC
+ BEGIN
+ IF d1 != '' THEN
+ SET debug_sync = d1;
+ END IF;
+ IF d2 != '' THEN
+ SET debug_sync = d2;
+ END IF;
+ RETURN x;
+ END
+||
+--delimiter ;
+SET sql_log_bin=1;
+
+# We need to restart all parallel threads for the new global setting to
+# be copied to the session-level values.
+SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads;
+SET GLOBAL slave_parallel_threads=10;
+CHANGE MASTER TO master_use_gtid=slave_pos;
+--source include/start_slave.inc
+
+--connection server_1
+ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
+CREATE TABLE t3 (a INT PRIMARY KEY, b INT) ENGINE=InnoDB;
+# Create some sentinel rows so that the rows inserted in parallel fall into
+# separate gaps and do not cause gap lock conflicts.
+INSERT INTO t3 VALUES (1,1), (3,3), (5,5), (7,7);
+--save_master_pos
+--connection server_2
+--sync_with_master
+
+
+# We want to test that the transactions can execute out-of-order on
+# the slave, but still end up committing in-order, and in a single
+# group commit.
+#
+# The idea is to group-commit three transactions together on the master:
+# A, B, and C. On the slave, C will execute the insert first, then A,
+# and then B. But B manages to complete before A has time to commit, so
+# all three end up committing together.
+#
+# So we start by setting up some row locks that will block transactions
+# A and B from executing, allowing C to run first.
+
+--connect (con_temp1,127.0.0.1,root,,test,$SERVER_MYPORT_2,)
+BEGIN;
+INSERT INTO t3 VALUES (2,102);
+--connect (con_temp2,127.0.0.1,root,,test,$SERVER_MYPORT_2,)
+BEGIN;
+INSERT INTO t3 VALUES (4,104);
+
+# On the master, queue three INSERT transactions as a single group commit.
+--connect (con_temp3,127.0.0.1,root,,test,$SERVER_MYPORT_1,)
+SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued1 WAIT_FOR master_cont1';
+SET binlog_format=statement;
+send INSERT INTO t3 VALUES (2, foo(12,
+ 'commit_after_release_LOCK_prepare_ordered SIGNAL slave_queued1 WAIT_FOR slave_cont1',
+ ''));
+
+--connection server_1
+SET debug_sync='now WAIT_FOR master_queued1';
+
+--connect (con_temp4,127.0.0.1,root,,test,$SERVER_MYPORT_1,)
+SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued2';
+SET binlog_format=statement;
+send INSERT INTO t3 VALUES (4, foo(14,
+ 'commit_after_release_LOCK_prepare_ordered SIGNAL slave_queued2',
+ ''));
+
+--connection server_1
+SET debug_sync='now WAIT_FOR master_queued2';
+
+--connect (con_temp5,127.0.0.1,root,,test,$SERVER_MYPORT_1,)
+SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued3';
+SET binlog_format=statement;
+send INSERT INTO t3 VALUES (6, foo(16,
+ 'group_commit_waiting_for_prior SIGNAL slave_queued3',
+ ''));
+
+--connection server_1
+SET debug_sync='now WAIT_FOR master_queued3';
+SET debug_sync='now SIGNAL master_cont1';
+
+--connection con_temp3
+REAP;
+--connection con_temp4
+REAP;
+--connection con_temp5
+REAP;
+SET debug_sync='RESET';
+
+--connection server_1
+SELECT * FROM t3 ORDER BY a;
+--let $binlog_file= master-bin.000001
+--source include/show_binlog_events.inc
+
+# First, wait until insert 3 is ready to queue up for group commit, but is
+# waiting for insert 2 to commit before it can do so itself.
+--connection server_2
+SET debug_sync='now WAIT_FOR slave_queued3';
+
+# Next, let insert 1 proceed, and allow it to queue up as the group commit
+# leader, but let it wait for insert 2 to also queue up before proceeding.
+--connection con_temp1
+ROLLBACK;
+--connection server_2
+SET debug_sync='now WAIT_FOR slave_queued1';
+
+# Now let insert 2 proceed and queue up.
+--connection con_temp2
+ROLLBACK;
+--connection server_2
+SET debug_sync='now WAIT_FOR slave_queued2';
+# And finally, we can let insert 1 proceed and do the group commit with all
+# three insert transactions together.
+SET debug_sync='now SIGNAL slave_cont1';
+
+# Wait for the commit to complete and check that all three transactions
+# group-committed together (will be seen in the binlog as all three having
+# cid=# on their GTID event).
+--let $wait_condition= SELECT COUNT(*) = 3 FROM t3 WHERE a IN (2,4,6)
+--source include/wait_condition.inc
+SELECT * FROM t3 ORDER BY a;
+--let $binlog_file= slave-bin.000001
+--source include/show_binlog_events.inc
+
+
+# Clean up.
+--connection server_2
+--source include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=@old_parallel_threads;
+--source include/start_slave.inc
+SET DEBUG_SYNC= 'RESET';
+
+--connection server_1
+DROP function foo;
+DROP TABLE t3;
+SET DEBUG_SYNC= 'RESET';
+
+--disable_connect_log
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_parallel_slave_bgc_kill.test b/mysql-test/suite/rpl/t/rpl_parallel_slave_bgc_kill.test
new file mode 100644
index 00000000..efb998b0
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_parallel_slave_bgc_kill.test
@@ -0,0 +1,458 @@
+--echo *** Test killing slave threads at various wait points ***
+
+--source include/have_innodb.inc
+--source include/have_debug.inc
+--source include/have_debug_sync.inc
+--source include/have_binlog_format_statement.inc
+--source include/master-slave.inc
+
+# Test various aspects of parallel replication.
+
+--connection server_2
+SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads;
+SET @old_parallel_mode=@@GLOBAL.slave_parallel_mode;
+--source include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=10;
+SET GLOBAL slave_parallel_mode='conservative';
+CHANGE MASTER TO master_use_gtid=slave_pos;
+--source include/start_slave.inc
+
+--connection server_1
+--connect (con_temp3,127.0.0.1,root,,test,$SERVER_MYPORT_1,)
+--connect (con_temp4,127.0.0.1,root,,test,$SERVER_MYPORT_1,)
+--connect (con_temp5,127.0.0.1,root,,test,$SERVER_MYPORT_1,)
+ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
+CREATE TABLE t1 (a int PRIMARY KEY) ENGINE=MyISAM;
+CREATE TABLE t2 (a int PRIMARY KEY) ENGINE=InnoDB;
+CREATE TABLE t3 (a INT PRIMARY KEY, b 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 t2 VALUES(100);
+INSERT INTO t3 VALUES(100, 100);
+--save_master_pos
+
+--connection server_2
+--sync_with_master
+
+--connection server_1
+# Use a stored function to inject a debug_sync into the appropriate THD.
+# The function does nothing on the master, and on the slave it injects the
+# desired debug_sync action(s).
+SET sql_log_bin=0;
+--delimiter ||
+CREATE FUNCTION foo(x INT, d1 VARCHAR(500), d2 VARCHAR(500))
+ RETURNS INT DETERMINISTIC
+ BEGIN
+ RETURN x;
+ END
+||
+--delimiter ;
+SET sql_log_bin=1;
+
+--connection server_2
+SET sql_log_bin=0;
+--delimiter ||
+CREATE FUNCTION foo(x INT, d1 VARCHAR(500), d2 VARCHAR(500))
+ RETURNS INT DETERMINISTIC
+ BEGIN
+ IF d1 != '' THEN
+ SET debug_sync = d1;
+ END IF;
+ IF d2 != '' THEN
+ SET debug_sync = d2;
+ END IF;
+ RETURN x;
+ END
+||
+--delimiter ;
+SET sql_log_bin=1;
+
+--echo *** 1. Test killing transaction waiting in commit for previous transaction to commit ***
+
+# Set up three transactions on the master that will be group-committed
+# together so they can be replicated in parallel on the slave.
+--connection con_temp3
+SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued1 WAIT_FOR master_cont1';
+send INSERT INTO t3 VALUES (31, foo(31,
+ 'commit_before_prepare_ordered WAIT_FOR t2_waiting',
+ 'commit_after_prepare_ordered SIGNAL t1_ready WAIT_FOR t1_cont'));
+
+--connection server_1
+SET debug_sync='now WAIT_FOR master_queued1';
+
+--connection con_temp4
+SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued2';
+BEGIN;
+# This insert is just so we can get T2 to wait while a query is running that we
+# can see in SHOW PROCESSLIST so we can get its thread_id to kill later.
+INSERT INTO t3 VALUES (32, foo(32,
+ 'ha_write_row_end SIGNAL t2_query WAIT_FOR t2_cont',
+ ''));
+# This insert sets up debug_sync points so that T2 will tell when it is at its
+# wait point where we want to kill it - and when it has been killed.
+INSERT INTO t3 VALUES (33, foo(33,
+ 'group_commit_waiting_for_prior SIGNAL t2_waiting',
+ 'group_commit_waiting_for_prior_killed SIGNAL t2_killed'));
+send COMMIT;
+
+--connection server_1
+SET debug_sync='now WAIT_FOR master_queued2';
+
+--connection con_temp5
+SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued3';
+send INSERT INTO t3 VALUES (34, foo(34,
+ '',
+ ''));
+
+--connection server_1
+SET debug_sync='now WAIT_FOR master_queued3';
+SET debug_sync='now SIGNAL master_cont1';
+
+--connection con_temp3
+REAP;
+--connection con_temp4
+REAP;
+--connection con_temp5
+REAP;
+
+--connection server_1
+SELECT * FROM t3 WHERE a >= 30 ORDER BY a;
+SET debug_sync='RESET';
+
+--connection server_2
+SET sql_log_bin=0;
+CALL mtr.add_suppression("Query execution was interrupted");
+CALL mtr.add_suppression("Commit failed due to failure of an earlier commit on which this one depends");
+CALL mtr.add_suppression("Slave: Connection was killed");
+SET sql_log_bin=1;
+# Wait until T2 is inside executing its insert of 32, then find it in SHOW
+# PROCESSLIST to know its thread id for KILL later.
+SET debug_sync='now WAIT_FOR t2_query';
+--let $thd_id= `SELECT ID FROM INFORMATION_SCHEMA.PROCESSLIST WHERE INFO LIKE '%foo(32%' AND INFO NOT LIKE '%LIKE%'`
+SET debug_sync='now SIGNAL t2_cont';
+
+# Wait until T2 has entered its wait for T1 to commit, and T1 has
+# progressed into its commit phase.
+SET debug_sync='now WAIT_FOR t1_ready';
+
+# Now kill the transaction T2.
+--replace_result $thd_id THD_ID
+eval KILL $thd_id;
+
+# Wait until T2 has reacted on the kill.
+SET debug_sync='now WAIT_FOR t2_killed';
+
+# Now we can allow T1 to proceed.
+SET debug_sync='now SIGNAL t1_cont';
+
+--let $slave_sql_errno= 1317,1927,1964
+--source include/wait_for_slave_sql_error.inc
+STOP SLAVE IO_THREAD;
+SELECT * FROM t3 WHERE a >= 30 ORDER BY a;
+
+# Now we have to disable the debug_sync statements, so they do not trigger
+# when the events are retried.
+SET debug_sync='RESET';
+SET GLOBAL slave_parallel_threads=0;
+SET GLOBAL slave_parallel_threads=10;
+SET sql_log_bin=0;
+DROP FUNCTION foo;
+--delimiter ||
+CREATE FUNCTION foo(x INT, d1 VARCHAR(500), d2 VARCHAR(500))
+ RETURNS INT DETERMINISTIC
+ BEGIN
+ RETURN x;
+ END
+||
+--delimiter ;
+SET sql_log_bin=1;
+
+--connection server_1
+INSERT INTO t3 VALUES (39,0);
+--save_master_pos
+
+--connection server_2
+--source include/start_slave.inc
+--sync_with_master
+SELECT * FROM t3 WHERE a >= 30 ORDER BY a;
+# Restore the foo() function.
+SET sql_log_bin=0;
+DROP FUNCTION foo;
+--delimiter ||
+CREATE FUNCTION foo(x INT, d1 VARCHAR(500), d2 VARCHAR(500))
+ RETURNS INT DETERMINISTIC
+ BEGIN
+ IF d1 != '' THEN
+ SET debug_sync = d1;
+ END IF;
+ IF d2 != '' THEN
+ SET debug_sync = d2;
+ END IF;
+ RETURN x;
+ END
+||
+--delimiter ;
+SET sql_log_bin=1;
+
+
+--connection server_2
+# Respawn all worker threads to clear any left-over debug_sync or other stuff.
+--source include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=0;
+SET GLOBAL slave_parallel_threads=10;
+--source include/start_slave.inc
+
+
+--echo *** 2. Same as (1), but without restarting IO thread after kill of SQL threads ***
+
+# Set up three transactions on the master that will be group-committed
+# together so they can be replicated in parallel on the slave.
+--connection con_temp3
+SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued1 WAIT_FOR master_cont1';
+send INSERT INTO t3 VALUES (41, foo(41,
+ 'commit_before_prepare_ordered WAIT_FOR t2_waiting',
+ 'commit_after_prepare_ordered SIGNAL t1_ready WAIT_FOR t1_cont'));
+
+--connection server_1
+SET debug_sync='now WAIT_FOR master_queued1';
+
+--connection con_temp4
+SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued2';
+BEGIN;
+# This insert is just so we can get T2 to wait while a query is running that we
+# can see in SHOW PROCESSLIST so we can get its thread_id to kill later.
+INSERT INTO t3 VALUES (42, foo(42,
+ 'ha_write_row_end SIGNAL t2_query WAIT_FOR t2_cont',
+ ''));
+# This insert sets up debug_sync points so that T2 will tell when it is at its
+# wait point where we want to kill it - and when it has been killed.
+INSERT INTO t3 VALUES (43, foo(43,
+ 'group_commit_waiting_for_prior SIGNAL t2_waiting',
+ 'group_commit_waiting_for_prior_killed SIGNAL t2_killed'));
+send COMMIT;
+
+--connection server_1
+SET debug_sync='now WAIT_FOR master_queued2';
+
+--connection con_temp5
+SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued3';
+send INSERT INTO t3 VALUES (44, foo(44,
+ '',
+ ''));
+
+--connection server_1
+SET debug_sync='now WAIT_FOR master_queued3';
+SET debug_sync='now SIGNAL master_cont1';
+
+--connection con_temp3
+REAP;
+--connection con_temp4
+REAP;
+--connection con_temp5
+REAP;
+
+--connection server_1
+SELECT * FROM t3 WHERE a >= 40 ORDER BY a;
+SET debug_sync='RESET';
+
+--connection server_2
+# Wait until T2 is inside executing its insert of 42, then find it in SHOW
+# PROCESSLIST to know its thread id for KILL later.
+SET debug_sync='now WAIT_FOR t2_query';
+--let $thd_id= `SELECT ID FROM INFORMATION_SCHEMA.PROCESSLIST WHERE INFO LIKE '%foo(42%' AND INFO NOT LIKE '%LIKE%'`
+SET debug_sync='now SIGNAL t2_cont';
+
+# Wait until T2 has entered its wait for T1 to commit, and T1 has
+# progressed into its commit phase.
+SET debug_sync='now WAIT_FOR t1_ready';
+
+# Now kill the transaction T2.
+--replace_result $thd_id THD_ID
+eval KILL $thd_id;
+
+# Wait until T2 has reacted on the kill.
+SET debug_sync='now WAIT_FOR t2_killed';
+
+# Now we can allow T1 to proceed.
+SET debug_sync='now SIGNAL t1_cont';
+
+--let $slave_sql_errno= 1317,1927,1964
+--source include/wait_for_slave_sql_error.inc
+
+# Now we have to disable the debug_sync statements, so they do not trigger
+# when the events are retried.
+SET debug_sync='RESET';
+SET GLOBAL slave_parallel_threads=0;
+SET GLOBAL slave_parallel_threads=10;
+SET sql_log_bin=0;
+DROP FUNCTION foo;
+--delimiter ||
+CREATE FUNCTION foo(x INT, d1 VARCHAR(500), d2 VARCHAR(500))
+ RETURNS INT DETERMINISTIC
+ BEGIN
+ RETURN x;
+ END
+||
+--delimiter ;
+SET sql_log_bin=1;
+
+--connection server_1
+INSERT INTO t3 VALUES (49,0);
+--save_master_pos
+
+--connection server_2
+START SLAVE SQL_THREAD;
+--sync_with_master
+SELECT * FROM t3 WHERE a >= 40 ORDER BY a;
+# Restore the foo() function.
+SET sql_log_bin=0;
+DROP FUNCTION foo;
+--delimiter ||
+CREATE FUNCTION foo(x INT, d1 VARCHAR(500), d2 VARCHAR(500))
+ RETURNS INT DETERMINISTIC
+ BEGIN
+ IF d1 != '' THEN
+ SET debug_sync = d1;
+ END IF;
+ IF d2 != '' THEN
+ SET debug_sync = d2;
+ END IF;
+ RETURN x;
+ END
+||
+--delimiter ;
+SET sql_log_bin=1;
+
+
+--connection server_2
+# Respawn all worker threads to clear any left-over debug_sync or other stuff.
+--source include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=0;
+SET GLOBAL slave_parallel_threads=10;
+--source include/start_slave.inc
+
+
+--echo *** 3. Same as (2), but not using gtid mode ***
+
+--connection server_2
+--source include/stop_slave.inc
+CHANGE MASTER TO master_use_gtid=no;
+--source include/start_slave.inc
+
+--connection server_1
+# Set up three transactions on the master that will be group-committed
+# together so they can be replicated in parallel on the slave.
+--connection con_temp3
+SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued1 WAIT_FOR master_cont1';
+send INSERT INTO t3 VALUES (51, foo(51,
+ 'commit_before_prepare_ordered WAIT_FOR t2_waiting',
+ 'commit_after_prepare_ordered SIGNAL t1_ready WAIT_FOR t1_cont'));
+
+--connection server_1
+SET debug_sync='now WAIT_FOR master_queued1';
+
+--connection con_temp4
+SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued2';
+BEGIN;
+# This insert is just so we can get T2 to wait while a query is running that we
+# can see in SHOW PROCESSLIST so we can get its thread_id to kill later.
+INSERT INTO t3 VALUES (52, foo(52,
+ 'ha_write_row_end SIGNAL t2_query WAIT_FOR t2_cont',
+ ''));
+# This insert sets up debug_sync points so that T2 will tell when it is at its
+# wait point where we want to kill it - and when it has been killed.
+INSERT INTO t3 VALUES (53, foo(53,
+ 'group_commit_waiting_for_prior SIGNAL t2_waiting',
+ 'group_commit_waiting_for_prior_killed SIGNAL t2_killed'));
+send COMMIT;
+
+--connection server_1
+SET debug_sync='now WAIT_FOR master_queued2';
+
+--connection con_temp5
+SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued3';
+send INSERT INTO t3 VALUES (54, foo(54,
+ '',
+ ''));
+
+--connection server_1
+SET debug_sync='now WAIT_FOR master_queued3';
+SET debug_sync='now SIGNAL master_cont1';
+
+--connection con_temp3
+REAP;
+--connection con_temp4
+REAP;
+--connection con_temp5
+REAP;
+
+--connection server_1
+SELECT * FROM t3 WHERE a >= 50 ORDER BY a;
+SET debug_sync='RESET';
+
+--connection server_2
+# Wait until T2 is inside executing its insert of 52, then find it in SHOW
+# PROCESSLIST to know its thread id for KILL later.
+SET debug_sync='now WAIT_FOR t2_query';
+--let $thd_id= `SELECT ID FROM INFORMATION_SCHEMA.PROCESSLIST WHERE INFO LIKE '%foo(52%' AND INFO NOT LIKE '%LIKE%'`
+SET debug_sync='now SIGNAL t2_cont';
+
+# Wait until T2 has entered its wait for T1 to commit, and T1 has
+# progressed into its commit phase.
+SET debug_sync='now WAIT_FOR t1_ready';
+
+# Now kill the transaction T2.
+--replace_result $thd_id THD_ID
+eval KILL $thd_id;
+
+# Wait until T2 has reacted on the kill.
+SET debug_sync='now WAIT_FOR t2_killed';
+
+# Now we can allow T1 to proceed.
+SET debug_sync='now SIGNAL t1_cont';
+
+--let $slave_sql_errno= 1317,1927,1964
+--source include/wait_for_slave_sql_error.inc
+SELECT * FROM t3 WHERE a >= 50 ORDER BY a;
+
+# Now we have to disable the debug_sync statements, so they do not trigger
+# when the events are retried.
+SET debug_sync='RESET';
+SET GLOBAL slave_parallel_threads=0;
+SET GLOBAL slave_parallel_threads=10;
+SET sql_log_bin=0;
+DROP FUNCTION foo;
+--delimiter ||
+CREATE FUNCTION foo(x INT, d1 VARCHAR(500), d2 VARCHAR(500))
+ RETURNS INT DETERMINISTIC
+ BEGIN
+ RETURN x;
+ END
+||
+--delimiter ;
+SET sql_log_bin=1;
+
+--connection server_1
+INSERT INTO t3 VALUES (59,0);
+--save_master_pos
+
+--connection server_2
+START SLAVE SQL_THREAD;
+--sync_with_master
+SELECT * FROM t3 WHERE a >= 50 ORDER BY a;
+
+# Clean up.
+--connection server_2
+--source include/stop_slave.inc
+CHANGE MASTER TO master_use_gtid=slave_pos;
+SET GLOBAL slave_parallel_threads=@old_parallel_threads;
+SET GLOBAL slave_parallel_mode=@old_parallel_mode;
+--source include/start_slave.inc
+SET DEBUG_SYNC= 'RESET';
+
+--connection server_1
+DROP function foo;
+DROP TABLE t1,t2,t3;
+SET DEBUG_SYNC= 'RESET';
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_parallel_stop_on_con_kill.test b/mysql-test/suite/rpl/t/rpl_parallel_stop_on_con_kill.test
new file mode 100644
index 00000000..63c483ea
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_parallel_stop_on_con_kill.test
@@ -0,0 +1,129 @@
+--echo *** MDEV-8031: Parallel replication stops on "connection killed" error (probably incorrectly handled deadlock kill) ***
+
+--source include/have_innodb.inc
+--source include/have_debug.inc
+--source include/have_debug_sync.inc
+--source include/master-slave.inc
+
+--connection server_2
+SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads;
+--source include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=10;
+CHANGE MASTER TO master_use_gtid=slave_pos;
+--source include/start_slave.inc
+
+--connection server_1
+ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
+CREATE TABLE t3 (a INT PRIMARY KEY, b INT) ENGINE=InnoDB;
+INSERT INTO t3 VALUES (201,0), (202,0);
+--source include/save_master_gtid.inc
+
+--connection server_2
+--source include/sync_with_master_gtid.inc
+--source include/stop_slave.inc
+SET @old_dbug= @@GLOBAL.debug_dbug;
+SET GLOBAL debug_dbug= '+d,inject_mdev8031';
+
+--connection server_1
+# We artificially create a situation that hopefully resembles the original
+# bug which was only seen "in the wild", and only once.
+# Setup a fake group commit with lots of conflicts that will lead to deadloc
+# kill. The slave DBUG injection causes the slave to be deadlock killed at
+# a particular point during the retry, and then later do a small sleep at
+# another critical point where the prior transaction then has a chance to
+# complete. Finally an extra KILL check catches an unhandled, lingering
+# deadlock kill. So rather artificial, but at least it exercises the
+# relevant code paths.
+SET @old_dbug= @@SESSION.debug_dbug;
+SET SESSION debug_dbug="+d,binlog_force_commit_id";
+
+SET @commit_id= 10200;
+INSERT INTO t3 VALUES (203, 1);
+INSERT INTO t3 VALUES (204, 1);
+INSERT INTO t3 VALUES (205, 1);
+UPDATE t3 SET b=b+1 WHERE a=201;
+UPDATE t3 SET b=b+1 WHERE a=201;
+UPDATE t3 SET b=b+1 WHERE a=201;
+UPDATE t3 SET b=b+1 WHERE a=202;
+UPDATE t3 SET b=b+1 WHERE a=202;
+UPDATE t3 SET b=b+1 WHERE a=202;
+UPDATE t3 SET b=b+1 WHERE a=202;
+UPDATE t3 SET b=b+1 WHERE a=203;
+UPDATE t3 SET b=b+1 WHERE a=203;
+UPDATE t3 SET b=b+1 WHERE a=204;
+UPDATE t3 SET b=b+1 WHERE a=204;
+UPDATE t3 SET b=b+1 WHERE a=204;
+UPDATE t3 SET b=b+1 WHERE a=203;
+UPDATE t3 SET b=b+1 WHERE a=205;
+UPDATE t3 SET b=b+1 WHERE a=205;
+SET SESSION debug_dbug=@old_dbug;
+
+SELECT * FROM t3 WHERE a>=200 ORDER BY a;
+--source include/save_master_gtid.inc
+
+--connection server_2
+--source include/start_slave.inc
+--source include/sync_with_master_gtid.inc
+
+SELECT * FROM t3 WHERE a>=200 ORDER BY a;
+--source include/stop_slave.inc
+SET GLOBAL debug_dbug= @old_dbug;
+--source include/start_slave.inc
+
+
+--echo *** Check getting deadlock killed inside open_binlog() during retry. ***
+
+--connection server_2
+--source include/stop_slave.inc
+SET @old_dbug= @@GLOBAL.debug_dbug;
+SET GLOBAL debug_dbug= '+d,inject_retry_event_group_open_binlog_kill';
+SET @old_max= @@GLOBAL.max_relay_log_size;
+SET GLOBAL max_relay_log_size= 4096;
+
+--connection server_1
+SET @old_dbug= @@SESSION.debug_dbug;
+SET SESSION debug_dbug="+d,binlog_force_commit_id";
+
+--let $large= `SELECT REPEAT("*", 8192)`
+SET @commit_id= 10210;
+--echo Omit long queries that cause relaylog rotations and transaction retries...
+--disable_query_log
+eval UPDATE t3 SET b=b+1 WHERE a=201 /* $large */;
+eval UPDATE t3 SET b=b+1 WHERE a=201 /* $large */;
+eval UPDATE t3 SET b=b+1 WHERE a=201 /* $large */;
+eval UPDATE t3 SET b=b+1 WHERE a=202 /* $large */;
+eval UPDATE t3 SET b=b+1 WHERE a=202 /* $large */;
+eval UPDATE t3 SET b=b+1 WHERE a=202 /* $large */;
+eval UPDATE t3 SET b=b+1 WHERE a=202 /* $large */;
+eval UPDATE t3 SET b=b+1 WHERE a=203 /* $large */;
+eval UPDATE t3 SET b=b+1 WHERE a=203 /* $large */;
+eval UPDATE t3 SET b=b+1 WHERE a=204 /* $large */;
+eval UPDATE t3 SET b=b+1 WHERE a=204 /* $large */;
+eval UPDATE t3 SET b=b+1 WHERE a=204 /* $large */;
+eval UPDATE t3 SET b=b+1 WHERE a=203 /* $large */;
+eval UPDATE t3 SET b=b+1 WHERE a=205 /* $large */;
+eval UPDATE t3 SET b=b+1 WHERE a=205 /* $large */;
+--enable_query_log
+SET SESSION debug_dbug=@old_dbug;
+
+SELECT * FROM t3 WHERE a>=200 ORDER BY a;
+--source include/save_master_gtid.inc
+
+--connection server_2
+--source include/start_slave.inc
+--source include/sync_with_master_gtid.inc
+
+SELECT * FROM t3 WHERE a>=200 ORDER BY a;
+
+# Cleanup
+--source include/stop_slave.inc
+SET GLOBAL debug_dbug= @old_debg;
+SET GLOBAL max_relay_log_size= @old_max;
+SET GLOBAL slave_parallel_threads=@old_parallel_threads;
+--source include/start_slave.inc
+
+--connection server_1
+DROP TABLE t3;
+
+--source include/rpl_end.inc
+
diff --git a/mysql-test/suite/rpl/t/rpl_parallel_stop_slave.test b/mysql-test/suite/rpl/t/rpl_parallel_stop_slave.test
new file mode 100644
index 00000000..35879e98
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_parallel_stop_slave.test
@@ -0,0 +1,118 @@
+--echo *** Test STOP SLAVE in parallel mode ***
+
+--source include/have_innodb.inc
+--source include/have_debug.inc
+--source include/have_debug_sync.inc
+--source include/have_binlog_format_statement.inc
+--source include/master-slave.inc
+
+--connection server_2
+SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads;
+SET @old_parallel_mode=@@GLOBAL.slave_parallel_mode;
+--source include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=10;
+SET GLOBAL slave_parallel_mode='conservative';
+
+CHANGE MASTER TO master_use_gtid=slave_pos;
+--source include/start_slave.inc
+--connect (con_temp1,127.0.0.1,root,,test,$SERVER_MYPORT_2,)
+--connect (con_temp2,127.0.0.1,root,,test,$SERVER_MYPORT_2,)
+
+--connection server_1
+ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
+CREATE TABLE t1 (a int PRIMARY KEY) ENGINE=MyISAM;
+CREATE TABLE t2 (a int PRIMARY KEY) ENGINE=InnoDB;
+CREATE TABLE t3 (a INT PRIMARY KEY, b 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 t2 VALUES(100);
+INSERT INTO t3 VALUES(100, 100);
+--save_master_pos
+
+--connection server_2
+--sync_with_master
+--source include/stop_slave.inc
+
+--connection server_1
+# Set up a couple of transactions. The first will be blocked halfway
+# through on a lock, and while it is blocked we initiate STOP SLAVE.
+# We then test that the halfway-initiated transaction is allowed to
+# complete, but no subsequent ones.
+# We have to use statement-based mode and set
+# binlog_direct_non_transactional_updates=0; otherwise the binlog will
+# be split into two event groups, one for the MyISAM part and one for the
+# InnoDB part.
+SET binlog_direct_non_transactional_updates=0;
+SET sql_log_bin=0;
+CALL mtr.add_suppression("Statement is unsafe because it accesses a non-transactional table after accessing a transactional table within the same transaction");
+SET sql_log_bin=1;
+BEGIN;
+INSERT INTO t2 VALUES (20);
+--disable_warnings
+INSERT INTO t1 VALUES (20);
+--enable_warnings
+INSERT INTO t2 VALUES (21);
+INSERT INTO t3 VALUES (20, 20);
+COMMIT;
+INSERT INTO t3 VALUES(21, 21);
+INSERT INTO t3 VALUES(22, 22);
+--save_master_pos
+
+# Start a connection that will block the replicated transaction halfway.
+--connection con_temp1
+BEGIN;
+INSERT INTO t2 VALUES (21);
+
+--connection server_2
+START SLAVE;
+# Wait for the MyISAM change to be visible, after which replication will wait
+# for con_temp1 to roll back.
+--let $wait_condition= SELECT COUNT(*) = 1 FROM t1 WHERE a=20
+--source include/wait_condition.inc
+
+--connection con_temp2
+# Initiate slave stop. It will have to wait for the current event group
+# to complete.
+# The dbug injection causes debug_sync to signal 'wait_for_done_waiting'
+# when the SQL driver thread is ready.
+SET @old_dbug= @@GLOBAL.debug_dbug;
+SET GLOBAL debug_dbug="+d,rpl_parallel_wait_for_done_trigger";
+send STOP SLAVE;
+
+--connection con_temp1
+SET debug_sync='now WAIT_FOR wait_for_done_waiting';
+ROLLBACK;
+
+--connection con_temp2
+reap;
+SET GLOBAL debug_dbug=@old_dbug;
+SET debug_sync='RESET';
+
+--connection server_2
+--source include/wait_for_slave_to_stop.inc
+# We should see the first transaction applied, but not the two others.
+SELECT * FROM t1 WHERE a >= 20 ORDER BY a;
+SELECT * FROM t2 WHERE a >= 20 ORDER BY a;
+SELECT * FROM t3 WHERE a >= 20 ORDER BY a;
+
+--source include/start_slave.inc
+--sync_with_master
+SELECT * FROM t1 WHERE a >= 20 ORDER BY a;
+SELECT * FROM t2 WHERE a >= 20 ORDER BY a;
+SELECT * FROM t3 WHERE a >= 20 ORDER BY a;
+
+--connection server_2
+# Respawn all worker threads to clear any left-over debug_sync or other stuff.
+--source include/stop_slave.inc
+SET GLOBAL slave_parallel_mode=@old_parallel_mode;
+SET GLOBAL slave_parallel_threads=@old_parallel_threads;
+--source include/start_slave.inc
+SET DEBUG_SYNC= 'RESET';
+--disconnect con_temp1
+--disconnect con_temp2
+
+--connection server_1
+DROP TABLE t1,t2,t3;
+SET DEBUG_SYNC= 'RESET';
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_parallel_temptable-master.opt b/mysql-test/suite/rpl/t/rpl_parallel_temptable-master.opt
new file mode 100644
index 00000000..590d44a6
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_parallel_temptable-master.opt
@@ -0,0 +1 @@
+--loose-skip-stack-trace --skip-core-file
diff --git a/mysql-test/suite/rpl/t/rpl_parallel_temptable.test b/mysql-test/suite/rpl/t/rpl_parallel_temptable.test
new file mode 100644
index 00000000..3684763d
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_parallel_temptable.test
@@ -0,0 +1,277 @@
+--source include/have_innodb.inc
+--source include/have_debug.inc
+--source include/have_binlog_format_statement.inc
+# Valgrind does not work well with test that crashes the server
+--source include/not_valgrind.inc
+--let $rpl_topology=1->2
+--source include/rpl_init.inc
+
+--echo *** MDEV-6321: close_temporary_tables() in format description event not serialised correctly ***
+
+--connection server_2
+SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads;
+--source include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=5;
+--source include/start_slave.inc
+
+--connection server_1
+CREATE TABLE t1 (a INT PRIMARY KEY, b VARCHAR(100) CHARACTER SET utf8);
+--save_master_pos
+
+--connection server_2
+--sync_with_master
+--source include/stop_slave.inc
+
+
+--connection server_1
+SET gtid_domain_id= 1;
+INSERT INTO t1 VALUES (1, 0);
+
+CREATE TEMPORARY TABLE t2 (a int);
+
+--connection default
+SET gtid_domain_id= 2;
+CREATE TEMPORARY TABLE t3 (a INT PRIMARY KEY);
+CREATE TEMPORARY TABLE t4 (a int);
+INSERT INTO t3 VALUES (100);
+INSERT INTO t4 SELECT a+1 FROM t3;
+
+--connection server_1
+INSERT INTO t2 VALUES (2), (4), (6), (8), (10), (12), (14), (16), (18), (20);
+INSERT INTO t2 VALUES (3), (6), (9), (12), (15), (18);
+INSERT INTO t2 VALUES (4), (8), (12), (16), (20);
+
+--connection default
+INSERT INTO t3 SELECT a+2 FROM t4;
+INSERT INTO t4 SELECT a+4 FROM t3;
+
+--connection server_1
+INSERT INTO t2 VALUES (5), (10), (15), (20);
+INSERT INTO t2 VALUES (6), (12), (18);
+INSERT INTO t2 VALUES (7), (14);
+INSERT INTO t2 VALUES (8), (16);
+INSERT INTO t2 VALUES (9), (18);
+INSERT INTO t2 VALUES (10), (20);
+
+--connection default
+INSERT INTO t3 SELECT a+8 FROM t4;
+INSERT INTO t4 SELECT a+16 FROM t3;
+
+--connection server_1
+INSERT INTO t2 VALUES (11);
+INSERT INTO t2 VALUES (12);
+INSERT INTO t2 VALUES (13);
+
+--connection default
+INSERT INTO t3 SELECT a+32 FROM t4;
+
+--connection server_1
+INSERT INTO t2 VALUES (14);
+INSERT INTO t2 VALUES (15);
+INSERT INTO t2 VALUES (16);
+
+--connection default
+INSERT INTO t4 SELECT a+64 FROM t3;
+
+--connection server_1
+INSERT INTO t2 VALUES (17);
+INSERT INTO t2 VALUES (18);
+INSERT INTO t2 VALUES (19);
+
+--connection default
+INSERT INTO t3 SELECT a+128 FROM t4;
+
+--connection server_1
+INSERT INTO t2 VALUES (20);
+
+--connection default
+INSERT INTO t1 SELECT a, a MOD 7 FROM t3;
+INSERT INTO t1 SELECT a, a MOD 7 FROM t4;
+
+--connection server_1
+INSERT INTO t1 SELECT a, COUNT(*) FROM t2 GROUP BY a;
+
+# Crash the master server, so that temporary tables are implicitly dropped.
+--write_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
+wait
+EOF
+
+FLUSH TABLES;
+SET SESSION debug_dbug="+d,crash_dispatch_command_before";
+--error 2006,2013
+SELECT 1;
+
+--source include/wait_until_disconnected.inc
+--connection default
+--source include/wait_until_disconnected.inc
+
+--append_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
+restart
+EOF
+
+--connection default
+--enable_reconnect
+--source include/wait_until_connected_again.inc
+
+--connection server_1
+--enable_reconnect
+--source include/wait_until_connected_again.inc
+
+INSERT INTO t1 VALUES (0, 1);
+--save_master_pos
+
+--connection server_2
+# Start the slave replicating the events.
+# The bug was that the format description event written after the crash could
+# be fetched ahead of the execution of the temporary table events and executed
+# out-of-band. This would cause drop of all temporary tables and thus failure
+# for execution of remaining events.
+
+--source include/start_slave.inc
+--sync_with_master
+
+SELECT * FROM t1 WHERE a <= 20 ORDER BY a;
+SELECT COUNT(*) FROM t1 WHERE a BETWEEN 100+0 AND 100+256;
+SHOW STATUS LIKE 'Slave_open_temp_tables';
+
+
+--echo *** Test that if master logged partial event group before crash, we finish that group correctly before executing format description event ***
+
+--source include/stop_slave.inc
+
+--connection server_1
+CALL mtr.add_suppression("Statement accesses nontransactional table as well as transactional or temporary table, and writes to any of them");
+SET gtid_domain_id= 1;
+DELETE FROM t1;
+ALTER TABLE t1 ENGINE=InnoDB;
+CREATE TEMPORARY TABLE t2 (a INT PRIMARY KEY);
+INSERT INTO t2 VALUES (1);
+INSERT INTO t2 VALUES (2);
+
+--connection default
+SET gtid_domain_id= 2;
+CREATE TEMPORARY TABLE t3 (a INT PRIMARY KEY);
+INSERT INTO t3 VALUES (10);
+INSERT INTO t3 VALUES (20);
+
+--connection server_1
+INSERT INTO t1 SELECT a, 'server_1' FROM t2;
+
+--connection default
+INSERT INTO t1 SELECT a, 'default' FROM t3;
+
+--connection server_1
+INSERT INTO t1 SELECT a+2, '+server_1' FROM t2;
+
+# Crash the master server in the middle of writing an event group.
+--write_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
+wait
+EOF
+
+FLUSH TABLES;
+SET SESSION debug_dbug="+d,crash_before_writing_xid";
+--error 2006,2013
+INSERT INTO t1 SELECT a+4, '++server_1' FROM t2;
+
+--source include/wait_until_disconnected.inc
+--connection default
+--source include/wait_until_disconnected.inc
+
+--append_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
+restart
+EOF
+
+--connection default
+--enable_reconnect
+--source include/wait_until_connected_again.inc
+
+--connection server_1
+--enable_reconnect
+--source include/wait_until_connected_again.inc
+
+INSERT INTO t1 VALUES (0, 1);
+#--save_master_pos
+--source include/save_master_gtid.inc
+
+--connection server_2
+# Start the slave replicating the events.
+# The main thing to test here is that the slave will know that it
+# needs to abort the partially received event group, so that the
+# execution of format_description event will not wait infinitely
+# for a commit of the incomplete group that never happens.
+
+# Apart from the suppression, MDEV-27697 refinement to the original test needs
+# an allowance to one time accept malformed event group.
+set @@sql_log_bin=0;
+call mtr.add_suppression("Unexpected break of being relay-logged GTID 1-1-32 event group by the current GTID event 0-1-4");
+set @@sql_log_bin=1;
+set @@global.debug_dbug="+d,slave_discard_xid_for_gtid_0_x_1000";
+--source include/start_slave.inc
+#--sync_with_master
+--source include/sync_with_master_gtid.inc
+set @@global.debug_dbug="";
+
+SELECT * FROM t1 ORDER BY a;
+SHOW STATUS LIKE 'Slave_open_temp_tables';
+
+--connection server_1
+# This FLUSH can be removed once MDEV-6608 is fixed.
+FLUSH LOGS;
+
+
+--echo *** MDEV-7936: Assertion `!table || table->in_use == _current_thd()' failed on parallel replication in optimistic mode ***
+
+--connection server_1
+CREATE TEMPORARY TABLE t4 (a INT PRIMARY KEY) ENGINE=InnoDB;
+SET @old_dbug= @@SESSION.debug_dbug;
+SET SESSION debug_dbug="+d,binlog_force_commit_id";
+SET @commit_id= 10000;
+INSERT INTO t4 VALUES (30);
+INSERT INTO t4 VALUES (31);
+SET SESSION debug_dbug= @old_dbug;
+INSERT INTO t1 SELECT a, "conservative" FROM t4;
+DROP TEMPORARY TABLE t4;
+SELECT * FROM t1 WHERE a >= 30 ORDER BY a;
+--source include/save_master_gtid.inc
+
+--connection server_2
+--source include/sync_with_master_gtid.inc
+
+SELECT * FROM t1 WHERE a >= 30 ORDER BY a;
+
+--source include/stop_slave.inc
+SET @old_mode= @@GLOBAL.slave_parallel_mode;
+SET GLOBAL slave_parallel_mode=optimistic;
+
+--connection server_1
+CREATE TEMPORARY TABLE t4 (a INT PRIMARY KEY) ENGINE=InnoDB;
+INSERT INTO t4 VALUES (32);
+INSERT INTO t4 VALUES (33);
+INSERT INTO t1 SELECT a, "optimistic" FROM t4;
+DROP TEMPORARY TABLE t4;
+
+SELECT * FROM t1 WHERE a >= 30 ORDER BY a;
+--source include/save_master_gtid.inc
+
+--connection server_2
+--source include/start_slave.inc
+--source include/sync_with_master_gtid.inc
+
+SELECT * FROM t1 WHERE a >= 30 ORDER BY a;
+
+--source include/stop_slave.inc
+SET GLOBAL slave_parallel_mode=@old_mode;
+--source include/start_slave.inc
+
+
+# Clean up.
+
+--connection server_2
+--source include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=@old_parallel_threads;
+--source include/start_slave.inc
+
+--connection server_1
+DROP TABLE t1;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_parallel_wrong_binlog_order.test b/mysql-test/suite/rpl/t/rpl_parallel_wrong_binlog_order.test
new file mode 100644
index 00000000..093693d4
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_parallel_wrong_binlog_order.test
@@ -0,0 +1,91 @@
+--echo *** MDEV-6775: Wrong binlog order in parallel replication ***
+
+# A bit tricky bug to reproduce. On the master, we binlog in statement-mode
+# two transactions, an UPDATE followed by a DELETE. On the slave, we replicate
+# with binlog-mode set to ROW, which means the DELETE, which modifies no rows,
+# is not binlogged. Then we inject a wait in the group commit code on the
+# slave, shortly before the actual commit of the UPDATE. The bug was that the
+# DELETE could wake up from wait_for_prior_commit() before the commit of the
+# UPDATE. So the test could see the slave position updated to after DELETE,
+# while the UPDATE was still not visible.
+
+--source include/have_innodb.inc
+--source include/have_debug.inc
+--source include/have_debug_sync.inc
+--source include/master-slave.inc
+
+--connection server_2
+SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads;
+--source include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=10;
+CHANGE MASTER TO master_use_gtid=slave_pos;
+--source include/start_slave.inc
+
+--connection server_1
+ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
+CREATE TABLE t4 (a INT PRIMARY KEY, b INT, KEY b_idx(b)) ENGINE=InnoDB;
+INSERT INTO t4 VALUES (1,NULL), (3,NULL), (4,4), (5, NULL), (6, 6);
+--connect (con1,127.0.0.1,root,,test,$SERVER_MYPORT_1,)
+--connect (con2,127.0.0.1,root,,test,$SERVER_MYPORT_1,)
+--source include/save_master_gtid.inc
+
+--connection server_2
+--source include/sync_with_master_gtid.inc
+--source include/stop_slave.inc
+SET @old_dbug= @@GLOBAL.debug_dbug;
+SET GLOBAL debug_dbug="+d,inject_binlog_commit_before_get_LOCK_log";
+SET @old_format=@@GLOBAL.binlog_format;
+SET GLOBAL binlog_format=ROW;
+# Re-spawn the worker threads to be sure they pick up the new binlog format
+SET GLOBAL slave_parallel_threads=0;
+SET GLOBAL slave_parallel_threads=10;
+
+--connection con1
+SET @old_format= @@binlog_format;
+SET binlog_format= statement;
+SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued1 WAIT_FOR master_cont1';
+send UPDATE t4 SET b=NULL WHERE a=6;
+--connection server_1
+SET debug_sync='now WAIT_FOR master_queued1';
+
+--connection con2
+SET @old_format= @@binlog_format;
+SET binlog_format= statement;
+SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued2';
+send DELETE FROM t4 WHERE b <= 3;
+
+--connection server_1
+SET debug_sync='now WAIT_FOR master_queued2';
+SET debug_sync='now SIGNAL master_cont1';
+
+--connection con1
+REAP;
+SET binlog_format= @old_format;
+--connection con2
+REAP;
+SET binlog_format= @old_format;
+SET debug_sync='RESET';
+--save_master_pos
+SELECT * FROM t4 ORDER BY a;
+
+--connection server_2
+--source include/start_slave.inc
+SET debug_sync= 'now WAIT_FOR waiting';
+--sync_with_master
+SELECT * FROM t4 ORDER BY a;
+SET debug_sync= 'now SIGNAL cont';
+
+# Re-spawn the worker threads to remove any DBUG injections or DEBUG_SYNC.
+--source include/stop_slave.inc
+SET GLOBAL debug_dbug=@old_dbug;
+SET GLOBAL binlog_format= @old_format;
+SET GLOBAL slave_parallel_threads=@old_parallel_threads;
+--source include/start_slave.inc
+SET DEBUG_SYNC= 'RESET';
+
+--connection server_1
+DROP TABLE t4;
+SET DEBUG_SYNC= 'RESET';
+--disconnect con1
+--disconnect con2
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_parallel_wrong_exec_master_pos.test b/mysql-test/suite/rpl/t/rpl_parallel_wrong_exec_master_pos.test
new file mode 100644
index 00000000..672ade57
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_parallel_wrong_exec_master_pos.test
@@ -0,0 +1,56 @@
+--echo *** MDEV-5938: Exec_master_log_pos not updated at log rotate in parallel replication ***
+--source include/have_innodb.inc
+--source include/master-slave.inc
+
+--connection server_2
+--source include/stop_slave.inc
+SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads;
+SET GLOBAL slave_parallel_threads=1;
+CHANGE MASTER TO master_use_gtid=slave_pos;
+--source include/start_slave.inc
+
+--connection server_1
+ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
+CREATE TABLE t5 (a INT PRIMARY KEY, b INT);
+INSERT INTO t5 VALUES (1,1);
+INSERT INTO t5 VALUES (2,2), (3,8);
+INSERT INTO t5 VALUES (4,16);
+--save_master_pos
+
+--connection server_2
+--sync_with_master
+let $io_file= query_get_value(SHOW SLAVE STATUS, Master_Log_File, 1);
+let $io_pos= query_get_value(SHOW SLAVE STATUS, Read_Master_Log_Pos, 1);
+let $sql_file= query_get_value(SHOW SLAVE STATUS, Relay_Master_Log_File, 1);
+let $sql_pos= query_get_value(SHOW SLAVE STATUS, Exec_Master_Log_Pos, 1);
+--disable_query_log
+eval SELECT IF('$io_file' = '$sql_file', "OK", "Not ok, $io_file <> $sql_file") AS test_check;
+eval SELECT IF('$io_pos' = '$sql_pos', "OK", "Not ok, $io_pos <> $sql_pos") AS test_check;
+--enable_query_log
+
+--connection server_1
+FLUSH LOGS;
+--source include/wait_for_binlog_checkpoint.inc
+--save_master_pos
+
+--connection server_2
+--sync_with_master
+let $io_file= query_get_value(SHOW SLAVE STATUS, Master_Log_File, 1);
+let $io_pos= query_get_value(SHOW SLAVE STATUS, Read_Master_Log_Pos, 1);
+let $sql_file= query_get_value(SHOW SLAVE STATUS, Relay_Master_Log_File, 1);
+let $sql_pos= query_get_value(SHOW SLAVE STATUS, Exec_Master_Log_Pos, 1);
+--disable_query_log
+eval SELECT IF('$io_file' = '$sql_file', "OK", "Not ok, $io_file <> $sql_file") AS test_check;
+eval SELECT IF('$io_pos' = '$sql_pos', "OK", "Not ok, $io_pos <> $sql_pos") AS test_check;
+--enable_query_log
+
+# Clean up.
+--connection server_2
+--source include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=@old_parallel_threads;
+--source include/start_slave.inc
+
+--connection server_1
+DROP TABLE t5;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_parallel_xa_same_xid.test b/mysql-test/suite/rpl/t/rpl_parallel_xa_same_xid.test
new file mode 100644
index 00000000..888dd2f1
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_parallel_xa_same_xid.test
@@ -0,0 +1,138 @@
+# The tests verify concurrent execution of replicated (MDEV-742)
+# XA transactions in the parallel optimistic mode.
+# Prove optimistic scheduler handles xid-namesake XA:s.
+# That is despite running in parallel there must be no conflicts
+# caused by multiple transactions' same xid.
+
+--source include/have_binlog_format_mixed_or_row.inc
+--source include/have_innodb.inc
+--source include/have_perfschema.inc
+--source include/master-slave.inc
+
+--let $xid_num = 19
+--let $repeat = 17
+--let $workers = 7
+--connection slave
+call mtr.add_suppression("WSREP: handlerton rollback failed");
+
+--source include/stop_slave.inc
+# a measure against MDEV-20605
+ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
+
+SET @old_parallel_threads = @@GLOBAL.slave_parallel_threads;
+--disable_query_log
+--eval SET @@global.slave_parallel_threads = $workers
+--enable_query_log
+SET @old_parallel_mode = @@GLOBAL.slave_parallel_mode;
+SET @@global.slave_parallel_mode ='optimistic';
+--source include/start_slave.inc
+
+--connection master
+CREATE TABLE t1 (a INT, b INT) ENGINE=InnoDB;
+
+--let $i = $xid_num
+--let $t = t1
+--disable_query_log
+while ($i)
+{
+--let $k = $repeat
+while ($k)
+{
+--eval XA START 'xid_$i'
+--eval INSERT INTO $t SET a=$i, b=$k
+--eval XA END 'xid_$i'
+--let $one_phase = `SELECT IF(floor(rand()*10)%2, "ONE PHASE", 0)`
+ if (!$one_phase)
+ {
+ --eval XA PREPARE 'xid_$i'
+ --eval XA COMMIT 'xid_$i'
+ }
+ if ($one_phase)
+ {
+ --eval XA COMMIT 'xid_$i' ONE PHASE
+ }
+
+ if (!$one_phase)
+ {
+ --eval XA START 'xid_$i'
+ --eval INSERT INTO $t SET a=$i, b=$k
+ --eval XA END 'xid_$i'
+ --eval XA PREPARE 'xid_$i'
+ --eval XA ROLLBACK 'xid_$i'
+ }
+
+--dec $k
+}
+
+--dec $i
+}
+--enable_query_log
+
+
+
+# Above-like test complicates execution env to create
+# data conflicts as well. They will be resolved by the optmistic
+# scheduler as usual.
+
+CREATE TABLE t2 (a INT AUTO_INCREMENT PRIMARY KEY, b INT) ENGINE=InnoDB;
+
+--let $i = $xid_num
+--let $t = t2
+--disable_query_log
+while ($i)
+{
+--let $k = $repeat
+while ($k)
+{
+--eval XA START 'xid_$i'
+--eval INSERT INTO $t SET a=NULL, b=$k
+--eval UPDATE $t SET b=$k + 1 WHERE a=last_insert_id() % $workers
+--eval XA END 'xid_$i'
+--let $one_phase = `SELECT IF(floor(rand()*10)%2, "ONE PHASE", 0)`
+ if (!$one_phase)
+ {
+ --eval XA PREPARE 'xid_$i'
+ --eval XA COMMIT 'xid_$i'
+ }
+ if ($one_phase)
+ {
+ --eval XA COMMIT 'xid_$i' ONE PHASE
+ }
+
+--eval XA START 'xid_$i'
+--eval UPDATE $t SET b=$k + 1 WHERE a=last_insert_id() % $workers
+--eval DELETE FROM $t WHERE a=last_insert_id()
+--eval XA END 'xid_$i'
+--eval XA PREPARE 'xid_$i'
+--eval XA ROLLBACK 'xid_$i'
+
+--let $do_drop_create = `SELECT IF(floor(rand()*10)%100, 1, 0)`
+if ($do_drop_create)
+{
+ DROP TABLE t1;
+ CREATE TABLE t1 (a INT, b INT) ENGINE=InnoDB;
+}
+--dec $k
+}
+
+--dec $i
+}
+--enable_query_log
+
+--source include/sync_slave_sql_with_master.inc
+--let $diff_tables= master:t1, slave:t1
+--source include/diff_tables.inc
+
+#
+# Clean up.
+#
+--connection slave
+--source include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=@old_parallel_threads;
+SET GLOBAL slave_parallel_mode=@old_parallel_mode;
+--source include/start_slave.inc
+
+--connection master
+DROP TABLE t1, t2;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_partition_archive.test b/mysql-test/suite/rpl/t/rpl_partition_archive.test
new file mode 100644
index 00000000..5b64576d
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_partition_archive.test
@@ -0,0 +1,12 @@
+# Test of partitioning features with replication for archive
+--source include/have_archive.inc
+--source include/have_partition.inc
+--source include/master-slave.inc
+
+# Set the default connection to 'master'
+
+let $engine_type= 'Archive';
+
+--source suite/rpl/include/rpl_partition.inc
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_partition_innodb-master.opt b/mysql-test/suite/rpl/t/rpl_partition_innodb-master.opt
new file mode 100644
index 00000000..0eed7aaa
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_partition_innodb-master.opt
@@ -0,0 +1 @@
+--innodb_autoinc_lock_mode=0
diff --git a/mysql-test/suite/rpl/t/rpl_partition_innodb.test b/mysql-test/suite/rpl/t/rpl_partition_innodb.test
new file mode 100644
index 00000000..098bc407
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_partition_innodb.test
@@ -0,0 +1,12 @@
+# Test of partitioning features with replication for InnoDB
+--source include/have_innodb.inc
+--source include/have_partition.inc
+--source include/master-slave.inc
+
+# Set the default connection to 'master'
+
+let $engine_type= 'InnoDB';
+
+--source suite/rpl/include/rpl_partition.inc
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_partition_memory.test b/mysql-test/suite/rpl/t/rpl_partition_memory.test
new file mode 100644
index 00000000..4ce68d6f
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_partition_memory.test
@@ -0,0 +1,11 @@
+# Test of partitioning features with replication for Memory
+--source include/have_partition.inc
+--source include/master-slave.inc
+
+# Set the default connection to 'master'
+
+let $engine_type= 'Memory';
+
+--source suite/rpl/include/rpl_partition.inc
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_partition_myisam.test b/mysql-test/suite/rpl/t/rpl_partition_myisam.test
new file mode 100644
index 00000000..56003d89
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_partition_myisam.test
@@ -0,0 +1,11 @@
+# Test of partitioning features with replication for MyISAM
+--source include/have_partition.inc
+--source include/master-slave.inc
+
+# Set the default connection to 'master'
+
+let $engine_type= 'MyISAM';
+
+--source suite/rpl/include/rpl_partition.inc
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_password_boundaries.test b/mysql-test/suite/rpl/t/rpl_password_boundaries.test
new file mode 100644
index 00000000..567fe35e
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_password_boundaries.test
@@ -0,0 +1,104 @@
+source include/not_embedded.inc;
+source include/master-slave.inc;
+source include/rpl_reset.inc;
+
+# Suppress warnings that might be generated during the test
+disable_query_log;
+connection master;
+call mtr.add_suppression("Timeout waiting for reply of binlog");
+connection slave;
+call mtr.add_suppression("Slave SQL.*Request to stop slave SQL Thread received while applying a group that has non-transactional changes; waiting for completion of the group");
+enable_query_log;
+
+connection master;
+
+# wait for dying connections (if any) to disappear
+let $wait_condition= select count(*) = 0 from information_schema.processlist where command='killed';
+--source include/wait_condition.inc
+
+# 32*3-character ASCII password should work all right
+
+set sql_log_bin=0;
+grant replication slave on *.* to rpl32@127.0.0.1 identified by '0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef';
+set sql_log_bin=1;
+
+connection slave;
+source include/stop_slave.inc;
+change master to master_user='rpl32',master_password='0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef';
+source include/start_slave.inc;
+
+connection master;
+drop table if exists t1;
+create table t1 (i int);
+insert into t1 values (1);
+sync_slave_with_master;
+echo [ synchronized ];
+
+connection master;
+
+# 32*3+1 -character ASCII password expected to fail
+set sql_log_bin=0;
+grant replication slave on *.* to rpl33@127.0.0.1 identified by '0123456789abcdef0123456789abcdef!';
+set sql_log_bin=1;
+
+connection slave;
+source include/stop_slave.inc;
+--error ER_WRONG_STRING_LENGTH
+change master to master_user='rpl33',master_password='0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef!';
+
+# Check also master_user and master_host
+
+--error ER_WRONG_STRING_LENGTH
+change master to master_user='aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa';
+
+# One more char to the master host naturally max ends up with
+--error ER_WRONG_STRING_LENGTH
+change master to master_host='aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddE';
+
+# 48-character cyrillic password should work all right
+connection master;
+set sql_log_bin=0;
+grant replication slave on *.* to rpl16cyr@127.0.0.1 identified by 'воттакойужпарольвоттакойужпарольвоттакойужпароль';
+set sql_log_bin=1;
+
+connection slave;
+SET NAMES utf8;
+change master to master_user='rpl16cyr',master_password='воттакойужпарольвоттакойужпарольвоттакойужпароль';
+source include/start_slave.inc;
+
+connection master;
+drop table if exists t1;
+create table t1 (i int);
+insert into t1 values (1);
+sync_slave_with_master;
+echo [ synchronized ];
+
+# 48+1-character cyrillic password should fail
+
+connection master;
+set sql_log_bin=0;
+grant replication slave on *.* to rpl17mix@127.0.0.1 identified by 'воттакойужпарольвоттакойужпарольвоттакойужпароль!';
+set sql_log_bin=1;
+
+connection slave;
+source include/stop_slave.inc;
+--error ER_WRONG_STRING_LENGTH
+change master to master_user='rpl17mix',master_password='воттакойужпарольвоттакойужпарольвоттакойужпароль!';
+
+# Cleanup
+
+connection master;
+set sql_log_bin=0;
+drop user rpl32@127.0.0.1, rpl33@127.0.0.1, rpl16cyr@127.0.0.1, rpl17mix@127.0.0.1;
+set sql_log_bin=1;
+
+connection slave;
+change master to master_user='root',master_password='';
+source include/start_slave.inc;
+
+connection master;
+drop table if exists t1;
+sync_slave_with_master;
+
+connection master;
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_performance_schema.test b/mysql-test/suite/rpl/t/rpl_performance_schema.test
new file mode 100644
index 00000000..18aabe52
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_performance_schema.test
@@ -0,0 +1,10 @@
+--source include/have_perfschema.inc
+--source include/have_binlog_format_mixed.inc
+--source include/master-slave.inc
+
+UPDATE performance_schema.setup_instruments SET ENABLED="NO";
+
+--sync_slave_with_master
+--source include/rpl_end.inc
+
+# End of test case
diff --git a/mysql-test/suite/rpl/t/rpl_perfschema_applier_config.test b/mysql-test/suite/rpl/t/rpl_perfschema_applier_config.test
new file mode 100644
index 00000000..5e7b1104
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_perfschema_applier_config.test
@@ -0,0 +1,97 @@
+# ==== Purpose ====
+#
+# This test script serves as the functionality testing for the table
+# performance_schema.replication_applier_configuration. Test for ddl and dml
+# operations is a part of the perfschema suite. The ddl/dml tests are named:
+# 1) ddl_replication_applier_configuration.test and
+# 2) dml_replication_applier_configuration.test.
+#
+# The follwing scenarios are tested in this script:
+#
+# - Verify that output is same as SSS on a fresh slave.
+# - Verify that the value of this field is correct after STOP SLAVE.
+# - Verify that, when desired delay is set, the value is shown corectly.
+# - Verify that the value is preserved after STOP SLAVE.
+# - Verify that, when desired delay is reset, the value is shown corectly.
+#
+# ==== Related Worklog ====
+#
+# MDEV-16437: merge 5.7 P_S replication instrumentation and tables
+#
+
+source include/have_perfschema.inc;
+source include/have_binlog_format_mixed.inc;
+source include/master-slave.inc;
+
+let $assert_text= On master, the table should return an empty set.;
+let $assert_cond= count(*) = 0 from performance_schema.replication_applier_configuration;
+source include/assert.inc;
+
+--connection slave
+
+--echo
+--echo # Verify that SELECT works and produces an output similar to
+--echo # the corresponding field in SHOW SLAVE STATUS(SSS) in all scenarios.
+--echo
+
+--echo
+--echo # Verify that output is same as SSS on a fresh slave.
+--echo
+
+let $sss_value= query_get_value(SHOW SLAVE STATUS, SQL_Delay, 1);
+let $ps_value= query_get_value(select Desired_Delay from performance_schema.replication_applier_configuration, Desired_Delay, 1);
+let $assert_text= Value returned by SSS and PS table for Desired_Delay should be same.;
+let $assert_cond= "$sss_value" = "$ps_value";
+source include/assert.inc;
+
+--echo
+--echo # Verify that the value of this field is correct after STOP SLAVE.
+--echo
+
+source include/stop_slave.inc;
+
+let $sss_value= query_get_value(SHOW SLAVE STATUS, SQL_Delay, 1);
+let $ps_value= query_get_value(select Desired_Delay from performance_schema.replication_applier_configuration, Desired_Delay, 1);
+let $assert_text= Value returned by SSS and PS table for Desired_Delay should be same.;
+let $assert_cond= "$sss_value" = "$ps_value";
+source include/assert.inc;
+
+--echo
+--echo # Verify that, when desired delay is set, the value is shown corectly.
+--echo
+
+eval change master to master_delay= 2;
+source include/start_slave.inc;
+
+let $sss_value= query_get_value(SHOW SLAVE STATUS, SQL_Delay, 1);
+let $ps_value= query_get_value(select Desired_Delay from performance_schema.replication_applier_configuration, Desired_Delay, 1);
+let $assert_text= Value returned by SSS and PS table for Desired_Delay should be same.;
+let $assert_cond= "$sss_value" = "$ps_value";
+source include/assert.inc;
+
+--echo
+--echo # Verify that the value is preserved after STOP SLAVE.
+--echo
+
+source include/stop_slave.inc;
+
+let $ss_value= query_get_value(SHOW SLAVE STATUS, SQL_Delay, 1);
+let $ps_value= query_get_value(select Desired_Delay from performance_schema.replication_applier_configuration, Desired_Delay, 1);
+let $assert_text= Value returned by SSS and PS table for Desired_Delay should be same.;
+let $assert_cond= "$sss_value" = "$ps_value";
+source include/assert.inc;
+
+--echo
+--echo # Verify that, when desired delay is reset, the value is shown corectly.
+--echo
+
+eval change master to master_delay= 0;
+source include/start_slave.inc;
+
+let $sss_value= query_get_value(SHOW SLAVE STATUS, SQL_Delay, 1);
+let $ps_value= query_get_value(select Desired_Delay from performance_schema.replication_applier_configuration, Desired_Delay, 1);
+let $assert_text= Value returned by SSS and PS table for Desired_Delay should be same.;
+let $assert_cond= "$sss_value" = "$ps_value";
+source include/assert.inc;
+
+source include/rpl_end.inc;
diff --git a/mysql-test/suite/rpl/t/rpl_perfschema_applier_status.test b/mysql-test/suite/rpl/t/rpl_perfschema_applier_status.test
new file mode 100644
index 00000000..7a0e9cf9
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_perfschema_applier_status.test
@@ -0,0 +1,73 @@
+# ==== Purpose ====
+#
+# This test script serves as the functionality testing for the table
+# performance_schema.replication_applier_status. Test for ddl and dml
+# operations is a part of the perfschema suite. The ddl/dml tests are named:
+# 1) ddl_replication_applier_status.test and
+# 2) dml_replication_applier_status.test.
+#
+# The follwing scenarios are tested in this script:
+#
+# - Verify that output is same as SSS on a fresh slave.
+# - Verify that the value of this field is correct after STOP SLAVE.
+# - Remaining delay is not tested.
+# - Count_trnsaction is partially tested here making sure it can be queried.
+# More testing in rpl/include/rpl_deadlock.test
+#
+# ==== Related Worklog ====
+#
+# MDEV-16437: merge 5.7 P_S replication instrumentation and tables
+#
+
+source include/have_perfschema.inc;
+source include/have_binlog_format_mixed.inc;
+source include/master-slave.inc;
+
+let $assert_text= On master, the table should return an empty set.;
+let $assert_cond= count(*) = 0 from performance_schema.replication_applier_status;
+source include/assert.inc;
+
+--connection slave
+
+--echo
+--echo # Verify that SELECT works and produces an output similar to
+--echo # the corresponding field in SHOW SLAVE STATUS(SSS) in all scenarios.
+--echo
+
+--echo
+--echo # Verify that output is same as SSS on a fresh slave.
+--echo
+
+let $sss_value= query_get_value(SHOW SLAVE STATUS, Slave_SQL_Running, 1);
+let $ps_value= query_get_value(select Service_State from performance_schema.replication_applier_status, Service_State, 1);
+let $assert_text= SSS shows Slave_SQL_Running as "Yes". So, Service_State from this PS table should be "ON".;
+let $assert_cond= "$sss_value" = "Yes" AND "$ps_value"= "ON";
+source include/assert.inc;
+
+let $ss_value= query_get_value(SHOW STATUS LIKE 'Slave_retried_transactions', Value, 1);
+let $ps_value= query_get_value(select count_transactions_retries from performance_schema.replication_applier_status, count_transactions_retries, 1);
+let $assert_text= COUNT_TRANSACTION_RETRIES should be equal to Slave_retried_transactions.;
+let $assert_cond= "$ps_value"= "$ss_value";
+source include/assert.inc;
+
+--echo
+--echo # Verify that the fields show the correct values after STOP SLAVE.
+--echo
+
+source include/stop_slave.inc;
+
+let $sss_value= query_get_value(SHOW SLAVE STATUS, Slave_SQL_Running, 1);
+let $ps_value= query_get_value(select Service_State from performance_schema.replication_applier_status, Service_State, 1);
+let $assert_text= SSS shows Slave_SQL_Running as "No". So, Service_State from this PS table should be "OFF".;
+let $assert_cond= "$sss_value" = "No" AND "$ps_value"= "OFF";
+source include/assert.inc;
+
+let $ss_value= query_get_value(SHOW STATUS LIKE 'Slave_retried_transactions', Value, 1);
+let $ps_value= query_get_value(select count_transactions_retries from performance_schema.replication_applier_status, count_transactions_retries, 1);
+let $assert_text= COUNT_TRANSACTION_RETRIES should be equal to Slave_retried_transactions.;
+let $assert_cond= "$ps_value"= "$ss_value";
+source include/assert.inc;
+
+source include/start_slave.inc;
+source include/rpl_end.inc;
+
diff --git a/mysql-test/suite/rpl/t/rpl_perfschema_applier_status_by_coordinator-slave.opt b/mysql-test/suite/rpl/t/rpl_perfschema_applier_status_by_coordinator-slave.opt
new file mode 100644
index 00000000..3f82baff
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_perfschema_applier_status_by_coordinator-slave.opt
@@ -0,0 +1 @@
+--loose-innodb-lock-wait-timeout=1
diff --git a/mysql-test/suite/rpl/t/rpl_perfschema_applier_status_by_coordinator.test b/mysql-test/suite/rpl/t/rpl_perfschema_applier_status_by_coordinator.test
new file mode 100644
index 00000000..44df3ca4
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_perfschema_applier_status_by_coordinator.test
@@ -0,0 +1,318 @@
+# ==== Purpose ====
+#
+# This test script serves as the functionality testing for the table
+# performance_schema.replication_applier_status_by_coordinator. Test
+# for ddl and dml operations is a part of the perfschema suite.
+# The ddl/dml tests are named:
+# 1) ddl_replication_connection_configuration.test and
+# 2) dml_replication_connection_configuration.test.
+#
+# This test script does the following:
+
+# - Verify that SELECT works for every field in the table.
+# - The SELECT per field produces an output similar to the corresponding field
+# in SHOW SLAVE STATUS(SSS), if there is one.
+# - If there is no matching field in SSS, we resort to other method of testing
+# those fields.
+# - We perform all the testing on connection "slave". On master, the table
+# returns an empty set.
+#
+# The follwing scenarios are tested in this test script:
+#
+# - Test each field in STS on a fresh replication setup.
+# - Change configuration parameters using CHANGE MASTER TO and verify that
+# these changes are seen in SELECTs from PS table.
+# - Verify that, the change in values are correctly shown by the table.
+# - Verify that the values are preserved after STOP SLAVE, thread_id
+# changes to NULL and service_state changes to "Off".
+# - A priliminary test for Multi-threaded slave(MTS) mode.
+#
+# ==== Reference ====
+#
+# MDEV:16437: merge 5.7 P_S replication instrumentation and tables
+#
+--source include/have_innodb.inc
+--source include/have_binlog_format_mixed.inc
+--source include/have_perfschema.inc
+--source include/master-slave.inc
+
+call mtr.add_suppression("Error 'Table 'test.t' doesn't exist' on query.");
+
+let $assert_text= On master, the table should return an empty set.;
+let $assert_cond= count(*) = 0 from performance_schema.replication_applier_status_by_coordinator;
+source include/assert.inc;
+
+--connection slave
+
+--let $slave_param= Slave_SQL_Running_State
+--let $slave_param_value= Slave has read all relay log; waiting for more updates
+source include/wait_for_slave_param.inc;
+
+--echo
+--echo # Testing on fresh slave.
+--echo
+
+# To verify the correctness of thread_id field, we check for the name of
+# the thread.
+let $thread_name= `select name from performance_schema.threads where thread_id= (select Thread_Id from performance_schema.replication_applier_status_by_coordinator)`;
+let $assert_text= thread_name should should indicate sql thread.;
+let $assert_cond= "$thread_name" = "thread/sql/slave_sql";
+source include/assert.inc;
+
+let $sss_value= query_get_value(SHOW SLAVE STATUS, Slave_SQL_Running, 1);
+let $ps_value= query_get_value(select Service_State from performance_schema.replication_applier_status_by_coordinator, Service_State, 1);
+let $assert_text= SSS shows Slave_IO_Running as "Yes". So, Service_State from this PS table should be "ON".;
+let $assert_cond= "$sss_value" = "Yes" AND "$ps_value"= "ON";
+source include/assert.inc;
+
+let $sss_value= query_get_value(SHOW SLAVE STATUS, Last_SQL_Errno, 1);
+let $ps_value= query_get_value(select Last_Error_Number from performance_schema.replication_applier_status_by_coordinator, Last_Error_Number, 1);
+let $assert_text= Value returned by SSS and PS table for Last_Error_Number should be same.;
+let $assert_cond= "$sss_value" = "$ps_value";
+source include/assert.inc;
+
+let $sss_value= query_get_value(SHOW SLAVE STATUS, Last_SQL_Error, 1);
+let $ps_value= query_get_value(select Last_Error_Message from performance_schema.replication_applier_status_by_coordinator, Last_Error_Message, 1);
+let $assert_text= Value returned by SSS and PS table for Last_Error_Message should be same.;
+let $assert_cond= "$sss_value" = "$ps_value";
+source include/assert.inc;
+
+let $ps_value= query_get_value(select Last_Error_Timestamp from performance_schema.replication_applier_status_by_coordinator, Last_Error_Timestamp, 1);
+let $assert_text= Value returned by SSS and PS table for Last_Error_Timestamp should be 0000-00-00 00:00:00.;
+let $assert_cond= "$ps_value" = "0000-00-00 00:00:00";
+source include/assert.inc;
+
+let $ps_value= query_get_value(select Last_Trans_Retry_Count from performance_schema.replication_applier_status_by_coordinator, Last_Trans_Retry_Count, 1);
+let $assert_text= Last_trans_retry_count should be 0.;
+let $assert_cond= "$ps_value"= 0;
+source include/assert.inc;
+
+--echo
+--echo # Cause an error in the SQL thread and check for the correctness of
+--echo # values in error number, message and timestamp fields.
+--echo
+
+# Cause an error in SQL thread.
+# 1) Ceate a table 't' at master, replicate at slave.
+# 2) Drop table 't' at slave only.
+# 3) Insert a value in table 't' on master and replicate on slave.
+# Since slave doesnt have table 't' anymore, SQL thread will show an error.
+
+--connection master
+use test;
+create table t(a int primary key);
+--source include/sync_slave_sql_with_master.inc
+drop table t;
+--connection master
+insert into t values(1);
+--connection slave
+let $slave_sql_errno=1146;
+source include/wait_for_slave_sql_error.inc;
+
+--echo
+--echo # Extract the error related fields from SSS and PS table and compare
+--echo # them for correctness.
+--echo
+
+let $sss_value= query_get_value(SHOW SLAVE STATUS, Last_SQL_Errno, 1);
+let $ps_value= query_get_value(select Last_Error_Number from performance_schema.replication_applier_status_by_coordinator, Last_Error_Number, 1);
+let $assert_text= Value returned by SSS and PS table for Last_Error_Number should be same.;
+let $assert_cond= "$sss_value" = "$ps_value";
+source include/assert.inc;
+
+# Availability of special characters like single quote and backtick character
+# makes it difficult use the assert.inc or mysql functionstrcmp().
+# So, the equality of error messages is checked using the below perl code.
+
+let $sss_value= query_get_value(SHOW SLAVE STATUS, Last_SQL_Error, 1);
+let $ps_value= query_get_value(select Last_Error_Message from performance_schema.replication_applier_status_by_coordinator, Last_Error_Message, 1);
+
+let PS_VALUE= $ps_value;
+let SSS_VALUE= $sss_value;
+
+perl;
+use strict;
+my $ps_value= $ENV{'PS_VALUE'};
+my $sss_value= $ENV{'SSS_VALUE'};
+
+if ($ps_value eq $sss_value)
+{
+ print "Value returned by SSS and PS table for Last_Error_Message is same.\n";
+}
+else
+{
+ print "Value returned by SSS and PS table for Last_Error_Message is NOT same\n";
+}
+EOF
+
+--echo
+--echo # Verify that the error fields are preserved after STOP SLAVE, thread_id
+--echo # changes to NULL and service_state changes to "Off".
+--echo
+
+--echo
+--echo # 1. Verify that thread_id changes to NULL and service_state to "off" on
+--echo # STOP SLAVE.
+--echo
+
+let $ps_value= query_get_value(select thread_id from performance_schema.replication_applier_status_by_coordinator, thread_id, 1);
+let $assert_text= After STOP SLAVE, thread_id should be NULL;
+let $assert_cond= "$ps_value" = "NULL";
+source include/assert.inc;
+
+let $sss_value= query_get_value(SHOW SLAVE STATUS, Slave_SQL_Running, 1);
+let $ps_value= query_get_value(select Service_State from performance_schema.replication_applier_status_by_coordinator, Service_State, 1);
+let $assert_text= SSS shows Slave_SQL_Running as "No". So, Service_State from this PS table should be "OFF".;
+let $assert_cond= "$sss_value" = "No" AND "$ps_value"= "OFF";
+source include/assert.inc;
+
+--echo
+--echo # 2. Extract the error related fields from SSS and PS table and compare
+--echo # them. These fields should preserve their values.
+--echo
+
+let $sss_value= query_get_value(SHOW SLAVE STATUS, Last_SQL_Errno, 1);
+let $ps_value= query_get_value(select Last_Error_Number from performance_schema.replication_applier_status_by_coordinator, Last_Error_Number, 1);
+let $assert_text= Value returned by SSS and PS table for Last_Error_Number should be same.;
+let $assert_cond= "$sss_value" = "$ps_value";
+source include/assert.inc;
+
+# Availability of special characters like single quote and backtick character
+# makes it difficult use the assert.inc or mysql functionstrcmp().
+# So, the equality of error messages is checked using the below perl code.
+
+let $sss_value= query_get_value(SHOW SLAVE STATUS, Last_SQL_Error, 1);
+let $ps_value= query_get_value(select Last_Error_Message from performance_schema.replication_applier_status_by_coordinator, Last_Error_Message, 1);
+
+let PS_VALUE= $ps_value;
+let SSS_VALUE= $sss_value;
+
+perl;
+use strict;
+my $ps_value= $ENV{'PS_VALUE'};
+my $sss_value= $ENV{'SSS_VALUE'};
+
+if ($ps_value eq $sss_value)
+{
+ print "Value returned by SSS and PS table for Last_Error_Message is same.\n";
+}
+else
+{
+ print "Value returned by SSS and PS table for Last_Error_Message is NOT same\n";
+}
+EOF
+
+# End of perl code for testing the error message.
+
+--connection master
+drop table t;
+reset master;
+
+--connection slave
+--source include/stop_slave.inc
+reset slave;
+reset master;
+set @@global.gtid_slave_pos= "";
+set @saved_slave_trans_retry_interval= @@GLOBAL.slave_transaction_retry_interval;
+set global slave_transaction_retry_interval=1;
+--source include/start_slave.inc
+# End of perl code for testing error message.
+
+
+--echo #
+--echo # Test Last_Trans_Retry_Count value.
+--echo #
+
+--connection master
+create table t1 (f int primary key) engine=innodb;
+insert into t1 values (10);
+--sync_slave_with_master
+connect (slave2,127.0.0.1,root,,test,$SLAVE_MYPORT,);
+--connection slave2
+begin;
+update t1 set f=40 where f=10;
+
+--connection master
+begin;
+update t1 set f=60 where f=10;
+commit;
+
+--connection slave
+--let $wait_condition= SELECT COUNT(*) > 0 FROM information_schema.processlist WHERE Info = "update t1 set f=60 where f=10"
+--source include/wait_condition.inc
+sleep 4 ;
+--connection slave2
+rollback;
+
+let $ps_value= query_get_value(select Last_Trans_Retry_Count from performance_schema.replication_applier_status_by_coordinator, Last_Trans_Retry_Count, 1);
+let $assert_text= Value returned by PS table for Last_Trans_Retry_Count should be > 0.;
+let $assert_cond= "$ps_value" > 0;
+source include/assert.inc;
+
+--connection master
+drop table t1;
+--sync_slave_with_master
+--disconnect slave2
+set global slave_transaction_retry_interval=@saved_slave_trans_retry_interval;
+
+source include/stop_slave.inc;
+
+--echo
+--echo # Restarting servers and setting up MTS now. Since, SQL thread and
+--echo # coordinator are the same and follow same code path, we can skip
+--echo # testing for coordinator thread in all scenarios. Testing for one
+--echo # scenario is enough.
+--echo
+
+--let $rpl_server_number= 1
+--source include/rpl_restart_server.inc
+
+--let $rpl_server_number= 2
+--source include/rpl_restart_server.inc
+
+--connection slave
+replace_result $MASTER_MYPORT MASTER_MYPORT;
+replace_column 2 ###;
+eval change master to
+ master_host='127.0.0.1',
+ master_port=$MASTER_MYPORT,
+ master_user='root';
+SET @save.slave_parallel_workers=@@global.slave_parallel_workers;
+SET @@global.slave_parallel_workers=1;
+# to avoid warnings
+set @save.slave_transaction_retries= @@global.slave_transaction_retries;
+source include/start_slave.inc;
+
+--let $slave_param= Slave_SQL_Running_State
+--let $slave_param_value= Slave has read all relay log; waiting for more updates
+source include/wait_for_slave_param.inc;
+
+# To verify the correctness of thread_id field, we check for the name of
+# the thread.
+let $thread_name= `select name from performance_schema.threads where thread_id= (select Thread_Id from performance_schema.replication_applier_status_by_coordinator)`;
+let $assert_text= thread_name should should indicate sql thread.;
+let $assert_cond= "$thread_name" = "thread/sql/slave_sql";
+source include/assert.inc;
+
+let $sss_value= query_get_value(SHOW SLAVE STATUS, Slave_SQL_Running, 1);
+let $ps_value= query_get_value(select Service_State from performance_schema.replication_applier_status_by_coordinator, Service_State, 1);
+let $assert_text= SSS shows Slave_SQL_Running as "Yes". So, Service_State from this PS table should be "ON".;
+let $assert_cond= "$sss_value" = "Yes" AND "$ps_value"= "ON";
+source include/assert.inc;
+
+let $sss_value= query_get_value(SHOW SLAVE STATUS, Last_SQL_Errno, 1);
+let $ps_value= query_get_value(select Last_Error_Number from performance_schema.replication_applier_status_by_coordinator, Last_Error_Number, 1);
+let $assert_text= Value returned by SSS and PS table for Last_Error_Number should be same.;
+let $assert_cond= "$sss_value" = "$ps_value";
+source include/assert.inc;
+
+--echo
+--echo # Cleanup.
+--echo
+
+source include/stop_slave.inc;
+set @@global.slave_parallel_workers= @save.slave_parallel_workers;
+set @@global.slave_transaction_retries= @save.slave_transaction_retries;
+source include/start_slave.inc;
+
+source include/rpl_end.inc;
diff --git a/mysql-test/suite/rpl/t/rpl_perfschema_applier_status_by_worker.test b/mysql-test/suite/rpl/t/rpl_perfschema_applier_status_by_worker.test
new file mode 100644
index 00000000..857979d0
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_perfschema_applier_status_by_worker.test
@@ -0,0 +1,257 @@
+# ==== Purpose ====
+#
+# This test script serves as the functionality testing for the table
+# performance_schema.replication_applier_status_by_worker. Test
+# for ddl and dml operations is a part of the perfschema suite.
+# The ddl/dml tests are named:
+# 1) ddl_replication_applier_status_by_worker.test and
+# 2) dml_replication_applier_status_by_worker.test.
+#
+# This test script does the following:
+
+# - Verify that SELECT works for every field in the table.
+# - The SELECT per field produces an output similar to the corresponding field
+# in SHOW SLAVE STATUS(SSS), if there is one.
+# - If there is no matching field in SSS, we resort to other method of testing
+# those fields.
+# - We perform all the testing on connection "slave". On master, the table
+# returns an empty set.
+#
+# The follwing scenarios are tested in this test script:
+#
+# - Test each field on a fresh replication setup.
+# - Introduce error in worker thread and check for the correctness of error
+# error number, message and timestamp.
+# - Verify that, the change in values are correctly shown by the table.
+# - Verify that the values are preserved after STOP SLAVE.
+# - Set up replication in gtid-mode=on and test 'Last_Seen_Transaction' field.
+# - Verify that the value in 'Last_Seen_Transaction' field is preserved after
+# STOP SLAVE.
+#
+# ==== Related Bugs and Worklogs ====
+#
+# MDEV-20220: Merge 5.7 P_S replication table 'replication_applier_status_by_worker
+#
+--source include/have_perfschema.inc
+--source include/have_binlog_format_mixed.inc
+--source include/have_innodb.inc
+--source include/master-slave.inc
+
+
+let $assert_text= On master, the table should return an empty set.;
+let $assert_cond= count(*) = 0 from performance_schema.replication_applier_status_by_worker;
+source include/assert.inc;
+
+--echo
+--echo # Setup MTS and perform testing on a fresh slave.
+--echo
+--connection slave
+call mtr.add_suppression("Error 'Table 'test.t' doesn't exist' on query.");
+source include/stop_slave.inc;
+set @save_slave_parallel_workers= @@global.slave_parallel_workers;
+# to avoid warnings
+set @save_slave_transaction_retries= @@global.slave_transaction_retries;
+RESET SLAVE ALL;
+evalp CHANGE MASTER 'slave1' TO MASTER_USER='root',MASTER_PORT=$MASTER_MYPORT, MASTER_HOST='127.0.0.1', MASTER_USE_GTID=slave_pos;
+SET default_master_connection='slave1';
+SET @@global.slave_parallel_workers=1;
+ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
+START SLAVE 'slave1';
+--source include/wait_for_slave_to_start.inc
+
+let $ps_value= query_get_value(select channel_name from performance_schema.replication_applier_status_by_worker, channel_name, 1);
+let $assert_text= Channel_name will be empty for a worker when it has not processed any transaction;
+let $assert_cond= "$ps_value"= "";
+source include/assert.inc;
+
+# To verify the correctness of thread_id field, we check for the name of
+# the thread.
+let $thread_name= `select name from performance_schema.threads where thread_id= (select Thread_Id from performance_schema.replication_applier_status_by_worker)`;
+let $assert_text= thread_name should should indicate worker thread.;
+let $assert_cond= "$thread_name" = "thread/sql/rpl_parallel_thread";
+source include/assert.inc;
+
+let $ps_value= query_get_value(select Service_State from performance_schema.replication_applier_status_by_worker, Service_State, 1);
+let $assert_text= Service_State should be "ON" on a fresh slave server.;
+let $assert_cond= "$ps_value"= "ON";
+source include/assert.inc;
+
+let $ps_value= query_get_value(select Last_Seen_Transaction from performance_schema.replication_applier_status_by_worker, Last_Seen_Transaction, 1);
+let $assert_text= Last_Seen_Transaction should show "" if no transaction applierd;
+let $assert_cond= "$ps_value" = "";
+source include/assert.inc;
+
+--connection master
+CREATE TABLE t1 (a INT) ENGINE=InnoDB;
+--source include/save_master_gtid.inc
+
+connection slave;
+--source include/sync_with_master_gtid.inc
+
+let $ps_value= query_get_value(select channel_name from performance_schema.replication_applier_status_by_worker, channel_name, 1);
+let $assert_text= Channel_name must be slave1;
+let $assert_cond= "$ps_value"= "slave1";
+source include/assert.inc;
+
+let $ps_value= query_get_value(select Last_Seen_Transaction from performance_schema.replication_applier_status_by_worker, Last_Seen_Transaction, 1);
+let $sss_value= query_get_value(SHOW SLAVE STATUS, Gtid_IO_Pos, 1);
+let $assert_text= Last_Seen_Transaction should show $sss_value;
+let $assert_cond= "$ps_value" = "$sss_value";
+source include/assert.inc;
+
+let $sss_value= query_get_value(SHOW SLAVE STATUS, Last_SQL_Errno, 1);
+let $ps_value= query_get_value(select Last_Error_Number from performance_schema.replication_applier_status_by_worker, Last_Error_Number, 1);
+let $assert_text= Value returned by SSS and PS table for Last_Error_Number should be same.;
+let $assert_cond= "$sss_value" = "$ps_value";
+source include/assert.inc;
+
+let $sss_value= query_get_value(SHOW SLAVE STATUS, Last_SQL_Error, 1);
+let $ps_value= query_get_value(select Last_Error_Message from performance_schema.replication_applier_status_by_worker, Last_Error_Message, 1);
+let $assert_text= Value returned by SSS and PS table for Last_Error_Message should both be empty.;
+let $assert_cond= "$sss_value" = "$ps_value";
+source include/assert.inc;
+
+let $ps_value= query_get_value(select Last_Error_Timestamp from performance_schema.replication_applier_status_by_worker, Last_Error_Timestamp, 1);
+let $assert_text= Value returned by PS table for Last_Error_Timestamp should be 0000-00-00 00:00:00.;
+let $assert_cond= "$ps_value" = "0000-00-00 00:00:00";
+source include/assert.inc;
+
+--connection master
+sleep 1;
+--connection slave
+let $ps_value= query_get_value(select worker_idle_time from performance_schema.replication_applier_status_by_worker, worker_idle_time, 1);
+let $assert_text= Value returned by PS table for worker_idle_time should be >= 1;
+let $assert_cond= "$ps_value" >= "1";
+source include/assert.inc;
+
+--connection master
+DROP TABLE t1;
+--save_master_pos
+
+--connection slave
+--sync_with_master 0,'slave1'
+
+STOP SLAVE 'slave1';
+--source include/wait_for_slave_to_stop.inc
+RESET SLAVE ALL;
+SET default_master_connection='';
+evalp CHANGE MASTER TO MASTER_USER='root', MASTER_HOST='127.0.0.1',MASTER_PORT=$MASTER_MYPORT;
+--source include/start_slave.inc
+
+--echo
+--echo # Introduce an error in the worker thread and check for the correctness
+--echo # of error number, message and timestamp fields.
+--echo
+
+# Cause an error in Worker thread.
+# 1) Create a table 't' at master, replicate at slave.
+# 2) Drop table 't' at slave only.
+# 3) Insert a value in table 't' on master and replicate on slave.
+# Since slave doesnt have table 't' anymore, worker thread will report an error.
+
+--connection master
+use test;
+create table t(a int primary key);
+sync_slave_with_master;
+drop table t;
+--connection master
+insert into t values(1);
+--connection slave
+let $slave_sql_errno=1146;
+source include/wait_for_slave_sql_error.inc;
+
+--echo
+--echo # Extract the error related fields from SSS and PS table and compare
+--echo # them for correctness.
+--echo
+
+let $sss_value= query_get_value(SHOW SLAVE STATUS, Last_SQL_Errno, 1);
+let $ps_value= query_get_value(select Last_Error_Number from performance_schema.replication_applier_status_by_worker, Last_Error_Number, 1);
+let $assert_text= Value returned by SSS and PS table for Last_Error_Number should be same.;
+let $assert_cond= "$sss_value" = "$ps_value";
+source include/assert.inc;
+
+--disable_query_log
+--replace_regex /master-bin.[0-9]+/FILENAME/ /end_log_pos [0-9]+/end_log_pos POSITION/
+select Last_Error_Message from performance_schema.replication_applier_status_by_worker;
+--enable_query_log
+
+--echo
+--echo # Verify that the error fields are preserved after STOP SLAVE.
+--echo
+
+--echo
+--echo # 1. Verify that thread_id changes to NULL and service_state to "off" on
+--echo # STOP SLAVE.
+--echo
+
+let $ps_value= query_get_value(select thread_id from performance_schema.replication_applier_status_by_worker, thread_id, 1);
+let $assert_text= After STOP SLAVE, thread_id should be NULL;
+let $assert_cond= "$ps_value" = "NULL";
+source include/assert.inc;
+
+let $ps_value= query_get_value(select service_state from performance_schema.replication_applier_status_by_worker, service_state, 1);
+let $assert_text= So, Service_State after STOP SLAVE should be "OFF".;
+let $assert_cond= "$ps_value"= "OFF";
+source include/assert.inc;
+
+--echo
+--echo # 2. Extract the worker_id and the error related fields from SSS and PS
+--echo # table and compare them. These fields should preserve their values.
+--echo
+
+let $sss_value= query_get_value(SHOW SLAVE STATUS, Last_SQL_Errno, 1);
+let $ps_value= query_get_value(select Last_Error_Number from performance_schema.replication_applier_status_by_worker, Last_Error_Number, 1);
+let $assert_text= Value returned by SSS and PS table for Last_Error_Number should be same.;
+let $assert_cond= "$sss_value" = "$ps_value";
+source include/assert.inc;
+
+--disable_query_log
+--replace_regex /master-bin.[0-9]+/FILENAME/ /end_log_pos [0-9]+/end_log_pos POSITION/
+select Last_Error_Message from performance_schema.replication_applier_status_by_worker;
+--enable_query_log
+
+# The timestamp format is slightly different in SSS and PS.
+# SSS => YYMMDD HH:MM:SS
+# PS => YYYY-MM-DD HH:MM:SS
+# To match the two, we get rid of hyphons from PS output and first two digits
+# the year field so that it can be matched directly.
+
+#--- TODO: Can we include Last_SQL_Error_Timestamp as part of SSS
+
+#let $sss_value= query_get_value(SHOW SLAVE STATUS, Last_SQL_Error_Timestamp, 1);
+#let $ps_value= query_get_value(select Last_Error_Timestamp from performance_schema.replication_applier_status_by_worker, Last_Error_Timestamp, 1);
+#let $ps_value_without_hyphons= `SELECT REPLACE("$ps_value", '-', '')`;
+#let $ps_value_in_sss_format= `select substring("$ps_value_without_hyphons", 3)`;
+#let $assert_text= Value returned by SSS and PS table for Last_Error_Timestamp should be same.;
+#let $assert_cond= "$sss_value" = "$ps_value_in_sss_format";
+#source include/assert.inc;
+
+--source include/stop_slave.inc
+RESET SLAVE;
+--connection master
+DROP TABLE t;
+RESET MASTER;
+
+--echo
+--echo # Verify that number of rows in 'replication_applier_status_by_worker' table match with
+--echo # number of slave_parallel_workers.
+--echo
+
+--connection slave
+SET @@global.slave_parallel_workers=4;
+--source include/start_slave.inc
+--let $assert_text= On slave, the table should return 4 rows.
+--let $assert_cond= count(*) = 4 from performance_schema.replication_applier_status_by_worker
+--source include/assert.inc
+--source include/stop_slave.inc
+
+--echo
+--echo # Cleanup.
+--echo
+
+set @@global.slave_parallel_workers= @save_slave_parallel_workers;
+set @@global.slave_transaction_retries= @save_slave_transaction_retries;
+source include/start_slave.inc;
+
+source include/rpl_end.inc;
diff --git a/mysql-test/suite/rpl/t/rpl_perfschema_connect_config.test b/mysql-test/suite/rpl/t/rpl_perfschema_connect_config.test
new file mode 100644
index 00000000..7b2bf8d5
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_perfschema_connect_config.test
@@ -0,0 +1,331 @@
+# ==== Purpose ====
+#
+# This test script serves as the functionality testing for the table
+# performance_schema.replication_connection_configuration. Test for ddl and dml
+# operations is a part of the perfschema suite. The ddl/dml tests are named:
+# 1) ddl_replication_connection_configuration.test and
+# 2) dml_replication_connection_configuration.test.
+#
+# This test script does the following:
+
+# - On master, the table returns an empty set.
+# - We perform all other testing on connection "slave". So, the below points
+# are checked on slave only.
+# - Verify that SELECT works for every field in the table.
+# - The SELECT per field produces an output similar to the corresponding field
+# in SHOW SLAVE STATUS(SSS), if there is one.
+# - If there is no matching field in SSS, we resort to other method of testing
+# those fields.
+#
+# The follwing scenarios are tested:
+#
+# - Test each field on a fresh replication setup.
+# - Change configuration parameters using CHANGE MASTER TO and verify that
+# these changes are seen in SELECTs from PS table.
+# - Verify that, the change in values are correctly shown by the table.
+# - Verify different values for MASTER_USE_GTID are present in table.
+# - Verify IGNORE_SERVER_IDS, DO_DOMAIN_IDS and IGNORE_DOMAIN_IDS
+#
+# ==== Related Worklog ====
+#
+# MDEV-16437: merge 5.7 P_S replication instrumentation and tables
+#
+
+source include/have_ssl_communication.inc;
+source include/have_binlog_format_mixed.inc;
+source include/have_perfschema.inc;
+source include/master-slave.inc;
+
+--let $assert_text= On master, the table should return an empty set.
+--let $assert_cond= count(*) = 0 from performance_schema.replication_connection_configuration
+--source include/rpl_assert.inc
+
+--connection slave
+
+--echo
+--echo # Verify that SELECT works for every field and produces an output
+--echo # similar to the corresponding field in SHOW SLAVE STATUS(SSS).
+--echo
+
+let $sss_value= query_get_value(SHOW SLAVE STATUS, Master_Host, 1);
+let $ps_value= query_get_value(select Host from performance_schema.replication_connection_configuration, Host, 1);
+let $assert_text= Value returned by SSS and PS table for Host should be same.;
+let $assert_cond= "$sss_value" = "$ps_value";
+source include/assert.inc;
+
+let $sss_value= query_get_value(SHOW SLAVE STATUS, Master_Port, 1);
+let $ps_value= query_get_value(select Port from performance_schema.replication_connection_configuration, Port, 1);
+let $assert_text= Value returned by SSS and PS table for Port should be same.;
+let $assert_cond= "$sss_value" = "$ps_value";
+source include/assert.inc;
+
+let $sss_value= query_get_value(SHOW SLAVE STATUS, Master_User, 1);
+let $ps_value= query_get_value(select User from performance_schema.replication_connection_configuration, User, 1);
+let $assert_text= Value returned by SSS and PS table for User should be same.;
+let $assert_cond= "$sss_value" = "$ps_value";
+source include/assert.inc;
+
+let $sss_value= query_get_value(SHOW SLAVE STATUS, Using_Gtid, 1);
+let $ps_value= query_get_value(select Using_Gtid from performance_schema.replication_connection_configuration, Using_Gtid, 1);
+let $assert_text= Value returned by SSS and PS table for Using_Gtid should be same.;
+let $assert_cond= "$sss_value" = "$ps_value";
+source include/assert.inc;
+
+let $sss_value= query_get_value(SHOW SLAVE STATUS, Master_SSL_Allowed, 1);
+let $ps_value= query_get_value(select SSL_Allowed from performance_schema.replication_connection_configuration, SSL_Allowed, 1);
+let $assert_text= Value returned by SSS and PS table for SSL_Allowed should be same.;
+let $assert_cond= "$sss_value" = "$ps_value";
+source include/assert.inc;
+
+let $sss_value= query_get_value(SHOW SLAVE STATUS, Master_SSL_CA_File, 1);
+let $ps_value= query_get_value(select SSL_CA_File from performance_schema.replication_connection_configuration, SSL_CA_File, 1);
+let $assert_text= Value returned by SSS and PS table for SSL_CA_File should be same.;
+let $assert_cond= "$sss_value" = "$ps_value";
+source include/assert.inc;
+
+let $sss_value= query_get_value(SHOW SLAVE STATUS, Master_SSL_CA_Path, 1);
+let $ps_value= query_get_value(select SSL_CA_Path from performance_schema.replication_connection_configuration, SSL_CA_Path, 1);
+let $assert_text= Value returned by SSS and PS table for SSL_CA_Path should be same.;
+let $assert_cond= "$sss_value" = "$ps_value";
+source include/assert.inc;
+
+let $sss_value= query_get_value(SHOW SLAVE STATUS, Master_SSL_Cert, 1);
+let $ps_value= query_get_value(select SSL_Certificate from performance_schema.replication_connection_configuration, SSL_Certificate, 1);
+let $assert_text= Value returned by SSS and PS table for SSL_Certificate should be same.;
+let $assert_cond= "$sss_value" = "$ps_value";
+source include/assert.inc;
+
+let $sss_value= query_get_value(SHOW SLAVE STATUS, Master_SSL_Cipher, 1);
+let $ps_value= query_get_value(select SSL_Cipher from performance_schema.replication_connection_configuration, SSL_Cipher, 1);
+let $assert_text= Value returned by SSS and PS table for SSL_Cipher should be same.;
+let $assert_cond= "$sss_value" = "$ps_value";
+source include/assert.inc;
+
+let $sss_value= query_get_value(SHOW SLAVE STATUS, Master_SSL_Key, 1);
+let $ps_value= query_get_value(select SSL_Key from performance_schema.replication_connection_configuration, SSL_Key, 1);
+let $assert_text= Value returned by SSS and PS table for SSL_Key should be same.;
+let $assert_cond= "$sss_value" = "$ps_value";
+source include/assert.inc;
+
+let $sss_value= query_get_value(SHOW SLAVE STATUS, Master_SSL_Verify_Server_Cert, 1);
+let $ps_value= query_get_value(select SSL_Verify_Server_Certificate from performance_schema.replication_connection_configuration, SSL_Verify_Server_Certificate, 1);
+let $assert_text= Value returned by SSS and PS table for SSL_Verify_Server_Certificate should be same.;
+let $assert_cond= "$sss_value" = "$ps_value";
+source include/assert.inc;
+
+let $sss_value= query_get_value(SHOW SLAVE STATUS, Master_SSL_Crl, 1);
+let $ps_value= query_get_value(select SSL_Crl_File from performance_schema.replication_connection_configuration, SSL_Crl_File, 1);
+let $assert_text= Value returned by SSS and PS table for SSL_Crl_File should be same.;
+let $assert_cond= "$sss_value" = "$ps_value";
+source include/assert.inc;
+
+let $sss_value= query_get_value(SHOW SLAVE STATUS, Master_SSL_Crlpath, 1);
+let $ps_value= query_get_value(select SSL_Crl_Path from performance_schema.replication_connection_configuration, SSL_Crl_Path, 1);
+let $assert_text= Value returned by SSS and PS table for SSL_Crl_Path should be same.;
+let $assert_cond= "$sss_value" = "$ps_value";
+source include/assert.inc;
+
+let $sss_value= query_get_value(SHOW SLAVE STATUS, Connect_Retry, 1);
+let $ps_value= query_get_value(select Connection_Retry_Interval from performance_schema.replication_connection_configuration, Connection_Retry_Interval, 1);
+let $assert_text= Value returned by SSS and PS table for Connection_Retry_Interval should be same.;
+let $assert_cond= "$sss_value" = "$ps_value";
+source include/assert.inc;
+
+let $ps_value= query_get_value(select Connection_Retry_Count from performance_schema.replication_connection_configuration, Connection_Retry_Count, 1);
+let $assert_text= Value returned by PS table for Connection_Retry_Count should be 10.; # master-retry-count=10, as part of default my.cnf used by MTR
+let $assert_cond= "$ps_value" = 10;
+source include/assert.inc;
+
+--echo
+--echo # Heartbeat_Interval is part of I_S and P_S. We will compare the
+--echo # two to make sure both match.
+--echo
+
+let $is_value= query_get_value(select Variable_Value from information_schema.GLOBAL_STATUS where variable_name= 'Slave_heartbeat_period', Variable_Value, 1);
+let $ps_value= query_get_value(select Heartbeat_Interval from performance_schema.replication_connection_configuration, Heartbeat_Interval, 1);
+let $assert_text= Value returned by IS and PS table for Heartbeat_Interval should be same.;
+let $assert_cond= $is_value = $ps_value;
+source include/assert.inc;
+
+--echo
+--echo # Change configuration parameters and verify that these changes
+--echo # are shown correctly by SELECTs from PS table.
+--echo
+
+# create a user for replication that requires ssl encryption
+--connection master
+create user replssl@localhost;
+grant replication slave on *.* to replssl@localhost require ssl;
+--source include/sync_slave_sql_with_master.inc
+
+# Setup slave to use SSL for connection to master
+--source include/stop_slave.inc
+replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR;
+replace_column 2 ####;
+eval change master to
+ master_user= 'replssl',
+ master_password= '',
+ master_ssl= 1,
+ master_ssl_ca= '$MYSQL_TEST_DIR/std_data/cacert.pem',
+ master_ssl_cert= '$MYSQL_TEST_DIR/std_data/client-cert.pem',
+ master_ssl_key= '$MYSQL_TEST_DIR/std_data/client-key.pem';
+--source include/start_slave.inc
+
+--connection slave
+--echo
+--echo # Checking SSL parameters, they were empty in tests done in the
+--echo # previous section.
+--echo
+
+let $sss_value= query_get_value(SHOW SLAVE STATUS, Master_SSL_Allowed, 1);
+let $ps_value= query_get_value(select SSL_Allowed from performance_schema.replication_connection_configuration, SSL_Allowed, 1);
+let $assert_text= Value returned by SSS and PS table for SSL_Allowed should be same.;
+let $assert_cond= "$sss_value" = "$ps_value";
+source include/assert.inc;
+
+let $sss_value= query_get_value(SHOW SLAVE STATUS, Master_SSL_CA_File, 1);
+let $ps_value= query_get_value(select SSL_CA_File from performance_schema.replication_connection_configuration, SSL_CA_File, 1);
+let $assert_text= Value returned by SSS and PS table for SSL_CA_File should be same.;
+let $assert_cond= "$sss_value" = "$ps_value";
+source include/assert.inc;
+
+let $sss_value= query_get_value(SHOW SLAVE STATUS, Master_SSL_CA_Path, 1);
+let $ps_value= query_get_value(select SSL_CA_Path from performance_schema.replication_connection_configuration, SSL_CA_Path, 1);
+let $assert_text= Value returned by SSS and PS table for SSL_CA_Path should be same.;
+let $assert_cond= "$sss_value" = "$ps_value";
+source include/assert.inc;
+
+let $sss_value= query_get_value(SHOW SLAVE STATUS, Master_SSL_Cert, 1);
+let $ps_value= query_get_value(select SSL_Certificate from performance_schema.replication_connection_configuration, SSL_Certificate, 1);
+let $assert_text= Value returned by SSS and PS table for SSL_Certificate should be same.;
+let $assert_cond= "$sss_value" = "$ps_value";
+source include/assert.inc;
+
+let $sss_value= query_get_value(SHOW SLAVE STATUS, Master_SSL_Cipher, 1);
+let $ps_value= query_get_value(select SSL_Cipher from performance_schema.replication_connection_configuration, SSL_Cipher, 1);
+let $assert_text= Value returned by SSS and PS table for SSL_Cipher should be same.;
+let $assert_cond= "$sss_value" = "$ps_value";
+source include/assert.inc;
+
+let $sss_value= query_get_value(SHOW SLAVE STATUS, Master_SSL_Key, 1);
+let $ps_value= query_get_value(select SSL_Key from performance_schema.replication_connection_configuration, SSL_Key, 1);
+let $assert_text= Value returned by SSS and PS table for SSL_Key should be same.;
+let $assert_cond= "$sss_value" = "$ps_value";
+source include/assert.inc;
+
+let $sss_value= query_get_value(SHOW SLAVE STATUS, Master_SSL_Verify_Server_Cert, 1);
+let $ps_value= query_get_value(select SSL_Verify_Server_Certificate from performance_schema.replication_connection_configuration, SSL_Verify_Server_Certificate, 1);
+let $assert_text= Value returned by SSS and PS table for SSL_Verify_Server_Certificate should be same.;
+let $assert_cond= "$sss_value" = "$ps_value";
+source include/assert.inc;
+
+--connection master
+drop user replssl@localhost;
+--sync_slave_with_master
+--source include/stop_slave.inc
+
+CHANGE MASTER TO
+ master_host= '127.0.0.1',
+ master_user= 'root',
+ master_password= '',
+ master_ssl_ca= '',
+ master_ssl_cert= '',
+ master_ssl_key= '',
+ master_ssl_verify_server_cert=0,
+ master_ssl=0,
+ master_use_gtid=no;
+--source include/start_slave.inc
+
+--echo
+--echo # Test with different MASTER_USE_GTID values
+--echo
+
+--echo
+--echo # 1) Test for MASTER_USE_GTID=NO
+--echo
+--source include/stop_slave.inc
+replace_column 2 ####;
+change master to
+ master_user = 'root',
+ master_use_gtid = NO;
+
+let $sss_value= query_get_value(SHOW SLAVE STATUS, Using_Gtid, 1);
+let $ps_value= query_get_value(select Using_Gtid from performance_schema.replication_connection_configuration, Using_Gtid, 1);
+let $assert_text= Value returned by SSS and PS table for Using_Gtid should be same.;
+let $assert_cond= "$sss_value" = "$ps_value";
+source include/assert.inc;
+
+--echo
+--echo # 2) Test for Auto_position= CURRENT_POS.
+--echo
+replace_column 2 ####;
+change master to
+ master_user = 'root',
+ master_use_gtid= CURRENT_POS;
+
+let $sss_value= query_get_value(SHOW SLAVE STATUS, Using_Gtid, 1);
+let $ps_value= query_get_value(select Using_Gtid from performance_schema.replication_connection_configuration, Using_Gtid, 1);
+let $assert_text= Value returned by SSS and PS table for Using_Gtid should be same.;
+let $assert_cond= "$sss_value" = "$ps_value";
+source include/assert.inc;
+
+--echo
+--echo # 3) Test for Auto_position= SLAVE_POS
+--echo
+replace_column 2 ####;
+change master to
+ master_user = 'root',
+ master_use_gtid= SLAVE_POS;
+let $sss_value= query_get_value(SHOW SLAVE STATUS, Using_Gtid, 1);
+let $ps_value= query_get_value(select Using_Gtid from performance_schema.replication_connection_configuration, Using_Gtid, 1);
+let $assert_text= Value returned by SSS and PS table for Using_Gtid should be same.;
+let $assert_cond= "$sss_value" = "$ps_value";
+source include/assert.inc;
+
+--echo
+--echo # Test INOGRE_SERVER_IDS
+--echo
+
+--echo
+--echo # 1) Test for IGNORE_SERVER_IDS= (10, 100);
+--echo
+
+--connection slave
+change master to IGNORE_SERVER_IDS= (10, 100);
+let $sss_value= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Server_Ids, 1);
+let $ps_value= query_get_value(select Ignore_Server_Ids from performance_schema.replication_connection_configuration, Ignore_Server_Ids, 1);
+let $assert_text= Value returned by SSS and PS table for Ignore_server_ids should be same.;
+let $assert_cond= "$sss_value" = "$ps_value";
+source include/assert.inc;
+CHANGE MASTER TO IGNORE_SERVER_IDS=();
+
+--echo
+--echo # 2) Test for IGNORE_DOMAIN_IDS(2)
+--echo
+
+CHANGE MASTER TO IGNORE_DOMAIN_IDS=(2), MASTER_USE_GTID=slave_pos;
+--source include/start_slave.inc
+let $sss_value= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Domain_Ids, 1);
+let $ps_value= query_get_value(select Repl_Ignore_Domain_Ids from performance_schema.replication_connection_configuration, Repl_Ignore_Domain_Ids, 1);
+let $assert_text= Value returned by SSS and PS table for Replicate_Ignore_Domain_Ids should be same.;
+let $assert_cond= "$sss_value" = "$ps_value";
+source include/assert.inc;
+--source include/stop_slave.inc
+
+--echo
+--echo # 3) Test for DO_DOMAIN_IDS(1)
+--echo
+
+CHANGE MASTER TO DO_DOMAIN_IDS=(1), IGNORE_DOMAIN_IDS=(), MASTER_USE_GTID=slave_pos;
+--source include/start_slave.inc
+let $sss_value= query_get_value(SHOW SLAVE STATUS, Replicate_Do_Domain_Ids, 1);
+let $ps_value= query_get_value(select Repl_Do_Domain_Ids from performance_schema.replication_connection_configuration, Repl_Do_Domain_Ids, 1);
+let $assert_text= Value returned by SSS and PS table for Replicate_Do_Domain_Ids should be same.;
+let $assert_cond= "$sss_value" = "$ps_value";
+source include/assert.inc;
+--source include/stop_slave.inc
+
+CHANGE MASTER TO DO_DOMAIN_IDS=(), IGNORE_DOMAIN_IDS=();
+--source include/start_slave.inc
+
+source include/rpl_end.inc;
diff --git a/mysql-test/suite/rpl/t/rpl_plugin_load.test b/mysql-test/suite/rpl/t/rpl_plugin_load.test
new file mode 100644
index 00000000..c319479a
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_plugin_load.test
@@ -0,0 +1,59 @@
+#
+# Bug#35807 - INSTALL PLUGIN replicates row-based, but not stmt-based
+#
+# The test verifies that INSTALL PLUGIN and UNINSTALL PLUGIN
+# work with replication.
+#
+# The test tries to install and uninstall a plugin on master,
+# and verifies that it does not affect the slave,
+# and that it does not add anything to the binlog.
+
+--source include/not_embedded.inc
+--source include/have_log_bin.inc
+--source include/have_example_plugin.inc
+
+# Initialize replication.
+--source include/master-slave.inc
+--echo Verify that example engine is not installed.
+SELECT * FROM INFORMATION_SCHEMA.ENGINES WHERE ENGINE='EXAMPLE';
+--echo Get binlog position before install plugin.
+let $before_pos = query_get_value("SHOW MASTER STATUS", Position, 1);
+--echo Install example engine.
+--replace_regex /\.dll/.so/
+eval INSTALL PLUGIN example SONAME '$HA_EXAMPLE_SO';
+--echo Get binlog position after install plugin.
+let $after_pos = query_get_value("SHOW MASTER STATUS", Position, 1);
+--echo Compute the difference of the binlog positions.
+--echo Should be zero as install plugin should not be replicated.
+--disable_query_log
+eval SELECT $after_pos - $before_pos AS Delta;
+--enable_query_log
+--echo Verify that example engine is installed.
+SELECT * FROM INFORMATION_SCHEMA.ENGINES WHERE ENGINE='EXAMPLE';
+# Wait for slave to catch up with master.
+sync_slave_with_master;
+#
+ --echo Verify that example engine is not installed.
+ connection slave;
+ SELECT * FROM INFORMATION_SCHEMA.ENGINES WHERE ENGINE='EXAMPLE';
+#
+--echo Uninstall example engine.
+connection master;
+--echo Get binlog position before uninstall plugin.
+let $before_pos = query_get_value("SHOW MASTER STATUS", Position, 1);
+UNINSTALL PLUGIN example;
+--echo Get binlog position after uninstall plugin.
+let $after_pos = query_get_value("SHOW MASTER STATUS", Position, 1);
+--echo Compute the difference of the binlog positions.
+--echo Should be zero as uninstall plugin should not be replicated.
+--disable_query_log
+eval SELECT $after_pos - $before_pos AS Delta;
+--enable_query_log
+--echo Verify that example engine is not installed.
+SELECT * FROM INFORMATION_SCHEMA.ENGINES WHERE ENGINE='EXAMPLE';
+# Wait for slave to catch up with master.
+sync_slave_with_master;
+#
+# Cleanup
+--source include/rpl_end.inc
+--echo End of test
diff --git a/mysql-test/suite/rpl/t/rpl_ps.test b/mysql-test/suite/rpl/t/rpl_ps.test
new file mode 100644
index 00000000..45ab55bf
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_ps.test
@@ -0,0 +1,94 @@
+#
+# Test of replicating user variables
+#
+source include/master-slave.inc;
+
+#sync_slave_with_master;
+#reset master;
+#connection master;
+
+--disable_warnings
+drop table if exists t1;
+--enable_warnings
+
+create table t1(n char(30));
+
+prepare stmt1 from 'insert into t1 values (?)';
+set @var1= "from-master-1";
+execute stmt1 using @var1;
+set @var1= "from-master-2-'',";
+execute stmt1 using @var1;
+SELECT * FROM t1 ORDER BY n;
+
+set @var2= 'insert into t1 values (concat("from-var-", ?))';
+prepare stmt2 from @var2;
+set @var1='from-master-3';
+execute stmt2 using @var1;
+
+sync_slave_with_master;
+SELECT * FROM t1 ORDER BY n;
+
+connection master;
+
+drop table t1;
+
+sync_slave_with_master;
+stop slave;
+source include/wait_for_slave_to_stop.inc;
+# End of 4.1 tests
+
+#
+# Bug #25843 Changing default database between PREPARE and EXECUTE of statement
+# breaks binlog.
+#
+# There were actually two problems discovered by this bug:
+#
+# 1. Default (current) database is not fixed at the creation time.
+# That leads to wrong output of DATABASE() function.
+#
+# 2. Database attributes (@@collation_database) are not fixed at the creation
+# time. That leads to wrong resultset.
+#
+# Binlog breakage and Query Cache wrong output happened because of the first
+# problem.
+#
+
+--echo
+--echo ########################################################################
+--echo #
+--echo # BUG#25843: Changing default database between PREPARE and EXECUTE of
+--echo # statement breaks binlog.
+--echo #
+--echo ########################################################################
+
+###############################################################################
+
+--connection slave
+
+START SLAVE;
+
+--connection master
+
+CREATE DATABASE mysqltest1;
+CREATE TABLE t1(db_name CHAR(32), db_col_name CHAR(32));
+
+PREPARE stmt_d_1 FROM 'INSERT INTO t1 VALUES(DATABASE(), @@collation_database)';
+
+EXECUTE stmt_d_1;
+
+use mysqltest1;
+
+EXECUTE stmt_d_1;
+
+--sync_slave_with_master
+
+SELECT * FROM t1;
+
+--connection master
+
+DROP DATABASE mysqltest1;
+
+use test;
+DROP TABLE t1;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_query_cache.test b/mysql-test/suite/rpl/t/rpl_query_cache.test
new file mode 100644
index 00000000..b23f2b20
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_query_cache.test
@@ -0,0 +1,27 @@
+-- source include/have_binlog_format_row.inc
+-- source include/have_innodb.inc
+-- source include/master-slave.inc
+
+--connection slave
+SET @qtype= @@global.query_cache_type;
+SET GLOBAL query_cache_type= ON;
+SET query_cache_type= ON;
+
+--connection master
+create table t1 (i int) engine=innodb;
+insert into t1 set i=1;
+
+--sync_slave_with_master
+select * from t1;
+--connection master
+insert into t1 set i=2;
+
+--sync_slave_with_master
+select * from t1;
+select sql_no_cache * from t1;
+
+--connection master
+DROP TABLE t1;
+--sync_slave_with_master
+SET GLOBAL query_cache_type= @qtype;
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_rbr_monitor.test b/mysql-test/suite/rpl/t/rpl_rbr_monitor.test
new file mode 100644
index 00000000..2bc1f9cd
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_rbr_monitor.test
@@ -0,0 +1,76 @@
+#
+# Mdev-7409 On RBR, extend the PROCESSLIST info to include at least the name of
+# the recently used table
+# This testcase create Write_rows_log_event , Update_rows_log_event and
+# Delete_rows_log_event which is blocked on slave and we will check whether
+# whether processinfo includes table name or not.
+--source include/have_innodb.inc
+--source include/have_binlog_format_row.inc
+--source include/master-slave.inc
+--enable_connect_log
+
+--connection master
+create table t1(a int primary key) engine=innodb;
+
+--sync_slave_with_master
+--connection slave1
+begin;
+insert into t1(a) values(1);
+--connection master
+select * from t1;
+
+insert into t1(a) values(1);
+--save_master_pos
+
+--echo #monitoring write rows
+--connection slave
+
+
+let $wait_condition= SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST
+ WHERE DB = 'test' AND STATE LIKE "Write_rows_log_event::write_row(%) on table %";
+--source include/wait_condition.inc
+
+
+--echo #monitoring update rows
+--connection slave1
+rollback;
+--sync_with_master
+begin;
+select a from t1 for update;
+
+--connection master
+update t1 set a = a + 1 ;
+--save_master_pos
+
+--connection slave
+let $wait_condition= SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST
+ WHERE DB = 'test' AND STATE LIKE "Update_rows_log_event::find_row(%) on table %";
+--source include/wait_condition.inc
+
+--echo #monitoring delete rows
+--connection slave1
+rollback;
+--sync_with_master
+begin;
+select * from t1 for update;
+
+--connection master
+delete from t1;
+--save_master_pos
+
+--connection slave
+select * from t1;
+let $wait_condition= SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST
+ WHERE DB = 'test' AND STATE LIKE "Delete_rows_log_event::find_row(%) on table %";
+--source include/wait_condition.inc
+
+#CleanUp
+--connection slave1
+rollback;
+--sync_with_master
+
+--connection master
+drop table t1;
+--sync_slave_with_master
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_rbr_to_sbr.test b/mysql-test/suite/rpl/t/rpl_rbr_to_sbr.test
new file mode 100644
index 00000000..1bc20c1e
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_rbr_to_sbr.test
@@ -0,0 +1,31 @@
+-- source include/have_binlog_format_mixed.inc
+-- source include/master-slave.inc
+
+# Test that the slave temporarily switches to ROW when seeing row
+# events when it is in MIXED mode
+
+CREATE TABLE t1 (a INT, b LONG);
+INSERT INTO t1 VALUES (1,1), (2,2);
+INSERT INTO t1 VALUES (3,UUID()), (4,UUID());
+source include/show_binlog_events.inc;
+sync_slave_with_master;
+source include/show_binlog_events.inc;
+
+--exec $MYSQL_DUMP --compact --order-by-primary --skip-extended-insert --no-create-info test > $MYSQLTEST_VARDIR/tmp/rpl_rbr_to_sbr_master.sql
+--exec $MYSQL_DUMP_SLAVE --compact --order-by-primary --skip-extended-insert --no-create-info test > $MYSQLTEST_VARDIR/tmp/rpl_rbr_to_sbr_slave.sql
+
+connection master;
+DROP TABLE IF EXISTS t1;
+
+# Let's compare. Note: If they match test will pass, if they do not match
+# the test will show that the diff statement failed and not reject file
+# will be created. You will need to go to the mysql-test dir and diff
+# the files your self to see what is not matching
+
+diff_files $MYSQLTEST_VARDIR/tmp/rpl_rbr_to_sbr_master.sql $MYSQLTEST_VARDIR/tmp/rpl_rbr_to_sbr_slave.sql;
+
+# If all is good, we can remove the files
+
+--remove_file $MYSQLTEST_VARDIR/tmp/rpl_rbr_to_sbr_master.sql
+--remove_file $MYSQLTEST_VARDIR/tmp/rpl_rbr_to_sbr_slave.sql
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_read_new_relay_log_info.test b/mysql-test/suite/rpl/t/rpl_read_new_relay_log_info.test
new file mode 100644
index 00000000..350071bf
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_read_new_relay_log_info.test
@@ -0,0 +1,48 @@
+# ==== Purpose ====
+#
+# - Verify that the post-WL#344 format of relay_log.info can be parsed.
+
+--source include/master-slave.inc
+
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (1);
+DROP TABLE t1;
+--sync_slave_with_master
+
+--echo ==== Check that we can understand the new format of relay-log.info ====
+--source include/stop_slave.inc
+
+--let $master_use_gtid_option= No
+--source include/reset_slave.inc
+--let $MYSQLD_DATADIR= `select @@datadir`
+
+# the new version of relay_log.info comes in two versions: with path
+# separator '/' (most systems) and with path separator '\' (windows)
+if ($SYSTEM_PATH_SEPARATOR != /) {
+ --let $file_suffix= -win
+}
+
+# MDEV-19801 changed the default Using_Gtid to Slave_Pos which doesn't
+# automatically purge relay-log.info
+--remove_file $MYSQLD_DATADIR/relay-log.info
+--copy_file $MYSQL_TEST_DIR/std_data/new-format-relay-log$file_suffix.info $MYSQLD_DATADIR/relay-log.info
+
+--echo # Read relay-log.info
+START SLAVE IO_THREAD;
+--source include/wait_for_slave_io_to_start.inc
+--echo # Check that relay log coordinates are equal to those saved in new-format_relay-log.info
+--let $master_file= query_get_value(SHOW SLAVE STATUS, Relay_Master_Log_File, 1)
+--let $master_pos= query_get_value(SHOW SLAVE STATUS, Exec_Master_Log_Pos, 1)
+--let $relay_log_file= query_get_value(SHOW SLAVE STATUS, Relay_Log_File, 1)
+--let $relay_log_pos= query_get_value(SHOW SLAVE STATUS, Relay_Log_Pos, 1)
+--echo $master_file= $master_file, $master_pos, $relay_log_file, $relay_log_pos
+if (`SELECT "$master_file" != "" OR
+ "$master_pos" != "0" OR
+ "$relay_log_file" != "slave-relay-bin.000001" OR
+ "$relay_log_pos" != "4"`) {
+ --echo ERROR: log coordinates changed
+ --die log coordinates changed
+}
+
+--let $rpl_only_running_threads= 1
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_read_old_relay_log_info.test b/mysql-test/suite/rpl/t/rpl_read_old_relay_log_info.test
new file mode 100644
index 00000000..d2206b5b
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_read_old_relay_log_info.test
@@ -0,0 +1,48 @@
+# ==== Purpose ====
+#
+# - Verify that the pre-WL#344 format of relay_log.info can still be
+# parsed.
+
+--source include/master-slave.inc
+
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (1);
+DROP TABLE t1;
+--sync_slave_with_master
+
+--echo ==== Check that we still understand the old format of relay-log.info ====
+--source include/stop_slave.inc
+
+--let $master_use_gtid_option= No
+--source include/reset_slave.inc
+--let $MYSQLD_DATADIR= `select @@datadir`
+
+# the old version of relay_log.info comes in two versions: with path
+# separator '/' (most systems) and with path separator '\' (windows)
+if ($SYSTEM_PATH_SEPARATOR != /) {
+ --let $file_suffix= -win
+}
+# MDEV-19801 changed the default Using_Gtid to Slave_Pos which doesn't
+# automatically purge relay-log.info
+--remove_file $MYSQLD_DATADIR/relay-log.info
+--copy_file $MYSQL_TEST_DIR/std_data/old-format-relay-log$file_suffix.info $MYSQLD_DATADIR/relay-log.info
+
+--echo # Read relay-log.info
+START SLAVE IO_THREAD;
+--source include/wait_for_slave_io_to_start.inc
+--echo # Check that relay log coordinates are equal to those we saved in old-format_relay-log.info
+--let $master_file= query_get_value(SHOW SLAVE STATUS, Relay_Master_Log_File, 1)
+--let $master_pos= query_get_value(SHOW SLAVE STATUS, Exec_Master_Log_Pos, 1)
+--let $relay_log_file= query_get_value(SHOW SLAVE STATUS, Relay_Log_File, 1)
+--let $relay_log_pos= query_get_value(SHOW SLAVE STATUS, Relay_Log_Pos, 1)
+--echo $master_file= $master_file, $master_pos, $relay_log_file, $relay_log_pos
+if (`SELECT "$master_file" != "" OR
+ "$master_pos" != "0" OR
+ "$relay_log_file" != "slave-relay-bin.000001" OR
+ "$relay_log_pos" != "4"`) {
+ --echo ERROR: log coordinates changed
+ --die log coordinates changed
+}
+
+--let $rpl_only_running_threads= 1
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_read_only.test b/mysql-test/suite/rpl/t/rpl_read_only.test
new file mode 100644
index 00000000..62a8fa61
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_read_only.test
@@ -0,0 +1,157 @@
+# Test case for BUG #11733
+-- source include/have_innodb.inc
+-- source include/master-slave.inc
+
+call mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT");
+
+# Create a test and replicate it to slave
+connection master;
+create user test;
+grant all on test.* to test;
+sync_slave_with_master;
+
+# Setting the master readonly :
+# - the variable @@readonly is not replicated on the slave
+
+connect (master2,127.0.0.1,test,,test,$MASTER_MYPORT,);
+connect (slave2,127.0.0.1,test,,test,$SLAVE_MYPORT,);
+
+connection master1;
+
+create table t1(a int) engine=InnoDB;
+create table t2(a int) engine=MyISAM;
+insert into t1 values(1001);
+insert into t2 values(2001);
+
+connection master;
+set global read_only=1;
+
+connection master1;
+select @@read_only;
+select * from t1;
+select * from t2;
+
+sync_slave_with_master;
+select @@read_only;
+select * from t1;
+select * from t2;
+
+# - replication of transactions
+connection master;
+set global read_only=0;
+
+connection master1;
+BEGIN;
+
+connection master2;
+BEGIN;
+
+connection master;
+select @@read_only;
+set global read_only=1;
+
+connection master1;
+-- echo *** On SUPER USER connection ***
+insert into t1 values(1002);
+--disable_warnings
+insert into t2 values(2002);
+--enable_warnings
+
+connection master2;
+-- echo *** On regular USER connection ***
+--error ER_OPTION_PREVENTS_STATEMENT
+insert into t1 values(1003);
+--error ER_OPTION_PREVENTS_STATEMENT
+insert into t2 values(2003);
+
+connection master1;
+## works even with read_only=1, because master1 is root
+-- echo *** SUPER USER COMMIT (must succeed) ***
+COMMIT;
+
+connection master2;
+-- echo *** regular USER COMMIT (must succeed - nothing to commit) ***
+COMMIT;
+
+connection master;
+select @@read_only;
+set global read_only=0;
+
+connection master1;
+insert into t1 values(1004);
+insert into t2 values(2004);
+
+select * from t1;
+select * from t2;
+
+sync_slave_with_master;
+select * from t1;
+select * from t2;
+
+# Setting the slave readonly : replication will pass
+#
+connection slave1;
+set global read_only=1;
+
+connection slave;
+select @@read_only;
+# Make sure the replicated table is also transactional
+show create table t1;
+# Make sure the replicated table is not transactional
+show create table t2;
+
+connection master;
+insert into t1 values(1005);
+insert into t2 values(2005);
+select * from t1;
+select * from t2;
+
+sync_slave_with_master;
+connection slave;
+select * from t1;
+select * from t2;
+
+# Non root user can not write on the slave
+connection slave2;
+--error ER_OPTION_PREVENTS_STATEMENT
+insert into t1 values(1006);
+--error ER_OPTION_PREVENTS_STATEMENT
+insert into t2 values(2006);
+
+
+--echo #
+--echo # MDEV-30978: On slave XA COMMIT/XA ROLLBACK fail to return an error in read-only mode
+--echo #
+--echo # Where a read-only server permits writes through replication, it
+--echo # should not permit user connections to commit/rollback XA transactions
+--echo # prepared via replication. This test ensure this behavior is prohibited
+--echo #
+
+# Note: slave's read_only=1 is set prior to this test case
+
+connection master;
+xa start '1';
+insert into t1 values (1007);
+xa end '1';
+xa prepare '1';
+sync_slave_with_master;
+
+connection slave2;
+--error ER_OPTION_PREVENTS_STATEMENT
+xa commit '1';
+--error ER_OPTION_PREVENTS_STATEMENT
+xa rollback '1';
+
+connection master;
+xa rollback '1';
+
+## Cleanup
+connection master;
+drop user test;
+drop table t1;
+drop table t2;
+sync_slave_with_master;
+set global read_only=0;
+
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_read_only2.test b/mysql-test/suite/rpl/t/rpl_read_only2.test
new file mode 100644
index 00000000..da825c8f
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_read_only2.test
@@ -0,0 +1,30 @@
+--source include/have_binlog_format_statement.inc
+--source include/master-slave.inc
+
+--echo #
+--echo # Ensure that read-only slave logs temporary table statements under statement based
+--echo # replication. This is related to MDEV-17863.
+--echo #
+
+connection slave;
+set global read_only=1;
+
+connection master;
+
+create table t1(a int) engine=MyISAM;
+create temporary table tmp1 (a int) engine=MyISAM;
+insert into t1 values(1);
+insert into tmp1 values (2);
+insert into t1 select * from tmp1;
+insert into t1 values(3);
+select * from t1;
+analyze table t1;
+drop table t1;
+drop temporary table tmp1;
+
+sync_slave_with_master;
+--source include/show_binlog_events.inc
+set global read_only=0;
+connection master;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_relay_max_extension.test b/mysql-test/suite/rpl/t/rpl_relay_max_extension.test
new file mode 100644
index 00000000..acca2f69
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_relay_max_extension.test
@@ -0,0 +1,111 @@
+# ==== Purpose ====
+#
+# Test verifies that auto purging mechanism of relay logs works fine when the
+# file extension grows beyond 999999.
+#
+# ==== Implementation ====
+#
+# Steps:
+# 0 - In master-slave setup clear all the relay logs on the slave server.
+# 1 - Start the slave so that new relay logs starting from
+# 'slave-relay-bin.000001' are created.
+# 2 - Get the active relay-log file name by using SHOW SLAVE STATUS.
+# Shutdown the slave server.
+# 3 - Rename active relay log to '999997' in both 'relay-log.info' and
+# 'slave-relay-bin.index' files.
+# 4 - Restart the slave server by configuring 'slave_parallel_threads=1'
+# and 'max_relay_log_size=100K'.
+# 5 - Generate load on master such that few relay logs are generated on
+# slave. The relay log sequence number will change to 7 digits.
+# 6 - Sync slave with master to ensure that relay logs are applied on
+# slave. They should have been automatically purged.
+# 7 - Assert that there is no 'slave-relay-bin.999999' file in
+# 'relay-log.info'.
+#
+# ==== References ====
+#
+# MDEV-8134: The relay-log is not flushed after the slave-relay-log.999999
+# showed
+#
+
+# MDEV-27721 rpl.rpl_relay_max_extension test is not FreeBSD-compatible
+--source include/linux.inc
+--source include/have_innodb.inc
+--source include/have_binlog_format_row.inc
+--let $rpl_topology=1->2
+--source include/rpl_init.inc
+
+--connection server_2
+--source include/stop_slave.inc
+RESET SLAVE;
+--source include/start_slave.inc
+--source include/stop_slave.inc
+--let $relay_log=query_get_value(SHOW SLAVE STATUS, Relay_Log_File, 1)
+
+--echo #
+--echo # Stop slave server
+--echo #
+
+--let $datadir = `select @@datadir`
+--exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.2.expect
+--shutdown_server 10
+--source include/wait_until_disconnected.inc
+
+--exec sed -i "s/$relay_log/slave-relay-bin.999997/g" $datadir/relay-log.info
+--exec sed -i "s/$relay_log/slave-relay-bin.999997/g" $datadir/slave-relay-bin.index
+
+--echo #
+--echo # Simulate file number get close to 999997
+--echo # by renaming relay logs and modifying index/info files
+
+--move_file $datadir/$relay_log $datadir/slave-relay-bin.999997
+
+--echo #
+--echo # Restart slave server
+--echo #
+
+--exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.2.expect
+--enable_reconnect
+--source include/wait_until_connected_again.inc
+SET @save_slave_parallel_threads= @@GLOBAL.slave_parallel_threads;
+SET @save_max_relay_log_size= @@GLOBAL.max_relay_log_size;
+
+SET GLOBAL slave_parallel_threads=1;
+SET GLOBAL max_relay_log_size=100 * 1024;
+--source include/start_slave.inc
+
+--connection server_1
+create table t1 (i int, c varchar(1024));
+--echo #
+--echo # Insert some data to generate enough amount of binary logs
+--echo #
+--let $count = 1000
+--disable_query_log
+while ($count)
+{
+ eval insert into t1 values (1001 - $count, repeat('a',1000));
+ dec $count;
+}
+--enable_query_log
+--save_master_pos
+
+--connection server_2
+--sync_with_master
+
+--let $relay_log=query_get_value(SHOW SLAVE STATUS, Relay_Log_File, 1)
+
+--echo #
+--echo # Assert that 'slave-relay-bin.999999' is purged.
+--echo #
+let SEARCH_FILE=$datadir/slave-relay-bin.index;
+let SEARCH_PATTERN=slave-relay-bin.999999;
+source include/search_pattern_in_file.inc;
+
+--source include/stop_slave.inc
+SET GLOBAL slave_parallel_threads= @save_slave_parallel_threads;
+SET GLOBAL max_relay_log_size= @save_max_relay_log_size;
+--source include/start_slave.inc
+
+--connection server_1
+DROP TABLE t1;
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_relay_space_innodb.test b/mysql-test/suite/rpl/t/rpl_relay_space_innodb.test
new file mode 100644
index 00000000..ccb1424a
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_relay_space_innodb.test
@@ -0,0 +1,3 @@
+-- source include/have_innodb.inc
+let $engine_type=InnoDB;
+-- source include/rpl_sv_relay_space.test
diff --git a/mysql-test/suite/rpl/t/rpl_relay_space_myisam.test b/mysql-test/suite/rpl/t/rpl_relay_space_myisam.test
new file mode 100644
index 00000000..6aa91dbc
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_relay_space_myisam.test
@@ -0,0 +1,2 @@
+let $engine_type=MyISAM;
+-- source include/rpl_sv_relay_space.test
diff --git a/mysql-test/suite/rpl/t/rpl_relayrotate-slave.opt b/mysql-test/suite/rpl/t/rpl_relayrotate-slave.opt
new file mode 100644
index 00000000..5cdfe28d
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_relayrotate-slave.opt
@@ -0,0 +1,2 @@
+--max_relay_log_size=16384
+--log-warnings
diff --git a/mysql-test/suite/rpl/t/rpl_relayrotate.test b/mysql-test/suite/rpl/t/rpl_relayrotate.test
new file mode 100644
index 00000000..4de554d3
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_relayrotate.test
@@ -0,0 +1,18 @@
+#
+# This include file is used by more than one test suite
+# (currently rpl and binlog_encryption).
+# Please check all dependent tests after modifying it
+#
+
+#######################################################
+# Wrapper for rpl_relayrotate.test to allow multi #
+# Engines to reuse test code. By JBM 2006-02-15 #
+#######################################################
+-- source include/have_innodb.inc
+# Slow test, don't run during staging part
+-- source include/not_staging.inc
+-- source include/master-slave.inc
+
+let $engine_type=innodb;
+-- source suite/rpl/include/rpl_relayrotate.test
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_relayspace-slave.opt b/mysql-test/suite/rpl/t/rpl_relayspace-slave.opt
new file mode 100644
index 00000000..06d96aa3
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_relayspace-slave.opt
@@ -0,0 +1 @@
+--relay_log_space_limit=10
diff --git a/mysql-test/suite/rpl/t/rpl_relayspace.test b/mysql-test/suite/rpl/t/rpl_relayspace.test
new file mode 100644
index 00000000..fc33d6bc
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_relayspace.test
@@ -0,0 +1,52 @@
+# The slave is started with relay_log_space_limit=10 bytes,
+# to force the deadlock after one event.
+
+source include/master-slave.inc;
+--let $master_log_file= query_get_value(SHOW MASTER STATUS, File, 1)
+connection slave;
+--source include/stop_slave.inc
+connection master;
+# This will generate a master's binlog > 10 bytes
+create table t1 (a int);
+drop table t1;
+create table t1 (a int);
+drop table t1;
+connection slave;
+reset slave;
+start slave io_thread;
+# Give the I/O thread time to block.
+let $slave_param= Slave_IO_State;
+let $slave_param_value= Waiting for the slave SQL thread to free enough relay log space;
+source include/wait_for_slave_param.inc;
+
+# A bug caused the I/O thread to refuse stopping.
+--source include/stop_slave_io.inc
+reset slave;
+--source include/start_slave.inc
+
+# The I/O thread stops filling the relay log when it's >10b. And the
+# SQL thread cannot purge this relay log as purge is done only when
+# the SQL thread switches to another relay log, which does not exist
+# here. So we should have a deadlock. If it is not resolved
+# automatically we'll detect it with master_pos_wait that waits for
+# farther than 1Ob; it will timeout after 300 seconds (which is inline
+# with the default used for sync_slave_with_master and will protect us
+# against slow test envs); also the slave will probably not cooperate
+# to shutdown (as 2 threads are locked)
+--let $outcome= `SELECT MASTER_POS_WAIT('$master_log_file',200,300) AS mpw;`
+
+# master_pos_wait returns:
+#
+# * >= 0, the number of events the slave had to wait to advance to the
+# position
+#
+# * -1, if there was a timeout
+#
+# * NULL, if an error occurred, or the SQL thread was not started,
+# slave master info is not initialized, the arguments are incorrect
+--let $assert_text= Assert that master_pos_wait does not timeout nor it returns NULL
+--let $assert_cond= $outcome IS NOT NULL AND $outcome <> -1
+--source include/assert.inc
+
+# End of 4.1 tests
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_reopen_temp_table.test b/mysql-test/suite/rpl/t/rpl_reopen_temp_table.test
new file mode 100644
index 00000000..2396dc34
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_reopen_temp_table.test
@@ -0,0 +1,43 @@
+--source include/have_innodb.inc
+--source include/master-slave.inc
+
+# Clean up old slave's binlogs (see rpl_temporary.test for explanation).
+save_master_pos;
+connection slave;
+sync_with_master;
+reset master;
+
+--echo #
+--echo # MDEV-5535: Cannot reopen temporary table
+--echo #
+
+connection 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
+
+disable_warnings;
+DROP TABLE IF EXISTS t1, t2, t3;
+enable_warnings;
+
+CREATE TEMPORARY TABLE t1(c1 INT) ENGINE=INNODB;
+INSERT INTO t1 VALUES (1), (2), (3), (4), (5);
+
+CREATE TEMPORARY TABLE t2 SELECT A.c1 a, B.c1 b FROM t1 AS A, t1 AS B;
+
+CREATE TABLE t3 SELECT * FROM t2;
+
+SELECT COUNT(*) = 5 FROM t1;
+SELECT COUNT(*) = 25 FROM t2;
+SELECT COUNT(*) = 25 FROM t3;
+
+sync_slave_with_master;
+
+SELECT COUNT(*) = 25 FROM t3;
+
+connection master;
+DROP TABLE t1, t2, t3;
+
+sync_slave_with_master;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_replicate_do-slave.opt b/mysql-test/suite/rpl/t/rpl_replicate_do-slave.opt
new file mode 100644
index 00000000..da345474
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_replicate_do-slave.opt
@@ -0,0 +1 @@
+--replicate-do-table=test.t1
diff --git a/mysql-test/suite/rpl/t/rpl_replicate_do.test b/mysql-test/suite/rpl/t/rpl_replicate_do.test
new file mode 100644
index 00000000..66ddf2df
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_replicate_do.test
@@ -0,0 +1,65 @@
+# This test assumes we are ignoring updates on table t2, but doing
+# updates on t1
+source include/master-slave.inc;
+--disable_warnings
+drop table if exists t11;
+connection slave;
+drop table if exists t11;
+--enable_warnings
+
+create table t2 (n int);
+insert into t2 values(4);
+connection master;
+create table t2 (s char(20));
+load data infile '../../std_data/words.dat' into table t2;
+insert into t2 values('five');
+create table t1 (m int);
+insert into t1 values(15),(16),(17);
+update t1 set m=20 where m=16;
+delete from t1 where m=17;
+create table t11 select * from t1;
+sync_slave_with_master;
+select * from t1 ORDER BY m;
+select * from t2;
+--error 1146
+select * from t11;
+connection master;
+drop table if exists t1,t2,t11;
+sync_slave_with_master;
+# show slave status, just to see of it prints replicate-do-table
+let $status_items= Replicate_Do_Table;
+source include/show_slave_status.inc;
+
+# End of 4.1 tests
+
+#
+# Bug#24478 DROP TRIGGER is not caught by replicate-*-table filters
+#
+connection master;
+create table t1 (a int, b int);
+create trigger trg1 before insert on t1 for each row set new.b=2;
+create table t2 (a int, b int);
+create trigger trg2 before insert on t2 for each row set new.b=2;
+show tables;
+--replace_column 6 #
+show triggers;
+sync_slave_with_master;
+connection slave;
+show tables;
+--replace_column 6 #
+show triggers;
+connection master;
+drop trigger trg1;
+drop trigger trg2;
+--replace_column 6 #
+show triggers;
+sync_slave_with_master;
+connection slave;
+show tables;
+--replace_column 6 #
+show triggers;
+connection master;
+drop table t1;
+drop table t2;
+sync_slave_with_master;
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_replicate_ignore_db-slave.opt b/mysql-test/suite/rpl/t/rpl_replicate_ignore_db-slave.opt
new file mode 100644
index 00000000..6e3aed44
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_replicate_ignore_db-slave.opt
@@ -0,0 +1 @@
+--replicate_ignore_db=mysqltest1
diff --git a/mysql-test/suite/rpl/t/rpl_replicate_ignore_db.test b/mysql-test/suite/rpl/t/rpl_replicate_ignore_db.test
new file mode 100644
index 00000000..f1907456
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_replicate_ignore_db.test
@@ -0,0 +1,31 @@
+# see if --replicate-ignore-db works
+
+--source include/master-slave.inc
+
+--disable_warnings
+drop database if exists mysqltest1;
+drop database if exists mysqltest2;
+--enable_warnings
+create database mysqltest1;
+create database mysqltest2;
+
+use mysqltest1;
+create table t1 (a int);
+insert into t1 values(1);
+sync_slave_with_master;
+--error 1146
+select * from mysqltest1.t1;
+
+connection master;
+use mysqltest2;
+create table t1 (a int);
+insert into t1 values(1);
+sync_slave_with_master;
+select * from mysqltest2.t1;
+
+# cleanup
+connection master;
+drop database mysqltest1;
+drop database mysqltest2;
+sync_slave_with_master;
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_report-slave.opt b/mysql-test/suite/rpl/t/rpl_report-slave.opt
new file mode 100644
index 00000000..123e5c27
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_report-slave.opt
@@ -0,0 +1,2 @@
+--report-host=127.0.0.1 --report-user='my_user' --report-password='my_password' --report-port=9308
+
diff --git a/mysql-test/suite/rpl/t/rpl_report.test b/mysql-test/suite/rpl/t/rpl_report.test
new file mode 100644
index 00000000..a7344291
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_report.test
@@ -0,0 +1,22 @@
+# Verify that mysqld init time --report-{host,port,user,password} parameters
+# are SHOW-able and SELECT-able FROM INFORMATION_SCHEMA.global_variables
+
+source include/master-slave.inc;
+
+connection slave;
+select * from Information_schema.GLOBAL_VARIABLES where variable_name like 'report_host';
+select * from Information_schema.GLOBAL_VARIABLES where variable_name like 'report_port';
+select * from Information_schema.GLOBAL_VARIABLES where variable_name like 'report_user';
+select * from Information_schema.GLOBAL_VARIABLES where variable_name like 'report_password';
+query_vertical show global variables like 'report_host';
+query_vertical show global variables like 'report_port';
+query_vertical show global variables like 'report_user';
+query_vertical show global variables like 'report_password';
+
+# to demonstrate that report global variables are read-only
+error ER_INCORRECT_GLOBAL_LOCAL_VAR;
+set @@global.report_host='my.new.address.net';
+
+
+--echo end of tests
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_report_port.test b/mysql-test/suite/rpl/t/rpl_report_port.test
new file mode 100644
index 00000000..2a14d278
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_report_port.test
@@ -0,0 +1,74 @@
+#
+#BUG#13333431 : INCORRECT DEFAULT PORT IN 'SHOW SLAVE HOSTS' OUTPUT
+#
+# ==== Purpose ====
+#
+# The test show the default value printed for the slave's port number if the
+# --report-port= <some value> is not set on the slave. This is different from
+# the present scenario which show 3306 as the default value if the report-port
+# is not set on the slave.
+#
+#====Method====
+#
+# Start replication with report port set to 9000 and restart the slave.
+# In this case on doing SHOW SLAVE HOSTS on the master, we get the port number
+# of the slave to be 9000.
+# In the second case restart the slave server with report port not set. In this
+# case on doing SHOW SLAVE HOSTS on the master, we get the actual port number
+# of the slave (ie. SLAVE_PORT).
+
+source include/have_binlog_format_mixed.inc;
+source include/master-slave.inc;
+
+connection master;
+
+# Start the server with some value being passed to the report_port= <option>
+# this will be used incase we have to mask the value of the slave's port
+# number in certain situations.
+
+--let $rpl_server_number= 2
+--let $rpl_server_parameters= --report-port=9000
+--source include/rpl_restart_server.inc
+
+connection slave;
+--source include/start_slave.inc
+--let $slave_param= Slave_IO_State
+--let $slave_param_value= Waiting for master to send event
+--source include/wait_for_slave_param.inc
+
+--echo [Slave restarted with the report-port set to some value]
+connection master;
+
+# 9000 is the value of the port we should get.
+--let $report_port= query_get_value(SHOW SLAVE HOSTS, Port, 1)
+--let assert_text= The value shown for the slave's port number is user specified port number which is the value set for report-port.
+--let assert_cond= $report_port = "9000"
+--source include/assert.inc
+
+# Start the server with the report-port being passed with no value. So on SHOW SLAVE HOSTS
+# on the master the value of slave's port should be the actual value of the slave port.
+connection master;
+
+--let $rpl_server_number= 2
+--let $rpl_server_parameters=
+--source include/rpl_restart_server.inc
+
+connection slave;
+--source include/start_slave.inc
+--let $slave_param= Slave_IO_State
+--let $slave_param_value= Waiting for master to send event
+--source include/wait_for_slave_param.inc
+
+connection master;
+sync_slave_with_master;
+--echo [Slave restarted with the report-port set to the value of slave's port number]
+
+connection master;
+
+# The value reported is the actual value of the slave's port.
+--let $report_port= query_get_value(SHOW SLAVE HOSTS, Port, 1)
+--let assert_text= The default value shown for the slave's port number is the actual port number of the slave.
+--let assert_cond= $report_port = "$SLAVE_MYPORT"
+--source include/assert.inc
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_reset_slave_all_clears_filters.test b/mysql-test/suite/rpl/t/rpl_reset_slave_all_clears_filters.test
new file mode 100644
index 00000000..7c01ce16
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_reset_slave_all_clears_filters.test
@@ -0,0 +1,72 @@
+#
+# Purpose:
+# This test validates that after issuing the `SLAVE RESET ALL` command,
+# any corresponding IGNORE_DOMAIN_IDS/DO_DOMAIN_IDS and IGNORE_SERVER_IDS
+# values are cleared.
+#
+#
+# Methodology:
+# To ensure the filtering variables are properly cleared after issuing
+# SLAVE RESET ALL, we categorize different combinations of allowable input
+# into three different options, and ensure that the variables are cleared for
+# each category. The categories are as follows:
+# Category 1) DO_DOMAIN_IDS and IGNORE_SERVER_IDS specified together
+# Category 2) IGNORE_DOMAIN_IDS and IGNORE_SERVER_IDS specified together
+# Category 3) Null check - edge case with all empty lists to ensure a lack
+# of specification doesn't break anything
+#
+# To specify the values, the variables are set in `CHANGE MASTER TO`. To
+# ensure the slave state is correct, we test the domain/server id filtering
+# variable values at the following times while testing each category.
+#
+# Before CHANGE MASTER TO the filtering variables are tested to all be
+# empty.
+#
+# After CHANGE MASTER TO the variables are tested to ensure they reflect
+# those set in the CHANGE MASTER command.
+#
+# After RESET SLAVE ALL the filtering variables are tested to all be
+# empty.
+#
+
+--source include/master-slave.inc
+--source include/have_debug.inc
+
+--connection slave
+--source include/stop_slave.inc
+
+--echo #
+--echo # Category 1) DO_DOMAIN_IDS and IGNORE_SERVER_IDS specified together
+--echo #
+--let $_do_domain_ids= (1)
+--let $_ignore_domain_ids= ()
+--let $_ignore_server_ids= (3)
+--source include/rpl_reset_slave_all_check.inc
+
+--echo #
+--echo # Category 2) IGNORE_DOMAIN_IDS and IGNORE_SERVER_IDS specified together
+--echo #
+--let $_do_domain_ids= ()
+--let $_ignore_domain_ids= (2)
+--let $_ignore_server_ids= (3)
+--source include/rpl_reset_slave_all_check.inc
+
+--echo #
+--echo # Category 3) Null check - edge case with all empty lists to ensure a
+--echo # lack of specification doesn't break anything
+--echo #
+--let $_do_domain_ids= ()
+--let $_ignore_domain_ids= ()
+--let $_ignore_server_ids= ()
+--source include/rpl_reset_slave_all_check.inc
+
+
+--echo ############################
+--echo # Cleanup
+--echo ############################
+--connection slave
+--replace_result $MASTER_MYPORT MASTER_MYPORT
+eval change master to master_port=$MASTER_MYPORT, master_host='127.0.0.1', master_user='root';
+--source include/start_slave.inc
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_reset_slave_fail.test b/mysql-test/suite/rpl/t/rpl_reset_slave_fail.test
new file mode 100644
index 00000000..5c7e6676
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_reset_slave_fail.test
@@ -0,0 +1,91 @@
+###############################################################################
+# Bug#24901077: RESET SLAVE ALL DOES NOT ALWAYS RESET SLAVE
+#
+# Problem:
+# =======
+# If you have a relay log index file that has ended up with
+# some relay log files that do not exists, then RESET SLAVE
+# ALL is not enough to get back to a clean state.
+###############################################################################
+# Remove all slave-relay-bin.0* files (do not remove slave-relay-bin.index)
+# During server restart rli initialization will fail as there are no
+# relay logs. In case of bug RESET SLAVE will not do the required clean up
+# as rli is not inited and subsequent START SLAVE will fail.
+# Disable "Warning 1612 Being purged log ./slave-relay-bin.0* was not found"
+# because it is different on Unix and Windows systems.
+
+--source include/have_binlog_format_mixed.inc
+--source include/master-slave.inc
+
+--connection master
+CREATE TABLE t1 (c1 INT);
+INSERT INTO t1 (c1) VALUES (1);
+--sync_slave_with_master
+
+--connection slave
+--source include/stop_slave_sql.inc
+--let $MYSQLD_SLAVE_DATADIR= `select @@datadir`
+
+--connection master
+# Generate more relay logs on slave.
+FLUSH LOGS;
+FLUSH LOGS;
+INSERT INTO t1 (c1) VALUES (2);
+
+--source include/sync_slave_io_with_master.inc
+call mtr.add_suppression("File '.*slave-relay-bin.");
+call mtr.add_suppression("Could not open log file");
+call mtr.add_suppression("Failed to open the relay log");
+call mtr.add_suppression("Failed to initialize the master info structure");
+
+# Stop slave
+--let $rpl_server_number= 2
+--source include/rpl_stop_server.inc
+
+# Delete file(s)
+--echo # Removing $remove_pattern file(s)
+--let $remove_pattern= slave-relay-bin.0*
+--remove_files_wildcard $MYSQLD_SLAVE_DATADIR $remove_pattern
+
+# Start slave
+--let $rpl_server_number= 2
+--source include/rpl_start_server.inc
+
+# Start slave must fail because of the removed file(s).
+--error ER_MASTER_INFO
+START SLAVE;
+
+# Try a second time, it must fail again.
+--error ER_MASTER_INFO
+START SLAVE;
+
+# Retrieve master executed position before reset slave.
+--let $master_exec_file= query_get_value("SHOW SLAVE STATUS", Relay_Master_Log_File, 1)
+--let $master_exec_pos= query_get_value("SHOW SLAVE STATUS", Exec_Master_Log_Pos, 1)
+
+# Reset slave.
+# Disable "Warning 1612 Being purged log ./slave-relay-bin.0* was not found"
+# because it is different on Unix and Windows systems.
+--disable_warnings
+--source include/reset_slave.inc
+--enable_warnings
+DROP TABLE t1;
+--replace_result $master_exec_file MASTER_LOG_FILE $master_exec_pos MASTER_LOG_POS
+--eval START SLAVE UNTIL MASTER_LOG_FILE= '$master_exec_file', MASTER_LOG_POS= $master_exec_pos;
+--source include/wait_for_slave_sql_to_stop.inc
+--source include/stop_slave_io.inc
+
+# Start slave.
+--source include/start_slave.inc
+
+--connection master
+--sync_slave_with_master
+# Check consistency.
+--let $diff_tables= master:t1, slave:t1
+--source include/diff_tables.inc
+
+# Cleanup
+--connection master
+DROP TABLE t1;
+--sync_slave_with_master
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_rewrite_db_sys_vars-slave.opt b/mysql-test/suite/rpl/t/rpl_rewrite_db_sys_vars-slave.opt
new file mode 100644
index 00000000..5a8f8233
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_rewrite_db_sys_vars-slave.opt
@@ -0,0 +1,2 @@
+"--replicate-rewrite-db=primary_db1->replica_db1"
+"--replicate-rewrite-db=x->y"
diff --git a/mysql-test/suite/rpl/t/rpl_rewrite_db_sys_vars.test b/mysql-test/suite/rpl/t/rpl_rewrite_db_sys_vars.test
new file mode 100644
index 00000000..b06899bb
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_rewrite_db_sys_vars.test
@@ -0,0 +1,163 @@
+-- source include/have_binlog_format_mixed.inc
+-- source include/master-slave.inc
+
+# Testing rpl option replicate_rewrite_db
+
+--echo #
+--echo # MDEV-15530 Variable replicate_rewrite_db cannot be found
+--echo # in "show global variables"
+--echo #
+
+--echo # Create DBs and verify that slave has to be stopped before setting sys var
+
+connection slave;
+--let $rpl_server_id= `select @@session.server_id`
+select @@session.server_id;
+
+# These DBs will be rewrited from opt file
+create database replica_db1;
+create database y;
+# This DB will be rewrited from test case
+create database test_replica;
+SELECT @@GLOBAL.replicate_rewrite_db;
+let $rewrite_db_sss= query_get_value(SHOW SLAVE STATUS, Replicate_Rewrite_DB, 1);
+--echo # Ensuring SHOW SLAVE STATUS produces correct value for Replicate_Rewrite_DB...
+if (`SELECT strcmp(@@global.replicate_rewrite_db, "$rewrite_db_sss") != 0`)
+{
+ die SHOW SLAVE STATUS Replicate_Rewrite_DB value $rewrite_db_sss does not match variable @@GLOBAL.replicate_rewrite_db;
+}
+--echo # ...success
+
+
+--echo # Create DBs and tables on primary
+connection master;
+--enable_warnings
+create database primary_db1;
+create database x;
+use primary_db1;
+create table my_table (t int);
+insert into my_table values (2),(4);
+use x;
+create table my_table (t int);
+insert into my_table values (654),(532);
+--source include/save_master_gtid.inc
+
+--echo # Check replica
+--connection slave
+--source include/sync_with_master_gtid.inc
+--let $diff_tables=master:primary_db1.my_table,slave:replica_db1.my_table
+--source include/diff_tables.inc
+--let $diff_tables=master:x.my_table,slave:y.my_table
+--source include/diff_tables.inc
+SELECT @@GLOBAL.replicate_rewrite_db;
+show tables from replica_db1;
+select * from replica_db1.my_table;
+show tables from y;
+select * from y.my_table;
+
+--echo # Set replica sys var replicate_rewrite_db
+connection slave;
+--error ER_SLAVE_MUST_STOP
+SET @@GLOBAL.replicate_rewrite_db="test_master->test_replica";
+source include/stop_slave.inc;
+SET @save_replicate_rewrite_db = @@GLOBAL.replicate_rewrite_db;
+SELECT @@GLOBAL.replicate_rewrite_db;
+SET @@GLOBAL.replicate_rewrite_db="test_master->test_replica";
+SELECT @@GLOBAL.replicate_rewrite_db;
+SHOW DATABASES like 'test_replica';
+source include/start_slave.inc;
+let $rewrite_db_sss= query_get_value(SHOW SLAVE STATUS, Replicate_Rewrite_DB, 1);
+--echo # Ensuring SHOW SLAVE STATUS produces correct value for Replicate_Rewrite_DB...
+if (`SELECT strcmp(@@global.replicate_rewrite_db, "$rewrite_db_sss") != 0`)
+{
+ die SHOW SLAVE STATUS Replicate_Rewrite_DB value $rewrite_db_sss does not match variable @@GLOBAL.replicate_rewrite_db;
+}
+--echo # ...success
+
+--echo # Create DB and tables on primary
+connection master;
+--enable_warnings
+create database test_master;
+use test_master;
+create table my_table (t int);
+insert into my_table values (1),(3);
+--source include/save_master_gtid.inc
+
+--echo # Ensure that the replica receives all of the primary's events without
+--echo # error
+--connection slave
+--source include/sync_with_master_gtid.inc
+let $error= query_get_value(SHOW SLAVE STATUS, Last_SQL_Error, 1);
+--echo Last_SQL_Error = $error
+let $errno= query_get_value(SHOW SLAVE STATUS, Last_SQL_Errno, 1);
+--echo Last_SQL_Errno = $errno
+
+SELECT @@GLOBAL.replicate_rewrite_db;
+SHOW tables from test_replica;
+select * from test_replica.my_table;
+
+# Additional check for tables
+--let $diff_tables=master:test_master.my_table,slave:test_replica.my_table
+--source include/diff_tables.inc
+
+--echo # Update of values on primary for DB not set in replication_rewrite_db
+connection master;
+use x;
+insert into my_table values (314);
+select * from my_table;
+--source include/save_master_gtid.inc
+
+connection slave;
+--source include/stop_slave.inc
+--source include/reset_slave.inc
+--source include/start_slave.inc
+SELECT @@GLOBAL.replicate_rewrite_db;
+--source include/sync_with_master_gtid.inc
+# This shouldn't get the new values from x DB on master
+select * from y.my_table;
+
+--echo # Dynamic updates to the replication filter should be lost after server restart
+# Old value
+connection slave;
+SELECT @@GLOBAL.replicate_rewrite_db;
+
+connection master;
+use x;
+insert into my_table values (1000);
+select * from my_table;
+--source include/save_master_gtid.inc
+
+connection slave;
+--source include/stop_slave.inc
+--source include/reset_slave.inc
+--let $rpl_server_number= 2
+--source include/rpl_restart_server.inc
+--replace_result $MASTER_MYPORT MASTER_MYPORT
+eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=$MASTER_MYPORT, MASTER_USER='root';
+
+# New value
+connection slave;
+--source include/start_slave.inc
+SELECT @@GLOBAL.replicate_rewrite_db;
+--source include/sync_with_master_gtid.inc
+# This should update values with 314 and 1000 from primary
+select * from y.my_table;
+
+--echo # Cleanup
+connection master;
+drop database test_master;
+drop database primary_db1;
+drop database x;
+--source include/save_master_gtid.inc
+
+
+--connection slave
+--source include/sync_with_master_gtid.inc
+drop database test_replica;
+drop database replica_db1;
+drop database y;
+source include/stop_slave.inc;
+source include/start_slave.inc;
+
+--source include/rpl_end.inc
+# end of 10.11 tests
diff --git a/mysql-test/suite/rpl/t/rpl_rewrt_db-slave.opt b/mysql-test/suite/rpl/t/rpl_rewrt_db-slave.opt
new file mode 100644
index 00000000..cb165442
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_rewrt_db-slave.opt
@@ -0,0 +1,6 @@
+"--replicate-rewrite-db=test->rewrite"
+"--replicate-rewrite-db=mysqltest1 -> test"
+"--replicate-rewrite-db=x -> y"
+"--replicate-rewrite-db=database_master_temp_01->database_slave_temp_01"
+"--replicate-rewrite-db=database_master_temp_02->database_slave_temp_02"
+"--replicate-rewrite-db=database_master_temp_03->database_slave_temp_03"
diff --git a/mysql-test/suite/rpl/t/rpl_rewrt_db.test b/mysql-test/suite/rpl/t/rpl_rewrt_db.test
new file mode 100644
index 00000000..aa0370c8
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_rewrt_db.test
@@ -0,0 +1,250 @@
+# TBF - difference in row level logging
+-- source include/have_binlog_format_mixed_or_statement.inc
+-- source include/master-slave.inc
+
+--connection slave
+set sql_log_bin=0;
+create database y;
+set sql_log_bin=1;
+
+--connection master
+--disable_warnings
+drop database if exists mysqltest1;
+drop database if exists x;
+--enable_warnings
+create database mysqltest1;
+set sql_log_bin=0;
+create database x;
+set sql_log_bin=1;
+
+use mysqltest1;
+create table t1 (a int);
+insert into t1 values(9);
+use x;
+create table t1 (a int);
+insert into t1 values(9);
+select * from mysqltest1.t1;
+select * from x.t1;
+sync_slave_with_master;
+#TODO no it is no empty
+show databases like 'mysqltest1'; # should be empty
+select * from test.t1;
+select * from y.t1;
+# cleanup
+connection master;
+use mysqltest1;
+drop table t1;
+drop database mysqltest1;
+sync_slave_with_master;
+
+#
+# BUG#6353:
+# Option --replicate-rewrite-db should work together with LOAD DATA INFILE
+#
+
+connection slave;
+--disable_warnings
+drop database if exists rewrite;
+--enable_warnings
+create database rewrite;
+
+connection master;
+use test;
+create table t1 (a date, b date, c date not null, d date);
+load data infile '../../std_data/loaddata1.dat' ignore into table t1 fields terminated by ',';
+load data infile '../../std_data/loaddata1.dat' into table t1 fields terminated by ',' IGNORE 2 LINES;
+sync_slave_with_master;
+
+connection slave;
+select * from rewrite.t1;
+
+connection master;
+truncate table t1;
+load data infile '../../std_data/loaddata1.dat' ignore into table t1 fields terminated by ',' LINES STARTING BY ',' (b,c,d);
+sync_slave_with_master;
+
+connection slave;
+select * from rewrite.t1;
+
+connection master;
+drop table t1;
+create table t1 (a text, b text);
+load data infile '../../std_data/loaddata2.dat' into table t1 fields terminated by ',' enclosed by '''';
+sync_slave_with_master;
+
+connection slave;
+select concat('|',a,'|'), concat('|',b,'|') from rewrite.t1;
+
+connection master;
+drop table t1;
+create table t1 (a int, b char(10));
+load data infile '../../std_data/loaddata3.dat' into table t1 fields terminated by '' enclosed by '' ignore 1 lines;
+sync_slave_with_master;
+
+connection slave;
+select * from rewrite.t1;
+
+connection master;
+truncate table t1;
+load data infile '../../std_data/loaddata4.dat' into table t1 fields terminated by '' enclosed by '' lines terminated by '' ignore 1 lines;
+sync_slave_with_master;
+
+connection slave;
+# The empty line last comes from the end line field in the file
+select * from rewrite.t1;
+
+set sql_log_bin= 0;
+drop database rewrite;
+set sql_log_bin= 1;
+
+connection master;
+set sql_log_bin= 0;
+drop table t1;
+set sql_log_bin= 1;
+
+# End of 4.1 tests
+
+--echo
+--echo ****
+--echo **** Bug #46861 Auto-closing of temporary tables broken by replicate-rewrite-db
+--echo ****
+--echo
+
+--echo ****
+--echo **** Preparing the environment
+--echo ****
+connection master;
+
+connect (con_temp_03,127.0.0.1,root,,test,$MASTER_MYPORT,);
+connect (con_temp_02,127.0.0.1,root,,test,$MASTER_MYPORT,);
+connect (con_temp_01,127.0.0.1,root,,test,$MASTER_MYPORT,);
+
+connection master;
+SET sql_log_bin= 0;
+CREATE DATABASE database_master_temp_01;
+CREATE DATABASE database_master_temp_02;
+CREATE DATABASE database_master_temp_03;
+SET sql_log_bin= 1;
+
+connection slave;
+SET sql_log_bin= 0;
+CREATE DATABASE database_slave_temp_01;
+CREATE DATABASE database_slave_temp_02;
+CREATE DATABASE database_slave_temp_03;
+SET sql_log_bin= 1;
+
+--echo
+--echo ****
+--echo **** Creating temporary tables on different databases with different connections
+--echo ****
+--echo **** con_temp_01 --> creates
+--echo **** t_01_01_temp on database_master_temp_01
+--echo ****
+--echo **** con_temp_02 --> creates
+--echo **** t_01_01_temp on database_master_temp_01
+--echo **** t_02_01_temp, t_02_02_temp on database_master_temp_02
+--echo ****
+--echo **** con_temp_02 --> creates
+--echo **** t_01_01_temp on database_master_temp_01
+--echo **** t_02_01_temp, t_02_02_temp on database_master_temp_02
+--echo **** t_03_01_temp, t_03_02_temp, t_03_03_temp on database_master_temp_03
+--echo ****
+
+connection con_temp_01;
+USE database_master_temp_01;
+CREATE TEMPORARY TABLE t_01_01_temp(a int);
+INSERT INTO t_01_01_temp VALUES(1);
+
+connection con_temp_02;
+USE database_master_temp_01;
+CREATE TEMPORARY TABLE t_01_01_temp(a int);
+INSERT INTO t_01_01_temp VALUES(1);
+USE database_master_temp_02;
+CREATE TEMPORARY TABLE t_02_01_temp(a int);
+INSERT INTO t_02_01_temp VALUES(1);
+CREATE TEMPORARY TABLE t_02_02_temp(a int);
+INSERT INTO t_02_02_temp VALUES(1);
+
+connection con_temp_03;
+USE database_master_temp_01;
+CREATE TEMPORARY TABLE t_01_01_temp(a int);
+INSERT INTO t_01_01_temp VALUES(1);
+USE database_master_temp_02;
+CREATE TEMPORARY TABLE t_02_01_temp(a int);
+INSERT INTO t_02_01_temp VALUES(1);
+CREATE TEMPORARY TABLE t_02_02_temp(a int);
+INSERT INTO t_02_02_temp VALUES(1);
+USE database_master_temp_03;
+CREATE TEMPORARY TABLE t_03_01_temp(a int);
+INSERT INTO t_03_01_temp VALUES(1);
+CREATE TEMPORARY TABLE t_03_02_temp(a int);
+INSERT INTO t_03_02_temp VALUES(1);
+CREATE TEMPORARY TABLE t_03_03_temp(a int);
+INSERT INTO t_03_03_temp VALUES(1);
+
+--echo
+--echo **** Dropping the connections
+--echo **** We want to SHOW BINLOG EVENTS, to know what was logged. But there is no
+--echo **** guarantee that logging of the terminated con1 has been done yet.a To be
+--echo **** sure that logging has been done, we use a user lock.
+--echo
+connection master;
+sync_slave_with_master;
+connection slave;
+show status like 'Slave_open_temp_tables';
+
+connection master;
+let $binlog_start= query_get_value(SHOW MASTER STATUS, Position, 1);
+connection con_temp_01;
+select get_lock("con_01",10);
+connection master;
+disconnect con_temp_01;
+select get_lock("con_01",10);
+
+connection con_temp_02;
+select get_lock("con_02",10);
+connection master;
+disconnect con_temp_02;
+select get_lock("con_02",10);
+
+connection con_temp_03;
+select get_lock("con_03",10);
+connection master;
+disconnect con_temp_03;
+select get_lock("con_03",10);
+
+--echo
+--echo **** Checking the binary log and temporary tables
+--echo
+connection master;
+sync_slave_with_master;
+connection slave;
+show status like 'Slave_open_temp_tables';
+
+connection master;
+--source include/show_binlog_events.inc
+
+--echo ****
+--echo **** Cleaning up the test case
+--echo ****
+connection master;
+SET sql_log_bin= 0;
+DROP DATABASE database_master_temp_01;
+DROP DATABASE database_master_temp_02;
+DROP DATABASE database_master_temp_03;
+DROP DATABASE x;
+SET sql_log_bin= 1;
+
+connection slave;
+SET sql_log_bin= 0;
+DROP DATABASE database_slave_temp_01;
+DROP DATABASE database_slave_temp_02;
+DROP DATABASE database_slave_temp_03;
+DROP DATABASE y;
+SET sql_log_bin= 1;
+
+connection master;
+sync_slave_with_master;
+
+# end of 5.0 tests
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_rotate_logs.cnf b/mysql-test/suite/rpl/t/rpl_rotate_logs.cnf
new file mode 100644
index 00000000..7e676dc2
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_rotate_logs.cnf
@@ -0,0 +1,6 @@
+!include ../rpl_1slave_base.cnf
+
+[mysqld.1]
+max_binlog_size=4096
+
+
diff --git a/mysql-test/suite/rpl/t/rpl_rotate_logs.test b/mysql-test/suite/rpl/t/rpl_rotate_logs.test
new file mode 100644
index 00000000..4dd58931
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_rotate_logs.test
@@ -0,0 +1,203 @@
+# This test uses chmod, can't be run with root permissions
+-- source include/not_as_root.inc
+
+-- source include/have_log_bin.inc
+
+#
+# Test is run with max_binlog_size=2048 to force automatic rotation of the
+# binary log
+# Tests done:
+# - Check that slaves reports correct failures if master.info has strange
+# modes/information
+# - Automatic binary log rotation
+# - Ensure that temporary tables works over flush logs and binary log
+# changes
+# - Test creating a duplicate key error and recover from it
+
+# Requires statement logging
+-- source include/have_binlog_format_mixed_or_statement.inc
+
+connect (master,localhost,root,,test,$MASTER_MYPORT,$MASTER_MYSOCK);
+connect (slave,localhost,root,,test,$SLAVE_MYPORT,$SLAVE_MYSOCK);
+
+# Reset the GTID position explicitly (since we're not using rpl_init.inc).
+SET GLOBAL gtid_slave_pos= "";
+
+# Create empty file
+let $MYSQLD_SLAVE_DATADIR= `select @@datadir`;
+write_file $MYSQLD_SLAVE_DATADIR/master.info;
+EOF
+chmod 0000 $MYSQLD_SLAVE_DATADIR/master.info;
+connection slave;
+
+CALL mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT.");
+# START SLAVE will fail because it can't read the file (mode 000)
+# (system error 13)
+--replace_result $MYSQL_TEST_DIR TESTDIR
+--error 1105,1105,29
+start slave;
+chmod 0600 $MYSQLD_SLAVE_DATADIR/master.info;
+# It will fail again because the file is empty so the slave cannot get valuable
+# info about how to connect to the master from it (failure in
+# init_strvar_from_file() in init_master_info()).
+--error 1201
+start slave;
+--replace_result $MASTER_MYPORT MASTER_PORT
+
+# CHANGE MASTER will fail because it first parses master.info before changing
+# it (so when master.info is bad, people have to use RESET SLAVE first).
+--error 1201
+eval change master to master_host='127.0.0.1',master_port=$MASTER_MYPORT, master_user='root';
+reset slave;
+--replace_result $MASTER_MYPORT MASTER_PORT
+eval change master to master_host='127.0.0.1',master_port=$MASTER_MYPORT, master_user='root';
+connection master;
+reset master;
+connection slave;
+start slave;
+--source include/wait_for_slave_to_start.inc
+connection master;
+
+#
+# Test FLUSH LOGS
+#
+create temporary table temp_table (a char(80) not null);
+insert into temp_table values ("testing temporary tables");
+create table t1 (s text);
+insert into t1 values('Could not break slave'),('Tried hard');
+sync_slave_with_master;
+let $status_items= Master_Log_File, Relay_Master_Log_File;
+source include/show_slave_status.inc;
+source include/check_slave_is_running.inc;
+select * from t1;
+connection master;
+flush logs;
+create table t2(m int not null auto_increment primary key);
+insert into t2 values (34),(67),(123);
+flush logs;
+source include/show_binary_logs.inc;
+create table t3 select * from temp_table;
+
+sync_slave_with_master;
+
+select * from t3;
+connection master;
+drop table temp_table, t3;
+
+#
+# Now lets make some duplicate key mess and see if we can recover from it
+#
+
+# First insert a value on the slave
+connection slave;
+insert into t2 values(1234);
+
+#same value on the master
+connection master;
+set insert_id=1234;
+insert into t2 values(NULL);
+connection slave;
+# 1062 = ER_DUP_ENTRY
+call mtr.add_suppression("Slave SQL.*Error .Duplicate entry .1234. for key .PRIMARY.. on query.* error.* 1062");
+--let $slave_sql_errno= 1062
+--source include/wait_for_slave_sql_error_and_skip.inc
+
+connection master;
+
+#let slave catch up
+sync_slave_with_master;
+connection master;
+purge master logs to 'master-bin.000002';
+source include/show_master_logs.inc;
+# we just tests if synonyms are accepted
+purge binary logs to 'master-bin.000002';
+source include/show_binary_logs.inc;
+--source include/wait_for_binlog_checkpoint.inc
+
+# Set the purge time 1 second after the last modify time of master-bin.000002.
+perl;
+open F, ">>".$ENV{'MYSQLTEST_VARDIR'}.'/tmp/rpl_rotate_logs.tmp' or die "Tmp file rpl_rotate_logs.tmp not found";
+my $binlogpath = $ENV{'MYSQLTEST_VARDIR'}.'/mysqld.1/data/master-bin.000002';
+my @array = stat($binlogpath);
+my $filemodifytime = $array[9];
+my @t = localtime $filemodifytime;
+my $modifytime = sprintf "%04u-%02u-%02u %02u:%02u:%02u",$t[5]+1900,$t[4]+1,$t[3],$t[2],$t[1],$t[0];
+printf F ("let \$tmpval = %s;",$modifytime);
+close F;
+EOF
+
+--source $MYSQLTEST_VARDIR/tmp/rpl_rotate_logs.tmp
+remove_file $MYSQLTEST_VARDIR/tmp/rpl_rotate_logs.tmp;
+
+--disable_result_log
+--replace_result $tmpval tmpval
+--eval SELECT @time_for_purge:=DATE_ADD('$tmpval', INTERVAL 1 SECOND)
+--enable_result_log
+
+purge master logs before (@time_for_purge);
+source include/show_binary_logs.inc;
+insert into t2 values (65);
+sync_slave_with_master;
+source include/show_slave_status.inc;
+source include/check_slave_is_running.inc;
+select * from t2;
+
+#
+# Test forcing the replication log to rotate
+#
+
+connection master;
+create temporary table temp_table (a char(80) not null);
+insert into temp_table values ("testing temporary tables part 2");
+
+# the nummber of produced logs is sensitive to whether checksum is NONE or CRC32
+# the value of 103 makes it even
+let $1=103;
+
+create table t3 (n int);
+disable_query_log;
+while ($1)
+{
+#eval means expand $ expressions
+ eval insert HIGH_PRIORITY into t3 values($1 + 4);
+ dec $1;
+}
+enable_query_log;
+select count(*) from t3 where n >= 4;
+create table t4 select * from temp_table;
+source include/show_binary_logs.inc;
+source include/show_master_status.inc;
+sync_slave_with_master;
+select * from t4;
+
+source include/show_slave_status.inc;
+source include/check_slave_is_running.inc;
+# because of concurrent insert, the table may not be up to date
+# if we do not lock
+lock tables t3 read;
+select count(*) from t3 where n >= 4;
+unlock tables;
+#clean up
+connection master;
+drop table if exists t1,t2,t3,t4;
+drop temporary table temp_table;
+sync_slave_with_master;
+
+--echo End of 4.1 tests
+
+#
+# Bug #29420: crash with show and purge binlogs
+#
+--error 1220
+show binlog events in 'non existing_binlog_file';
+purge master logs before now();
+--error 1220
+show binlog events in '';
+purge master logs before now();
+
+--echo End of 5.0 tests
+--echo #cleanup
+
+--remove_file $MYSQLD_SLAVE_DATADIR/master.info
+--source include/stop_slave.inc
+reset slave all;
diff --git a/mysql-test/suite/rpl/t/rpl_rotate_purge_deadlock-master.opt b/mysql-test/suite/rpl/t/rpl_rotate_purge_deadlock-master.opt
new file mode 100644
index 00000000..f71317fc
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_rotate_purge_deadlock-master.opt
@@ -0,0 +1 @@
+--max-binlog-size=4k --expire-logs-days=1
diff --git a/mysql-test/suite/rpl/t/rpl_rotate_purge_deadlock.test b/mysql-test/suite/rpl/t/rpl_rotate_purge_deadlock.test
new file mode 100644
index 00000000..6db4e2be
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_rotate_purge_deadlock.test
@@ -0,0 +1,96 @@
+#
+# Bug#11763573 - 56299: MUTEX DEADLOCK WITH COM_BINLOG_DUMP, BINLOG PURGE, AND PROCESSLIST/KILL
+#
+source include/have_debug_sync.inc;
+source include/have_binlog_format_row.inc;
+source include/have_innodb.inc;
+source include/master-slave.inc;
+
+#
+# Testing that execution of two concurrent INSERTing connections both
+# triggering the binlog rotation is correct even though their execution
+# is interleaved.
+# The test makes the first connection to complete the rotation part
+# and yields control to the second connection that rotates as well and
+# gets first on purging. And the fact of interleaving does not create
+# any issue.
+#
+
+connection master;
+source include/show_binary_logs.inc;
+create table t1 (f text) engine=innodb;
+SET DEBUG_SYNC = 'at_purge_logs_before_date WAIT_FOR rotated';
+SET DEBUG_SYNC = 'after_purge_logs_before_date SIGNAL continued';
+send insert into t1 set f=repeat('a', 4096);
+
+connection master1;
+
+let $wait_condition=
+ SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST
+ WHERE STATE like "debug sync point: at_purge_logs_before_date%";
+--source include/wait_condition.inc
+
+--echo *** there must be two logs in the list ***
+source include/show_binary_logs.inc;
+
+insert into t1 set f=repeat('b', 4096);
+
+--echo *** there must be three logs in the list ***
+source include/show_binary_logs.inc;
+
+SET DEBUG_SYNC = 'now SIGNAL rotated';
+SET DEBUG_SYNC = 'now WAIT_FOR continued';
+SET DEBUG_SYNC = 'RESET';
+
+# the first connection finally completes its INSERT
+connection master;
+reap;
+SET DEBUG_SYNC = 'RESET';
+
+sync_slave_with_master;
+
+
+#
+# Testing the reported deadlock involving DUMP, KILL and INSERT threads
+#
+
+connection master;
+SET DEBUG_SYNC = 'at_purge_logs_before_date WAIT_FOR rotated';
+SET DEBUG_SYNC = 'after_purge_logs_before_date SIGNAL continued';
+send insert into t1 set f=repeat('b', 4096);
+
+connection master1;
+
+# make sure INSERT reaches waiting point
+let $wait_condition=
+ SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST
+ WHERE STATE like "debug sync point: at_purge_logs_before_date%";
+--source include/wait_condition.inc
+
+# find and kill DUMP thread
+let $_tid= `select id from information_schema.processlist where command = 'Binlog Dump' limit 1`;
+--disable_query_log
+eval kill query $_tid;
+--enable_query_log
+
+#
+# Now the proof is that the new DUMP thread has executed
+# a critical section of the deadlock without any regression and is UP
+#
+let $wait_condition=
+ SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST
+ WHERE command = 'Binlog Dump' and STATE like "Master has sent all binlog to slave%";
+--source include/wait_condition.inc
+
+SET DEBUG_SYNC = 'now SIGNAL rotated';
+SET DEBUG_SYNC = 'now WAIT_FOR continued';
+SET DEBUG_SYNC = 'RESET';
+
+connection master;
+reap;
+SET DEBUG_SYNC = 'RESET';
+drop table t1;
+
+sync_slave_with_master;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_row_001.test b/mysql-test/suite/rpl/t/rpl_row_001.test
new file mode 100644
index 00000000..887c0961
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_row_001.test
@@ -0,0 +1,51 @@
+########################################################
+# By JBM 2005-02-15 Wrapped to allow reuse of test code#
+########################################################
+-- source include/have_binlog_format_row.inc
+-- source include/master-slave.inc
+
+# Test if the slave SQL thread can be more than 16K behind the slave
+# I/O thread (> IO_SIZE)
+
+# we'll use table-level locking to delay slave SQL thread
+eval CREATE TABLE t1 (n INT);
+sync_slave_with_master;
+connection master;
+RESET MASTER;
+connection slave;
+STOP SLAVE;
+--source include/reset_slave.inc
+
+connection master;
+let $1=5000;
+# Generate 16K of relay log
+disable_query_log;
+while ($1)
+{
+ eval INSERT INTO t1 VALUES($1);
+ dec $1;
+}
+enable_query_log;
+SELECT COUNT(*) FROM t1;
+save_master_pos;
+
+# Try to cause a large relay log lag on the slave by locking t1
+connection slave;
+LOCK TABLES t1 READ;
+START SLAVE;
+UNLOCK TABLES;
+sync_with_master;
+SELECT COUNT(*) FROM t1;
+
+connection master;
+DROP TABLE t1;
+CREATE TABLE t1 (n INT);
+INSERT INTO t1 VALUES(3456);
+sync_slave_with_master;
+SELECT n FROM t1;
+
+connection master;
+DROP TABLE t1;
+
+sync_slave_with_master;
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_row_4_bytes-master.opt b/mysql-test/suite/rpl/t/rpl_row_4_bytes-master.opt
new file mode 100644
index 00000000..3073fa4f
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_row_4_bytes-master.opt
@@ -0,0 +1,2 @@
+--loose-debug=d,"old_row_based_repl_4_byte_map_id_master"
+--log-bin-use-v1-row-events=1
diff --git a/mysql-test/suite/rpl/t/rpl_row_4_bytes.test b/mysql-test/suite/rpl/t/rpl_row_4_bytes.test
new file mode 100644
index 00000000..6130f749
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_row_4_bytes.test
@@ -0,0 +1,34 @@
+# This test is to make sure that slaves can read a binlog containining
+# table map ids stored in 4 bytes, even though we now store them in 6
+# bytes. This is for backward-compatibility.
+# If the slave does not detect that the master stores the table map id
+# in 4 bytes, slave will read 6 bytes, and so will read the 2 bytes of
+# flags at the place where there actually is data, so the test should
+# fail.
+
+-- source include/have_binlog_format_row.inc
+-- source include/have_debug.inc
+-- source include/master-slave.inc
+
+connection master;
+--disable_warnings
+drop database if exists mysqltest1;
+create database mysqltest1;
+--enable_warnings
+use mysqltest1;
+CREATE TABLE t1 (a char(3));
+CREATE TABLE t2 (a char(3));
+insert into t1 values("ANN");
+insert into t1 values("GUI");
+insert into t2 values("LIL");
+insert into t2 values("ABE");
+insert into t2 values("ANG");
+sync_slave_with_master;
+use mysqltest1;
+select * from t1 order by a;
+select * from t2 order by a;
+
+connection master;
+DROP DATABASE mysqltest1;
+sync_slave_with_master;
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_row_NOW.test b/mysql-test/suite/rpl/t/rpl_row_NOW.test
new file mode 100644
index 00000000..d732c6e6
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_row_NOW.test
@@ -0,0 +1,75 @@
+#############################################################################
+# Original Author: JBM #
+# Original Date: Aug/18/2005 #
+# Updated 08/30/2005 Added dumps and diff #
+#############################################################################
+#TEST: Taken and modfied from http://bugs.mysql.com/bug.php?id=12480 #
+#############################################################################
+
+# Includes
+-- source include/have_binlog_format_row.inc
+-- source include/master-slave.inc
+
+
+# Begin clean up test section
+connection master;
+--disable_warnings
+create database if not exists mysqltest1;
+DROP TABLE IF EXISTS mysqltest1.t1;
+--enable_warnings
+
+
+# Begin test section 1
+CREATE TABLE mysqltest1.t1 (n MEDIUMINT NOT NULL AUTO_INCREMENT,
+ a TIMESTAMP DEFAULT '2005-05-05 01:01:01',
+ b TIMESTAMP DEFAULT '2005-05-05 01:01:01',
+ PRIMARY KEY(n));
+delimiter |;
+CREATE FUNCTION mysqltest1.f1() RETURNS TIMESTAMP
+BEGIN
+ DECLARE v1 INT DEFAULT 300;
+ WHILE v1 > 0 DO
+ SET v1 = v1 - 1;
+ END WHILE;
+ RETURN NOW();
+END|
+delimiter ;|
+
+INSERT INTO mysqltest1.t1 VALUES(NULL,NOW(),mysqltest1.f1());
+
+delimiter |;
+CREATE TRIGGER mysqltest1.trig1 BEFORE INSERT ON mysqltest1.t1
+FOR EACH ROW BEGIN
+ SET new.b = mysqltest1.f1();
+END|
+delimiter ;|
+
+INSERT INTO mysqltest1.t1 SET n = NULL, a = now();
+
+sync_slave_with_master;
+
+connection master;
+
+--exec $MYSQL_DUMP --compact --order-by-primary --skip-extended-insert --no-create-info mysqltest1 > $MYSQLTEST_VARDIR/tmp/NOW_master.sql
+--exec $MYSQL_DUMP_SLAVE --compact --order-by-primary --skip-extended-insert --no-create-info mysqltest1 > $MYSQLTEST_VARDIR/tmp/NOW_slave.sql
+
+# lets cleanup
+DROP TABLE IF EXISTS mysqltest1.t1;
+DROP FUNCTION mysqltest1.f1;
+DROP DATABASE mysqltest1;
+
+# Lets compare. Note: If they match test will pass, if they do not match
+# the test will show that the diff statement failed and not reject file
+# will be created. You will need to go to the mysql-test dir and diff
+# the files your self to see what is not matching :-) The failed dump
+# files will be located in $MYSQLTEST_VARDIR/tmp
+
+diff_files $MYSQLTEST_VARDIR/tmp/NOW_master.sql $MYSQLTEST_VARDIR/tmp/NOW_slave.sql;
+
+# If all is good, when can cleanup our dump files.
+--remove_file $MYSQLTEST_VARDIR/tmp/NOW_master.sql
+--remove_file $MYSQLTEST_VARDIR/tmp/NOW_slave.sql
+
+sync_slave_with_master;
+# End of 5.1 test case
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_row_USER.test b/mysql-test/suite/rpl/t/rpl_row_USER.test
new file mode 100644
index 00000000..405f609f
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_row_USER.test
@@ -0,0 +1,59 @@
+#############################################################################
+# Original Author: JBM #
+# Original Date: Aug/18/2005 #
+#############################################################################
+# TEST: To test the USER() and CURRENT_USER() in rbr #
+#############################################################################
+# Change Author: JBM
+# Change Date: 2006-01-16
+##########
+
+# Includes
+-- source include/have_binlog_format_row.inc
+-- source include/master-slave.inc
+set local sql_mode="";
+
+# Begin clean up test section
+connection master;
+--disable_warnings
+DROP DATABASE IF EXISTS mysqltest1;
+CREATE DATABASE mysqltest1;
+--enable_warnings
+
+# Section 1 test
+CREATE USER tester IDENTIFIED BY 'test';
+GRANT ALL ON mysqltest1.* TO 'tester'@'%' IDENTIFIED BY 'test';
+GRANT ALL ON mysqltest1.* TO ''@'localhost%';
+FLUSH PRIVILEGES;
+connect (m_1,localhost,tester,,mysqltest1);
+
+connection m_1;
+CREATE TABLE mysqltest1.t1 (a INT, users VARCHAR(255), PRIMARY KEY(a));
+INSERT INTO mysqltest1.t1 VALUES(1,USER());
+INSERT INTO mysqltest1.t1 VALUES(2,CURRENT_USER());
+delimiter |;
+create procedure mysqltest1.p1()
+begin
+ INSERT INTO mysqltest1.t1 VALUES(3,USER());
+ INSERT INTO mysqltest1.t1 VALUES(4,CURRENT_USER());
+end|
+delimiter ;|
+
+CALL mysqltest1.p1();
+connection master;
+SELECT * FROM mysqltest1.t1 ORDER BY a;
+--sync_slave_with_master
+SELECT * FROM mysqltest1.t1 ORDER BY a;
+
+connection master;
+# Lets cleanup
+
+DROP DATABASE mysqltest1;
+REVOKE ALL ON mysqltest1.* FROM 'tester'@'%';
+REVOKE ALL ON mysqltest1.* FROM ''@'localhost%';
+DROP USER tester@'%';
+DROP USER ''@'localhost%';
+FLUSH PRIVILEGES;
+--sync_slave_with_master
+# End of 5.0 test case
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_row_UUID.test b/mysql-test/suite/rpl/t/rpl_row_UUID.test
new file mode 100644
index 00000000..8e1aa6d2
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_row_UUID.test
@@ -0,0 +1,8 @@
+########################################################
+# By JBM 2005-02-15 Wrapped to allow reuse of test code#
+########################################################
+-- source include/have_binlog_format_row.inc
+-- source include/master-slave.inc
+let $engine_type=myisam;
+--source include/rpl_row_UUID.test
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_row_annotate_do-slave.opt b/mysql-test/suite/rpl/t/rpl_row_annotate_do-slave.opt
new file mode 100644
index 00000000..18de9bd1
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_row_annotate_do-slave.opt
@@ -0,0 +1 @@
+--log-slave-updates --replicate-annotate-row-events --replicate-ignore-table=test1.xt1 --replicate-ignore-table=test1.xt2
diff --git a/mysql-test/suite/rpl/t/rpl_row_annotate_do.test b/mysql-test/suite/rpl/t/rpl_row_annotate_do.test
new file mode 100644
index 00000000..ffaae314
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_row_annotate_do.test
@@ -0,0 +1,16 @@
+###############################################################################
+# WL47: Store in binlog text of statements that caused RBR events
+# Wrapper for extra/rpl/rpl_row_annotate.test.
+# Intended to test that if the --replicate-annotate-row-events option
+# is switched on on slave then Annotate_events:
+# - are reproduced on slave
+# - are reproduced only once for "multi-table-maps" rbr queries
+# - are not reproduced when the corresponding queries are filtered away
+# on replication
+# - are reproduced when the corresponding queries are filtered away partialy
+# (e.g. in case of multi-delete)
+# - are not generated on slave for queries that are not annotated on master.
+###############################################################################
+
+--source include/have_binlog_format_row.inc
+--source include/rpl_row_annotate.test
diff --git a/mysql-test/suite/rpl/t/rpl_row_annotate_dont-slave.opt b/mysql-test/suite/rpl/t/rpl_row_annotate_dont-slave.opt
new file mode 100644
index 00000000..feef43f7
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_row_annotate_dont-slave.opt
@@ -0,0 +1 @@
+--log-slave-updates --skip-replicate-annotate-row-events --replicate-ignore-table=test1.xt1 --replicate-ignore-table=test1.xt2
diff --git a/mysql-test/suite/rpl/t/rpl_row_annotate_dont.test b/mysql-test/suite/rpl/t/rpl_row_annotate_dont.test
new file mode 100644
index 00000000..24dd2a1c
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_row_annotate_dont.test
@@ -0,0 +1,9 @@
+###############################################################################
+# WL47: Store in binlog text of statements that caused RBR events
+# Wrapper for extra/rpl/rpl_row_annotate.test.
+# Intended to test that if the --replicate-annotate-row-events option
+# is switched off on slave then Annotate_events are not reproduced.
+###############################################################################
+
+--source include/have_binlog_format_row.inc
+--source include/rpl_row_annotate.test
diff --git a/mysql-test/suite/rpl/t/rpl_row_basic_11bugs-master.opt b/mysql-test/suite/rpl/t/rpl_row_basic_11bugs-master.opt
new file mode 100644
index 00000000..bd772813
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_row_basic_11bugs-master.opt
@@ -0,0 +1,2 @@
+--binlog_ignore_db=test_ignore --default-storage-engine=MyISAM
+
diff --git a/mysql-test/suite/rpl/t/rpl_row_basic_11bugs.test b/mysql-test/suite/rpl/t/rpl_row_basic_11bugs.test
new file mode 100644
index 00000000..b875b97d
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_row_basic_11bugs.test
@@ -0,0 +1,242 @@
+-- source include/have_query_cache.inc
+--source include/have_binlog_format_row.inc
+--source include/have_innodb.inc
+
+let $SERVER_VERSION=`select version()`;
+
+--source include/master-slave.inc
+
+# Add suppression for expected warning(s) in slaves error log
+call mtr.add_suppression("Can't find record in 't.'");
+
+# Bug#15942 (RBR ignores --binlog_ignore_db and tries to map to table
+# on slave for writes)
+
+CREATE DATABASE test_ignore; # --binlog_ignore_db=mysqltest_ignore
+
+SHOW DATABASES;
+USE test;
+CREATE TABLE t1 (a INT, b INT);
+SHOW TABLES;
+INSERT INTO t1 VALUES (1,1), (2,2);
+USE test_ignore;
+CREATE TABLE t2 (a INT, b INT);
+SHOW TABLES;
+INSERT INTO t2 VALUES (3,3), (4,4);
+source include/show_binlog_events.inc;
+sync_slave_with_master;
+SHOW DATABASES;
+USE test;
+SHOW TABLES;
+--error 1049
+USE test_ignore;
+
+connection master;
+DROP DATABASE test_ignore;
+USE test;
+DROP TABLE t1;
+sync_slave_with_master;
+USE test;
+
+
+# Bug#19995: Extreneous table maps generated for statements that does
+# not generate rows
+--source include/rpl_reset.inc
+
+connection master;
+CREATE TABLE t1 (a INT);
+DELETE FROM t1;
+INSERT INTO t1 VALUES (1),(2);
+DELETE FROM t1 WHERE a = 0;
+UPDATE t1 SET a=99 WHERE a = 0;
+source include/show_binlog_events.inc;
+
+DROP TABLE t1;
+--sync_slave_with_master
+
+# BUG#17620: Replicate (Row Based) Fails when Query Cache enabled on
+# slave
+--echo ================ Test for BUG#17620 ================
+--source include/rpl_reset.inc
+
+connection slave;
+SET GLOBAL QUERY_CACHE_SIZE=0;
+call mtr.add_suppression("Slave SQL.*Could not execute Update_rows event on table test.t1.* error.* 1032");
+
+connection master;
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (1),(2),(3);
+
+sync_slave_with_master;
+SET GLOBAL QUERY_CACHE_SIZE=16*1024*1024;
+
+connection master;
+INSERT INTO t1 VALUES (4),(5),(6);
+
+sync_slave_with_master;
+SELECT * FROM t1;
+
+connection master;
+INSERT INTO t1 VALUES (7),(8),(9);
+
+sync_slave_with_master;
+SELECT * FROM t1;
+
+SET GLOBAL QUERY_CACHE_SIZE=default;
+--connection master
+DROP TABLE t1;
+
+
+# Bug#22550: Replication of BIT columns failing
+--echo ================ Test for BUG#22550 ================
+--source include/rpl_reset.inc
+
+connection master;
+CREATE TABLE t1 (a BIT(1), b INT) ENGINE=MYISAM;
+sync_slave_with_master;
+
+connection master;
+INSERT INTO t1 VALUES(1,2);
+SELECT HEX(a),b FROM t1;
+sync_slave_with_master;
+SELECT HEX(a),b FROM t1;
+
+connection master;
+UPDATE t1 SET a=0 WHERE b=2;
+SELECT HEX(a),b FROM t1;
+sync_slave_with_master;
+SELECT HEX(a),b FROM t1;
+
+connection master;
+DROP TABLE IF EXISTS t1;
+sync_slave_with_master;
+
+# BUG#22583: RBR between MyISAM and non-MyISAM tables containing a BIT
+# field does not work
+
+--echo ================ Test for BUG#22583 ================
+--source include/rpl_reset.inc
+
+# disabling warnings temporarily for ENGINE=INNODB to work without InnoDB
+--disable_warnings
+connection master;
+CREATE TABLE t1_myisam (k INT, a BIT(1), b BIT(9)) ENGINE=MYISAM;
+CREATE TABLE t1_innodb (k INT, a BIT(1), b BIT(9)) ENGINE=INNODB;
+CREATE TABLE t2_myisam (k INT, a BIT(1) NOT NULL, b BIT(4) NOT NULL) ENGINE=MYISAM;
+CREATE TABLE t2_innodb (k INT, a BIT(1) NOT NULL, b BIT(4) NOT NULL) ENGINE=INNODB;
+sync_slave_with_master;
+ALTER TABLE t1_myisam ENGINE=INNODB;
+ALTER TABLE t1_innodb ENGINE=MYISAM;
+ALTER TABLE t2_myisam ENGINE=INNODB;
+ALTER TABLE t2_innodb ENGINE=MYISAM;
+--enable_warnings
+
+connection master;
+INSERT INTO t1_myisam VALUES(1, b'0', 257);
+INSERT INTO t1_myisam VALUES(2, b'1', 256);
+INSERT INTO t1_innodb VALUES(1, b'0', 257);
+INSERT INTO t1_innodb VALUES(2, b'1', 256);
+SELECT k, HEX(a),HEX(b) FROM t1_myisam;
+SELECT k, HEX(a),HEX(b) FROM t1_innodb;
+INSERT INTO t2_myisam VALUES(1, b'0', 9);
+INSERT INTO t2_myisam VALUES(2, b'1', 8);
+INSERT INTO t2_innodb VALUES(1, b'0', 9);
+INSERT INTO t2_innodb VALUES(2, b'1', 8);
+SELECT k, HEX(a),HEX(b) FROM t2_myisam;
+SELECT k, HEX(a),HEX(b) FROM t2_innodb;
+sync_slave_with_master;
+SELECT k, HEX(a),HEX(b) FROM t1_myisam;
+SELECT k, HEX(a),HEX(b) FROM t1_innodb;
+SELECT k, HEX(a),HEX(b) FROM t2_myisam;
+SELECT k, HEX(a),HEX(b) FROM t2_innodb;
+
+connection master;
+UPDATE t1_myisam SET a=0 WHERE k=2;
+SELECT k, HEX(a),HEX(b) FROM t1_myisam;
+UPDATE t1_innodb SET a=0 WHERE k=2;
+SELECT k, HEX(a),HEX(b) FROM t1_innodb;
+UPDATE t2_myisam SET a=0 WHERE k=2;
+SELECT k, HEX(a),HEX(b) FROM t2_myisam;
+UPDATE t2_innodb SET a=0 WHERE k=2;
+SELECT k, HEX(a),HEX(b) FROM t2_innodb;
+sync_slave_with_master;
+SELECT k, HEX(a),HEX(b) FROM t1_myisam;
+SELECT k, HEX(a),HEX(b) FROM t1_innodb;
+SELECT k, HEX(a),HEX(b) FROM t2_myisam;
+SELECT k, HEX(a),HEX(b) FROM t2_innodb;
+
+connection master;
+DROP TABLE IF EXISTS t1_myisam, t1_innodb, t2_myisam, t2_innodb;
+sync_slave_with_master;
+
+#
+# Bug#27716 multi-update did partially and has not binlogged
+#
+
+connection master;
+
+--disable_warnings
+drop table if exists t1, t2;
+--enable_warnings
+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=MyISAM DEFAULT CHARSET=latin1 ;
+
+# testing multi_update::send_error() effective update
+insert into t1 values (1,1),(2,2);
+insert into t2 values (1,1),(4,4);
+
+connection master;
+error ER_DUP_ENTRY;
+UPDATE t2,t1 SET t2.a=t1.a+2;
+select * from t2 /* must be (3,1), (4,4) */;
+sync_slave_with_master;
+
+connection slave;
+select * from t2 /* must be (3,1), (4,4) */;
+
+connection master;
+drop table t1,t2;
+
+sync_slave_with_master;
+
+#
+# BUG#31702: Missing row on slave causes assertion failure under
+# row-based replication
+#
+
+--source include/rpl_reset.inc
+
+connection master;
+CREATE TABLE t1 (a INT PRIMARY KEY, b SET('master','slave'));
+INSERT INTO t1 VALUES (1,'master,slave'), (2,'master,slave');
+sync_slave_with_master;
+UPDATE t1 SET a = 5, b = 'slave' WHERE a = 1;
+SELECT * FROM t1 ORDER BY a;
+# since bug#31552/31609 idempotency is not default any longer. In
+# order for the preceding test UPDATE t1 to pass, the mode is switched
+# temprorarily
+set @@global.slave_exec_mode= 'IDEMPOTENT';
+connection master;
+UPDATE t1 SET a = 5, b = 'master' WHERE a = 1;
+SELECT * FROM t1 ORDER BY a;
+sync_slave_with_master;
+set @@global.slave_exec_mode= default;
+let $last_error = query_get_value("SHOW SLAVE STATUS", Last_SQL_Error, 1);
+disable_query_log;
+eval SELECT "$last_error" AS Last_SQL_Error;
+enable_query_log;
+
+SELECT * FROM t1 ORDER BY a;
+
+connection master;
+DROP TABLE t1;
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_row_basic_2myisam.test b/mysql-test/suite/rpl/t/rpl_row_basic_2myisam.test
new file mode 100644
index 00000000..f1e836c6
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_row_basic_2myisam.test
@@ -0,0 +1,11 @@
+-- source include/have_binlog_format_row.inc
+-- source include/master-slave.inc
+
+let $type= 'MYISAM' ;
+let $extra_index= ;
+-- source include/rpl_row_basic.test
+
+connection slave;
+call mtr.add_suppression("Can't find record in 't1'");
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_row_basic_3innodb.test b/mysql-test/suite/rpl/t/rpl_row_basic_3innodb.test
new file mode 100644
index 00000000..b84a4c13
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_row_basic_3innodb.test
@@ -0,0 +1,11 @@
+-- source include/have_innodb.inc
+-- source include/have_binlog_format_row.inc
+-- source include/master-slave.inc
+
+connection slave;
+let $bit_field_special = ALL_LOSSY;
+let $type= 'INNODB' ;
+let $extra_index= ;
+-- source include/rpl_row_basic.test
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_row_basic_8partition.test b/mysql-test/suite/rpl/t/rpl_row_basic_8partition.test
new file mode 100644
index 00000000..7a477056
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_row_basic_8partition.test
@@ -0,0 +1,190 @@
+############################################################
+# Author: MATZ #
+# Date: 2006-03-22 #
+# Purpose: See if replication of partition tables work #
+# Most of this test is copied from the rpl_xxx2yyy tests, #
+# but here we just test some simple basic replication of #
+# partition tables with same engine (MyISAM) in both ends. #
+############################################################
+
+--source include/have_binlog_format_row.inc
+--source include/have_partition.inc
+--source include/master-slave.inc
+connection master;
+--disable_warnings
+DROP TABLE IF EXISTS t1;
+
+SET @@BINLOG_FORMAT = ROW;
+
+--echo **** Partition RANGE testing ****
+
+# Create table that is partitioned by range on year i.e. year(t) and
+# replicate basice operations such at insert, update delete between 2
+# different storage engines Alter table and ensure table is handled
+# Correctly on the slave
+# Note that the storage engine should not be explicit: the default
+# storage engine is used on master and slave.
+
+CREATE TABLE t1 (id MEDIUMINT NOT NULL, b1 BIT(8), vc VARCHAR(255),
+ bc CHAR(255), d DECIMAL(10,4) DEFAULT 0,
+ f FLOAT DEFAULT 0, total BIGINT UNSIGNED,
+ y YEAR, t DATE)
+ PARTITION BY RANGE (YEAR(t))
+ (PARTITION p0 VALUES LESS THAN (1901),
+ PARTITION p1 VALUES LESS THAN (1946),
+ PARTITION p2 VALUES LESS THAN (1966),
+ PARTITION p3 VALUES LESS THAN (1986),
+ PARTITION p4 VALUES LESS THAN (2005),
+ PARTITION p5 VALUES LESS THAN MAXVALUE);
+
+SHOW CREATE TABLE t1;
+
+sync_slave_with_master;
+SHOW CREATE TABLE t1;
+
+--source include/rpl_multi_engine3.inc
+
+connection master;
+# Check that simple Alter statements are replicated correctly
+ALTER TABLE t1 MODIFY vc TEXT;
+
+SHOW CREATE TABLE t1;
+
+sync_slave_with_master;
+SHOW CREATE TABLE t1;
+
+# Perform basic operation on master and ensure replicated correctly
+--source include/rpl_multi_engine3.inc
+
+connection master;
+DROP TABLE IF EXISTS t1;
+
+########################################################
+
+--echo **** Partition LIST testing ****
+
+# Create table that is partitioned by list on id i.e. (2,4). Pretend
+# that we missed one and alter to add. Then replicate basice
+# operations such at insert, update delete between 2 different storage
+# engines Alter table and ensure table is handled Correctly on the
+# slave.
+
+
+CREATE TABLE t1 (id MEDIUMINT NOT NULL, b1 BIT(8), vc VARCHAR(255),
+ bc CHAR(255), d DECIMAL(10,4) DEFAULT 0,
+ f FLOAT DEFAULT 0, total BIGINT UNSIGNED,
+ y YEAR, t DATE)
+ PARTITION BY LIST(id)
+ (PARTITION p0 VALUES IN (2, 4),
+ PARTITION p1 VALUES IN (42, 142),
+ PARTITION p2 VALUES IN (412));
+
+SHOW CREATE TABLE t1;
+
+sync_slave_with_master;
+SHOW CREATE TABLE t1;
+
+# Perform basic operation on master and ensure replicated correctly
+--source include/rpl_multi_engine3.inc
+
+connection master;
+# Check that simple Alter statements are replicated correctly ---
+ALTER TABLE t1 MODIFY vc TEXT;
+
+SHOW CREATE TABLE t1;
+
+sync_slave_with_master;
+SHOW CREATE TABLE t1;
+
+# Perform basic operation on master and ensure replicated correctly
+--source include/rpl_multi_engine3.inc
+
+connection master;
+DROP TABLE IF EXISTS t1;
+
+########################################################
+
+--echo **** Partition HASH testing ****
+
+# Create table that is partitioned by hash on year i.e. YEAR(t). Then
+# replicate basice operations such at insert, update delete between 2
+# different storage engines Alter table and ensure table is handled
+# Correctly on the slave
+
+CREATE TABLE t1 (id MEDIUMINT NOT NULL, b1 BIT(8), vc VARCHAR(255),
+ bc CHAR(255), d DECIMAL(10,4) DEFAULT 0,
+ f FLOAT DEFAULT 0, total BIGINT UNSIGNED,
+ y YEAR, t DATE)
+ PARTITION BY HASH( YEAR(t) )
+ PARTITIONS 4;
+
+SHOW CREATE TABLE t1;
+
+sync_slave_with_master;
+SHOW CREATE TABLE t1;
+
+--source include/rpl_multi_engine3.inc
+
+# Check that simple Alter statements are replicated correctly
+ALTER TABLE t1 MODIFY vc TEXT;
+
+SHOW CREATE TABLE t1;
+
+sync_slave_with_master;
+SHOW CREATE TABLE t1;
+
+--source include/rpl_multi_engine3.inc
+
+connection master;
+DROP TABLE IF EXISTS t1;
+
+########################################################
+
+# This part does not work
+--echo **** Partition by KEY ****
+
+# Create table that is partitioned by key on id with 4 parts. Then
+# replicate basice operations such at insert, update delete between 2
+# different storage engines Alter table and ensure table is handled
+# Correctly on the slave
+
+CREATE TABLE t1 (id MEDIUMINT NOT NULL, b1 BIT(8), vc VARCHAR(255),
+ bc CHAR(255), d DECIMAL(10,4) DEFAULT 0,
+ f FLOAT DEFAULT 0, total BIGINT UNSIGNED,
+ y YEAR, t DATE,PRIMARY KEY(id))
+ PARTITION BY KEY()
+ PARTITIONS 4;
+
+SHOW CREATE TABLE t1;
+
+sync_slave_with_master;
+SHOW CREATE TABLE t1;
+
+--source include/rpl_multi_engine3.inc
+
+connection master;
+# Check that simple Alter statements are replicated correctly
+ALTER TABLE t1 DROP PRIMARY KEY, ADD PRIMARY KEY(id, total);
+
+SHOW CREATE TABLE t1;
+
+sync_slave_with_master;
+SHOW CREATE TABLE t1;
+
+--source include/rpl_multi_engine3.inc
+
+connection master;
+# Check that simple Alter statements are replicated correctly
+ALTER TABLE t1 MODIFY vc TEXT;
+
+SHOW CREATE TABLE t1;
+
+sync_slave_with_master;
+SHOW CREATE TABLE t1;
+
+--source include/rpl_multi_engine3.inc
+
+DROP TABLE IF EXISTS t1;
+
+# End of 5.1 test case
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_row_big_table_id.opt b/mysql-test/suite/rpl/t/rpl_row_big_table_id.opt
new file mode 100644
index 00000000..7c3d2411
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_row_big_table_id.opt
@@ -0,0 +1 @@
+--verbose=1
diff --git a/mysql-test/suite/rpl/t/rpl_row_big_table_id.test b/mysql-test/suite/rpl/t/rpl_row_big_table_id.test
new file mode 100644
index 00000000..15eadedb
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_row_big_table_id.test
@@ -0,0 +1,58 @@
+##################################################################
+# rpl_row_big_table_id
+#
+# MDEV-17803 Row-based event is not applied when
+# table map id is greater 32 bit int
+#
+# This test is depending on that the server was restarted before test was run
+#
+# Verify row-based events applying when table map id value is about and greater
+# than 1 << 32.
+##################################################################
+--source include/not_valgrind.inc
+--source include/word_size.inc
+--source include/have_debug.inc
+--source include/have_binlog_format_row.inc
+--source include/master-slave.inc
+
+SET @old_debug_dbug= @@debug_dbug;
+SET @@debug_dbug="+d,simulate_big_table_id";
+CREATE TABLE t (a int);
+
+--let $binlog_file= query_get_value(SHOW MASTER STATUS, File, 1)
+--let $binlog_pos= query_get_value(SHOW MASTER STATUS, Position, 1)
+INSERT INTO t SET a= 0;
+ALTER TABLE t comment '';
+INSERT INTO t SET a= 1;
+ALTER TABLE t comment '';
+INSERT INTO t SET a= 2;
+ALTER TABLE t comment '';
+INSERT INTO t SET a= 3;
+
+# display simulated big table_id
+--let $_in_from=in '$binlog_file' from $binlog_pos
+--replace_result "$_in_from" "in <file> from <pos>"
+--replace_column 2 # 5 #
+--replace_regex /\/\* xid=.* \*\//\/* XID *\// /file_id=[0-9]+/file_id=#/ /GTID [0-9]+-[0-9]+-[0-9]+/GTID #-#-#/
+--eval show binlog events in '$binlog_file' from $binlog_pos
+
+
+--sync_slave_with_master
+
+if (`SELECT sum(a) != 6 FROM t`)
+{
+ --echo *** unexpected result; check slave applier ***
+ --die
+}
+
+
+# Cleanup
+
+--connection master
+SET debug_dbug=@old_debug_dbug;
+
+DROP TABLE t;
+
+--sync_slave_with_master
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_row_binlog_max_cache_size.test b/mysql-test/suite/rpl/t/rpl_row_binlog_max_cache_size.test
new file mode 100644
index 00000000..a4db32cf
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_row_binlog_max_cache_size.test
@@ -0,0 +1,8 @@
+--source include/have_innodb.inc
+--source include/not_embedded.inc
+--source include/not_windows.inc
+--source include/have_binlog_format_row.inc
+--source include/master-slave.inc
+
+--source include/rpl_binlog_max_cache_size.test
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_row_blob_innodb.test b/mysql-test/suite/rpl/t/rpl_row_blob_innodb.test
new file mode 100644
index 00000000..57f3e91a
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_row_blob_innodb.test
@@ -0,0 +1,13 @@
+#################################
+# Wrapper for rpl_row_blob.test#
+#################################
+########################################################
+# By JBM 2005-02-15 Wrapped to allow reuse of test code#
+########################################################
+-- source include/have_innodb.inc
+-- source include/have_binlog_format_row.inc
+-- source include/master-slave.inc
+let $engine_type=InnoDB;
+-- source include/rpl_row_blob.test
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_row_blob_myisam.test b/mysql-test/suite/rpl/t/rpl_row_blob_myisam.test
new file mode 100644
index 00000000..246d38f4
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_row_blob_myisam.test
@@ -0,0 +1,12 @@
+#################################
+# Wrapper for rpl_row_blob.test#
+#################################
+########################################################
+# By JBM 2005-02-15 Wrapped to allow reuse of test code#
+########################################################
+-- source include/have_binlog_format_row.inc
+-- source include/master-slave.inc
+let $engine_type=myisam;
+-- source include/rpl_row_blob.test
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_row_colSize.test b/mysql-test/suite/rpl/t/rpl_row_colSize.test
new file mode 100644
index 00000000..21c68b55
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_row_colSize.test
@@ -0,0 +1,173 @@
+##################################################################
+# rpl_colSize #
+# #
+# This test is designed to test the changes included in WL#3228. #
+# The changes include the ability to replicate with the master #
+# having columns that are smaller (shorter) than the slave. #
+##################################################################
+
+-- source include/have_binlog_format_row.inc
+-- source include/master-slave.inc
+
+--disable_warnings
+DROP TABLE IF EXISTS t1;
+--enable_warnings
+
+
+--echo **** Testing WL#3228 changes. ****
+--echo *** Create "wider" table on slave ***
+sync_slave_with_master;
+
+#
+# Check each column type to verify error 1532 fires (BUG#22086)
+# This check covers only those fields that require additional
+# metadata from the master to be replicated to the slave. These
+# field types are:
+# MYSQL_TYPE_NEWDECIMAL:
+# MYSQL_TYPE_FLOAT:
+# MYSQL_TYPE_BIT:
+# MYSQL_TYPE_SET:
+# MYSQL_TYPE_STRING:
+# MYSQL_TYPE_ENUM:
+# MYSQL_TYPE_VARCHAR:
+# MYSQL_TYPE_BLOB:
+
+#
+# Test: Checking MYSQL_TYPE_NEWDECIMAL fields
+#
+--echo Checking MYSQL_TYPE_NEWDECIMAL fields
+let $test_table_master = CREATE TABLE t1 (a DECIMAL(20, 10));
+let $test_table_slave = CREATE TABLE t1 (a DECIMAL(5,2));
+let $test_insert = INSERT INTO t1 VALUES (901251.90125);
+source include/test_fieldsize.inc;
+
+let $test_table_master = CREATE TABLE t1 (a DECIMAL(27, 18));
+let $test_table_slave = CREATE TABLE t1 (a DECIMAL(27, 9));
+let $test_insert = INSERT INTO t1 VALUES (901251.90125);
+source include/test_fieldsize.inc;
+
+let $test_table_master = CREATE TABLE t1 (a NUMERIC(20, 10));
+let $test_table_slave = CREATE TABLE t1 (a NUMERIC(5,2));
+let $test_insert = INSERT INTO t1 VALUES (901251.90125);
+source include/test_fieldsize.inc;
+
+#
+# Test: Checking MYSQL_TYPE_FLOAT fields
+#
+--echo Checking MYSQL_TYPE_FLOAT fields
+let $test_table_master = CREATE TABLE t1 (a FLOAT(47));
+let $test_table_slave = CREATE TABLE t1 (a FLOAT(20));
+let $test_insert = INSERT INTO t1 VALUES (901251.90125);
+source include/test_fieldsize.inc;
+
+#
+# Test: Checking MYSQL_TYPE_BIT fields
+#
+--echo Checking MYSQL_TYPE_BIT fields
+let $test_table_master = CREATE TABLE t1 (a BIT(64));
+let $test_table_slave = CREATE TABLE t1 (a BIT(5));
+let $test_insert = INSERT INTO t1 VALUES (B'10101');
+source include/test_fieldsize.inc;
+
+let $test_table_master = CREATE TABLE t1 (a BIT(12));
+let $test_table_slave = CREATE TABLE t1 (a BIT(11));
+let $test_insert = INSERT INTO t1 VALUES (B'10101');
+source include/test_fieldsize.inc;
+
+#
+# Test: Checking MYSQL_TYPE_SET fields
+#
+--echo Checking MYSQL_TYPE_SET fields
+let $test_table_master = CREATE TABLE t1 (a SET('1','2','3','4','5','6','7','8','9'));
+let $test_table_slave = CREATE TABLE t1 (a SET('4'));
+let $test_insert = INSERT INTO t1 VALUES ('4');
+source include/test_fieldsize.inc;
+
+#
+# Test: Checking MYSQL_TYPE_STRING fields
+#
+--echo Checking MYSQL_TYPE_STRING fields
+let $test_table_master = CREATE TABLE t1 (a CHAR(20));
+let $test_table_slave = CREATE TABLE t1 (a CHAR(10));
+let $test_insert = INSERT INTO t1 VALUES ('This is a test.');
+source include/test_fieldsize.inc;
+
+#
+# Test: Checking MYSQL_TYPE_ENUM fields
+#
+--echo Checking MYSQL_TYPE_ENUM fields
+let $test_table_master = CREATE TABLE t1 (a ENUM(
+ '01','02','03','04','05','06','07','08','09',
+ '11','12','13','14','15','16','17','18','19',
+ '21','22','23','24','25','26','27','28','29',
+ '31','32','33','34','35','36','37','38','39',
+ '41','42','43','44','45','46','47','48','49',
+ '51','52','53','54','55','56','57','58','59',
+ '61','62','63','64','65','66','67','68','69',
+ '71','72','73','74','75','76','77','78','79',
+ '81','82','83','84','85','86','87','88','89',
+ '91','92','93','94','95','96','97','98','99',
+ '101','102','103','104','105','106','107','108','109',
+ '111','112','113','114','115','116','117','118','119',
+ '121','122','123','124','125','126','127','128','129',
+ '131','132','133','134','135','136','137','138','139',
+ '141','142','143','144','145','146','147','148','149',
+ '151','152','153','154','155','156','157','158','159',
+ '161','162','163','164','165','166','167','168','169',
+ '171','172','173','174','175','176','177','178','179',
+ '181','182','183','184','185','186','187','188','189',
+ '191','192','193','194','195','196','197','198','199',
+ '201','202','203','204','205','206','207','208','209',
+ '211','212','213','214','215','216','217','218','219',
+ '221','222','223','224','225','226','227','228','229',
+ '231','232','233','234','235','236','237','238','239',
+ '241','242','243','244','245','246','247','248','249',
+ '251','252','253','254','255','256','257','258','259',
+ '261','262','263','264','265','266','267','268','269',
+ '271','272','273','274','275','276','277','278','279',
+ '281','282','283','284','285','286','287','288','289',
+ '291','292','293','294','295','296','297','298','299'
+ ));
+let $test_table_slave = CREATE TABLE t1 (a ENUM('44','54'));
+let $test_insert = INSERT INTO t1 VALUES ('44');
+source include/test_fieldsize.inc;
+
+#
+# Test: Checking MYSQL_TYPE_VARCHAR fields
+#
+--echo Checking MYSQL_TYPE_VARCHAR fields
+let $test_table_master = CREATE TABLE t1 (a VARCHAR(2000));
+let $test_table_slave = CREATE TABLE t1 (a VARCHAR(100));
+let $test_insert = INSERT INTO t1 VALUES ('This is a test.');
+source include/test_fieldsize.inc;
+
+let $test_table_master = CREATE TABLE t1 (a VARCHAR(200));
+let $test_table_slave = CREATE TABLE t1 (a VARCHAR(10));
+let $test_insert = INSERT INTO t1 VALUES ('This is a test.');
+source include/test_fieldsize.inc;
+
+let $test_table_master = CREATE TABLE t1 (a VARCHAR(2000));
+let $test_table_slave = CREATE TABLE t1 (a VARCHAR(1000));
+let $test_insert = INSERT INTO t1 VALUES ('This is a test.');
+source include/test_fieldsize.inc;
+
+#
+# Test: Checking MYSQL_TYPE_BLOB fields
+#
+--echo Checking MYSQL_TYPE_BLOB fields
+let $test_table_master = CREATE TABLE t1 (a LONGBLOB);
+let $test_table_slave = CREATE TABLE t1 (a TINYBLOB);
+let $test_insert = INSERT INTO t1 VALUES ('This is a test.');
+source include/test_fieldsize.inc;
+
+connection slave;
+call mtr.add_suppression("Slave SQL.*Table definition on master and slave does not match: Column 0 ...e mismatch.* error.* 1535");
+call mtr.add_suppression("Slave SQL.*Column 0 of table .test.t1. cannot be converted from type.* error.* 1677");
+
+--echo *** Cleanup ***
+connection master;
+DROP TABLE IF EXISTS t1;
+sync_slave_with_master;
+# END 5.1 Test Case
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_row_conflicts.test b/mysql-test/suite/rpl/t/rpl_row_conflicts.test
new file mode 100644
index 00000000..adf37d99
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_row_conflicts.test
@@ -0,0 +1,33 @@
+# See the top of mysql-test/include/rpl_conflicts.test for
+# explanation of what this test does.
+#
+# This test file is for row-logging mode. It runs the test twice, with
+# slave_exec_mode=STRICT and slave_exec_mode=IDEMPOTENT, respectively.
+
+source include/have_binlog_format_row.inc;
+source include/master-slave.inc;
+
+connection slave;
+call mtr.add_suppression("Slave: Can\'t find record in \'t1\' error.* .*");
+call mtr.add_suppression("Can't find record in 't.'");
+
+connection slave;
+SET @old_slave_exec_mode= @@global.slave_exec_mode;
+
+
+--echo ######## Run with slave_exec_mode=STRICT ########
+
+SET @@global.slave_exec_mode = 'STRICT';
+source include/rpl_conflicts.test;
+
+--source include/rpl_reset.inc
+
+
+--echo ######## Run with slave_exec_mode=IDEMPOTENT ########
+
+set @@global.slave_exec_mode= 'IDEMPOTENT';
+source include/rpl_conflicts.test;
+
+
+SET @@global.slave_exec_mode= @old_slave_exec_mode;
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_row_corruption-slave.opt b/mysql-test/suite/rpl/t/rpl_row_corruption-slave.opt
new file mode 100644
index 00000000..da199510
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_row_corruption-slave.opt
@@ -0,0 +1 @@
+--replicate-ignore-table=test.t2_11753004_ign
diff --git a/mysql-test/suite/rpl/t/rpl_row_corruption.test b/mysql-test/suite/rpl/t/rpl_row_corruption.test
new file mode 100644
index 00000000..d78df905
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_row_corruption.test
@@ -0,0 +1,115 @@
+#
+--source include/have_debug.inc
+--source include/have_binlog_format_row.inc
+--source include/master-slave.inc
+
+# BUG#11753004: 44360: REPLICATION FAILED
+
+## assert that we get an error when checking the
+## identifiers at the slave (instead of a crash or
+## different table being updated)
+
+--let $t1= t1_11753004
+--let $t2= t2_11753004
+--let $t2_ign= t2_11753004_ign
+
+## test #1: assert that we get an error raised when multiple
+## tables in the same RBR statement are mapped with the
+## same identifier
+
+--eval CREATE TABLE $t1 (c1 INT)
+--eval CREATE TABLE $t2 (c1 INT)
+--eval INSERT INTO $t1 VALUES (1)
+--eval INSERT INTO $t2 VALUES (2)
+
+--sync_slave_with_master
+call mtr.add_suppression(".*Found table map event mapping table id 0 which was already mapped but with different settings.*");
+
+# stop the slave and inject corruption
+--source include/stop_slave.inc
+SET @saved_debug= @@global.debug_dbug;
+SET @@global.debug_dbug="d,inject_tblmap_same_id_maps_diff_table";
+--source include/start_slave.inc
+--connection master
+# both tables get mapped to 0 (in a way, simulating scenario
+# originated by BUG#56226)
+--eval UPDATE $t1, $t2 SET $t1.c1=3, $t2.c1=4 WHERE $t1.c1=1 OR $t2.c1=2
+--connection slave
+
+# wait for error 1593 (ER_SLAVE_FATAL_ERROR)
+--let $slave_sql_errno=1593
+--source include/wait_for_slave_sql_error.inc
+--source include/stop_slave.inc
+
+# clean up
+SET @@global.debug_dbug=@saved_debug;
+--source include/start_slave.inc
+--connection master
+--source include/rpl_reset.inc
+--eval DROP TABLE $t1, $t2
+--sync_slave_with_master
+
+## test #2: assert that ignored tables that may have been mapped
+## with the same identifier are skipped, thus no error
+## is raised.
+
+--connection slave
+--source include/stop_slave.inc
+SET @@global.debug_dbug="d,inject_tblmap_same_id_maps_diff_table";
+--source include/start_slave.inc
+--source include/rpl_reset.inc
+--connection master
+--eval CREATE TABLE $t1 (c1 INT)
+--eval CREATE TABLE $t2_ign (c1 INT)
+--eval INSERT INTO $t1 VALUES (1)
+--eval INSERT INTO $t2_ign VALUES (2)
+--eval UPDATE $t1, $t2_ign SET $t1.c1=3, $t2_ign.c1=4 WHERE $t1.c1=1 OR $t2_ign.c1=2
+
+# must not raise error as second table is filtered
+--sync_slave_with_master
+
+
+## test #3: check that BINLOG statements will also raise an
+## error if containing table map events mapping different
+## tables to same table identifier.
+
+CREATE TABLE t1 (c1 INT);
+CREATE TABLE t2 (c1 INT);
+
+INSERT INTO t1 VALUES (1);
+INSERT INTO t2 VALUES (1);
+
+# FD event
+BINLOG '
+SOgWTg8BAAAAbgAAAHIAAAAAAAQANS42LjMtbTUtZGVidWctbG9nAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAABI6BZOEzgNAAgAEgAEBAQEEgAAVgAEGggAAAAICAgCAAAAAAVAYI8=
+'/*!*/;
+
+#110708 12:21:44 server id 1 end_log_pos 774 Table_map: `test`.`t1` mapped to number 66
+# at 774
+#110708 12:21:44 server id 1 end_log_pos 815 Table_map: `test`.`t2` mapped to number 67
+# at 815
+#110708 12:21:44 server id 1 end_log_pos 855 Update_rows: table id 66
+# at 855
+#110708 12:21:44 server id 1 end_log_pos 895 Update_rows: table id 67 flags: STMT_END_F
+SET @@global.debug_dbug="d,inject_tblmap_same_id_maps_diff_table";
+--error ER_SLAVE_FATAL_ERROR
+BINLOG '
+SOgWThMBAAAAKQAAAAYDAAAAAEIAAAAAAAEABHRlc3QAAnQxAAEDAAE=
+SOgWThMBAAAAKQAAAC8DAAAAAEMAAAAAAAEABHRlc3QAAnQyAAEDAAE=
+SOgWThgBAAAAKAAAAFcDAAAAAEIAAAAAAAAAAf///gEAAAD+AwAAAA==
+SOgWThgBAAAAKAAAAH8DAAAAAEMAAAAAAAEAAf///gEAAAD+BAAAAA==
+'/*!*/;
+
+
+# clean up
+DROP TABLE t1,t2;
+--connection slave
+SET @@global.debug_dbug=@saved_debug;
+--connection master
+--eval DROP TABLE $t1
+--eval DROP TABLE $t2_ign
+--sync_slave_with_master
+SET @@global.debug_dbug= @save_debug;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_row_create_select.test b/mysql-test/suite/rpl/t/rpl_row_create_select.test
new file mode 100644
index 00000000..d870b68f
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_row_create_select.test
@@ -0,0 +1,30 @@
+# Testing table creations for row-based replication.
+
+--source include/have_binlog_format_row.inc
+--source include/master-slave.inc
+
+--echo #
+--echo # BUG#17994219: CREATE TABLE .. SELECT PRODUCES INVALID STRUCTURE,
+--echo # BREAKS RBR
+--echo #
+
+connection master;
+--echo #After the patch, the display width is set to a default
+--echo #value of 21.
+SET STATEMENT sql_mode = 'NO_ENGINE_SUBSTITUTION' FOR
+CREATE TABLE t1 AS SELECT REPEAT('A', 1000) DIV 1 AS a;
+SHOW CREATE TABLE t1;
+
+SET STATEMENT sql_mode = 'NO_ENGINE_SUBSTITUTION' FOR
+CREATE TABLE t2 AS SELECT CONVERT(REPEAT('A', 255) USING UCS2) DIV 1 AS a;
+SHOW CREATE TABLE t2;
+
+--echo #After the patch, no error is reported.
+sync_slave_with_master;
+
+connection master;
+DROP TABLE t1;
+DROP TABLE t2;
+
+--source include/rpl_end.inc
+
diff --git a/mysql-test/suite/rpl/t/rpl_row_create_table.test b/mysql-test/suite/rpl/t/rpl_row_create_table.test
new file mode 100644
index 00000000..b62955e2
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_row_create_table.test
@@ -0,0 +1,285 @@
+# Testing table creations for row-based replication.
+
+--source include/have_binlog_format_row.inc
+--source include/have_innodb.inc
+--source include/master-slave.inc
+connection slave;
+--source include/have_innodb.inc
+connection master;
+
+# Set the default storage engine to different values on master and
+# slave. We need to stop the slave for the server variable to take
+# effect, since the variable is only read on start-up.
+sync_slave_with_master;
+--disable_query_log
+set @@default_storage_engine = @@global.default_storage_engine;
+STOP SLAVE;
+--source include/wait_for_slave_to_stop.inc
+SET GLOBAL default_storage_engine=memory;
+START SLAVE;
+--source include/wait_for_slave_to_start.inc
+--enable_query_log
+
+--source include/rpl_reset.inc
+
+connection master;
+CREATE TABLE t1 (a INT);
+CREATE OR REPLACE TABLE t1 (a INT, b INT);
+CREATE TABLE t2 (a INT, b INT) ENGINE=Merge;
+CREATE TABLE t3 (a INT, b INT) CHARSET=utf8;
+CREATE TABLE t4 (a INT, b INT) ENGINE=Merge CHARSET=utf8;
+--source include/show_binlog_events.inc
+--query_vertical SHOW CREATE TABLE t1
+--query_vertical SHOW CREATE TABLE t2
+--query_vertical SHOW CREATE TABLE t3
+sync_slave_with_master;
+--query_vertical SHOW CREATE TABLE t1
+--query_vertical SHOW CREATE TABLE t2
+--query_vertical SHOW CREATE TABLE t3
+
+connection master;
+CREATE TABLE t5 (b INT, c INT) SELECT * FROM t3;
+
+CREATE TEMPORARY TABLE tt3 (a INT, b INT);
+INSERT INTO tt3 VALUES (1,2), (2,4), (3,6), (4,2), (5,10), (6,12);
+CREATE TABLE t6 (b INT, c INT) SELECT * FROM tt3;
+--query_vertical SHOW CREATE TABLE t5
+SELECT * FROM t5 ORDER BY a,b,c;
+--query_vertical SHOW CREATE TABLE t6
+SELECT * FROM t6 ORDER BY a,b,c;
+sync_slave_with_master;
+--query_vertical SHOW CREATE TABLE t5
+SELECT * FROM t5 ORDER BY a,b,c;
+--query_vertical SHOW CREATE TABLE t6
+SELECT * FROM t6 ORDER BY a,b,c;
+
+--source include/rpl_reset.inc
+
+connection master;
+# Test for erroneous constructions
+--error ER_DUP_ENTRY
+CREATE TABLE t7 (UNIQUE(b)) SELECT a,b FROM tt3;
+# Shouldn't be written to the binary log
+--source include/show_binlog_events.inc
+
+# Test that INSERT-SELECT works the same way as for SBR.
+CREATE TABLE t7 (a INT, b INT UNIQUE);
+--error ER_DUP_ENTRY
+INSERT INTO t7 SELECT a,b FROM tt3;
+SELECT * FROM t7 ORDER BY a,b;
+# Should be written to the binary log
+--source include/show_binlog_events.inc
+sync_slave_with_master;
+SELECT * FROM t7 ORDER BY a,b;
+
+--source include/rpl_reset.inc
+
+connection master;
+CREATE TEMPORARY TABLE tt4 (a INT, b INT);
+INSERT INTO tt4 VALUES (4,8), (5,10), (6,12);
+BEGIN;
+INSERT INTO t7 SELECT a,b FROM tt4;
+ROLLBACK;
+--source include/show_binlog_events.inc
+SELECT * FROM t7 ORDER BY a,b;
+sync_slave_with_master;
+SELECT * FROM t7 ORDER BY a,b;
+
+--source include/rpl_reset.inc
+
+connection master;
+CREATE TABLE t8 LIKE t4;
+CREATE TABLE t9 LIKE tt4;
+CREATE TEMPORARY TABLE tt5 LIKE t4;
+CREATE TEMPORARY TABLE tt6 LIKE tt4;
+CREATE TEMPORARY TABLE tt7 SELECT 1;
+--query_vertical SHOW CREATE TABLE t8
+--query_vertical SHOW CREATE TABLE t9
+--source include/show_binlog_events.inc
+sync_slave_with_master;
+--query_vertical SHOW CREATE TABLE t8
+--query_vertical SHOW CREATE TABLE t9
+
+connection master;
+DROP TABLE IF EXISTS t1,t2,t3,t4,t5,t6,t7,t8,t9;
+sync_slave_with_master;
+# Here we reset the value of the default storage engine
+STOP SLAVE;
+--source include/wait_for_slave_to_stop.inc
+SET GLOBAL default_storage_engine=@@default_storage_engine;
+START SLAVE;
+--source include/wait_for_slave_to_start.inc
+--enable_ps_protocol
+
+# BUG#22864 (Rollback following CREATE ... SELECT discards 'CREATE
+# table' from log):
+--echo ================ BUG#22864 ================
+
+--source include/rpl_reset.inc
+
+connection master;
+SET AUTOCOMMIT=0;
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (1),(2),(3);
+
+CREATE TABLE t2 ENGINE=INNODB SELECT * FROM t1;
+ROLLBACK;
+
+CREATE TABLE t3 ENGINE=INNODB SELECT * FROM t1;
+INSERT INTO t3 VALUES (4),(5),(6);
+ROLLBACK;
+
+CREATE TABLE t4 ENGINE=INNODB SELECT * FROM t1;
+INSERT INTO t1 VALUES (4),(5),(6);
+ROLLBACK;
+
+SHOW TABLES;
+SELECT * FROM t1 ORDER BY a;
+SELECT * FROM t2 ORDER BY a;
+SELECT * FROM t3 ORDER BY a;
+SELECT * FROM t4 ORDER BY a;
+--source include/show_binlog_events.inc
+sync_slave_with_master;
+SHOW TABLES;
+SELECT * FROM t1 ORDER BY a;
+SELECT * FROM t2 ORDER BY a;
+SELECT * FROM t3 ORDER BY a;
+SELECT * FROM t4 ORDER BY a;
+
+connection master;
+DROP TABLE IF EXISTS t1,t2,t3,t4;
+SET AUTOCOMMIT=1;
+sync_slave_with_master;
+
+# Some tests with temporary tables
+--source include/rpl_reset.inc
+
+connection master;
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (1),(2),(3);
+
+CREATE TABLE t2 (a INT) ENGINE=INNODB;
+
+BEGIN;
+INSERT INTO t2 SELECT a*a FROM t1;
+CREATE TEMPORARY TABLE tt1
+SELECT a+1 AS a
+ FROM t1
+ WHERE a MOD 2 = 1;
+INSERT INTO t2 SELECT a+2 FROM tt1;
+COMMIT;
+
+SELECT * FROM t2 ORDER BY a;
+--source include/show_binlog_events.inc
+sync_slave_with_master;
+SELECT * FROM t2 ORDER BY a;
+
+connection master;
+TRUNCATE TABLE t2;
+sync_slave_with_master;
+
+--source include/rpl_reset.inc
+
+connection master;
+BEGIN;
+INSERT INTO t2 SELECT a*a FROM t1;
+CREATE TEMPORARY TABLE tt2
+SELECT a+1 AS a
+ FROM t1
+ WHERE a MOD 2 = 1;
+INSERT INTO t2 SELECT a+2 FROM tt2;
+ROLLBACK;
+
+SELECT * FROM t2 ORDER BY a;
+source include/show_binlog_events.inc;
+sync_slave_with_master;
+SELECT * FROM t2 ORDER BY a;
+
+connection master;
+DROP TABLE t1,t2;
+sync_slave_with_master;
+
+#
+# bug#35762 Failing CREATE-SELECT produces bad binlog in row mode
+#
+
+connection master;
+
+CREATE TABLE t1 (a INT);
+
+INSERT INTO t1 VALUES (1),(1);
+--error ER_DUP_ENTRY
+CREATE TABLE t2 (a INT UNIQUE) ENGINE=INNODB SELECT * FROM t1;
+INSERT INTO t1 VALUES (2);
+
+sync_slave_with_master;
+# connection slave;
+
+--echo *** the proof of the fix:
+--echo select must show that the last insert performed on the slave ***
+SELECT * FROM t1;
+
+connection master;
+DROP TABLE t1;
+sync_slave_with_master;
+
+#
+# BUG#34707: Row based replication: slave creates table within wrong database
+#
+
+--source include/rpl_reset.inc
+
+connection master;
+--disable_warnings
+DROP DATABASE IF EXISTS mysqltest1;
+--enable_warnings
+CREATE DATABASE mysqltest1;
+
+CREATE TABLE mysqltest1.without_select (f1 BIGINT);
+CREATE TABLE mysqltest1.with_select AS SELECT 1 AS f1;
+source include/show_binlog_events.inc;
+sync_slave_with_master;
+
+connection master;
+DROP DATABASE mysqltest1;
+sync_slave_with_master;
+
+#
+# BUG#48506: crash in CREATE TABLE <existing_view> IF NOT EXISTS LIKE
+# <tmp_tbl> with RBL
+#
+
+--source include/rpl_reset.inc
+
+connection master;
+CREATE TEMPORARY TABLE t7(c1 INT);
+CREATE TABLE t5(c1 INT);
+CREATE TABLE t4(c1 INT);
+CREATE VIEW bug48506_t1 AS SELECT 1;
+CREATE VIEW bug48506_t2 AS SELECT * FROM t4;
+CREATE VIEW bug48506_t3 AS SELECT t5.c1 AS A, t4.c1 AS B FROM t5, t4;
+CREATE TABLE bug48506_t4(c1 INT);
+--disable_warnings
+sync_slave_with_master;
+DROP VIEW bug48506_t1, bug48506_t2, bug48506_t3;
+DROP TABLE bug48506_t4;
+
+connection master;
+CREATE TABLE IF NOT EXISTS bug48506_t1 LIKE t7;
+CREATE TABLE IF NOT EXISTS bug48506_t2 LIKE t7;
+CREATE TABLE IF NOT EXISTS bug48506_t3 LIKE t7;
+CREATE TABLE IF NOT EXISTS bug48506_t4 LIKE t7;
+--enable_warnings
+sync_slave_with_master;
+
+SHOW TABLES LIKE 'bug48506%';
+
+connection master;
+DROP VIEW IF EXISTS bug48506_t1, bug48506_t2, bug48506_t3;
+DROP TEMPORARY TABLES t7;
+DROP TABLES t4, t5;
+DROP TABLES IF EXISTS bug48506_t4;
+
+--source include/rpl_end.inc
+
+--echo end of the tests
diff --git a/mysql-test/suite/rpl/t/rpl_row_delayed_ins.test b/mysql-test/suite/rpl/t/rpl_row_delayed_ins.test
new file mode 100644
index 00000000..603af398
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_row_delayed_ins.test
@@ -0,0 +1,2 @@
+let $engine_type=myisam;
+-- source include/rpl_row_delayed_ins.test
diff --git a/mysql-test/suite/rpl/t/rpl_row_drop.test b/mysql-test/suite/rpl/t/rpl_row_drop.test
new file mode 100644
index 00000000..4df6e2ad
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_row_drop.test
@@ -0,0 +1,38 @@
+-- source include/have_binlog_format_row.inc
+-- source include/master-slave.inc
+
+# Bug#12415: DROP of temporary table on master stops slave
+connection master;
+CREATE TABLE t1 (a int);
+CREATE TABLE t2 (a int);
+CREATE TEMPORARY TABLE t2 (a int, b int);
+SHOW TABLES;
+sync_slave_with_master;
+SHOW TABLES;
+connection master;
+DROP TABLE t2; # Dropping the temporary table
+SHOW TABLES;
+sync_slave_with_master;
+SHOW TABLES; # There should be two tables on the slave
+
+connection master;
+CREATE TEMPORARY TABLE t2 (a int, b int);
+SHOW TABLES;
+sync_slave_with_master;
+SHOW TABLES;
+connection master;
+# Should drop the non-temporary table t1 and the temporary table t2
+DROP TABLE t1,t2;
+source include/show_binlog_events.inc;
+SHOW TABLES;
+sync_slave_with_master;
+SHOW TABLES;
+
+--disable_query_log
+--disable_warnings
+connection master;
+DROP TABLE IF EXISTS t2;
+sync_slave_with_master;
+--enable_warnings
+--enable_query_log
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_row_drop_create_temp_table.test b/mysql-test/suite/rpl/t/rpl_row_drop_create_temp_table.test
new file mode 100644
index 00000000..bc5c6074
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_row_drop_create_temp_table.test
@@ -0,0 +1,11 @@
+###################################################################################
+# This test cases evaluates the mixture of non-transactional and transcational
+# tables. Specifically when drop temporary tables and create temporary tables
+# are used.
+###################################################################################
+--source include/have_binlog_format_row.inc
+--source include/have_innodb.inc
+--source include/master-slave.inc
+
+--source include/rpl_drop_create_temp_table.test
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_row_drop_temp_table.test b/mysql-test/suite/rpl/t/rpl_row_drop_temp_table.test
new file mode 100644
index 00000000..ba3770d3
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_row_drop_temp_table.test
@@ -0,0 +1,54 @@
+# ==== Purpose ====
+#
+# Test verifies that plain DROP TEMPORARY TABLE IF EXISTS statements are not
+# replicated during row based replication.
+#
+# ==== Implementation ====
+#
+# Steps:
+# 0 - Have a read_only master and slave. Binlog format should be "ROW".
+# 1 - Create a procedure which executes DROP TEMPORARY TABLE IF EXISTS
+# statements prior to CREATE TEMPORARY TABLE.
+# 2 - Execute the procedure.
+# 3 - Verify that the DROP TEMPORARY TABLE IF EXISTS statements within the
+# procedure are not written to the binary log.
+#
+# ==== References ====
+#
+# MDEV-20091: DROP TEMPORARY table is logged despite no CREATE was logged
+#
+
+--source include/have_binlog_format_row.inc
+--source include/have_innodb.inc
+--source include/master-slave.inc
+
+connection slave;
+SET GLOBAL read_only=1;
+
+connection master;
+DELIMITER |;
+CREATE PROCEDURE testproc()
+BEGIN
+ DROP TEMPORARY TABLE IF EXISTS t1_tmp;
+ DROP TEMPORARY TABLE IF EXISTS t2_tmp;
+ CREATE TEMPORARY TABLE IF NOT EXISTS t1_tmp ( t1 varchar(400) DEFAULT NULL) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+ CREATE TEMPORARY TABLE IF NOT EXISTS t2_tmp ( t2 varchar(16) NOT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+END|
+DELIMITER ;|
+SET GLOBAL read_only=1;
+CALL testproc();
+--echo ******** None of the above DROP TEMPORARY TABLE statement should be found in binary log ********
+--source include/show_binlog_events.inc
+--sync_slave_with_master
+SELECT @@read_only;
+
+--echo ======== CLEAN UP =========
+connection master;
+DROP TEMPORARY TABLE t1_tmp;
+DROP TEMPORARY TABLE t2_tmp;
+DROP PROCEDURE testproc;
+SET GLOBAL read_only=0;
+--sync_slave_with_master
+SET GLOBAL read_only=0;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_row_end_of_statement_loss-master.opt b/mysql-test/suite/rpl/t/rpl_row_end_of_statement_loss-master.opt
new file mode 100644
index 00000000..144bbca0
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_row_end_of_statement_loss-master.opt
@@ -0,0 +1,2 @@
+--binlog-row-event-max-size=8192
+
diff --git a/mysql-test/suite/rpl/t/rpl_row_end_of_statement_loss.test b/mysql-test/suite/rpl/t/rpl_row_end_of_statement_loss.test
new file mode 100644
index 00000000..5b2d99f3
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_row_end_of_statement_loss.test
@@ -0,0 +1,66 @@
+--source include/have_debug.inc
+--source include/have_binlog_format_row.inc
+--source include/master-slave.inc
+
+# Loss of STMT_END flagged event must error out the IO thread
+--connection slave
+call mtr.add_suppression("Slave IO thread did not receive an expected Rows-log end-of-statement");
+call mtr.add_suppression("Relay log write failure: could not queue event from master");
+
+SET @save_debug= @@global.debug;
+SET GLOBAL debug_dbug="+d,simulate_stmt_end_rows_event_loss";
+--source include/stop_slave.inc
+--replace_result $MASTER_MYPORT MASTER_PORT
+--eval CHANGE MASTER TO master_host = '127.0.0.1', master_port = $MASTER_MYPORT, MASTER_USE_GTID=SLAVE_POS
+
+--connection master
+--let $max_row_size=8192
+--eval CREATE TABLE t (a INT, b text($max_row_size));
+--eval INSERT INTO t values (1, repeat('b', $max_row_size)), (1, repeat('b', $max_row_size))
+
+# Prove that the missed STMT_END marked rows-event causes the io thread stop.
+--connection slave
+START SLAVE IO_THREAD;
+--let $slave_io_errno=1595
+--source include/wait_for_slave_io_error.inc
+SET GLOBAL debug_dbug="-d,simulate_stmt_end_rows_event_loss";
+--source include/start_slave.inc
+
+--connection master
+sync_slave_with_master;
+
+# Compressed version of the above
+--connection slave
+--source include/stop_slave.inc
+
+--connection master
+SET @save_log_bin_compress= @@GLOBAL.log_bin_compress;
+SET @save_log_bin_compress_min_len= @@GLOBAL.log_bin_compress_min_len;
+
+SET @@GLOBAL.log_bin_compress=ON;
+SET @@GLOBAL.log_bin_compress_min_len=10;
+
+--eval INSERT INTO t values (2, repeat('b', $max_row_size)), (2, repeat('b', $max_row_size))
+
+# Prove that the missed STMT_END marked rows-event causes the io thread stop.
+--connection slave
+SET GLOBAL debug_dbug="+d,simulate_stmt_end_rows_event_loss";
+START SLAVE IO_THREAD;
+--let $slave_io_errno=1595
+--source include/wait_for_slave_io_error.inc
+SET GLOBAL debug_dbug="-d,simulate_stmt_end_rows_event_loss";
+--source include/start_slave.inc
+
+--connection master
+sync_slave_with_master;
+
+# cleanup
+
+--connection master
+SET @@GLOBAL.log_bin_compress= @save_log_bin_compress;
+SET @@GLOBAL.log_bin_compress_min_len= @save_log_bin_compress_min_len;
+DROP TABLE t;
+sync_slave_with_master;
+SET GLOBAL debug_dbug= @save_debug;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_row_err_daisychain-master.opt b/mysql-test/suite/rpl/t/rpl_row_err_daisychain-master.opt
new file mode 100644
index 00000000..83ed8522
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_row_err_daisychain-master.opt
@@ -0,0 +1 @@
+--binlog-format=row
diff --git a/mysql-test/suite/rpl/t/rpl_row_err_daisychain-slave.opt b/mysql-test/suite/rpl/t/rpl_row_err_daisychain-slave.opt
new file mode 100644
index 00000000..4cb7a31d
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_row_err_daisychain-slave.opt
@@ -0,0 +1 @@
+--binlog-format=statement --log-slave-updates
diff --git a/mysql-test/suite/rpl/t/rpl_row_find_row.test b/mysql-test/suite/rpl/t/rpl_row_find_row.test
new file mode 100644
index 00000000..444706ac
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_row_find_row.test
@@ -0,0 +1,103 @@
+# BUG#47312: RBR: Disabling key on slave breaks replication:
+# HA_ERR_WRONG_INDEX
+#
+# Description
+# ===========
+#
+# This test case checks whether disabling a key on a slave breaks
+# replication or not.
+#
+# Case #1, shows that while not using ALTER TABLE... DISABLE KEYS and
+# the slave has no key defined while the master has one, replication
+# won't break.
+#
+# Case #2, shows that before patch for BUG#47312, if defining key on
+# slave table, and later disable it, replication would break. This
+# has been fixed.
+#
+
+-- source include/have_binlog_format_row.inc
+-- source include/master-slave.inc
+
+#
+# Case #1: master has key, but slave has not.
+# Replication does not break.
+#
+
+SET SQL_LOG_BIN=0;
+CREATE TABLE t (a int, b int, c int, key(b));
+SET SQL_LOG_BIN=1;
+
+-- connection slave
+
+CREATE TABLE t (a int, b int, c int);
+
+-- connection master
+
+INSERT INTO t VALUES (1,2,4);
+INSERT INTO t VALUES (4,3,4);
+DELETE FROM t;
+
+-- sync_slave_with_master
+
+-- connection master
+DROP TABLE t;
+
+-- sync_slave_with_master
+
+#
+# Case #2: master has key, slave also has one,
+# but it gets disabled sometime.
+# Replication does not break anymore.
+#
+--source include/rpl_reset.inc
+-- connection master
+
+CREATE TABLE t (a int, b int, c int, key(b));
+
+-- sync_slave_with_master
+
+ALTER TABLE t DISABLE KEYS;
+
+-- connection master
+
+INSERT INTO t VALUES (1,2,4);
+INSERT INTO t VALUES (4,3,4);
+DELETE FROM t;
+
+-- sync_slave_with_master
+
+-- connection master
+DROP TABLE t;
+
+-- sync_slave_with_master
+
+#
+# BUG#53893: RBR: nullable unique key can lead to out-of-sync slave
+#
+
+#
+# We insert two rows. Both with part of UNIQUE KEY set to null.
+# Then we update the last row inserted. On master the correct
+# row is updated. On the slave the wrong row would be updated
+# because the engine would look it up by the NULL Unique KEY.
+# As a consquence, the wrong row would be updated.
+#
+
+-- source include/rpl_reset.inc
+-- connection master
+
+CREATE TABLE t1 (c1 INT NOT NULL, c2 INT NOT NULL, c3 INT, UNIQUE KEY(c1,c3), KEY(c2));
+INSERT INTO t1(c1,c2) VALUES(1,1);
+INSERT INTO t1(c1,c2) VALUES(1,2);
+UPDATE t1 SET c1=1000 WHERE c2=2;
+-- sync_slave_with_master
+
+-- let $diff_tables= master:t1, slave:t1
+-- source include/diff_tables.inc
+
+-- connection master
+DROP TABLE t1;
+-- sync_slave_with_master
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_row_find_row_debug.test b/mysql-test/suite/rpl/t/rpl_row_find_row_debug.test
new file mode 100644
index 00000000..e3edabe2
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_row_find_row_debug.test
@@ -0,0 +1,57 @@
+#
+# Bug#11760927: 53375: RBR + NO PK => HIGH LOAD ON SLAVE (TABLE SCAN/CPU) => SLAVE FAILURE
+#
+--source include/have_binlog_format_row.inc
+--source include/have_debug.inc
+--source include/master-slave.inc
+
+# SETUP
+# - setup log_warnings and debug
+--connection slave
+--source include/stop_slave.inc
+SET @saved_dbug = @@GLOBAL.debug_dbug;
+--let $log_warnings_save= `SELECT @@GLOBAL.log_warnings`
+
+SET GLOBAL log_warnings = 2;
+
+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.2.err;
+}
+
+# Assign env variable LOG_ERROR
+let LOG_ERROR=$log_error_;
+
+# force printing the notes to the error log
+SET GLOBAL debug_dbug="d,inject_long_find_row_note";
+--source include/start_slave.inc
+
+# test
+--connection master
+CREATE TABLE t1 (c1 INT);
+--sync_slave_with_master
+--connection master
+
+INSERT INTO t1 VALUES (1), (2);
+UPDATE t1 SET c1= 1000 WHERE c1=2;
+DELETE FROM t1;
+DROP TABLE t1;
+--sync_slave_with_master
+
+--echo # Check if any note related to long DELETE_ROWS and UPDATE_ROWS appears in the error log
+--let SEARCH_FILE=$log_error_
+--let SEARCH_PATTERN=The slave is applying a ROW event on behalf of an UPDATE statement on table t1 and is currently taking a considerable amount
+--source include/search_pattern_in_file.inc
+--let SEARCH_PATTERN=The slave is applying a ROW event on behalf of a DELETE statement on table t1 and is currently taking a considerable amount
+--source include/search_pattern_in_file.inc
+
+# cleanup
+--source include/stop_slave.inc
+SET @@GLOBAL.debug_dbug = @saved_dbug;
+--eval SET GLOBAL log_warnings = $log_warnings_save
+--source include/start_slave.inc
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_row_flsh_tbls.test b/mysql-test/suite/rpl/t/rpl_row_flsh_tbls.test
new file mode 100644
index 00000000..c10b3570
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_row_flsh_tbls.test
@@ -0,0 +1,7 @@
+# depends on the binlog output
+-- source include/have_binlog_format_row.inc
+--source include/binlog_start_pos.inc
+
+let $rename_event_pos= `select @binlog_start_pos + 819`;
+
+-- source include/rpl_flsh_tbls.test
diff --git a/mysql-test/suite/rpl/t/rpl_row_func001.test b/mysql-test/suite/rpl/t/rpl_row_func001.test
new file mode 100644
index 00000000..2327ba9a
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_row_func001.test
@@ -0,0 +1,60 @@
+#############################################################################
+# This test is being created to test out the non deterministic items with #
+# row based replication. #
+# Original Author: JBM #
+# Original Date: Aug/10/2005 #
+# Update: 08/29/2005 change name to initails #
+#############################################################################
+
+# Includes
+-- source include/have_binlog_format_row.inc
+-- source include/master-slave.inc
+
+
+# Begin clean up test section
+connection master;
+--disable_warnings
+--error 0,1305
+DROP FUNCTION test.f1;
+DROP TABLE IF EXISTS test.t1;
+
+
+--enable_warnings
+
+# Section 1 test from bug #12487 Uses stored function to insert rows to see what is replicated.
+
+create table test.t1 (a int, PRIMARY KEY(a));
+
+delimiter //;
+create function test.f1(i int) returns int
+begin
+insert into test.t1 values(i);
+return 0;
+end//
+delimiter ;//
+
+--disable_ps2_protocol
+select test.f1(1);
+select test.f1(2);
+--enable_ps2_protocol
+select * from test.t1;
+
+save_master_pos;
+sync_slave_with_master;
+connection slave;
+#show create table test.t1;
+select * from test.t1;
+
+connection master;
+
+#Used for debugging
+#show binlog events;
+
+# Cleanup
+
+DROP FUNCTION test.f1;
+DROP TABLE test.t1;
+sync_slave_with_master;
+
+# End of 5.0 test case
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_row_func002.test b/mysql-test/suite/rpl/t/rpl_row_func002.test
new file mode 100644
index 00000000..2f4e3fdd
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_row_func002.test
@@ -0,0 +1,105 @@
+#############################################################################
+# This test is being created to test out the non deterministic items with #
+# row based replication. #
+# Original Author: JBM #
+# Original Date: Aug/10/2005 #
+# Update: 08/29/2005 Turn on diff #
+#############################################################################
+# Note: Many lines are commented out in this test case. These were used for #
+# creating the test case and debugging and are being left for #
+# debugging, but they can not be used for the regular testing as the #
+# Time changes and is not deteministic, so instead we dump both the #
+# master and slave and diff the dumps. If the dumps differ then the #
+# test case will fail. To run during diff failuers, comment out the #
+# diff. #
+#############################################################################
+
+# Includes
+-- source include/have_binlog_format_row.inc
+-- source include/master-slave.inc
+
+
+# Begin clean up test section
+connection master;
+--disable_warnings
+--error 0,1305
+DROP FUNCTION test.f1;
+DROP TABLE IF EXISTS test.t1;
+DROP TABLE IF EXISTS test.t2;
+
+--enable_warnings
+
+# Section 1 test from Peter G. This test changes uses a stored function to update rows and return the timestamp. We change the value of the time stamp on the master to see what is replicated.
+
+CREATE TABLE test.t1 (a INT NOT NULL AUTO_INCREMENT, t TIMESTAMP, t2 TIMESTAMP, PRIMARY KEY(a));
+CREATE TABLE test.t2 (a INT NOT NULL AUTO_INCREMENT, t TIMESTAMP, t2 TIMESTAMP, PRIMARY KEY(a));
+
+delimiter //;
+create function test.f1() RETURNS TIMESTAMP
+BEGIN
+UPDATE test.t1 SET t = CURRENT_TIMESTAMP;
+RETURN CURRENT_TIMESTAMP;
+END//
+delimiter ;//
+
+INSERT INTO test.t2 VALUES (null,f1(),CURRENT_TIMESTAMP);
+#select * from test.t1;
+#save_master_pos;
+#sync_slave_with_master;
+#connection slave;
+#select * from test.t1;
+#connection master;
+
+
+SET TIMESTAMP=2;
+INSERT INTO test.t2 VALUES (null,f1(),CURRENT_TIMESTAMP);
+#select * from test.t1;
+#save_master_pos;
+#sync_slave_with_master;
+#connection slave;
+#select * from test.t1;
+#connection master;
+
+#sleep 3;
+SET TIMESTAMP=1;
+INSERT INTO test.t2 VALUES (null,f1(),CURRENT_TIMESTAMP);
+#select * from test.t1;
+#save_master_pos;
+#sync_slave_with_master;
+#connection slave;
+#select * from test.t1;
+#connection master;
+
+
+SET TIMESTAMP=333300000;
+INSERT INTO test.t2 VALUES (null,f1(),CURRENT_TIMESTAMP);
+
+# We need a sync to ensure that the slave has caught up before
+# dumping the database.
+sync_slave_with_master;
+
+connection master;
+#Used for debugging
+#show binlog events;
+
+# time to dump the databases and so we can see if they match
+
+--exec $MYSQL_DUMP --compact --order-by-primary --skip-extended-insert --no-create-info test > $MYSQLTEST_VARDIR/tmp/func002_master.sql
+--exec $MYSQL_DUMP_SLAVE --compact --order-by-primary --skip-extended-insert --no-create-info test > $MYSQLTEST_VARDIR/tmp/func002_slave.sql
+
+# Cleanup
+DROP FUNCTION test.f1;
+DROP TABLE test.t1;
+DROP TABLE test.t2;
+sync_slave_with_master;
+
+# the test will show that the diff statement failed and no reject file
+# will be created. You will need to go to the mysql-test dir and diff
+# the files your self to see what is not matching :-). The files are located
+# in mysql-test/var/tmp
+
+diff_files $MYSQLTEST_VARDIR/tmp/func002_master.sql $MYSQLTEST_VARDIR/tmp/func002_slave.sql;
+
+# End of 5.0 test case
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_row_func003.test b/mysql-test/suite/rpl/t/rpl_row_func003.test
new file mode 100644
index 00000000..def987fa
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_row_func003.test
@@ -0,0 +1,12 @@
+###################################
+# Wrapper for rpl_row_func003.test#
+###################################
+########################################################
+# By JBM 2005-02-15 Wrapped to allow reuse of test code#
+########################################################
+-- source include/have_innodb.inc
+-- source include/have_binlog_format_row.inc
+-- source include/master-slave.inc
+let $engine_type=INNODB;
+-- source include/rpl_row_func003.test
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_row_idempotency.test b/mysql-test/suite/rpl/t/rpl_row_idempotency.test
new file mode 100644
index 00000000..85775832
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_row_idempotency.test
@@ -0,0 +1,333 @@
+# Testing various forms of idempotency for replication. This file is
+# for tests that should only be executed in row mode.
+
+source include/have_binlog_format_row.inc;
+source include/master-slave.inc;
+connection master;
+source include/have_innodb.inc;
+connection slave;
+source include/have_innodb.inc;
+
+# Add suppression for expected warning(s) in slaves error log
+call mtr.add_suppression("Can.t find record in .t[12].* error.* 1032");
+call mtr.add_suppression("Cannot delete or update a parent row: a foreign key constraint fails .* error.* 1451");
+call mtr.add_suppression("Cannot add or update a child row: a foreign key constraint fails .* error.* 1452");
+call mtr.add_suppression("Duplicate entry .1. for key .PRIMARY.* error.* 1062");
+call mtr.add_suppression("Can't find record in 't1'");
+call mtr.add_suppression("Can't find record in 't2'");
+
+
+# bug#31609 Not all RBR slave errors reported as errors
+# bug#31552 Replication breaks when deleting rows from out-of-sync table
+# without PK
+
+# The default for slave-exec-mode option and server
+# variable slave_exec_mode is 'STRICT'.
+# When 'STRICT' mode is set, the slave SQL thread will stop whenever
+# the row to change is not found. In 'IDEMPOTENT' mode, the SQL thread
+# will continue running and apply the row - replace if it's Write_rows event -
+# or skip to the next event.
+
+# the previous part of the tests was with IDEMPOTENT slave's mode.
+
+
+#
+# Other than above idempotent errors dealing with foreign keys constraint
+#
+connection slave;
+
+set @old_slave_exec_mode= @@global.slave_exec_mode;
+set @@global.slave_exec_mode= IDEMPOTENT;
+
+connection master;
+
+create table ti1 (b int primary key) engine = innodb;
+create table ti2 (a int primary key, b int, foreign key (b) references ti1(b))
+ engine = innodb;
+set foreign_key_checks=1 /* ensure the check */;
+
+insert into ti1 values (1),(2),(3);
+insert into ti2 set a=2, b=2;
+
+sync_slave_with_master;
+
+#connection slave;
+select * from ti1 order by b /* must be (1),(2),(3) */;
+insert into ti2 set a=1, b=1;
+select * from ti2 order by b /* must be (1,1) (2,2) */;
+
+connection master;
+
+# from now on checking rbr specific idempotent errors
+set @save_binlog_format= @@session.binlog_format;
+set @@session.binlog_format= row;
+delete from ti1 where b=1;
+
+select * from ti1 order by b /* must be (2),(3) */;
+
+# slave must catch up (expect some warnings in error.log)
+sync_slave_with_master;
+
+#connection slave;
+select * from ti1 order by b /* must stays as were on master (1),(2),(3) */;
+
+delete from ti1 where b=3;
+
+connection master;
+insert into ti2 set a=3, b=3;
+
+# slave must catch up (expect some warnings in error.log)
+sync_slave_with_master;
+
+#connection slave;
+select * from ti2 order by b /* must be (1,1),(2,2) - not inserted */;
+
+
+#
+# Checking the new global sys variable
+#
+
+connection slave;
+
+set global slave_exec_mode='IDEMPOTENT';
+set global slave_exec_mode='STRICT';
+
+# checking mutual exclusion for the options
+--error ER_WRONG_VALUE_FOR_VAR
+set global slave_exec_mode='IDEMPOTENT,STRICT';
+
+select @@global.slave_exec_mode /* must be STRICT */;
+
+#
+# Checking stops.
+# In the following sections strict slave sql thread is going to
+# stop when faces an idempotent error. In order to proceed
+# the mode is temporarily switched to indempotent.
+#
+
+#
+--echo *** foreign keys errors as above now forces to stop
+#
+
+connection master;
+
+set foreign_key_checks=0;
+drop table ti2, ti1;
+
+create table ti1 (b int primary key) engine = innodb;
+create table ti2 (a int primary key, b int, foreign key (b) references ti1(b))
+ engine = innodb;
+set foreign_key_checks=1 /* ensure the check */;
+
+insert into ti1 values (1),(2),(3);
+insert into ti2 set a=2, b=2;
+
+sync_slave_with_master;
+
+#connection slave;
+select * from ti1 order by b /* must be (1),(2),(3) */;
+--echo *** conspire future problem
+insert into ti2 set a=1, b=1;
+select * from ti2 order by b /* must be (1,1) (2,2) */;
+
+connection master;
+
+delete from ti1 where b=1 /* offending delete event */;
+select * from ti1 order by b /* must be (2),(3) */;
+
+# foreign key: row is referenced
+
+--echo *** slave must stop (Trying to delete a referenced foreing key)
+connection slave;
+source include/wait_for_slave_sql_to_stop.inc;
+
+let $last_error = query_get_value("SHOW SLAVE STATUS", Last_SQL_Errno, 1);
+disable_query_log;
+eval SELECT "$last_error" AS Last_SQL_Error;
+enable_query_log;
+
+select * from ti1 order by b /* must be (1),(2),(3) - not deleted */;
+set foreign_key_checks= 0;
+delete from ti2 where b=1;
+set foreign_key_checks= 1;
+set global slave_exec_mode='IDEMPOTENT';
+start slave sql_thread;
+connection master;
+sync_slave_with_master;
+#connection slave;
+set global slave_exec_mode='STRICT';
+
+connection master;
+
+sync_slave_with_master;
+
+#connection slave;
+--echo *** conspire the following insert failure
+# foreign key: no referenced row
+
+--echo *** conspire future problem
+delete from ti1 where b=3;
+
+connection master;
+insert into ti2 set a=3, b=3 /* offending write event */;
+
+--echo *** slave must stop (Trying to insert an invalid foreign key)
+connection slave;
+source include/wait_for_slave_sql_to_stop.inc;
+
+let $last_error = query_get_value("SHOW SLAVE STATUS", Last_SQL_Errno, 1);
+disable_query_log;
+eval SELECT "$last_error" AS Last_SQL_Error;
+enable_query_log;
+
+select * from ti2 order by b /* must be (2,2) */;
+set foreign_key_checks= 0;
+insert into ti1 set b=3;
+set foreign_key_checks= 1;
+set global slave_exec_mode='IDEMPOTENT';
+start slave sql_thread;
+connection master;
+sync_slave_with_master;
+#connection slave;
+set global slave_exec_mode='STRICT';
+
+connection master;
+
+sync_slave_with_master;
+
+select * from ti2 order by b /* must be (2,2),(3,3) */;
+
+#
+--echo *** other errors
+#
+
+# dup key insert
+
+#connection slave;
+--echo *** conspiring query
+insert into ti1 set b=1;
+
+connection master;
+insert into ti1 set b=1 /* offending write event */;
+
+--echo *** slave must stop (Trying to insert a dupliacte key)
+connection slave;
+source include/wait_for_slave_sql_to_stop.inc;
+
+let $last_error = query_get_value("SHOW SLAVE STATUS", Last_SQL_Errno, 1);
+disable_query_log;
+eval SELECT "$last_error" AS Last_SQL_Error;
+enable_query_log;
+
+set foreign_key_checks= 0;
+delete from ti1 where b=1;
+set foreign_key_checks= 1;
+set global slave_exec_mode='IDEMPOTENT';
+start slave sql_thread;
+connection master;
+sync_slave_with_master;
+#connection slave;
+set global slave_exec_mode='STRICT';
+
+# key not found
+
+connection master;
+
+CREATE TABLE t1 (a INT PRIMARY KEY);
+CREATE TABLE t2 (a INT);
+INSERT INTO t1 VALUES (-1),(-2),(-3);
+INSERT INTO t2 VALUES (-1),(-2),(-3);
+sync_slave_with_master;
+
+#connection slave;
+DELETE FROM t1 WHERE a = -2;
+DELETE FROM t2 WHERE a = -2;
+connection master;
+DELETE FROM t1 WHERE a = -2;
+
+--echo *** slave must stop (Key was not found)
+connection slave;
+source include/wait_for_slave_sql_to_stop.inc;
+
+let $last_error = query_get_value("SHOW SLAVE STATUS", Last_SQL_Errno, 1);
+disable_query_log;
+eval SELECT "$last_error" AS Last_SQL_Error;
+enable_query_log;
+
+set global slave_exec_mode='IDEMPOTENT';
+start slave sql_thread;
+connection master;
+sync_slave_with_master;
+#connection slave;
+set global slave_exec_mode='STRICT';
+
+connection master;
+DELETE FROM t2 WHERE a = -2;
+--echo *** slave must stop (Key was not found)
+connection slave;
+source include/wait_for_slave_sql_to_stop.inc;
+
+let $last_error = query_get_value("SHOW SLAVE STATUS", Last_SQL_Errno, 1);
+disable_query_log;
+eval SELECT "$last_error" AS Last_SQL_Error;
+enable_query_log;
+
+set global slave_exec_mode='IDEMPOTENT';
+start slave sql_thread;
+connection master;
+sync_slave_with_master;
+#connection slave;
+set global slave_exec_mode='STRICT';
+
+UPDATE t1 SET a = 1 WHERE a = -1;
+UPDATE t2 SET a = 1 WHERE a = -1;
+
+connection master;
+UPDATE t1 SET a = 1 WHERE a = -1;
+
+--echo *** slave must stop (Key was not found)
+connection slave;
+source include/wait_for_slave_sql_to_stop.inc;
+
+let $last_error = query_get_value("SHOW SLAVE STATUS", Last_SQL_Errno, 1);
+disable_query_log;
+eval SELECT "$last_error" AS Last_SQL_Error;
+enable_query_log;
+
+set global slave_exec_mode='IDEMPOTENT';
+start slave sql_thread;
+connection master;
+sync_slave_with_master;
+#connection slave;
+set global slave_exec_mode='STRICT';
+
+
+connection master;
+UPDATE t2 SET a = 1 WHERE a = -1;
+
+--echo *** slave must stop (Key was not found)
+connection slave;
+source include/wait_for_slave_sql_to_stop.inc;
+
+let $last_error = query_get_value("SHOW SLAVE STATUS", Last_SQL_Errno, 1);
+disable_query_log;
+eval SELECT "$last_error" AS Last_SQL_Error;
+enable_query_log;
+
+set global slave_exec_mode='IDEMPOTENT';
+start slave sql_thread;
+connection master;
+sync_slave_with_master;
+#connection slave;
+SET @@global.slave_exec_mode= @old_slave_exec_mode;
+
+# cleanup for bug#31609 tests
+
+connection master;
+
+drop table t1,t2,ti2,ti1;
+sync_slave_with_master;
+set @@global.slave_exec_mode= @old_slave_exec_mode;
+
+--echo *** end of tests
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_row_img.cnf b/mysql-test/suite/rpl/t/rpl_row_img.cnf
new file mode 100644
index 00000000..ed9a4292
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_row_img.cnf
@@ -0,0 +1,21 @@
+!include include/default_mysqld.cnf
+
+[mysqld.1]
+log-slave-updates
+innodb
+innodb_flush_log_at_trx_commit= 0
+
+[mysqld.2]
+log-slave-updates
+innodb
+innodb_flush_log_at_trx_commit= 0
+
+[mysqld.3]
+log-slave-updates
+innodb
+innodb_flush_log_at_trx_commit= 0
+
+[ENV]
+SERVER_MYPORT_1= @mysqld.1.port
+SERVER_MYPORT_2= @mysqld.2.port
+SERVER_MYPORT_3= @mysqld.3.port
diff --git a/mysql-test/suite/rpl/t/rpl_row_img_blobs.cnf b/mysql-test/suite/rpl/t/rpl_row_img_blobs.cnf
new file mode 100644
index 00000000..d758d29f
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_row_img_blobs.cnf
@@ -0,0 +1 @@
+!include suite/rpl/t/rpl_row_img.cnf
diff --git a/mysql-test/suite/rpl/t/rpl_row_img_blobs.test b/mysql-test/suite/rpl/t/rpl_row_img_blobs.test
new file mode 100644
index 00000000..21f224f5
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_row_img_blobs.test
@@ -0,0 +1,59 @@
+#Want to skip this test from daily Valgrind execution
+--source include/no_valgrind_without_big.inc
+
+#
+# This file contains tests for WL#5096.
+#
+
+--let $rpl_topology= 1->2->3
+--source include/rpl_init.inc
+-- source include/have_binlog_format_row.inc
+
+-- connection server_1
+-- source include/have_innodb.inc
+-- connection server_2
+-- source include/have_innodb.inc
+-- connection server_3
+-- source include/have_innodb.inc
+-- connection server_1
+
+#
+# WL#5096 Tests.
+#
+
+#
+# Tests combinations of binlog-row-image against mixes of MyISAM and InnoDB
+# storage engines on all three servers.
+#
+# All the combinarions need not to be separated into their own files as
+# the tests for indexes and engines mixes are, because noblobs test script
+# does not take too long time, thence we do not risk triggering PB2 timeout
+# on valgrind runs.
+#
+
+## NOBLOB
+
+-- let $row_img_set=server_1:NOBLOB:N,server_2:NOBLOB:Y,server_3:NOBLOB:Y
+-- source include/rpl_row_img_set.inc
+
+-- let $row_img_test_script= include/rpl_row_img_blobs.test
+-- source include/rpl_row_img_general_loop.inc
+
+## MINIMAL
+
+-- let $row_img_set=server_1:MINIMAL:N,server_2:MINIMAL:Y,server_3:MINIMAL:Y
+-- source include/rpl_row_img_set.inc
+
+-- let $row_img_test_script= include/rpl_row_img_blobs.test
+-- source include/rpl_row_img_general_loop.inc
+
+## FULL
+
+-- let $row_img_set=server_1:FULL:N,server_2:FULL:Y,server_3:FULL:Y
+-- source include/rpl_row_img_set.inc
+
+-- let $row_img_test_script= include/rpl_row_img_blobs.test
+-- source include/rpl_row_img_general_loop.inc
+
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_row_img_eng_min.cnf b/mysql-test/suite/rpl/t/rpl_row_img_eng_min.cnf
new file mode 100644
index 00000000..d758d29f
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_row_img_eng_min.cnf
@@ -0,0 +1 @@
+!include suite/rpl/t/rpl_row_img.cnf
diff --git a/mysql-test/suite/rpl/t/rpl_row_img_eng_min.test b/mysql-test/suite/rpl/t/rpl_row_img_eng_min.test
new file mode 100644
index 00000000..06764fe8
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_row_img_eng_min.test
@@ -0,0 +1,39 @@
+#Want to skip this test from daily Valgrind execution
+--source include/no_valgrind_without_big.inc
+#
+# This file contains tests for WL#5096 and bug fixes.
+#
+
+--let $rpl_topology= 1->2->3
+--source include/rpl_init.inc
+-- source include/have_binlog_format_row.inc
+
+-- connection server_1
+-- source include/have_innodb.inc
+-- connection server_2
+-- source include/have_innodb.inc
+-- connection server_3
+-- source include/have_innodb.inc
+-- connection server_1
+
+#
+# WL#5096
+#
+
+#
+# Tests for different storage engines on each server,
+# but same index structure on tables. The tests are conducted
+# using MINIMAL binlog-row-image on all servers.
+#
+
+-- let $row_img_set=server_1:MINIMAL:N,server_2:MINIMAL:Y,server_3:MINIMAL:Y
+-- source include/rpl_row_img_set.inc
+
+-- let $row_img_test_script= include/rpl_row_img.test
+-- source include/rpl_row_img_general_loop.inc
+
+-- let $row_img_set=server_1:FULL:N,server_2:FULL:Y,server_3:FULL:Y
+-- source include/rpl_row_img_set.inc
+
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_row_img_eng_noblob.cnf b/mysql-test/suite/rpl/t/rpl_row_img_eng_noblob.cnf
new file mode 100644
index 00000000..d758d29f
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_row_img_eng_noblob.cnf
@@ -0,0 +1 @@
+!include suite/rpl/t/rpl_row_img.cnf
diff --git a/mysql-test/suite/rpl/t/rpl_row_img_eng_noblob.test b/mysql-test/suite/rpl/t/rpl_row_img_eng_noblob.test
new file mode 100644
index 00000000..7f4944b5
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_row_img_eng_noblob.test
@@ -0,0 +1,39 @@
+#Want to skip this test from daily Valgrind execution
+--source include/no_valgrind_without_big.inc
+#
+# This file contains tests for WL#5096 and bug fixes.
+#
+
+--let $rpl_topology= 1->2->3
+--source include/rpl_init.inc
+-- source include/have_binlog_format_row.inc
+
+-- connection server_1
+-- source include/have_innodb.inc
+-- connection server_2
+-- source include/have_innodb.inc
+-- connection server_3
+-- source include/have_innodb.inc
+-- connection server_1
+
+#
+# WL#5096
+#
+
+#
+# Tests for different storage engines on each server,
+# but same index structure on tables. The tests are conducted
+# using NOBLOB binlog-row-image on all servers.
+#
+
+-- let $row_img_set=server_1:NOBLOB:N,server_2:NOBLOB:Y,server_3:NOBLOB:Y
+-- source include/rpl_row_img_set.inc
+
+-- let $row_img_test_script= include/rpl_row_img.test
+-- source include/rpl_row_img_general_loop.inc
+
+-- let $row_img_set=server_1:FULL:N,server_2:FULL:Y,server_3:FULL:Y
+-- source include/rpl_row_img_set.inc
+
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_row_img_sequence_full.cnf b/mysql-test/suite/rpl/t/rpl_row_img_sequence_full.cnf
new file mode 100644
index 00000000..7104b4e4
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_row_img_sequence_full.cnf
@@ -0,0 +1,21 @@
+!include include/default_mysqld.cnf
+
+[mysqld.1]
+log-slave-updates
+innodb
+gtid_domain_id=0
+
+[mysqld.2]
+log-slave-updates
+innodb
+gtid_domain_id=1
+
+[mysqld.3]
+log-slave-updates
+innodb
+gtid_domain_id=2
+
+[ENV]
+SERVER_MYPORT_1= @mysqld.1.port
+SERVER_MYPORT_2= @mysqld.2.port
+SERVER_MYPORT_3= @mysqld.3.port
diff --git a/mysql-test/suite/rpl/t/rpl_row_img_sequence_full.test b/mysql-test/suite/rpl/t/rpl_row_img_sequence_full.test
new file mode 100644
index 00000000..a0c6aa4d
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_row_img_sequence_full.test
@@ -0,0 +1,48 @@
+#
+# Purpose:
+# The rpl_row_img_sequence group of tests verify that sequence MDL updates,
+# i.e. NEXTVAL and SETVAL, respect the binlog_row_image variable value when
+# written into the binary log. In particular, it ensures that only changed
+# columns are written with MINIMAL image mode, and all columns are written
+# otherwise. This test focuses on validating the behavior of
+# binlog_row_img=FULL.
+#
+# Methodology
+# After issuing a sequence update, ensure that both 1) it was replicated
+# correctly, and 2) it was binlogged respective to the binlog_row_image value.
+# The sequence table does not use caching to ensure each update is immediately
+# binlogged. Each command is binlogged into its own unique log file, and the
+# entirety of the file is analyzed for correctness of its sequence event.
+# Specifically, mysqlbinlog is used in verbose mode so it outputs the columns
+# which belong to the event, and the columns are analyzed to ensure the correct
+# ones were logged. rpl_row_img_general_loop.inc is used to test with multiple
+# chained replicas, varying engines between InnoDB and MyISAM.
+#
+# References:
+# MDEV-28487: sequences not respect value of binlog_row_image with select
+# nextval(seq_gen)
+#
+
+--let $rpl_topology= 1->2->3
+--source include/rpl_init.inc
+--source include/have_binlog_format_row.inc
+
+--connection server_1
+--source include/have_innodb.inc
+--connection server_2
+--source include/have_innodb.inc
+--connection server_3
+--source include/have_innodb.inc
+--connection server_1
+
+--echo #
+--echo # binlog_row_image=FULL should write all columns to the binary log
+--echo #
+--let $row_img_set=server_1:FULL:N,server_2:FULL:Y,server_3:FULL:Y
+--source include/rpl_row_img_set.inc
+--let $expected_columns=(1,2,3,4,5,6,7,8)
+--let row_img_test_script= include/rpl_row_img_sequence.inc
+--source include/rpl_row_img_general_loop.inc
+
+--source include/rpl_end.inc
+--echo # End of tests
diff --git a/mysql-test/suite/rpl/t/rpl_row_img_sequence_min.cnf b/mysql-test/suite/rpl/t/rpl_row_img_sequence_min.cnf
new file mode 100644
index 00000000..7104b4e4
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_row_img_sequence_min.cnf
@@ -0,0 +1,21 @@
+!include include/default_mysqld.cnf
+
+[mysqld.1]
+log-slave-updates
+innodb
+gtid_domain_id=0
+
+[mysqld.2]
+log-slave-updates
+innodb
+gtid_domain_id=1
+
+[mysqld.3]
+log-slave-updates
+innodb
+gtid_domain_id=2
+
+[ENV]
+SERVER_MYPORT_1= @mysqld.1.port
+SERVER_MYPORT_2= @mysqld.2.port
+SERVER_MYPORT_3= @mysqld.3.port
diff --git a/mysql-test/suite/rpl/t/rpl_row_img_sequence_min.test b/mysql-test/suite/rpl/t/rpl_row_img_sequence_min.test
new file mode 100644
index 00000000..0a3b2827
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_row_img_sequence_min.test
@@ -0,0 +1,52 @@
+#
+# Purpose:
+# The rpl_row_img_sequence group of tests verify that sequence MDL updates,
+# i.e. NEXTVAL and SETVAL, respect the binlog_row_image variable value when
+# written into the binary log. In particular, it ensures that only changed
+# columns are written with MINIMAL image mode, and all columns are written
+# otherwise. This test focuses on validating the behavior of
+# binlog_row_img=MINIMAL.
+#
+# Methodology
+# After issuing a sequence update, ensure that both 1) it was replicated
+# correctly, and 2) it was binlogged respective to the binlog_row_image value.
+# The sequence table does not use caching to ensure each update is immediately
+# binlogged. Each command is binlogged into its own unique log file, and the
+# entirety of the file is analyzed for correctness of its sequence event.
+# Specifically, mysqlbinlog is used in verbose mode so it outputs the columns
+# which belong to the event, and the columns are analyzed to ensure the correct
+# ones were logged. rpl_row_img_general_loop.inc is used to test with multiple
+# chained replicas, varying engines between InnoDB and MyISAM.
+#
+# References:
+# MDEV-28487: sequences not respect value of binlog_row_image with select
+# nextval(seq_gen)
+#
+
+--let $rpl_topology= 1->2->3
+--source include/rpl_init.inc
+--source include/have_binlog_format_row.inc
+
+--connection server_1
+--source include/have_innodb.inc
+--connection server_2
+--source include/have_innodb.inc
+--connection server_3
+--source include/have_innodb.inc
+--connection server_1
+
+--echo #
+--echo # binlog_row_image=MINIMAL should write only columns 1 and 8 to the
+--echo # binary log
+--echo #
+--let $row_img_set=server_1:MINIMAL:N,server_2:MINIMAL:Y,server_3:MINIMAL:Y
+--source include/rpl_row_img_set.inc
+--let $expected_columns=(1,8)
+--let row_img_test_script= include/rpl_row_img_sequence.inc
+--source include/rpl_row_img_general_loop.inc
+
+--let $row_img_set=server_1:FULL:N,server_2:FULL:Y,server_3:FULL:Y
+--source include/rpl_row_img_set.inc
+
+--source include/rpl_end.inc
+--echo # End of tests
diff --git a/mysql-test/suite/rpl/t/rpl_row_img_sequence_noblob.cnf b/mysql-test/suite/rpl/t/rpl_row_img_sequence_noblob.cnf
new file mode 100644
index 00000000..7104b4e4
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_row_img_sequence_noblob.cnf
@@ -0,0 +1,21 @@
+!include include/default_mysqld.cnf
+
+[mysqld.1]
+log-slave-updates
+innodb
+gtid_domain_id=0
+
+[mysqld.2]
+log-slave-updates
+innodb
+gtid_domain_id=1
+
+[mysqld.3]
+log-slave-updates
+innodb
+gtid_domain_id=2
+
+[ENV]
+SERVER_MYPORT_1= @mysqld.1.port
+SERVER_MYPORT_2= @mysqld.2.port
+SERVER_MYPORT_3= @mysqld.3.port
diff --git a/mysql-test/suite/rpl/t/rpl_row_img_sequence_noblob.test b/mysql-test/suite/rpl/t/rpl_row_img_sequence_noblob.test
new file mode 100644
index 00000000..38ff469f
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_row_img_sequence_noblob.test
@@ -0,0 +1,51 @@
+#
+# Purpose:
+# The rpl_row_img_sequence group of tests verify that sequence MDL updates,
+# i.e. NEXTVAL and SETVAL, respect the binlog_row_image variable value when
+# written into the binary log. In particular, it ensures that only changed
+# columns are written with MINIMAL image mode, and all columns are written
+# otherwise. This test focuses on validating the behavior of
+# binlog_row_img=NOBLOB.
+#
+# Methodology
+# After issuing a sequence update, ensure that both 1) it was replicated
+# correctly, and 2) it was binlogged respective to the binlog_row_image value.
+# The sequence table does not use caching to ensure each update is immediately
+# binlogged. Each command is binlogged into its own unique log file, and the
+# entirety of the file is analyzed for correctness of its sequence event.
+# Specifically, mysqlbinlog is used in verbose mode so it outputs the columns
+# which belong to the event, and the columns are analyzed to ensure the correct
+# ones were logged. rpl_row_img_general_loop.inc is used to test with multiple
+# chained replicas, varying engines between InnoDB and MyISAM.
+#
+# References:
+# MDEV-28487: sequences not respect value of binlog_row_image with select
+# nextval(seq_gen)
+#
+
+--let $rpl_topology= 1->2->3
+--source include/rpl_init.inc
+--source include/have_binlog_format_row.inc
+
+--connection server_1
+--source include/have_innodb.inc
+--connection server_2
+--source include/have_innodb.inc
+--connection server_3
+--source include/have_innodb.inc
+--connection server_1
+
+--echo #
+--echo # binlog_row_image=NOBLOB should write all columns to the binary logs
+--echo #
+--let $row_img_set=server_1:NOBLOB:N,server_2:NOBLOB:Y,server_3:NOBLOB:Y
+--source include/rpl_row_img_set.inc
+--let $expected_columns=(1,2,3,4,5,6,7,8)
+--let row_img_test_script= include/rpl_row_img_sequence.inc
+--source include/rpl_row_img_general_loop.inc
+
+--let $row_img_set=server_1:FULL:N,server_2:FULL:Y,server_3:FULL:Y
+--source include/rpl_row_img_set.inc
+
+--source include/rpl_end.inc
+--echo # End of tests
diff --git a/mysql-test/suite/rpl/t/rpl_row_implicit_commit_binlog.test b/mysql-test/suite/rpl/t/rpl_row_implicit_commit_binlog.test
new file mode 100644
index 00000000..ba204b05
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_row_implicit_commit_binlog.test
@@ -0,0 +1,12 @@
+################################################################################
+# Check file include/rpl_implicit_commit_binlog.test
+################################################################################
+--source include/have_udf.inc
+--source include/have_binlog_format_row.inc
+--source include/have_innodb.inc
+--source include/master-slave.inc
+
+--let $engine=Innodb
+set session default_storage_engine=innodb;
+--source include/rpl_implicit_commit_binlog.test
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_row_index_choice.test b/mysql-test/suite/rpl/t/rpl_row_index_choice.test
new file mode 100644
index 00000000..958fa235
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_row_index_choice.test
@@ -0,0 +1,243 @@
+--source include/have_binlog_format_row.inc
+--source include/have_debug.inc
+--source include/have_innodb.inc
+--source include/master-slave.inc
+
+# Bug#58997: Row-based replication breaks on table with only fulltext index:
+connection master;
+CREATE TABLE t1 (a int, b varchar(100), fulltext(b)) engine=MyISAM;
+INSERT INTO t1 VALUES (1,"a"), (2,"b");
+UPDATE t1 SET b='A' WHERE a=1;
+DELETE FROM t1 WHERE a=2;
+
+sync_slave_with_master;
+
+connection slave;
+
+SELECT * FROM t1 ORDER BY a;
+
+connection master;
+DROP TABLE t1;
+
+
+# A utility table used to populate subsequent tables in various ways.
+connection master;
+CREATE TABLE t1 (d INT PRIMARY KEY) ENGINE=myisam;
+INSERT INTO t1 VALUES (0);
+INSERT INTO t1 SELECT d+1 FROM t1;
+INSERT INTO t1 SELECT d+2 FROM t1;
+INSERT INTO t1 SELECT d+4 FROM t1;
+INSERT INTO t1 SELECT d+8 FROM t1;
+INSERT INTO t1 SELECT d+16 FROM t1;
+INSERT INTO t1 SELECT d+32 FROM t1;
+INSERT INTO t1 SELECT d+64 FROM t1;
+INSERT INTO t1 SELECT d+128 FROM t1;
+INSERT INTO t1 SELECT d+256 FROM t1;
+INSERT INTO t1 SELECT d+512 FROM t1;
+
+# Test that we pick the better multi-column index, even if the
+# single-column index is more selective in the first column.
+CREATE TABLE t2 (a INT, b INT, c INT, d INT,
+ KEY wrong_key(a),
+ KEY expected_key(b,c),
+ KEY wrong_key2(c)) ENGINE=myisam;
+INSERT INTO t2 SELECT d DIV 10, d MOD 41, d MOD 37, d FROM t1;
+
+sync_slave_with_master;
+connection slave;
+ANALYZE TABLE t2;
+--echo # Slave will crash if using the wrong or no index
+SET @saved_dbug = @@GLOBAL.debug_dbug;
+SET GLOBAL debug_dbug="+d,slave_crash_if_wrong_index,slave_crash_if_table_scan";
+
+connection master;
+UPDATE t2 SET d=10042 WHERE d=42;
+DELETE FROM t2 WHERE d=53;
+
+sync_slave_with_master;
+connection slave;
+SET GLOBAL debug_dbug="";
+SELECT * FROM t2 WHERE d IN (10042,53);
+
+# Test that we don't pick a unique index with NULLS over a more selective
+# non-unique index.
+connection master;
+DROP TABLE t2;
+CREATE TABLE t2 (a INT, b INT, c INT, d INT NOT NULL, e INT,
+ UNIQUE wrong_key3(a,e),
+ KEY wrong_key4(b,c),
+ UNIQUE expected_key(d)) ENGINE=myisam;
+INSERT INTO t2 SELECT d DIV 10, d MOD 41, d MOD 37, d, NULL FROM t1;
+
+sync_slave_with_master;
+connection slave;
+ANALYZE TABLE t2;
+--echo # Slave will crash if using the wrong or no index
+SET GLOBAL debug_dbug="+d,slave_crash_if_wrong_index,slave_crash_if_table_scan";
+
+connection master;
+UPDATE t2 SET d=10042 WHERE d=42;
+DELETE FROM t2 WHERE d=53;
+
+sync_slave_with_master;
+connection slave;
+SET GLOBAL debug_dbug="";
+SELECT * FROM t2 WHERE d IN (10042,53);
+
+connection master;
+DROP TABLE t2;
+
+# Test that we pick a reasonable index when there is no rec_per_key[]
+# information (no ANALYZE TABLE).
+CREATE TABLE t2 (a INT NOT NULL, b INT NOT NULL, c INT NOT NULL, d INT NOT NULL,
+ KEY wrong_key5(b),
+ UNIQUE expected_key(d),
+ KEY wrong_key6(c)) ENGINE=myisam;
+INSERT INTO t2 SELECT d DIV 10, d MOD 41, d MOD 37, d FROM t1;
+
+sync_slave_with_master;
+connection slave;
+--echo # Slave will crash if using the wrong or no index
+SET GLOBAL debug_dbug="+d,slave_crash_if_wrong_index,slave_crash_if_table_scan";
+
+connection master;
+UPDATE t2 SET d=10042 WHERE d=42;
+DELETE FROM t2 WHERE d=53;
+
+sync_slave_with_master;
+connection slave;
+SET GLOBAL debug_dbug="";
+SELECT * FROM t2 WHERE d IN (10042,53);
+
+connection master;
+DROP TABLE t2;
+
+
+# Also test without ANALYZE when we pick the sub-optimal index.
+# In this case the key on (d) is the best one, but without ANALYZE TABLE we
+# have no information and will pick the first one on (b).
+# (This test should be updated if we improve the index selection, of course).
+CREATE TABLE t2 (a INT NOT NULL, b INT NOT NULL, c INT NOT NULL, d INT NOT NULL,
+ KEY expected_key(b),
+ KEY wrong_key7(d),
+ KEY wrong_key8(c)) ENGINE=myisam;
+INSERT INTO t2 SELECT d DIV 10, d MOD 41, d MOD 37, d FROM t1;
+
+sync_slave_with_master;
+connection slave;
+--echo # Slave will crash if using the wrong or no index
+SET GLOBAL debug_dbug="+d,slave_crash_if_wrong_index,slave_crash_if_table_scan";
+
+connection master;
+UPDATE t2 SET d=10042 WHERE d=42;
+DELETE FROM t2 WHERE d=53;
+
+sync_slave_with_master;
+connection slave;
+SET GLOBAL debug_dbug="";
+SELECT * FROM t2 WHERE d IN (10042,53);
+
+connection master;
+DROP TABLE t2;
+
+
+# Test that we pick the primary key for InnoDB, if available.
+CREATE TABLE t2 (a INT NOT NULL, b INT NOT NULL, c INT NOT NULL, d INT,
+ UNIQUE wrong_key9(d),
+ KEY wrong_key10(a),
+ PRIMARY KEY expected_key(c,b)) ENGINE=innodb;
+INSERT INTO t2 SELECT d DIV 10, d MOD 41, d MOD 37, d FROM t1;
+
+sync_slave_with_master;
+connection slave;
+--echo # Slave will crash if using the wrong or no index
+SET GLOBAL debug_dbug="+d,slave_crash_if_wrong_index,slave_crash_if_table_scan,slave_crash_if_index_scan";
+
+connection master;
+UPDATE t2 SET d=10042 WHERE d=42;
+DELETE FROM t2 WHERE d=53;
+
+sync_slave_with_master;
+connection slave;
+SET GLOBAL debug_dbug="";
+SELECT * FROM t2 WHERE d IN (10042,53);
+
+connection master;
+DROP TABLE t2;
+
+
+# Test that we pick a good index for InnoDB when primary key is not available.
+CREATE TABLE t2 (a INT NOT NULL, b INT NOT NULL, c INT NOT NULL, d INT, e INT,
+ UNIQUE wrong_key11(e),
+ KEY wrong_key12(a),
+ KEY expected_key(c,b)) ENGINE=innodb;
+INSERT INTO t2 SELECT d DIV 10, d MOD 41, d MOD 37, d, IF(d<10, d, NULL) FROM t1;
+
+sync_slave_with_master;
+connection slave;
+ANALYZE TABLE t2;
+--echo # Slave will crash if using the wrong or no index
+SET GLOBAL debug_dbug="+d,slave_crash_if_wrong_index,slave_crash_if_table_scan";
+
+connection master;
+UPDATE t2 SET d=10042 WHERE d=42;
+DELETE FROM t2 WHERE d=53;
+
+sync_slave_with_master;
+connection slave;
+SET GLOBAL debug_dbug="";
+SELECT * FROM t2 WHERE d IN (10042,53);
+
+connection master;
+DROP TABLE t2;
+
+
+# When there is no ANALYZE TABLE, InnoDB will just report "1" for index
+# cardinality for all indexes in rec_per_key. So currently we cannot choose
+# index to use intelligently. Just test that we work as expected (select
+# first index, remember that unique keys are sorted first by server).
+CREATE TABLE t2 (a INT NOT NULL, b INT NOT NULL, c INT NOT NULL, d INT, e INT,
+ KEY wrong_key13(a),
+ UNIQUE expected_key(e),
+ KEY wrong_key14(c,b)) ENGINE=innodb;
+INSERT INTO t2 SELECT d DIV 10, d MOD 41, d MOD 37, d, IF(d<10, d, NULL) FROM t1;
+
+sync_slave_with_master;
+connection slave;
+--echo # Slave will crash if using the wrong or no index
+SET GLOBAL debug_dbug="+d,slave_crash_if_wrong_index,slave_crash_if_table_scan";
+
+connection master;
+UPDATE t2 SET d=10042 WHERE d=42;
+DELETE FROM t2 WHERE d=53;
+
+sync_slave_with_master;
+connection slave;
+SET GLOBAL debug_dbug="";
+SELECT * FROM t2 WHERE d IN (10042,53);
+
+connection master;
+DROP TABLE t2;
+
+
+# Finally, test behaviour when no indexes are available at all.
+CREATE TABLE t2 (a INT NOT NULL, d INT) ENGINE=innodb;
+INSERT INTO t2 SELECT d DIV 10, d FROM t1;
+
+UPDATE t2 SET d=10042 WHERE d=42;
+DELETE FROM t2 WHERE d=53;
+
+sync_slave_with_master;
+connection slave;
+SELECT * FROM t2 WHERE d IN (10042,53);
+
+connection master;
+DROP TABLE t2;
+
+
+connection master;
+DROP TABLE t1;
+sync_slave_with_master;
+connection slave;
+SET @@GLOBAL.debug_dbug = @saved_dbug;
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_row_inexist_tbl.test b/mysql-test/suite/rpl/t/rpl_row_inexist_tbl.test
new file mode 100644
index 00000000..907e309a
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_row_inexist_tbl.test
@@ -0,0 +1,40 @@
+# ==== Purpose ====
+#
+# Verify that slave gives an error message if master updates a table
+# that slave does not have.
+#
+# ==== Method ====
+#
+# Create a table on master, wait till it's on slave, remove it from
+# slave. Then update the table on master.
+
+--source include/have_binlog_format_row.inc
+
+source include/master-slave.inc;
+
+--echo ==== Setup table on master but not on slave ====
+CREATE TABLE t1 (a INT);
+
+sync_slave_with_master;
+DROP TABLE t1;
+
+--echo ==== Modify table on master ====
+connection master;
+INSERT INTO t1 VALUES (1);
+
+--echo ==== Verify error on slave ====
+connection slave;
+# slave should have stopped because can't find table t1
+# 1146 = ER_NO_SUCH_TABLE
+call mtr.add_suppression("Slave SQL.*Error executing row event: .Table .test.t1. doesn.t exist., error.* 1146");
+--let $slave_sql_errno= 1146
+--source include/wait_for_slave_sql_error.inc
+
+--echo ==== Clean up ====
+source include/stop_slave_io.inc;
+RESET SLAVE;
+
+connection master;
+DROP TABLE t1;
+--let $rpl_only_running_threads= 1
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_row_lcase_tblnames-slave.opt b/mysql-test/suite/rpl/t/rpl_row_lcase_tblnames-slave.opt
new file mode 100644
index 00000000..7624b013
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_row_lcase_tblnames-slave.opt
@@ -0,0 +1 @@
+--replicate-do-db=bug_37656 --replicate-ignore-table=buG_37656.T1 --replicate-do-table=bUg_37656.T2 --replicate-do-table=bUg_37656.T3 --lower-case-table-names=1
diff --git a/mysql-test/suite/rpl/t/rpl_row_lcase_tblnames.test b/mysql-test/suite/rpl/t/rpl_row_lcase_tblnames.test
new file mode 100644
index 00000000..7decd130
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_row_lcase_tblnames.test
@@ -0,0 +1,12 @@
+# BUG#37656
+#
+# For details look into extra/rpl_tests/rpl_lower_case_table_names.test
+#
+
+-- source include/not_windows.inc
+-- source include/have_innodb.inc
+-- source include/have_binlog_format_row.inc
+-- source include/master-slave.inc
+
+-- let $engine=InnoDB
+-- source include/rpl_lower_case_table_names.test
diff --git a/mysql-test/suite/rpl/t/rpl_row_loaddata_concurrent.test b/mysql-test/suite/rpl/t/rpl_row_loaddata_concurrent.test
new file mode 100644
index 00000000..c2cb2b4a
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_row_loaddata_concurrent.test
@@ -0,0 +1,13 @@
+-- source include/have_log_bin.inc
+-- source include/have_binlog_format_row.inc
+
+let $binlog_start= query_get_value(SHOW MASTER STATUS, Position, 1);
+CREATE TABLE t1 (c1 char(50)) engine=myisam;
+LOAD DATA INFILE '../../std_data/words.dat' INTO TABLE t1;
+LOAD DATA CONCURRENT INFILE '../../std_data/words.dat' INTO TABLE t1;
+-- source include/show_binlog_events.inc
+DROP TABLE t1;
+
+let $lock_option= CONCURRENT;
+let $engine_type=MyISAM;
+-- source include/rpl_loaddata.test
diff --git a/mysql-test/suite/rpl/t/rpl_row_log-master.opt b/mysql-test/suite/rpl/t/rpl_row_log-master.opt
new file mode 100644
index 00000000..e0d075c3
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_row_log-master.opt
@@ -0,0 +1 @@
+--skip-external-locking
diff --git a/mysql-test/suite/rpl/t/rpl_row_log-slave.opt b/mysql-test/suite/rpl/t/rpl_row_log-slave.opt
new file mode 100644
index 00000000..8b137891
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_row_log-slave.opt
@@ -0,0 +1 @@
+
diff --git a/mysql-test/suite/rpl/t/rpl_row_log.test b/mysql-test/suite/rpl/t/rpl_row_log.test
new file mode 100644
index 00000000..25fcc4f4
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_row_log.test
@@ -0,0 +1,15 @@
+###################################
+# Wrapper for rpl_row_log.test #
+# Added wrapper so that MyISAM & #
+# Innodb could all use the#
+# Same test
+###################################
+########################################################
+# By JBM 2005-02-15 Wrapped to allow reuse of test code#
+########################################################
+-- source include/have_binlog_format_row.inc
+-- source include/master-slave.inc
+let $engine_type=MyISAM;
+-- source include/rpl_log.test
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_row_log_innodb-master.opt b/mysql-test/suite/rpl/t/rpl_row_log_innodb-master.opt
new file mode 100644
index 00000000..773ec62b
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_row_log_innodb-master.opt
@@ -0,0 +1,2 @@
+--skip-external-locking
+--default-storage-engine=MyISAM
diff --git a/mysql-test/suite/rpl/t/rpl_row_log_innodb.test b/mysql-test/suite/rpl/t/rpl_row_log_innodb.test
new file mode 100644
index 00000000..92fe0eb9
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_row_log_innodb.test
@@ -0,0 +1,13 @@
+###################################
+# Wrapper for rpl_row_log.test #
+# Added wrapper so that MyISAM & #
+# Innodb could all use the#
+# Same test.
+###################################
+-- source include/have_binlog_format_row.inc
+-- source include/have_innodb.inc
+-- source include/master-slave.inc
+let $engine_type=InnoDB;
+-- source include/rpl_log.test
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_row_max_relay_size.test b/mysql-test/suite/rpl/t/rpl_row_max_relay_size.test
new file mode 100644
index 00000000..0ec85244
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_row_max_relay_size.test
@@ -0,0 +1,9 @@
+# Test of options max_binlog_size and max_relay_log_size and
+# how they act (if max_relay_log_size == 0, use max_binlog_size
+# for relay logs too).
+# Test of manual relay log rotation with FLUSH LOGS.
+
+# Requires statement logging
+source include/have_binlog_format_row.inc;
+
+source include/rpl_max_relay_size.test;
diff --git a/mysql-test/suite/rpl/t/rpl_row_merge_engine.test b/mysql-test/suite/rpl/t/rpl_row_merge_engine.test
new file mode 100644
index 00000000..c28d4a89
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_row_merge_engine.test
@@ -0,0 +1,52 @@
+#
+# BUG#47103
+#
+# This test case checks whether the slave crashes or not when there is
+# a merge table in use.
+#
+# Description
+# ===========
+#
+# The test case creates two regular MyISAM tables on the master and
+# one MERGE table. Then it populates the MyISAM tables, updates and
+# deletes their contents through the merge table. Finally, the slave
+# is synchronized with the master and (after the fix) it won't crash.
+#
+--source include/have_binlog_format_row.inc
+--source include/master-slave.inc
+--connection master
+
+CREATE TABLE t1 (a int) ENGINE=MyISAM;
+CREATE TABLE t2 (a int) ENGINE=MyISAM;
+INSERT INTO t1 VALUES (1), (2), (3);
+INSERT INTO t2 VALUES (4), (5), (6);
+# Changed a little to check also an issue reported on BUG#20574550
+CREATE TEMPORARY TABLE IF NOT EXISTS tt1_merge LIKE t1;
+ALTER TABLE tt1_merge ENGINE=MERGE UNION (t2, t1);
+CREATE TABLE t1_merge LIKE tt1_merge;
+
+--sync_slave_with_master
+
+--let diff_tables=master:test.t1, slave:test.t1
+--source include/diff_tables.inc
+
+--let diff_tables=master:test.t2, slave:test.t2
+--source include/diff_tables.inc
+
+--connection master
+UPDATE t1_merge SET a=10 WHERE a=1;
+DELETE FROM t1_merge WHERE a=10;
+
+--sync_slave_with_master
+--connection master
+
+--let diff_tables=master:test.t1, slave:test.t1
+--source include/diff_tables.inc
+
+--let diff_tables=master:test.t2, slave:test.t2
+--source include/diff_tables.inc
+
+DROP TABLE t1_merge, t1, t2;
+--sync_slave_with_master
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_row_mixing_engines.test b/mysql-test/suite/rpl/t/rpl_row_mixing_engines.test
new file mode 100644
index 00000000..5aa4f2c9
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_row_mixing_engines.test
@@ -0,0 +1,14 @@
+###################################################################################
+# This test cases evaluates the mixture of non-transactional and transcational
+# tables. For further details, please, read WL#2687 and WL#5072.
+###################################################################################
+--source include/have_binlog_format_row.inc
+--source include/have_innodb.inc
+# MDEV-31790 FIXME: This test is extremely slow
+--source include/not_msan.inc
+--source include/master-slave.inc
+
+let $engine_type=Innodb;
+let $database_name=test;
+--source include/rpl_mixing_engines.test
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_row_mysqlbinlog-master.opt b/mysql-test/suite/rpl/t/rpl_row_mysqlbinlog-master.opt
new file mode 100644
index 00000000..07d12817
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_row_mysqlbinlog-master.opt
@@ -0,0 +1 @@
+--max-binlog-size=1040384
diff --git a/mysql-test/suite/rpl/t/rpl_row_mysqlbinlog.test b/mysql-test/suite/rpl/t/rpl_row_mysqlbinlog.test
new file mode 100644
index 00000000..9e10aaa6
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_row_mysqlbinlog.test
@@ -0,0 +1,285 @@
+##################################################################
+# Author: JBM #
+# Date: 2006-02-22 #
+# Purpose: To test changes to mysqlbinlog for row based bin logs #
+# We are using .opt file since we need small binlog size #
+##################################################################
+-- source include/have_binlog_format_row.inc
+-- source include/not_embedded.inc
+-- source include/have_cp932.inc
+-- source include/master-slave.inc
+
+--echo ---Setup Section --
+
+# we need this for getting fixed timestamps inside of this test
+set timestamp=1000000000;
+
+CREATE TABLE t1(word VARCHAR(20));
+CREATE TABLE t2(id INT AUTO_INCREMENT NOT NULL PRIMARY KEY);
+--let position= query_get_value(SHOW MASTER STATUS, Position, 1)
+CREATE TABLE t3(c1 INT NOT NULL PRIMARY KEY, c2 LONGBLOB, c3 TIMESTAMP, c4 TEXT, c5 FLOAT);
+--let stop_position=query_get_value(SHOW MASTER STATUS, Position, 1)
+--let stop_position1=`select $stop_position - 1`
+--let binlog_start_pos=query_get_value(SHOW BINLOG EVENTS LIMIT 1, End_log_pos, 1)
+
+# Test Section
+# Lets start by putting some data into the tables.
+
+INSERT INTO t1 VALUES ("abirvalg");
+LOAD DATA INFILE '../../std_data/words.dat' INTO TABLE t1;
+LOAD DATA INFILE '../../std_data/words.dat' INTO TABLE t1;
+LOAD DATA INFILE '../../std_data/words.dat' INTO TABLE t1;
+LOAD DATA INFILE '../../std_data/words.dat' INTO TABLE t1;
+LOAD DATA INFILE '../../std_data/words.dat' INTO TABLE t1;
+
+# d1 length 3000
+set @d1 = 'dd1';
+set @d1 = concat(@d1,@d1,@d1,@d1,@d1,@d1,@d1,@d1,@d1,@d1);
+set @d1 = concat(@d1,@d1,@d1,@d1,@d1,@d1,@d1,@d1,@d1,@d1);
+set @d1 = concat(@d1,@d1,@d1,@d1,@d1,@d1,@d1,@d1,@d1,@d1);
+
+--disable_query_log
+let count=500;
+while ($count)
+{
+ INSERT INTO t2 VALUES (NULL);
+ eval INSERT INTO t3 VALUES ($count,@d1,'20060222000000','Tested in Texas',$count*2.2);
+ dec $count;
+}
+--enable_query_log
+
+--echo ---Test 1 check table load --
+
+# Lets Check the tables on the Master
+SELECT COUNT(*) from t1;
+SELECT COUNT(*) from t2;
+SELECT COUNT(*) from t3;
+SELECT * FROM t1 ORDER BY word LIMIT 5;
+SELECT * FROM t2 ORDER BY id LIMIT 5;
+SELECT c1, c3, c4, c5 FROM t3 ORDER BY c1 LIMIT 5;
+
+# Should have the same on the slave;
+
+sync_slave_with_master;
+SELECT COUNT(*) from t1;
+SELECT COUNT(*) from t2;
+SELECT COUNT(*) from t3;
+SELECT * FROM t1 ORDER BY word LIMIT 5;
+SELECT * FROM t2 ORDER BY id LIMIT 5;
+SELECT c1, c3, c4, c5 FROM t3 ORDER BY c1 LIMIT 5;
+
+# Okay time to get busy, back to master
+
+connection master;
+
+# simple query to show more in second binlog
+insert into t1 values ("Alas");
+flush logs;
+
+# delimiters are for easier debugging in future
+--echo --- Test 1 Dump binlog to file --
+
+#
+# Prepare local temporary file to recreate what we have currently.
+let MYSQLD_DATADIR= `select @@datadir;`;
+--exec $MYSQL_BINLOG $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/master.sql
+
+--exec $MYSQL_BINLOG $MYSQLD_DATADIR/master-bin.000002 >> $MYSQLTEST_VARDIR/tmp/master.sql
+
+# Now that we have our file, lets get rid of the current database.
+# Cleanup the master and the slave and try to recreate.
+--echo --- Test 1 delete tables, clean master and slave --
+
+DROP TABLE t1;
+DROP TABLE t2;
+DROP TABLE t3;
+
+sync_slave_with_master;
+stop slave;
+--source include/wait_for_slave_to_stop.inc
+connection master;
+reset master;
+connection slave;
+--source include/reset_slave.inc
+start slave;
+--source include/wait_for_slave_to_start.inc
+connection master;
+
+# We should be clean at this point, now we will run in the file from above.
+--echo --- Test 1 Load from Dump binlog file --
+
+--exec $MYSQL -e "source $MYSQLTEST_VARDIR/tmp/master.sql"
+
+--echo --- Test 1 Check Load Results --
+
+# Lets Check the tables on the Master
+SELECT COUNT(*) from t1;
+SELECT COUNT(*) from t2;
+SELECT COUNT(*) from t3;
+SELECT * FROM t1 ORDER BY word LIMIT 5;
+SELECT * FROM t2 ORDER BY id LIMIT 5;
+SELECT c1, c3, c4, c5 FROM t3 ORDER BY c1 LIMIT 5;
+
+# Should have the same on the slave;
+
+sync_slave_with_master;
+SELECT COUNT(*) from t1;
+SELECT COUNT(*) from t2;
+SELECT COUNT(*) from t3;
+SELECT * FROM t1 ORDER BY word LIMIT 5;
+SELECT * FROM t2 ORDER BY id LIMIT 5;
+SELECT c1, c3, c4, c5 FROM t3 ORDER BY c1 LIMIT 5;
+connection master;
+
+# We should be gold by the time, so I will get rid of our file.
+
+remove_file $MYSQLTEST_VARDIR/tmp/master.sql;
+
+
+# this test for start-position option
+# By setting this position to 416, we should only get the create of t3
+--echo --- Test 2 position test --
+--exec $MYSQL_BINLOG --short-form --local-load=$MYSQLTEST_VARDIR/tmp/ --start-position=$position --stop-position=$stop_position $MYSQLD_DATADIR/master-bin.000001
+
+# These are tests for remote binlog.
+# They should return the same as previous test.
+
+--echo --- Test 3 First Remote test --
+
+# This is broken now
+--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
+--exec $MYSQL_BINLOG --short-form --local-load=$MYSQLTEST_VARDIR/tmp/ --stop-position=$stop_position --read-from-remote-server --user=root --host=127.0.0.1 --port=$MASTER_MYPORT master-bin.000001
+
+--echo --- Test 4 Second Remote test --
+--exec $MYSQL_BINLOG --read-from-remote-server --user=root --host=127.0.0.1 --port=$MASTER_MYPORT --to-last-log master-bin.000001 > $MYSQLTEST_VARDIR/tmp/remote.sql
+
+# Now that we have our file, lets get rid of the current database.
+# Cleanup the master and the slave and try to recreate.
+
+DROP TABLE t1;
+DROP TABLE t2;
+DROP TABLE t3;
+
+sync_slave_with_master;
+
+stop slave;
+--source include/wait_for_slave_to_stop.inc
+connection master;
+reset master;
+connection slave;
+--source include/reset_slave.inc
+start slave;
+--source include/wait_for_slave_to_start.inc
+connection master;
+
+# We should be clean at this point, now we will run in the file from above.
+
+--exec $MYSQL -e "source $MYSQLTEST_VARDIR/tmp/remote.sql"
+
+# Lets Check the tables on the Master
+
+SELECT COUNT(*) from t1;
+SELECT COUNT(*) from t2;
+SELECT COUNT(*) from t3;
+SELECT * FROM t1 ORDER BY word LIMIT 5;
+SELECT * FROM t2 ORDER BY id LIMIT 5;
+SELECT c1, c3, c4, c5 FROM t3 ORDER BY c1 LIMIT 5;
+
+# Should have the same on the slave;
+
+sync_slave_with_master;
+SELECT COUNT(*) from t1;
+SELECT COUNT(*) from t2;
+SELECT COUNT(*) from t3;
+SELECT * FROM t1 ORDER BY word LIMIT 5;
+SELECT * FROM t2 ORDER BY id LIMIT 5;
+SELECT c1, c3, c4, c5 FROM t3 ORDER BY c1 LIMIT 5;
+connection master;
+
+# We should be gold by the time, so I will get rid of our file.
+
+--remove_file $MYSQLTEST_VARDIR/tmp/remote.sql
+################### End Bug 17654 ######################
+
+# What is the point of this test? It seems entirely pointless. It
+# might make sense for statement-based replication, but for row-based
+# replication the LOAD DATA INFILE is printed just as empty
+# transactions. /Matz
+
+# LOAD DATA
+--echo --- Test 5 LOAD DATA --
+--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
+--exec $MYSQL_BINLOG --short-form --local-load=$MYSQLTEST_VARDIR/tmp/ --stop-position=$binlog_start_pos --read-from-remote-server --user=root --host=127.0.0.1 --port=$MASTER_MYPORT master-bin.000002
+
+# Bug#7853 (mysqlbinlog does not accept input from stdin)
+
+--echo --- Test 6 reading stdin --
+--replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR
+--exec $MYSQL_BINLOG --short-form --stop-position=$stop_position1 - < $MYSQLD_DATADIR/master-bin.000001
+
+--echo --- Test 7 reading stdin w/position --
+--replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR
+--exec $MYSQL_BINLOG --short-form --start-position=$position --stop-position=$stop_position - < $MYSQLD_DATADIR/master-bin.000001
+
+# Bug#16217 (mysql client did not know how not switch its internal charset)
+--echo --- Test 8 switch internal charset --
+sync_slave_with_master;
+
+stop slave;
+--source include/wait_for_slave_to_stop.inc
+connection master;
+reset master;
+connection slave;
+--source include/reset_slave.inc
+start slave;
+--source include/wait_for_slave_to_start.inc
+connection master;
+
+create table t4 (f text character set utf8);
+create table t5 (f text character set cp932);
+--exec $MYSQL --default-character-set=utf8 test -e "insert into t4 values(_utf8'ソ')"
+--exec $MYSQL --default-character-set=cp932 test -e "insert into t5 values(_cp932'ƒ\');"
+flush logs;
+rename table t4 to t04, t5 to t05;
+--exec $MYSQL_BINLOG $MYSQLD_DATADIR/master-bin.000001 | $MYSQL --default-character-set=utf8
+# original and recovered data must be equal
+select HEX(f) from t04;
+select HEX(f) from t4;
+select HEX(f) from t05;
+select HEX(f) from t5;
+
+# slave should have same
+sync_slave_with_master;
+select HEX(f) from t04;
+select HEX(f) from t4;
+select HEX(f) from t05;
+select HEX(f) from t5;
+
+--echo --- Test cleanup --
+# clean up
+connection master;
+sync_slave_with_master;
+
+connection master;
+DROP TABLE t1, t2, t3, t04, t05, t4, t5;
+
+# BUG#17654 also test mysqlbinlog to ensure it can read the binlog from a remote server
+# and ensure that the results are the same as if read from a file (the same file).
+
+CREATE TABLE t1 (a INT NOT NULL KEY, b INT);
+INSERT INTO t1 VALUES(1,1);
+SELECT * FROM t1;
+FLUSH LOGS;
+
+--exec $MYSQL_BINLOG --read-from-remote-server --user=root --host=127.0.0.1 --port=$MASTER_MYPORT master-bin.000001 > $MYSQLTEST_VARDIR/tmp/remote.sql
+--exec $MYSQL_BINLOG $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/local.sql
+
+--diff_files $MYSQLTEST_VARDIR/tmp/local.sql $MYSQLTEST_VARDIR/tmp/remote.sql
+--remove_file $MYSQLTEST_VARDIR/tmp/remote.sql
+--remove_file $MYSQLTEST_VARDIR/tmp/local.sql
+DROP TABLE t1;
+
+sync_slave_with_master;
+
+# End of 4.1 tests
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_row_rec_comp_innodb.test b/mysql-test/suite/rpl/t/rpl_row_rec_comp_innodb.test
new file mode 100644
index 00000000..39149f6b
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_row_rec_comp_innodb.test
@@ -0,0 +1,11 @@
+-- source include/have_binlog_format_row.inc
+-- source include/have_innodb.inc
+-- source include/master-slave.inc
+
+#
+# BUG#52868 Wrong handling of NULL value during update, replication out of sync
+#
+
+-- let $engine= InnoDB
+-- source include/rpl_record_compare.test
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_row_rec_comp_myisam.test b/mysql-test/suite/rpl/t/rpl_row_rec_comp_myisam.test
new file mode 100644
index 00000000..d9c06d6b
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_row_rec_comp_myisam.test
@@ -0,0 +1,32 @@
+-- source include/have_binlog_format_row.inc
+-- source include/master-slave.inc
+-- let $engine= MyISAM
+
+#
+# BUG#52868 Wrong handling of NULL value during update, replication out of sync
+#
+
+
+-- echo ## coverage purposes - Field_bits
+-- echo ## 1 X bit + 2 Null bits + 5 bits => last_null_bit_pos==0
+
+--source include/rpl_reset.inc
+-- connection master
+
+-- eval CREATE TABLE t1 (c1 bigint(20) DEFAULT 0, c2 bit(5)) ENGINE=$engine DEFAULT CHARSET=latin1
+
+INSERT INTO t1(c1,c2) VALUES (10, b'1');
+INSERT INTO t1(c1,c2) VALUES (NULL, b'1');
+UPDATE t1 SET c1= 0;
+-- sync_slave_with_master
+
+-- let $diff_tables= master:t1, slave:t1
+-- source include/diff_tables.inc
+
+-- connection master
+DROP TABLE t1;
+-- sync_slave_with_master
+
+-- source include/rpl_record_compare.test
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_row_reset_slave.test b/mysql-test/suite/rpl/t/rpl_row_reset_slave.test
new file mode 100644
index 00000000..284c6154
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_row_reset_slave.test
@@ -0,0 +1,5 @@
+# TBF - difference in row level logging
+# Temp tables are not replicated in rbr, but it is still good to hit rbr with everthing
+-- source include/have_binlog_format_row.inc
+-- source include/rpl_reset_slave.test
+
diff --git a/mysql-test/suite/rpl/t/rpl_row_rollback_to_savepoint.test b/mysql-test/suite/rpl/t/rpl_row_rollback_to_savepoint.test
new file mode 100644
index 00000000..9bc812bb
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_row_rollback_to_savepoint.test
@@ -0,0 +1,312 @@
+###############################################################################
+# Bug#76727: SLAVE ASSERTION IN UNPACK_ROW WITH ROLLBACK TO
+# SAVEPOINT IN ERROR HANDLER
+#
+# Problem:
+# ========
+# "SAVEPOINT", "ROLLBACK TO savepoint" wipe out table map on slave during
+# execution binary log events. For trigger the map is written to binary log once
+# for all trigger body and if trigger contains "SAVEPOINT" or
+# "ROLLBACK TO savepoint" statements any trigger's events after these
+# statements will not have table map. This results in an assert on slave.
+#
+# Test:
+# =====
+# Test case 1:
+# Create a trigger with exception handler which rolls back to a savepoint.
+# Test proves that there will not be any assert during execution of rolling
+# back to savepoint.
+#
+# Test case 2:
+# Create a trigger which calls a procedure which in turn calls an exception
+# handler which rolls back to a savepoint. Prove that it doesn't cause any
+# assertion during execution.
+#
+# Test case 3:
+# Create a simple trigger which does SAVEPOINT and ROLLBACK TO SAVEPOINT
+# and doesn't follow with any other DML statement. Prove that it doesn't cause
+# any assertion during execution.
+#
+# Test case 4:
+# Create a trigger with SAVEPOINT and follows with a DML without ROLLBACK TO
+# savepoint. Ensure that data is replicated properly.
+#
+# Test case 5:
+# Create a trigger with SAVEPOINT and it does nothing. Do few DMLs following
+# the trigger ensure that the data is replicated properly
+#
+# Test case 6:
+# Create a stored function which does SAVEPOINT and ROLLBACK TO
+# SAVEPOINT. Do few inserts following the stored function call and ensure that
+# no assert is generated on slave and all the rows are replicated to slave.
+#
+# Test case 7:
+# Create a stored function which creates a SAVEPOINT alone and follows with
+# DMLs without ROLLBACK TO savepoint. Ensure that data is replicated properly.
+#
+# Test case 8:
+# Create a stored function which has SAVEPOINT inside it and does noting. It
+# should follow with other DMLs. Ensure that data is replicated properly.
+###############################################################################
+--source include/have_binlog_format_row.inc
+--source include/have_innodb.inc
+--source include/master-slave.inc
+
+--echo #Test case 1:
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=INNODB;
+CREATE TABLE t2 (f1 INTEGER PRIMARY KEY) ENGINE=INNODB;
+CREATE TABLE t3 (f1 INTEGER PRIMARY KEY) ENGINE=INNODB;
+DELIMITER |;
+
+CREATE TRIGGER tr1 AFTER INSERT ON t1 FOR EACH ROW
+BEGIN
+ DECLARE EXIT HANDLER FOR SQLEXCEPTION
+ BEGIN
+ ROLLBACK TO event_logging_1;
+ INSERT t3 VALUES (1);
+ END;
+ SAVEPOINT event_logging_1;
+ INSERT INTO t2 VALUES (1);
+ RELEASE SAVEPOINT event_logging_1;
+END|
+DELIMITER ;|
+
+INSERT INTO t2 VALUES (1);
+INSERT INTO t1 VALUES (1);
+
+--source include/show_binlog_events.inc
+
+--sync_slave_with_master
+
+connection master;
+
+DROP TRIGGER tr1;
+DELETE FROM t1;
+DELETE FROM t2;
+DELETE FROM t3;
+
+--echo # Test case 2:
+
+DELIMITER |;
+
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE EXIT HANDLER FOR SQLEXCEPTION
+ BEGIN
+ ROLLBACK TO event_logging_2;
+ INSERT t3 VALUES (3);
+ END;
+ SAVEPOINT event_logging_2;
+ INSERT INTO t2 VALUES (1);
+ RELEASE SAVEPOINT event_logging_2;
+END|
+
+CREATE TRIGGER tr1 AFTER INSERT ON t1 FOR EACH ROW CALL p1()|
+
+DELIMITER ;|
+
+INSERT INTO t2 VALUES (1);
+INSERT INTO t1 VALUES (1);
+
+--source include/show_binlog_events.inc
+
+--sync_slave_with_master
+
+connection master;
+
+DROP TABLE t1;
+DROP TABLE t2;
+DROP TABLE t3;
+
+DROP PROCEDURE p1;
+
+--echo # Test case 3:
+--source include/rpl_reset.inc
+connection master;
+
+CREATE TABLE t (f1 int(10) unsigned NOT NULL, PRIMARY KEY (f1)) ENGINE=InnoDB;
+
+--delimiter |
+CREATE TRIGGER t_insert_trig AFTER INSERT ON t FOR EACH ROW
+BEGIN
+ SAVEPOINT savepoint_1;
+ ROLLBACK TO savepoint_1;
+END |
+--delimiter ;
+
+INSERT INTO t VALUES (2);
+INSERT INTO t VALUES (3);
+
+--source include/show_binlog_events.inc
+
+SELECT * FROM t;
+
+--source include/sync_slave_sql_with_master.inc
+
+SELECT * FROM t;
+
+connection master;
+DROP TABLE t;
+
+--echo # Test case 4:
+--source include/rpl_reset.inc
+connection master;
+CREATE TABLE t (f1 int(10) unsigned NOT NULL) ENGINE=InnoDB;
+CREATE TABLE t1 (f1 int(10) unsigned NOT NULL) ENGINE=InnoDB;
+
+--delimiter |
+CREATE TRIGGER t_insert_trig BEFORE INSERT ON t FOR EACH ROW
+BEGIN
+ SAVEPOINT savepoint_1;
+ INSERT INTO t1 VALUES (5);
+END |
+--delimiter ;
+
+INSERT INTO t VALUES (2), (3);
+INSERT INTO t1 VALUES (30);
+--source include/show_binlog_events.inc
+
+SELECT * FROM t;
+SELECT * FROM t1;
+--source include/sync_slave_sql_with_master.inc
+
+SELECT * FROM t;
+SELECT * FROM t1;
+
+connection master;
+DROP TABLE t;
+DROP TABLE t1;
+
+--echo # Test case 5:
+--source include/rpl_reset.inc
+connection master;
+CREATE TABLE t (f1 int(10) unsigned NOT NULL) ENGINE=InnoDB;
+CREATE TABLE t1 (f1 int(10) unsigned NOT NULL) ENGINE=InnoDB;
+
+--delimiter |
+CREATE TRIGGER t_insert_trig BEFORE INSERT ON t
+FOR EACH ROW
+BEGIN
+
+SAVEPOINT savepoint_1;
+END |
+
+--delimiter ;
+
+INSERT INTO t VALUES (2), (3);
+INSERT INTO t1 VALUES (30);
+--source include/show_binlog_events.inc
+
+SELECT * FROM t;
+SELECT * FROM t1;
+--source include/sync_slave_sql_with_master.inc
+
+SELECT * FROM t;
+SELECT * FROM t1;
+
+connection master;
+DROP TABLE t;
+DROP TABLE t1;
+
+--echo # Test case 6:
+--source include/rpl_reset.inc
+connection master;
+CREATE TABLE t1 (f1 INTEGER ) ENGINE=INNODB;
+CREATE TABLE t2 (f1 INTEGER ) ENGINE=INNODB;
+
+--delimiter |
+
+CREATE FUNCTION f1() RETURNS INT
+BEGIN
+ SAVEPOINT event_logging_2;
+ INSERT INTO t1 VALUES (1);
+ ROLLBACK TO event_logging_2;
+ RETURN 0;
+END|
+
+--delimiter ;
+
+BEGIN;
+INSERT INTO t2 VALUES (1), (f1()), (2), (4);
+COMMIT;
+INSERT INTO t2 VALUES (10);
+--source include/show_binlog_events.inc
+
+connection master;
+SELECT * FROM t2;
+SELECT * FROM t1;
+--source include/sync_slave_sql_with_master.inc
+SELECT * FROM t2;
+SELECT * FROM t1;
+
+connection master;
+DROP TABLE t1;
+DROP TABLE t2;
+DROP FUNCTION f1;
+
+--echo # Test case 7:
+--source include/rpl_reset.inc
+connection master;
+CREATE TABLE t1 (f1 INTEGER ) ENGINE=INNODB;
+CREATE TABLE t2 (f1 INTEGER ) ENGINE=INNODB;
+
+--delimiter |
+
+CREATE FUNCTION f1() RETURNS INT
+BEGIN
+ SAVEPOINT event_logging_2;
+ INSERT INTO t1 VALUES (1);
+ RETURN 0;
+END|
+
+--delimiter ;
+
+BEGIN;
+INSERT INTO t2 VALUES (1), (f1()), (2), (4);
+COMMIT;
+INSERT INTO t2 VALUES (10);
+--source include/show_binlog_events.inc
+
+connection master;
+SELECT * FROM t2;
+SELECT * FROM t1;
+--source include/sync_slave_sql_with_master.inc
+SELECT * FROM t2;
+SELECT * FROM t1;
+
+connection master;
+DROP TABLE t1;
+DROP TABLE t2;
+DROP FUNCTION f1;
+
+--echo # Test case 8:
+--source include/rpl_reset.inc
+connection master;
+CREATE TABLE t1 (f1 INTEGER ) ENGINE=INNODB;
+
+--delimiter |
+
+CREATE FUNCTION f1() RETURNS INT
+BEGIN
+ SAVEPOINT event_logging_2;
+ RETURN 0;
+END|
+
+--delimiter ;
+
+BEGIN;
+INSERT INTO t1 VALUES (1), (f1()), (2), (4);
+COMMIT;
+INSERT INTO t1 VALUES (10);
+--source include/show_binlog_events.inc
+
+connection master;
+SELECT * FROM t1;
+--source include/sync_slave_sql_with_master.inc
+SELECT * FROM t1;
+
+connection master;
+DROP TABLE t1;
+DROP FUNCTION f1;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_row_show_relaylog_events.test b/mysql-test/suite/rpl/t/rpl_row_show_relaylog_events.test
new file mode 100644
index 00000000..3d4b8f1e
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_row_show_relaylog_events.test
@@ -0,0 +1,19 @@
+# BUG#28777 SHOW BINLOG EVENTS does not work on relay log files
+#
+# GOAL
+# ====
+#
+# Test that SHOW BINLOG EVENTS and the new SHOW RELAYLOG EVENTS works after
+# the patch, both on master and slave.
+#
+# HOW
+# ===
+#
+# This test issues SHOW [BINLOG|RELAYLOG] EVENTS both on master and slave after
+# some statements have been issued.
+
+-- source include/have_binlog_format_row.inc
+-- source include/master-slave.inc
+
+-- source include/rpl_show_relaylog_events.inc
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_row_sp001.test b/mysql-test/suite/rpl/t/rpl_row_sp001.test
new file mode 100644
index 00000000..99db5e7f
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_row_sp001.test
@@ -0,0 +1,145 @@
+#############################################################################
+# This test is being created to test out the non deterministic items with #
+# row based replication. #
+# Original Author: JBM #
+# Original Date: Aug/09/2005 #
+# Updated: Aug/29/2005
+#############################################################################
+# Test: Includes two stored procedure tests. First test uses SP to insert #
+# values from RAND() and NOW() into a table. #
+# The second test uses SP with CASE structure to decide what to text #
+# to update a given table with. #
+############################################################################
+
+# Includes
+-- source include/have_binlog_format_row.inc
+-- source include/master-slave.inc
+
+-- disable_query_log
+-- disable_result_log
+
+# Begin clean up test section
+connection master;
+--disable_warnings
+DROP PROCEDURE IF EXISTS test.p1;
+DROP PROCEDURE IF EXISTS test.p2;
+DROP TABLE IF EXISTS test.t1;
+DROP TABLE IF EXISTS test.t2;
+
+-- enable_query_log
+-- enable_result_log
+
+# Begin test section 1 for non deterministic SP
+let $message=<Begin test section 1 (non deterministic SP)>;
+--source include/show_msg.inc
+
+create table test.t1 (n MEDIUMINT NOT NULL AUTO_INCREMENT, f FLOAT, d DATETIME, PRIMARY KEY(n));
+
+delimiter //;
+create procedure test.p1()
+begin
+ INSERT INTO test.t1 (f,d) VALUES (RAND(),NOW());
+end//
+delimiter ;//
+
+# show binlog events;
+
+-- disable_query_log
+-- disable_result_log
+SET @wait_count=1;
+let $1=10;
+while ($1)
+{
+ call test.p1();
+ let $wait_condition= SELECT COUNT(*) = @wait_count FROM test.t1;
+ -- source include/wait_condition.inc
+ -- disable_query_log
+ SET @wait_count = @wait_count + 1;
+ dec $1;
+}
+-- enable_result_log
+-- enable_query_log
+
+## Used for debugging
+#show binlog events;
+#select * from test.t1;
+#sync_slave_with_master;
+#select * from test.t1;
+#connection master;
+
+let $message=<End test section 1 (non deterministic SP)>;
+--source include/show_msg.inc
+
+
+CREATE TABLE test.t2 (a INT NOT NULL AUTO_INCREMENT, t CHAR(4), PRIMARY KEY(a));
+
+delimiter //;
+CREATE PROCEDURE test.p2(n int)
+begin
+CASE n
+WHEN 1 THEN
+ UPDATE test.t2 set t ='Tex';
+WHEN 2 THEN
+ UPDATE test.t2 set t ='SQL';
+ELSE
+ UPDATE test.t2 set t ='NONE';
+END CASE;
+end//
+delimiter ;//
+
+INSERT INTO test.t2 VALUES(NULL,'NEW'),(NULL,'NEW'),(NULL,'NEW'),(NULL,'NEW');
+
+SELECT * FROM t2 ORDER BY a;
+sync_slave_with_master;
+SELECT * FROM t2 ORDER BY a;
+
+connection master;
+call test.p2(1);
+SELECT * FROM t2 ORDER BY a;
+sync_slave_with_master;
+SELECT * FROM t2 ORDER BY a;
+
+
+connection master;
+call test.p2(2);
+SELECT * FROM t2 ORDER BY a;
+sync_slave_with_master;
+SELECT * FROM t2 ORDER BY a;
+
+connection master;
+call test.p2(3);
+SELECT * FROM t2 ORDER BY a;
+sync_slave_with_master;
+SELECT * FROM t2 ORDER BY a;
+
+##Used for debugging
+#show binlog events;
+
+# time to dump the databases and so we can see if they match
+
+--exec $MYSQL_DUMP --compact --order-by-primary --skip-extended-insert --no-create-info test > $MYSQLTEST_VARDIR/tmp/sp001_master.sql
+--exec $MYSQL_DUMP_SLAVE --compact --order-by-primary --skip-extended-insert --no-create-info test > $MYSQLTEST_VARDIR/tmp/sp001_slave.sql
+
+# First lets cleanup
+
+connection master;
+DROP PROCEDURE test.p1;
+DROP PROCEDURE test.p2;
+DROP TABLE test.t1;
+DROP TABLE test.t2;
+sync_slave_with_master;
+
+# Lets compare. Note: If they match test will pass, if they do not match
+# the test will show that the diff statement failed and not reject file
+# will be created. You will need to go to the mysql-test dir and diff
+# the files your self to see what is not matching :-) Failed dump files
+# will be located in $MYSQLTEST_VARDIR/tmp
+
+diff_files $MYSQLTEST_VARDIR/tmp/sp001_master.sql $MYSQLTEST_VARDIR/tmp/sp001_slave.sql;
+
+# If all is good, when can cleanup our dump files.
+--remove_file $MYSQLTEST_VARDIR/tmp/sp001_master.sql
+--remove_file $MYSQLTEST_VARDIR/tmp/sp001_slave.sql
+
+# End of 5.0 test case
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_row_sp002_innodb.test b/mysql-test/suite/rpl/t/rpl_row_sp002_innodb.test
new file mode 100644
index 00000000..f096c157
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_row_sp002_innodb.test
@@ -0,0 +1,3 @@
+-- source include/have_innodb.inc
+let $engine_type=INNODB;
+-- source include/rpl_row_sp002.test
diff --git a/mysql-test/suite/rpl/t/rpl_row_sp003.test b/mysql-test/suite/rpl/t/rpl_row_sp003.test
new file mode 100644
index 00000000..0a361202
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_row_sp003.test
@@ -0,0 +1,16 @@
+#################################
+# Wrapper for rpl_row_sp003.test#
+#################################
+########################################################
+# By JBM 2005-02-15 Wrapped to allow reuse of test code#
+########################################################
+-- source include/have_innodb.inc
+-- source include/have_binlog_format_row.inc
+# Slow test, don't run during staging part
+-- source include/not_staging.inc
+--source include/long_test.inc
+-- source include/master-slave.inc
+
+let $engine_type=INNODB;
+-- source include/rpl_row_sp003.test
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_row_sp005.test b/mysql-test/suite/rpl/t/rpl_row_sp005.test
new file mode 100644
index 00000000..865f2e94
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_row_sp005.test
@@ -0,0 +1,102 @@
+#############################################################################
+# Original Author: JBM #
+# Original Date: Aug/15/2005 #
+# Updated: Aug/29/2005: Removed sleeps #
+#############################################################################
+# Test: Tests SPs with cursors, flow logic, and alter sp. In addition the #
+# tests SPs with insert and update operations. #
+#############################################################################
+
+# Includes
+-- source include/have_binlog_format_row.inc
+-- source include/master-slave.inc
+
+
+# Begin clean up test section
+connection master;
+--disable_warnings
+DROP PROCEDURE IF EXISTS test.p1;
+DROP PROCEDURE IF EXISTS test.p2;
+DROP TABLE IF EXISTS test.t2;
+DROP TABLE IF EXISTS test.t1;
+DROP TABLE IF EXISTS test.t3;
+--enable_warnings
+# End of cleanup
+
+# Begin test section 1
+CREATE TABLE IF NOT EXISTS test.t1(id INT, data CHAR(16),PRIMARY KEY(id));
+CREATE TABLE IF NOT EXISTS test.t2(id2 INT,PRIMARY KEY(id2));
+CREATE TABLE IF NOT EXISTS test.t3(id3 INT,PRIMARY KEY(id3), c CHAR(16));
+
+delimiter |;
+CREATE PROCEDURE test.p1()
+BEGIN
+DECLARE done INT DEFAULT 0;
+ DECLARE spa CHAR(16);
+ DECLARE spb,spc INT;
+ DECLARE cur1 CURSOR FOR SELECT id,data FROM test.t1 ORDER BY id;
+ DECLARE cur2 CURSOR FOR SELECT id2 FROM test.t2 ORDER BY id2;
+ DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done = 1;
+
+ OPEN cur1;
+ OPEN cur2;
+
+ REPEAT
+ FETCH cur1 INTO spb, spa;
+ FETCH cur2 INTO spc;
+ IF NOT done THEN
+ IF spb < spc THEN
+ INSERT INTO test.t3 VALUES (spb,spa);
+ ELSE
+ INSERT INTO test.t3 VALUES (spc,spa);
+ END IF;
+ END IF;
+ UNTIL done END REPEAT;
+
+ CLOSE cur1;
+ CLOSE cur2;
+END|
+CREATE PROCEDURE test.p2()
+BEGIN
+ INSERT INTO test.t1 VALUES (4,'MySQL'),(20,'ROCKS'),(11,'Texas'),(10,'kyle');
+ INSERT INTO test.t2 VALUES (4),(2),(1),(3);
+ UPDATE test.t1 SET id=id+4 WHERE id=4;
+END|
+delimiter ;|
+
+CALL test.p2();
+SELECT * FROM test.t1 ORDER BY id;
+SELECT * FROM test.t2 ORDER BY id2;
+
+sync_slave_with_master;
+SELECT * FROM test.t1 ORDER BY id;
+SELECT * FROM test.t2 ORDER BY id2;
+
+connection master;
+CALL test.p1();
+
+let $wait_condition= SELECT COUNT(*) = 4 FROM t3;
+--source include/wait_condition.inc
+save_master_pos;
+SELECT * FROM test.t3 ORDER BY id3;
+
+sync_slave_with_master;
+SELECT * FROM test.t3 ORDER BY id3;
+
+connection master;
+
+ALTER PROCEDURE test.p1 MODIFIES SQL DATA;
+#show binlog events;
+
+# Cleanup
+
+connection master;
+DROP PROCEDURE IF EXISTS test.p1;
+DROP PROCEDURE IF EXISTS test.p2;
+DROP TABLE IF EXISTS test.t1;
+DROP TABLE IF EXISTS test.t2;
+DROP TABLE IF EXISTS test.t3;
+sync_slave_with_master;
+
+# End of 5.0 test case
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_row_sp006_InnoDB.test b/mysql-test/suite/rpl/t/rpl_row_sp006_InnoDB.test
new file mode 100644
index 00000000..c575a105
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_row_sp006_InnoDB.test
@@ -0,0 +1,12 @@
+#################################
+# Wrapper for rpl_row_sp006.test#
+#################################
+########################################################
+# By JBM 2005-02-15 Wrapped to allow reuse of test code#
+########################################################
+-- source include/have_innodb.inc
+-- source include/have_binlog_format_row.inc
+-- source include/master-slave.inc
+let $engine_type=InnoDB;
+-- source include/rpl_row_sp006.test
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_row_sp007_innodb.test b/mysql-test/suite/rpl/t/rpl_row_sp007_innodb.test
new file mode 100644
index 00000000..6eaafa8c
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_row_sp007_innodb.test
@@ -0,0 +1,3 @@
+-- source include/have_innodb.inc
+let $engine_type=INNODB;
+-- source include/rpl_row_sp007.test
diff --git a/mysql-test/suite/rpl/t/rpl_row_sp008.test b/mysql-test/suite/rpl/t/rpl_row_sp008.test
new file mode 100644
index 00000000..74a988ee
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_row_sp008.test
@@ -0,0 +1,52 @@
+#############################################################################
+# Original Author: JBM #
+# Original Date: Aug/15/2005 #
+# Update: 08/29/2005 Remove sleep #
+#############################################################################
+# TEST: Use SQL_CALC_FOUND_ROWS and insert results into a table inside a sp #
+#############################################################################
+
+
+# Includes
+-- source include/have_binlog_format_row.inc
+-- source include/master-slave.inc
+
+# Begin clean up test section
+connection master;
+--disable_warnings
+DROP PROCEDURE IF EXISTS test.p1;
+DROP TABLE IF EXISTS test.t2;
+--enable_warnings
+# End of cleanup
+
+
+
+# Begin test section 1
+CREATE TABLE test.t1 (a INT,PRIMARY KEY(a));
+CREATE TABLE test.t2 (a INT,PRIMARY KEY(a));
+INSERT INTO test.t1 VALUES(1),(2);
+
+delimiter |;
+CREATE PROCEDURE test.p1()
+BEGIN
+ SELECT SQL_CALC_FOUND_ROWS * FROM test.t1 LIMIT 1;
+ INSERT INTO test.t2 VALUES(FOUND_ROWS());
+END|
+delimiter ;|
+
+CALL test.p1();
+SELECT * FROM test.t2;
+
+sync_slave_with_master;
+SELECT * FROM test.t2;
+
+# Cleanup
+
+connection master;
+DROP PROCEDURE IF EXISTS test.p1;
+DROP TABLE IF EXISTS test.t1;
+DROP TABLE IF EXISTS test.t2;
+sync_slave_with_master;
+
+# End of 5.0 test case
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_row_sp009.test b/mysql-test/suite/rpl/t/rpl_row_sp009.test
new file mode 100644
index 00000000..83d743b8
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_row_sp009.test
@@ -0,0 +1,98 @@
+#############################################################################
+# Original Author: JBM #
+# Original Date: Aug/18/2005 #
+# Updated: 08/29/2005 removed sleeps and added master pos save and snyc #
+#############################################################################
+#TEST: Taken and modfied from http://bugs.mysql.com/bug.php?id=12168 #
+#############################################################################
+
+# Includes
+-- source include/have_binlog_format_row.inc
+-- source include/master-slave.inc
+
+
+# Begin clean up test section
+connection master;
+--disable_warnings
+DROP PROCEDURE IF EXISTS test.p1;
+DROP TABLE IF EXISTS test.t1;
+DROP TABLE IF EXISTS test.t2;
+
+
+# Begin test section 1
+CREATE TABLE test.t1 (a INT, PRIMARY KEY(a));
+INSERT INTO test.t1 VALUES (1),(2),(3),(4);
+CREATE TABLE test.t2 (a INT, PRIMARY KEY(a));
+
+delimiter |;
+CREATE PROCEDURE test.p1 (arg1 CHAR(1))
+BEGIN
+ DECLARE b, c INT;
+ IF arg1 = 'a' THEN
+ BEGIN
+ DECLARE cur1 CURSOR FOR SELECT A FROM test.t1 WHERE a % 2;
+ DECLARE continue handler for not found set b = 1;
+ SET b = 0;
+ OPEN cur1;
+ c1_repeat: REPEAT
+ FETCH cur1 INTO c;
+ IF (b = 1) THEN
+ LEAVE c1_repeat;
+ END IF;
+
+ INSERT INTO test.t2 VALUES (c);
+ UNTIL b = 1
+ END REPEAT;
+ CLOSE cur1;
+ END;
+ END IF;
+ IF arg1 = 'b' THEN
+ BEGIN
+ DECLARE cur2 CURSOR FOR SELECT a FROM test.t1 WHERE NOT a % 2;
+ DECLARE continue handler for not found set b = 1;
+ SET b = 0;
+ OPEN cur2;
+ c2_repeat: REPEAT
+ FETCH cur2 INTO c;
+ IF (b = 1) THEN
+ LEAVE c2_repeat;
+ END IF;
+
+ INSERT INTO test.t2 VALUES (c);
+ UNTIL b = 1
+ END REPEAT;
+ CLOSE cur2;
+ END;
+ END IF;
+END|
+delimiter ;|
+
+CALL test.p1('a');
+SELECT * FROM test.t2 ORDER BY a;
+sync_slave_with_master;
+SELECT * FROM test.t2 ORDER BY a;
+connection master;
+truncate test.t2;
+
+# this next call fails, but should not
+call test.p1('b');
+select * from test.t2 ORDER BY a;
+sync_slave_with_master;
+SELECT * FROM test.t2 ORDER BY a;
+
+connection master;
+truncate test.t2;
+SELECT * FROM test.t2 ORDER BY a;
+sync_slave_with_master;
+SELECT * FROM test.t2 ORDER BY a;
+
+# Cleanup
+connection master;
+#show binlog events;
+DROP PROCEDURE test.p1;
+DROP TABLE test.t1;
+DROP TABLE test.t2;
+sync_slave_with_master;
+
+# End of 5.0 test case
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_row_sp010.test b/mysql-test/suite/rpl/t/rpl_row_sp010.test
new file mode 100644
index 00000000..aad7edcd
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_row_sp010.test
@@ -0,0 +1,77 @@
+#############################################################################
+# Original Author: JBM #
+# Original Date: Aug/18/2005 #
+# Update: 08/29/2005 remove sleep added master pos save and sync #
+#############################################################################
+#TEST: Taken and modfied from http://bugs.mysql.com/bug.php?id=11126 #
+#############################################################################
+
+# Includes
+-- source include/have_binlog_format_row.inc
+-- source include/master-slave.inc
+
+
+# Begin clean up test section
+connection master;
+--disable_warnings
+DROP PROCEDURE IF EXISTS test.p1;
+DROP PROCEDURE IF EXISTS test.p2;
+DROP PROCEDURE IF EXISTS test.p3;
+DROP PROCEDURE IF EXISTS test.p4;
+DROP TABLE IF EXISTS test.t1;
+DROP TABLE IF EXISTS test.t2;
+
+
+# Begin test section 1
+delimiter |;
+CREATE PROCEDURE test.p1()
+BEGIN
+ INSERT INTO test.t1 VALUES(2);
+END|
+CREATE PROCEDURE test.p2()
+BEGIN
+ DROP TEMPORARY TABLE IF EXISTS test.t1;
+ CREATE TEMPORARY TABLE test.t1 (a int, PRIMARY KEY(a));
+ INSERT INTO test.t1 VALUES(1);
+ CALL test.p1();
+END|
+delimiter ;|
+CALL test.p2();
+SELECT * FROM test.t1 ORDER BY a;
+
+sync_slave_with_master;
+show tables;
+
+connection master;
+delimiter |;
+CREATE PROCEDURE test.p3()
+BEGIN
+ INSERT INTO test.t2 VALUES(7);
+END|
+CREATE PROCEDURE test.p4()
+BEGIN
+ DROP TABLE IF EXISTS test.t2;
+ CREATE TABLE test.t2 (a int, PRIMARY KEY(a));
+ INSERT INTO test.t2 VALUES(6);
+ CALL test.p3();
+END|
+delimiter ;|
+CALL test.p4();
+SELECT * FROM test.t2 ORDER BY a;
+
+sync_slave_with_master;
+SELECT * FROM test.t2 ORDER BY a;
+
+# Cleanup
+connection master;
+#show binlog events;
+DROP PROCEDURE IF EXISTS test.p1;
+DROP PROCEDURE IF EXISTS test.p2;
+DROP PROCEDURE IF EXISTS test.p3;
+DROP PROCEDURE IF EXISTS test.p4;
+DROP TABLE IF EXISTS test.t1;
+DROP TABLE IF EXISTS test.t2;
+sync_slave_with_master;
+
+# End of 5.0 test case
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_row_sp011.test b/mysql-test/suite/rpl/t/rpl_row_sp011.test
new file mode 100644
index 00000000..d2a323fa
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_row_sp011.test
@@ -0,0 +1,112 @@
+#############################################################################
+# Original Author: JBM #
+# Original Date: Aug/18/2005 #
+# Updated: 08/29/2005 turned on diff and commented out debug SQL statements#
+#############################################################################
+#TEST: SP to test alter table and nested SP calls #
+#############################################################################
+
+# Includes
+-- source include/have_binlog_format_row.inc
+-- source include/master-slave.inc
+
+
+# Begin clean up test section
+connection master;
+--disable_warnings
+DROP PROCEDURE IF EXISTS test.p1;
+DROP PROCEDURE IF EXISTS test.p2;
+DROP PROCEDURE IF EXISTS test.p3;
+DROP PROCEDURE IF EXISTS test.p4;
+DROP PROCEDURE IF EXISTS test.p5;
+DROP PROCEDURE IF EXISTS test.p6;
+DROP PROCEDURE IF EXISTS test.p7;
+DROP TABLE IF EXISTS test.t1;
+DROP TABLE IF EXISTS test.t2;
+
+
+# Begin test section 1
+CREATE TABLE test.t1 (a int, PRIMARY KEY(a));
+INSERT INTO test.t1 VALUES (1);
+
+delimiter |;
+CREATE PROCEDURE test.p1()
+BEGIN
+ ALTER TABLE test.t1 ADD COLUMN b CHAR(4) AFTER a;
+ UPDATE test.t1 SET b = 'rbr' WHERE a = 1;
+ CALL test.p2();
+END|
+CREATE PROCEDURE test.p2()
+BEGIN
+ ALTER TABLE test.t1 ADD COLUMN f FLOAT AFTER b;
+ UPDATE test.t1 SET f = RAND() WHERE a = 1;
+ CALL test.p3();
+END|
+CREATE PROCEDURE test.p3()
+BEGIN
+ ALTER TABLE test.t1 RENAME test.t2;
+ CALL test.p4();
+END|
+CREATE PROCEDURE test.p4()
+BEGIN
+ ALTER TABLE test.t2 ADD INDEX (f);
+ ALTER TABLE test.t2 CHANGE a a INT UNSIGNED NOT NULL AUTO_INCREMENT;
+ INSERT INTO test.t2 VALUES (NULL,'TEST',RAND());
+ CALL test.p5();
+END|
+CREATE PROCEDURE test.p5()
+BEGIN
+ ALTER TABLE test.t2 ORDER BY f;
+ INSERT INTO test.t2 VALUES (NULL,'STM',RAND());
+ CALL test.p6();
+END|
+CREATE PROCEDURE test.p6()
+BEGIN
+ ALTER TABLE test.t2 ADD COLUMN b2 CHAR(4) FIRST;
+ ALTER TABLE test.t2 ADD COLUMN to_drop BIT(8) AFTER b2;
+ INSERT INTO test.t2 VALUES ('new',1,NULL,'STM',RAND());
+ CALL test.p7();
+END|
+CREATE PROCEDURE test.p7()
+BEGIN
+ ALTER TABLE test.t2 DROP COLUMN to_drop;
+ INSERT INTO test.t2 VALUES ('gone',NULL,'STM',RAND());
+END|
+delimiter ;|
+CALL test.p1();
+
+#SELECT * FROM test.t2;
+sync_slave_with_master;
+#SELECT * FROM test.t2;
+
+--exec $MYSQL_DUMP --compact --order-by-primary --skip-extended-insert --no-create-info test > $MYSQLTEST_VARDIR/tmp/sp011_master.sql
+--exec $MYSQL_DUMP_SLAVE --compact --order-by-primary --skip-extended-insert --no-create-info test > $MYSQLTEST_VARDIR/tmp/sp011_slave.sql
+
+# Cleanup
+connection master;
+#show binlog events;
+DROP PROCEDURE IF EXISTS test.p1;
+DROP PROCEDURE IF EXISTS test.p2;
+DROP PROCEDURE IF EXISTS test.p3;
+DROP PROCEDURE IF EXISTS test.p4;
+DROP PROCEDURE IF EXISTS test.p5;
+DROP PROCEDURE IF EXISTS test.p6;
+DROP PROCEDURE IF EXISTS test.p7;
+DROP TABLE IF EXISTS test.t1;
+DROP TABLE IF EXISTS test.t2;
+sync_slave_with_master;
+
+# Lets compare. Note: If they match test will pass, if they do not match
+# the test will show that the diff statement failed and not reject file
+# will be created. You will need to go to the mysql-test dir and diff
+# the files your self to see what is not matching :-) Failed test
+# Will leave dump files in $MYSQLTEST_VARDIR/tmp
+
+diff_files $MYSQLTEST_VARDIR/tmp/sp011_master.sql $MYSQLTEST_VARDIR/tmp/sp011_slave.sql;
+
+# If all is good, when can cleanup our dump files.
+--remove_file $MYSQLTEST_VARDIR/tmp/sp011_master.sql
+--remove_file $MYSQLTEST_VARDIR/tmp/sp011_slave.sql
+
+# End of 5.0 test case
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_row_sp012.test b/mysql-test/suite/rpl/t/rpl_row_sp012.test
new file mode 100644
index 00000000..2b8549bf
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_row_sp012.test
@@ -0,0 +1,74 @@
+#############################################################################
+# Original Author: JBM #
+# Original Date: Aug/22/2005 #
+# Update: 08/29/2005 Added save pos and sync #
+#############################################################################
+#TEST: SP to test security and current_user and user #
+#############################################################################
+
+
+# Includes
+-- source include/have_binlog_format_row.inc
+-- source include/not_embedded.inc
+-- source include/master-slave.inc
+
+
+# Begin clean up test section
+connection master;
+--disable_warnings
+DROP PROCEDURE IF EXISTS test.p1;
+DROP PROCEDURE IF EXISTS test.p2;
+DROP PROCEDURE IF EXISTS test.p3;
+
+
+# Begin test section 1
+# Create user user1 with no particular access rights
+create user user1@localhost;
+grant usage on *.* to user1@localhost;
+flush privileges;
+
+SELECT CURRENT_USER();
+SELECT USER();
+CREATE PROCEDURE test.p1 () SQL SECURITY INVOKER SELECT CURRENT_USER(), USER();
+CREATE PROCEDURE test.p2 () SQL SECURITY DEFINER CALL test.p1();
+CREATE PROCEDURE test.p3 () SQL SECURITY INVOKER CALL test.p1();
+GRANT EXECUTE ON PROCEDURE p1 TO user1@localhost;
+GRANT EXECUTE ON PROCEDURE p2 TO user1@localhost;
+GRANT EXECUTE ON PROCEDURE p3 TO user1@localhost;
+set sql_mode=default;
+
+# Need to wait for the rights to be applied at the slave
+sync_slave_with_master;
+
+connect (muser1,localhost,user1,,);
+connection muser1;
+SELECT CURRENT_USER();
+SELECT USER();
+CALL test.p3();
+CALL test.p2();
+
+connect (suser1,127.0.0.1,user1,,test,$SLAVE_MYPORT,);
+
+connection master;
+save_master_pos;
+connection suser1;
+sync_with_master;
+
+SELECT CURRENT_USER();
+SELECT USER();
+CALL test.p3();
+CALL test.p2();
+
+# Cleanup
+connection master;
+DROP PROCEDURE IF EXISTS test.p1;
+DROP PROCEDURE IF EXISTS test.p3;
+DROP PROCEDURE IF EXISTS test.p2;
+DROP TABLE IF EXISTS test.t1;
+DROP TABLE IF EXISTS test.t2;
+DROP USER user1@localhost;
+sync_slave_with_master;
+
+# End of 5.0 test case
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_row_spatial.test b/mysql-test/suite/rpl/t/rpl_row_spatial.test
new file mode 100644
index 00000000..00c3dd7c
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_row_spatial.test
@@ -0,0 +1,17 @@
+--source include/have_binlog_format_row.inc
+--source include/master-slave.inc
+
+CREATE TABLE t1 (g POINT NOT NULL, SPATIAL INDEX(g));
+INSERT INTO t1 VALUES (ST_GEOMFROMTEXT('Point(1 1)'));
+INSERT INTO t1 VALUES (ST_GEOMFROMTEXT('Point(2 1)'));
+INSERT INTO t1 VALUES (ST_GEOMFROMTEXT('Point(1 2)'));
+INSERT INTO t1 VALUES (ST_GEOMFROMTEXT('Point(2 2)'));
+DELETE FROM t1 where MBREqual(g, ST_GEOMFROMTEXT('Point(1 2)'));
+
+--sync_slave_with_master
+select count(*) from t1;
+
+--connection master
+DELETE FROM t1;
+drop table t1;
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_row_tabledefs_2myisam.test b/mysql-test/suite/rpl/t/rpl_row_tabledefs_2myisam.test
new file mode 100644
index 00000000..e1ecf702
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_row_tabledefs_2myisam.test
@@ -0,0 +1,9 @@
+
+-- source include/have_binlog_format_row.inc
+-- source include/master-slave.inc
+
+let $engine_type = 'MyISAM';
+-- source include/rpl_row_tabledefs.test
+
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_row_tabledefs_3innodb.test b/mysql-test/suite/rpl/t/rpl_row_tabledefs_3innodb.test
new file mode 100644
index 00000000..49abc84c
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_row_tabledefs_3innodb.test
@@ -0,0 +1,10 @@
+
+-- source include/have_binlog_format_row.inc
+-- source include/have_innodb.inc
+-- source include/master-slave.inc
+
+let $engine_type = 'InnoDB';
+-- source include/rpl_row_tabledefs.test
+
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_row_tbl_metadata.test b/mysql-test/suite/rpl/t/rpl_row_tbl_metadata.test
new file mode 100644
index 00000000..d3a115e9
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_row_tbl_metadata.test
@@ -0,0 +1,338 @@
+#
+# BUG#42749: infinite loop writing to row based binlog - processlist shows
+# "freeing items"
+#
+#
+# WHY
+# ===
+#
+# This bug would make table map event to report data_written one
+# byte less than what would actually be written in its body. This
+# would cause one byte shorter event end_log_pos. The ultimate
+# impact was that it would make fixing the position in
+# MYSQL_BIN_LOG::write_cache bogus or end up in an infinite loop.
+#
+# HOW
+# ===
+#
+# Checking that the patch fixes the problem is done as follows:
+#
+# i) one table with m_field_metadata sized at 290
+# ii) an insert is performed;
+# iii) the logs are flushed;
+# iv) mysqlbinlog is used to check if it succeeds.
+#
+# In step iv), before the bug was fixed, the test case would fail
+# with mysqlbinlog reporting that it was unable to succeed in
+# reading the event.
+
+-- source include/have_innodb.inc
+-- source include/have_binlog_format_row.inc
+-- source include/master-slave.inc
+
+-- disable_warnings
+DROP TABLE IF EXISTS `t1`;
+-- enable_warnings
+
+-- echo ### TABLE with field_metadata_size == 290
+CREATE TABLE `t1` (
+ `c1` int(11) NOT NULL AUTO_INCREMENT,
+ `c2` varchar(30) NOT NULL,
+ `c3` varchar(30) DEFAULT NULL,
+ `c4` varchar(30) DEFAULT NULL,
+ `c5` varchar(30) DEFAULT NULL,
+ `c6` varchar(30) DEFAULT NULL,
+ `c7` varchar(30) DEFAULT NULL,
+ `c8` varchar(30) DEFAULT NULL,
+ `c9` varchar(30) DEFAULT NULL,
+ `c10` varchar(30) DEFAULT NULL,
+ `c11` varchar(30) DEFAULT NULL,
+ `c12` varchar(30) DEFAULT NULL,
+ `c13` varchar(30) DEFAULT NULL,
+ `c14` varchar(30) DEFAULT NULL,
+ `c15` varchar(30) DEFAULT NULL,
+ `c16` varchar(30) DEFAULT NULL,
+ `c17` varchar(30) DEFAULT NULL,
+ `c18` varchar(30) DEFAULT NULL,
+ `c19` varchar(30) DEFAULT NULL,
+ `c20` varchar(30) DEFAULT NULL,
+ `c21` varchar(30) DEFAULT NULL,
+ `c22` varchar(30) DEFAULT NULL,
+ `c23` varchar(30) DEFAULT NULL,
+ `c24` varchar(30) DEFAULT NULL,
+ `c25` varchar(30) DEFAULT NULL,
+ `c26` varchar(30) DEFAULT NULL,
+ `c27` varchar(30) DEFAULT NULL,
+ `c28` varchar(30) DEFAULT NULL,
+ `c29` varchar(30) DEFAULT NULL,
+ `c30` varchar(30) DEFAULT NULL,
+ `c31` varchar(30) DEFAULT NULL,
+ `c32` varchar(30) DEFAULT NULL,
+ `c33` varchar(30) DEFAULT NULL,
+ `c34` varchar(30) DEFAULT NULL,
+ `c35` varchar(30) DEFAULT NULL,
+ `c36` varchar(30) DEFAULT NULL,
+ `c37` varchar(30) DEFAULT NULL,
+ `c38` varchar(30) DEFAULT NULL,
+ `c39` varchar(30) DEFAULT NULL,
+ `c40` varchar(30) DEFAULT NULL,
+ `c41` varchar(30) DEFAULT NULL,
+ `c42` varchar(30) DEFAULT NULL,
+ `c43` varchar(30) DEFAULT NULL,
+ `c44` varchar(30) DEFAULT NULL,
+ `c45` varchar(30) DEFAULT NULL,
+ `c46` varchar(30) DEFAULT NULL,
+ `c47` varchar(30) DEFAULT NULL,
+ `c48` varchar(30) DEFAULT NULL,
+ `c49` varchar(30) DEFAULT NULL,
+ `c50` varchar(30) DEFAULT NULL,
+ `c51` varchar(30) DEFAULT NULL,
+ `c52` varchar(30) DEFAULT NULL,
+ `c53` varchar(30) DEFAULT NULL,
+ `c54` varchar(30) DEFAULT NULL,
+ `c55` varchar(30) DEFAULT NULL,
+ `c56` varchar(30) DEFAULT NULL,
+ `c57` varchar(30) DEFAULT NULL,
+ `c58` varchar(30) DEFAULT NULL,
+ `c59` varchar(30) DEFAULT NULL,
+ `c60` varchar(30) DEFAULT NULL,
+ `c61` varchar(30) DEFAULT NULL,
+ `c62` varchar(30) DEFAULT NULL,
+ `c63` varchar(30) DEFAULT NULL,
+ `c64` varchar(30) DEFAULT NULL,
+ `c65` varchar(30) DEFAULT NULL,
+ `c66` varchar(30) DEFAULT NULL,
+ `c67` varchar(30) DEFAULT NULL,
+ `c68` varchar(30) DEFAULT NULL,
+ `c69` varchar(30) DEFAULT NULL,
+ `c70` varchar(30) DEFAULT NULL,
+ `c71` varchar(30) DEFAULT NULL,
+ `c72` varchar(30) DEFAULT NULL,
+ `c73` varchar(30) DEFAULT NULL,
+ `c74` varchar(30) DEFAULT NULL,
+ `c75` varchar(30) DEFAULT NULL,
+ `c76` varchar(30) DEFAULT NULL,
+ `c77` varchar(30) DEFAULT NULL,
+ `c78` varchar(30) DEFAULT NULL,
+ `c79` varchar(30) DEFAULT NULL,
+ `c80` varchar(30) DEFAULT NULL,
+ `c81` varchar(30) DEFAULT NULL,
+ `c82` varchar(30) DEFAULT NULL,
+ `c83` varchar(30) DEFAULT NULL,
+ `c84` varchar(30) DEFAULT NULL,
+ `c85` varchar(30) DEFAULT NULL,
+ `c86` varchar(30) DEFAULT NULL,
+ `c87` varchar(30) DEFAULT NULL,
+ `c88` varchar(30) DEFAULT NULL,
+ `c89` varchar(30) DEFAULT NULL,
+ `c90` varchar(30) DEFAULT NULL,
+ `c91` varchar(30) DEFAULT NULL,
+ `c92` varchar(30) DEFAULT NULL,
+ `c93` varchar(30) DEFAULT NULL,
+ `c94` varchar(30) DEFAULT NULL,
+ `c95` varchar(30) DEFAULT NULL,
+ `c96` varchar(30) DEFAULT NULL,
+ `c97` varchar(30) DEFAULT NULL,
+ `c98` varchar(30) DEFAULT NULL,
+ `c99` varchar(30) DEFAULT NULL,
+ `c100` varchar(30) DEFAULT NULL,
+ `c101` varchar(30) DEFAULT NULL,
+ `c102` varchar(30) DEFAULT NULL,
+ `c103` varchar(30) DEFAULT NULL,
+ `c104` varchar(30) DEFAULT NULL,
+ `c105` varchar(30) DEFAULT NULL,
+ `c106` varchar(30) DEFAULT NULL,
+ `c107` varchar(30) DEFAULT NULL,
+ `c108` varchar(30) DEFAULT NULL,
+ `c109` varchar(30) DEFAULT NULL,
+ `c110` varchar(30) DEFAULT NULL,
+ `c111` varchar(30) DEFAULT NULL,
+ `c112` varchar(30) DEFAULT NULL,
+ `c113` varchar(30) DEFAULT NULL,
+ `c114` varchar(30) DEFAULT NULL,
+ `c115` varchar(30) DEFAULT NULL,
+ `c116` varchar(30) DEFAULT NULL,
+ `c117` varchar(30) DEFAULT NULL,
+ `c118` varchar(30) DEFAULT NULL,
+ `c119` varchar(30) DEFAULT NULL,
+ `c120` varchar(30) DEFAULT NULL,
+ `c121` varchar(30) DEFAULT NULL,
+ `c122` varchar(30) DEFAULT NULL,
+ `c123` varchar(30) DEFAULT NULL,
+ `c124` varchar(30) DEFAULT NULL,
+ `c125` varchar(30) DEFAULT NULL,
+ `c126` varchar(30) DEFAULT NULL,
+ `c127` varchar(30) DEFAULT NULL,
+ `c128` varchar(30) DEFAULT NULL,
+ `c129` varchar(30) DEFAULT NULL,
+ `c130` varchar(30) DEFAULT NULL,
+ `c131` varchar(30) DEFAULT NULL,
+ `c132` varchar(30) DEFAULT NULL,
+ `c133` varchar(30) DEFAULT NULL,
+ `c134` varchar(30) DEFAULT NULL,
+ `c135` varchar(30) DEFAULT NULL,
+ `c136` varchar(30) DEFAULT NULL,
+ `c137` varchar(30) DEFAULT NULL,
+ `c138` varchar(30) DEFAULT NULL,
+ `c139` varchar(30) DEFAULT NULL,
+ `c140` varchar(30) DEFAULT NULL,
+ `c141` varchar(30) DEFAULT NULL,
+ `c142` varchar(30) DEFAULT NULL,
+ `c143` varchar(30) DEFAULT NULL,
+ `c144` varchar(30) DEFAULT NULL,
+ `c145` varchar(30) DEFAULT NULL,
+ `c146` varchar(30) DEFAULT NULL,
+ PRIMARY KEY (`c1`)
+) ENGINE=InnoDB;
+
+LOCK TABLES `t1` WRITE;
+INSERT INTO `t1`(c2) VALUES ('1');
+FLUSH LOGS;
+
+-- sync_slave_with_master
+-- connection master
+
+-- echo ### assertion: the slave replicated event successfully and tables match
+-- let $diff_tables= master:t1, slave:t1
+-- source include/diff_tables.inc
+
+DROP TABLE `t1`;
+
+-- connection master
+-- sync_slave_with_master
+-- connection master
+
+-- echo === Using mysqlbinlog to detect failure. Before the patch mysqlbinlog would find a corrupted event, thence would fail.
+
+-- let $MYSQLD_DATADIR= `SELECT @@datadir`
+-- exec $MYSQL_BINLOG $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/mysqlbinlog_bug42749.binlog
+-- remove_file $MYSQLTEST_VARDIR/tmp/mysqlbinlog_bug42749.binlog
+
+#############################################################
+# BUG#50018: binlog corruption when table has many columns
+#
+# Same test from BUG#42749, but now we generate some SQL which
+# creates and inserts into tables with metadata size from 249
+# to 258.
+#
+# The test works as follows:
+# 1. SQL for several CREATE TABLE and INSERTS are generated
+# into a file.
+# 2. This file is then "sourced"
+# 3. The slave is synchronized with the master
+# 4. FLUSH LOGS on master
+# 5. Compare tables on master and slave.
+# 6. run mysqlbinlog on master's binary log
+#
+# Steps #5 and #6 assert that binary log is not corrupted
+# in both cases: when slave is replaying events and when
+# mysqlbinlog is used to read the binary log
+
+--source include/rpl_reset.inc
+-- connection master
+
+# Create several tables with field_metadata_size ranging
+# from 249 to 258 (so that we cover 251 and 255 range).
+# This should exercise the switch between using 1 or 3
+# bytes to pack m_field_metadata_size.
+#
+# Each varchar field takes up to 2 metadata bytes, see:
+#
+# Field_varstring::save_field_metadata (field.cc)
+#
+# The float field takes 1 byte, see:
+#
+# Field_float::save_field_metadata (field.cc)
+#
+
+-- let $generated_sql= $MYSQLTEST_VARDIR/tmp/b50018.sql
+-- let B50018_FILE= $generated_sql
+
+-- echo ### action: generating several tables with different metadata
+-- echo ### sizes (resorting to perl)
+-- perl
+my $file= $ENV{'B50018_FILE'};
+open(FILE, ">", "$file") or die "Unable to open bug 50018 generated SQL file: $!" ;
+
+my $tables= "";
+my $ntables= 10;
+my $base_ncols= 124;
+
+for my $i (1..$ntables)
+{
+ my $ncols= $base_ncols + $i;
+ my $metadata_size= $ncols_variable * 2 + 1;
+
+ print FILE "-- echo ### testing table with " . ($base_ncols*2 + $i) . " field metadata size.\n";
+ print FILE "CREATE TABLE t$i (\n";
+ for my $n (1..$base_ncols)
+ {
+ print FILE "c$n VARCHAR(30) NOT NULL DEFAULT 'BUG#50018',\n";
+ }
+
+ for my $n (1..$i)
+ {
+ print FILE "c" . ($base_ncols+$n) . " FLOAT NOT NULL DEFAULT 0";
+ if ($n < $i)
+ {
+ print FILE ",\n";
+ }
+ }
+
+ print FILE ") Engine=InnoDB;\n";
+
+ $tables.= " t$i WRITE";
+ if ($i < $ntables)
+ {
+ $tables .=",";
+ }
+
+ print FILE "LOCK TABLES t$i WRITE;\n";
+ print FILE "INSERT INTO t$i(c". ($base_ncols+1) . ") VALUES (50018);\n";
+ print FILE "UNLOCK TABLES;";
+}
+
+close(FILE);
+
+EOF
+
+## we don't need this in the result file
+## however, for debugging purposes you
+## may want to reactivate query logging
+-- disable_query_log
+-- source $generated_sql
+-- enable_query_log
+
+-- sync_slave_with_master
+-- connection master
+
+FLUSH LOGS;
+
+-- let $ntables=10
+while($ntables)
+{
+ -- echo ### assertion: the slave replicated event successfully and tables match for t$ntables
+ -- let $diff_tables= master:t$ntables, slave:t$ntables
+ -- source include/diff_tables.inc
+
+ -- connection master
+ -- disable_query_log
+ -- eval DROP TABLE t$ntables
+ -- enable_query_log
+ -- sync_slave_with_master
+ -- connection master
+
+ -- dec $ntables
+}
+
+-- echo ### assertion: check that binlog is not corrupt. Using mysqlbinlog to
+-- echo ### detect failure. Before the patch mysqlbinlog would find
+-- echo ### a corrupted event, thence would fail.
+-- let $MYSQLD_DATADIR= `SELECT @@datadir`
+-- exec $MYSQL_BINLOG -v --hexdump $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/mysqlbinlog_bug50018.binlog
+
+## clean up
+## For debugging purposes you might want not to remove these
+-- remove_file $MYSQLTEST_VARDIR/tmp/mysqlbinlog_bug50018.binlog
+-- remove_file $generated_sql
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_row_to_stmt-master.opt b/mysql-test/suite/rpl/t/rpl_row_to_stmt-master.opt
new file mode 100644
index 00000000..83ed8522
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_row_to_stmt-master.opt
@@ -0,0 +1 @@
+--binlog-format=row
diff --git a/mysql-test/suite/rpl/t/rpl_row_to_stmt-slave.opt b/mysql-test/suite/rpl/t/rpl_row_to_stmt-slave.opt
new file mode 100644
index 00000000..af3a2119
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_row_to_stmt-slave.opt
@@ -0,0 +1 @@
+--binlog-format=statement
diff --git a/mysql-test/suite/rpl/t/rpl_row_to_stmt.test b/mysql-test/suite/rpl/t/rpl_row_to_stmt.test
new file mode 100644
index 00000000..5ca583d8
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_row_to_stmt.test
@@ -0,0 +1,23 @@
+#
+# check that master starterd with log-format=ROW replication can replicate to
+# slave started with log-format=STATEMENT
+#
+
+--source include/have_binlog_format_row.inc
+--source include/master-slave.inc
+
+use test;
+
+create table t1 (a int primary key);
+insert into t1 values (1),(2),(3),(4),(5);
+update t1 set a=a*10;
+
+sync_slave_with_master;
+use test;
+select * from t1;
+source include/show_binlog_events.inc;
+
+connection master;
+drop table t1;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_row_trig001.test b/mysql-test/suite/rpl/t/rpl_row_trig001.test
new file mode 100644
index 00000000..39f2662b
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_row_trig001.test
@@ -0,0 +1,116 @@
+#############################################################################
+# Original Author: JBM #
+# Original Date: Aug/09/2005 #
+#############################################################################
+# TEST: Use after insert and before inset triggers and stored procdures to #
+# Update and insert data #
+#############################################################################
+
+# Includes
+-- source include/have_binlog_format_row.inc
+-- source include/master-slave.inc
+
+-- disable_query_log
+-- disable_result_log
+
+# Begin clean up test section
+connection master;
+--disable_warnings
+DROP PROCEDURE IF EXISTS test.p2;
+DROP PROCEDURE IF EXISTS test.p3;
+--error 0,1360
+DROP TRIGGER test.t2_ai;
+--error 0,1360
+DROP TRIGGER test.t3_bi_t2;
+--error 0,1360
+DROP TABLE IF EXISTS test.t1;
+DROP TABLE IF EXISTS test.t2;
+DROP TABLE IF EXISTS test.t3;
+
+
+# test section 1, lets add a trigger to the mix. Taken from bug #12280
+let $message=<Begin test section 1 (Tiggers & SP)>;
+--source include/show_msg.inc
+
+CREATE TABLE test.t1 (n MEDIUMINT NOT NULL, d DATETIME, PRIMARY KEY(n));
+CREATE TABLE test.t2 (n MEDIUMINT NOT NULL AUTO_INCREMENT, f FLOAT, d DATETIME, PRIMARY KEY(n));
+CREATE TABLE test.t3 (n MEDIUMINT NOT NULL AUTO_INCREMENT, d DATETIME, PRIMARY KEY(n));
+
+INSERT INTO test.t1 VALUES (1,NOW());
+
+delimiter //;
+CREATE TRIGGER test.t2_ai AFTER INSERT ON test.t2 FOR EACH ROW UPDATE test.t1 SET d=NOW() where n = 1//
+CREATE PROCEDURE test.p3()
+BEGIN
+ INSERT INTO test.t3 (d) VALUES (NOW());
+END//
+CREATE TRIGGER test.t3_bi_t2 BEFORE INSERT ON test.t2 FOR EACH ROW CALL test.p3()//
+CREATE PROCEDURE test.p2()
+BEGIN
+ INSERT INTO test.t2 (f,d) VALUES (RAND(),NOW());
+END//
+delimiter ;//
+
+# Make sure that all definition have propagated to the slave
+sync_slave_with_master;
+
+connection master;
+-- disable_query_log
+-- disable_result_log
+SET @wait_count = 1;
+let $1=10;
+while ($1)
+{
+ CALL test.p2();
+ let $wait_condition= SELECT COUNT(*) = @wait_count FROM test.t3;
+ --source include/wait_condition.inc
+ --disable_query_log
+ SET @wait_count = @wait_count + 1;
+ dec $1;
+}
+-- enable_result_log
+-- enable_query_log
+
+# Just a precaution to make sure all changes have made it over to the
+# slave
+connection master;
+let $count = `select count(*) from t1`;
+eval INSERT INTO test.t1 VALUES ($count+1, NOW());
+sync_slave_with_master;
+
+#show binlog events;
+#select * from test.t2;
+#select * from test.t3;
+#connection slave;
+#select * from test.t2;
+#select * from test.t3;
+
+let $message=<End test section 2 (Tiggers & SP)>;
+--source include/show_msg.inc
+
+# time to dump the databases and so we can see if they match
+
+--exec $MYSQL_DUMP --compact --order-by-primary --skip-extended-insert --no-create-info test > $MYSQLTEST_VARDIR/tmp/trig001_master.sql
+--exec $MYSQL_DUMP_SLAVE --compact --order-by-primary --skip-extended-insert --no-create-info test > $MYSQLTEST_VARDIR/tmp/trig001_slave.sql
+
+# Cleanup
+connection master;
+DROP PROCEDURE test.p2;
+DROP PROCEDURE test.p3;
+DROP TRIGGER test.t2_ai;
+DROP TRIGGER test.t3_bi_t2;
+DROP TABLE test.t1;
+DROP TABLE test.t2;
+DROP TABLE test.t3;
+sync_slave_with_master;
+
+# Lets compare. Note: If they match test will pass, if they do not match
+# the test will show that the diff statement failed and not reject file
+# will be created. You will need to go to the mysql-test dir and diff
+# the files your self to see what is not matching :-) Failed tests
+# will leave dump files in $MYSQLTEST_VARDIR/tmp
+
+diff_files $MYSQLTEST_VARDIR/tmp/trig001_master.sql $MYSQLTEST_VARDIR/tmp/trig001_slave.sql;
+
+# End of 5.0 test case
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_row_trig002.test b/mysql-test/suite/rpl/t/rpl_row_trig002.test
new file mode 100644
index 00000000..f04d1e6d
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_row_trig002.test
@@ -0,0 +1,77 @@
+#############################################################################
+# Original Author: JBM #
+# Original Date: Aug/14/2005 #
+# Updated: 08/29/2005 added save master pos and sync with master #
+#############################################################################
+# TEST: Taken and modified from BUG#12048 After Insert updates replication #
+#############################################################################
+
+# Includes
+-- source include/have_binlog_format_row.inc
+-- source include/master-slave.inc
+
+#-- disable_query_log
+#-- disable_result_log
+
+# Begin clean up test section
+connection master;
+--disable_warnings
+--error 0,1360
+DROP TRIGGER test.t2_ai;
+DROP TABLE IF EXISTS test.t1;
+DROP TABLE IF EXISTS test.t2;
+DROP TABLE IF EXISTS test.t3;
+--enable_warnings
+
+# test section 1, Taken from bug #12408
+
+CREATE TABLE test.t2 (value CHAR(30),domain_id INT, mailaccount_id INT, program CHAR(30),keey CHAR(30),PRIMARY KEY(domain_id));
+
+CREATE TABLE test.t3 (value CHAR(30),domain_id INT, mailaccount_id INT, program CHAR(30),keey CHAR(30),PRIMARY KEY(domain_id));
+
+CREATE TABLE test.t1 (id INT,domain CHAR(30),PRIMARY KEY(id));
+
+delimiter |;
+CREATE TRIGGER test.t2_ai AFTER INSERT ON test.t2 FOR EACH ROW UPDATE test.t3 ms, test.t1 d SET ms.value='No' WHERE ms.domain_id = (SELECT max(id) FROM test.t1 WHERE domain='example.com') AND ms.mailaccount_id IS NULL AND ms.program='spamfilter' AND ms.keey='scan_incoming'|
+delimiter ;|
+
+INSERT INTO test.t1 VALUES (1, 'example.com'),(2, 'mysql.com'),(3, 'earthmotherwear.com'), (4, 'yahoo.com'),(5, 'example.com');
+
+SELECT * FROM test.t1 ORDER BY id;
+#show binlog events;
+sync_slave_with_master;
+SELECT * FROM test.t1 ORDER BY id;
+connection master;
+
+INSERT INTO test.t3 VALUES ('Yes', 5, NULL, 'spamfilter','scan_incoming');
+INSERT INTO test.t3 VALUES ('Yes', 1, NULL, 'spamfilter','scan_incoming');
+INSERT INTO test.t2 VALUES ('Yes', 1, NULL, 'spamfilter','scan_incoming');
+
+select * from test.t2;
+--sorted_result
+select * from test.t3;
+sync_slave_with_master;
+select * from test.t2;
+--sorted_result
+select * from test.t3;
+connection master;
+
+DELETE FROM test.t1 WHERE id = 1;
+
+SELECT * FROM test.t1 ORDER BY id;
+connection master;
+SELECT * FROM test.t1 ORDER BY id;
+sync_slave_with_master;
+SELECT * FROM test.t1 ORDER BY id;
+
+# Cleanup
+connection master;
+#show binlog events;
+DROP TRIGGER test.t2_ai;
+DROP TABLE test.t1;
+DROP TABLE test.t2;
+DROP TABLE test.t3;
+sync_slave_with_master;
+
+# End of 5.0 test case
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_row_trig003.test b/mysql-test/suite/rpl/t/rpl_row_trig003.test
new file mode 100644
index 00000000..e332fc91
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_row_trig003.test
@@ -0,0 +1,155 @@
+#############################################################################
+# Original Author: JBM #
+# Original Date: Aug/16/2005 #
+# Updated: 8/29/2005 Remove sleep calls add dump and diff #
+#############################################################################
+# TEST: This test includes all trigger types. BEFORE/AFTER INSERT, UPDATE & #
+# DELETE. In addition, includes cursor, bit, varchar, flow control, #
+# looping, ROUND(), NOW(), YEAR(), TIMESTAMP #
+#############################################################################
+
+# Includes
+-- source include/have_binlog_format_row.inc
+-- source include/master-slave.inc
+
+#-- disable_query_log
+#-- disable_result_log
+
+# Begin clean up test section
+connection master;
+--disable_warnings
+--error 0,1360
+DROP TRIGGER test.t1_bi;
+--error 0,1360
+DROP TRIGGER test.t2_ai;
+--error 0,1360
+DROP TRIGGER test.t1_bu;
+--error 0,1360
+DROP TRIGGER test.t2_au;
+--error 0,1360
+DROP TRIGGER test.t1_bd;
+--error 0,1360
+DROP TRIGGER test.t2_ad;
+DROP TABLE IF EXISTS test.t1;
+DROP TABLE IF EXISTS test.t2;
+DROP TABLE IF EXISTS test.t3;
+--enable_warnings
+
+# test section 1
+
+CREATE TABLE test.t1 (id MEDIUMINT NOT NULL AUTO_INCREMENT, b1 BIT(8), vc VARCHAR(255), bc CHAR(255), d DECIMAL(10,4) DEFAULT 0, f FLOAT DEFAULT 0, total BIGINT UNSIGNED, y YEAR, t TIMESTAMP,PRIMARY KEY(id));
+CREATE TABLE test.t2 (id MEDIUMINT NOT NULL AUTO_INCREMENT, b1 BIT(8), vc VARCHAR(255), bc CHAR(255), d DECIMAL(10,4) DEFAULT 0, f FLOAT DEFAULT 0, total BIGINT UNSIGNED, y YEAR, t TIMESTAMP,PRIMARY KEY(id));
+CREATE TABLE test.t3 (id MEDIUMINT NOT NULL AUTO_INCREMENT, b1 BIT(8), vc VARCHAR(255), bc CHAR(255), d DECIMAL(10,4) DEFAULT 0, f FLOAT DEFAULT 0, total BIGINT UNSIGNED, y YEAR, t TIMESTAMP,PRIMARY KEY(id));
+
+# Note Most of these cause the slave to core or do not produce desired results. Currently commenting out the ones not working until they are fixed.
+
+delimiter |;
+CREATE TRIGGER test.t1_bi BEFORE INSERT ON test.t1 FOR EACH ROW UPDATE test.t3 SET b1=1 and y=YEAR(NOW())|
+CREATE TRIGGER test.t2_ai AFTER INSERT ON test.t2 FOR EACH ROW BEGIN
+ INSERT INTO test.t3 VALUES(NULL,0,'MySQL Replication team rocks!', 'Dark beer in prague is #1',12345.34,12.51,0,1965,NOW());
+ UPDATE test.t3 SET f = ROUND(f);
+END|
+CREATE TRIGGER test.t1_bu BEFORE UPDATE on test.t1 FOR EACH ROW BEGIN
+ UPDATE test.t3 SET y = '2000';
+ INSERT INTO test.t3 VALUES(NULL,1,'Testing MySQL databases before update ', 'Insert should work',621.43, 0105.21,0,1974,NOW());
+END|
+CREATE TRIGGER test.t2_au AFTER UPDATE on test.t2 FOR EACH ROW BEGIN
+ DECLARE done INT DEFAULT 0;
+ DECLARE a DECIMAL(10,4);
+ DECLARE b FLOAT;
+ DECLARE num MEDIUMINT;
+ DECLARE cur1 CURSOR FOR SELECT t2.id, t2.d, t2.f FROM test.t2;
+ DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done = 1;
+
+ OPEN cur1;
+
+ REPEAT
+ FETCH cur1 INTO num, a, b;
+ IF NOT done THEN
+ UPDATE test.t3 SET total =(a*b) WHERE ID = num;
+ END IF;
+ UNTIL done END REPEAT;
+ CLOSE cur1;
+END|
+CREATE TRIGGER test.t1_bd BEFORE DELETE on test.t1 FOR EACH ROW BEGIN
+ DECLARE done INT DEFAULT 0;
+ DECLARE a BIT(8);
+ DECLARE b VARCHAR(255);
+ DECLARE c CHAR(255);
+ DECLARE d DECIMAL(10,4);
+ DECLARE e FLOAT;
+ DECLARE f BIGINT UNSIGNED;
+ DECLARE g YEAR;
+ DECLARE h TIMESTAMP;
+ DECLARE cur1 CURSOR FOR SELECT t1.b1, t1.vc, t1.bc, t1.d, t1.f, t1.total, t1.y, t1.t FROM test.t1;
+ DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done = 1;
+
+ OPEN cur1;
+
+ REPEAT
+ FETCH cur1 INTO a, b, c, d, e, f, g, h;
+ IF NOT done THEN
+ INSERT INTO test.t3 VALUES(NULL, a, b, c, d, e, f, g, h);
+ END IF;
+ UNTIL done END REPEAT;
+ CLOSE cur1;
+END|
+CREATE TRIGGER test.t2_ad AFTER DELETE ON test.t2 FOR EACH ROW
+ DELETE FROM test.t1|
+delimiter ;|
+
+INSERT INTO test.t1 VALUES(NULL,1,'Testing MySQL databases is a cool ', 'Must make it bug free for the customer',654321.4321,15.21,0,1965,NOW());
+INSERT INTO test.t2 VALUES(NULL,0,'Testing MySQL databases is a cool ', 'MySQL Customers ROCK!',654321.4321,1.24521,0,YEAR(NOW()),NOW());
+
+UPDATE test.t1 SET b1 = 0 WHERE b1 = 1;
+
+INSERT INTO test.t2 VALUES(NULL,1,'This is an after update test.', 'If this works, total will not be zero on the master or slave',1.4321,5.221,0,YEAR(NOW()),NOW());
+UPDATE test.t2 SET b1 = 0 WHERE b1 = 1;
+
+INSERT INTO test.t1 VALUES(NULL,1,'add some more test data test.', 'and hope for the best', 3.321,5.221,0,YEAR(NOW()),NOW());
+
+# To make sure BUG#14698 is gone, we sleep before calling trigger
+# (with the bug in, that caused differences in TIMESTAMP columns).
+# We just need to let the machine's clock advance, it's not
+# to do synchronization.
+
+let $wait_condition= SELECT SUM(f)= ROUND(SUM(f)) FROM t3;
+--source include/wait_condition.inc
+
+DELETE FROM test.t1 WHERE id = 1;
+
+DELETE FROM test.t2 WHERE id = 1;
+
+sync_slave_with_master;
+connection master;
+
+# time to dump the databases and so we can see if they match
+
+--exec $MYSQL_DUMP --compact --order-by-primary --skip-extended-insert --no-create-info test > $MYSQLTEST_VARDIR/tmp/trg003_master.sql
+--exec $MYSQL_DUMP_SLAVE --compact --order-by-primary --skip-extended-insert --no-create-info test > $MYSQLTEST_VARDIR/tmp/trg003_slave.sql
+
+# cleanup
+--disable_warnings
+--error 0,1360
+DROP TRIGGER test.t1_bi;
+--error 0,1360
+DROP TRIGGER test.t2_ai;
+--error 0,1360
+DROP TRIGGER test.t1_bu;
+--error 0,1360
+DROP TRIGGER test.t2_au;
+--error 0,1360
+DROP TRIGGER test.t1_bd;
+--error 0,1360
+DROP TRIGGER test.t2_ad;
+DROP TABLE IF EXISTS test.t1;
+DROP TABLE IF EXISTS test.t2;
+DROP TABLE IF EXISTS test.t3;
+--enable_warnings
+
+sync_slave_with_master;
+
+diff_files $MYSQLTEST_VARDIR/tmp/trg003_master.sql $MYSQLTEST_VARDIR/tmp/trg003_slave.sql;
+
+# End of 5.0 test case
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_row_trig004.test b/mysql-test/suite/rpl/t/rpl_row_trig004.test
new file mode 100644
index 00000000..0cbdea33
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_row_trig004.test
@@ -0,0 +1,15 @@
+#############################################################################
+# Original Author: JBM #
+# Original Date: Oct/18/2005 #
+#############################################################################
+# TEST: Use before insert triggers and has the second insert fail #
+#############################################################################
+
+# Includes
+-- source include/have_binlog_format_row.inc
+-- source include/have_innodb.inc
+-- source include/master-slave.inc
+let $engine_type=INNODB;
+-- source include/rpl_trig004.test
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_row_trigger_multi_db.test b/mysql-test/suite/rpl/t/rpl_row_trigger_multi_db.test
new file mode 100644
index 00000000..0ade0090
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_row_trigger_multi_db.test
@@ -0,0 +1,98 @@
+#
+# This test ensures that a table share's database name is not freed when
+# using row based replication with triggers that open different databases
+#
+#
+# References:
+# MDEV-29894: Calling a function from a different database in a slave side
+# trigger crashes
+#
+--source include/master-slave.inc
+--source include/have_binlog_format_row.inc
+
+--connection slave
+--let $old_slave_run_triggers= `SELECT @@global.slave_run_triggers_for_rbr`
+set global slave_run_triggers_for_rbr=1;
+
+--connection master
+CREATE TABLE t1 (a int);
+--sync_slave_with_master
+
+--connection slave
+CREATE DATABASE db2;
+CREATE FUNCTION db2.get_value(a INT) RETURNS int(2) RETURN 0;
+
+--echo #
+--echo # Test Insert_rows_log_event
+
+--connection slave
+DELIMITER //;
+CREATE TRIGGER tr_ins BEFORE INSERT ON t1 FOR EACH ROW BEGIN
+DECLARE a INT;
+SET a = db2.get_value(1);
+END//
+DELIMITER ;//
+
+--connection master
+INSERT INTO t1 VALUES (1);
+--sync_slave_with_master
+
+--connection slave
+DROP TRIGGER tr_ins;
+
+
+--echo #
+--echo # Test Update_rows_log_event
+--connection master
+--let $row_val=5
+--eval INSERT INTO t1 VALUES ($row_val)
+--sync_slave_with_master
+
+--connection slave
+DELIMITER //;
+CREATE TRIGGER tr_upd BEFORE UPDATE ON t1 FOR EACH ROW BEGIN
+DECLARE a INT;
+SET a = db2.get_value(1);
+END//
+DELIMITER ;//
+
+--connection master
+--eval UPDATE t1 SET a=a+1 WHERE a=$row_val
+--sync_slave_with_master
+
+--connection slave
+DROP TRIGGER tr_upd;
+
+
+--echo #
+--echo # Test Delete_rows_log_event
+--connection master
+--let $row_val=7
+--eval INSERT INTO t1 VALUES ($row_val)
+--sync_slave_with_master
+
+--connection slave
+DELIMITER //;
+CREATE TRIGGER tr_del BEFORE DELETE ON t1 FOR EACH ROW BEGIN
+DECLARE a INT;
+SET a = db2.get_value(1);
+END//
+DELIMITER ;//
+
+--connection master
+--eval DELETE FROM t1 WHERE a=$row_val
+--sync_slave_with_master
+
+--connection slave
+DROP TRIGGER tr_del;
+
+
+--echo #
+--echo # Cleanup
+--connection slave
+--eval SET GLOBAL slave_run_triggers_for_rbr=$old_slave_run_triggers
+DROP DATABASE db2;
+--connection master
+DROP TABLE t1;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_row_triggers.test b/mysql-test/suite/rpl/t/rpl_row_triggers.test
new file mode 100644
index 00000000..68002dbe
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_row_triggers.test
@@ -0,0 +1,442 @@
+-- source include/have_binlog_format_row.inc
+-- source include/have_innodb.inc
+-- source include/master-slave.inc
+
+-- echo # Test of row replication with triggers on the slave side
+
+connection master;
+CREATE TABLE t1 (C1 CHAR(1) primary key, C2 CHAR(1)) engine=innodb;
+SELECT * FROM t1;
+
+sync_slave_with_master;
+
+connection slave;
+SET @old_slave_exec_mode= @@global.slave_exec_mode;
+SET @old_slave_run_triggers_for_rbr= @@global.slave_run_triggers_for_rbr;
+SET @@global.slave_exec_mode= IDEMPOTENT;
+SET @@global.slave_run_triggers_for_rbr= YES;
+SELECT * FROM t1;
+create table t2 (id char(2) primary key, cnt int, o char(1), n char(1));
+insert into t2 values
+ ('u0', 0, ' ', ' '),('u1', 0, ' ', ' '),
+ ('d0', 0, ' ', ' '),('d1', 0, ' ', ' '),
+ ('i0', 0, ' ', ' '),('i1', 0, ' ', ' ');
+create trigger t1_cnt_b before update on t1 for each row
+ update t2 set cnt=cnt+1, o=old.C1, n=new.C1 where id = 'u0';
+create trigger t1_cnt_db before delete on t1 for each row
+ update t2 set cnt=cnt+1, o=old.C1, n=' ' where id = 'd0';
+create trigger t1_cnt_ib before insert on t1 for each row
+ update t2 set cnt=cnt+1, n=new.C1, o=' ' where id = 'i0';
+create trigger t1_cnt_a after update on t1 for each row
+ update t2 set cnt=cnt+1, o=old.C1, n=new.C1 where id = 'u1';
+create trigger t1_cnt_da after delete on t1 for each row
+ update t2 set cnt=cnt+1, o=old.C1, n=' ' where id = 'd1';
+create trigger t1_cnt_ia after insert on t1 for each row
+ update t2 set cnt=cnt+1, n=new.C1, o=' ' where id = 'i1';
+SELECT * FROM t2 order by id;
+
+connection master;
+--echo # INSERT triggers test
+insert into t1 values ('a','b');
+
+sync_slave_with_master;
+
+connection slave;
+SELECT * FROM t2 order by id;
+
+connection master;
+
+--echo # UPDATE triggers test
+update t1 set C1= 'd';
+
+sync_slave_with_master;
+
+connection slave;
+SELECT * FROM t2 order by id;
+
+connection master;
+--echo # DELETE triggers test
+delete from t1 where C1='d';
+
+sync_slave_with_master;
+
+connection slave;
+SELECT * FROM t2 order by id;
+
+--echo # INSERT triggers causing DELETE + INSERT (on unique key conflict)
+insert into t1 values ('0','1');
+
+SELECT * FROM t2 order by id;
+
+connection master;
+
+insert into t1 values ('0','1');
+
+sync_slave_with_master;
+
+connection slave;
+SELECT * FROM t2 order by id;
+
+
+--echo # INSERT triggers which cause also DELETE test
+--echo # (insert duplicate row in table referenced by foreign key)
+insert into t1 values ('1','1');
+
+connection master;
+
+CREATE TABLE t3 (C1 CHAR(1) primary key, FOREIGN KEY (C1) REFERENCES t1(C1) ) engine=innodb;
+
+insert into t1 values ('1','1');
+
+sync_slave_with_master;
+
+connection slave;
+SELECT * FROM t2 order by id;
+
+connection master;
+
+drop table t3,t1;
+
+sync_slave_with_master;
+
+connection slave;
+SET @@global.slave_exec_mode= @old_slave_exec_mode;
+SET @@global.slave_run_triggers_for_rbr= @old_slave_run_triggers_for_rbr;
+drop table t2;
+
+--connection master
+
+CREATE TABLE t1 (i INT) ENGINE=InnoDB;
+CREATE TABLE t2 (i INT) ENGINE=InnoDB;
+
+--sync_slave_with_master
+
+SET @old_slave_run_triggers_for_rbr= @@global.slave_run_triggers_for_rbr;
+SET GLOBAL slave_run_triggers_for_rbr=YES;
+
+CREATE TRIGGER tr AFTER INSERT ON t1 FOR EACH ROW
+ INSERT INTO t2 VALUES (new.i);
+
+--connection master
+
+BEGIN;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+COMMIT;
+
+--sync_slave_with_master
+select * from t2;
+SET @@global.slave_run_triggers_for_rbr= @old_slave_run_triggers_for_rbr;
+
+--connection master
+drop tables t2,t1;
+
+--sync_slave_with_master
+
+-- echo # Triggers on slave do not work if master has some
+
+connection master;
+CREATE TABLE t1 (C1 CHAR(1) primary key, C2 CHAR(1)) engine=innodb;
+SELECT * FROM t1;
+
+create trigger t1_dummy before delete on t1 for each row
+ set @dummy= 1;
+
+sync_slave_with_master;
+
+connection slave;
+SET @old_slave_exec_mode= @@global.slave_exec_mode;
+SET @old_slave_run_triggers_for_rbr= @@global.slave_run_triggers_for_rbr;
+SET @@global.slave_exec_mode= IDEMPOTENT;
+SET @@global.slave_run_triggers_for_rbr= YES;
+SELECT * FROM t1;
+create table t2 (id char(2) primary key, cnt int, o char(1), n char(1));
+insert into t2 values
+ ('u0', 0, ' ', ' '),('u1', 0, ' ', ' '),
+ ('d0', 0, ' ', ' '),('d1', 0, ' ', ' '),
+ ('i0', 0, ' ', ' '),('i1', 0, ' ', ' ');
+create trigger t1_cnt_b before update on t1 for each row
+ update t2 set cnt=cnt+1, o=old.C1, n=new.C1 where id = 'u0';
+create trigger t1_cnt_ib before insert on t1 for each row
+ update t2 set cnt=cnt+1, n=new.C1, o=' ' where id = 'i0';
+create trigger t1_cnt_a after update on t1 for each row
+ update t2 set cnt=cnt+1, o=old.C1, n=new.C1 where id = 'u1';
+create trigger t1_cnt_da after delete on t1 for each row
+ update t2 set cnt=cnt+1, o=old.C1, n=' ' where id = 'd1';
+create trigger t1_cnt_ia after insert on t1 for each row
+ update t2 set cnt=cnt+1, n=new.C1, o=' ' where id = 'i1';
+SELECT * FROM t2 order by id;
+
+connection master;
+--echo # INSERT triggers test
+insert into t1 values ('a','b');
+
+sync_slave_with_master;
+
+connection slave;
+SELECT * FROM t2 order by id;
+
+connection master;
+
+--echo # UPDATE triggers test
+update t1 set C1= 'd';
+
+sync_slave_with_master;
+
+connection slave;
+SELECT * FROM t2 order by id;
+
+connection master;
+--echo # DELETE triggers test
+delete from t1 where C1='d';
+
+sync_slave_with_master;
+
+connection slave;
+SELECT * FROM t2 order by id;
+
+--echo # INSERT triggers which cause also UPDATE test (insert duplicate row)
+insert into t1 values ('0','1');
+
+SELECT * FROM t2 order by id;
+
+connection master;
+
+insert into t1 values ('0','1');
+
+sync_slave_with_master;
+
+connection slave;
+SELECT * FROM t2 order by id;
+
+
+--echo # INSERT triggers which cause also DELETE test
+--echo # (insert duplicate row in table referenced by foreign key)
+insert into t1 values ('1','1');
+
+connection master;
+
+CREATE TABLE t3 (C1 CHAR(1) primary key, FOREIGN KEY (C1) REFERENCES t1(C1) ) engine=innodb;
+
+insert into t1 values ('1','1');
+
+sync_slave_with_master;
+
+connection slave;
+SELECT * FROM t2 order by id;
+
+connection master;
+
+drop table t3,t1;
+
+sync_slave_with_master;
+
+connection slave;
+SET @@global.slave_exec_mode= @old_slave_exec_mode;
+SET @@global.slave_run_triggers_for_rbr= @old_slave_run_triggers_for_rbr;
+drop table t2;
+
+--echo #
+--echo # MDEV-5513: Trigger is applied to the rows after first one
+--echo #
+
+--connection master
+
+create table t1 (a int, b int);
+create table tlog (a int);
+
+set sql_log_bin=0;
+create trigger tr1 after insert on t1 for each row insert into tlog values (1);
+set sql_log_bin=1;
+
+sync_slave_with_master;
+--connection slave
+
+set @slave_run_triggers_for_rbr.saved = @@slave_run_triggers_for_rbr;
+set global slave_run_triggers_for_rbr=1;
+create trigger tr2 before insert on t1 for each row set new.b = new.a;
+
+--connection master
+
+insert into t1 values (1,10),(2,20),(3,30);
+
+--sync_slave_with_master
+
+select * from t1;
+
+# Cleanup
+
+set global slave_run_triggers_for_rbr = @slave_run_triggers_for_rbr.saved;
+
+--connection master
+
+drop table t1, tlog;
+
+sync_slave_with_master;
+
+
+--echo #
+--echo # MDEV-8411 Assertion `is_stat_field || !table || (!table->write_set ||
+--echo # bitmap_is_set(table->write_set, field_index) ||
+--echo # bitmap_is_set(table->vcol_set, field_index))'
+--echo # failed in Field_timestamp::store_TIME_with_warning
+--echo #
+--echo #
+--echo # Create table on master, replicate it on slave.
+--echo #
+--connection master
+set @binlog_row_image.saved = @@binlog_row_image;
+set binlog_row_image = MINIMAL;
+create table t1 (pk int primary key, f int);
+
+--sync_slave_with_master
+--echo #
+--echo # Create a trigger on the slave.
+--echo #
+create trigger tr before update on t1 for each row set new.f = 1000;
+set @old_slave_run_triggers_for_rbr = @@global.slave_run_triggers_for_rbr;
+set global slave_run_triggers_for_rbr = YES;
+
+--connection master
+--echo #
+--echo # Update the table to have the trigger fire on the slave.,
+--echo #
+insert into t1 values (1,1),(2,2);
+update t1 set pk=pk+10;
+select * from t1;
+
+--sync_slave_with_master
+--echo #
+--echo # Check to see if slave has the table updated.
+--echo #
+select * from t1;
+
+--echo #
+--echo # Cleanup
+--echo #
+
+set global slave_run_triggers_for_rbr = @old_slave_run_triggers_for_rbr;
+
+--connection master
+set binlog_row_image = @binlog_row_image.saved;
+drop table t1;
+
+--sync_slave_with_master
+
+--echo #
+--echo # enterprise 10.4 tests start
+--echo #
+
+--echo #
+--echo # MENT-607 : Make slave_run_triggers_for_rbr enforce triggers to run
+--echo # on slave, even when there are triggers on the master
+--echo #
+
+--echo # Triggers on slave WILL work (with ENFORCE) if master has some
+
+connection master;
+CREATE TABLE t1 (C1 CHAR(1) primary key, C2 CHAR(1)) engine=innodb;
+SELECT * FROM t1;
+
+create trigger t1_dummy before delete on t1 for each row
+ set @dummy= 1;
+
+sync_slave_with_master;
+
+connection slave;
+SET @old_slave_exec_mode= @@global.slave_exec_mode;
+SET @old_slave_run_triggers_for_rbr= @@global.slave_run_triggers_for_rbr;
+SET @@global.slave_exec_mode= IDEMPOTENT;
+SET @@global.slave_run_triggers_for_rbr= ENFORCE;
+SELECT * FROM t1;
+create table t2 (id char(2) primary key, cnt int, o char(1), n char(1));
+insert into t2 values
+ ('u0', 0, ' ', ' '),('u1', 0, ' ', ' '),
+ ('d0', 0, ' ', ' '),('d1', 0, ' ', ' '),
+ ('i0', 0, ' ', ' '),('i1', 0, ' ', ' ');
+create trigger t1_cnt_b before update on t1 for each row
+ update t2 set cnt=cnt+1, o=old.C1, n=new.C1 where id = 'u0';
+create trigger t1_cnt_ib before insert on t1 for each row
+ update t2 set cnt=cnt+1, n=new.C1, o=' ' where id = 'i0';
+create trigger t1_cnt_a after update on t1 for each row
+ update t2 set cnt=cnt+1, o=old.C1, n=new.C1 where id = 'u1';
+create trigger t1_cnt_da after delete on t1 for each row
+ update t2 set cnt=cnt+1, o=old.C1, n=' ' where id = 'd1';
+create trigger t1_cnt_ia after insert on t1 for each row
+ update t2 set cnt=cnt+1, n=new.C1, o=' ' where id = 'i1';
+SELECT * FROM t2 order by id;
+
+connection master;
+--echo # INSERT triggers test
+insert into t1 values ('a','b');
+
+sync_slave_with_master;
+
+connection slave;
+SELECT * FROM t2 order by id;
+
+connection master;
+
+--echo # UPDATE triggers test
+update t1 set C1= 'd';
+
+sync_slave_with_master;
+
+connection slave;
+SELECT * FROM t2 order by id;
+
+connection master;
+--echo # DELETE triggers test
+delete from t1 where C1='d';
+
+sync_slave_with_master;
+
+connection slave;
+SELECT * FROM t2 order by id;
+
+--echo # INSERT triggers which cause also UPDATE test (insert duplicate row)
+insert into t1 values ('0','1');
+
+SELECT * FROM t2 order by id;
+
+connection master;
+
+insert into t1 values ('0','1');
+
+sync_slave_with_master;
+
+connection slave;
+SELECT * FROM t2 order by id;
+
+
+--echo # INSERT triggers which cause also DELETE test
+--echo # (insert duplicate row in table referenced by foreign key)
+insert into t1 values ('1','1');
+
+connection master;
+
+CREATE TABLE t3 (C1 CHAR(1) primary key, FOREIGN KEY (C1) REFERENCES t1(C1) ) engine=innodb;
+
+insert into t1 values ('1','1');
+
+sync_slave_with_master;
+
+connection slave;
+SELECT * FROM t2 order by id;
+
+connection master;
+
+drop table t3,t1;
+
+sync_slave_with_master;
+
+connection slave;
+SET @@global.slave_exec_mode= @old_slave_exec_mode;
+SET @@global.slave_run_triggers_for_rbr= @old_slave_run_triggers_for_rbr;
+drop table t2;
+
+--echo #
+--echo # enterprise 10.4 tests end
+--echo #
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_row_trunc_temp.test b/mysql-test/suite/rpl/t/rpl_row_trunc_temp.test
new file mode 100644
index 00000000..a8d7f77d
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_row_trunc_temp.test
@@ -0,0 +1,35 @@
+#
+# Bug#48350 truncate temporary table crashes replication
+#
+# All statements operating on temporary tables should not be binlogged in RBR.
+# However, before fix of bug#48350, 'TRUNCATE ...' statement on a temporary
+# table was binlogged in RBR.
+#
+
+--source include/have_binlog_format_row.inc
+--source include/master-slave.inc
+
+#This statement is not binlogged in RBR.
+CREATE TEMPORARY TABLE t1(c1 INTEGER);
+CREATE TABLE t2(c1 INTEGER);
+sync_slave_with_master;
+
+CREATE TABLE t1(c1 INTEGER);
+INSERT INTO t1 VALUES(1), (2);
+INSERT INTO t2 VALUES(1), (2);
+SELECT * FROM t1;
+SELECT * FROM t2;
+
+connection master;
+TRUNCATE t1;
+TRUNCATE t2;
+sync_slave_with_master;
+# t1 will have nothing, if 'TRUNCATE t1' has been replicate from master to
+# slave.
+SELECT * FROM t1;
+SELECT * FROM t2;
+
+DROP TABLE t1;
+connection master;
+DROP TABLE t2;
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_row_type_conv_err_msg.test b/mysql-test/suite/rpl/t/rpl_row_type_conv_err_msg.test
new file mode 100644
index 00000000..2442f869
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_row_type_conv_err_msg.test
@@ -0,0 +1,356 @@
+# ==== Purpose ====
+#
+# Test verifies that when slave side type conversion fails in row based
+# replication, more informative error message is displayed. It also verifies
+# that in the case of blob fields appropriate type name is displayed in error
+# message.
+#
+# ==== Implementation ====
+#
+# Steps:
+# Test case1:
+# 1. Create a table on master with VARCHAR filed and charset
+# 'utf8mb3'.
+# 2. Create a table on slave with VARCHAR field and charset
+# 'utf8mb4'.
+# 3. Insert a tuple on master.
+# 4. Verify that slave provides more informative error message with
+# respect to difference in charsets.
+# Test case2: Repeat same steps as above for CHAR field
+# Test case3:
+# 1. Create a table on master with LONGBLOB field.
+# 2. Create a table on slave with TINYBLOB field.
+# 3. Insert a tuple on master.
+# 4. Verify that error message displayed on slave clearly states type
+# conversion failure from 'longblob' to 'tinyblob'.
+# 5. Also verify that error message doesn't show additional details
+# of charset when not required.
+# Test Case4: Verifies varbinary to binary type conversion failure specific
+# error message.
+# Test Case5: Verifies binary to varbinary type conversion failure specific
+# error message.
+# Test Case6: Verifies binary to binary type conversion failure specific
+# error message.
+# Test Case7: Verifies char to blob type conversion failure specific
+# error message.
+# Test Case8: Verifies char to text type conversion failure specific
+# error message.
+# ==== References ====
+#
+# MDEV-19925: Column ... cannot be converted from type 'varchar(20)' to type
+# 'varchar(20)'
+#
+
+--source include/have_binlog_format_row.inc
+# Inorder to grep a specific error pattern in error log a fresh error log
+# needs to be generated.
+--source include/force_restart.inc
+--source include/master-slave.inc
+
+--echo ####################################################################
+--echo # Test Case1: Improved error message with charset information
+--echo ####################################################################
+--connection master
+SET SQL_LOG_BIN=0;
+CREATE TABLE t1 (c1 VARCHAR(1) CHARACTER SET 'utf8mb3');
+SET SQL_LOG_BIN=1;
+
+--connection slave
+CREATE TABLE t1 (c1 VARCHAR(1) CHARACTER SET 'utf8mb4');
+
+--connection master
+INSERT INTO t1 VALUES ('a');
+
+--connection slave
+--let $slave_sql_errno= 1677
+--source include/wait_for_slave_sql_error.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.2.err;
+}
+
+# Error msg before: Column 0 of table 'test.t1' cannot be converted from type 'varchar(3)' to type 'varchar(1)'
+# Error msg after : Column 0 of table 'test.t1' cannot be converted from type 'varchar(3 octets)' to type 'varchar(4 octets) character set utf8mb4'
+--let SEARCH_FILE=$log_error_
+--let SEARCH_PATTERN=\'varchar\(3 octets\)\' to type \'varchar\(4 octets\) character set utf8mb4\'
+--source include/search_pattern_in_file.inc
+
+--connection master
+DROP TABLE t1;
+--connection slave
+DROP TABLE t1;
+--let $rpl_only_running_threads= 1
+--source include/rpl_reset.inc
+
+--echo ####################################################################
+--echo # Test Case2: Improved error message with charset information for CHAR
+--echo # type
+--echo ####################################################################
+--connection master
+SET SQL_LOG_BIN=0;
+CREATE TABLE t1 (c1 CHAR(1) CHARACTER SET 'utf8mb3');
+SET SQL_LOG_BIN=1;
+
+--connection slave
+CREATE TABLE t1 (c1 CHAR(1) CHARACTER SET 'utf8mb4');
+
+--connection master
+INSERT INTO t1 VALUES ('a');
+
+--connection slave
+--let $slave_sql_errno= 1677
+--source include/wait_for_slave_sql_error.inc
+
+# Error msg before: Column 0 of table 'test.t1' cannot be converted from type 'char(0)' to type 'char(1)'
+# Error msg after : Column 0 of table 'test.t1' cannot be converted from type 'char(3 octets)' to type 'char(4 octets) character set utf8mb4)'
+--let SEARCH_FILE=$log_error_
+--let SEARCH_PATTERN=\'char\(3 octets\)\' to type \'char\(4 octets\) character set utf8mb4\'
+--source include/search_pattern_in_file.inc
+
+--connection master
+DROP TABLE t1;
+--connection slave
+DROP TABLE t1;
+--let $rpl_only_running_threads= 1
+--source include/rpl_reset.inc
+
+--echo ####################################################################
+--echo # Test Case3: For BLOB type fileds, when type conversion failed on
+--echo # slave, the errormessage had incorrect type names.
+--echo ####################################################################
+--connection master
+SET SQL_LOG_BIN=0;
+CREATE TABLE t1 (c1 LONGBLOB);
+SET SQL_LOG_BIN=1;
+
+--connection slave
+CREATE TABLE t1 (c1 TINYBLOB);
+
+--connection master
+INSERT INTO t1 VALUES ('a');
+
+--connection slave
+--let $slave_sql_errno= 1677
+--source include/wait_for_slave_sql_error.inc
+
+# Error msg before: Column 0 of table 'test.t1' cannot be converted from type 'tinyblob' to type 'tinyblob'
+# Error msg after : Column 0 of table 'test.t1' cannot be converted from type 'longblob' to type 'tinyblob'
+--let SEARCH_FILE=$log_error_
+--let SEARCH_PATTERN=\'longblob\' to type \'tinyblob\'
+--source include/search_pattern_in_file.inc
+
+--connection master
+DROP TABLE t1;
+--connection slave
+DROP TABLE t1;
+--let $rpl_only_running_threads= 1
+--source include/rpl_reset.inc
+
+--echo ####################################################################
+--echo # Test Case4: Verifies varbinary to binary type conversion failure
+--echo # specific error message.
+--echo ####################################################################
+--connection master
+SET SQL_LOG_BIN=0;
+CREATE TABLE t1 (c1 VARBINARY(10));
+SET SQL_LOG_BIN=1;
+
+--connection slave
+CREATE TABLE t1 (c1 BINARY(10));
+
+--connection master
+INSERT INTO t1 VALUES ('a');
+
+--connection slave
+--let $slave_sql_errno= 1677
+--source include/wait_for_slave_sql_error.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.2.err;
+}
+
+# Expected Error : Column 0 of table 'test.t1' cannot be converted from type 'varbinary(10)' to type 'binary(10)'
+--let SEARCH_FILE=$log_error_
+--let SEARCH_PATTERN=\'varbinary\(10\)\' to type \'binary\(10\)\'
+--source include/search_pattern_in_file.inc
+
+--connection master
+DROP TABLE t1;
+--connection slave
+DROP TABLE t1;
+--let $rpl_only_running_threads= 1
+--source include/rpl_reset.inc
+
+--echo ####################################################################
+--echo # Test Case5: Verifies binary to varbinary type conversion failure
+--echo # specific error message.
+--echo ####################################################################
+--connection master
+SET SQL_LOG_BIN=0;
+CREATE TABLE t1 (c1 BINARY(10));
+SET SQL_LOG_BIN=1;
+
+--connection slave
+CREATE TABLE t1 (c1 VARBINARY(10));
+
+--connection master
+INSERT INTO t1 VALUES ('a');
+
+--connection slave
+--let $slave_sql_errno= 1677
+--source include/wait_for_slave_sql_error.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.2.err;
+}
+
+# Expected Error : Column 0 of table 'test.t1' cannot be converted from type 'binary(10)' to type 'varbinary(10)'
+--let SEARCH_FILE=$log_error_
+--let SEARCH_PATTERN=\'binary\(10\)\' to type \'varbinary\(10\)\'
+--source include/search_pattern_in_file.inc
+
+--connection master
+DROP TABLE t1;
+--connection slave
+DROP TABLE t1;
+--let $rpl_only_running_threads= 1
+--source include/rpl_reset.inc
+
+--echo ####################################################################
+--echo # Test Case6: Verifies binary to binary type conversion failure
+--echo # specific error message.
+--echo ####################################################################
+--connection master
+SET SQL_LOG_BIN=0;
+CREATE TABLE t1 (c1 BINARY(1));
+SET SQL_LOG_BIN=1;
+
+--connection slave
+CREATE TABLE t1 (c1 BINARY(10));
+
+--connection master
+INSERT INTO t1 VALUES ('a');
+
+--connection slave
+--let $slave_sql_errno= 1677
+--source include/wait_for_slave_sql_error.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.2.err;
+}
+
+# Expected Error : Column 0 of table 'test.t1' cannot be converted from type 'binary(1)' to type 'binary(10)'
+--let SEARCH_FILE=$log_error_
+--let SEARCH_PATTERN=\'binary\(1\)\' to type \'binary\(10\)\'
+--source include/search_pattern_in_file.inc
+
+--connection master
+DROP TABLE t1;
+--connection slave
+DROP TABLE t1;
+--let $rpl_only_running_threads= 1
+--source include/rpl_reset.inc
+
+--echo ####################################################################
+--echo # Test Case7: Verifies char to blob type conversion failure
+--echo # specific error message. BLOB field on slave has no
+--echo # associated character set hence the master side field
+--echo # is also considered as binary.
+--echo ####################################################################
+--connection master
+SET SQL_LOG_BIN=0;
+CREATE TABLE t1 (c1 CHAR(1));
+SET SQL_LOG_BIN=1;
+
+--connection slave
+CREATE TABLE t1 (c1 BLOB);
+
+--connection master
+INSERT INTO t1 VALUES ('a');
+
+--connection slave
+--let $slave_sql_errno= 1677
+--source include/wait_for_slave_sql_error.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.2.err;
+}
+
+# Expected Error : Column 0 of table 'test.t1' cannot be converted from type 'binary(1)' to type 'binary(10)'
+--let SEARCH_FILE=$log_error_
+--let SEARCH_PATTERN=\'binary\(1\)\' to type \'blob\'
+--source include/search_pattern_in_file.inc
+
+--connection master
+DROP TABLE t1;
+--connection slave
+DROP TABLE t1;
+--let $rpl_only_running_threads= 1
+--source include/rpl_reset.inc
+
+--echo ####################################################################
+--echo # Test Case8: Verifies char to text type conversion failure
+--echo # specific error message.
+--echo ####################################################################
+--connection master
+SET SQL_LOG_BIN=0;
+CREATE TABLE t1 (c1 CHAR(1));
+SET SQL_LOG_BIN=1;
+
+--connection slave
+CREATE TABLE t1 (c1 TEXT);
+
+--connection master
+INSERT INTO t1 VALUES ('a');
+
+--connection slave
+--let $slave_sql_errno= 1677
+--source include/wait_for_slave_sql_error.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.2.err;
+}
+
+# Expected Error : Column 0 of table 'test.t1' cannot be converted from type 'binary(1)' to type 'binary(10)'
+--let SEARCH_FILE=$log_error_
+--let SEARCH_PATTERN=\'char\(1 octets\)\' to type \'text\'
+--source include/search_pattern_in_file.inc
+
+--connection master
+DROP TABLE t1;
+--connection slave
+DROP TABLE t1;
+--let $rpl_only_running_threads= 1
+--source include/rpl_reset.inc
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_row_unsafe_funcs.test b/mysql-test/suite/rpl/t/rpl_row_unsafe_funcs.test
new file mode 100644
index 00000000..31eea3a2
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_row_unsafe_funcs.test
@@ -0,0 +1,36 @@
+source include/have_binlog_format_mixed.inc;
+source include/master-slave.inc;
+
+#
+# Bug #30244: row_count/found_rows does not replicate well
+#
+
+connection master;
+
+CREATE TABLE t1 (a INT);
+CREATE TABLE t2 (a INT, b INT);
+
+INSERT INTO t1 SELECT 1;
+
+connection master1;
+INSERT INTO t1 VALUES (2),(3),(4),(5),(6);
+
+connection master;
+INSERT INTO t2 SELECT 1, ROW_COUNT();
+
+INSERT INTO t1 VALUES (2),(3),(4);
+INSERT INTO t2 SELECT 2, ROW_COUNT();
+
+#must return 1 and 3
+SELECT b FROM t2 ORDER BY a;
+
+sync_slave_with_master;
+
+#must return 1 and 3
+SELECT b FROM t2 ORDER BY a;
+
+connection master;
+DROP TABLE t1, t2;
+sync_slave_with_master;
+connection master;
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_row_until.test b/mysql-test/suite/rpl/t/rpl_row_until.test
new file mode 100644
index 00000000..d318e0d7
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_row_until.test
@@ -0,0 +1,150 @@
+-- source include/have_binlog_format_row.inc
+-- source include/master-slave.inc
+
+##############################################################################
+# The test is dependent on binlog positions. The test is divided into two
+# sections. The first section checks START SLAVE UNTIL MASTER_LOG_FILE =
+# 'log_name', MASTER_LOG_POS = log_pos followed by a couple of failure
+# scenarios. The second section checks START SLAVE UNTIL RELAY_LOG_FILE =
+# 'log_name', RELAY_LOG_POS = log_pos.
+##############################################################################
+
+# Create some events on master
+connection master;
+CREATE TABLE t1(n INT NOT NULL AUTO_INCREMENT PRIMARY KEY);
+INSERT INTO t1 VALUES (1),(2),(3),(4);
+# Save master log position for query DROP TABLE t1
+let $master_pos_drop_t1= query_get_value(SHOW MASTER STATUS, Position, 1);
+DROP TABLE t1;
+# Save master log position for query DROP TABLE t1
+save_master_pos;
+#let $master_pos_drop_t1= query_get_value(SHOW BINLOG EVENTS, Pos, 10);
+let $master_log_file= query_get_value(SHOW BINLOG EVENTS, Log_name, 10);
+
+# Save master log position for query CREATE TABLE t2
+let $master_pos_create_t2= query_get_value(SHOW MASTER STATUS, Position, 1);
+CREATE TABLE t2(n INT NOT NULL AUTO_INCREMENT PRIMARY KEY);
+#show binlog events;
+
+INSERT INTO t2 VALUES (1),(2);
+# Save master log position for query INSERT INTO t2 VALUES (1),(2);
+let $master_pos_insert1_t2= query_get_value(SHOW MASTER STATUS, Position, 1);
+INSERT INTO t2 VALUES (3),(4);
+DROP TABLE t2;
+# Save master log position for query DROP TABLE t2;
+let $master_pos_drop_t2= query_get_value(SHOW MASTER STATUS, Position, 1);
+sync_slave_with_master;
+#show binlog events;
+
+--source include/stop_slave.inc
+# Reset slave.
+--source include/reset_slave.inc
+--replace_result $MASTER_MYPORT MASTER_MYPORT
+eval CHANGE MASTER TO MASTER_USER='root', MASTER_CONNECT_RETRY=1, MASTER_HOST='127.0.0.1', MASTER_PORT=$MASTER_MYPORT;
+
+# Try to replicate all queries until drop of t1
+
+connection slave;
+--replace_result $master_pos_drop_t1 master_pos_drop_t1
+eval START SLAVE UNTIL MASTER_LOG_FILE='$master_log_file', MASTER_LOG_POS=$master_pos_drop_t1;
+--source include/wait_for_slave_sql_to_stop.inc
+
+# Here table should be still not deleted
+SELECT * FROM t1;
+--let $slave_param= Exec_Master_Log_Pos
+--let $slave_param_value= $master_pos_drop_t1
+--source include/check_slave_param.inc
+
+# This should fail right after start
+START SLAVE UNTIL MASTER_LOG_FILE='master-no-such-bin.000001', MASTER_LOG_POS=291;
+--source include/wait_for_slave_sql_to_stop.inc
+# again this table should be still not deleted
+SELECT * FROM t1;
+
+--let $slave_param= Exec_Master_Log_Pos
+--let $slave_param_value= $master_pos_drop_t1
+--source include/check_slave_param.inc
+
+# clean up
+START SLAVE;
+--source include/wait_for_slave_to_start.inc
+connection master;
+sync_slave_with_master;
+--source include/stop_slave.inc
+
+# This should stop immediately as we are already there
+--replace_result $master_pos_create_t2 master_pos_create_t2
+eval START SLAVE SQL_THREAD UNTIL MASTER_LOG_FILE='$master_log_file', MASTER_LOG_POS=$master_pos_create_t2;
+let $slave_param= Until_Log_Pos;
+let $slave_param_value= $master_pos_create_t2;
+--source include/wait_for_slave_param.inc
+--source include/wait_for_slave_sql_to_stop.inc
+# here the sql slave thread should be stopped
+--let $slave_param= Exec_Master_Log_Pos
+--let $slave_param_value= $master_pos_drop_t2
+--source include/check_slave_param.inc
+
+#testing various error conditions
+--replace_result 561 MASTER_LOG_POS
+--error 1277
+START SLAVE UNTIL MASTER_LOG_FILE='master-bin', MASTER_LOG_POS=561;
+--replace_result 561 MASTER_LOG_POS 12 RELAY_LOG_POS
+--error 1277
+START SLAVE UNTIL MASTER_LOG_FILE='master-bin.000001', MASTER_LOG_POS=561, RELAY_LOG_POS=12;
+--error 1277
+START SLAVE UNTIL MASTER_LOG_FILE='master-bin.000001';
+--error 1277
+START SLAVE UNTIL RELAY_LOG_FILE='slave-relay-bin.000009';
+--replace_result 561 MASTER_LOG_POS
+--error 1277
+START SLAVE UNTIL RELAY_LOG_FILE='slave-relay-bin.000002', MASTER_LOG_POS=561;
+--replace_result 740 MASTER_LOG_POS
+START SLAVE UNTIL MASTER_LOG_FILE='master-bin.000001', MASTER_LOG_POS=740;
+
+--source include/stop_slave.inc
+--source include/reset_slave.inc
+--source include/start_slave.inc
+
+##############################################################################
+# The second section - checks START SLAVE UNTIL RELAY_LOG_FILE =# 'log_name',
+# RELAY_LOG_POS = log_pos. This section of the test does the following:
+# 1) At master, create a table and inserts a value. Let slave replicate this.
+# 2) Stop slave sql thread.
+# 3) Insert some more values at master. Note that io thread copies this insert
+# 4) Use start slave until to start the sql thread and check if it
+# stops at the correct position.
+##############################################################################
+
+--source include/rpl_reset.inc
+
+--connection master
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (1);
+
+--sync_slave_with_master
+--source include/stop_slave_sql.inc
+
+--connection master
+INSERT INTO t1 VALUES (2);
+--let $master_log_pos= query_get_value(SHOW MASTER STATUS, Position, 1)
+INSERT INTO t1 VALUES (3);
+
+--source include/sync_slave_io_with_master.inc
+
+--let $relay_log_file= query_get_value(SHOW SLAVE STATUS, Relay_Log_File,1)
+--source include/get_relay_log_pos.inc
+
+--replace_result $relay_log_pos relay_log_pos
+--eval start slave until relay_log_file='$relay_log_file', relay_log_pos=$relay_log_pos
+--source include/wait_for_slave_sql_to_stop.inc
+
+--let $assert_cond= COUNT(*) = 2 FROM t1
+--let $assert_text= table t1 should have two rows.
+--source include/assert.inc
+
+#cleanup
+--source include/start_slave.inc
+--connection master
+DROP TABLE t1;
+--sync_slave_with_master
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_row_utf16.test b/mysql-test/suite/rpl/t/rpl_row_utf16.test
new file mode 100644
index 00000000..d5dcdc42
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_row_utf16.test
@@ -0,0 +1,26 @@
+-- source include/have_binlog_format_row.inc
+-- source include/have_utf16.inc
+-- source include/master-slave.inc
+
+#
+# BUG#51716: Char column with utf16 character set gives wrong padding on slave
+#
+
+CREATE TABLE t1(c1 CHAR(10) CHARACTER SET utf16 DEFAULT 'ola');
+INSERT INTO t1 VALUES ('abc'); # explicit value is inserted and encoded correctly
+INSERT INTO t1 VALUES (); # default value is inserted and encoded correctly
+
+--query_vertical SELECT c1, hex(c1) from t1
+
+-- sync_slave_with_master
+
+--query_vertical SELECT c1, hex(c1) FROM t1
+
+# assertion: tables don't differ
+-- let $diff_tables=master:t1,slave:t1
+-- source include/diff_tables.inc
+
+--connection master
+DROP TABLE t1;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_row_utf32.test b/mysql-test/suite/rpl/t/rpl_row_utf32.test
new file mode 100644
index 00000000..546cf07a
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_row_utf32.test
@@ -0,0 +1,113 @@
+-- source include/have_binlog_format_row.inc
+-- source include/have_utf32.inc
+-- source include/master-slave.inc
+
+#
+# BUG#51787 Assertion `(n % 4) == 0' on slave upon INSERT into a table with UTF32
+#
+
+SET SQL_LOG_BIN=0;
+CREATE TABLE t1 (c1 char(255) DEFAULT NULL, KEY c1 (c1)) DEFAULT CHARSET=utf32;
+SET SQL_LOG_BIN=1;
+
+-- connection slave
+
+SET @saved_slave_type_conversions= @@global.slave_type_conversions;
+
+#
+# Force test to cover conversion execution path in the
+# slave, which also makes use of sql_type method, thence
+# can ultimately trigger the assertion.
+#
+-- source include/stop_slave.inc
+SET GLOBAL SLAVE_TYPE_CONVERSIONS='ALL_NON_LOSSY';
+-- source include/start_slave.inc
+
+SET SQL_LOG_BIN=0;
+CREATE TABLE t1 ( c1 varchar(255) DEFAULT NULL, KEY c1 (c1)) DEFAULT CHARSET=utf32;
+SET SQL_LOG_BIN=1;
+
+-- connection master
+
+INSERT INTO t1(c1) VALUES ('insert into t1');
+DROP TABLE t1;
+
+--sync_slave_with_master
+
+--echo #
+--echo # MDEV-32249 strings/ctype-ucs2.c:2336: my_vsnprintf_utf32: Assertion `(n
+--echo #
+
+--echo #
+--echo # Testing with VARCHAR
+--echo #
+
+-- connection slave
+-- source include/stop_slave.inc
+SET GLOBAL SLAVE_TYPE_CONVERSIONS= '';
+-- source include/start_slave.inc
+
+--connection master
+CREATE TABLE t1 (a INT);
+
+--sync_slave_with_master
+ALTER TABLE t1 MODIFY a VARCHAR(1) CHARACTER SET utf32;
+
+--connection master
+INSERT INTO t1 VALUES (1);
+
+--connection slave
+# ER_SLAVE_CONVERSION_FAILED
+--let $slave_sql_errno= 1677
+--source include/wait_for_slave_sql_error.inc
+SHOW CREATE TABLE t1;
+SELECT * FROM t1 ORDER BY a;
+SET GLOBAL SQL_SLAVE_SKIP_COUNTER = 1;
+START SLAVE;
+
+--connection master
+DROP TABLE t1;
+--sync_slave_with_master
+
+--echo #
+--echo # Testing with CHAR
+--echo #
+
+-- connection slave
+-- source include/stop_slave.inc
+SET GLOBAL SLAVE_TYPE_CONVERSIONS= '';
+-- source include/start_slave.inc
+
+--connection master
+CREATE TABLE t1 (a INT);
+
+--sync_slave_with_master
+ALTER TABLE t1 MODIFY a CHAR(1) CHARACTER SET utf32;
+
+--connection master
+INSERT INTO t1 VALUES (1);
+
+--connection slave
+# ER_SLAVE_CONVERSION_FAILED
+--let $slave_sql_errno= 1677
+--source include/wait_for_slave_sql_error.inc
+SHOW CREATE TABLE t1;
+SELECT * FROM t1 ORDER BY a;
+SET GLOBAL SQL_SLAVE_SKIP_COUNTER = 1;
+START SLAVE;
+
+--connection master
+DROP TABLE t1;
+--sync_slave_with_master
+
+
+# assertion: the slave woul hit an/several assertions:
+# before and during slave conversion procedure
+# Now that is fixed, it wont.
+
+-- connection slave
+SET GLOBAL SLAVE_TYPE_CONVERSIONS= @saved_slave_type_conversions;
+-- source include/stop_slave.inc
+-- source include/start_slave.inc
+-- connection master
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_row_vcol_crash.test b/mysql-test/suite/rpl/t/rpl_row_vcol_crash.test
new file mode 100644
index 00000000..84ee1497
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_row_vcol_crash.test
@@ -0,0 +1,425 @@
+# ==== Purpose ====
+#
+# Test verifies that, slave doesn't report any assert on UPDATE or DELETE of
+# row which tries to update the virtual columns with associated KEYs.
+#
+# Test scenarios are listed below.
+# 1) KEY on a virtual column with ON DELETE CASCADE
+# 2) Verify "ON DELETE CASCADE" for parent->child->child scenario
+# 3) KEY on a virtual column with ON UPDATE CASCADE
+# 4) Define triggers on master, their results should be replicated
+# as part of row events and they should be applied on slave with
+# the default slave_run_triggers_for_rbr=NO
+# 5) Define triggers + Foreign Keys on master, their results should be
+# replicated as part of row events and master and slave should be in sync.
+# 6) Triggers are present only on slave and 'slave_run_triggers_for_rbr=NO'
+# 7) Triggers are present only on slave and 'slave_run_triggers_for_rbr=YES'
+# 8) Triggers and Foreign Keys are present only on slave and
+# 'slave_run_triggers_for_rbr=NO'
+# 9) Triggers are Foreign Keys are present only on slave and
+# 'slave_run_triggers_for_rbr=YES'
+#
+# ==== References ====
+#
+# MDEV-23033: All slaves crash once in ~24 hours and loop restart with signal 11
+#
+
+--source include/have_binlog_format_row.inc
+--source include/have_innodb.inc
+--source include/master-slave.inc
+
+
+--echo #
+--echo # Test case 1: KEY on a virtual column with ON DELETE CASCADE
+--echo #
+CREATE TABLE t1 (id INT NOT NULL PRIMARY KEY) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1),(2),(3);
+
+CREATE TABLE t2 (id INT NOT NULL PRIMARY KEY,
+ t1_id INT NOT NULL,
+ v_col INT AS (t1_id+1) VIRTUAL, KEY (v_col), KEY (t1_id),
+ CONSTRAINT a FOREIGN KEY (t1_id) REFERENCES t1 (id) ON DELETE CASCADE
+) ENGINE=InnoDB;
+
+INSERT INTO t2 VALUES (90,1,NULL);
+INSERT INTO t2 VALUES (91,2,default);
+
+# Following query results in an assert on slave
+DELETE FROM t1 WHERE id=1;
+--sync_slave_with_master
+
+--echo #
+--echo # Verify data consistency on slave
+--echo #
+--let $diff_tables= master:test.t1, slave:test.t1
+--source include/diff_tables.inc
+--let $diff_tables= master:test.t2, slave:test.t2
+--source include/diff_tables.inc
+
+--connection master
+DROP TABLE t2,t1;
+--sync_slave_with_master
+
+--echo #
+--echo # Test case 2: Verify "ON DELETE CASCADE" for parent->child->child scenario
+--echo # Parent table: users
+--echo # Child tables: matchmaking_groups, matchmaking_group_users
+--echo # Parent table: matchmaking_groups
+--echo # Child tables: matchmaking_group_users, matchmaking_group_maps
+--echo #
+--echo # Deleting a row from parent table should be reflected in
+--echo # child tables.
+--echo # matchmaking_groups->matchmaking_group_users->matchmaking_group_maps
+--echo # users->matchmaking_group_users->matchmaking_group_maps
+--echo #
+
+--connection master
+CREATE TABLE users (id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
+ name VARCHAR(32) NOT NULL DEFAULT ''
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+CREATE TABLE matchmaking_groups (
+ id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
+ host_user_id INT UNSIGNED NOT NULL UNIQUE,
+ v_col INT AS (host_user_id+1) VIRTUAL, KEY (v_col),
+ CONSTRAINT FOREIGN KEY (host_user_id) REFERENCES users (id)
+ ON DELETE CASCADE ON UPDATE CASCADE
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+CREATE TABLE matchmaking_group_users (
+ matchmaking_group_id BIGINT UNSIGNED NOT NULL,
+ user_id INT UNSIGNED NOT NULL,
+ v_col1 int as (user_id+1) virtual, KEY (v_col1),
+ PRIMARY KEY (matchmaking_group_id,user_id),
+ UNIQUE KEY user_id (user_id),
+ CONSTRAINT FOREIGN KEY (matchmaking_group_id)
+ REFERENCES matchmaking_groups (id) ON DELETE CASCADE ON UPDATE CASCADE,
+ CONSTRAINT FOREIGN KEY (user_id)
+ REFERENCES users (id) ON DELETE CASCADE ON UPDATE CASCADE
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+CREATE TABLE matchmaking_group_maps (
+ matchmaking_group_id BIGINT UNSIGNED NOT NULL,
+ map_id TINYINT UNSIGNED NOT NULL,
+ v_col2 INT AS (map_id+1) VIRTUAL, KEY (v_col2),
+ PRIMARY KEY (matchmaking_group_id,map_id),
+ CONSTRAINT FOREIGN KEY (matchmaking_group_id)
+ REFERENCES matchmaking_groups (id) ON DELETE CASCADE ON UPDATE CASCADE
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+--sync_slave_with_master
+
+--connection master
+INSERT INTO users VALUES (NULL,'foo'),(NULL,'bar');
+INSERT INTO matchmaking_groups VALUES (10,1,default),(11,2,default);
+INSERT INTO matchmaking_group_users VALUES (10,1,default),(11,2,default);
+INSERT INTO matchmaking_group_maps VALUES (10,55,default),(11,66,default);
+
+DELETE FROM matchmaking_groups WHERE id = 10;
+--sync_slave_with_master
+
+--echo #
+--echo # No rows should be returned as ON DELETE CASCASE should have removed
+--echo # corresponding rows from child tables. There should not any mismatch
+--echo # of 'id' field between parent->child.
+--echo #
+SELECT * FROM matchmaking_group_users WHERE matchmaking_group_id NOT IN (SELECT id FROM matchmaking_groups);
+SELECT * FROM matchmaking_group_maps WHERE matchmaking_group_id NOT IN (SELECT id FROM matchmaking_groups);
+
+--echo #
+--echo # Rows with id=11 should be present
+--echo #
+SELECT * FROM matchmaking_group_users;
+SELECT * FROM matchmaking_group_maps;
+
+--connection master
+DELETE FROM users WHERE id = 2;
+--sync_slave_with_master
+
+--echo #
+--echo # No rows should be present in both the child tables
+--echo #
+SELECT * FROM matchmaking_group_users;
+SELECT * FROM matchmaking_group_maps;
+
+--connection master
+DROP TABLE matchmaking_group_maps, matchmaking_group_users, matchmaking_groups, users;
+--sync_slave_with_master
+
+--echo #
+--echo # Test case 3: KEY on a virtual column with ON UPDATE CASCADE
+--echo #
+
+--connection master
+CREATE TABLE t1 (a INT NOT NULL PRIMARY KEY, b INT NOT NULL) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1, 80);
+
+CREATE TABLE t2 (a INT KEY, b INT,
+ v_col int as (b+1) virtual, KEY (v_col),
+ CONSTRAINT b FOREIGN KEY (b) REFERENCES t1(a) ON UPDATE CASCADE
+) ENGINE=InnoDB;
+INSERT INTO t2 VALUES (51, 1, default);
+--sync_slave_with_master
+
+--connection master
+UPDATE t1 SET a = 50 WHERE a = 1;
+
+--echo #
+--echo # Master: Verify that ON UPDATE CASCADE works fine
+--echo # old_row: (51, 1, 2) ON UPDATE New_row: (51, 50, 51)
+--echo #
+SELECT * FROM t2 WHERE b=50;
+--sync_slave_with_master
+
+--echo #
+--echo # Slave: Verify that ON UPDATE CASCADE works fine
+--echo # old_row: (51, 1, 2) ON UPDATE New_row: (51, 50, 51)
+--echo #
+SELECT * FROM t2 WHERE b=50;
+
+--connection master
+DROP TABLE t2, t1;
+--sync_slave_with_master
+
+--echo #
+--echo # Test case 4: Define triggers on master, their results should be
+--echo # replicated as part of row events and they should be
+--echo # applied on slave with the default
+--echo # slave_run_triggers_for_rbr=NO
+--echo #
+
+# In row-based replication, the binary log contains row changes. It will have
+# both the changes made by the statement itself, and the changes made by the
+# triggers that were invoked by the statement. Slave server(s) do not need to
+# run triggers for row changes they are applying. Hence verify that this
+# property remains the same and data should be available as if trigger was
+# executed. Please note by default slave_run_triggers_for_rbr=NO.
+
+--connection master
+CREATE TABLE t1 (id INT NOT NULL PRIMARY KEY) ENGINE=InnoDB;
+CREATE TABLE t2 (count INT NOT NULL) ENGINE=InnoDB;
+CREATE TRIGGER trg AFTER INSERT ON t1 FOR EACH ROW INSERT INTO t2 VALUES (1);
+INSERT INTO t1 VALUES (2),(3);
+--sync_slave_with_master
+
+SHOW GLOBAL VARIABLES LIKE 'slave_run_triggers_for_rbr';
+--echo #
+--echo # As two rows are inserted in table 't1', two rows should get inserted
+--echo # into table 't2' as part of trigger.
+--echo #
+--let $assert_cond= COUNT(*) = 2 FROM t2
+--let $assert_text= Table t2 should have two rows.
+--source include/assert.inc
+
+--connection master
+DROP TABLE t1,t2;
+--sync_slave_with_master
+
+--echo #
+--echo # Test case 5: Define triggers + Foreign Keys on master, their results
+--echo # should be replicated as part of row events and master
+--echo # and slave should be in sync.
+--echo #
+--connection master
+CREATE TABLE t1 (id INT NOT NULL PRIMARY KEY) ENGINE=InnoDB;
+CREATE TABLE t2 (t1_id INT NOT NULL,
+ v_col INT AS (t1_id+1) VIRTUAL, KEY (v_col), KEY (t1_id),
+ CONSTRAINT a FOREIGN KEY (t1_id) REFERENCES t1 (id) ON DELETE CASCADE
+) ENGINE=InnoDB;
+CREATE TABLE t3 (count INT NOT NULL) ENGINE=InnoDB;
+CREATE TRIGGER trg AFTER INSERT ON t1 FOR EACH ROW INSERT INTO t3 VALUES (1);
+
+INSERT INTO t1 VALUES (2),(3);
+INSERT INTO t2 VALUES (2, default), (3, default);
+--sync_slave_with_master
+
+--echo #
+--echo # As two rows are inserted in table 't1', two rows should get inserted
+--echo # into table 't3' as part of trigger.
+--echo #
+--let $assert_cond= COUNT(*) = 2 FROM t3
+--let $assert_text= Table t3 should have two rows.
+--source include/assert.inc
+
+--echo #
+--echo # Verify ON DELETE CASCASE correctness
+--echo #
+--connection master
+DELETE FROM t1 WHERE id=2;
+--sync_slave_with_master
+
+--connection master
+--let $diff_tables= master:test.t1, slave:test.t1
+--source include/diff_tables.inc
+--let $diff_tables= master:test.t2, slave:test.t2
+--source include/diff_tables.inc
+--let $diff_tables= master:test.t3, slave:test.t3
+--source include/diff_tables.inc
+
+DROP TABLE t3,t2,t1;
+--sync_slave_with_master
+
+#
+# Test case: Triggers only on slave
+#
+--write_file $MYSQLTEST_VARDIR/tmp/trig_on_slave.inc PROCEDURE
+ if ($slave_run_triggers_for_rbr == '') {
+ --die !!!ERROR IN TEST: you must set $slave_run_triggers_for_rbr
+ }
+
+--connection slave
+SET @save_slave_run_triggers_for_rbr= @@GLOBAL.slave_run_triggers_for_rbr;
+--eval SET GLOBAL slave_run_triggers_for_rbr= $slave_run_triggers_for_rbr;
+SHOW GLOBAL VARIABLES LIKE '%slave_run_triggers_for_rbr%';
+
+--connection master
+CREATE TABLE t1 (id INT NOT NULL PRIMARY KEY) ENGINE=InnoDB;
+CREATE TABLE t2 (t1_id INT NOT NULL,
+ v_col INT AS (t1_id+1) VIRTUAL, KEY (v_col),
+ KEY (t1_id), CONSTRAINT a FOREIGN KEY (t1_id) REFERENCES t1 (id) ON DELETE CASCADE
+) ENGINE=InnoDB;
+CREATE TABLE t3 (count INT NOT NULL) ENGINE=InnoDB;
+--sync_slave_with_master
+
+CREATE TRIGGER trg AFTER INSERT ON t2 FOR EACH ROW INSERT INTO t3 VALUES (1);
+
+--connection master
+INSERT INTO t1 VALUES (2),(3);
+INSERT INTO t2 VALUES (2, default), (3, default);
+--sync_slave_with_master
+
+if ($slave_run_triggers_for_rbr == 'NO') {
+--echo #
+--echo # Count must be 0
+--echo #
+--let $assert_cond= COUNT(*) = 0 FROM t3
+--let $assert_text= Table t3 should have zero rows.
+--source include/assert.inc
+}
+if ($slave_run_triggers_for_rbr == 'YES') {
+--echo #
+--echo # Count must be 2
+--echo #
+--let $assert_cond= COUNT(*) = 2 FROM t3
+--let $assert_text= Table t3 should have two rows.
+--source include/assert.inc
+}
+
+--connection master
+DELETE FROM t1 WHERE id=2;
+--sync_slave_with_master
+SET GLOBAL slave_run_triggers_for_rbr= @save_slave_run_triggers_for_rbr;
+
+--echo #
+--echo # Verify t1, t2 are consistent on slave.
+--echo #
+--let $diff_tables= master:test.t1, slave:test.t1
+--source include/diff_tables.inc
+--let $diff_tables= master:test.t2, slave:test.t2
+--source include/diff_tables.inc
+
+--connection master
+DROP TABLE t3,t2,t1;
+--sync_slave_with_master
+#END OF
+PROCEDURE
+
+--echo #
+--echo # Test case 6: Triggers are present only on slave and
+--echo # 'slave_run_triggers_for_rbr=NO'
+--echo #
+--let $slave_run_triggers_for_rbr=NO
+--source $MYSQLTEST_VARDIR/tmp/trig_on_slave.inc
+
+--echo #
+--echo # Test case 7: Triggers are present only on slave and
+--echo # 'slave_run_triggers_for_rbr=YES'
+--echo #
+--let $slave_run_triggers_for_rbr=YES
+--source $MYSQLTEST_VARDIR/tmp/trig_on_slave.inc
+--remove_file $MYSQLTEST_VARDIR/tmp/trig_on_slave.inc
+
+#
+# Test case: Trigger and Foreign Key are present only on slave
+#
+--write_file $MYSQLTEST_VARDIR/tmp/trig_fk_on_slave.inc PROCEDURE
+ if ($slave_run_triggers_for_rbr == '') {
+ --die !!!ERROR IN TEST: you must set $slave_run_triggers_for_rbr
+ }
+
+--connection slave
+SET @save_slave_run_triggers_for_rbr= @@GLOBAL.slave_run_triggers_for_rbr;
+--eval SET GLOBAL slave_run_triggers_for_rbr= $slave_run_triggers_for_rbr;
+SHOW GLOBAL VARIABLES LIKE '%slave_run_triggers_for_rbr%';
+
+--connection master
+CREATE TABLE t1 (id INT NOT NULL PRIMARY KEY) ENGINE=InnoDB;
+SET sql_log_bin=0;
+CREATE TABLE t2 (t1_id INT NOT NULL,v_col INT AS (t1_id+1) VIRTUAL) ENGINE=INNODB;
+SET sql_log_bin=1;
+CREATE TABLE t3 (count INT NOT NULL) ENGINE=InnoDB;
+--sync_slave_with_master
+
+# Have foreign key and trigger on slave.
+CREATE TABLE t2 (t1_id INT NOT NULL,
+ v_col INT AS (t1_id+1) VIRTUAL, KEY (v_col), KEY (t1_id),
+ CONSTRAINT a FOREIGN KEY (t1_id) REFERENCES t1 (id) ON DELETE CASCADE
+) ENGINE=InnoDB;
+CREATE TRIGGER trg AFTER INSERT ON t2 FOR EACH ROW INSERT INTO t3 VALUES (1);
+
+--connection master
+INSERT INTO t1 VALUES (2),(3);
+INSERT INTO t2 VALUES (2, default), (3, default);
+--sync_slave_with_master
+
+if ($slave_run_triggers_for_rbr == 'NO') {
+--echo #
+--echo # Count must be 0
+--echo #
+--let $assert_cond= COUNT(*) = 0 FROM t3
+--let $assert_text= Table t3 should have zero rows.
+--source include/assert.inc
+}
+if ($slave_run_triggers_for_rbr == 'YES') {
+--echo #
+--echo # Count must be 2
+--echo #
+--let $assert_cond= COUNT(*) = 2 FROM t3
+--let $assert_text= Table t3 should have two rows.
+--source include/assert.inc
+}
+
+--connection master
+DELETE FROM t1 WHERE id=2;
+--echo # t1: Should have one row
+SELECT * FROM t1;
+--echo # t2: Should have two rows
+SELECT * FROM t2;
+--sync_slave_with_master
+--echo # t1: Should have one row
+SELECT * FROM t1;
+--echo # t2: Should have one row on slave due to ON DELETE CASCASE
+SELECT * FROM t2;
+SET GLOBAL slave_run_triggers_for_rbr= @save_slave_run_triggers_for_rbr;
+
+--connection master
+DROP TABLE t3,t2,t1;
+--sync_slave_with_master
+#END OF
+PROCEDURE
+
+--echo #
+--echo # Test case 8: Triggers and Foreign Keys are present only on slave and
+--echo # 'slave_run_triggers_for_rbr=NO'
+--echo #
+--let $slave_run_triggers_for_rbr=NO
+--source $MYSQLTEST_VARDIR/tmp/trig_fk_on_slave.inc
+
+--echo #
+--echo # Test case 9: Triggers are Foreign Keys are present only on slave and
+--echo # 'slave_run_triggers_for_rbr=YES'
+--echo #
+--let $slave_run_triggers_for_rbr=YES
+--source $MYSQLTEST_VARDIR/tmp/trig_fk_on_slave.inc
+--remove_file $MYSQLTEST_VARDIR/tmp/trig_fk_on_slave.inc
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_row_view01.test b/mysql-test/suite/rpl/t/rpl_row_view01.test
new file mode 100644
index 00000000..449196ae
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_row_view01.test
@@ -0,0 +1,85 @@
+#############################################################################
+# Original Author: JBM #
+# Original Date: Aug/19/2005 #
+# Updated: 08/29/2005 Remove sleeps #
+#############################################################################
+#TEST: row based replication of views #
+#############################################################################
+# Includes
+-- source include/have_binlog_format_row.inc
+-- source include/master-slave.inc
+
+# Begin clean up test section
+connection master;
+--disable_warnings
+create database if not exists mysqltest1;
+DROP VIEW IF EXISTS mysqltest1.v1;
+DROP VIEW IF EXISTS mysqltest1.v2;
+DROP VIEW IF EXISTS mysqltest1.v3;
+DROP VIEW IF EXISTS mysqltest1.v4;
+DROP TABLE IF EXISTS mysqltest1.t3;
+DROP TABLE IF EXISTS mysqltest1.t1;
+DROP TABLE IF EXISTS mysqltest1.t2;
+DROP TABLE IF EXISTS mysqltest1.t4;
+
+# Begin test section 1
+CREATE TABLE mysqltest1.t1 (a INT, c CHAR(6),PRIMARY KEY(a));
+CREATE TABLE mysqltest1.t2 (a INT, c CHAR(6),PRIMARY KEY(a));
+CREATE TABLE mysqltest1.t3 (a INT, c CHAR(6), c2 CHAR(6), PRIMARY KEY(a));
+CREATE TABLE mysqltest1.t4 (a INT, qty INT, price INT,PRIMARY KEY(a));
+CREATE TABLE mysqltest1.t5 (qty INT, price INT, total INT, PRIMARY KEY(qty));
+INSERT INTO mysqltest1.t1 VALUES (1,'Thank'),(2,'it'),(3,'Friday');
+INSERT INTO mysqltest1.t2 VALUES (1,'GOD'),(2,'is'),(3,'TGIF');
+INSERT INTO mysqltest1.t4 VALUES(1, 3, 50),(2, 18, 3),(4, 4, 4);
+
+
+CREATE VIEW mysqltest1.v2 AS SELECT qty, price, qty*price AS value FROM mysqltest1.t4 ORDER BY qty;
+CREATE VIEW mysqltest1.v1 AS SELECT t1.a, t1.c, t2.c as c2 FROM mysqltest1.t1 as t1, mysqltest1.t2 AS t2 WHERE mysqltest1.t1.a = mysqltest1.t2.a ORDER BY a;
+CREATE VIEW mysqltest1.v3 AS SELECT * FROM mysqltest1.t1;
+CREATE VIEW mysqltest1.v4 AS SELECT * FROM mysqltest1.v3 WHERE a > 1 WITH LOCAL CHECK OPTION;
+
+
+SELECT * FROM mysqltest1.v2;
+SELECT * FROM mysqltest1.v1;
+
+--sync_slave_with_master
+
+SELECT * FROM mysqltest1.v2;
+SELECT * FROM mysqltest1.v1;
+connection master;
+
+INSERT INTO mysqltest1.t5 SELECT * FROM mysqltest1.v2;
+INSERT INTO mysqltest1.t3 SELECT * FROM mysqltest1.v1;
+
+SELECT * FROM mysqltest1.t5 ORDER BY qty;
+SELECT * FROM mysqltest1.t3 ORDER BY a;
+sync_slave_with_master;
+SELECT * FROM mysqltest1.t5 ORDER BY qty;
+SELECT * FROM mysqltest1.t3 ORDER BY a;
+connection master;
+
+INSERT INTO mysqltest1.v4 VALUES (4,'TEST');
+
+SELECT * FROM mysqltest1.t1 ORDER BY a;
+SELECT * FROM mysqltest1.v4 ORDER BY a;
+sync_slave_with_master;
+SELECT * FROM mysqltest1.t1 ORDER BY a;
+SELECT * FROM mysqltest1.v4 ORDER BY a;
+
+connection master;
+
+# lets cleanup
+DROP VIEW IF EXISTS mysqltest1.v1;
+DROP VIEW IF EXISTS mysqltest1.v2;
+DROP VIEW IF EXISTS mysqltest1.v3;
+DROP VIEW IF EXISTS mysqltest1.v4;
+DROP TABLE IF EXISTS mysqltest1.t3;
+DROP TABLE IF EXISTS mysqltest1.t1;
+DROP TABLE IF EXISTS mysqltest1.t2;
+DROP TABLE IF EXISTS mysqltest1.t4;
+DROP DATABASE mysqltest1;
+sync_slave_with_master;
+
+# End of 5.1 test case
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_row_virt.test b/mysql-test/suite/rpl/t/rpl_row_virt.test
new file mode 100644
index 00000000..e79869cd
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_row_virt.test
@@ -0,0 +1,27 @@
+--source include/have_binlog_format_row.inc
+--source include/master-slave.inc
+--source include/have_innodb.inc
+connection master;
+
+create table t1 (
+ id int auto_increment,
+ data varchar(32),
+ virt tinyint as (1),
+ primary key (id),
+ key virt (virt)
+) engine=innodb default charset=utf8mb4;
+
+insert into t1 (data) values ('broken');
+
+update t1 set data='more broken';
+
+--sync_slave_with_master
+
+select * from t1;
+
+--connection master
+drop table t1;
+
+--sync_slave_with_master
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_row_wide_table.test b/mysql-test/suite/rpl/t/rpl_row_wide_table.test
new file mode 100644
index 00000000..01473f99
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_row_wide_table.test
@@ -0,0 +1,340 @@
+##################################################################
+# rpl_row_wide_table
+#
+# This test verifies that the table with number of attributes more
+# than 250 is replicated.
+# Related bugs:
+# Bug #42977 RBR logs for rows with more than 250 column results
+# in corrupt binlog
+##################################################################
+
+-- source include/have_binlog_format_row.inc
+-- source include/master-slave.inc
+
+--disable_warnings
+DROP TABLE IF EXISTS t300;
+--enable_warnings
+
+connection master;
+
+create table t300 (
+f1 int,
+f2 int,
+f3 int,
+f4 int,
+f5 int,
+f6 int,
+f7 int,
+f8 int,
+f9 int,
+f10 int,
+f11 int,
+f12 int,
+f13 int,
+f14 int,
+f15 int,
+f16 int,
+f17 int,
+f18 int,
+f19 int,
+f20 int,
+f21 int,
+f22 int,
+f23 int,
+f24 int,
+f25 int,
+f26 int,
+f27 int,
+f28 int,
+f29 int,
+f30 int,
+f31 int,
+f32 int,
+f33 int,
+f34 int,
+f35 int,
+f36 int,
+f37 int,
+f38 int,
+f39 int,
+f40 int,
+f41 int,
+f42 int,
+f43 int,
+f44 int,
+f45 int,
+f46 int,
+f47 int,
+f48 int,
+f49 int,
+f50 int,
+f51 int,
+f52 int,
+f53 int,
+f54 int,
+f55 int,
+f56 int,
+f57 int,
+f58 int,
+f59 int,
+f60 int,
+f61 int,
+f62 int,
+f63 int,
+f64 int,
+f65 int,
+f66 int,
+f67 int,
+f68 int,
+f69 int,
+f70 int,
+f71 int,
+f72 int,
+f73 int,
+f74 int,
+f75 int,
+f76 int,
+f77 int,
+f78 int,
+f79 int,
+f80 int,
+f81 int,
+f82 int,
+f83 int,
+f84 int,
+f85 int,
+f86 int,
+f87 int,
+f88 int,
+f89 int,
+f90 int,
+f91 int,
+f92 int,
+f93 int,
+f94 int,
+f95 int,
+f96 int,
+f97 int,
+f98 int,
+f99 int,
+f100 int,
+f101 int,
+f102 int,
+f103 int,
+f104 int,
+f105 int,
+f106 int,
+f107 int,
+f108 int,
+f109 int,
+f110 int,
+f111 int,
+f112 int,
+f113 int,
+f114 int,
+f115 int,
+f116 int,
+f117 int,
+f118 int,
+f119 int,
+f120 int,
+f121 int,
+f122 int,
+f123 int,
+f124 int,
+f125 int,
+f126 int,
+f127 int,
+f128 int,
+f129 int,
+f130 int,
+f131 int,
+f132 int,
+f133 int,
+f134 int,
+f135 int,
+f136 int,
+f137 int,
+f138 int,
+f139 int,
+f140 int,
+f141 int,
+f142 int,
+f143 int,
+f144 int,
+f145 int,
+f146 int,
+f147 int,
+f148 int,
+f149 int,
+f150 int,
+f151 int,
+f152 int,
+f153 int,
+f154 int,
+f155 int,
+f156 int,
+f157 int,
+f158 int,
+f159 int,
+f160 int,
+f161 int,
+f162 int,
+f163 int,
+f164 int,
+f165 int,
+f166 int,
+f167 int,
+f168 int,
+f169 int,
+f170 int,
+f171 int,
+f172 int,
+f173 int,
+f174 int,
+f175 int,
+f176 int,
+f177 int,
+f178 int,
+f179 int,
+f180 int,
+f181 int,
+f182 int,
+f183 int,
+f184 int,
+f185 int,
+f186 int,
+f187 int,
+f188 int,
+f189 int,
+f190 int,
+f191 int,
+f192 int,
+f193 int,
+f194 int,
+f195 int,
+f196 int,
+f197 int,
+f198 int,
+f199 int,
+f200 int,
+f201 int,
+f202 int,
+f203 int,
+f204 int,
+f205 int,
+f206 int,
+f207 int,
+f208 int,
+f209 int,
+f210 int,
+f211 int,
+f212 int,
+f213 int,
+f214 int,
+f215 int,
+f216 int,
+f217 int,
+f218 int,
+f219 int,
+f220 int,
+f221 int,
+f222 int,
+f223 int,
+f224 int,
+f225 int,
+f226 int,
+f227 int,
+f228 int,
+f229 int,
+f230 int,
+f231 int,
+f232 int,
+f233 int,
+f234 int,
+f235 int,
+f236 int,
+f237 int,
+f238 int,
+f239 int,
+f240 int,
+f241 int,
+f242 int,
+f243 int,
+f244 int,
+f245 int,
+f246 int,
+f247 int,
+f248 int,
+f249 int,
+f250 int,
+f251 int,
+f252 int,
+f253 int,
+f254 int,
+f255 int,
+f256 int,
+f257 int,
+f258 int,
+f259 int,
+f260 int,
+f261 int,
+f262 int,
+f263 int,
+f264 int,
+f265 int,
+f266 int,
+f267 int,
+f268 int,
+f269 int,
+f270 int,
+f271 int,
+f272 int,
+f273 int,
+f274 int,
+f275 int,
+f276 int,
+f277 int,
+f278 int,
+f279 int,
+f280 int,
+f281 int,
+f282 int,
+f283 int,
+f284 int,
+f285 int,
+f286 int,
+f287 int,
+f288 int,
+f289 int,
+f290 int,
+f291 int,
+f292 int,
+f293 int,
+f294 int,
+f295 int,
+f296 int,
+f297 int,
+f298 int,
+f299 int,
+f300 int,
+ primary key (f1));
+
+insert into t300 set f1= 1;
+
+sync_slave_with_master;
+
+#
+# prove that slave processed the create as well as the insert
+#
+eval select f300 from t300;
+select count(*) as one from t300;
+
+--echo *** Cleanup ***
+connection master;
+DROP TABLE t300;
+sync_slave_with_master;
+
+# END of Test Case
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_savepoint.test b/mysql-test/suite/rpl/t/rpl_savepoint.test
new file mode 100644
index 00000000..31af6151
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_savepoint.test
@@ -0,0 +1,43 @@
+--source include/have_innodb.inc
+--source include/master-slave.inc
+
+--echo #
+--echo # Bug#50124 Rpl failure on DROP table with concurrent txn/non-txn
+--echo # DML flow and SAVEPOINT
+--echo #
+
+connection master;
+
+--disable_warnings
+DROP TABLE IF EXISTS tt, nt;
+--enable_warnings
+
+CREATE TABLE tt (i INT) ENGINE = InnoDB;
+CREATE TABLE nt (i INT) ENGINE = MyISAM;
+FLUSH LOGS;
+START TRANSACTION;
+INSERT INTO nt VALUES (1);
+SAVEPOINT insert_statement;
+INSERT INTO tt VALUES (1);
+
+connection master1;
+--echo # Sending:
+--send DROP TABLE tt
+
+connection master;
+let $wait_condition=
+ SELECT COUNT(*) = 1 FROM information_schema.processlist
+ WHERE state = "Waiting for table metadata lock" AND info = "DROP TABLE tt";
+--source include/wait_condition.inc
+ROLLBACK TO SAVEPOINT insert_statement;
+COMMIT;
+
+connection master1;
+--echo # Reaping: DROP TABLE tt
+--reap
+FLUSH LOGS;
+
+connection master;
+DROP TABLE nt;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_seconds_behind_master_spike.test b/mysql-test/suite/rpl/t/rpl_seconds_behind_master_spike.test
new file mode 100644
index 00000000..7c2e39dc
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_seconds_behind_master_spike.test
@@ -0,0 +1,191 @@
+#
+# Purpose:
+# This test validates that a slave's relay log format description event is
+# not used to calculate the Seconds_Behind_Master time displayed by
+# SHOW SLAVE STATUS.
+#
+# Methodology:
+# Ensure that a slave's reported Seconds_Behind_Master does not point before
+# a time in which we can prove that it has progressed beyond. The slave's
+# relay log events are created using the timestamp at which the IO thread was
+# created. Therefore, after starting the slave's IO thread, we sleep so any
+# proceeding events are forced to have later timestamps. After sleeping, we run
+# MDL statements on the master and save the time at which they are binlogged.
+# Once the slave executes these MDL commands, we have proven that the slave has
+# caught up to this saved timestamp. At this point, if the value of
+# Seconds_Behind_Master points before the time in which the MDL events were
+# logged, it is invalid.
+#
+# References:
+# MDEV-16091: Seconds_Behind_Master spikes to millions of seconds
+#
+--source include/have_debug.inc
+--source include/have_debug_sync.inc
+--source include/have_innodb.inc
+--source include/master-slave.inc
+
+--connection slave
+
+# Using_Gtid needs to start as NO before updating debug_dbug
+--source include/stop_slave.inc
+CHANGE MASTER TO MASTER_USE_GTID=NO;
+--source include/start_slave.inc
+
+--source include/stop_slave.inc
+SET @save_dbug= @@GLOBAL.debug_dbug;
+SET @@global.debug_dbug="+d,pause_sql_thread_on_fde,negate_clock_diff_with_master";
+--source include/start_slave.inc
+
+--let $sleep_time=2
+--echo # Future events must be logged at least $sleep_time seconds after
+--echo # the slave starts
+--sleep $sleep_time
+
+--connection master
+--echo # Write events to ensure slave will be consistent with master
+create table t1 (a int);
+insert into t1 values (1);
+--let $t_master_events_logged= `SELECT UNIX_TIMESTAMP()`
+
+--echo # Flush logs on master forces slave to generate a Format description
+--echo # event in its relay log
+flush logs;
+
+--connection slave
+--echo # Ignore FDEs that happen before the CREATE/INSERT commands
+SET DEBUG_SYNC='now WAIT_FOR paused_on_fde';
+SET DEBUG_SYNC='now SIGNAL sql_thread_continue';
+SET DEBUG_SYNC='now WAIT_FOR paused_on_fde';
+SET DEBUG_SYNC='now SIGNAL sql_thread_continue';
+
+--echo # On the next FDE, the slave should have the master CREATE/INSERT events
+SET DEBUG_SYNC='now WAIT_FOR paused_on_fde';
+select count(*)=1 from t1;
+
+--echo # The relay log FDE has been processed - here we check to ensure it was
+--echo # not considered in Seconds_Behind_Master calculation
+--connection slave1
+let $sbm= query_get_value(SHOW SLAVE STATUS, Seconds_Behind_Master, 1);
+--let $t_now= `SELECT UNIX_TIMESTAMP()`
+
+# Ensure Seconds_Behind_Master does not point beyond when we have proven the
+# events we have proven to have executed. The extra second is needed as a
+# buffer because the recorded times are not exact with when the events were
+# recorded on the master.
+if(`select $sbm > $t_now - $t_master_events_logged + 1`)
+{
+ die "A relay log event was incorrectly used to set Seconds_Behind_Master";
+}
+
+--echo # Safely resume slave SQL thread
+
+--let $dbug_wait_state="debug sync point: now"
+--echo # Prove SQL thread is in state $dbug_wait_state
+--let $wait_condition= SELECT STATE=$dbug_wait_state from information_schema.PROCESSLIST where COMMAND="Slave_SQL"
+--source include/wait_condition.inc
+
+SET @@global.debug_dbug="-d,pause_sql_thread_on_fde";
+SET DEBUG_SYNC='now SIGNAL sql_thread_continue';
+
+# We have to wait for the SQL thread to acknowledge the sql_thread_continue
+# signal. Otherwise the below RESET command can overwrite the signal before
+# the SQL thread is notified to proceed, causing it to "permanently" become
+# stuck awaiting the signal (until timeout is reached).
+
+--echo # Wait for SQL thread to continue into normal execution
+--let $wait_condition= SELECT STATE!= $dbug_wait_state from information_schema.PROCESSLIST where COMMAND="Slave_SQL"
+--source include/wait_condition.inc
+
+# Reset last sql_thread_continue signal
+SET DEBUG_SYNC='RESET';
+
+
+--echo #
+--echo # MDEV-29639
+--echo # When receiving an event after the SQL Thread idles,
+--echo # Seconds_Behind_Master should not update before it updates
+--echo # last_master_timestamp
+
+--connection slave
+--source include/stop_slave.inc
+set @@global.debug_dbug="+d,pause_sql_thread_on_next_event";
+--source include/start_slave.inc
+
+--connection master
+insert into t1 values(2);
+--source include/save_master_gtid.inc
+
+# Each event after starting will trigger a pause, so continually send signal
+# sql_thread_continue until caught up
+--connection slave
+--let $caught_up=0
+--let $tries= 0
+set debug_sync='now wait_for paused_on_event';
+--disable_query_log
+while (!$caught_up)
+{
+ set debug_sync='now signal sql_thread_continue';
+ --let $slave_gtid= `SELECT @@global.gtid_slave_pos`
+ if (`SELECT strcmp("$master_pos","$slave_gtid") = 0`)
+ {
+ --inc $caught_up
+ }
+ --inc $tries
+ # Wait 30s
+ if (`SELECT $tries > 300`)
+ {
+ --die Replica failed to sync with primary
+ }
+ sleep 0.1;
+}
+--enable_query_log
+
+--connection master
+--echo # Sleeping 1s to create a visible SBM gap between events
+sleep 1;
+insert into t1 values(3);
+--source include/save_master_gtid.inc
+
+--connection slave
+set debug_sync='now wait_for paused_on_event';
+--let $sbm= query_get_value(SHOW SLAVE STATUS, Seconds_Behind_Master, 1)
+
+if ($sbm)
+{
+ --echo # Expected Seconds_Behind_Master to be 0 but was $sbm
+ --die Seconds_Behind_Master should not show updates before last_master_timestamp is updated
+}
+
+# Continually send signal sql_thread_continue until caught up
+--let $caught_up=0
+--let $tries= 0
+--disable_query_log
+while (!$caught_up)
+{
+ set debug_sync='now signal sql_thread_continue';
+ --let $slave_gtid= `SELECT @@global.gtid_slave_pos`
+ if (`SELECT strcmp("$master_pos","$slave_gtid") = 0`)
+ {
+ --inc $caught_up
+ }
+ --inc $tries
+ # Wait 30s
+ if (`SELECT $tries > 300`)
+ {
+ --die Replica failed to sync with primary
+ }
+ sleep 0.1;
+}
+--enable_query_log
+
+# Cleanup
+--source include/stop_slave.inc
+set debug_sync='RESET';
+SET @@global.debug_dbug=$save_dbug;
+--source include/start_slave.inc
+--source include/sync_with_master_gtid.inc
+
+--connection master
+DROP TABLE t1;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_semi_sync.test b/mysql-test/suite/rpl/t/rpl_semi_sync.test
new file mode 100644
index 00000000..720ec059
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_semi_sync.test
@@ -0,0 +1,532 @@
+#
+# This include file is used by more than one test suite
+# (currently rpl and binlog_encryption).
+# Please check all dependent tests after modifying it
+#
+
+source include/not_embedded.inc;
+source include/have_innodb.inc;
+source include/master-slave.inc;
+
+let $engine_type= InnoDB;
+
+# Suppress warnings that might be generated during the test
+connection master;
+call mtr.add_suppression("Timeout waiting for reply of binlog");
+call mtr.add_suppression("Read semi-sync reply");
+call mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT.");
+call mtr.add_suppression("mysqld: Got an error reading communication packets");
+connection slave;
+# While 'Current_Pos' exists as an option for Using_Gtd, keeping these
+# events in the binlog will update gtid_binlog_pos, and the later calls to
+# set `@@global.gtid_slave_pos= ""` will provide warning messages with
+# inconsistent GTID values because the seq_nos are non-deterministic with
+# the masters events coming in concurrently
+set sql_log_bin=0;
+call mtr.add_suppression("Master server does not support semi-sync");
+call mtr.add_suppression("Semi-sync slave .* reply");
+call mtr.add_suppression("Slave SQL.*Request to stop slave SQL Thread received while applying a group that has non-transactional changes; waiting for completion of the group");
+set sql_log_bin=1;
+connection master;
+
+# wait for dying connections (if any) to disappear
+let $wait_condition= select count(*) = 0 from information_schema.processlist where command='killed';
+--source include/wait_condition.inc
+
+# After fix of BUG#45848, semi-sync slave should not create any extra
+# connections on master, save the count of connections before start
+# semi-sync slave for comparison below.
+let $_connections_normal_slave= query_get_value(SHOW STATUS LIKE 'Threads_connected', Value, 1);
+
+--echo #
+--echo # Uninstall semi-sync plugins on master and slave
+--echo #
+connection slave;
+source include/stop_slave.inc;
+--source include/reset_slave.inc
+set global rpl_semi_sync_master_enabled= 0;
+set global rpl_semi_sync_slave_enabled= 0;
+
+connection master;
+reset master;
+set global rpl_semi_sync_master_enabled= 0;
+set global rpl_semi_sync_slave_enabled= 0;
+
+--echo #
+--echo # Main test of semi-sync replication start here
+--echo #
+
+connection master;
+
+set global rpl_semi_sync_master_timeout= 60000; # 60s
+
+echo [ default state of semi-sync on master should be OFF ];
+show variables like 'rpl_semi_sync_master_enabled';
+
+echo [ enable semi-sync on master ];
+set global rpl_semi_sync_master_enabled = 1;
+show variables like 'rpl_semi_sync_master_enabled';
+
+echo [ status of semi-sync on master should be ON even without any semi-sync slaves ];
+show status like 'Rpl_semi_sync_master_clients';
+show status like 'Rpl_semi_sync_master_status';
+show status like 'Rpl_semi_sync_master_yes_tx';
+
+--echo #
+--echo # BUG#45672 Semisync repl: ActiveTranx:insert_tranx_node: transaction node allocation failed
+--echo # BUG#45673 Semisynch reports correct operation even if no slave is connected
+--echo #
+
+# BUG#45672 When semi-sync is enabled on master, it would allocate
+# transaction node even without semi-sync slave connected, and would
+# finally result in transaction node allocation error.
+#
+# Semi-sync master will pre-allocate 'max_connections' transaction
+# nodes, so here we do more than that much transactions to check if it
+# will fail or not.
+# select @@global.max_connections + 1;
+let $i= `select @@global.max_connections + 1`;
+disable_query_log;
+eval create table t1 (a int) engine=$engine_type;
+while ($i)
+{
+ eval insert into t1 values ($i);
+ dec $i;
+}
+drop table t1;
+enable_query_log;
+
+# BUG#45673
+echo [ status of semi-sync on master should be OFF ];
+show status like 'Rpl_semi_sync_master_clients';
+show status like 'Rpl_semi_sync_master_status';
+show status like 'Rpl_semi_sync_master_yes_tx';
+
+# reset master to make sure the following test will start with a clean environment
+reset master;
+
+connection slave;
+
+echo [ default state of semi-sync on slave should be OFF ];
+show variables like 'rpl_semi_sync_slave_enabled';
+
+echo [ enable semi-sync on slave ];
+set global rpl_semi_sync_slave_enabled = 1;
+show variables like 'rpl_semi_sync_slave_enabled';
+source include/start_slave.inc;
+
+connection master;
+
+# NOTE: Rpl_semi_sync_master_client will only be updated when
+# semi-sync slave has started binlog dump request
+let $status_var= Rpl_semi_sync_master_clients;
+let $status_var_value= 1;
+source include/wait_for_status_var.inc;
+
+echo [ initial master state after the semi-sync slave connected ];
+show status like 'Rpl_semi_sync_master_clients';
+show status like 'Rpl_semi_sync_master_status';
+show status like 'Rpl_semi_sync_master_no_tx';
+show status like 'Rpl_semi_sync_master_yes_tx';
+
+replace_result $engine_type ENGINE_TYPE;
+eval create table t1(a int) engine = $engine_type;
+
+echo [ master state after CREATE TABLE statement ];
+show status like 'Rpl_semi_sync_master_status';
+show status like 'Rpl_semi_sync_master_no_tx';
+show status like 'Rpl_semi_sync_master_yes_tx';
+
+# After fix of BUG#45848, semi-sync slave should not create any extra
+# connections on master.
+let $_connections_semisync_slave= query_get_value(SHOW STATUS LIKE 'Threads_connected', Value, 1);
+replace_result $_connections_normal_slave CONNECTIONS_NORMAL_SLAVE $_connections_semisync_slave CONNECTIONS_SEMISYNC_SLAVE;
+eval select $_connections_semisync_slave - $_connections_normal_slave as 'Should be 0';
+
+echo [ insert records to table ];
+insert t1 values (10);
+insert t1 values (9);
+insert t1 values (8);
+insert t1 values (7);
+insert t1 values (6);
+insert t1 values (5);
+insert t1 values (4);
+insert t1 values (3);
+insert t1 values (2);
+insert t1 values (1);
+
+echo [ master status after inserts ];
+show status like 'Rpl_semi_sync_master_status';
+show status like 'Rpl_semi_sync_master_no_tx';
+show status like 'Rpl_semi_sync_master_yes_tx';
+
+sync_slave_with_master;
+
+echo [ slave status after replicated inserts ];
+show status like 'Rpl_semi_sync_slave_status';
+
+select count(distinct a) from t1;
+select min(a) from t1;
+select max(a) from t1;
+
+--echo
+--echo # BUG#50157
+--echo # semi-sync replication crashes when replicating a transaction which
+--echo # include 'CREATE TEMPORARY TABLE `MyISAM_t` SELECT * FROM `Innodb_t` ;
+
+connection master;
+SET SESSION AUTOCOMMIT= 0;
+CREATE TABLE t2(c1 INT) ENGINE=innodb;
+sync_slave_with_master;
+
+connection master;
+BEGIN;
+--echo
+--echo # Even though it is in a transaction, this statement is binlogged into binlog
+--echo # file immediately.
+--disable_warnings
+CREATE TEMPORARY TABLE t3 SELECT c1 FROM t2 where 1=1;
+--enable_warnings
+--echo
+--echo # These statements will not be binlogged until the transaction is committed
+INSERT INTO t2 VALUES(11);
+INSERT INTO t2 VALUES(22);
+COMMIT;
+
+DROP TABLE t2, t3;
+SET SESSION AUTOCOMMIT= 1;
+sync_slave_with_master;
+
+
+--echo #
+--echo # Test semi-sync master will switch OFF after one transaction
+--echo # timeout waiting for slave reply.
+--echo #
+connection slave;
+source include/stop_slave.inc;
+
+connection master;
+--source include/kill_binlog_dump_threads.inc
+set global rpl_semi_sync_master_timeout= 5000;
+
+# The first semi-sync check should be on because after slave stop,
+# there are no transactions on the master.
+echo [ master status should be ON ];
+
+let $status_var= Rpl_semi_sync_master_status;
+let $status_var_value= ON;
+source include/wait_for_status_var.inc;
+
+let $status_var= Rpl_semi_sync_master_clients;
+let $status_var_value= 0;
+source include/wait_for_status_var.inc;
+
+show status like 'Rpl_semi_sync_master_no_tx';
+show status like 'Rpl_semi_sync_master_yes_tx';
+
+echo [ semi-sync replication of these transactions will fail ];
+insert into t1 values (500);
+
+# Wait for the semi-sync replication of this transaction to timeout
+let $status_var= Rpl_semi_sync_master_status;
+let $status_var_value= OFF;
+source include/wait_for_status_var.inc;
+
+# The second semi-sync check should be off because one transaction
+# times out during waiting.
+echo [ master status should be OFF ];
+show status like 'Rpl_semi_sync_master_status';
+show status like 'Rpl_semi_sync_master_no_tx';
+show status like 'Rpl_semi_sync_master_yes_tx';
+
+# Semi-sync status on master is now OFF, so all these transactions
+# will be replicated asynchronously.
+delete from t1 where a=10;
+delete from t1 where a=9;
+delete from t1 where a=8;
+delete from t1 where a=7;
+delete from t1 where a=6;
+delete from t1 where a=5;
+delete from t1 where a=4;
+delete from t1 where a=3;
+delete from t1 where a=2;
+delete from t1 where a=1;
+
+insert into t1 values (100);
+
+echo [ master status should be OFF ];
+show status like 'Rpl_semi_sync_master_status';
+show status like 'Rpl_semi_sync_master_no_tx';
+show status like 'Rpl_semi_sync_master_yes_tx';
+
+--echo #
+--echo # Test semi-sync status on master will be ON again when slave catches up
+--echo #
+
+# Save the master position for later use.
+save_master_pos;
+
+connection slave;
+
+echo [ slave status should be OFF ];
+show status like 'Rpl_semi_sync_slave_status';
+source include/start_slave.inc;
+sync_with_master;
+
+echo [ slave status should be ON ];
+show status like 'Rpl_semi_sync_slave_status';
+
+select count(distinct a) from t1;
+select min(a) from t1;
+select max(a) from t1;
+
+connection master;
+
+# The master semi-sync status should be on again after slave catches up.
+echo [ master status should be ON again after slave catches up ];
+
+let $status_var= Rpl_semi_sync_master_status;
+let $status_var_value= ON;
+source include/wait_for_status_var.inc;
+show status like 'Rpl_semi_sync_master_no_tx';
+show status like 'Rpl_semi_sync_master_yes_tx';
+show status like 'Rpl_semi_sync_master_clients';
+
+--echo #
+--echo # Test disable/enable master semi-sync on the fly.
+--echo #
+
+drop table t1;
+sync_slave_with_master;
+
+source include/stop_slave.inc;
+
+--echo #
+--echo # Flush status
+--echo #
+connection master;
+echo [ Semi-sync master status variables before FLUSH STATUS ];
+SHOW STATUS LIKE 'Rpl_semi_sync_master_no_tx';
+SHOW STATUS LIKE 'Rpl_semi_sync_master_yes_tx';
+# Do not write the FLUSH STATUS to binlog, to make sure we'll get a
+# clean status after this.
+FLUSH NO_WRITE_TO_BINLOG STATUS;
+echo [ Semi-sync master status variables after FLUSH STATUS ];
+SHOW STATUS LIKE 'Rpl_semi_sync_master_no_tx';
+SHOW STATUS LIKE 'Rpl_semi_sync_master_yes_tx';
+
+connection master;
+
+source include/show_master_logs.inc;
+show variables like 'rpl_semi_sync_master_enabled';
+
+echo [ disable semi-sync on the fly ];
+set global rpl_semi_sync_master_enabled=0;
+show variables like 'rpl_semi_sync_master_enabled';
+show status like 'Rpl_semi_sync_master_status';
+
+echo [ enable semi-sync on the fly ];
+set global rpl_semi_sync_master_enabled=1;
+show variables like 'rpl_semi_sync_master_enabled';
+show status like 'Rpl_semi_sync_master_status';
+
+--echo #
+--echo # Test RESET MASTER/SLAVE
+--echo #
+
+connection slave;
+
+source include/start_slave.inc;
+
+connection master;
+
+replace_result $engine_type ENGINE_TYPE;
+eval create table t1 (a int) engine = $engine_type;
+drop table t1;
+
+sync_slave_with_master;
+
+echo [ test reset master ];
+connection master;
+
+reset master;
+
+show status like 'Rpl_semi_sync_master_status';
+show status like 'Rpl_semi_sync_master_no_tx';
+show status like 'Rpl_semi_sync_master_yes_tx';
+
+connection slave;
+
+source include/stop_slave.inc;
+--source include/reset_slave.inc
+
+# Kill the dump thread on master for previous slave connection and
+--source include/kill_binlog_dump_threads.inc
+
+connection slave;
+source include/start_slave.inc;
+
+connection master;
+
+# Wait for dump thread to start, Rpl_semi_sync_master_clients will be
+# 1 after dump thread started.
+let $status_var= Rpl_semi_sync_master_clients;
+let $status_var_value= 1;
+source include/wait_for_status_var.inc;
+
+replace_result $engine_type ENGINE_TYPE;
+eval create table t1 (a int) engine = $engine_type;
+insert into t1 values (1);
+insert into t1 values (2), (3);
+
+sync_slave_with_master;
+
+select * from t1;
+
+connection master;
+
+echo [ master semi-sync status should be ON ];
+show status like 'Rpl_semi_sync_master_status';
+show status like 'Rpl_semi_sync_master_no_tx';
+show status like 'Rpl_semi_sync_master_yes_tx';
+
+--echo #
+--echo # Start semi-sync replication without SUPER privilege
+--echo #
+connection slave;
+source include/stop_slave.inc;
+--source include/reset_slave.inc
+connection master;
+reset master;
+
+# Kill the dump thread on master for previous slave connection and wait for it to exit
+--source include/kill_binlog_dump_threads.inc
+
+# Do not binlog the following statement because it will generate
+# different events for ROW and STATEMENT format
+set sql_log_bin=0;
+grant replication slave on *.* to rpl@127.0.0.1 identified by 'rpl_password';
+flush privileges;
+set sql_log_bin=1;
+connection slave;
+grant replication slave on *.* to rpl@127.0.0.1 identified by 'rpl_password';
+flush privileges;
+change master to master_user='rpl',master_password='rpl_password';
+source include/start_slave.inc;
+show status like 'Rpl_semi_sync_slave_status';
+connection master;
+
+# Wait for the semi-sync binlog dump thread to start
+let $status_var= Rpl_semi_sync_master_clients;
+let $status_var_value= 1;
+source include/wait_for_status_var.inc;
+echo [ master semi-sync should be ON ];
+show status like 'Rpl_semi_sync_master_clients';
+show status like 'Rpl_semi_sync_master_status';
+show status like 'Rpl_semi_sync_master_no_tx';
+show status like 'Rpl_semi_sync_master_yes_tx';
+insert into t1 values (4);
+insert into t1 values (5);
+echo [ master semi-sync should be ON ];
+show status like 'Rpl_semi_sync_master_clients';
+show status like 'Rpl_semi_sync_master_status';
+show status like 'Rpl_semi_sync_master_no_tx';
+show status like 'Rpl_semi_sync_master_yes_tx';
+
+--echo #
+--echo # Test semi-sync slave connect to non-semi-sync master
+--echo #
+
+# Disable semi-sync on master
+connection slave;
+source include/stop_slave.inc;
+SHOW STATUS LIKE 'Rpl_semi_sync_slave_status';
+
+connection master;
+
+# Kill the dump thread on master for previous slave connection and wait for it to exit
+--source include/kill_binlog_dump_threads.inc
+
+echo [ Semi-sync status on master should be ON ];
+let $status_var= Rpl_semi_sync_master_clients;
+let $status_var_value= 0;
+source include/wait_for_status_var.inc;
+show status like 'Rpl_semi_sync_master_status';
+let $status_var= Rpl_semi_sync_master_status;
+let $status_var_value= ON;
+source include/wait_for_status_var.inc;
+set global rpl_semi_sync_master_enabled= 0;
+
+connection slave;
+SHOW VARIABLES LIKE 'rpl_semi_sync_slave_enabled';
+source include/start_slave.inc;
+connection master;
+insert into t1 values (8);
+let $status_var= Rpl_semi_sync_master_clients;
+let $status_var_value= 1;
+source include/wait_for_status_var.inc;
+echo [ master semi-sync clients should be 1, status should be OFF ];
+show status like 'Rpl_semi_sync_master_clients';
+show status like 'Rpl_semi_sync_master_status';
+sync_slave_with_master;
+show status like 'Rpl_semi_sync_slave_status';
+
+# Uninstall semi-sync plugin on master
+connection slave;
+source include/stop_slave.inc;
+connection master;
+set global rpl_semi_sync_master_enabled= 0;
+
+connection slave;
+SHOW VARIABLES LIKE 'rpl_semi_sync_slave_enabled';
+source include/start_slave.inc;
+
+connection master;
+insert into t1 values (10);
+sync_slave_with_master;
+
+--echo #
+--echo # Test non-semi-sync slave connect to semi-sync master
+--echo #
+
+connection master;
+set global rpl_semi_sync_master_timeout= 5000; # 5s
+set global rpl_semi_sync_master_enabled= 1;
+
+connection slave;
+source include/stop_slave.inc;
+SHOW STATUS LIKE 'Rpl_semi_sync_slave_status';
+
+echo [ uninstall semi-sync slave plugin ];
+set global rpl_semi_sync_slave_enabled= 0;
+
+echo [ reinstall semi-sync slave plugin and disable semi-sync ];
+SHOW VARIABLES LIKE 'rpl_semi_sync_slave_enabled';
+SHOW STATUS LIKE 'Rpl_semi_sync_slave_status';
+source include/start_slave.inc;
+SHOW STATUS LIKE 'Rpl_semi_sync_slave_status';
+
+--echo #
+--echo # Clean up
+--echo #
+
+connection slave;
+source include/stop_slave.inc;
+set global rpl_semi_sync_slave_enabled= 0;
+
+connection master;
+set global rpl_semi_sync_master_enabled= 0;
+
+connection slave;
+change master to master_user='root',master_password='';
+source include/start_slave.inc;
+
+connection master;
+drop table t1;
+sync_slave_with_master;
+
+connection master;
+drop user rpl@127.0.0.1;
+flush privileges;
+set global rpl_semi_sync_master_timeout= default;
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_semi_sync_after_sync.test b/mysql-test/suite/rpl/t/rpl_semi_sync_after_sync.test
new file mode 100644
index 00000000..2d91d2e4
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_semi_sync_after_sync.test
@@ -0,0 +1,4 @@
+--source include/have_binlog_format_statement.inc
+set global rpl_semi_sync_master_wait_point=AFTER_SYNC;
+source rpl_semi_sync.test;
+set global rpl_semi_sync_master_wait_point=default;
diff --git a/mysql-test/suite/rpl/t/rpl_semi_sync_after_sync_row.test b/mysql-test/suite/rpl/t/rpl_semi_sync_after_sync_row.test
new file mode 100644
index 00000000..47af6c34
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_semi_sync_after_sync_row.test
@@ -0,0 +1,4 @@
+--source include/have_binlog_format_row.inc
+set global rpl_semi_sync_master_wait_point=AFTER_SYNC;
+source rpl_semi_sync.test;
+set global rpl_semi_sync_master_wait_point=default;
diff --git a/mysql-test/suite/rpl/t/rpl_semi_sync_crash.inc b/mysql-test/suite/rpl/t/rpl_semi_sync_crash.inc
new file mode 100644
index 00000000..01b0d0e5
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_semi_sync_crash.inc
@@ -0,0 +1,112 @@
+if ($failover_to_slave)
+{
+ --let $server_to_crash=1
+ --let $server_to_promote=2
+ --let $new_master_port=$SERVER_MYPORT_2
+ --let $client_port=$SERVER_MYPORT_1
+
+ --connect (conn_client,127.0.0.1,root,,test,$SERVER_MYPORT_1,)
+}
+if (!$failover_to_slave)
+{
+ --let $server_to_crash=2
+ --let $server_to_promote=1
+ --let $new_master_port=$SERVER_MYPORT_1
+ --let $client_port=$SERVER_MYPORT_2
+
+ --connect (conn_client,127.0.0.1,root,,test,$SERVER_MYPORT_2,)
+}
+
+
+# Hold insert after write to binlog and before "run_commit_ordered" in engine
+
+
+if ($case == 1)
+{
+ SET DEBUG_SYNC= "commit_after_release_LOCK_after_binlog_sync SIGNAL con1_ready WAIT_FOR con1_go";
+ --send_eval $query_to_crash
+ --connection server_$server_to_crash
+ SET DEBUG_SYNC= "now WAIT_FOR con1_ready";
+ --source include/kill_mysqld.inc
+}
+
+# complicate recovery with an extra binlog file
+if ($case == 2)
+{
+ SET DEBUG_SYNC= "commit_before_get_LOCK_commit_ordered SIGNAL con1_ready WAIT_FOR con1_go";
+ --send_eval $query_to_crash
+ --connect (conn_client_2,127.0.0.1,root,,test,$SERVER_MYPORT_2,)
+ # use the same signal with $query_to_crash
+ SET DEBUG_SYNC= "now WAIT_FOR con1_ready";
+ SET GLOBAL debug_dbug="d,Notify_binlog_EOF";
+ --send_eval $query2_to_crash
+ --connection server_$server_to_crash
+ SET DEBUG_SYNC= "now WAIT_FOR eof_reached";
+ --source include/kill_mysqld.inc
+}
+
+# complicate recovery with an extra binlog file
+if ($case == 3)
+{
+ SET DEBUG_SYNC= "commit_before_get_LOCK_commit_ordered SIGNAL con1_ready WAIT_FOR con1_go";
+ --send_eval $query_to_crash
+ --connect (conn_client_3,127.0.0.1,root,,test,$SERVER_MYPORT_1,)
+ SET DEBUG_SYNC= "now WAIT_FOR con1_ready";
+ # use the same signal with $query_to_crash
+ SET DEBUG_SYNC= "commit_before_update_binlog_end_pos SIGNAL con3_ready WAIT_FOR con1_go";
+ --send_eval $query2_to_crash
+ --connection server_$server_to_crash
+ SET DEBUG_SYNC= "now WAIT_FOR con3_ready";
+ --source include/kill_mysqld.inc
+}
+
+--connection server_$server_to_promote
+--let $slave_param= Slave_SQL_Running_State
+--let $slave_param_value= Slave has read all relay log; waiting for more updates
+source include/wait_for_slave_param.inc;
+
+--error 2003
+--source include/stop_slave.inc
+
+--let $assert_cond= COUNT(*) = $expected_rows_on_slave FROM t1
+--let $assert_text= Table t1 should have $expected_rows_on_slave rows.
+--source include/assert.inc
+
+SELECT @@GLOBAL.gtid_current_pos;
+
+--let $restart_parameters=--skip-slave-start=1 --rpl-semi-sync-slave-enabled=1
+--let $allow_rpl_inited=1
+--source include/start_mysqld.inc
+--connection server_$server_to_crash
+--enable_reconnect
+--source include/wait_until_connected_again.inc
+
+--let $assert_cond= COUNT(*) = $expected_rows_on_master FROM t1
+--let $assert_text= Table t1 should have $expected_rows_on_master rows.
+--source include/assert.inc
+
+# Check error log for correct messages.
+let $log_error_ = $MYSQLTEST_VARDIR/log/mysqld.$server_to_crash.err;
+--let SEARCH_FILE=$log_error_
+--let SEARCH_PATTERN=$log_search_pattern
+--source include/search_pattern_in_file.inc
+
+--disconnect conn_client
+
+#
+# FAIL OVER now to new master
+#
+--connection server_$server_to_promote
+set global rpl_semi_sync_master_enabled = 1;
+set global rpl_semi_sync_master_wait_point=AFTER_SYNC;
+
+--connection server_$server_to_crash
+--let $master_port=$SERVER_MYPORT_2
+if (`select $server_to_crash = 2`)
+{
+ --let $master_port=$SERVER_MYPORT_1
+}
+evalp CHANGE MASTER TO master_host='127.0.0.1', master_port=$new_master_port, master_user='root', master_use_gtid=SLAVE_POS;
+set global rpl_semi_sync_slave_enabled = 1;
+set @@global.gtid_slave_pos=@@global.gtid_binlog_pos;
+--source include/start_slave.inc
diff --git a/mysql-test/suite/rpl/t/rpl_semi_sync_event-master.opt b/mysql-test/suite/rpl/t/rpl_semi_sync_event-master.opt
new file mode 100644
index 00000000..4cfb5d53
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_semi_sync_event-master.opt
@@ -0,0 +1 @@
+--max-connections=40
diff --git a/mysql-test/suite/rpl/t/rpl_semi_sync_event.test b/mysql-test/suite/rpl/t/rpl_semi_sync_event.test
new file mode 100644
index 00000000..d4df9b40
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_semi_sync_event.test
@@ -0,0 +1,91 @@
+source include/no_valgrind_without_big.inc;
+source include/not_embedded.inc;
+source include/have_innodb.inc;
+source include/master-slave.inc;
+
+let $engine_type= InnoDB;
+
+# Suppress warnings that might be generated during the test
+connection master;
+call mtr.add_suppression("Timeout waiting for reply of binlog");
+call mtr.add_suppression("Semi-sync master .* waiting for slave reply");
+call mtr.add_suppression("Read semi-sync reply");
+call mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT.");
+call mtr.add_suppression("mysqld: Got an error reading communication packets");
+
+connection slave;
+call mtr.add_suppression("Master server does not support semi-sync");
+call mtr.add_suppression("Semi-sync slave .* reply");
+call mtr.add_suppression("Slave SQL.*Request to stop slave SQL Thread received while applying a group that has non-transactional changes; waiting for completion of the group");
+
+connection master;
+set global rpl_semi_sync_master_enabled = 1;
+
+connection slave;
+source include/stop_slave.inc;
+set global rpl_semi_sync_slave_enabled = 1;
+
+source include/start_slave.inc;
+
+connection master;
+SET GLOBAL event_scheduler = ON;
+
+replace_result $engine_type ENGINE_TYPE;
+eval CREATE TABLE t1 (i INT NOT NULL AUTO_INCREMENT PRIMARY KEY, f varchar(8)) ENGINE=$engine_type;
+INSERT INTO t1 (f) VALUES ('a'),('a'),('a'),('a'),('a');
+--disable_warnings
+INSERT INTO t1 SELECT i+5, f FROM t1;
+INSERT INTO t1 SELECT i+10, f FROM t1;
+--enable_warnings
+CREATE EVENT ev1 ON SCHEDULE EVERY 1 SECOND
+DO INSERT INTO t1 VALUES (SLEEP(5),CONCAT('ev1_',CONNECTION_ID()));
+CREATE EVENT ev2 ON SCHEDULE EVERY 1 SECOND
+DO INSERT INTO t1 VALUES (SLEEP(5),CONCAT('ev2_',CONNECTION_ID()));
+
+connection slave;
+STOP SLAVE IO_THREAD;
+
+connection master;
+let $run = 20;
+while ($run)
+{
+ connect (m$run,localhost,root,,);
+ connection m$run;
+ send;
+ eval UPDATE t1 SET f = CONCAT('up_',CONNECTION_ID()) WHERE i = $run;
+ connection master;
+ dec $run;
+}
+
+connection master;
+SET GLOBAL event_scheduler = OFF;
+
+let $run = 20;
+while ($run)
+{
+ connection m$run;
+ reap;
+ disconnect m$run;
+ dec $run;
+}
+
+#
+# Clean up
+#
+connection slave;
+source include/stop_slave.inc;
+set global rpl_semi_sync_slave_enabled = 0;
+
+connection master;
+set global rpl_semi_sync_master_enabled = 0;
+
+connection slave;
+source include/start_slave.inc;
+
+connection master;
+
+DROP EVENT ev1;
+DROP EVENT ev2;
+DROP TABLE t1;
+sync_slave_with_master;
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_semi_sync_event_after_sync-master.opt b/mysql-test/suite/rpl/t/rpl_semi_sync_event_after_sync-master.opt
new file mode 100644
index 00000000..4cfb5d53
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_semi_sync_event_after_sync-master.opt
@@ -0,0 +1 @@
+--max-connections=40
diff --git a/mysql-test/suite/rpl/t/rpl_semi_sync_event_after_sync.test b/mysql-test/suite/rpl/t/rpl_semi_sync_event_after_sync.test
new file mode 100644
index 00000000..527900fd
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_semi_sync_event_after_sync.test
@@ -0,0 +1,3 @@
+set global rpl_semi_sync_master_wait_point=AFTER_SYNC;
+source rpl_semi_sync_event.test;
+set global rpl_semi_sync_master_wait_point=default;
diff --git a/mysql-test/suite/rpl/t/rpl_semi_sync_fail_over.cnf b/mysql-test/suite/rpl/t/rpl_semi_sync_fail_over.cnf
new file mode 100644
index 00000000..8c5e6362
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_semi_sync_fail_over.cnf
@@ -0,0 +1,13 @@
+!include suite/rpl/rpl_1slave_base.cnf
+!include include/default_client.cnf
+
+
+[mysqld.1]
+log-slave-updates
+gtid-strict-mode=1
+sync-binlog=1
+
+[mysqld.2]
+log-slave-updates
+gtid-strict-mode=1
+sync-binlog=1
diff --git a/mysql-test/suite/rpl/t/rpl_semi_sync_fail_over.test b/mysql-test/suite/rpl/t/rpl_semi_sync_fail_over.test
new file mode 100644
index 00000000..6a691ae0
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_semi_sync_fail_over.test
@@ -0,0 +1,221 @@
+# ==== References ====
+#
+# MDEV-21117 recovery for --rpl-semi-sync-slave-enabled server
+# MDEV-27760 event may non stop replicate in circular semisync setup
+#
+
+--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/master-slave.inc
+
+# Initial slave
+--connection server_2
+--source include/stop_slave.inc
+
+# Initial master
+--connection server_1
+RESET MASTER;
+SET @@global.max_binlog_size= 4096;
+
+--connection server_2
+RESET MASTER;
+SET @@global.max_binlog_size= 4096;
+set @@global.rpl_semi_sync_slave_enabled = 1;
+set @@global.gtid_slave_pos = "";
+CHANGE MASTER TO master_use_gtid= slave_pos;
+--source include/start_slave.inc
+
+--connection server_1
+ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
+set @@global.rpl_semi_sync_master_enabled = 1;
+set @@global.rpl_semi_sync_master_wait_point=AFTER_SYNC;
+
+CREATE TABLE t1 (a INT PRIMARY KEY, b MEDIUMTEXT) ENGINE=Innodb;
+INSERT INTO t1 VALUES (1, 'dummy1');
+--save_master_pos
+
+--connection server_2
+--sync_with_master
+
+--connection server_1
+--let $case = 1
+--echo #
+--echo # Case:$case
+--echo #
+--echo # CRASH the original master, and FAILOVER to the new
+# value 1 for server id 1 -> 2 failover
+--let $failover_to_slave=1
+--let $query_to_crash= INSERT INTO t1 VALUES (2, REPEAT("x", 4100))
+--echo # $query_to_crash
+--echo # Row - 2 will be in master's binlog but not committed, gets replicated
+--echo # to slave and applied. On crash master should have 1 row and slave
+--echo # should have 2 rows.
+--echo #
+--echo # Expected State post crash:
+--echo #=================================================================
+--echo # Master | Slave |
+--echo # 0-1-4 (Not committed) | 0-1-4 (Received through semi-sync |
+--echo # | replication and applied) |
+--echo #=================================================================
+--let $log_search_pattern=truncated binlog file:.*master.*000001
+--let $expected_rows_on_master= 1
+--let $expected_rows_on_slave= 2
+--source rpl_semi_sync_crash.inc
+
+--echo #
+--echo # Server_2 promoted as master will send 0-1-4 to new slave Server_1
+--echo #
+--connection server_2
+--let $rows_so_far=3
+--eval INSERT INTO t1 VALUES ($rows_so_far, 'dummy3')
+--save_master_pos
+--echo # The gtid state on current master must be equal to ...
+SHOW VARIABLES LIKE 'gtid_binlog_pos';
+SHOW VARIABLES LIKE 'gtid_binlog_state';
+SHOW VARIABLES LIKE 'gtid_slave_pos';
+
+--connection server_1
+--sync_with_master
+--eval SELECT COUNT(*) = $rows_so_far as 'true' FROM t1
+--echo # ... the gtid states on the slave:
+SHOW VARIABLES LIKE 'gtid_slave_pos';
+SHOW VARIABLES LIKE 'gtid_binlog_pos';
+SHOW VARIABLES LIKE 'gtid_binlog_state';
+
+--connection server_2
+--let $case = 2
+--echo #
+--echo # Case:$case
+--echo #
+--echo # CRASH the new master, and FAILOVER back to the original
+# value 0 for the reverse server id 2 -> 1 failover
+--let $failover_to_slave=0
+# Additionally through "foreign" server_id verify MDEV-27760's acceptance
+# policy on the recient (to be promoted into master) server.
+--let $query_to_crash = SET STATEMENT server_id=1 FOR INSERT INTO t1 VALUES (4, REPEAT("x", 4100))
+--let $query2_to_crash= INSERT INTO t1 VALUES (5, REPEAT("x", 4100))
+--echo # $query_to_crash
+--echo # $query2_to_crash
+--echo # Rows 4 and 5 will be in master's binlog but not committed, they get
+--echo # replicated to slave and applied. On crash master should have 3 rows
+--echo # and slave should have 5 rows.
+--echo #
+--echo # Expected State post crash:
+--echo #=================================================================
+--echo # Master | Slave |
+--echo # 0-1-6 (Not commited) | 0-1-6 (Received through semi-sync |
+--echo # | replication and applied) |
+--echo # 0-2-7 (Not commited) | 0-2-7 (Received through semi-sync |
+--echo # | replication and applied) |
+--echo #=================================================================
+--let $log_search_pattern=truncated binlog file:.*slave.*000002.* to remove transactions starting from GTID 0-1-6
+--let $expected_rows_on_master= 3
+--let $expected_rows_on_slave= 5
+--source rpl_semi_sync_crash.inc
+
+--echo #
+--echo # Server_1 promoted as master will send 0-1-6 and 0-2-7 to slave Server_2
+--echo #
+--connection server_1
+--let $rows_so_far=6
+--eval INSERT INTO t1 VALUES ($rows_so_far, 'dummy6')
+--save_master_pos
+--echo # The gtid state on current master must be equal to ...
+SHOW VARIABLES LIKE 'gtid_binlog_pos';
+SHOW VARIABLES LIKE 'gtid_binlog_state';
+SHOW VARIABLES LIKE 'gtid_slave_pos';
+
+--connection server_2
+--sync_with_master
+--eval SELECT COUNT(*) = $rows_so_far as 'true' FROM t1
+--echo # ... the gtid states on the slave:
+SHOW VARIABLES LIKE 'gtid_slave_pos';
+SHOW VARIABLES LIKE 'gtid_binlog_pos';
+SHOW VARIABLES LIKE 'gtid_binlog_state';
+
+--let $diff_tables=server_1:t1, server_2:t1
+--source include/diff_tables.inc
+
+--connection server_1
+--let $case = 3
+--echo #
+--echo # Case:$case
+--echo #
+--echo # CRASH the master and FAILOVER to slave
+--let $failover_to_slave=1
+--let $query_to_crash = INSERT INTO t1 VALUES (7, REPEAT("x", 4100))
+--let $query2_to_crash= INSERT INTO t1 VALUES (8, REPEAT("x", 4100))
+--echo # $query_to_crash
+--echo # $query2_to_crash
+--echo # Rows 7 and 8 will be in master's binlog but not committed, only 7
+--echo # gets replicated to slave and applied. On crash master should have 6
+--echo # rows and slave should have 7 rows.
+--echo #
+--echo # Expected State post crash:
+--echo #=================================================================
+--echo # Master | Slave |
+--echo # 0-1-9 (Not commited) | 0-1-9 (Received through semi-sync |
+--echo # | replication and applied) |
+--echo # 0-1-10 (Not commited - | |
+--echo # never sent to slave) | |
+--echo #=================================================================
+--let $log_search_pattern=truncated binlog file:.*master.*000002.* to remove transactions starting from GTID 0-1-9
+--let $expected_rows_on_master= 6
+--let $expected_rows_on_slave= 7
+--source rpl_semi_sync_crash.inc
+
+--echo #
+--echo # Server_2 promoted as master will send 0-1-9 to slave Server_1
+--echo #
+--connection server_2
+--let $rows_so_far=8
+--eval INSERT INTO t1 VALUES ($rows_so_far, 'Done')
+--source include/save_master_gtid.inc
+--echo # The gtid state on current master must be equal to ...
+SHOW VARIABLES LIKE 'gtid_binlog_pos';
+SHOW VARIABLES LIKE 'gtid_binlog_state';
+SHOW VARIABLES LIKE 'gtid_slave_pos';
+
+--connection server_1
+--source include/sync_with_master_gtid.inc
+--eval SELECT COUNT(*) = $rows_so_far as 'true' FROM t1
+--echo # ... the gtid states on the slave:
+SHOW VARIABLES LIKE 'gtid_slave_pos';
+SHOW VARIABLES LIKE 'gtid_binlog_pos';
+SHOW VARIABLES LIKE 'gtid_binlog_state';
+
+--echo #
+--echo # Cleanup
+--echo #
+
+--source include/stop_slave.inc
+set global rpl_semi_sync_slave_enabled = 0;
+set global rpl_semi_sync_master_enabled = 0;
+set global rpl_semi_sync_master_wait_point=default;
+RESET MASTER;
+RESET SLAVE;
+
+--connection server_2
+RESET MASTER;
+RESET SLAVE;
+set @@global.rpl_semi_sync_master_enabled = 0;
+set @@global.rpl_semi_sync_slave_enabled = 0;
+set @@global.rpl_semi_sync_master_wait_point=default;
+evalp CHANGE MASTER TO master_host='127.0.0.1', master_port=$SERVER_MYPORT_1, master_user='root', master_use_gtid=SLAVE_POS;
+set @@global.gtid_slave_pos=@@global.gtid_binlog_pos;
+--source include/start_slave.inc
+
+--connection server_1
+DROP TABLE t1;
+--save_master_pos
+
+--connection server_2
+--sync_with_master
+
+connection default;
+--enable_reconnect
+--source include/wait_until_connected_again.inc
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_semi_sync_gtid_reconnect.test b/mysql-test/suite/rpl/t/rpl_semi_sync_gtid_reconnect.test
new file mode 100644
index 00000000..96f7e805
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_semi_sync_gtid_reconnect.test
@@ -0,0 +1,74 @@
+source include/not_embedded.inc;
+source include/have_binlog_format_mixed.inc;
+source include/master-slave.inc;
+
+#
+# Semisync initialization
+#
+--connection master
+RESET MASTER;
+--let $sav_enabled_master=`SELECT @@GLOBAL.rpl_semi_sync_master_enabled`
+SET @@GLOBAL.rpl_semi_sync_master_enabled = 1;
+
+--connection slave
+source include/stop_slave.inc;
+--let $sav_enabled_slave=`SELECT @@GLOBAL.rpl_semi_sync_slave_enabled`
+SET @@GLOBAL. rpl_semi_sync_slave_enabled = 1;
+source include/start_slave.inc;
+
+# Prove fixes to
+# MDEV-19376 Assert (!m_active_tranxs->is_tranx_end_pos(trx_wait_binlog_name...)
+#
+#
+# Run few queries to replicate/execute on slave.
+# Stop the slave applier.
+# Replicate/not-executed few more.
+# Restart the slave.
+#
+--connection master
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 SET a = 1;
+--source include/save_master_gtid.inc
+--let $resume_gtid = $master_pos
+FLUSH LOGS;
+INSERT INTO t1 SET a = 2;
+
+--sync_slave_with_master
+--connection slave
+--source include/stop_slave_sql.inc
+
+--connection master
+INSERT INTO t1 SET a = 3;
+
+# the sync connection is 'slave' by default
+--source include/sync_slave_io_with_master.inc
+--connection slave
+--source include/stop_slave_io.inc
+
+--connection master
+RESET MASTER;
+--eval SET @@global.gtid_binlog_state = '$resume_gtid'
+
+# The resume gtid is set up to point to the very first binlog file
+--connection slave
+CHANGE MASTER TO MASTER_USE_GTID = slave_pos;
+--eval SET @@global.gtid_slave_pos = '$resume_gtid'
+# Yet the slave io first submits the last received binlog file name:pos.
+--source include/start_slave.inc
+
+# Here goes the cracker.
+--connection master
+INSERT INTO t1 SET a = 4;
+
+#
+# Clean up
+#
+--connection master
+DROP TABLE t1;
+--eval SET @@GLOBAL. rpl_semi_sync_master_enabled = $sav_enabled_master
+
+--sync_slave_with_master
+source include/stop_slave.inc;
+--eval SET @@GLOBAL. rpl_semi_sync_slave_enabled = $sav_enabled_slave
+source include/start_slave.inc;
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_semi_sync_master_shutdown.test b/mysql-test/suite/rpl/t/rpl_semi_sync_master_shutdown.test
new file mode 100644
index 00000000..2224f78d
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_semi_sync_master_shutdown.test
@@ -0,0 +1,60 @@
+# MDEV-16812 Semisync slave io thread segfaults at STOP-SLAVE handling
+#
+# The test verifies that the semisync-enabled slave io thread
+# finishes off as specified in particular trying to connect even to a shut down
+# master for a semisync firewell routine.
+
+source include/not_embedded.inc;
+source include/have_debug.inc;
+source include/master-slave.inc;
+
+--connection master
+
+--let $sav_enabled_master=`SELECT @@GLOBAL.rpl_semi_sync_master_enabled `
+SET @@GLOBAL.rpl_semi_sync_master_enabled = 1;
+
+--connection slave
+source include/stop_slave.inc;
+--let $sav_enabled_slave=`SELECT @@GLOBAL.rpl_semi_sync_slave_enabled `
+SET @@GLOBAL. rpl_semi_sync_slave_enabled = 1;
+source include/start_slave.inc;
+
+--connection master
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 SET a=1;
+
+--sync_slave_with_master
+
+connection master;
+--echo # Shutdown master
+--let $rpl_server_number=1
+source include/rpl_stop_server.inc;
+
+--connection slave
+--source include/stop_slave.inc
+
+#connection master;
+--echo # Restart master
+--let $rpl_server_number=1
+source include/rpl_start_server.inc;
+
+#
+# Clean up
+#
+--connection slave
+--source include/stop_slave.inc
+--source include/start_slave.inc
+
+--connection master
+SET @@GLOBAL.debug_dbug="";
+--eval SET @@GLOBAL. rpl_semi_sync_master_enabled = $sav_enabled_master
+
+--connection master
+DROP TABLE t1;
+
+--sync_slave_with_master
+source include/stop_slave.inc;
+--eval SET @@GLOBAL. rpl_semi_sync_slave_enabled = $sav_enabled_slave
+
+--let $rpl_only_running_threads= 1
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_semi_sync_shutdown_await_ack.cnf b/mysql-test/suite/rpl/t/rpl_semi_sync_shutdown_await_ack.cnf
new file mode 100644
index 00000000..2cf1b178
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_semi_sync_shutdown_await_ack.cnf
@@ -0,0 +1,14 @@
+!include ../my.cnf
+
+[mysqld.1]
+log_warnings=9
+
+[mysqld.2]
+log_warnings=9
+
+[mysqld.3]
+log_warnings=9
+
+[ENV]
+SERVER_MYPORT_3= @mysqld.3.port
+SERVER_MYSOCK_3= @mysqld.3.socket
diff --git a/mysql-test/suite/rpl/t/rpl_semi_sync_shutdown_await_ack.inc b/mysql-test/suite/rpl/t/rpl_semi_sync_shutdown_await_ack.inc
new file mode 100644
index 00000000..a232f685
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_semi_sync_shutdown_await_ack.inc
@@ -0,0 +1,163 @@
+#
+# Helper file to ensure that a primary waits for all ACKS (or timeout) from its
+# replicas before shutting down.
+#
+# Parameters:
+# server_1_dbug (string) Debug setting for primary (server 1)
+# server_2_dbug (string) Debug setting to simulate delay or error on
+# the first replica (server 2)
+# server_3_dbug (string) Debug setting to simulate delay or error on
+# the second replica (server 3)
+# semisync_timeout (int) Rpl_semi_sync_master_timeout to use
+# server_2_expect_row_count (int) The number of rows expected on the first
+# replica after the shutdown
+# server_3_expect_row_count (int) The number of rows expected on the second
+# replica after the shutdown
+#
+
+--connection server_1
+let $log_error_file= `SELECT @@GLOBAL.log_error`;
+
+--echo #--
+--echo #-- Semi-sync Setup
+
+--connection server_1
+--save_master_pos
+
+echo #-- Enable semi-sync on slaves
+let slave_last= 3;
+--let i= 2
+while (`SELECT $i <= $slave_last`)
+{
+ --connection server_$i
+ --sync_with_master
+
+ set global rpl_semi_sync_slave_enabled = 1;
+ source include/stop_slave.inc;
+ source include/start_slave.inc;
+ show status like 'Rpl_semi_sync_slave_status';
+
+ --inc $i
+}
+
+--echo #-- Enable semi-sync on master
+--connection server_1
+SET @@GLOBAL.rpl_semi_sync_master_enabled = 1;
+--eval set @@global.rpl_semi_sync_master_timeout= $semisync_timeout
+
+--echo #-- Wait for master to recognize semi-sync slaves
+--connection server_1
+let $status_var= Rpl_semi_sync_master_clients;
+let $status_var_value= 2;
+source include/wait_for_status_var.inc;
+
+--echo #-- Master should have semi-sync enabled with 2 connections
+show status like 'Rpl_semi_sync_master_status';
+show status like 'Rpl_semi_sync_master_clients';
+
+--echo #-- Prepare servers to simulate delay or error
+--connection server_1
+--eval SET @@GLOBAL.debug_dbug= $server_1_dbug
+--connection server_2
+--eval SET @@GLOBAL.debug_dbug= $server_2_dbug
+--connection server_3
+--eval SET @@GLOBAL.debug_dbug= $server_3_dbug
+
+--echo #--
+--echo #-- Test begins
+
+--connection server_1
+--echo #-- Begin semi-sync transaction
+--send INSERT INTO t1 VALUES (1)
+
+--connection server_1_con2
+--echo #-- Wait until master recognizes a connection is awaiting semi-sync ACK
+let $status_var= Rpl_semi_sync_master_wait_sessions;
+let $status_var_value= 1;
+source include/wait_for_status_var.inc;
+show status like 'Rpl_semi_sync_master_wait_sessions';
+
+--write_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
+wait
+EOF
+
+--echo #-- Give enough time after timeout/ack received to query yes_tx/no_tx
+SET @@GLOBAL.debug_dbug= "+d,delay_shutdown_phase_2_after_semisync_wait";
+
+--echo #-- Begin master shutdown
+--send SHUTDOWN WAIT FOR ALL SLAVES
+
+--connection server_1
+--reap
+--echo #-- Ensure either ACK was received (yes_tx=1) or timeout (no_tx=1)
+show status like 'Rpl_semi_sync_master_yes_tx';
+show status like 'Rpl_semi_sync_master_no_tx';
+
+--connection server_1_con2
+--reap
+--source include/wait_until_disconnected.inc
+
+--echo # Check logs to ensure shutdown was delayed
+--let SEARCH_FILE=$log_error_file
+--let SEARCH_PATTERN=Delaying shutdown to await semi-sync ACK
+--source include/search_pattern_in_file.inc
+
+--echo # Validate slave data is in correct state
+--connection server_2
+--eval select count(*)=$server_2_expect_row_count from t1
+--connection server_3
+--eval select count(*)=$server_3_expect_row_count from t1
+
+--echo #
+--echo #-- Re-synchronize slaves with master and disable semi-sync
+
+--echo #-- Stop slaves
+
+--connection server_2
+--eval SET @@GLOBAL.debug_dbug= "$sav_server_2_dbug"
+--eval SET @@GLOBAL.rpl_semi_sync_slave_enabled= 0
+source include/stop_slave.inc;
+
+--connection server_3
+--eval SET @@GLOBAL.debug_dbug= "$sav_server_3_dbug"
+--eval SET @@GLOBAL.rpl_semi_sync_slave_enabled= 0
+source include/stop_slave.inc;
+
+--echo #-- Bring the master back up
+--connection server_1_con2
+--append_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
+restart
+EOF
+
+--enable_reconnect
+--source include/wait_until_connected_again.inc
+
+--connection default
+--enable_reconnect
+--source include/wait_until_connected_again.inc
+
+--connection server_1
+--enable_reconnect
+--source include/wait_until_connected_again.inc
+
+--eval SET @@GLOBAL.debug_dbug= "$sav_master_dbug"
+let $status_var= Rpl_semi_sync_master_clients;
+let $status_var_value= 0;
+source include/wait_for_status_var.inc;
+--eval SET @@GLOBAL.rpl_semi_sync_master_enabled = 0
+show status like 'Rpl_semi_sync_master_status';
+
+TRUNCATE TABLE t1;
+--save_master_pos
+
+--echo #-- Bring slaves back up
+--let i= 2
+while (`SELECT $i <= $slave_last`)
+{
+ --connection server_$i
+ source include/start_slave.inc;
+ show status like 'Rpl_semi_sync_slave_status';
+ --sync_with_master
+ SELECT COUNT(*)=0 from t1;
+ --inc $i
+}
diff --git a/mysql-test/suite/rpl/t/rpl_semi_sync_shutdown_await_ack.test b/mysql-test/suite/rpl/t/rpl_semi_sync_shutdown_await_ack.test
new file mode 100644
index 00000000..6c088c57
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_semi_sync_shutdown_await_ack.test
@@ -0,0 +1,217 @@
+--source include/no_valgrind_without_big.inc
+
+#
+# Purpose:
+# This test validates that data is consistent between a primary and replica
+# in semi-sync mode when the primary is issued `SHUTDOWN WAIT FOR SLAVES`
+# during an active communication. More specifically, the primary should not
+# kill the connection until it is sure a replica has received all binlog
+# data, i.e. once the primary receives the ACK. If a primary is issued a
+# shutdown before receiving an ACK, it should wait until either 1) the ACK is
+# received, or 2) the configured timeout (rpl_semi_sync_master_timeout) is
+# reached.
+#
+# Methodology:
+# Using a topology consisting of one primary with two replicas, all in
+# semi-sync mode, we use DEBUG_DBUG to simulate an error or delay on the
+# replicas during an active communication while the primary is issued
+# `SHUTDOWN WAIT FOR SLAVES`. We create four test cases to ensure the primary
+# will correctly wait for the communication to finish, and use the semi-sync
+# status variables Rpl_semi_sync_master_yes_tx and Rpl_semi_sync_master_no_tx
+# to ensure the connection was not prematurely killed due to the shutdown.
+# Test Case 1) If both replicas simulate a delay that is within the allowed
+# timeout, the primary should delay killing the suspended thread
+# until an ACK is received (Rpl_semi_sync_master_yes_tx should
+# be 1).
+# Test Case 2) If both replicas simulate an error before sending an ACK, the
+# primary should delay killing the suspended thread until the
+# the timeout is reached (Rpl_semi_sync_master_no_tx should be
+# 1).
+# Test Case 3) If one replica simulates a delay within the allowed timeout
+# and the other simulates an error before sending an ACK, the
+# primary should delay killing the suspended thread until it
+# receives an ACK from the delayed slave
+# (Rpl_semi_sync_master_yes_tx should be 1).
+# Test Case 4) If a replica errors before sending an ACK, it will cause the
+# IO thread to stop and handle the error. During error handling,
+# if semi-sync is active, the replica will form a new connection
+# with the primary to kill the active connection. However, if
+# the primary is shutting down, it may kill the new connection,
+# thereby leaving the active semi-sync connection in-tact. The
+# slave should notice this, and not issue a `QUIT` command to
+# the primary, which would otherwise be sent to kill an active
+# connection. This test case validates that the slave does not
+# send a `QUIT` in this case (Rpl_semi_sync_master_yes_tx should
+# be 1 because server_3 will send the ACK within a valid
+# timeout).
+#
+# References:
+# MDEV-11853: semisync thread can be killed after sync binlog but before ACK
+# in the sync state
+# MDEV-28114: Semi-sync Master ACK Receiver Thread Can Error on COM_QUIT
+#
+
+--echo #############################
+--echo # Common setup for all tests
+--echo #############################
+
+--echo # Note: Simulated slave delay is hardcoded to 800 milliseconds
+--echo # Note: Simulated master shutdown delay is hardcoded to 500 milliseconds
+
+--source include/have_debug.inc
+--let $rpl_topology=1->2, 1->3
+--source include/rpl_init.inc
+
+--connection server_1
+
+--echo # Slaves which simulate an error will produce a timeout on the primary
+call mtr.add_suppression("Timeout waiting");
+call mtr.add_suppression("did not exit");
+call mtr.add_suppression("Got an error reading communication packets");
+
+--let $sav_master_timeout= `SELECT @@global.rpl_semi_sync_master_timeout`
+--let $sav_enabled_master= `SELECT @@GLOBAL.rpl_semi_sync_master_enabled`
+--let $sav_master_dbug= `SELECT @@GLOBAL.debug_dbug`
+
+--echo # Suppress slave errors related to the simulated error
+--connection server_2
+call mtr.add_suppression("reply failed");
+call mtr.add_suppression("Replication event checksum verification");
+call mtr.add_suppression("Relay log write failure");
+call mtr.add_suppression("Failed to kill the active semi-sync connection");
+--let $sav_enabled_server_2=`SELECT @@GLOBAL.rpl_semi_sync_slave_enabled`
+--let $sav_server_2_dbug= `SELECT @@GLOBAL.debug_dbug`
+
+--connection server_3
+call mtr.add_suppression("reply failed");
+call mtr.add_suppression("Replication event checksum verification");
+call mtr.add_suppression("Relay log write failure");
+call mtr.add_suppression("Failed to kill the active semi-sync connection");
+--let $sav_enabled_server_3=`SELECT @@GLOBAL.rpl_semi_sync_slave_enabled`
+--let $sav_server_3_dbug= `SELECT @@GLOBAL.debug_dbug`
+
+--connection server_1
+CREATE TABLE t1 (a int);
+--save_master_pos
+
+--let i= 2
+--let slave_last= 3
+while (`SELECT $i <= $slave_last`)
+{
+ --connection server_$i
+ --sync_with_master
+ --inc $i
+}
+
+# Set up the connection used to issue the shutdown
+--connect(server_1_con2, localhost, root,,)
+
+
+--echo #############################
+--echo # Test cases
+--echo #############################
+
+--echo #
+--echo # Test Case 1) If both replicas simulate a delay that is within the
+--echo # allowed timeout, the primary should delay killing the suspended thread
+--echo # until an ACK is received (Rpl_semi_sync_master_yes_tx should be 1).
+--echo #
+--let server_1_dbug= ""
+--let server_2_dbug= "+d,simulate_delay_semisync_slave_reply"
+--let server_3_dbug= "+d,simulate_delay_semisync_slave_reply"
+--let semisync_timeout= 1600
+--let server_2_expect_row_count= 1
+--let server_3_expect_row_count= 1
+--source rpl_semi_sync_shutdown_await_ack.inc
+
+--echo #
+--echo # Test Case 2) If both replicas simulate an error before sending an ACK,
+--echo # the primary should delay killing the suspended thread until the
+--echo # timeout is reached (Rpl_semi_sync_master_no_tx should be 1).
+--echo #
+--let server_1_dbug= "+d,mysqld_delay_kill_threads_phase_1"
+--let server_2_dbug= "+d,corrupt_queue_event"
+--let server_3_dbug= "+d,corrupt_queue_event"
+--let semisync_timeout= 500
+--let server_2_expect_row_count= 0
+--let server_3_expect_row_count= 0
+--source rpl_semi_sync_shutdown_await_ack.inc
+
+--echo #
+--echo # Test Case 3) If one replica simulates a delay within the allowed
+--echo # timeout and the other simulates an error before sending an ACK, the
+--echo # primary should delay killing the suspended thread until it receives an
+--echo # ACK from the delayed slave (Rpl_semi_sync_master_yes_tx should be 1).
+--echo #
+--let server_1_dbug= "+d,mysqld_delay_kill_threads_phase_1"
+--let server_2_dbug= "+d,corrupt_queue_event"
+--let server_3_dbug= "+d,simulate_delay_semisync_slave_reply"
+--let semisync_timeout= 1600
+--let server_2_expect_row_count= 0
+--let server_3_expect_row_count= 1
+--source rpl_semi_sync_shutdown_await_ack.inc
+
+--echo #
+--echo # Test Case 4) If a replica errors before sending an ACK, it will cause
+--echo # the IO thread to stop and handle the error. During error handling, if
+--echo # semi-sync is active, the replica will form a new connection with the
+--echo # primary to kill the active connection. However, if the primary is
+--echo # shutting down, it may kill the new connection, thereby leaving the
+--echo # active semi-sync connection in-tact. The slave should notice this, and
+--echo # not issue a `QUIT` command to the primary, which would otherwise be
+--echo # sent to kill an active connection. This test case validates that the
+--echo # slave does not send a `QUIT` in this case (Rpl_semi_sync_master_yes_tx
+--echo # should be 1 because server_3 will send the ACK within a valid timeout).
+--echo #
+
+# mysqld_delay_kill_threads_phase1 ensures that server_2 will have enough time
+# to start a new connection that has the intent to kill the active semi-sync
+# connection
+--let server_1_dbug= "+d,mysqld_delay_kill_threads_phase_1"
+
+# slave_delay_killing_semisync_connection ensures that the primary has force
+# killed its current connection before it is able to issue `KILL`
+--let server_2_dbug= "+d,corrupt_queue_event,slave_delay_killing_semisync_connection"
+--let server_3_dbug= "+d,simulate_delay_semisync_slave_reply"
+--let semisync_timeout= 1600
+--let server_2_expect_row_count= 0
+--let server_3_expect_row_count= 1
+--source rpl_semi_sync_shutdown_await_ack.inc
+
+--echo #############################
+--echo # Cleanup
+--echo #############################
+
+--connection server_2
+source include/stop_slave.inc;
+source include/start_slave.inc;
+
+--disable_query_log
+--eval SET @@GLOBAL.rpl_semi_sync_slave_enabled = $sav_enabled_server_2
+--eval SET @@GLOBAL.debug_dbug= "$sav_server_2_dbug"
+--enable_query_log
+
+--connection server_3
+source include/stop_slave.inc;
+source include/start_slave.inc;
+
+--disable_query_log
+--eval SET @@GLOBAL.rpl_semi_sync_slave_enabled = $sav_enabled_server_3
+--eval SET @@GLOBAL.debug_dbug= "$sav_server_3_dbug"
+--enable_query_log
+
+
+--connection server_1
+let $status_var= Rpl_semi_sync_master_clients;
+let $status_var_value= 0;
+source include/wait_for_status_var.inc;
+
+--disable_query_log
+--eval SET @@GLOBAL.rpl_semi_sync_master_timeout= $sav_master_timeout
+--eval SET @@GLOBAL.rpl_semi_sync_master_enabled= $sav_enabled_master
+--eval SET @@GLOBAL.debug_dbug= "$sav_master_dbug"
+--enable_query_log
+
+drop table t1;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_semi_sync_skip_repl.test b/mysql-test/suite/rpl/t/rpl_semi_sync_skip_repl.test
new file mode 100644
index 00000000..587e1290
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_semi_sync_skip_repl.test
@@ -0,0 +1,66 @@
+# MDEV-14721 Big transaction events get lost on semisync master when
+# replicate_events_marked_for_skip=FILTER_ON_MASTER
+#
+# When events of a big transaction are binlogged offsetting over 2GB from
+# the beginning of the log the semisync master's dump thread
+# lost such events.
+# The test verifies the fixes' correctness simulating the 2GB offset.
+
+source include/not_embedded.inc;
+source include/have_innodb.inc;
+source include/have_debug.inc;
+source include/master-slave.inc;
+
+--connection master
+# Suppress warnings that might be generated during the test
+call mtr.add_suppression("Timeout waiting for reply of binlog");
+
+--let $sav_enabled_master=`SELECT @@GLOBAL.rpl_semi_sync_master_enabled`
+--let $sav_timeout_master=`SELECT @@GLOBAL.rpl_semi_sync_master_timeout`
+SET @@GLOBAL.rpl_semi_sync_master_enabled = 1;
+SET @@GLOBAL.rpl_semi_sync_master_timeout=100;
+
+--connection slave
+--let $sav_skip_marked_slave=`SELECT @@GLOBAL.replicate_events_marked_for_skip`
+--let $sav_enabled_slave=`SELECT @@GLOBAL.rpl_semi_sync_slave_enabled`
+source include/stop_slave.inc;
+SET @@GLOBAL.replicate_events_marked_for_skip=FILTER_ON_MASTER;
+SET @@GLOBAL.rpl_semi_sync_slave_enabled = 1;
+source include/start_slave.inc;
+
+--connection master
+CREATE TABLE t1 (a INT) ENGINE=innodb;
+
+# Make the following events as if they offset over 2GB from the beginning of binlog
+SET @saved_dbug = @@GLOBAL.debug_dbug;
+SET @@GLOBAL.debug_dbug="d,dbug_master_binlog_over_2GB";
+SET @@SESSION.skip_replication=1;
+INSERT INTO t1 SET a=1;
+SET @@SESSION.skip_replication=0;
+INSERT INTO t1 SET a=0;
+SET @@GLOBAL.debug_dbug="";
+
+# The current binlog is inconsistent so let's rotate it away
+# to clean up simulation results.
+FLUSH LOGS;
+
+--sync_slave_with_master
+
+#
+# Clean up
+#
+--connection master
+SET @@GLOBAL.debug_dbug = @saved_dbug;
+--eval SET @@GLOBAL.rpl_semi_sync_master_timeout = $sav_timeout_master
+--eval SET @@GLOBAL.rpl_semi_sync_master_enabled = $sav_enabled_master
+
+--connection master
+DROP TABLE t1;
+
+--sync_slave_with_master
+source include/stop_slave.inc;
+--eval SET @@GLOBAL.rpl_semi_sync_slave_enabled = $sav_enabled_slave
+--eval SET @@GLOBAL.replicate_events_marked_for_skip = $sav_skip_marked_slave
+
+source include/start_slave.inc;
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_semi_sync_slave_compressed_protocol-slave.opt b/mysql-test/suite/rpl/t/rpl_semi_sync_slave_compressed_protocol-slave.opt
new file mode 100644
index 00000000..a1b687d6
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_semi_sync_slave_compressed_protocol-slave.opt
@@ -0,0 +1 @@
+--slave_compressed_protocol
diff --git a/mysql-test/suite/rpl/t/rpl_semi_sync_slave_compressed_protocol.test b/mysql-test/suite/rpl/t/rpl_semi_sync_slave_compressed_protocol.test
new file mode 100644
index 00000000..bc05bec2
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_semi_sync_slave_compressed_protocol.test
@@ -0,0 +1,55 @@
+################################################################################
+# Bug#26027024 SLAVE_COMPRESSED_PROTOCOL DOESN'T WORK WITH SEMI-SYNC
+# REPLICATION IN MYSQL-5.7
+#
+# Steps to reproduce:
+# 1) Set slave_compressed_protocol ON on Slave.
+# 2) Do some sample work on Master
+# 3) After the work is synced on Slave, check that there is no error
+# (Read semi-sync reply magic number error) on Slave.
+# 4) Cleanup
+################################################################################
+# Test is independent of Binlog format. One of the three formats is enough
+# for testing. Choosing 'Row' format.
+--source include/have_binlog_format_row.inc
+--source include/master-slave.inc
+
+--let $sav_enabled_master=`SELECT @@GLOBAL.rpl_semi_sync_master_enabled `
+SET @@GLOBAL.rpl_semi_sync_master_enabled = 1;
+
+--connection slave
+source include/stop_slave.inc;
+--let $sav_enabled_slave=`SELECT @@GLOBAL.rpl_semi_sync_slave_enabled `
+SET @@GLOBAL.rpl_semi_sync_slave_enabled = 1;
+source include/start_slave.inc;
+
+--connection master
+# Do some sample work on Master with slave_compressed_protocol ON.
+# (slave_compressed_protocol is set to ON in -slave.opt file of this test.)
+CREATE TABLE t1 (i INT);
+DROP TABLE t1;
+
+# Make sure sync is done, so that next 'assert' step can be executed without
+# any issues.
+--source include/rpl_sync.inc
+
+# Without the fix, the test would have generated few
+# errors in the error log. With the fix, test will
+# pass without any errors in the error log.
+--let $assert_text= Check that there is no 'Read semi-sync reply magic number error' in error log.
+--let $assert_select=Read semi-sync reply magic number error
+--let $assert_file= $MYSQLTEST_VARDIR/log/mysqld.1.err
+--let $assert_count= 0
+--let $assert_only_after = CURRENT_TEST:rpl.rpl_semi_sync_slave_compressed_protocol.test
+--source include/assert_grep.inc
+
+--connection master
+--evalp SET @@GLOBAL. rpl_semi_sync_master_enabled = $sav_enabled_master
+
+--connection slave
+source include/stop_slave.inc;
+--evalp SET @@GLOBAL. rpl_semi_sync_slave_enabled = $sav_enabled_slave
+source include/start_slave.inc;
+
+# Cleanup
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_semi_sync_slave_reply_fail.test b/mysql-test/suite/rpl/t/rpl_semi_sync_slave_reply_fail.test
new file mode 100644
index 00000000..94853799
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_semi_sync_slave_reply_fail.test
@@ -0,0 +1,97 @@
+# ==== Purpose ====
+#
+# Test verifies that slave IO thread doesn't report an error, when slave fails
+# to send an acknowledgment to master with semi sync replication in use.
+#
+# ==== Implementation ====
+#
+# Steps:
+# 0 - Have semi synchronous replication in use.
+# 1 - Enable a debug simulation point which simulates network flush failure
+# at the time of slave reply operation.
+# 2 - Do some operation on master and wait for it to be replicated. Master
+# will timeout waiting for reply from slave.
+# 3 - Check the slave error log for appropriate error message regarding
+# net_flush operation failure.
+# 4 - Remove the debug simulation and do some more DML operations on master
+# and wait for them to be replicated.
+# 5 - Slave will be able to replicate and data is consistent on both master
+# and slave. Semi sync will be automatically turned on.
+#
+# ==== References ====
+#
+# MDEV-20217: Semi_sync: Last_IO_Error: Fatal error: Failed to run
+# 'after_queue_event' hook
+#
+--source include/have_debug.inc
+--source include/master-slave.inc
+
+--connection slave
+--source include/stop_slave.inc
+
+--connection master
+call mtr.add_suppression("Timeout waiting for reply of binlog*");
+--let $sav_timeout_master=`SELECT @@GLOBAL.rpl_semi_sync_master_timeout`
+set global rpl_semi_sync_master_enabled = ON;
+SET @@GLOBAL.rpl_semi_sync_master_timeout=100;
+create table t1 (i int);
+
+--connection slave
+set global rpl_semi_sync_slave_enabled = ON;
+CALL mtr.add_suppression("Semi-sync slave net_flush*");
+SET @save_debug= @@global.debug;
+SET GLOBAL debug_dbug="+d,semislave_failed_net_flush";
+--source include/start_slave.inc
+
+--connection master
+--sync_slave_with_master
+
+# 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.2.err;
+}
+--echo "Assert that the net_fulsh() reply failed is present in slave error log.
+--let SEARCH_FILE=$log_error_
+--let SEARCH_PATTERN=Semi-sync slave net_flush\(\) reply failed
+--source include/search_pattern_in_file.inc
+
+--echo "Assert that Slave IO thread is up and running."
+SHOW STATUS LIKE 'Slave_running';
+let $status= query_get_value("show slave status", Slave_IO_Running, 1);
+echo Slave_IO_Running= $status;
+
+--echo "Clear the network failure simulation."
+SET GLOBAL debug_dbug= @save_debug;
+
+--connection master
+insert into t1 values (10);
+--sync_slave_with_master
+
+--connection slave
+--echo # Compare the tables on master and slave.
+--let $diff_tables= master:t1, slave:t1
+--source include/diff_tables.inc
+
+--connection master
+set statement sql_log_bin=0 for call mtr.add_suppression("Read semi-sync reply magic number error");
+SET @save_debug_master= @@global.debug;
+SET GLOBAL debug_dbug="+d,semisync_corrupt_magic";
+insert into t1 values (11);
+
+--sync_slave_with_master
+
+--connection master
+SET GLOBAL debug_dbug= @save_debug_master;
+
+drop table t1;
+--sync_slave_with_master
+set global rpl_semi_sync_slave_enabled = OFF;
+
+--connection master
+set global rpl_semi_sync_master_enabled = OFF;
+--eval SET @@GLOBAL.rpl_semi_sync_master_timeout = $sav_timeout_master
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_semi_sync_wait_no_slave-master.opt b/mysql-test/suite/rpl/t/rpl_semi_sync_wait_no_slave-master.opt
new file mode 100644
index 00000000..d84ebab5
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_semi_sync_wait_no_slave-master.opt
@@ -0,0 +1 @@
+--rpl_semi_sync_master_enabled=0 --rpl_semi_sync_master_wait_no_slave=0
diff --git a/mysql-test/suite/rpl/t/rpl_semi_sync_wait_no_slave.test b/mysql-test/suite/rpl/t/rpl_semi_sync_wait_no_slave.test
new file mode 100644
index 00000000..fecd0e25
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_semi_sync_wait_no_slave.test
@@ -0,0 +1,14 @@
+# The test verifies master crash of MDEV-18096 when the server starts with
+# rpl_semi_sync_master_enabled = OFF rpl_semi_sync_master_wait_no_slave = OFF
+
+--source include/master-slave.inc
+--source include/have_binlog_format_mixed.inc
+
+--connection master
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 SET a=1;
+DROP TABLE t1;
+
+--sync_slave_with_master
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_semi_sync_wait_point.opt b/mysql-test/suite/rpl/t/rpl_semi_sync_wait_point.opt
new file mode 100644
index 00000000..e49ae455
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_semi_sync_wait_point.opt
@@ -0,0 +1 @@
+--log_bin
diff --git a/mysql-test/suite/rpl/t/rpl_semi_sync_wait_point.test b/mysql-test/suite/rpl/t/rpl_semi_sync_wait_point.test
new file mode 100644
index 00000000..5eae91a5
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_semi_sync_wait_point.test
@@ -0,0 +1,251 @@
+source include/not_embedded.inc;
+source include/have_innodb.inc;
+
+#
+# This test the rpl_semi_sync_master_wait_point functionality
+# and illustrates the differences between the two values AFTER_COMMIT and
+# AFTER_SYNC
+#
+
+--echo #
+--echo # Preparation
+--echo #
+
+CREATE TABLE t1 (i INT NOT NULL, PRIMARY KEY (i)) ENGINE=InnoDB;
+RESET MASTER;
+
+let $save_timeout = `select @@global.rpl_semi_sync_master_timeout`;
+let $save_wait_no_slave = `select @@global.rpl_semi_sync_master_wait_no_slave`;
+let $save_wait_point = `select @@global.rpl_semi_sync_master_wait_point`;
+
+SET @@global.rpl_semi_sync_master_timeout = 60000;
+SET @@global.rpl_semi_sync_master_wait_no_slave = 1;
+
+--echo # It's okay to see "Killed" but we should not see "Timeout" in the log.
+call mtr.add_suppression("Killed waiting for reply of binlog");
+
+--echo #
+--echo # Test wait point = AFTER_COMMIT
+--echo #
+SET @@global.rpl_semi_sync_master_wait_point = AFTER_COMMIT;
+
+--echo # Make another connection to INSERT from.
+connect (other,localhost,root,,);
+connection other;
+let $other_connection_id = `SELECT CONNECTION_ID()`;
+
+connection default;
+
+--disable_query_log
+eval SET @other_connection_id = $other_connection_id;
+--enable_query_log
+
+SET GLOBAL rpl_semi_sync_master_enabled = 1;
+
+--echo # Go ahead and send the INSERT; it should block.
+connection other;
+send INSERT INTO t1 (i) VALUES (1);
+
+connection default;
+
+let $wait_condition =
+ SELECT COUNT(*) > 0 AS should_be_true
+ FROM information_schema.processlist
+ WHERE id = @other_connection_id
+ AND state = "Waiting for semi-sync ACK from slave";
+--source include/wait_condition.inc
+
+--echo # The INSERT thread should now be waiting.
+SELECT state AS should_be_waiting
+FROM information_schema.processlist WHERE id = @other_connection_id;
+
+--echo # The insert should be visible to other threads
+SELECT * FROM t1 ORDER BY 1;
+
+--echo # Kill the waiting thread; it should die immediately.
+KILL @other_connection_id;
+
+--echo # Collect the error from the INSERT thread; it should be disconnected.
+connection other;
+--error 2013,ER_CONNECTION_KILLED
+reap;
+
+connection default;
+
+--echo # Wait for INSERT thread to actually disappear (KILL closes connection
+--echo # before thread actually finishes its processing).
+let $wait_condition =
+ SELECT COUNT(*) = 0 AS should_be_true
+ FROM information_schema.processlist
+ WHERE id = @other_connection_id;
+--source include/wait_condition.inc
+
+--echo # The INSERT thread should now be gone.
+SELECT state AS should_be_empty_set
+FROM information_schema.processlist WHERE id = @other_connection_id;
+
+--echo # The insert is still there
+SELECT * FROM t1 ORDER BY 1;
+
+connection default;
+disconnect other;
+
+--echo # Make another connection to INSERT from.
+connect (other,localhost,root,,);
+connection other;
+let $other_connection_id = `SELECT CONNECTION_ID()`;
+connection default;
+--disable_query_log
+eval SET @other_connection_id = $other_connection_id;
+--enable_query_log
+
+--echo # Go ahead and send the INSERT; it should block.
+connection other;
+send INSERT INTO t1 (i) VALUES (2);
+
+connection default;
+
+let $wait_condition =
+ SELECT COUNT(*) > 0 AS should_be_true
+ FROM information_schema.processlist
+ WHERE id = @other_connection_id
+ AND state = "Waiting for semi-sync ACK from slave";
+--source include/wait_condition.inc
+
+--echo # The INSERT thread should now be waiting.
+SELECT state AS should_be_waiting
+FROM information_schema.processlist WHERE id = @other_connection_id;
+
+--echo # The insert should be visible to other threads
+SELECT * FROM t1 ORDER BY 1;
+
+--echo # Now restart server
+--source include/restart_mysqld.inc
+--echo # Done restarting server
+
+--echo # Reset setting that were lost in restart
+SET @@global.rpl_semi_sync_master_timeout = 60000;
+SET @@global.rpl_semi_sync_master_wait_no_slave = 1;
+
+--echo # Check that row is still there
+SELECT * FROM t1 ORDER BY 1;
+
+disconnect other;
+
+--echo #
+--echo # Test wait point = AFTER_SYNC
+--echo #
+SET @@global.rpl_semi_sync_master_wait_point = AFTER_SYNC;
+
+--echo # Make another connection to INSERT from.
+connect (other,localhost,root,,);
+connection other;
+let $other_connection_id = `SELECT CONNECTION_ID()`;
+
+connection default;
+
+--disable_query_log
+eval SET @other_connection_id = $other_connection_id;
+--enable_query_log
+
+SET GLOBAL rpl_semi_sync_master_enabled = 1;
+
+--echo # Go ahead and send the INSERT; it should block.
+connection other;
+send INSERT INTO t1 (i) VALUES (3);
+
+connection default;
+
+let $wait_condition =
+ SELECT COUNT(*) > 0 AS should_be_true
+ FROM information_schema.processlist
+ WHERE id = @other_connection_id
+ AND state = "Waiting for semi-sync ACK from slave";
+--source include/wait_condition.inc
+
+--echo # The INSERT thread should now be waiting.
+SELECT state AS should_be_waiting
+FROM information_schema.processlist WHERE id = @other_connection_id;
+
+--echo # The insert should NOT be visible to other threads
+SELECT * FROM t1 ORDER BY 1;
+
+--echo # Kill the waiting thread; it should die immediately.
+KILL @other_connection_id;
+
+--echo # Collect the error from the INSERT thread; it should be disconnected.
+connection other;
+--error 2013,ER_CONNECTION_KILLED
+reap;
+
+connection default;
+
+--echo # Wait for INSERT thread to actually disappear (KILL closes connection
+--echo # before thread actually finishes its processing).
+let $wait_condition =
+ SELECT COUNT(*) = 0 AS should_be_true
+ FROM information_schema.processlist
+ WHERE id = @other_connection_id;
+--source include/wait_condition.inc
+
+--echo # The INSERT thread should now be gone.
+SELECT state AS should_be_empty_set
+FROM information_schema.processlist WHERE id = @other_connection_id;
+
+--echo # The row inserted is there
+SELECT * FROM t1 ORDER BY 1;
+
+connection default;
+disconnect other;
+
+--echo # Make another connection to INSERT from.
+connect (other,localhost,root,,);
+connection other;
+let $other_connection_id = `SELECT CONNECTION_ID()`;
+connection default;
+--disable_query_log
+eval SET @other_connection_id = $other_connection_id;
+--enable_query_log
+
+--echo # Go ahead and send the INSERT; it should block.
+connection other;
+send INSERT INTO t1 (i) VALUES (4);
+
+connection default;
+
+let $wait_condition =
+ SELECT COUNT(*) > 0 AS should_be_true
+ FROM information_schema.processlist
+ WHERE id = @other_connection_id
+ AND state = "Waiting for semi-sync ACK from slave";
+--source include/wait_condition.inc
+
+--echo # The INSERT thread should now be waiting.
+SELECT state AS should_be_waiting
+FROM information_schema.processlist WHERE id = @other_connection_id;
+
+--echo # The insert should NOT be visible to other threads
+SELECT * FROM t1 ORDER BY 1;
+
+--echo # Now restart server
+--source include/restart_mysqld.inc
+--echo # Done restarting server
+
+--echo # Reset setting that were lost in restart
+SET @@global.rpl_semi_sync_master_timeout = 60000;
+SET @@global.rpl_semi_sync_master_wait_no_slave = 1;
+
+--echo # But the row inserted is there
+SELECT * FROM t1 ORDER BY 1;
+
+disconnect other;
+
+--echo #
+--echo # Cleanup
+--echo #
+SET GLOBAL rpl_semi_sync_master_enabled = 0;
+DROP TABLE t1;
+
+eval SET @@global.rpl_semi_sync_master_timeout = $save_timeout;
+eval SET @@global.rpl_semi_sync_master_wait_no_slave = $save_wait_no_slave;
+eval SET @@global.rpl_semi_sync_master_wait_point = $save_wait_point;
diff --git a/mysql-test/suite/rpl/t/rpl_semisync_ali_issues-master.opt b/mysql-test/suite/rpl/t/rpl_semisync_ali_issues-master.opt
new file mode 100644
index 00000000..2672d4ff
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_semisync_ali_issues-master.opt
@@ -0,0 +1 @@
+--binlog_format=row
diff --git a/mysql-test/suite/rpl/t/rpl_semisync_ali_issues-slave.opt b/mysql-test/suite/rpl/t/rpl_semisync_ali_issues-slave.opt
new file mode 100644
index 00000000..2672d4ff
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_semisync_ali_issues-slave.opt
@@ -0,0 +1 @@
+--binlog_format=row
diff --git a/mysql-test/suite/rpl/t/rpl_semisync_ali_issues.test b/mysql-test/suite/rpl/t/rpl_semisync_ali_issues.test
new file mode 100644
index 00000000..5e6f350b
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_semisync_ali_issues.test
@@ -0,0 +1,429 @@
+--source include/have_innodb.inc
+--source include/have_debug_sync.inc
+--source include/master-slave.inc
+
+CALL mtr.add_suppression("Failed to start semi-sync ACK receiver thread.*");
+CALL mtr.add_suppression("Failed to register slave to semi-sync ACK receiver thread.*");
+CALL mtr.add_suppression("Failed to stop ack receiver thread on pthread_join.*");
+CALL mtr.add_suppression("Got an error reading communication packets:*");
+CALL mtr.add_suppression("Timeout waiting for reply of binlog*");
+CALL mtr.add_suppression("slave_read_sync_header*");
+CALL mtr.add_suppression("Missing magic number for semi-sync*");
+CALL mtr.add_suppression("Got timeout reading communication packets*");
+CALL mtr.add_suppression("Failed to call*");
+CALL mtr.add_suppression("Execution failed on master*");
+CALL mtr.add_suppression("Failed on request_dump()*");
+CALL mtr.add_suppression("Semi-sync master failed on*");
+CALL mtr.add_suppression("Master command COM_BINLOG_DUMP failed*");
+CALL mtr.add_suppression("on master failed*");
+CALL mtr.add_suppression("Master server does not support semi-sync*");
+CALL mtr.add_suppression("Semi-sync slave net_flush*");
+CALL mtr.add_suppression("Failed to flush master info*");
+CALL mtr.add_suppression("Request to stop slave SQL Thread received while apply*");
+
+connection master;
+echo [ enable semi-sync on master ];
+set global rpl_semi_sync_master_enabled = 1;
+show variables like 'rpl_semi_sync_master_enabled';
+
+connection slave;
+echo [ enable semi-sync on slave ];
+stop slave;
+set global rpl_semi_sync_slave_enabled = 1;
+start slave;
+let $status_var= rpl_semi_sync_slave_status;
+let $status_var_value= ON;
+source include/wait_for_status_var.inc;
+show status like 'rpl_semi_sync_slave%';
+
+
+connection master;
+CREATE TABLE t1(a INT) ENGINE=InnoDB;
+sync_slave_with_master;
+
+connection master;
+connect(con1,localhost,root,,);
+connect(con2,localhost,root,,);
+connect(con3,localhost,root,,);
+
+show status like 'Rpl_semi_sync_master_clients';
+show status like "rpl_semi_sync_master_yes_tx";
+
+--echo #########################################
+--echo # Test rpl_semi_sync_master_wait_point #
+--echo #########################################
+--echo # Test after_sync and after_commit first.
+
+--echo #Test after_sync
+connection con1;
+# Let's set a very large timeout value for testing purpose.
+SET GLOBAL rpl_semi_sync_master_timeout = 1000000;
+SET GLOBAL rpl_semi_sync_master_wait_point= 'AFTER_SYNC';
+SET DEBUG_SYNC= "commit_before_get_LOCK_commit_ordered SIGNAL after_sync_done WAIT_FOR end";
+--send INSERT into t1 values (1);
+
+connection con2;
+SET DEBUG_SYNC= "now WAIT_FOR after_sync_done";
+
+sync_slave_with_master;
+--echo #slave can see record (1) after sync slave with master
+select * from t1;
+
+connection con2;
+--echo #con2 shouldn't see record (1)
+select * from t1;
+SET DEBUG_SYNC= "now SIGNAL end";
+
+connection con1;
+reap;
+
+connection con1;
+select * from t1;
+truncate table t1;
+
+# MDEV-515 takes X-lock on the table
+# So concurrent DML won't happen on the table
+INSERT INTO t1 VALUES (100);
+
+sync_slave_with_master;
+
+# Test more threads in one semisync queue
+connection con1;
+SET DEBUG_SYNC= 'reset';
+SET DEBUG_SYNC= "commit_before_get_LOCK_log SIGNAL before_fetch_done WAIT_FOR more_queue";
+#SET DEBUG_SYNC= "before_semisync_fetch SIGNAL before_fetch_done WAIT_FOR more_queue";
+--send INSERT into t1 VALUES (1);
+
+connection con2;
+SET DEBUG_SYNC= "now WAIT_FOR before_fetch_done";
+SET DEBUG_SYNC= "after_semisync_queue SIGNAL more_queue";
+INSERT INTO t1 VALUES (2);
+
+connection con1;
+reap;
+
+# Test more threads in one semisync queue, but disable semisync before
+# waiting.
+connection con1;
+SET DEBUG_SYNC= 'reset';
+SET DEBUG_SYNC= "commit_before_get_LOCK_log SIGNAL before_fetch_done WAIT_FOR disable_semisync";
+#SET DEBUG_SYNC= "before_semisync_fetch SIGNAL before_fetch_done WAIT_FOR more_queue";
+#SET DEBUG_SYNC= "before_semisync_fetch SIGNAL before_fetch_done WAIT_FOR disable_semisync";
+--send INSERT into t1 VALUES (3);
+
+connection con2;
+SET DEBUG_SYNC= "now WAIT_FOR before_fetch_done";
+SET GLOBAL rpl_semi_sync_master_enabled= 0;
+SET DEBUG_SYNC= "now SIGNAL disable_semisync";
+
+connection con1;
+reap;
+SET GLOBAL rpl_semi_sync_master_enabled = 1;
+show status like 'Rpl_semi_sync_master_clients';
+
+--echo #Test after_commit
+connection con1;
+SET GLOBAL rpl_semi_sync_master_wait_point= 'AFTER_COMMIT';
+SET DEBUG_SYNC= "after_group_after_commit SIGNAL after_commit_done WAIT_FOR end";
+--send INSERT into t1 values (4);
+
+connection con2;
+SET DEBUG_SYNC= "now WAIT_FOR after_commit_done";
+
+sync_slave_with_master;
+select * from t1;
+
+connection con2;
+select * from t1;
+SET DEBUG_SYNC= "now SIGNAL end";
+
+connection con1;
+reap;
+
+connection con1;
+select * from t1;
+truncate table t1;
+
+--echo #######################################################
+--echo # Test some other options in order to cover the patch #
+--echo #######################################################
+connection slave;
+--echo # Test rpl_semi_sync_slave_trace_level
+SET GLOBAL rpl_semi_sync_slave_trace_level= 1;
+SET GLOBAL rpl_semi_sync_slave_trace_level= 16;
+SET GLOBAL rpl_semi_sync_slave_trace_level= 64;
+SET GLOBAL rpl_semi_sync_slave_trace_level= 128;
+SET GLOBAL rpl_semi_sync_slave_trace_level= 32;
+connection master;
+--echo # Test rpl_semi_sync_master_trace_level
+SET GLOBAL rpl_semi_sync_master_trace_level= 1;
+SET GLOBAL rpl_semi_sync_master_trace_level= 16;
+SET GLOBAL rpl_semi_sync_master_trace_level= 64;
+SET GLOBAL rpl_semi_sync_master_trace_level= 128;
+SET GLOBAL rpl_semi_sync_master_trace_level= 32;
+--echo # Test rpl_semi_sync_master_timeout
+SET GLOBAL rpl_semi_sync_master_timeout= 1000;
+SET GLOBAL rpl_semi_sync_master_timeout= 10000;
+SET GLOBAL rpl_semi_sync_master_timeout = 1000000;
+
+--echo # Test rpl_semi_sync_slave_kill_conn_timeout
+SET GLOBAL rpl_semi_sync_slave_kill_conn_timeout= 10;
+SET GLOBAL rpl_semi_sync_slave_kill_conn_timeout= 20;
+SET GLOBAL rpl_semi_sync_slave_kill_conn_timeout= 60;
+SET GLOBAL rpl_semi_sync_slave_kill_conn_timeout= 5;
+
+--echo ############################################
+--echo # Test rpl_semi_sync_master_wait_no_slave #
+--echo ############################################
+SET GLOBAL rpl_semi_sync_master_wait_no_slave = 1;
+connection slave;
+STOP SLAVE IO_THREAD;
+--source include/wait_for_slave_io_to_stop.inc
+
+connection con1;
+SET GLOBAL rpl_semi_sync_master_timeout = 1000;
+--send INSERT INTO t1 values (1);
+
+connection con1;
+reap;
+echo # Rpl_semi_sync_master_no_tx should be non-zero
+SHOW STATUS LIKE 'Rpl_semi_sync_master_no_tx';
+
+# test rpl_semi_sync_master_wait_no_slave = 0
+connection slave;
+START SLAVE IO_THREAD;
+--source include/wait_for_slave_io_to_start.inc
+
+connection con1;
+INSERT INTO t1 values (2);
+sync_slave_with_master;
+connection con1;
+let $status_var= Rpl_semi_sync_master_clients;
+let $status_var_value= 1;
+source include/wait_for_status_var.inc;
+let $status_var= Rpl_semi_sync_master_status;
+let $status_var_value= ON;
+source include/wait_for_status_var.inc;
+show status like 'Rpl_semi_sync_master_clients';
+show status like 'Rpl_semi_sync_master_status';
+
+connection slave;
+STOP SLAVE IO_THREAD;
+--source include/wait_for_slave_io_to_stop.inc
+
+connection con1;
+SET GLOBAL rpl_semi_sync_master_wait_no_slave= 0;
+SET GLOBAL rpl_semi_sync_master_timeout= 1000000000;
+INSERT INTO t1 values (3);
+show status like 'Rpl_semi_sync_master_clients';
+show status like 'Rpl_semi_sync_master_status';
+
+
+connection slave;
+START SLAVE IO_THREAD;
+--source include/wait_for_slave_io_to_start.inc
+
+connection con1;
+--let $status_var= Rpl_semi_sync_master_status
+--let $status_var_value=ON
+--source include/wait_for_status_var.inc
+
+SET GLOBAL rpl_semi_sync_master_timeout= 10000000;
+SET GLOBAL rpl_semi_sync_master_wait_no_slave= 1;
+INSERT INTO t1 values (4);
+sync_slave_with_master;
+
+connection con1;
+show status like 'Rpl_semi_sync_master_status';
+show status like 'Rpl_semi_sync_master_clients';
+
+--echo ##########################################
+--echo # Test rpl_semi_sync_slave_delay_master #
+--echo ##########################################
+
+connection slave;
+SET GLOBAL rpl_semi_sync_slave_delay_master= 1;
+START SLAVE IO_THREAD;
+--source include/wait_for_slave_io_to_start.inc
+
+connection con1;
+INSERT INTO t1 values (3);
+--source include/sync_slave_io_with_master.inc
+
+connection con1;
+show status like 'Rpl_semi_sync_master_clients';
+show status like 'Rpl_semi_sync_master_status';
+
+sync_slave_with_master;
+
+connection slave;
+select * from t1 order by a;
+connection con1;
+select * from t1 order by a;
+
+connection slave;
+SET GLOBAL rpl_semi_sync_slave_delay_master = 0;
+STOP SLAVE IO_THREAD;
+--source include/wait_for_slave_io_to_stop.inc
+START SLAVE IO_THREAD;
+--source include/wait_for_slave_io_to_start.inc
+
+--echo ##########################################################
+--echo # Test rpl_semi_sync_master_enabled and new ACK thread #
+--echo #########################################################
+connection con1;
+SET GLOBAL rpl_semi_sync_master_enabled = 0;
+
+let $status_var= Rpl_semi_sync_master_clients;
+let $status_var_value= 1;
+source include/wait_for_status_var.inc;
+show status like 'Rpl_semi_sync_master_clients';
+
+INSERT INTO t1 VALUES (1);
+SET GLOBAL rpl_semi_sync_master_enabled = 1;
+INSERT INTO t1 VALUES (2);
+show status like 'Rpl_semi_sync_master_clients';
+
+--echo # Test failure of select error .
+SET GLOBAL debug = 'd,rpl_semisync_simulate_select_error';
+# It can still receive ACK from semi-sync slave
+INSERT INTO t1 VALUES(3);
+sync_slave_with_master;
+
+connection con1;
+--echo # Test failure of pthread_create
+SET GLOBAL rpl_semi_sync_master_enabled = 0;
+SET GLOBAL debug = 'd,rpl_semisync_simulate_create_thread_failure';
+SET GLOBAL rpl_semi_sync_master_enabled= ON;
+
+--let $wait_condition= SELECT @@global.rpl_semi_sync_master_enabled = 0
+--source include/wait_condition.inc
+
+# Todo: implement the thread join failure simulation
+--echo # Test failure of pthread_join
+#SET GLOBAL DEBUG = 'd,rpl_semisync_simulate_thread_join_failure';
+#SET GLOBAL rpl_semi_sync_master_enabled= ON;
+#
+#--let $wait_condition= SELECT @@global.rpl_semi_sync_master_enabled = 0
+#--source include/wait_condition.inc
+SET GLOBAL rpl_semi_sync_master_enabled= OFF;
+
+--echo #
+--echo # Failure on registering semisync slave
+--echo #
+SET GLOBAL debug= 'd,rpl_semisync_simulate_add_slave_failure';
+SET GLOBAL rpl_semi_sync_master_enabled= ON;
+
+connection slave;
+STOP SLAVE IO_THREAD;
+--source include/wait_for_slave_io_to_stop.inc
+START SLAVE IO_THREAD;
+--source include/wait_for_slave_io_to_start.inc
+
+connection con1;
+#--echo # Should be Zero.
+# Todo: implement the add_slave_failure simulation. Meanwhile
+# the status will be 1.
+# show status like 'Rpl_semi_sync_master_clients';
+SET GLOBAL debug='';
+
+--let $status_var= Rpl_semi_sync_master_clients
+--let $status_var_value= 1
+--let $status_type= GLOBAL
+--source include/wait_for_status_var.inc
+
+connection slave;
+--disable_warnings
+START SLAVE IO_THREAD;
+--source include/wait_for_slave_io_to_start.inc
+--enable_warnings
+
+connection con1;
+sync_slave_with_master;
+
+show status like 'Rpl_semi_sync_master_clients';
+
+--echo ##################################################################
+--echo # Test fixing of BUG#70669 #
+--echo #SLAVE CAN'T CONTINUE REPLICATION AFTER MASTER'S CRASH RECOVERY #
+--echo #################################################################
+connection con1;
+SET GLOBAL sync_binlog = 1;
+CREATE TABLE t2 (c1 INT);
+sync_slave_with_master;
+
+connection con1;
+# Block the session before its events are synced to disk
+#SET DEBUG_SYNC = 'before_sync_binlog_file SIGNAL before_sync_done WAIT_FOR continue';
+send INSERT INTO t2 values (1);
+
+connection slave;
+--let $table= t2
+--let $count= 1
+--source include/wait_until_rows_count.inc
+
+connection con2;
+#SET DEBUG_SYNC= "now WAIT_FOR before_sync_done";
+#SET DEBUG_SYNC = "now SIGNAL continue";
+
+connection con1;
+reap;
+
+sync_slave_with_master;
+show tables like 't2';
+select * from t2;
+
+connection con1;
+#SET DEBUG_SYNC= "before_update_pos SIGNAL leader_ready WAIT_FOR follower_ready";
+send INSERT INTO t2 VALUES (2);
+
+connection con2;
+#SET DEBUG_SYNC= "now WAIT_FOR leader_ready";
+#SET DEBUG_SYNC= "after_sync_queue SIGNAL follower_ready";
+send INSERT INTO t2 VALUES (3);
+
+connection con1;
+reap;
+connection con2;
+reap;
+
+connection con1;
+#SET DEBUG_SYNC = 'before_sync_binlog_file SIGNAL before_sync_done WAIT_FOR continue';
+SET GLOBAL sync_binlog = 0;
+
+# Todo: fix this simulation and implement the intended sync protocol.
+# As a workaround the DROP sender explicitly okays
+# which naturally increments the binlog position.
+#send DROP TABLE t2;
+DROP TABLE t2;
+
+connection con2;
+#SET DEBUG_SYNC= "now WAIT_FOR before_sync_done";
+
+sync_slave_with_master;
+
+# t2 should be dropped
+show tables like 't2';
+
+connection con2;
+#SET DEBUG_SYNC = "now SIGNAL continue";
+
+# This block is commented out on purpose. See the todo/workaround above.
+#connection con1;
+#reap;
+
+
+--echo #cleanup
+connection master;
+SET DEBUG_SYNC= 'reset';
+disconnect con1;
+disconnect con2;
+disconnect con3;
+SET GLOBAL rpl_semi_sync_master_timeout= 10000;
+SET GLOBAL rpl_semi_sync_master_enabled = 0;
+DROP TABLE t1;
+connection slave;
+SET GLOBAL rpl_semi_sync_slave_enabled = 0;
+stop slave;start slave;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_server_id1.test b/mysql-test/suite/rpl/t/rpl_server_id1.test
new file mode 100644
index 00000000..90198a4a
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_server_id1.test
@@ -0,0 +1,22 @@
+# This test checks that the slave I/O thread refuses to start if slave
+# and master have the same server id (because this is a useless setup,
+# and otherwise SHOW SLAVE STATUS shows progress but all queries are
+# ignored, which has caught our customers), unless
+# --replicate-same-server-id.
+
+--let $rpl_topology= 2->2
+--let $rpl_skip_start_slave= 1
+--source include/rpl_init.inc
+
+--connection server_2
+START SLAVE;
+# 1593 = ER_SLAVE_FATAL_ERROR
+--let $slave_io_errno= 1593
+--let $show_slave_io_error= 1
+--source include/wait_for_slave_io_error.inc
+
+--source include/stop_slave_sql.inc
+RESET SLAVE;
+
+--let $rpl_only_running_threads= 1
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_server_id2-slave.opt b/mysql-test/suite/rpl/t/rpl_server_id2-slave.opt
new file mode 100644
index 00000000..30288952
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_server_id2-slave.opt
@@ -0,0 +1 @@
+--disable-log-slave-updates --replicate-same-server-id
diff --git a/mysql-test/suite/rpl/t/rpl_server_id2.test b/mysql-test/suite/rpl/t/rpl_server_id2.test
new file mode 100644
index 00000000..6dc2f791
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_server_id2.test
@@ -0,0 +1,72 @@
+# This test checks that a slave DOES execute queries originating
+# from itself, if running with --replicate-same-server-id.
+
+source include/master-slave.inc;
+
+connection slave;
+--source include/stop_slave.inc
+CHANGE MASTER TO MASTER_USE_GTID=NO;
+--source include/start_slave.inc
+
+create table t1 (n int);
+reset master;
+# replicate ourselves
+stop slave;
+--source include/wait_for_slave_to_stop.inc
+--replace_result $SLAVE_MYPORT SLAVE_PORT
+eval change master to master_port=$SLAVE_MYPORT;
+start slave;
+--source include/wait_for_slave_to_start.inc
+insert into t1 values (1);
+save_master_pos;
+sync_with_master;
+select * from t1; # check that indeed 2 were inserted
+# We stop the slave before cleaning up otherwise we'll get
+# 'drop table t1' executed twice, so an error in the slave.err
+# (not critical).
+stop slave;
+--source include/wait_for_slave_to_stop.inc
+drop table t1;
+
+
+#
+# Bug#38934 slave slave until does not work with --replicate-same-server-id
+#
+# Verifying that slave performs all events until the master_log_pos
+# in presense of --replicate-same-server-id the slave is started with.
+
+connection master;
+reset master;
+
+# setting the until position to correspond to the last position of
+# create table which will make the event executed and the slave sql
+# thread stopped right after that.
+
+create table t1(n int);
+let $until_pos= query_get_value(SHOW MASTER STATUS, Position, 1);
+dec $until_pos;
+create table t2(n int);
+
+connection slave;
+--replace_result $MASTER_MYPORT MASTER_PORT
+eval change master to master_port=$MASTER_MYPORT;
+--replace_result $until_pos UNTIL_POS
+eval start slave until master_log_file='master-bin.000001', master_log_pos=$until_pos;
+--source include/wait_for_slave_io_to_start.inc
+--source include/wait_for_slave_sql_to_stop.inc
+
+--echo *** checking until position execution: must be only t1 in the list ***
+show tables;
+
+# cleanup
+
+connection slave;
+start slave sql_thread;
+
+connection master;
+drop table t1;
+drop table t2;
+sync_slave_with_master;
+
+# End of tests
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_server_id_ignore-slave.opt b/mysql-test/suite/rpl/t/rpl_server_id_ignore-slave.opt
new file mode 100644
index 00000000..30288952
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_server_id_ignore-slave.opt
@@ -0,0 +1 @@
+--disable-log-slave-updates --replicate-same-server-id
diff --git a/mysql-test/suite/rpl/t/rpl_server_id_ignore.test b/mysql-test/suite/rpl/t/rpl_server_id_ignore.test
new file mode 100644
index 00000000..dbe7544b
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_server_id_ignore.test
@@ -0,0 +1,116 @@
+# This test checks that the slave rejects events originating
+# by a server from the list of ignored originators (bug#27808 etc)
+#
+# phases of tests:
+#
+# 0. master_id new line in show slave status
+# 1. syntax related:
+# a. error reporting if options clash;
+# b. overriding the old IGNORE_SERVER_IDS setup by the following
+# CHANGE MASTER ... IGNORE_SERVER_IDS= (list);
+# c. the old setup preserving by CHANGE MASTER w/o IGNORE_SERVER_IDS
+# d. resetting the ignored server ids with the empty list arg to
+# IGNORE_SERVER_IDS=()
+# e. RESET SLAVE preserves the list
+# 2. run time related:
+# a. observing no processing events from a master listed in IGNORE_SERVER_IDS
+# b. nullifying the list and resuming of taking binlog from the very beginning with
+# executing events this time
+
+source include/have_binlog_format_mixed.inc;
+source include/master-slave.inc;
+
+connection slave;
+
+# a new line for master_id
+let $master_id= query_get_value(SHOW SLAVE STATUS, Master_Server_Id, 1);
+echo master_id: $master_id;
+
+stop slave;
+--echo *** --replicate-same-server-id and change master option can clash ***
+--error ER_SLAVE_IGNORE_SERVER_IDS
+change master to IGNORE_SERVER_IDS= (2, 1);
+--echo *** must be empty due to the error ***
+let $ignore_list= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Server_Ids, 1);
+echo ignore server id list: $ignore_list;
+
+change master to IGNORE_SERVER_IDS= (10, 100);
+--echo *** must be 10, 100 ***
+let $ignore_list= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Server_Ids, 1);
+echo ignore server id list: $ignore_list;
+--source include/reset_slave.inc
+--echo *** must be empty due to reset slave ***
+let $ignore_list= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Server_Ids, 1);
+echo ignore server id list: $ignore_list;
+change master to IGNORE_SERVER_IDS= (10, 100);
+--echo *** CHANGE MASTER with IGNORE_SERVER_IDS option overrides (does not increment) the previous setup ***
+change master to IGNORE_SERVER_IDS= (5, 1, 4, 3, 1);
+--echo *** must be 1, 3, 4, 5 due to overriding policy ***
+let $ignore_list= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Server_Ids, 1);
+echo ignore server id list: $ignore_list;
+--echo *** ignore master (server 1) queries for a while ***
+start slave;
+
+connection master;
+
+#connection slave;
+sync_slave_with_master;
+let $slave_relay_pos0= query_get_value(SHOW SLAVE STATUS, Relay_Log_Pos, 1);
+
+connection master;
+create table t1 (n int);
+let $master_binlog_end= query_get_value(SHOW MASTER STATUS, Position, 1);
+
+connection slave;
+let $slave_param= Exec_Master_Log_Pos;
+let $slave_param_value= $master_binlog_end;
+source include/wait_for_slave_param.inc;
+--echo *** must be empty as the event is to be filtered out ***
+show tables;
+--echo *** allowing events from master ***
+let $slave_relay_pos1= query_get_value(SHOW SLAVE STATUS, Relay_Log_Pos, 1);
+#
+# checking stability of relay log pos
+#
+if (`select $slave_relay_pos1 - $slave_relay_pos0`)
+{
+ --echo Error: relay log position changed: $slave_relay_pos0, $slave_relay_pos1
+ query_vertical show slave status;
+}
+
+stop slave;
+source include/wait_for_slave_to_stop.inc;
+--source include/reset_slave.inc
+change master to IGNORE_SERVER_IDS= (10, 100);
+--echo *** the list must remain (10, 100) after reset slave ***
+let $ignore_list= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Server_Ids, 1);
+
+change master to IGNORE_SERVER_IDS= ();
+--echo *** must be empty due to IGNORE_SERVER_IDS empty list ***
+let $ignore_list= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Server_Ids, 1);
+echo ignore server id list: $ignore_list;
+--replace_result $MASTER_MYPORT MASTER_PORT
+eval change master to master_host='127.0.0.1', master_port=$MASTER_MYPORT, master_user='root';
+start slave;
+
+connection master;
+
+#connection slave;
+sync_slave_with_master;
+--echo *** must have caught create table ***
+show tables;
+
+# cleanup
+connection master;
+drop table t1;
+#connection slave
+sync_slave_with_master;
+
+--echo end of the tests
+
+
+
+
+
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_session_var.test b/mysql-test/suite/rpl/t/rpl_session_var.test
new file mode 100644
index 00000000..cf3faa65
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_session_var.test
@@ -0,0 +1,61 @@
+# Replication of session variables.
+# FOREIGN_KEY_CHECKS is tested in rpl_insert_id.test
+
+source include/master-slave.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;
+
+drop table if exists t1;
+create table t1(a varchar(100),b int);
+set @@session.sql_mode=pipes_as_concat;
+insert into t1 values('My'||'SQL', 1);
+set @@session.sql_mode=default;
+insert into t1 values('1'||'2', 2);
+select * from t1 where b<3 order by a;
+sync_slave_with_master;
+select * from t1 where b<3 order by a;
+connection master;
+# if the slave does the next sync_with_master fine, then it means it accepts the
+# two lines of ANSI syntax below, which is what we want to check.
+set @@session.sql_mode=ignore_space;
+insert into t1 values(password ('MySQL'), 3);
+set @@session.sql_mode=ansi_quotes;
+create table "t2" ("a" int);
+drop table t1, t2;
+set @@session.sql_mode=default;
+create table t1(a int auto_increment primary key);
+create table t2(b int, a int);
+set @@session.sql_auto_is_null=1;
+insert into t1 values(null);
+insert into t2 select 1,a from t1 where a is null;
+set @@session.sql_auto_is_null=0;
+insert into t1 values(null);
+insert into t2 select 2,a from t1 where a is null;
+select * from t2 order by b;
+sync_slave_with_master;
+select * from t2 order by b;
+connection master;
+drop table t1,t2;
+sync_slave_with_master;
+
+#
+# Bug #29878 Garbage data generation when executing SESSION_USER() on a slave.
+#
+
+connection master;
+CREATE TABLE t1 (
+ `id` int(11) NOT NULL auto_increment,
+ `data` varchar(100),
+ PRIMARY KEY (`id`)
+ ) ENGINE=MyISAM;
+--disable_warnings
+INSERT INTO t1(data) VALUES(SESSION_USER());
+--enable_warnings
+sync_slave_with_master;
+SELECT length(data) < 100 FROM t1;
+connection master;
+drop table t1;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_set_charset.test b/mysql-test/suite/rpl/t/rpl_set_charset.test
new file mode 100644
index 00000000..72b89a13
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_set_charset.test
@@ -0,0 +1,30 @@
+source include/master-slave.inc;
+--disable_warnings
+drop database if exists mysqltest1;
+# 4.1 bases its conversion on the db's charset,
+# while 4.0 uses the part of "SET CHARACTER SET" after "_".
+# So for 4.1 we add a clause to CREATE DATABASE.
+create database mysqltest1 /*!40100 character set latin2 */;
+use mysqltest1;
+drop table if exists t1;
+--enable_warnings
+create table t1 (a varchar(255) character set latin2, b varchar(4));
+SET CHARACTER SET cp1250_latin2;
+INSERT INTO t1 VALUES ('ŠŒŽ','80');
+INSERT INTO t1 VALUES ('šœžŸ','90');
+INSERT INTO t1 VALUES ('£¥ª¯','A0');
+INSERT INTO t1 VALUES ('³¹º¼¾¿','B0');
+INSERT INTO t1 VALUES ('ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏ','C0');
+INSERT INTO t1 VALUES ('ÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞß','D0');
+INSERT INTO t1 VALUES ('àáâãäåæçèéêëìíîï','E0');
+INSERT INTO t1 VALUES ('ðñòóôõö÷øùúûüýþÿ','F0');
+select hex(a),b from t1 order by b;
+sync_slave_with_master;
+use mysqltest1;
+select hex(a),b from t1 order by b;
+connection master;
+drop database mysqltest1;
+sync_slave_with_master;
+
+# End of 4.1 tests
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_set_null_innodb.test b/mysql-test/suite/rpl/t/rpl_set_null_innodb.test
new file mode 100644
index 00000000..84f7adb3
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_set_null_innodb.test
@@ -0,0 +1,7 @@
+-- source include/have_binlog_format_mixed_or_row.inc
+-- source include/have_innodb.inc
+-- source include/master-slave.inc
+
+-- let $engine= InnoDB
+-- source include/rpl_set_null.test
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_set_null_myisam.test b/mysql-test/suite/rpl/t/rpl_set_null_myisam.test
new file mode 100644
index 00000000..db1bd4b7
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_set_null_myisam.test
@@ -0,0 +1,6 @@
+-- source include/have_binlog_format_mixed_or_row.inc
+-- source include/master-slave.inc
+
+-- let $engine= MyISAM
+-- source include/rpl_set_null.test
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_set_statement.test b/mysql-test/suite/rpl/t/rpl_set_statement.test
new file mode 100644
index 00000000..5bc54e44
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_set_statement.test
@@ -0,0 +1,61 @@
+--source include/master-slave.inc
+--source include/have_binlog_format_statement.inc
+set sql_mode="";
+connection slave;
+set sql_mode="";
+connection master;
+
+--disable_warnings
+DROP TABLE IF EXISTS t1;
+DROP TABLE IF EXISTS t2;
+--enable_warnings
+
+call mtr.add_suppression("Unsafe statement written to the binary log*");
+CREATE TABLE t1 (a bigint unsigned not null);
+CREATE TABLE t2 (a char(255) not null);
+
+--echo
+--echo There are the following types of variables:
+--echo 1) variables that are NOT replicated correctly when using STATEMENT mode;
+--echo
+
+--let $rpl_ssvt_var_name=max_join_size
+--let $rpl_ssvt_var_value=2
+--let $rpl_ssvt_table=t1
+--source suite/rpl/include/rpl_set_statement.inc
+
+--echo
+--echo 2) variables thar ARE replicated correctly
+--echo They must be replicated correctly with "SET STATEMENT" too.
+--echo
+--let $rpl_ssvt_var_name=auto_increment_increment
+--let $rpl_ssvt_var_value=10
+--let $rpl_ssvt_table=t1
+--source suite/rpl/include/rpl_set_statement.inc
+
+--echo
+--echo 3) sql_mode which is replicated correctly exept NO_DIR_IN_CREATE value;
+--echo
+--let $rpl_ssvt_var_name=sql_mode
+--let $rpl_ssvt_var_value='ERROR_FOR_DIVISION_BY_ZERO'
+--let $rpl_ssvt_table=t2
+--source suite/rpl/include/rpl_set_statement.inc
+--let $rpl_ssvt_var_name=sql_mode
+--let $rpl_ssvt_var_value='NO_DIR_IN_CREATE'
+--let $rpl_ssvt_table=t2
+--source suite/rpl/include/rpl_set_statement.inc
+
+--echo
+--echo 4) variables that are not replicated at all:
+--echo default_storage_engine, storage_engine, max_heap_table_size
+--echo
+--let $rpl_ssvt_var_name=max_heap_table_size
+--let $rpl_ssvt_var_value=16384
+--let $rpl_ssvt_table=t1
+--source suite/rpl/include/rpl_set_statement.inc
+
+connection master;
+DROP TABLE t1;
+DROP TABLE t2;
+sync_slave_with_master;
+source include/stop_slave.inc;
diff --git a/mysql-test/suite/rpl/t/rpl_set_statement_default_master.test b/mysql-test/suite/rpl/t/rpl_set_statement_default_master.test
new file mode 100644
index 00000000..106cb454
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_set_statement_default_master.test
@@ -0,0 +1,34 @@
+--source include/master-slave.inc
+
+--connection slave
+
+--source include/stop_slave.inc
+RESET SLAVE ALL;
+
+--echo # Does not work for CHANGE MASTER:
+--replace_result $MASTER_MYPORT MASTER_MYPORT
+eval SET STATEMENT default_master_connection = 'm1' FOR
+ CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=$MASTER_MYPORT, MASTER_USER='root';
+
+
+--echo #
+--echo # The first field, Connection_name, should say 'm1'...
+--echo #
+--let $status_items= Connection_name
+--source include/show_all_slaves_status.inc
+#query_vertical SHOW ALL SLAVES STATUS;
+
+
+RESET SLAVE ALL;
+
+--replace_result $MASTER_MYPORT MASTER_MYPORT
+eval CHANGE MASTER 'm1' TO MASTER_HOST='127.0.0.1', MASTER_PORT=$MASTER_MYPORT, MASTER_USER='root';
+SET STATEMENT default_master_connection = 'm1' FOR START SLAVE;
+
+set default_master_connection = 'm1';
+stop slave;
+--source include/wait_for_slave_to_stop.inc
+reset slave all;
+set default_master_connection = '';
+--disconnect slave
+--connection default
diff --git a/mysql-test/suite/rpl/t/rpl_show_slave_hosts.cnf b/mysql-test/suite/rpl/t/rpl_show_slave_hosts.cnf
new file mode 100644
index 00000000..288f0132
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_show_slave_hosts.cnf
@@ -0,0 +1,20 @@
+!include ../my.cnf
+
+[mysqld.1]
+server_id=1
+
+[mysqld.2]
+server_id=2
+report-host=
+report-user=
+
+[mysqld.3]
+server_id=3
+report-host=slave2
+slave-net-timeout=5
+
+[ENV]
+SLAVE_MYPORT2= @mysqld.3.port
+SLAVE_MYSOCK2= @mysqld.3.socket
+
+
diff --git a/mysql-test/suite/rpl/t/rpl_show_slave_hosts.test b/mysql-test/suite/rpl/t/rpl_show_slave_hosts.test
new file mode 100644
index 00000000..84c5c215
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_show_slave_hosts.test
@@ -0,0 +1,52 @@
+###############################################################################
+# Bug#13963 SHOW SLAVE HOSTS is unreliable
+#
+# Slaves only appear in the output of SHOW SLAVE HOSTS when report-host option
+# is set. If an expected slave does not appear in the list, nobody knows
+# whether the slave does not connect or has started without the "report-host"
+# option.
+#
+# Remove the "Rpl_recovery_rank" column from SHOW SLAVE HOSTS, It is not
+# implemented.
+#######################################################################
+source include/master-slave.inc;
+connect (slave2,127.0.0.1,root,,test,$SLAVE_MYPORT2,);
+
+connection slave2;
+RESET SLAVE;
+--replace_result $MASTER_MYPORT MASTER_PORT
+--eval CHANGE MASTER TO master_host='127.0.0.1',master_port=$MASTER_MYPORT,master_user='root'
+START SLAVE IO_THREAD;
+source include/wait_for_slave_io_to_start.inc;
+
+connection master;
+let $show_statement= SHOW SLAVE HOSTS;
+let $field= Server_id;
+# 3 is server_id of slave2.
+let $condition= ='3';
+source include/wait_show_condition.inc;
+# Make sure that the other slave also had time to register. Otherwise we get
+# occasional spurious failures where server_id=2 is missing from SHOW SLAVE
+# HOSTS, when that slave is much slower to register due to thread scheduling.
+let $condition= ='2';
+source include/wait_show_condition.inc;
+--replace_column 3 'SLAVE_PORT'
+--replace_result $SLAVE_MYPORT SLAVE_PORT $DEFAULT_MASTER_PORT DEFAULT_PORT
+SHOW SLAVE HOSTS;
+
+connection slave2;
+--source include/stop_slave_io.inc
+
+connection master;
+let $show_statement= SHOW SLAVE HOSTS;
+let $field= Server_id;
+# 3 is server_id of slave2.
+let $condition= <> '3';
+# All rows of 'SHOW SLAVE HOSTS' are not equal to 3. It mean that master has
+# knew the leave of slave2 and has unregistered it.
+let $wait_for_all= 1;
+source include/wait_show_condition.inc;
+--replace_result $SLAVE_MYPORT SLAVE_PORT
+SHOW SLAVE HOSTS;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_show_slave_running.test b/mysql-test/suite/rpl/t/rpl_show_slave_running.test
new file mode 100644
index 00000000..cb4a8819
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_show_slave_running.test
@@ -0,0 +1,83 @@
+#
+# Bug #30703 SHOW STATUS LIKE 'Slave_running' is not compatible with `SHOW SLAVE STATUS'
+# The test verifies that SHOW STATUS LIKE 'Slave_running' displays ON
+# if and only if `SHOW SLAVE STATUS' displays YES for Slave_IO_Running and Slave_SQL_Running
+#
+source include/have_debug.inc;
+source include/have_debug_sync.inc;
+source include/master-slave.inc;
+
+connection slave;
+
+SET DEBUG_SYNC= 'RESET';
+source include/stop_slave.inc;
+SET @saved_dbug = @@GLOBAL.debug_dbug;
+set global debug_dbug= 'd,dbug.before_get_running_status_yes'; # to block due-started IO
+
+# Test 1. Slave is stopped
+
+--echo Slave_running, Slave_IO_Running, Slave_SQL_Running, must be OFF, NO, NO in three following queries
+
+SHOW STATUS LIKE 'Slave_running';
+let $status= query_get_value("show slave status", Slave_IO_Running, 1);
+echo Slave_IO_Running= $status;
+let $status= query_get_value("show slave status", Slave_SQL_Running, 1);
+echo Slave_SQL_Running= $status;
+
+# Test 2. The slave IO thread is started but not yet got connected to master
+# and SQL thread is not started
+
+start slave io_thread;
+
+#
+# Notice a difference between versions in showing p.2:
+# 5.1 has two OFF,ON IO-thread state running state whereas later versions
+# have three: OFF,Connecting,ON.
+# Hence, 5.1 must display OFF NO NO where as 5.1+ OFF Connecting NO
+#
+--echo Slave_running, Slave_IO_Running, Slave_SQL_Running must be OFF Connecting NO in three following queries
+
+SHOW STATUS LIKE 'Slave_running';
+let $status= query_get_value("show slave status", Slave_IO_Running, 1);
+echo Slave_IO_Running= $status;
+let $status= query_get_value("show slave status", Slave_SQL_Running, 1);
+echo Slave_SQL_Running= $status;
+
+# Test 3. The slave IO thread is started and got connected to master
+# and SQL thread is still not started
+
+SET DEBUG_SYNC='now SIGNAL signal.io_thread_let_running'; # unblock IO thread now
+let $slave_param= Slave_IO_Running;
+let $slave_param_value= YES;
+source include/wait_for_slave_param.inc;
+
+--echo Slave_running, Slave_IO_Running, Slave_SQL_Running must be OFF YES NO in three following queries
+
+SHOW STATUS LIKE 'Slave_running';
+let $status= query_get_value("show slave status", Slave_IO_Running, 1);
+echo Slave_IO_Running= $status;
+let $status= query_get_value("show slave status", Slave_SQL_Running, 1);
+echo Slave_SQL_Running= $status;
+
+# Test 4. The slave IO thread is started and got connected to master
+# and SQL thread is started
+
+start slave sql_thread;
+source include/wait_for_slave_sql_to_start.inc;
+
+--echo Slave_running, Slave_IO_Running, Slave_SQL_Running must be ON, YES, YES in three following queries
+
+SHOW STATUS LIKE 'Slave_running';
+let $status= query_get_value("show slave status", Slave_IO_Running, 1);
+echo Slave_IO_Running= $status;
+let $status= query_get_value("show slave status", Slave_SQL_Running, 1);
+echo Slave_SQL_Running= $status;
+
+# cleanup
+
+connection slave;
+
+SET @@GLOBAL.debug_dbug = @saved_dbug;
+SET DEBUG_SYNC= 'RESET';
+--echo End of tests
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_shutdown_wait_semisync_slaves.cnf b/mysql-test/suite/rpl/t/rpl_shutdown_wait_semisync_slaves.cnf
new file mode 100644
index 00000000..8ff9df03
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_shutdown_wait_semisync_slaves.cnf
@@ -0,0 +1,16 @@
+!include ../my.cnf
+
+[mysqld.1]
+log_warnings=3
+[mysqld.2]
+
+[mysqld.3]
+
+[mysqld.4]
+
+[ENV]
+SERVER_MYPORT_3= @mysqld.3.port
+SERVER_MYSOCK_3= @mysqld.3.socket
+
+SERVER_MYPORT_4= @mysqld.4.port
+SERVER_MYSOCK_4= @mysqld.4.socket
diff --git a/mysql-test/suite/rpl/t/rpl_shutdown_wait_semisync_slaves.test b/mysql-test/suite/rpl/t/rpl_shutdown_wait_semisync_slaves.test
new file mode 100644
index 00000000..2c63df30
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_shutdown_wait_semisync_slaves.test
@@ -0,0 +1,46 @@
+#
+# MDEV-18450 "Slow" shutdown to wait for slaves that are to be fed
+# with everything in the master binlog before shutdown completes.
+#
+# This is a semisync version of basic tests.
+--source include/have_innodb.inc
+--source include/have_debug.inc
+--let $rpl_topology=1->2, 1->3, 1->4
+--source include/rpl_init.inc
+
+--connection server_1
+call mtr.add_suppression("Timeout waiting for reply of binlog");
+--let $sav_enabled_master=`SELECT @@GLOBAL.rpl_semi_sync_master_enabled`
+SET @@GLOBAL.rpl_semi_sync_master_enabled = 1;
+
+--let slaves= 3
+--let i= 2
+while (`SELECT $i <= $slaves`)
+{
+ --connection server_$i
+ --let $sav_enabled_slave=`SELECT @@GLOBAL.rpl_semi_sync_slave_enabled`
+ set global rpl_semi_sync_slave_enabled = 1;
+
+ source include/stop_slave.inc;
+ source include/start_slave.inc;
+ set global rpl_semi_sync_slave_enabled = 1;
+
+ --inc $i
+}
+
+--source include/rpl_shutdown_wait_slaves.inc
+--let i= 2
+while (`SELECT $i <= $slaves`)
+{
+ --connection server_$i
+ source include/stop_slave.inc;
+ source include/start_slave.inc;
+ --eval SET @@GLOBAL.rpl_semi_sync_slave_enabled = $sav_enabled_slave;
+
+ --inc $i
+}
+
+--connection server_1
+--eval SET @@GLOBAL.rpl_semi_sync_master_enabled = $sav_enabled_master
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_shutdown_wait_slaves.cnf b/mysql-test/suite/rpl/t/rpl_shutdown_wait_slaves.cnf
new file mode 100644
index 00000000..8ff9df03
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_shutdown_wait_slaves.cnf
@@ -0,0 +1,16 @@
+!include ../my.cnf
+
+[mysqld.1]
+log_warnings=3
+[mysqld.2]
+
+[mysqld.3]
+
+[mysqld.4]
+
+[ENV]
+SERVER_MYPORT_3= @mysqld.3.port
+SERVER_MYSOCK_3= @mysqld.3.socket
+
+SERVER_MYPORT_4= @mysqld.4.port
+SERVER_MYSOCK_4= @mysqld.4.socket
diff --git a/mysql-test/suite/rpl/t/rpl_shutdown_wait_slaves.test b/mysql-test/suite/rpl/t/rpl_shutdown_wait_slaves.test
new file mode 100644
index 00000000..97363206
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_shutdown_wait_slaves.test
@@ -0,0 +1,11 @@
+#
+# MDEV-18450 "Slow" shutdown to wait for slaves that are to be fed
+# with everything in the master binlog before shutdown completes.
+#
+--source include/have_innodb.inc
+--source include/have_debug.inc
+--let $rpl_topology=1->2, 1->3, 1->4
+--source include/rpl_init.inc
+
+--source include/rpl_shutdown_wait_slaves.inc
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_skip_error-slave.opt b/mysql-test/suite/rpl/t/rpl_skip_error-slave.opt
new file mode 100644
index 00000000..208da1fa
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_skip_error-slave.opt
@@ -0,0 +1 @@
+--slave-skip-errors=1062
diff --git a/mysql-test/suite/rpl/t/rpl_skip_error.test b/mysql-test/suite/rpl/t/rpl_skip_error.test
new file mode 100644
index 00000000..d3ef834e
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_skip_error.test
@@ -0,0 +1,175 @@
+# ==== Purpose ====
+#
+# Verify that --slave-skip-errors works correctly. The error messages
+# specified by --slave-skip-errors on slave should be ignored. If
+# such errors occur, they should not be reported and not cause the
+# slave to stop.
+#
+# ==== Method ====
+#
+# We run the slave with --slave-skip-errors=1062 (the code for
+# duplicate key). Then we have two set of tests. In the first
+# set, we insert value 1 in a table on the slave, and then, on
+# master, we insert value 1 in the table. In the second set, we
+# insert several values on the master, disable the binlog and
+# delete one of the values and re-enable the binlog. Right after,
+# we perform an update on the set of values in order to generate
+# a duplicate key on the slave. The errors should be ignored on
+# the slave.
+#
+# ==== Related bugs ====
+#
+# BUG#28839: Errors in strict mode silently stop SQL thread if --slave-skip-errors exists
+# bug in this test: BUG#30594: rpl.rpl_skip_error is nondeterministic:
+# BUG#39393: slave-skip-errors does not work when using ROW based replication
+
+source include/have_innodb.inc;
+source include/master-slave.inc;
+
+--connection slave
+let $initial_skipped_error= query_get_value(show global status like "Slave_skipped_errors", Value, 1);
+
+connection master;
+--echo ==== Test Without sql_mode=strict_trans_tables ====
+
+create table t1 (n int not null primary key);
+
+sync_slave_with_master;
+insert into t1 values (1);
+
+connection master;
+# Here we expect (ignored) error, since 1 is already in slave table
+insert into t1 values (1);
+# These should work fine
+insert into t1 values (2),(3);
+
+sync_slave_with_master;
+select * from t1 order by n;
+
+--echo ==== Test With sql_mode=strict_trans_tables ====
+insert into t1 values (7),(8);
+connection master;
+set sql_mode=strict_trans_tables;
+insert into t1 values (7), (8), (9);
+sync_slave_with_master;
+select * from t1 order by n;
+source include/check_slave_is_running.inc;
+
+--echo ==== Clean Up ====
+connection master;
+drop table t1;
+sync_slave_with_master;
+# End of 4.1 tests
+
+#
+# #28839 Errors in strict mode silently stop SQL thread if --slave-skip-errors exists
+#
+connection master;
+create table t1(a int primary key);
+insert into t1 values (1),(2);
+SET SQL_LOG_BIN=0;
+delete from t1;
+SET SQL_LOG_BIN=1;
+set sql_mode=strict_trans_tables;
+insert into t1 values (1), (2), (3);
+
+sync_slave_with_master;
+select * from t1;
+source include/check_slave_is_running.inc;
+
+
+--echo ==== Clean Up ====
+
+connection master;
+drop table t1;
+sync_slave_with_master;
+# End of 5.0 tests
+
+#
+# BUG#39393: slave-skip-errors does not work when using ROW based replication
+#
+--echo ==== Using Innodb ====
+
+connection master;
+
+SET SQL_LOG_BIN=0;
+CREATE TABLE t1(id INT NOT NULL PRIMARY KEY, data INT) Engine=InnoDB;
+SHOW CREATE TABLE t1;
+SET SQL_LOG_BIN=1;
+
+connection slave;
+
+call mtr.add_suppression("Slave SQL.*Could not execute .*te_rows event on table test.t.; Duplicate entry.* error.* 1062");
+
+CREATE TABLE t1(id INT NOT NULL PRIMARY KEY, data INT) Engine=InnoDB;
+SHOW CREATE TABLE t1;
+
+connection master;
+
+INSERT INTO t1 VALUES(1, 1);
+INSERT INTO t1 VALUES(2, 1);
+INSERT INTO t1 VALUES(3, 1);
+INSERT INTO t1 VALUES(4, 1);
+
+SET SQL_LOG_BIN=0;
+DELETE FROM t1 WHERE id = 4;
+SET SQL_LOG_BIN=1;
+UPDATE t1 SET id= id + 3, data = 2;
+
+sync_slave_with_master;
+
+let $error= query_get_value("SHOW SLAVE STATUS", Last_SQL_Error, 1);
+echo $error;
+
+--echo **** We cannot execute a select as there are differences in the
+--echo **** behavior between STMT and RBR.
+
+--echo ==== Using MyIsam ====
+
+connection master;
+
+SET SQL_LOG_BIN=0;
+CREATE TABLE t2(id INT NOT NULL PRIMARY KEY, data INT) Engine=MyIsam;
+SHOW CREATE TABLE t2;
+SET SQL_LOG_BIN=1;
+
+connection slave;
+
+CREATE TABLE t2(id INT NOT NULL PRIMARY KEY, data INT) Engine=MyIsam;
+SHOW CREATE TABLE t2;
+let $current_skipped_error= query_get_value(show global status like "Slave_skipped_errors", Value, 1);
+--let $delta_skipped_error= `select $current_skipped_error - $initial_skipped_error from dual`
+--echo # Slave_skipped_errros = $delta_skipped_error
+connection master;
+
+INSERT INTO t2 VALUES(1, 1);
+INSERT INTO t2 VALUES(2, 1);
+INSERT INTO t2 VALUES(3, 1);
+INSERT INTO t2 VALUES(5, 1);
+
+SET SQL_LOG_BIN=0;
+DELETE FROM t2 WHERE id = 5;
+SET SQL_LOG_BIN=1;
+UPDATE t2 SET id= id + 3, data = 2;
+
+sync_slave_with_master;
+
+let $error= query_get_value("SHOW SLAVE STATUS", Last_SQL_Error, 1);
+echo $error;
+
+let $current_skipped_error= query_get_value(show global status like "Slave_skipped_errors", Value, 1);
+--let $delta_skipped_error= `select $current_skipped_error - $initial_skipped_error from dual`
+--echo # Slave_skipped_errros = $delta_skipped_error
+
+--echo **** We cannot execute a select as there are differences in the
+--echo **** behavior between STMT and RBR.
+
+--echo ==== Clean Up ====
+
+connection master;
+
+DROP TABLE t1;
+DROP TABLE t2;
+
+sync_slave_with_master;
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_skip_incident-master.opt b/mysql-test/suite/rpl/t/rpl_skip_incident-master.opt
new file mode 100644
index 00000000..912801de
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_skip_incident-master.opt
@@ -0,0 +1 @@
+--loose-debug=+d,incident_database_resync_on_replace
diff --git a/mysql-test/suite/rpl/t/rpl_skip_incident-slave.opt b/mysql-test/suite/rpl/t/rpl_skip_incident-slave.opt
new file mode 100644
index 00000000..a223f2e0
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_skip_incident-slave.opt
@@ -0,0 +1 @@
+--slave-skip-errors=1590
diff --git a/mysql-test/suite/rpl/t/rpl_skip_incident.test b/mysql-test/suite/rpl/t/rpl_skip_incident.test
new file mode 100644
index 00000000..704854ae
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_skip_incident.test
@@ -0,0 +1,42 @@
+--source include/have_debug.inc
+--source include/master-slave.inc
+
+connection master;
+SET GLOBAL BINLOG_CHECKSUM=NONE;
+connection slave;
+SET GLOBAL BINLOG_CHECKSUM=NONE;
+connection master;
+
+--echo **** On Master ****
+CREATE TABLE t1 (a INT);
+
+INSERT INTO t1 VALUES (1),(2),(3);
+SELECT * FROM t1;
+
+# This will generate an incident log event and store it in the binary
+# log before the replace statement.
+REPLACE INTO t1 VALUES (4);
+
+--sync_slave_with_master
+
+# Now, we should have inserted the row into the table and the slave
+# should be running. We should also have rotated to a new binary log.
+
+SELECT * FROM t1;
+source include/check_slave_is_running.inc;
+
+connection master;
+
+--echo Should have two binary logs here
+--source include/show_binary_logs.inc
+DROP TABLE t1;
+--sync_slave_with_master
+
+
+connection master;
+SET GLOBAL BINLOG_CHECKSUM=default;
+connection slave;
+SET GLOBAL BINLOG_CHECKSUM=default;
+connection master;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_skip_replication.test b/mysql-test/suite/rpl/t/rpl_skip_replication.test
new file mode 100644
index 00000000..d1044c4b
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_skip_replication.test
@@ -0,0 +1,408 @@
+#
+# This include file is used by more than one test suite
+# (currently rpl and binlog_encryption).
+# Please check all dependent tests after modifying it.
+#
+# Usage:
+#
+# --let $use_remote_mysqlbinlog= 1 # optional
+# --source suite/rpl/include/rpl_skip_replication.inc
+#
+# The script uses MYSQLBINLOG to verify certain results.
+# By default, it uses binary logs directly. If it is undesirable,
+# this behavior can be overridden by setting $use_remote_binlog
+# as shown above.
+# The value will be unset after every execution of the script,
+# so if it is needed, it should be set explicitly before each call.
+#
+
+--source include/have_innodb.inc
+--source include/master-slave.inc
+
+--connection slave
+--source include/stop_slave.inc
+CHANGE MASTER TO MASTER_USE_GTID=NO;
+--source include/start_slave.inc
+--connection master
+
+connection slave;
+# Test that SUPER is required to change @@replicate_events_marked_for_skip.
+CREATE USER 'nonsuperuser'@'127.0.0.1';
+GRANT ALTER,CREATE,DELETE,DROP,EVENT,INSERT,PROCESS,REPLICATION SLAVE,
+ SELECT,UPDATE ON *.* TO 'nonsuperuser'@'127.0.0.1';
+connect(nonpriv, 127.0.0.1, nonsuperuser,, test, $SLAVE_MYPORT,);
+connection nonpriv;
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
+SET GLOBAL replicate_events_marked_for_skip=FILTER_ON_MASTER;
+disconnect nonpriv;
+connection slave;
+DROP USER'nonsuperuser'@'127.0.0.1';
+
+SELECT @@global.replicate_events_marked_for_skip;
+--error ER_SLAVE_MUST_STOP
+SET GLOBAL replicate_events_marked_for_skip=FILTER_ON_SLAVE;
+SELECT @@global.replicate_events_marked_for_skip;
+STOP SLAVE;
+--error ER_GLOBAL_VARIABLE
+SET SESSION replicate_events_marked_for_skip=FILTER_ON_MASTER;
+SELECT @@global.replicate_events_marked_for_skip;
+SET GLOBAL replicate_events_marked_for_skip=FILTER_ON_MASTER;
+SELECT @@global.replicate_events_marked_for_skip;
+START SLAVE;
+
+connection master;
+SELECT @@skip_replication;
+--error ER_LOCAL_VARIABLE
+SET GLOBAL skip_replication=1;
+SELECT @@skip_replication;
+
+CREATE TABLE t1 (a INT PRIMARY KEY, b INT) ENGINE=myisam;
+CREATE TABLE t2 (a INT PRIMARY KEY, b INT) ENGINE=innodb;
+INSERT INTO t1(a) VALUES (1);
+INSERT INTO t2(a) VALUES (1);
+
+
+# Test that master-side filtering works.
+SET skip_replication=1;
+
+CREATE TABLE t3 (a INT PRIMARY KEY, b INT) ENGINE=myisam;
+INSERT INTO t1(a) VALUES (2);
+INSERT INTO t2(a) VALUES (2);
+
+# Inject a rotate event in the binlog stream sent to slave (otherwise we will
+# fail sync_slave_with_master as the last event on the master is not present
+# on the slave).
+FLUSH NO_WRITE_TO_BINLOG LOGS;
+
+sync_slave_with_master;
+connection slave;
+SHOW TABLES;
+SELECT * FROM t1;
+SELECT * FROM t2;
+
+connection master;
+DROP TABLE t3;
+
+FLUSH NO_WRITE_TO_BINLOG LOGS;
+sync_slave_with_master;
+
+
+# Test that slave-side filtering works.
+connection slave;
+STOP SLAVE;
+SET GLOBAL replicate_events_marked_for_skip=FILTER_ON_SLAVE;
+START SLAVE;
+
+connection master;
+SET skip_replication=1;
+CREATE TABLE t3 (a INT PRIMARY KEY, b INT) ENGINE=myisam;
+INSERT INTO t1(a) VALUES (3);
+INSERT INTO t2(a) VALUES (3);
+
+# Inject a rotate event in the binlog stream sent to slave (otherwise we will
+# fail sync_slave_with_master as the last event on the master is not present
+# on the slave).
+FLUSH NO_WRITE_TO_BINLOG LOGS;
+
+sync_slave_with_master;
+connection slave;
+SHOW TABLES;
+SELECT * FROM t1;
+SELECT * FROM t2;
+
+connection master;
+DROP TABLE t3;
+
+FLUSH NO_WRITE_TO_BINLOG LOGS;
+sync_slave_with_master;
+connection slave;
+STOP SLAVE;
+SET GLOBAL replicate_events_marked_for_skip=REPLICATE;
+START SLAVE;
+
+
+# Test that events with @@skip_replication=1 are not filtered when filtering is
+# not set on slave.
+connection master;
+SET skip_replication=1;
+CREATE TABLE t3 (a INT PRIMARY KEY, b INT) ENGINE=myisam;
+INSERT INTO t3(a) VALUES(2);
+sync_slave_with_master;
+connection slave;
+SELECT * FROM t3;
+connection master;
+DROP TABLE t3;
+
+#
+# Test that the slave will preserve the @@skip_replication flag in its
+# own binlog.
+#
+
+TRUNCATE t1;
+sync_slave_with_master;
+connection slave;
+RESET MASTER;
+
+connection master;
+SET skip_replication=0;
+INSERT INTO t1 VALUES (1,0);
+SET skip_replication=1;
+INSERT INTO t1 VALUES (2,0);
+SET skip_replication=0;
+INSERT INTO t1 VALUES (3,0);
+
+sync_slave_with_master;
+connection slave;
+# Since slave has @@replicate_events_marked_for_skip=REPLICATE, it should have
+# applied all events.
+SELECT * FROM t1 ORDER by a;
+
+STOP SLAVE;
+SET GLOBAL replicate_events_marked_for_skip=FILTER_ON_MASTER;
+let $SLAVE_DATADIR= `select @@datadir`;
+
+connection master;
+TRUNCATE t1;
+
+# Now apply the slave binlog to the master, to check that both the slave
+# and mysqlbinlog will preserve the @@skip_replication flag.
+
+--let $mysqlbinlog_args= $SLAVE_DATADIR/slave-bin.000001
+if ($use_remote_mysqlbinlog)
+{
+ --let $mysqlbinlog_args= --read-from-remote-server --protocol=tcp --host=127.0.0.1 --port=$SLAVE_MYPORT -uroot slave-bin.000001
+ --let $use_remote_mysqlbinlog= 0
+}
+--exec $MYSQL_BINLOG $mysqlbinlog_args > $MYSQLTEST_VARDIR/tmp/rpl_skip_replication.binlog
+--exec $MYSQL test < $MYSQLTEST_VARDIR/tmp/rpl_skip_replication.binlog
+
+# The master should have all three events.
+SELECT * FROM t1 ORDER by a;
+
+# The slave should be missing event 2, which is marked with the
+# @@skip_replication flag.
+
+connection slave;
+START SLAVE;
+
+connection master;
+sync_slave_with_master;
+
+connection slave;
+SELECT * FROM t1 ORDER by a;
+
+#
+# Test that @@sql_slave_skip_counter does not count skipped @@skip_replication
+# events.
+#
+
+connection master;
+TRUNCATE t1;
+
+sync_slave_with_master;
+connection slave;
+STOP SLAVE;
+# We will skip two INSERTs (in addition to any skipped due to
+# @@skip_replication). Since from 5.5 every statement is wrapped in
+# BEGIN ... END, we need to skip 6 events for this.
+SET GLOBAL sql_slave_skip_counter=6;
+SET GLOBAL replicate_events_marked_for_skip=FILTER_ON_SLAVE;
+START SLAVE;
+
+connection master;
+# Need to fix @@binlog_format to get consistent event count.
+SET @old_binlog_format= @@binlog_format;
+SET binlog_format= statement;
+SET skip_replication=0;
+INSERT INTO t1 VALUES (1,5);
+SET skip_replication=1;
+INSERT INTO t1 VALUES (2,5);
+SET skip_replication=0;
+INSERT INTO t1 VALUES (3,5);
+INSERT INTO t1 VALUES (4,5);
+SET binlog_format= @old_binlog_format;
+
+sync_slave_with_master;
+connection slave;
+
+# The slave should have skipped the first three inserts (number 1 and 3 due
+# to @@sql_slave_skip_counter=2, number 2 due to
+# @@replicate_events_marked_for_skip=FILTER_ON_SLAVE). So only number 4
+# should be left.
+SELECT * FROM t1;
+
+
+#
+# Check that BINLOG statement preserves the @@skip_replication flag.
+#
+connection slave;
+# Need row @@binlog_format for BINLOG statements containing row events.
+--source include/stop_slave.inc
+SET @old_slave_binlog_format= @@global.binlog_format;
+SET GLOBAL binlog_format= row;
+--source include/start_slave.inc
+
+connection master;
+TRUNCATE t1;
+
+SET @old_binlog_format= @@binlog_format;
+SET binlog_format= row;
+# Format description log event.
+BINLOG 'wlZOTw8BAAAA8QAAAPUAAAAAAAQANS41LjIxLU1hcmlhREItZGVidWctbG9nAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAEzgNAAgAEgAEBAQEEgAA2QAEGggAAAAICAgCAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAA371saA==';
+# INSERT INTO t1 VALUES (1,8) # with @@skip_replication=1
+BINLOG 'wlZOTxMBAAAAKgAAAGMBAAAAgCkAAAAAAAEABHRlc3QAAnQxAAIDAwAC
+wlZOTxcBAAAAJgAAAIkBAAAAgCkAAAAAAAEAAv/8AQAAAAgAAAA=';
+# INSERT INTO t1 VALUES (2,8) # with @@skip_replication=0
+BINLOG 'wlZOTxMBAAAAKgAAADwCAAAAACkAAAAAAAEABHRlc3QAAnQxAAIDAwAC
+wlZOTxcBAAAAJgAAAGICAAAAACkAAAAAAAEAAv/8AgAAAAgAAAA=';
+SET binlog_format= @old_binlog_format;
+
+SELECT * FROM t1 ORDER BY a;
+sync_slave_with_master;
+connection slave;
+# Slave should have only the second insert, the first should be ignored due to
+# the @@skip_replication flag.
+SELECT * FROM t1 ORDER by a;
+
+--source include/stop_slave.inc
+SET GLOBAL binlog_format= @old_slave_binlog_format;
+--source include/start_slave.inc
+
+
+# Test that it is not possible to change @@skip_replication inside a
+# transaction or statement, thereby replicating only parts of statements
+# or transactions.
+connection master;
+SET skip_replication=0;
+
+BEGIN;
+--error ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_SKIP_REPLICATION
+SET skip_replication=0;
+--error ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_SKIP_REPLICATION
+SET skip_replication=1;
+ROLLBACK;
+SET skip_replication=1;
+BEGIN;
+--error ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_SKIP_REPLICATION
+SET skip_replication=0;
+--error ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_SKIP_REPLICATION
+SET skip_replication=1;
+COMMIT;
+SET autocommit=0;
+INSERT INTO t2(a) VALUES(100);
+--error ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_SKIP_REPLICATION
+SET skip_replication=1;
+ROLLBACK;
+SET autocommit=1;
+
+SET skip_replication=1;
+--delimiter |
+CREATE FUNCTION foo (x INT) RETURNS INT BEGIN SET SESSION skip_replication=x; RETURN x; END|
+CREATE PROCEDURE bar(x INT) BEGIN SET SESSION skip_replication=x; END|
+CREATE FUNCTION baz (x INT) RETURNS INT BEGIN CALL bar(x); RETURN x; END|
+--delimiter ;
+--error ER_STORED_FUNCTION_PREVENTS_SWITCH_SKIP_REPLICATION
+SELECT foo(0);
+--error ER_STORED_FUNCTION_PREVENTS_SWITCH_SKIP_REPLICATION
+SELECT baz(0);
+--error ER_STORED_FUNCTION_PREVENTS_SWITCH_SKIP_REPLICATION
+SET @a= foo(1);
+--error ER_STORED_FUNCTION_PREVENTS_SWITCH_SKIP_REPLICATION
+SET @a= baz(1);
+--error ER_STORED_FUNCTION_PREVENTS_SWITCH_SKIP_REPLICATION
+UPDATE t2 SET b=foo(0);
+--error ER_STORED_FUNCTION_PREVENTS_SWITCH_SKIP_REPLICATION
+UPDATE t2 SET b=baz(0);
+--error ER_STORED_FUNCTION_PREVENTS_SWITCH_SKIP_REPLICATION
+INSERT INTO t1 VALUES (101, foo(1));
+--error ER_STORED_FUNCTION_PREVENTS_SWITCH_SKIP_REPLICATION
+INSERT INTO t1 VALUES (101, baz(0));
+SELECT @@skip_replication;
+CALL bar(0);
+SELECT @@skip_replication;
+CALL bar(1);
+SELECT @@skip_replication;
+DROP FUNCTION foo;
+DROP PROCEDURE bar;
+DROP FUNCTION baz;
+
+
+# Test that master-side filtering happens on the master side, and that
+# slave-side filtering happens on the slave.
+
+# First test that events do not reach the slave when master-side filtering
+# is configured. Do this by replicating first with only the IO thread running
+# and master-side filtering; then change to no filtering and start the SQL
+# thread. This should still skip the events, as master-side filtering
+# means the events never reached the slave.
+connection master;
+SET skip_replication= 0;
+TRUNCATE t1;
+sync_slave_with_master;
+connection slave;
+STOP SLAVE;
+SET GLOBAL replicate_events_marked_for_skip=FILTER_ON_MASTER;
+START SLAVE IO_THREAD;
+connection master;
+SET skip_replication= 1;
+INSERT INTO t1(a) VALUES (1);
+SET skip_replication= 0;
+INSERT INTO t1(a) VALUES (2);
+--source include/save_master_pos.inc
+connection slave;
+--source include/sync_io_with_master.inc
+STOP SLAVE IO_THREAD;
+SET GLOBAL replicate_events_marked_for_skip=REPLICATE;
+START SLAVE;
+connection master;
+sync_slave_with_master;
+connection slave;
+# Now only the second insert of (2) should be visible, as the first was
+# filtered on the master, so even though the SQL thread ran without skipping
+# events, it will never see the event in the first place.
+SELECT * FROM t1;
+
+# Now tests that when slave-side filtering is configured, events _do_ reach
+# the slave.
+connection master;
+SET skip_replication= 0;
+TRUNCATE t1;
+sync_slave_with_master;
+connection slave;
+STOP SLAVE;
+SET GLOBAL replicate_events_marked_for_skip=FILTER_ON_SLAVE;
+START SLAVE IO_THREAD;
+connection master;
+SET skip_replication= 1;
+INSERT INTO t1(a) VALUES (1);
+SET skip_replication= 0;
+INSERT INTO t1(a) VALUES (2);
+--source include/save_master_pos.inc
+connection slave;
+--source include/sync_io_with_master.inc
+STOP SLAVE IO_THREAD;
+SET GLOBAL replicate_events_marked_for_skip=REPLICATE;
+START SLAVE;
+connection master;
+sync_slave_with_master;
+connection slave;
+# Now both inserts should be visible. Since filtering was configured to be
+# slave-side, the event is in the relay log, and when the SQL thread ran we
+# had disabled filtering again.
+SELECT * FROM t1 ORDER BY a;
+
+
+# Clean up.
+connection master;
+SET skip_replication=0;
+DROP TABLE t1,t2;
+connection slave;
+STOP SLAVE;
+SET GLOBAL replicate_events_marked_for_skip=REPLICATE;
+START SLAVE;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_slave_alias_replica.test b/mysql-test/suite/rpl/t/rpl_slave_alias_replica.test
new file mode 100644
index 00000000..06cf12ab
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_slave_alias_replica.test
@@ -0,0 +1,103 @@
+# ==== Purpose ====
+#
+# Test verifies that SQL statements which use keyword 'REPLICA' a synonym for
+# 'SLAVE' work as expected.
+#
+# ==== Implementation ====
+#
+# List of commands being verified are
+# On Master: SHOW REPLICA HOSTS
+# : Privilege "REPLICA"
+#
+# On Slave: START REPLICA
+# START REPLICA UNTIL
+# STOP REPLICA
+# SHOW REPLICA STATUS
+# RESET REPLICA ALL
+# REPLICA_POS
+#
+# ==== References ====
+#
+# MDEV-20601: Make REPLICA a synonym for SLAVE in SQL statements
+#
+
+--source include/have_innodb.inc
+--source include/master-slave.inc
+
+--echo "Command: STOP SLAVE --> STOP REPLICA"
+--connection slave
+STOP REPLICA;
+--source include/wait_for_slave_io_to_stop.inc
+--source include/wait_for_slave_sql_to_stop.inc
+
+--connection master
+CREATE USER 'repl_user';
+--echo "Privilege: SLAVE --> REPLICA"
+GRANT REPLICATION REPLICA on *.* TO repl_user;
+FLUSH PRIVILEGES;
+
+--connection slave
+--echo "SHOW SLAVE STATUS --> SHOW REPLICA STATUS"
+--let $master_user= query_get_value(SHOW REPLICA STATUS, Master_User, 1)
+CHANGE MASTER TO MASTER_USER= 'repl_user';
+--echo "Command: START SLAVE --> START REPLICA"
+START REPLICA;
+--source include/wait_for_slave_io_to_start.inc
+--source include/wait_for_slave_sql_to_start.inc
+
+--connection master
+--sync_slave_with_master
+
+--connection master
+--echo "Command: SHOW SLAVE HOSTS --> SHOW REPLICA HOSTS"
+let $show_statement= SHOW REPLICA HOSTS;
+let $field= Server_id;
+# Slave's server_id 2
+let $condition= ='2';
+source include/wait_show_condition.inc;
+DROP USER 'repl_user';
+--sync_slave_with_master
+
+--echo "Command: SHOW SLAVE IO/SQL THREAD --> SHOW REPLICA IO/SQL THREAD"
+STOP REPLICA IO_THREAD;
+STOP REPLICA SQL_THREAD;
+--source include/wait_for_slave_io_to_stop.inc
+--source include/wait_for_slave_sql_to_stop.inc
+--echo "Command: RESET SLAVE ALL --> RESET REPLICA ALL"
+RESET REPLICA ALL;
+set @@global.gtid_slave_pos= "";
+
+--connection master
+RESET MASTER;
+CREATE TABLE t(f INT) ENGINE=INNODB;
+INSERT INTO t VALUES (10);
+let $master_log_file= query_get_value(SHOW MASTER STATUS, File, 1);
+let $master_pos= query_get_value(SHOW MASTER STATUS, Position, 1);
+DROP TABLE t;
+
+--connection slave
+--replace_result $MASTER_MYPORT MASTER_PORT
+eval CHANGE MASTER TO MASTER_HOST='127.0.0.1',MASTER_PORT=$MASTER_MYPORT,MASTER_USER='$master_user';
+--echo "Command: START SLAVE UNTIL --> START REPLICA UNTIL"
+--replace_result $master_log_file MASTER_LOG_FILE $master_pos MASTER_POS
+--eval START REPLICA UNTIL MASTER_LOG_FILE='$master_log_file', MASTER_LOG_POS=$master_pos
+--source include/wait_for_slave_sql_to_stop.inc
+--source include/stop_slave_io.inc
+
+SELECT * FROM t;
+--let $slave_param= Exec_Master_Log_Pos
+--let $slave_param_value= $master_pos
+--source include/check_slave_param.inc
+
+--replace_result $MASTER_MYPORT MASTER_PORT
+--echo "MASTER_USE_GTID=SLAVE_POS --> MASTER_USE_GTID=REPLICA_POS"
+--replace_result $MASTER_MYPORT MASTER_PORT
+--eval CHANGE MASTER TO master_host = '127.0.0.1', master_port = $MASTER_MYPORT, MASTER_USE_GTID=REPLICA_POS
+--source include/start_slave.inc
+
+--connection master
+CREATE TABLE t2 (f INT PRIMARY KEY) ENGINE=INNODB;
+INSERT INTO t2 VALUES (10);
+DROP TABLE t2;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_slave_grp_exec.test b/mysql-test/suite/rpl/t/rpl_slave_grp_exec.test
new file mode 100644
index 00000000..5b08b2cd
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_slave_grp_exec.test
@@ -0,0 +1,186 @@
+#############################################################
+# Author: Serge Kozlov <skozlov@mysql.com>
+# Date: 03/21/2008
+# Purpose:
+# WL#3734 Test: slave group execution
+# Testing slave group execution: stop in middle of the group
+# (of events) should be immpossible on slave.
+# Group of events means set of statements between BEGIN/COMMIT
+# for transactional engines or a statement for
+# non-transactional engines that fires triggers and
+# affects to another tables.
+# Implementation of slave stop in middle of the group:
+# Delete the table on slave before start of the group
+# on master where this table is participant of the group.
+# So sql thread will failed inside of the group.
+# Expected results:
+# 1. For non-transactional engines w/o PK slave should trying
+# to complete executing of the group.
+# 2. For non-transactional engines slave should stop on
+# start position of the group.
+#############################################################
+--source include/have_innodb.inc
+--source include/master-slave.inc
+--echo
+
+# Create tables and data
+--echo *** Preparing data ***
+--connection master
+CREATE TABLE t1 (a INT NOT NULL, b VARCHAR(10)) ENGINE=MyISAM;
+CREATE TABLE t2 LIKE t1;
+CREATE TABLE t3 LIKE t1;
+
+DELIMITER |;
+CREATE TRIGGER tr1 BEFORE UPDATE ON t1
+ FOR EACH ROW BEGIN
+ UPDATE t2 SET b='YY' WHERE a=NEW.a;
+ END|
+CREATE TRIGGER tr2 AFTER UPDATE ON t1
+ FOR EACH ROW BEGIN
+ UPDATE t3 SET b='ZZ' WHERE a=NEW.a;
+ END|
+DELIMITER ;|
+--echo
+
+# Test non-transactional group with MyISAM tables w/o PK.
+# Data for t1,t2 should be replicated for SBR even t3
+# doesn't exist on slave
+--echo *** Test non-transactional group w/o PK ***
+
+--connection master
+INSERT INTO t3 VALUES(1, 'AA');
+INSERT INTO t2 VALUES(1, 'AA');
+INSERT INTO t1 VALUES(1, 'AA');
+--sync_slave_with_master
+
+RENAME TABLE t3 TO t3_bak;
+
+--connection master
+UPDATE t1 SET b = 'XX' WHERE a = 1;
+SELECT * FROM t1 ORDER BY a;
+SELECT * FROM t2 ORDER BY a;
+SELECT * FROM t3 ORDER BY a;
+
+--connection slave
+# 1146 = ER_NO_SUCH_TABLE
+call mtr.add_suppression("Slave SQL.*Table .test.t3. doesn.t exist.* error.* 1146");
+call mtr.add_suppression("At line *");
+--let $slave_sql_errno= 1146
+--source include/wait_for_slave_sql_error.inc
+SHOW TABLES LIKE 't%';
+if (`SELECT @@BINLOG_FORMAT = 'ROW'`) {
+--replace_regex /AA/AA_for_row_or_XX_for_stmt_mixed/
+ SELECT * FROM t1 ORDER BY a;
+--replace_regex /AA/AA_for_row_or_YY_for_stmt_mixed/
+ SELECT * FROM t2 ORDER BY a;
+}
+if (!`SELECT @@BINLOG_FORMAT = 'ROW'`) {
+--replace_regex /XX/AA_for_row_or_XX_for_stmt_mixed/
+ SELECT * FROM t1 ORDER BY a;
+--replace_regex /YY/AA_for_row_or_YY_for_stmt_mixed/
+ SELECT * FROM t2 ORDER BY a;
+}
+
+--source include/stop_slave_io.inc
+RENAME TABLE t3_bak TO t3;
+--source include/start_slave.inc
+
+--connection master
+TRUNCATE t1;
+TRUNCATE t2;
+TRUNCATE t3;
+--sync_slave_with_master
+--echo
+
+
+# Test non-transactional group with MyISAM tables and PK.
+# No data replicated because update based on PK
+--echo *** Test non-transactional group w/ PK ***
+
+--connection master
+ALTER TABLE t1 ADD PRIMARY KEY (a);
+ALTER TABLE t2 ADD PRIMARY KEY (a);
+ALTER TABLE t3 ADD PRIMARY KEY (a);
+
+--sync_slave_with_master
+RENAME TABLE t3 TO t3_bak;
+
+--connection master
+INSERT INTO t3 VALUES(2, 'B');
+INSERT INTO t2 VALUES(2, 'B');
+INSERT INTO t1 VALUES(2, 'B');
+UPDATE t1 SET b = 'X' WHERE a = 2;
+
+--connection slave
+# 1146 = ER_NO_SUCH_TABLE
+--let $slave_sql_errno= 1146
+--source include/wait_for_slave_sql_error.inc
+
+--connection master
+SELECT * FROM t1 ORDER BY a;
+SELECT * FROM t2 ORDER BY a;
+SELECT * FROM t3 ORDER BY a;
+
+--connection slave
+SHOW TABLES LIKE 't%';
+SELECT * FROM t1 ORDER BY a;
+SELECT * FROM t2 ORDER BY a;
+
+--source include/stop_slave_io.inc
+RENAME TABLE t3_bak TO t3;
+--source include/start_slave.inc
+
+--connection master
+TRUNCATE t1;
+TRUNCATE t2;
+TRUNCATE t3;
+--sync_slave_with_master
+--echo
+
+
+# Test transactional group with InnoDB tables with PK
+# No data replicated if errors happens inside transaction
+--echo *** Test transactional group w/ PK ***
+
+--connection master
+ALTER TABLE t1 ENGINE=InnoDB;
+ALTER TABLE t2 ENGINE=InnoDB;
+ALTER TABLE t3 ENGINE=InnoDB;
+
+--sync_slave_with_master
+RENAME TABLE t3 TO t3_bak;
+
+--connection master
+BEGIN;
+INSERT INTO t1 VALUES (3, 'C'), (4, 'D');
+INSERT INTO t2 VALUES (3, 'C'), (4, 'D');
+INSERT INTO t3 VALUES (3, 'C'), (4, 'D');
+COMMIT;
+
+--connection slave
+# 1146 = ER_NO_SUCH_TABLE
+--let $slave_sql_errno= 1146
+--source include/wait_for_slave_sql_error.inc
+
+--connection master
+SELECT * FROM t1 ORDER BY a;
+SELECT * FROM t2 ORDER BY a;
+SELECT * FROM t3 ORDER BY a;
+
+--connection slave
+SHOW TABLES LIKE 't%';
+SELECT * FROM t1 ORDER BY a;
+SELECT * FROM t2 ORDER BY a;
+
+source include/stop_slave_io.inc;
+RENAME TABLE t3_bak TO t3;
+source include/start_slave.inc;
+
+# Clean up
+--echo *** Clean up ***
+--connection master
+DROP TABLE t1,t2,t3;
+--sync_slave_with_master
+
+# End of 5.1 test
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_slave_invalid_external_user.test b/mysql-test/suite/rpl/t/rpl_slave_invalid_external_user.test
new file mode 100644
index 00000000..5099d7ee
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_slave_invalid_external_user.test
@@ -0,0 +1,42 @@
+# ==== Purpose ====
+#
+# Test verifies that when applier thread tries to access 'variable_name' of
+# INFORMATION_SCHEMA.SESSION_VARIABLES table through triggers it successfully
+# retrieves all the session variables.
+#
+# ==== Implementation ====
+#
+# Steps:
+# 0 - Create two tables t1 and t2.
+# 1 - Create a trigger such that it reads the names of all session variables
+# from INFORMATION_SCHEMA.SESSION_VARIABLES table and populates one of the
+# tables.
+# 2 - Do a DML on master and wait for it to be replicated and ensure that
+# slave is in sync with master and it is up and running.
+#
+# ==== References ====
+#
+# MDEV-14784: Slave crashes in show_status_array upon running a trigger with
+# select from I_S
+
+--source include/master-slave.inc
+--source include/have_binlog_format_mixed.inc
+--enable_connect_log
+CREATE USER test_user@localhost;
+SET PASSWORD FOR test_user@localhost = password('PWD');
+GRANT ALL ON *.* TO test_user@localhost WITH GRANT OPTION;
+connect(conn_test,localhost,test_user,PWD,test,$MASTER_MYPORT,$MASTER_MYSOCK);
+
+--connection conn_test
+CREATE TABLE t1 (f1 INT);
+CREATE TABLE t2 (f2 VARCHAR(64));
+CREATE TRIGGER tr_before BEFORE INSERT ON t1 FOR EACH ROW INSERT INTO t2 SELECT variable_name FROM INFORMATION_SCHEMA.SESSION_VARIABLES;
+CREATE DEFINER='root'@'localhost' TRIGGER tr_after AFTER INSERT ON t1 FOR EACH ROW INSERT INTO t2 SELECT variable_name FROM INFORMATION_SCHEMA.SESSION_VARIABLES;
+
+INSERT INTO t1 VALUES (1);
+--disable_connect_log
+# Cleanup
+--connection master
+DROP USER 'test_user'@'localhost';
+DROP TABLE t1, t2;
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_slave_load_in.test b/mysql-test/suite/rpl/t/rpl_slave_load_in.test
new file mode 100644
index 00000000..80a27479
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_slave_load_in.test
@@ -0,0 +1,49 @@
+##########################################################################
+# This test verifies if a slave is able to process a "LOAD DATA INFILE"
+# event while the "--secure-file-priv" option is set.
+#
+# The test is divided in two steps:
+# 1 - Creates tables and populates them through "LOAD DATA INFILE".
+# 2 - Compares the master and slave.
+##########################################################################
+--source include/have_innodb.inc
+--source include/master-slave.inc
+
+##########################################################################
+# Loading data
+##########################################################################
+connection master;
+
+create table t1(a int not null auto_increment, b int, primary key(a));
+create table t2(a int not null auto_increment, b int, primary key(a)) engine=innodb;
+
+load data infile '../../std_data/rpl_loaddata.dat' into table t1;
+
+start transaction;
+ insert into t2(b) values (1);
+ insert into t2(b) values (2);
+ load data infile '../../std_data/rpl_loaddata.dat' into table t2;
+ load data infile '../../std_data/rpl_loaddata.dat' into table t2;
+commit;
+
+##########################################################################
+# Checking Consistency
+##########################################################################
+sync_slave_with_master;
+
+let $diff_tables= master:t1, slave:t1;
+source include/diff_tables.inc;
+
+let $diff_tables= master:t2, slave:t2;
+source include/diff_tables.inc;
+
+##########################################################################
+# Clean up
+##########################################################################
+connection master;
+
+drop table t1;
+drop table t2;
+
+sync_slave_with_master;
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_slave_load_remove_tmpfile.test b/mysql-test/suite/rpl/t/rpl_slave_load_remove_tmpfile.test
new file mode 100644
index 00000000..10051408
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_slave_load_remove_tmpfile.test
@@ -0,0 +1,80 @@
+# ==== Purpose ====
+#
+# This test verifies if the slave fails gracefully when the temporary
+# file used to load data is removed while it is about to be used.
+# Similar errors are caught if the temporary directory is removed.
+#
+# ==== Implementation ====
+#
+# Steps:
+# 0 - Set debug variable remove_slave_load_file_before_write. This
+# causes the slave to remove the file.
+# 1 - Creates a table and populates it through "LOAD DATA INFILE".
+# 2 - Catches error.
+#
+# ==== References ====
+#
+# BUG#42861: Assigning invalid directories to --slave-load-tmpdir crashes the slave
+# BUG#11872422: rpl_slave_load_remove_tmpfile fails sporadically in pb2
+
+--source include/have_binlog_format_statement.inc
+--source include/have_innodb.inc
+--source include/have_debug.inc
+--source include/not_embedded.inc
+--source include/not_var_link.inc
+--source include/master-slave.inc
+
+##########################################################################
+# Loading data
+##########################################################################
+
+connection slave;
+SET @saved_dbug = @@GLOBAL.debug_dbug;
+SET @@global.debug_dbug= '+d,remove_slave_load_file_before_write';
+
+connection master;
+
+create table t1(a int not null auto_increment, b int, primary key(a)) engine=innodb;
+
+start transaction;
+ insert into t1(b) values (1);
+ insert into t1(b) values (2);
+ load data infile '../../std_data/rpl_loaddata.dat' into table t1;
+commit;
+
+##########################################################################
+# Catch Error
+##########################################################################
+connection slave;
+
+# windows and linux different error numbers here:
+# Windows:
+# - Last_Errno 29 (File not found)
+# Unix like OS:
+# - Last_Errno 13 (Can't stat file)
+--let $slave_sql_errno= 29, 13
+--source include/wait_for_slave_sql_error.inc
+
+##########################################################################
+# Clean up
+##########################################################################
+connection master;
+
+drop table t1;
+
+--source include/sync_slave_io_with_master.inc
+--source include/stop_slave_io.inc
+RESET SLAVE;
+
+drop table t1;
+
+call mtr.add_suppression("Slave: Can't get stat of .*");
+call mtr.add_suppression("Slave SQL: Error .Can.t get stat of.* error.* 13");
+call mtr.add_suppression("Slave: File.* not found.*");
+call mtr.add_suppression("Slave SQL: Error .File.* not found.* error.* 29");
+--let $rpl_only_running_threads= 1
+
+SET @@GLOBAL.debug_dbug = @saved_dbug;
+
+--source include/rpl_end.inc
+
diff --git a/mysql-test/suite/rpl/t/rpl_slave_load_tmpdir_not_exist-slave.opt b/mysql-test/suite/rpl/t/rpl_slave_load_tmpdir_not_exist-slave.opt
new file mode 100644
index 00000000..c4f91e97
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_slave_load_tmpdir_not_exist-slave.opt
@@ -0,0 +1 @@
+--slave-load-tmpdir=../../../error
diff --git a/mysql-test/suite/rpl/t/rpl_slave_load_tmpdir_not_exist.test b/mysql-test/suite/rpl/t/rpl_slave_load_tmpdir_not_exist.test
new file mode 100644
index 00000000..16dcd8ec
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_slave_load_tmpdir_not_exist.test
@@ -0,0 +1,22 @@
+##########################################################################
+# This test verifies if the start slave fails gracefuly when an
+# invalid directory is used to set --slave-load-tmpdir.
+##########################################################################
+--source include/have_log_bin.inc
+--source include/not_embedded.inc
+
+--let $rpl_skip_start_slave= 1
+--source include/master-slave.inc
+
+--connection slave
+START SLAVE;
+call mtr.add_suppression("Slave SQL.*Unable to use slave.s temporary directory");
+# 12 = EE_CANT_MKDIR
+--let $slave_sql_errno= 12
+source include/wait_for_slave_sql_error.inc;
+
+--source include/stop_slave_io.inc
+RESET SLAVE;
+
+--let $rpl_only_running_threads= 1
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_slave_max_statement_time.test b/mysql-test/suite/rpl/t/rpl_slave_max_statement_time.test
new file mode 100644
index 00000000..b600c843
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_slave_max_statement_time.test
@@ -0,0 +1,110 @@
+#
+# Purpose:
+# This test ensures that the slave can limit the execution time of its
+# events via the global system variable @@slave_max_statement_time.
+#
+# Methodology:
+# This test uses the following test cases to ensure that a slave will
+# correctly limit the execution time of its events:
+# 1) Using a serial slave, the SQL thread should time out when its underlying
+# event executes for longer than @@slave_max_statement_time.
+# 2) Using a parallel slave, a worker thread should time out when its
+# underlying event executes for longer than @@slave_max_statement_time.
+# 3) Load-based log events (from LOAD DATA INFILE) should time out if their
+# execution time exceeds @@slave_max_statement_time
+# 4) Locally executed long running statements should not time out due to
+# @@slave_max_statement_time.
+#
+# References:
+# MDEV-27161: Add option for SQL thread to limit maximum execution time per
+# query replicated
+#
+--source include/have_innodb.inc
+--source include/master-slave.inc
+
+--echo #
+--echo # Set up
+--echo #
+--connection master
+SET STATEMENT sql_log_bin=0 FOR CALL mtr.add_suppression("Unsafe statement written to the binary log using statement format");
+SET STATEMENT sql_log_bin=0 FOR CALL mtr.add_suppression("Unsafe statement written to the binary log using statement format");
+--connection slave
+SET STATEMENT sql_log_bin=0 FOR CALL mtr.add_suppression("Slave log event execution was interrupted");
+SET STATEMENT sql_log_bin=0 FOR CALL mtr.add_suppression("Unsafe statement written to the binary log using statement format");
+SET @save_slave_max_statement_time=@@GLOBAL.slave_max_statement_time;
+
+--let $with_lock= 1
+
+--echo #
+--echo # Test Case 1) Using a serial slave, the SQL thread should time out when
+--echo # its underlying event executes for longer than @@slave_max_statement_time.
+--echo #
+--source include/rpl_slave_max_statement_time.inc
+
+
+--echo #
+--echo # Test Case 2) Using a parallel slave, a worker thread should time out
+--echo # when its underlying event executes for longer than
+--echo # @@slave_max_statement_time
+--echo #
+
+--source include/stop_slave.inc
+SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads;
+SET @old_parallel_mode=@@GLOBAL.slave_parallel_mode;
+SET GLOBAL slave_parallel_threads=2;
+SET GLOBAL slave_parallel_mode='optimistic';
+--source include/start_slave.inc
+
+--source include/rpl_slave_max_statement_time.inc
+
+--source include/stop_slave.inc
+SET GLOBAL slave_parallel_mode=@old_parallel_mode;
+SET GLOBAL slave_parallel_threads=@old_parallel_threads;
+--source include/start_slave.inc
+
+
+--echo #
+--echo # Test Case 3) Load-based log events (from LOAD DATA INFILE) should time
+--echo # out if their execution time exceeds @@slave_max_statement_time
+--echo #
+--let $use_load_data= 1
+--source include/rpl_slave_max_statement_time.inc
+--let $use_load_data=
+
+
+--echo #
+--echo # Test Case 4) Locally executed long running statements should not time
+--echo # out due to @@slave_max_statement_time
+--echo #
+
+--connection slave
+--source include/stop_slave.inc
+SET @old_slave_max_statement_time=@@GLOBAL.slave_max_statement_time;
+SET @old_gtid_domain_id=@@GLOBAL.gtid_domain_id;
+SET @@GLOBAL.slave_max_statement_time=0.75;
+SET @@GLOBAL.gtid_domain_id=1;
+--source include/start_slave.inc
+
+CREATE TABLE t2 (a int);
+SET STATEMENT sql_log_bin=0 FOR INSERT INTO t2 SELECT SLEEP(1);
+--let $t2_count= `SELECT COUNT(*) FROM t2`
+if ($t2_count != 1)
+{
+ --die Local long running insert statement should have completed
+}
+DROP TABLE t2;
+
+--source include/stop_slave.inc
+SET GLOBAL gtid_domain_id=@old_gtid_domain_id;
+SET GLOBAL slave_max_statement_time=@old_slave_max_statement_time;
+--source include/start_slave.inc
+
+
+--echo # Cleanup
+--source include/stop_slave.inc
+SET GLOBAL slave_max_statement_time=@save_slave_max_statement_time;
+--source include/start_slave.inc
+
+--source include/rpl_end.inc
+
+--echo # End of rpl_slave_max_statement_time.test
diff --git a/mysql-test/suite/rpl/t/rpl_slave_shutdown_mdev20821.cnf b/mysql-test/suite/rpl/t/rpl_slave_shutdown_mdev20821.cnf
new file mode 100644
index 00000000..1e7cdee5
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_slave_shutdown_mdev20821.cnf
@@ -0,0 +1,19 @@
+!include suite/rpl/rpl_1slave_base.cnf
+!include include/default_client.cnf
+
+[mysqld.1]
+log-slave-updates
+gtid-domain-id=1
+
+[mysqld.2]
+log-slave-updates
+gtid-domain-id=2
+
+[mysqld.3]
+log-slave-updates
+gtid-domain-id=3
+slave_parallel_threads=2
+
+[ENV]
+SERVER_MYPORT_3= @mysqld.3.port
+SERVER_MYSOCK_3= @mysqld.3.socket
diff --git a/mysql-test/suite/rpl/t/rpl_slave_shutdown_mdev20821.test b/mysql-test/suite/rpl/t/rpl_slave_shutdown_mdev20821.test
new file mode 100644
index 00000000..6f73de98
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_slave_shutdown_mdev20821.test
@@ -0,0 +1,171 @@
+# MDEV-20821 parallel slave server shutdown hang
+#
+# Test the bug condition of a parallel slave server shutdown
+# hang when the parallel workers were idle.
+# The bug reported scenario is extented to cover the multi-sources case as well as
+# checking is done for both the idle and busy workers cases.
+#
+# MDEV-25336 Parallel replication causes failed assert while restarting
+# Since this test case involves slave restart this will help in testing
+# Mdev-25336 too.
+
+--source include/have_innodb.inc
+--source include/have_binlog_format_mixed.inc
+--let $rpl_topology= 1->3
+--source include/rpl_init.inc
+
+#
+# A. idle workers.
+#
+--connection server_3
+set default_master_connection = '';
+--source include/start_slave.inc
+
+set default_master_connection = 'm2';
+--replace_result $SERVER_MYPORT_2 SERVER_MYPORT_2
+eval change master to master_host='127.0.0.1', master_port=$SERVER_MYPORT_2, master_user='root', master_use_gtid=slave_pos;
+--source include/start_slave.inc
+
+select @@global.slave_parallel_workers as two;
+
+# At this point worker threads have no assignement.
+# Shutdown must not hang.
+# In 10.2/10.3 there should not be any assert failure `prev != 0 && next != 0'
+--connection server_3
+--write_file $MYSQLTEST_VARDIR/tmp/mysqld.3.expect
+wait
+EOF
+--send SHUTDOWN
+--reap
+--source include/wait_until_disconnected.inc
+
+--connection server_3
+--append_file $MYSQLTEST_VARDIR/tmp/mysqld.3.expect
+restart
+EOF
+
+# No hang is *proved* to occur when this point is reached.
+--connection server_3
+--enable_reconnect
+--source include/wait_until_connected_again.inc
+
+#
+# B. resting workers after some busy time
+#
+--connection server_1
+create table t1 (i int primary key) engine=Innodb;
+
+--connection server_2
+create table t2 (i int primary key) engine=Innodb;
+
+--connection server_3
+set default_master_connection = '';
+--source include/start_slave.inc
+
+set default_master_connection = 'm2';
+--source include/start_slave.inc
+
+--connection server_2
+insert into t2 values (1);
+--save_master_pos
+
+--connection server_3
+--sync_with_master 0,'m2'
+
+--connection server_1
+insert into t1 values (1);
+--save_master_pos
+
+--connection server_3
+--sync_with_master 0,''
+
+# In 10.2/10.3 there should not be any assert failure `prev != 0 && next != 0'
+# At this point worker threads have no assignement.
+# Shutdown must not hang.
+
+--connection server_3
+--write_file $MYSQLTEST_VARDIR/tmp/mysqld.3.expect
+wait
+EOF
+--send SHUTDOWN
+--reap
+--source include/wait_until_disconnected.inc
+
+--connection server_3
+--append_file $MYSQLTEST_VARDIR/tmp/mysqld.3.expect
+restart
+EOF
+
+# No hang is *proved* to occur when this point is reached.
+--connection server_3
+--enable_reconnect
+--source include/wait_until_connected_again.inc
+
+#
+# C. busy workers
+#
+--connection server_3
+set default_master_connection = '';
+--source include/start_slave.inc
+
+set default_master_connection = 'm2';
+--source include/start_slave.inc
+
+--connect (conn_block_server3, 127.0.0.1, root,, test, $SERVER_MYPORT_3,)
+begin;
+ insert into t1 values (2);
+ insert into t2 values (2);
+
+--connection server_1
+insert into t1 values (2);
+--connection server_2
+insert into t2 values (2);
+
+
+# In 10.2/10.3 there should not be any assert failure `prev != 0 && next != 0'
+# At this point there's a good chance the worker threads are busy.
+# SHUTDOWN must proceed without any delay as above.
+--connection server_3
+--write_file $MYSQLTEST_VARDIR/tmp/mysqld.3.expect
+wait
+EOF
+--send SHUTDOWN
+--reap
+--source include/wait_until_disconnected.inc
+
+--connection server_3
+--append_file $MYSQLTEST_VARDIR/tmp/mysqld.3.expect
+restart
+EOF
+
+# No hang is *proved* to occur when this point is reached.
+--connection server_3
+--enable_reconnect
+--source include/wait_until_connected_again.inc
+
+
+# Cleanup
+
+--connection server_3
+set default_master_connection = '';
+--source include/start_slave.inc
+
+set default_master_connection = 'm2';
+--source include/start_slave.inc
+
+--connection server_1
+drop table t1;
+
+--connection server_2
+drop table t2;
+--save_master_pos
+
+# (!) The following block is critical to avoid check-mysqld_3.reject by mtr:
+--connection server_3
+--sync_with_master 0,'m2'
+set default_master_connection = 'm2';
+--source include/stop_slave.inc
+RESET SLAVE ALL;
+set default_master_connection = '';
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_slave_skip.test b/mysql-test/suite/rpl/t/rpl_slave_skip.test
new file mode 100644
index 00000000..933e7d14
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_slave_skip.test
@@ -0,0 +1,293 @@
+# Every statement in this test is either executing under ROW or
+# STATEMENT format, which requires the slave thread to be able to apply
+# both statement and row events. Hence, we only need to execute this
+# test for MIXED mode.
+source include/have_binlog_format_mixed.inc;
+
+source include/have_innodb.inc;
+source include/master-slave.inc;
+
+connection slave;
+source include/have_innodb.inc;
+STOP SLAVE;
+--source include/wait_for_slave_to_stop.inc
+
+connection master;
+SET SESSION BINLOG_FORMAT=ROW;
+
+CREATE TABLE t1 (a INT, b INT) ENGINE=MyISAM;
+CREATE TABLE t2 (c INT, d INT) ENGINE=MyISAM;
+INSERT INTO t1 VALUES (1,1),(2,4),(3,9);
+INSERT INTO t2 VALUES (1,1),(2,8),(3,27);
+let $master_log_pos= query_get_value(SHOW MASTER STATUS, Position, 1);
+UPDATE t1,t2 SET b = d, d = b * 2 WHERE a = c;
+source include/show_binlog_events.inc;
+
+# These tables should be changed
+SELECT * FROM t1;
+SELECT * FROM t2;
+save_master_pos;
+connection slave;
+
+# Stop when reaching the the first table map event.
+--replace_result $master_log_pos MASTER_LOG_POS
+eval START SLAVE UNTIL MASTER_LOG_FILE='master-bin.000001', MASTER_LOG_POS=$master_log_pos;
+source include/wait_for_slave_sql_to_stop.inc;
+let $slave_param= Exec_Master_Log_Pos;
+let $slave_param_value= $master_log_pos;
+source include/check_slave_param.inc;
+source include/check_slave_no_error.inc;
+
+# Now we skip *one* table map event. If the execution starts right
+# after that table map event, *one* of the involved tables will be
+# changed.
+SET GLOBAL SQL_SLAVE_SKIP_COUNTER=1;
+START SLAVE;
+--source include/wait_for_slave_to_start.inc
+sync_with_master;
+
+# These values should be what was inserted, not what was
+# updated. Since we are skipping the first table map of the group
+# representing the UPDATE statement above, we should skip the entire
+# group and not start executing at the first table map.
+SELECT * FROM t1;
+SELECT * FROM t2;
+
+STOP SLAVE;
+--source include/wait_for_slave_to_stop.inc
+--source include/reset_slave.inc
+connection master;
+RESET MASTER;
+
+SET SESSION BINLOG_FORMAT=STATEMENT;
+SET @foo = 12;
+let $master_log_pos= query_get_value(SHOW MASTER STATUS, Position, 1);
+INSERT INTO t1 VALUES(@foo, 2*@foo);
+save_master_pos;
+source include/show_binlog_events.inc;
+
+connection slave;
+--replace_result $master_log_pos MASTER_LOG_POS
+eval START SLAVE UNTIL MASTER_LOG_FILE='master-bin.000001', MASTER_LOG_POS=$master_log_pos;
+source include/wait_for_slave_sql_to_stop.inc;
+SET GLOBAL SQL_SLAVE_SKIP_COUNTER=1;
+START SLAVE;
+--source include/wait_for_slave_to_start.inc
+sync_with_master;
+
+connection master;
+DROP TABLE t1, t2;
+sync_slave_with_master;
+
+#
+# More tests for BUG#28618
+#
+# Case 1.
+# ROW binlog format and non-transactional tables.
+# Create the group of events via triggers and try to skip
+# some items of that group.
+#
+
+connection master;
+SET SESSION BINLOG_FORMAT=ROW;
+SET AUTOCOMMIT=0;
+
+CREATE TABLE t1 (a INT, b VARCHAR(20)) ENGINE=myisam;
+CREATE TABLE t2 (a INT, b VARCHAR(20)) ENGINE=myisam;
+CREATE TABLE t3 (a INT, b VARCHAR(20)) ENGINE=myisam;
+
+INSERT INTO t1 VALUES (1,'master/slave');
+INSERT INTO t2 VALUES (1,'master/slave');
+INSERT INTO t3 VALUES (1,'master/slave');
+
+DELIMITER |;
+
+CREATE TRIGGER tr1 AFTER UPDATE on t1 FOR EACH ROW
+BEGIN
+ INSERT INTO t2 VALUES (NEW.a,NEW.b);
+ DELETE FROM t2 WHERE a < NEW.a;
+END|
+
+CREATE TRIGGER tr2 AFTER INSERT on t2 FOR EACH ROW
+BEGIN
+ UPDATE t3 SET a =2, b = 'master only';
+END|
+
+DELIMITER ;|
+
+sync_slave_with_master;
+source include/stop_slave.inc;
+
+connection master;
+UPDATE t1 SET a = 2, b = 'master only' WHERE a = 1;
+DROP TRIGGER tr1;
+DROP TRIGGER tr2;
+INSERT INTO t1 VALUES (3,'master/slave');
+INSERT INTO t2 VALUES (3,'master/slave');
+INSERT INTO t3 VALUES (3,'master/slave');
+COMMIT;
+
+SELECT * FROM t1 ORDER BY a;
+SELECT * FROM t2 ORDER BY a;
+SELECT * FROM t3 ORDER BY a;
+
+save_master_pos;
+
+connection slave;
+SET GLOBAL SQL_SLAVE_SKIP_COUNTER=1;
+source include/start_slave.inc;
+sync_with_master;
+
+SELECT * FROM t1 ORDER BY a;
+SELECT * FROM t2 ORDER BY a;
+SELECT * FROM t3 ORDER BY a;
+
+connection master;
+DROP TABLE t1, t2, t3;
+sync_slave_with_master;
+
+--echo **** Case 2: Row binlog format and transactional tables ****
+
+# Create the transaction and try to skip some
+# queries from one.
+
+connection master;
+CREATE TABLE t4 (a INT, b VARCHAR(20)) ENGINE=innodb;
+CREATE TABLE t5 (a INT, b VARCHAR(20)) ENGINE=innodb;
+CREATE TABLE t6 (a INT, b VARCHAR(20)) ENGINE=innodb;
+
+sync_slave_with_master;
+source include/stop_slave.inc;
+
+connection master;
+BEGIN;
+INSERT INTO t4 VALUES (2, 'master only');
+INSERT INTO t5 VALUES (2, 'master only');
+INSERT INTO t6 VALUES (2, 'master only');
+COMMIT;
+
+BEGIN;
+INSERT INTO t4 VALUES (3, 'master/slave');
+INSERT INTO t5 VALUES (3, 'master/slave');
+INSERT INTO t6 VALUES (3, 'master/slave');
+COMMIT;
+
+SELECT * FROM t4 ORDER BY a;
+SELECT * FROM t5 ORDER BY a;
+SELECT * FROM t6 ORDER BY a;
+
+save_master_pos;
+
+connection slave;
+SET GLOBAL SQL_SLAVE_SKIP_COUNTER=1;
+source include/start_slave.inc;
+sync_with_master;
+
+SELECT * FROM t4 ORDER BY a;
+SELECT * FROM t5 ORDER BY a;
+SELECT * FROM t6 ORDER BY a;
+
+# Test skipping two groups
+
+connection slave;
+source include/stop_slave.inc;
+
+connection master;
+BEGIN;
+INSERT INTO t4 VALUES (6, 'master only');
+INSERT INTO t5 VALUES (6, 'master only');
+INSERT INTO t6 VALUES (6, 'master only');
+COMMIT;
+
+BEGIN;
+INSERT INTO t4 VALUES (7, 'master only');
+INSERT INTO t5 VALUES (7, 'master only');
+INSERT INTO t6 VALUES (7, 'master only');
+COMMIT;
+
+SELECT * FROM t4 ORDER BY a;
+SELECT * FROM t5 ORDER BY a;
+SELECT * FROM t6 ORDER BY a;
+
+save_master_pos;
+
+connection slave;
+SET GLOBAL SQL_SLAVE_SKIP_COUNTER=12;
+source include/start_slave.inc;
+sync_with_master;
+
+SELECT * FROM t4 ORDER BY a;
+SELECT * FROM t5 ORDER BY a;
+SELECT * FROM t6 ORDER BY a;
+
+#
+# And the same, but with autocommit = 0
+#
+connection slave;
+source include/stop_slave.inc;
+
+connection master;
+SET AUTOCOMMIT=0;
+
+INSERT INTO t4 VALUES (4, 'master only');
+INSERT INTO t5 VALUES (4, 'master only');
+INSERT INTO t6 VALUES (4, 'master only');
+COMMIT;
+
+INSERT INTO t4 VALUES (5, 'master/slave');
+INSERT INTO t5 VALUES (5, 'master/slave');
+INSERT INTO t6 VALUES (5, 'master/slave');
+COMMIT;
+
+SELECT * FROM t4 ORDER BY a;
+SELECT * FROM t5 ORDER BY a;
+SELECT * FROM t6 ORDER BY a;
+
+save_master_pos;
+
+connection slave;
+SET GLOBAL SQL_SLAVE_SKIP_COUNTER=1;
+source include/start_slave.inc;
+sync_with_master;
+
+SELECT * FROM t4 ORDER BY a;
+SELECT * FROM t5 ORDER BY a;
+SELECT * FROM t6 ORDER BY a;
+
+connection master;
+DROP TABLE t4, t5, t6;
+sync_slave_with_master;
+
+--echo **** Case 3: Statement logging format and LOAD DATA with non-transactional table ****
+
+# LOAD DATA creates two events in binary log for statement binlog format.
+# Try to skip the first.
+
+connection master;
+CREATE TABLE t10 (a INT, b VARCHAR(20)) ENGINE=myisam;
+
+sync_slave_with_master;
+source include/stop_slave.inc;
+
+connection master;
+SET SESSION BINLOG_FORMAT=STATEMENT;
+
+--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
+eval LOAD DATA INFILE '$MYSQLTEST_VARDIR/std_data/rpl_bug28618.dat' INTO TABLE t10 FIELDS TERMINATED BY '|';
+
+SELECT * FROM t10 ORDER BY a;
+
+save_master_pos;
+
+connection slave;
+SET GLOBAL SQL_SLAVE_SKIP_COUNTER=1;
+source include/start_slave.inc;
+sync_with_master;
+
+SELECT * FROM t10 ORDER BY a;
+
+connection master;
+DROP TABLE t10;
+sync_slave_with_master;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_slave_status.test b/mysql-test/suite/rpl/t/rpl_slave_status.test
new file mode 100644
index 00000000..63e37216
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_slave_status.test
@@ -0,0 +1,81 @@
+# ==== Purpose ====
+#
+# Verify that a slave without replication privileges has
+# Slave_IO_Running = No
+# Check that relay_log_status doesn't change by CHANGE MASTER
+# ==== Method ====
+#
+# We do the following steps:
+# - Create a new replication user on master
+# - Connect to slave and start replication as this user.
+# - Verify that slave can replicate well, by creating a table and
+# inserting a row into it.
+# - Delete the user from the master.
+# - Stop and start the slave (this should fail).
+# - Check the Slave_IO_Running column of SHOW SLAVE STATUS.
+#
+# ==== Related bugs ====
+#
+# BUG#10780: slave can't connect to master - IO and SQL threads running
+
+--source include/master-slave.inc
+
+--echo ==== Create new replication user ====
+connection master;
+GRANT REPLICATION SLAVE ON *.* TO rpl@127.0.0.1 IDENTIFIED BY 'rpl';
+
+sync_slave_with_master;
+source include/stop_slave.inc;
+
+# Test that relay_log_purge doesn't change because of CHANGE MASTER
+set @save_relay_log_purge=@@global.relay_log_purge;
+set @@global.relay_log_purge=0;
+CHANGE MASTER TO master_user='rpl', master_password='rpl';
+select @@global.relay_log_purge;
+set @@global.relay_log_purge=1;
+CHANGE MASTER TO master_user='rpl', master_password='rpl';
+select @@global.relay_log_purge;
+set @@global.relay_log_purge=@save_relay_log_purge;
+
+CHANGE MASTER TO master_user='rpl', master_password='rpl';
+source include/start_slave.inc;
+
+--echo ==== Do replication as new user ====
+connection master;
+CREATE TABLE t1 (n INT);
+INSERT INTO t1 VALUES (1);
+sync_slave_with_master;
+SELECT * FROM t1;
+
+--echo ==== Delete new replication user ====
+connection master;
+DROP USER rpl@127.0.0.1;
+FLUSH PRIVILEGES;
+
+sync_slave_with_master;
+
+--echo ==== Restart slave without privileges =====
+# (slave.err will contain access denied error for this START SLAVE command)
+source include/stop_slave.inc;
+START SLAVE;
+source include/wait_for_slave_sql_to_start.inc;
+source include/wait_for_slave_io_to_stop.inc;
+
+--echo ==== Verify that Slave IO thread stopped with error ====
+# 1045 = ER_ACCESS_DENIED_ERROR
+--let $slave_io_errno= 1045
+--source include/wait_for_slave_io_error.inc
+
+--echo ==== Cleanup (Note that slave IO thread is not running) ====
+
+# cleanup: slave io thread has is stopped so we reset replication
+--source include/stop_slave_sql.inc
+CHANGE MASTER TO MASTER_USER = 'root', MASTER_PASSWORD = '';
+# clear Slave_IO_Errno
+--let $rpl_only_running_threads= 1
+--source include/rpl_reset.inc
+
+connection master;
+DROP TABLE t1;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_slow_query_log-slave.opt b/mysql-test/suite/rpl/t/rpl_slow_query_log-slave.opt
new file mode 100644
index 00000000..43911726
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_slow_query_log-slave.opt
@@ -0,0 +1 @@
+--log-slow-slave-statements --slow-query-log
diff --git a/mysql-test/suite/rpl/t/rpl_slow_query_log.test b/mysql-test/suite/rpl/t/rpl_slow_query_log.test
new file mode 100644
index 00000000..2d5d08a4
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_slow_query_log.test
@@ -0,0 +1,345 @@
+#
+# BUG#23300: Slow query log on slave does not log slow replicated statements
+#
+# Description:
+# The slave should log slow queries replicated from master when
+# --log-slow-slave-statements is used.
+#
+# Test is implemented as follows:
+# i) stop slave
+# ii) On slave, set long_query_time to a small value.
+# ii) start slave so that long_query_time variable is picked by sql thread
+# iii) On master, do one short time query and one long time query, on slave
+# and check that slow query is logged to slow query log but fast query
+# is not.
+# iv) On slave, check that slow queries go into the slow log and fast don't,
+# when issued through a regular client connection
+# v) On slave, check that slow queries go into the slow log and fast don't
+# when we use SET TIMESTAMP= 1 on a regular client connection.
+# vi) check that when setting slow_query_log= OFF in a connection 'extra2'
+# prevents logging slow queries in a connection 'extra'
+#
+# OBS:
+# This test only runs for statement binlogging format because on row format
+# slow queries do not get slow query logged.
+# Note that due to the sleep() command the insert is written to the binary
+# log in row format.
+
+source include/have_binlog_format_statement.inc;
+source include/master-slave.inc;
+
+CALL mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT");
+call mtr.add_suppression("Slave SQL.*Request to stop slave SQL Thread received while applying a group that has non-transactional changes; waiting for completion of the group");
+
+# Prepare slave for different long_query_time we need to stop the slave
+# and restart it as long_query_time variable is dynamic and, after
+# setting it, it only takes effect on new connections.
+#
+# Reference:
+# http://dev.mysql.com/doc/refman/6.0/en/set-option.html
+connection slave;
+
+source include/stop_slave.inc;
+
+SET @old_log_output= @@log_output;
+SET GLOBAL log_output= 'TABLE';
+SET @old_long_query_time= @@long_query_time;
+SET GLOBAL long_query_time= 2;
+TRUNCATE mysql.slow_log;
+
+source include/start_slave.inc;
+
+--disable_ps2_protocol
+connection master;
+CREATE TABLE t1 (a int, b int);
+
+# test:
+# check that slave logs the slow query to the slow log, but not the fast one.
+
+let $slow_query= INSERT INTO t1 values(1, sleep(3));
+let $fast_query= INSERT INTO t1 values(1, 1);
+
+eval $fast_query;
+--disable_warnings
+eval $slow_query;
+--enable_warnings
+sync_slave_with_master;
+
+let $found_fast_query= `SELECT count(*) = 1 FROM mysql.slow_log WHERE sql_text like '$fast_query'`;
+let $found_slow_query= `SELECT count(*) = 1 FROM mysql.slow_log WHERE sql_text like '$slow_query'`;
+
+if ($found_fast_query)
+{
+ SELECT * FROM mysql.slow_log;
+ die "Assertion failed! Fast query FOUND in slow query log. Bailing out!";
+}
+
+if (!$found_slow_query)
+{
+ SELECT * FROM mysql.slow_log;
+ die "Assertion failed! Slow query NOT FOUND in slow query log. Bailing out!";
+}
+TRUNCATE mysql.slow_log;
+
+# regular checks for slow query log (using a new connection - 'extra' - to slave)
+
+# test:
+# when using direct connections to the slave, check that slow query is logged
+# but not the fast one.
+
+connect(extra,127.0.0.1,root,,test,$SLAVE_MYPORT);
+connection extra;
+
+let $fast_query= SELECT 1;
+let $slow_query= SELECT 1, sleep(3);
+
+eval $slow_query;
+eval $fast_query;
+
+let $found_fast_query= `SELECT count(*) = 1 FROM mysql.slow_log WHERE sql_text like '$fast_query'`;
+let $found_slow_query= `SELECT count(*) = 1 FROM mysql.slow_log WHERE sql_text like '$slow_query'`;
+
+if ($found_fast_query)
+{
+ SELECT * FROM mysql.slow_log;
+ die "Assertion failed! Fast query FOUND in slow query log. Bailing out!";
+}
+
+if (!$found_slow_query)
+{
+ SELECT * FROM mysql.slow_log;
+ die "Assertion failed! Slow query NOT FOUND in slow query log. Bailing out!";
+}
+TRUNCATE mysql.slow_log;
+
+# test:
+# when using direct connections to the slave, check that when setting timestamp to 1 the
+# slow query is logged but the fast one is not.
+
+let $fast_query= SELECT 2;
+let $slow_query= SELECT 2, sleep(3);
+
+SET TIMESTAMP= 1;
+eval $slow_query;
+eval $fast_query;
+
+let $found_fast_query= `SELECT count(*) = 1 FROM mysql.slow_log WHERE sql_text like '$fast_query'`;
+let $found_slow_query= `SELECT count(*) = 1 FROM mysql.slow_log WHERE sql_text like '$slow_query'`;
+
+if ($found_fast_query)
+{
+ SELECT * FROM mysql.slow_log;
+ die "Assertion failed! Fast query FOUND in slow query log. Bailing out!";
+}
+
+if (!$found_slow_query)
+{
+ SELECT * FROM mysql.slow_log;
+ die "Assertion failed! Slow query NOT FOUND in slow query log. Bailing out!";
+}
+TRUNCATE mysql.slow_log;
+
+# test:
+# check that when setting the slow_query_log= OFF on connection 'extra2'
+# prevents connection 'extra' from logging to slow query log.
+
+let $fast_query= SELECT 3;
+let $slow_query= SELECT 3, sleep(3);
+
+connect(extra2,127.0.0.1,root,,test,$SLAVE_MYPORT);
+connection extra2;
+
+SET @old_slow_query_log= @@slow_query_log;
+SET GLOBAL slow_query_log= 'OFF';
+
+connection extra;
+
+eval $slow_query;
+eval $fast_query;
+
+let $found_fast_query= `SELECT count(*) = 1 FROM mysql.slow_log WHERE sql_text like '$fast_query'`;
+let $found_slow_query= `SELECT count(*) = 1 FROM mysql.slow_log WHERE sql_text like '$slow_query'`;
+
+if ($found_fast_query)
+{
+ SELECT * FROM mysql.slow_log;
+ die "Assertion failed! Fast query FOUND in slow query log when slow_query_log= OFF. Bailing out!";
+}
+
+if ($found_slow_query)
+{
+ SELECT * FROM mysql.slow_log;
+ die "Assertion failed! Slow query FOUND in slow query log when slow_query_log= OFF. Bailing out!";
+}
+TRUNCATE mysql.slow_log;
+
+# clean up: drop tables, reset the variables back to the previous value,
+# disconnect extra connections
+connection extra2;
+
+SET GLOBAL slow_query_log= @old_slow_query_log;
+
+connection master;
+DROP TABLE t1;
+sync_slave_with_master;
+
+source include/stop_slave.inc;
+
+SET GLOBAL long_query_time= @old_long_query_time;
+SET GLOBAL log_output= @old_log_output;
+
+source include/start_slave.inc;
+
+disconnect extra;
+disconnect extra2;
+
+#
+# BUG#50620: Adding an index to a table prevents slave from logging into slow log
+#
+
+--source include/rpl_reset.inc
+
+-- connection master
+SET @old_log_output= @@log_output;
+SET GLOBAL log_output= 'TABLE';
+SET GLOBAL long_query_time= 2;
+SET @old_long_query_time= @@long_query_time;
+SET SESSION long_query_time= 2;
+TRUNCATE mysql.slow_log;
+-- connection slave
+
+-- source include/stop_slave.inc
+SET @old_log_output= @@log_output;
+SET GLOBAL log_output= 'TABLE';
+SET @old_long_query_time= @@long_query_time;
+SET GLOBAL long_query_time= 2;
+TRUNCATE mysql.slow_log;
+-- source include/start_slave.inc
+
+let $slow_query= INSERT INTO t1 values(1, sleep(3));
+
+-- connection master
+CREATE TABLE t1 (a int, b int);
+
+-- echo ********************************************************************
+-- echo **** INSERT one row that exceeds long_query_time
+-- echo **** Outcome: query ends up in both master and slave slow log
+-- echo ********************************************************************
+
+-- disable_warnings
+-- eval $slow_query
+-- enable_warnings
+
+let $master_slow_query= `SELECT count(*) = 1 FROM mysql.slow_log WHERE sql_text like '$slow_query'`;
+-- sync_slave_with_master
+let $slave_slow_query= `SELECT count(*) = 1 FROM mysql.slow_log WHERE sql_text like '$slow_query'`;
+
+if ($master_slow_query != $slave_slow_query)
+{
+ -- connection master
+ -- echo ***********************************************
+ -- echo ** DUMPING MASTER SLOW LOG CONTENTS
+ -- echo ***********************************************
+ SELECT * FROM mysql.slow_log;
+
+ -- connection slave
+ -- echo ***********************************************
+ -- echo ** DUMPING SLAVE SLOW LOG CONTENTS
+ -- echo ***********************************************
+ SELECT * FROM mysql.slow_log;
+
+ -- die "Assertion failed! Master and slave slow log contents differ. Bailing out!"
+}
+
+if ($master_slow_query == $slave_slow_query)
+{
+ -- echo ### Assertion is good. Both Master and Slave exhibit the
+ -- echo ### same number of queries in slow log: $master_slow_query
+}
+
+TRUNCATE mysql.slow_log;
+-- connection master
+TRUNCATE mysql.slow_log;
+
+-- echo ********************************************************************
+-- echo **** Now do inserts again, but first add an index to the table.
+-- echo **** Outcome: Note that the slave contains the same one entry (as
+-- echo **** the master does) whereas before the patch it did not.
+-- echo ********************************************************************
+
+ALTER TABLE t1 ADD INDEX id1(a);
+
+-- disable_warnings
+-- eval $slow_query
+-- enable_warnings
+
+let $master_slow_query= `SELECT count(*) = 1 FROM mysql.slow_log WHERE sql_text like '$slow_query'`;
+-- sync_slave_with_master
+let $slave_slow_query= `SELECT count(*) = 1 FROM mysql.slow_log WHERE sql_text like '$slow_query'`;
+
+if ($master_slow_query != $slave_slow_query)
+{
+ -- connection master
+ -- echo ***********************************************
+ -- echo ** DUMPING MASTER SLOW LOG CONTENTS
+ -- echo ***********************************************
+ SELECT * FROM mysql.slow_log;
+
+ -- connection slave
+ -- echo ***********************************************
+ -- echo ** DUMPING SLAVE SLOW LOG CONTENTS
+ -- echo ***********************************************
+ SELECT * FROM mysql.slow_log;
+
+ -- die "Assertion failed! Master and slave slow log contents differ. Bailing out!"
+}
+
+if ($master_slow_query == $slave_slow_query)
+{
+ -- echo ### Assertion is good. Both Master and Slave exhibit the
+ -- echo ### same number of queries in slow log: $master_slow_query
+}
+
+-- echo ********************************************************************
+-- echo **** TRUNCATE the slow log then check whether runtime changes of
+-- echo **** log_slow_slave_statements work without slave restart.
+-- echo ********************************************************************
+
+SET @old_log_slow_slave_statements= @@global.log_slow_slave_statements;
+SET @@global.log_slow_slave_statements = off;
+TRUNCATE mysql.slow_log;
+
+-- connection master
+
+--disable_warnings
+-- eval $slow_query;
+--enable_warnings
+sync_slave_with_master;
+
+-- connection slave
+
+eval SELECT sql_text FROM mysql.slow_log WHERE sql_text like '$slow_query';
+
+SET @@global.log_slow_slave_statements = on;
+
+-- connection master
+
+--disable_warnings
+-- eval $slow_query;
+--enable_warnings
+sync_slave_with_master;
+
+-- connection slave
+
+eval SELECT sql_text FROM mysql.slow_log WHERE sql_text like '$slow_query';
+
+-- connection master
+SET @@global.log_output= @old_log_output;
+SET @@global.long_query_time= @old_long_query_time;
+DROP TABLE t1;
+
+-- sync_slave_with_master
+SET @@global.log_output= @old_log_output;
+SET @@global.long_query_time= @old_long_query_time;
+--source include/rpl_end.inc
+--enable_ps2_protocol
diff --git a/mysql-test/suite/rpl/t/rpl_sp-master.opt b/mysql-test/suite/rpl/t/rpl_sp-master.opt
new file mode 100644
index 00000000..18c5c969
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_sp-master.opt
@@ -0,0 +1 @@
+--log_bin_trust_function_creators=0
diff --git a/mysql-test/suite/rpl/t/rpl_sp-slave.opt b/mysql-test/suite/rpl/t/rpl_sp-slave.opt
new file mode 100644
index 00000000..18c5c969
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_sp-slave.opt
@@ -0,0 +1 @@
+--log_bin_trust_function_creators=0
diff --git a/mysql-test/suite/rpl/t/rpl_sp.test b/mysql-test/suite/rpl/t/rpl_sp.test
new file mode 100644
index 00000000..12619a00
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_sp.test
@@ -0,0 +1,732 @@
+# row-based and statement have expected binlog difference in result files
+
+# Test of replication of stored procedures (WL#2146 for MySQL 5.0)
+# Modified by WL#2971.
+
+source include/have_binlog_format_mixed.inc;
+source include/master-slave.inc;
+
+set local sql_mode='';
+# we need a db != test, where we don't have automatic grants
+--disable_warnings
+drop database if exists mysqltest1;
+--enable_warnings
+create database mysqltest1;
+use mysqltest1;
+create table t1 (a varchar(100));
+sync_slave_with_master;
+use mysqltest1;
+
+# ********************** PART 1 : STORED PROCEDURES ***************
+
+# Does the same proc as on master get inserted into mysql.proc ?
+# (same definer, same properties...)
+
+connection master;
+
+delimiter |;
+
+# Stored procedures don't have the limitations that functions have
+# regarding binlogging: it's ok to create a procedure as not
+# deterministic and updating data, while it's not ok to create such a
+# function. We test this.
+
+create procedure foo()
+begin
+ declare b int;
+ set b = 8;
+ insert into t1 values (b);
+ insert into t1 values (unix_timestamp());
+end|
+delimiter ;|
+
+# we replace columns having times
+# (even with fixed timestamp displayed time may changed based on TZ)
+--replace_result localhost.localdomain localhost 127.0.0.1 localhost
+--replace_column 13 # 14 #
+select * from mysql.proc where name='foo' and db='mysqltest1';
+sync_slave_with_master;
+# You will notice in the result that the definer does not match what
+# it is on master, it is a known bug on which Alik is working
+--replace_result localhost.localdomain localhost 127.0.0.1 localhost
+--replace_column 13 # 14 #
+select * from mysql.proc where name='foo' and db='mysqltest1';
+
+connection master;
+# see if timestamp used in SP on slave is same as on master
+set timestamp=1000000000;
+call foo();
+select * from t1;
+sync_slave_with_master;
+select * from t1;
+
+# Now a SP which is not updating tables
+
+connection master;
+delete from t1;
+create procedure foo2()
+ select * from mysqltest1.t1;
+call foo2();
+
+# check that this is allowed (it's not for functions):
+alter procedure foo2 contains sql;
+
+# SP with definer's right
+
+drop table t1;
+create table t1 (a int);
+create table t2 like t1;
+
+create procedure foo3()
+ deterministic
+ insert into t1 values (15);
+
+# let's create a non-privileged user
+grant CREATE ROUTINE, EXECUTE on mysqltest1.* to "zedjzlcsjhd"@127.0.0.1;
+grant SELECT on mysqltest1.t1 to "zedjzlcsjhd"@127.0.0.1;
+grant SELECT, INSERT on mysqltest1.t2 to "zedjzlcsjhd"@127.0.0.1;
+
+# ToDo: BUG#14931: There is a race between the last grant binlogging, and
+# the binlogging in the new connection made below, causing sporadic test
+# failures due to switched statement order in binlog. To fix this we do
+# SELECT 1 in the first connection before starting the second, ensuring
+# that binlogging is done in the expected order.
+# Please remove this SELECT 1 when BUG#14931 is fixed.
+SELECT 1;
+
+connect (con1,127.0.0.1,zedjzlcsjhd,,mysqltest1,$MASTER_MYPORT,);
+connection con1;
+
+# this routine will fail in the second INSERT because of privileges
+delimiter |;
+create procedure foo4()
+ deterministic
+ begin
+ insert into t2 values(3);
+ insert into t1 values (5);
+ end|
+
+delimiter ;|
+
+# I add ,0 so that it does not print the error in the test output,
+# because this error is hostname-dependent
+--error 1142,0
+call foo4(); # invoker has no INSERT grant on table t1 => failure
+
+connection master;
+call foo3(); # success (definer == root)
+show warnings;
+
+--error 1142,0
+call foo4(); # definer's rights => failure
+
+# we test replication of ALTER PROCEDURE
+alter procedure foo4 sql security invoker;
+call foo4(); # invoker's rights => success
+show warnings;
+
+# Note that half-failed procedure calls are ok with binlogging;
+# if we compare t2 on master and slave we see they are identical:
+
+select * from t1;
+select * from t2;
+sync_slave_with_master;
+select * from t1;
+select * from t2;
+
+# Let's check another failing-in-the-middle procedure
+connection master;
+delete from t2;
+alter table t2 add unique (a);
+
+drop procedure foo4;
+delimiter |;
+create procedure foo4()
+ deterministic
+ begin
+ insert into t2 values(20),(20);
+ end|
+
+delimiter ;|
+
+--error ER_DUP_ENTRY
+call foo4();
+show warnings;
+
+select * from t2;
+sync_slave_with_master;
+# check that this failed-in-the-middle replicated right:
+select * from t2;
+
+# Test of DROP PROCEDURE
+
+--replace_result localhost.localdomain localhost 127.0.0.1 localhost
+--replace_column 13 # 14 #
+select * from mysql.proc where name="foo4" and db='mysqltest1';
+connection master;
+drop procedure foo4;
+select * from mysql.proc where name="foo4" and db='mysqltest1';
+sync_slave_with_master;
+select * from mysql.proc where name="foo4" and db='mysqltest1';
+
+# ********************** PART 2 : FUNCTIONS ***************
+
+connection master;
+drop procedure foo;
+drop procedure foo2;
+drop procedure foo3;
+
+delimiter |;
+# check that needs "deterministic"
+--error 1418
+create function fn1(x int)
+ returns int
+begin
+ insert into t1 values (x);
+ return x+2;
+end|
+create function fn1(x int)
+ returns int
+ deterministic
+begin
+ insert into t1 values (x);
+ return x+2;
+end|
+
+delimiter ;|
+delete t1,t2 from t1,t2;
+--disable_ps2_protocol
+select fn1(20);
+--enable_ps2_protocol
+insert into t2 values(fn1(21));
+--sorted_result
+select * from t1;
+select * from t2;
+sync_slave_with_master;
+--sorted_result
+select * from t1;
+select * from t2;
+
+connection master;
+delimiter |;
+
+drop function fn1|
+
+create function fn1()
+ returns int
+ no sql
+begin
+ return unix_timestamp();
+end|
+
+delimiter ;|
+# check that needs "deterministic"
+--error 1418
+alter function fn1 contains sql;
+
+delete from t1;
+set timestamp=1000000000;
+insert into t1 values(fn1());
+
+connection con1;
+
+delimiter |;
+--error 1419 # only full-global-privs user can create a function
+create function fn2()
+ returns int
+ no sql
+begin
+ return unix_timestamp();
+end|
+delimiter ;|
+connection master;
+set @old_log_bin_trust_function_creators= @@global.log_bin_trust_function_creators;
+set global log_bin_trust_function_creators=0;
+set global log_bin_trust_function_creators=1;
+# slave needs it too otherwise will not execute what master allowed:
+connection slave;
+set @old_log_bin_trust_function_creators= @@global.log_bin_trust_function_creators;
+set global log_bin_trust_function_creators=1;
+
+connection con1;
+
+delimiter |;
+create function fn2()
+ returns int
+ no sql
+begin
+ return unix_timestamp();
+end|
+delimiter ;|
+
+connection master;
+
+# Now a function which is supposed to not update tables
+# as it's "reads sql data", so should not give error even if
+# non-deterministic.
+
+delimiter |;
+create function fn3()
+ returns int
+ not deterministic
+ reads sql data
+begin
+ return 0;
+end|
+delimiter ;|
+
+select fn3();
+--replace_result localhost.localdomain localhost 127.0.0.1 localhost
+--replace_column 13 # 14 #
+select * from mysql.proc where db='mysqltest1';
+select * from t1;
+
+sync_slave_with_master;
+use mysqltest1;
+select * from t1;
+--replace_result localhost.localdomain localhost 127.0.0.1 localhost
+--replace_column 13 # 14 #
+select * from mysql.proc where db='mysqltest1';
+
+# Let's check a failing-in-the-middle function
+connection master;
+delete from t2;
+alter table t2 add unique (a);
+
+drop function fn1;
+
+delimiter |;
+create function fn1(x int)
+ returns int
+begin
+ insert into t2 values(x),(x);
+ return 10;
+end|
+
+delimiter ;|
+
+do fn1(100);
+
+--error ER_DUP_ENTRY
+select fn1(20);
+
+select * from t2;
+sync_slave_with_master;
+
+# check that this failed-in-the-middle replicated right:
+select * from t2;
+
+# ********************** PART 3 : TRIGGERS ***************
+
+connection con1;
+# now fails due to missing trigger grant (err 1142 i/o 1227) due to new
+# check in sql_trigger.cc (v1.44) by anozdrin on 2006/02/01 --azundris
+--error ER_TABLEACCESS_DENIED_ERROR
+create trigger trg before insert on t1 for each row set new.a= 10;
+
+connection master;
+delete from t1;
+# TODO: when triggers can contain an update, test that this update
+# does not go into binlog.
+# I'm not setting user vars in the trigger, because replication of user vars
+# would take care of propagating the user var's value to slave, so even if
+# the trigger was not executed on slave it would not be discovered.
+create trigger trg before insert on t1 for each row set new.a= 10;
+insert into t1 values (1);
+select * from t1;
+sync_slave_with_master;
+select * from t1;
+
+connection master;
+delete from t1;
+drop trigger trg;
+insert into t1 values (1);
+select * from t1;
+sync_slave_with_master;
+select * from t1;
+
+
+# ********************** PART 4 : RELATED FIXED BUGS ***************
+
+
+#
+# Test for bug #13969 "Routines which are replicated from master can't be
+# executed on slave".
+#
+connection master;
+create procedure foo()
+ not deterministic
+ reads sql data
+ select * from t1;
+sync_slave_with_master;
+# This should not fail
+call foo();
+connection master;
+drop procedure foo;
+sync_slave_with_master;
+
+
+# Clean up
+connection master;
+drop function fn1;
+drop database mysqltest1;
+drop user "zedjzlcsjhd"@127.0.0.1;
+use test;
+sync_slave_with_master;
+use test;
+
+#
+# Bug#14077 "Failure to replicate a stored function with a cursor":
+# verify that stored routines with cursors work on slave.
+#
+connection master;
+--disable_warnings
+drop function if exists f1;
+--enable_warnings
+delimiter |;
+create function f1() returns int reads sql data
+begin
+ declare var integer;
+ declare c cursor for select a from v1;
+ open c;
+ fetch c into var;
+ close c;
+ return var;
+end|
+delimiter ;|
+create view v1 as select 1 as a;
+create table t1 (a int);
+insert into t1 (a) values (f1());
+select * from t1;
+drop view v1;
+drop function f1;
+sync_slave_with_master;
+connection slave;
+select * from t1;
+
+#
+# Bug#16621 "INSERTs in Stored Procedures causes data corruption in the Binary
+# Log for 5.0.18"
+#
+
+# Prepare environment.
+
+connection master;
+
+--disable_warnings
+DROP PROCEDURE IF EXISTS p1;
+DROP TABLE IF EXISTS t1;
+--enable_warnings
+
+# Test case.
+
+CREATE TABLE t1(col VARCHAR(10));
+
+CREATE PROCEDURE p1(arg VARCHAR(10))
+ INSERT INTO t1 VALUES(arg);
+
+CALL p1('test');
+
+SELECT * FROM t1;
+
+sync_slave_with_master;
+SELECT * FROM t1;
+
+# Cleanup
+connection master;
+DROP PROCEDURE p1;
+
+
+#
+# BUG#20438: CREATE statements for views, stored routines and triggers can be
+# not replicable.
+#
+
+--echo
+--echo ---> Test for BUG#20438
+
+# Prepare environment.
+
+--echo
+--echo ---> Preparing environment...
+--connection master
+
+--disable_warnings
+DROP PROCEDURE IF EXISTS p1;
+DROP FUNCTION IF EXISTS f1;
+--enable_warnings
+
+--echo
+--echo ---> Synchronizing slave with master...
+
+--sync_slave_with_master
+
+--connection master
+
+# Test.
+
+--echo
+--echo ---> Creating procedure...
+
+/*!50003 CREATE PROCEDURE p1() SET @a = 1 */;
+
+/*!50003 CREATE FUNCTION f1() RETURNS INT RETURN 0 */;
+
+--echo
+--echo ---> Checking on master...
+
+SHOW CREATE PROCEDURE p1;
+SHOW CREATE FUNCTION f1;
+
+--echo
+--echo ---> Synchronizing slave with master...
+
+--sync_slave_with_master
+
+--echo
+--echo ---> Checking on slave...
+
+SHOW CREATE PROCEDURE p1;
+SHOW CREATE FUNCTION f1;
+
+# Cleanup.
+
+--connection master
+
+--echo
+--echo ---> Cleaning up...
+
+DROP PROCEDURE p1;
+DROP FUNCTION f1;
+
+--sync_slave_with_master
+--connection master
+
+
+# cleanup
+connection master;
+drop table t1;
+sync_slave_with_master;
+
+#
+# Bug22043: MySQL don't add "USE <DATABASE>" before "DROP PROCEDURE IF EXISTS"
+#
+
+connection master;
+--disable_warnings
+drop database if exists mysqltest;
+drop database if exists mysqltest2;
+--enable_warnings
+create database mysqltest;
+create database mysqltest2;
+use mysqltest2;
+create table t ( t integer );
+create procedure mysqltest.test() begin end;
+insert into t values ( 1 );
+--error ER_BAD_DB_ERROR
+create procedure `\\`.test() begin end;
+
+#
+# BUG#19725: Calls to stored function in other database are not
+# replicated correctly in some cases
+#
+
+connection master;
+delimiter |;
+create function f1 () returns int
+begin
+ insert into t values (1);
+ return 0;
+end|
+delimiter ;|
+sync_slave_with_master;
+# Let us test if we don't forget to binlog the function's database
+connection master;
+use mysqltest;
+set @a:= mysqltest2.f1();
+sync_slave_with_master;
+connection master;
+
+# Final inspection which verifies how all statements of this test file
+# were written to the binary log.
+--source include/show_binlog_events.inc
+
+
+# Restore log_bin_trust_function_creators to its original value.
+# This is a cleanup for all parts above where we tested stored
+# functions and triggers.
+connection slave;
+set @@global.log_bin_trust_function_creators= @old_log_bin_trust_function_creators;
+connection master;
+set @@global.log_bin_trust_function_creators= @old_log_bin_trust_function_creators;
+
+# Clean up
+drop database mysqltest;
+drop database mysqltest2;
+sync_slave_with_master;
+
+#
+# Bug#36570: Parse error of CREATE PROCEDURE stmt with comments on slave
+#
+connection master;
+use test;
+delimiter |;
+
+/*!50001 create procedure `mysqltestbug36570_p1`() */
+begin
+ select 1;
+end|
+
+use mysql|
+create procedure test.` mysqltestbug36570_p2`(/*!50001 a int*/)`label`:
+begin
+ select a;
+end|
+
+/*!50001 create function test.mysqltestbug36570_f1() */
+ returns int
+ /*!50001 deterministic */
+begin
+ return 3;
+end|
+use test|
+
+delimiter ;|
+
+--replace_column 5 t 6 t
+show procedure status like '%mysqltestbug36570%';
+show create procedure ` mysqltestbug36570_p2`;
+
+sync_slave_with_master;
+connection slave;
+
+--replace_column 5 t 6 t
+show procedure status like '%mysqltestbug36570%';
+show create procedure ` mysqltestbug36570_p2`;
+call ` mysqltestbug36570_p2`(42);
+
+--replace_column 5 t 6 t
+show function status like '%mysqltestbug36570%';
+
+connection master;
+flush logs;
+let $MYSQLD_DATADIR= `select @@datadir`;
+--replace_regex /$MYSQL_TEST_DIR/MYSQL_TEST_DIR/ /TIMESTAMP=[0-9]*/TIMESTAMP=t/
+--exec $MYSQL_BINLOG --short-form $MYSQLD_DATADIR/master-bin.000001
+use test;
+drop procedure mysqltestbug36570_p1;
+drop procedure ` mysqltestbug36570_p2`;
+drop function mysqltestbug36570_f1;
+--echo End of 5.0 tests
+--echo # End of 5.1 tests
+--echo #
+--echo # Test Bug#30977 Concurrent statement using stored
+--echo # function and DROP FUNCTION breaks SBR.
+--echo #
+--echo # Demonstrate that stored function DDL can not go through,
+--echo # or, worse yet, make its way into the binary log, while
+--echo # the stored function is in use.
+--echo # For that, try to insert a result of a stored function
+--echo # into a table. Block the insert in the beginning, waiting
+--echo # on a table lock. While insert is blocked, attempt to
+--echo # drop the routine. Verify that this attempt
+--echo # blocks and waits for INSERT to complete. Commit and
+--echo # reap the chain of events. Master and slave must contain
+--echo # identical data. Statements in the binrary log must be
+--echo # consistent with data in the table.
+--echo #
+connection default;
+--disable_warnings
+drop table if exists t1, t2;
+drop function if exists t1;
+--enable_warnings
+create table t1 (a int);
+create table t2 (a int) as select 1 as a;
+create function f1() returns int deterministic return (select max(a) from t2);
+lock table t2 write;
+connection master;
+--echo # Sending 'insert into t1 (a) values (f1())'...
+--send insert into t1 (a) values (f1())
+connection master1;
+--echo # Waitng for 'insert into t1 ...' to get blocked on table lock...
+let $wait_condition=select count(*)=1 from information_schema.processlist
+where state='Waiting for table metadata lock' and
+ info='insert into t1 (a) values (f1())';
+--source include/wait_condition.inc
+--echo # Sending 'drop function f1'. It will wait till insert finishes.
+--send drop function f1;
+connection default;
+--echo # Check that 'drop function f1' gets blocked.
+let $wait_condition=select count(*)=1 from information_schema.processlist
+where state='Waiting for stored function metadata lock' and info='drop function f1';
+--source include/wait_condition.inc
+--echo # Now let's let 'insert' go through...
+unlock tables;
+connection master;
+--echo # Reaping 'insert into t1 (a) values (f1())'...
+--reap
+connection master1;
+--echo # Reaping 'drop function f1'
+--reap
+connection master;
+select * from t1;
+sync_slave_with_master;
+connection slave;
+select * from t1;
+# Cleanup
+connection master;
+drop table t1, t2;
+--error ER_SP_DOES_NOT_EXIST
+drop function f1;
+
+
+--echo #
+--echo # Bug #11918 Can't use a declared variable in LIMIT clause
+--echo #
+--source include/rpl_reset.inc
+
+create table t1 (c1 int);
+insert into t1 (c1) values
+(1), (2), (3), (4), (5), (6), (7), (8), (9), (10);
+
+call mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT");
+
+create procedure p1(p1 integer)
+ delete from t1 limit p1;
+
+set @save_binlog_format=@@session.binlog_format;
+set @@session.binlog_format=STATEMENT;
+
+--disable_warnings
+call p1(NULL);
+call p1(0);
+call p1(1);
+call p1(2);
+call p1(3);
+--enable_warnings
+
+select * from t1;
+sync_slave_with_master;
+connection slave;
+select * from t1;
+connection master;
+--disable_warnings
+call p1(-1);
+--enable_warnings
+select * from t1;
+sync_slave_with_master;
+connection slave;
+select * from t1;
+connection master;
+
+--echo # Cleanup
+set @@session.binlog_format=@save_binlog_format;
+drop table t1;
+drop procedure p1;
+
+--echo # End of 5.5 tests.
+
+
+# Cleanup
+sync_slave_with_master;
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_sp004.test b/mysql-test/suite/rpl/t/rpl_sp004.test
new file mode 100644
index 00000000..31e4ce37
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_sp004.test
@@ -0,0 +1,92 @@
+#############################################################################
+# Original Author: JBM #
+# Original Date: Aug/14/2005 #
+#############################################################################
+# Test: This test contains two sp that create and drop tables, insert and #
+# updated data and uses the NOW() function. #
+#############################################################################
+
+
+# Includes
+-- source include/master-slave.inc
+
+
+# Begin clean up test section
+connection master;
+--disable_warnings
+DROP PROCEDURE IF EXISTS test.p1;
+DROP PROCEDURE IF EXISTS test.p2;
+DROP TABLE IF EXISTS test.t2;
+DROP TABLE IF EXISTS test.t1;
+DROP TABLE IF EXISTS test.t3;
+--enable_warnings
+# End of cleanup
+
+# Begin test section 1
+
+delimiter |;
+CREATE PROCEDURE test.p1()
+BEGIN
+ CREATE TABLE IF NOT EXISTS test.t1(a INT,PRIMARY KEY(a));
+ CREATE TABLE IF NOT EXISTS test.t2(a INT,PRIMARY KEY(a));
+ INSERT INTO test.t1 VALUES (4),(2),(1),(3);
+ UPDATE test.t1 SET a=a+4 WHERE a=4;
+ INSERT INTO test.t2 (a) SELECT t1.a FROM test.t1;
+ UPDATE test.t1 SET a=a+4 WHERE a=8;
+ CREATE TABLE IF NOT EXISTS test.t3(n MEDIUMINT NOT NULL AUTO_INCREMENT, f FLOAT, d DATETIME, PRIMARY KEY(n));
+END|
+CREATE PROCEDURE test.p2()
+BEGIN
+ DROP TABLE IF EXISTS test.t1;
+ DROP TABLE IF EXISTS test.t2;
+ INSERT INTO test.t3 VALUES(NULL,11111111.233333,NOW());
+END|
+delimiter ;|
+
+CALL test.p1();
+SELECT * FROM test.t1 ORDER BY a;
+SELECT * FROM test.t2 ORDER BY a;
+sync_slave_with_master;
+SELECT * FROM test.t1 ORDER BY a;
+SELECT * FROM test.t2 ORDER BY a;
+
+connection master;
+CALL test.p2();
+USE test;
+SHOW TABLES;
+#SELECT * FROM test.t3;
+sync_slave_with_master;
+USE test;
+SHOW TABLES;
+#SELECT * FROM test.t3;
+
+connection master;
+CALL test.p1();
+SELECT * FROM test.t1 ORDER BY a;
+SELECT * FROM test.t2 ORDER BY a;
+#SELECT * FROM test.t3;
+sync_slave_with_master;
+SELECT * FROM test.t1 ORDER BY a;
+SELECT * FROM test.t2 ORDER BY a;
+#SELECT * FROM test.t3;
+
+--exec $MYSQL_DUMP --compact --order-by-primary --skip-extended-insert --no-create-info test > $MYSQLTEST_VARDIR/tmp/sp004_master.sql
+--exec $MYSQL_DUMP_SLAVE --compact --order-by-primary --skip-extended-insert --no-create-info test > $MYSQLTEST_VARDIR/tmp/sp004_slave.sql
+
+# Cleanup
+connection master;
+#show binlog events;
+DROP PROCEDURE IF EXISTS test.p1;
+DROP PROCEDURE IF EXISTS test.p2;
+DROP TABLE IF EXISTS test.t1;
+DROP TABLE IF EXISTS test.t2;
+DROP TABLE IF EXISTS test.t3;
+sync_slave_with_master;
+
+# If the test fails, you will need to diff the dumps to see why.
+
+diff_files $MYSQLTEST_VARDIR/tmp/sp004_master.sql $MYSQLTEST_VARDIR/tmp/sp004_slave.sql;
+
+
+# End of 5.0 test case
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_sp_effects-master.opt b/mysql-test/suite/rpl/t/rpl_sp_effects-master.opt
new file mode 100644
index 00000000..27fad140
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_sp_effects-master.opt
@@ -0,0 +1 @@
+--log_bin_trust_function_creators=1
diff --git a/mysql-test/suite/rpl/t/rpl_sp_effects-slave.opt b/mysql-test/suite/rpl/t/rpl_sp_effects-slave.opt
new file mode 100644
index 00000000..27fad140
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_sp_effects-slave.opt
@@ -0,0 +1 @@
+--log_bin_trust_function_creators=1
diff --git a/mysql-test/suite/rpl/t/rpl_sp_effects.test b/mysql-test/suite/rpl/t/rpl_sp_effects.test
new file mode 100644
index 00000000..08d806b1
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_sp_effects.test
@@ -0,0 +1,294 @@
+##########################################
+# Change Author: JBM
+# Change Date: 2006-05-02
+##########################################
+
+# Test of replication of stored procedures (WL#2146 for MySQL 5.0)
+-- source include/master-slave.inc
+
+# ****************************************************************
+connection master;
+
+SET @old_log_bin_trust_function_creators= @@global.log_bin_trust_function_creators;
+
+# cleanup
+--disable_warnings
+drop procedure if exists p1;
+drop procedure if exists p2;
+drop function if exists f1;
+drop table if exists t1,t2;
+drop view if exists v1;
+--enable_warnings
+create table t1 (a int);
+
+SET GLOBAL log_bin_trust_function_creators = 1;
+
+# 1. Test simple variables use.
+delimiter //;
+create procedure p1()
+begin
+ declare spv int default 0;
+ while spv < 5 do
+ insert into t1 values(spv+1);
+ set spv=spv+1;
+ end while;
+end//
+delimiter ;//
+
+call p1();
+
+sync_slave_with_master;
+connection slave;
+SELECT * FROM t1 ORDER BY a;
+connection master;
+SELECT * FROM t1 ORDER BY a;
+
+# 2. Test SP variable name
+delimiter //;
+create procedure p2()
+begin
+ declare a int default 4;
+ create table t2 as select a;
+end//
+delimiter ;//
+
+call p2();
+SELECT * FROM t2 ORDER BY a;
+sync_slave_with_master;
+connection slave;
+SELECT * FROM t2 ORDER BY a;
+
+connection master;
+drop procedure p1;
+drop procedure p2;
+drop table t2;
+
+# 3. Test FUNCTIONs in various places
+
+delimiter //;
+create function f1(x int) returns int
+begin
+ insert into t1 values(x);
+ return x+1;
+end//
+
+create procedure p1(a int, b int)
+begin
+ declare v int default f1(5);
+ if (f1(6)) then
+ select 'yes';
+ end if;
+ set v = f1(7);
+ while f1(8) < 1 do
+ select 'this cant be';
+ end while;
+
+end//
+delimiter ;//
+
+call p1(f1(1), f1(2));
+SELECT * FROM t1 ORDER BY a;
+
+create table t2(a int);
+insert into t2 values (10),(11);
+--disable_ps2_protocol
+SELECT a,f1(a) FROM t2 ORDER BY a;
+--enable_ps2_protocol
+
+# This shouldn't put separate 'call f1(3)' into binlog:
+insert into t2 select f1(3);
+SELECT 'master:',a FROM t1 ORDER BY a;
+
+sync_slave_with_master;
+connection slave;
+SELECT 'slave:',a FROM t1 ORDER BY a;
+
+connection master;
+drop procedure p1;
+delete from t1;
+delete from t2;
+
+# 4. VIEWs
+delete from t1;
+insert into t2 values(1),(2);
+create view v1 as select f1(a) as f from t2;
+--disable_ps2_protocol
+select * from v1 order by f;
+--enable_ps2_protocol
+SELECT 'master:',a FROM t1 ORDER BY a;
+
+sync_slave_with_master;
+connection slave;
+SELECT 'slave:',a FROM t1 ORDER BY a;
+
+connection master;
+drop view v1;
+delete from t1;
+
+# 5. Prepared statements.
+prepare s1 from 'select f1(?)';
+set @xx=123;
+execute s1 using @xx;
+SELECT 'master:',a FROM t1 ORDER BY a;
+
+sync_slave_with_master;
+connection slave;
+SELECT 'slave:',a FROM t1 ORDER BY a;
+
+connection master;
+delete from t1;
+
+# 5. Cursors.
+# t2 has (1),(2);
+delimiter //;
+create procedure p1(spv int)
+begin
+ declare c cursor for select f1(spv) from t2;
+ while (spv > 2) do
+ open c;
+ fetch c into spv;
+ close c;
+ set spv= spv - 10;
+ end while;
+end//
+delimiter ;//
+call p1(15);
+SELECT 'master:',a FROM t1 ORDER BY a;
+sync_slave_with_master;
+connection slave;
+SELECT 'slave:',a FROM t1 ORDER BY a;
+
+connection master;
+drop procedure p1;
+drop function f1;
+drop table t1,t2;
+
+# BUG#12637: User variables + SPs replication
+create table t1 (a int);
+delimiter //;
+create procedure p1()
+begin
+ insert into t1 values(@x);
+ set @x=@x+1;
+ insert into t1 values(@x);
+ if (f2()) then
+ insert into t1 values(1243);
+ end if;
+end//
+
+create function f2() returns int
+begin
+ insert into t1 values(@z);
+ set @z=@z+1;
+ insert into t1 values(@z);
+ return 0;
+end//
+
+create function f1() returns int
+begin
+ insert into t1 values(@y);
+ call p1();
+ return 0;
+end//
+
+delimiter ;//
+
+set @x=10;
+set @y=20;
+set @z=100;
+--disable_ps2_protocol
+select f1();
+--enable_ps2_protocol
+
+set @x=30;
+call p1();
+
+SELECT 'master', a FROM t1 ORDER BY a;
+sync_slave_with_master;
+connection slave;
+SELECT 'slave', a FROM t1 ORDER BY a;
+
+#
+# cleanup
+#
+
+connection master;
+drop table t1;
+drop function f1;
+drop function f2;
+drop procedure p1;
+sync_slave_with_master;
+
+#
+# bug#26199 Replication Failure on Slave when using stored procs
+# with bit-type parameters
+
+connection master;
+
+create table t2 (b BIT(7));
+delimiter //;
+create procedure sp_bug26199(bitvalue BIT(7))
+begin
+ insert into t2 set b = bitvalue;
+end //
+
+create function sf_bug26199(b BIT(7)) returns int
+begin
+ insert into t2 values(b);
+ return 0;
+end//
+
+DELIMITER ;//
+
+
+
+call sp_bug26199(b'1110');
+call sp_bug26199('\0');
+--disable_ps2_protocol
+select sf_bug26199(b'1111111');
+SET STATEMENT sql_mode = '' FOR
+select sf_bug26199(b'101111111');
+select sf_bug26199('\'');
+--enable_ps2_protocol
+select hex(b) from t2;
+
+sync_slave_with_master;
+#connection slave;
+select hex(b) from t2;
+
+#
+# cleanup bug#26199
+#
+connection master;
+drop table t2;
+drop procedure sp_bug26199;
+drop function sf_bug26199;
+
+SET @@global.log_bin_trust_function_creators= @old_log_bin_trust_function_creators;
+
+sync_slave_with_master;
+
+#
+# Bug#16056537: MYSQLD CRASHES IN ITEM_FUNC_GET_USER_VAR::FIX_LENGTH_AND_DEC()
+#
+set names utf8;
+--delimiter |
+CREATE FUNCTION f() RETURNS timestamp DETERMINISTIC
+BEGIN RETURN '2012-12-21 12:12:12'; END |
+CREATE PROCEDURE p(t timestamp)
+BEGIN
+ SET @t = t;
+ PREPARE stmt FROM "
+ UPDATE t1 SET a = @t WHERE '2012-12-31 08:00:00' < f() ";
+ EXECUTE stmt;
+ DEALLOCATE PREPARE stmt;
+END |
+--delimiter ;
+create table t1 (a timestamp);
+call p('2012-12-31 08:00:00');
+drop table t1;
+drop procedure p;
+drop function f;
+
+--echo end of the tests
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_sp_variables.test b/mysql-test/suite/rpl/t/rpl_sp_variables.test
new file mode 100644
index 00000000..87e9fe19
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_sp_variables.test
@@ -0,0 +1,28 @@
+source include/master-slave.inc;
+
+--echo #
+--echo # MDEV-13685 Can not replay binary log due to Illegal mix of collations (latin1_swedish_ci,IMPLICIT) and (utf8mb4_general_ci,COERCIBLE) for operation 'concat'
+--echo #
+
+connection master;
+SET NAMES utf8;
+CREATE TABLE t1 (a VARCHAR(10) CHARACTER SET utf8);
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE v_id INT DEFAULT 2017;
+ INSERT INTO test.t1 SELECT CONCAT(v_id, '오');
+END;
+$$
+DELIMITER ;$$
+CALL p1;
+SELECT * FROM t1;
+sync_slave_with_master;
+SET NAMES utf8;
+SELECT * FROM t1;
+connection master;
+DROP PROCEDURE p1;
+DROP TABLE t1;
+sync_slave_with_master;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_spec_variables.test b/mysql-test/suite/rpl/t/rpl_spec_variables.test
new file mode 100644
index 00000000..fdd000d0
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_spec_variables.test
@@ -0,0 +1,312 @@
+#############################################################
+# Author: Serge Kozlov <skozlov@mysql.com>
+# Date: 07/01/2008
+# Purpose: Testing possible affects of some system dynamic
+# variables to the replication.
+# Scenario for each variable:
+# 1) Set different values for master and slave
+# 2) Create and replicate a data from master to slave
+# 3) Check results on master and slave: changes on slave
+# shouldn't be affected to replicated data.
+#############################################################
+--source include/have_innodb.inc
+--source include/master-slave.inc
+--echo
+
+#
+# AUTO_INCREMENT
+#
+--echo * auto_increment_increment, auto_increment_offset *
+
+--connection master
+SET @@global.auto_increment_increment=2;
+SET @@session.auto_increment_increment=2;
+SET @@global.auto_increment_offset=10;
+SET @@session.auto_increment_offset=10;
+
+--connection slave
+SET @@global.auto_increment_increment=3;
+SET @@session.auto_increment_increment=3;
+SET @@global.auto_increment_offset=20;
+SET @@session.auto_increment_offset=20;
+
+--connection master
+CREATE TABLE t1 (a INT NOT NULL AUTO_INCREMENT PRIMARY KEY, b VARCHAR(10)) ENGINE=MyISAM;
+INSERT INTO t1 (b) VALUES ('master');
+INSERT INTO t1 (b) VALUES ('master');
+SELECT * FROM t1 ORDER BY a;
+
+--sync_slave_with_master
+CREATE TABLE t2 (a INT NOT NULL AUTO_INCREMENT PRIMARY KEY, b VARCHAR(10)) ENGINE=MyISAM;
+INSERT INTO t1 (b) VALUES ('slave');
+INSERT INTO t1 (b) VALUES ('slave');
+INSERT INTO t2 (b) VALUES ('slave');
+INSERT INTO t2 (b) VALUES ('slave');
+SELECT * FROM t1 ORDER BY a;
+SELECT * FROM t2 ORDER BY a;
+
+--connection master
+--disable_warnings
+DROP TABLE IF EXISTS t1,t2;
+--enable_warnings
+SET @@global.auto_increment_increment=1;
+SET @@session.auto_increment_increment=1;
+SET @@global.auto_increment_offset=1;
+SET @@session.auto_increment_offset=1;
+
+--connection slave
+SET @@global.auto_increment_increment=1;
+SET @@session.auto_increment_increment=1;
+SET @@global.auto_increment_offset=1;
+SET @@session.auto_increment_offset=1;
+
+--connection slave
+SET auto_increment_increment=1;
+SET auto_increment_offset=1;
+--echo
+
+#
+# CHARACTER_SET_DATABASE, COLLATION_SERVER
+#
+--echo * character_set_database, collation_server *
+
+--connection master
+SET @restore_master_character_set_database=@@global.character_set_database;
+SET @restore_master_collation_server=@@global.collation_server;
+SET @@global.character_set_database=latin1;
+SET @@session.character_set_database=latin1;
+SET @@global.collation_server=latin1_german1_ci;
+SET @@session.collation_server=latin1_german1_ci;
+
+--connection slave
+SET @restore_slave_character_set_database=@@global.character_set_database;
+SET @restore_slave_collation_server=@@global.collation_server;
+SET @@global.character_set_database=utf8;
+SET @@session.character_set_database=utf8;
+SET @@global.collation_server=utf8_bin;
+SET @@session.collation_server=utf8_bin;
+
+--connection master
+CREATE TABLE t1 (a INT NOT NULL PRIMARY KEY, b VARCHAR(10)) ENGINE=MyISAM;
+SHOW CREATE TABLE t1;
+
+--sync_slave_with_master
+CREATE TABLE t2 (a INT NOT NULL PRIMARY KEY, b VARCHAR(10)) ENGINE=MyISAM;
+SHOW CREATE TABLE t1;
+SHOW CREATE TABLE t2;
+
+SET @@global.collation_server=latin1_swedish_ci;
+SET @@session.collation_server=latin1_swedish_ci;
+
+--connection master
+SET @@global.collation_server=latin1_swedish_ci;
+SET @@session.collation_server=latin1_swedish_ci;
+
+--disable_warnings
+DROP TABLE IF EXISTS t1,t2;
+--enable_warnings
+--echo
+
+#
+# DEFAULT_WEEK_FORMAT
+#
+--echo * default_week_format *
+
+--connection master
+SET @@global.default_week_format=0;
+SET @@session.default_week_format=0;
+
+--connection slave
+SET @@global.default_week_format=1;
+SET @@session.default_week_format=1;
+
+--connection master
+CREATE TABLE t1 (a INT NOT NULL PRIMARY KEY, b VARCHAR(10), c INT) ENGINE=MyISAM;
+INSERT INTO t1 VALUES (1, 'master ', WEEK('2008-01-07'));
+SELECT * FROM t1 ORDER BY a;
+
+--sync_slave_with_master
+INSERT INTO t1 VALUES (2, 'slave ', WEEK('2008-01-07'));
+SELECT * FROM t1 ORDER BY a;
+
+--connection master
+DROP TABLE t1;
+
+--connection slave
+SET @@global.default_week_format=0;
+SET @@session.default_week_format=0;
+--echo
+
+#
+# LOCAL_INFILE
+#
+--echo * local_infile *
+
+--connection slave
+SET @@global.local_infile=0;
+
+--connection master
+CREATE TABLE t1 (a INT NOT NULL AUTO_INCREMENT PRIMARY KEY, b VARCHAR(20), c CHAR(254)) ENGINE=MyISAM;
+--copy_file ./std_data/words.dat $MYSQLTEST_VARDIR/tmp/words.dat
+--copy_file ./std_data/words2.dat $MYSQLTEST_VARDIR/tmp/words2.dat
+--replace_regex /\'.+\'/'FILE'/
+--eval LOAD DATA LOCAL INFILE '$MYSQLTEST_VARDIR/tmp/words.dat' INTO TABLE t1 (b)
+SELECT COUNT(*) FROM t1;
+--sync_slave_with_master
+--replace_regex /\'.+\'/'FILE2'/
+--error ER_LOAD_INFILE_CAPABILITY_DISABLED
+--eval LOAD DATA LOCAL INFILE '$MYSQLTEST_VARDIR/tmp/words2.dat' INTO TABLE t1 (b)
+SELECT COUNT(*) FROM t1;
+
+SET @@global.local_infile=1;
+
+--connection master
+DROP TABLE t1;
+--echo
+
+#
+# MAX_HEAP_TABLE_SIZE
+#
+--echo * max_heap_table_size *
+
+--connection slave
+SET @restore_slave_max_heap_table_size=@@global.max_heap_table_size;
+SET @@global.max_heap_table_size=16384;
+SET @@session.max_heap_table_size=16384;
+
+--connection master
+CREATE TABLE t1 (a INT NOT NULL AUTO_INCREMENT PRIMARY KEY, b VARCHAR(10), c CHAR(254)) ENGINE=MEMORY;
+let $counter=2000;
+--disable_query_log
+while ($counter) {
+ INSERT INTO t1 (b,c) VALUES ('master', REPEAT('A', 254));
+ dec $counter;
+}
+--enable_query_log
+SELECT COUNT(*)=2000 FROM t1;
+
+--sync_slave_with_master
+let $counter=2000;
+--disable_query_log
+while ($counter) {
+ --error 0,1114
+ INSERT INTO t1 (b,c) VALUES ('slave', REPEAT('A', 254));
+ dec $counter;
+}
+CREATE TABLE t2 (a INT NOT NULL AUTO_INCREMENT PRIMARY KEY, b VARCHAR(10), c CHAR(254)) ENGINE=MEMORY;
+let $counter=2000;
+--disable_query_log
+while ($counter) {
+ --error 0,1114
+ INSERT INTO t2 (b,c) VALUES ('slave', REPEAT('A', 254));
+ dec $counter;
+}
+--enable_query_log
+# We don't know how many memory used and can't check exact values so need to check following
+# conditions
+SELECT COUNT(*)=2000 FROM t1 WHERE b='master' GROUP BY b ORDER BY b;
+SELECT COUNT(*)<2000 AND COUNT(*)>0 FROM t1 WHERE b='slave' GROUP BY b ORDER BY b;
+SELECT COUNT(*)<2000 AND COUNT(*)>0 FROM t2 WHERE b='slave' GROUP BY b ORDER BY b;
+
+--connection master
+--disable_warnings
+DROP TABLE IF EXISTS t1,t2;
+--enable_warnings
+--echo
+
+#
+# STORAGE_ENGINE
+#
+--echo * storage_engine *
+
+--connection master
+SET @restore_master_storage_engine=@@global.default_storage_engine;
+SET @@global.default_storage_engine=InnoDB;
+SET @@session.default_storage_engine=InnoDB;
+
+--connection slave
+SET @restore_slave_storage_engine=@@global.default_storage_engine;
+SET @@global.default_storage_engine=Memory;
+SET @@session.default_storage_engine=Memory;
+
+--connection master
+CREATE TABLE t1 (a INT NOT NULL PRIMARY KEY, b VARCHAR(10));
+CREATE TABLE t2 (a INT NOT NULL PRIMARY KEY, b VARCHAR(10)) ENGINE=InnoDB;
+
+--sync_slave_with_master
+CREATE TABLE t3 (a INT NOT NULL PRIMARY KEY, b VARCHAR(10));
+
+--connection master
+SHOW CREATE TABLE t1;
+SHOW CREATE TABLE t2;
+
+--connection slave
+SHOW CREATE TABLE t1;
+SHOW CREATE TABLE t2;
+SHOW CREATE TABLE t3;
+
+SET @@global.default_storage_engine=InnoDB;
+SET @@session.default_storage_engine=InnoDB;
+
+--connection master
+--disable_warnings
+DROP TABLE IF EXISTS t1,t2,t3;
+--enable_warnings
+--echo
+
+#
+# SQL_MODE
+#
+--echo * sql_mode *
+
+--connection master
+SET @old_sql_mode_master= @@global.sql_mode;
+SET @@global.sql_mode=ANSI;
+SET @@session.sql_mode=ANSI;
+
+--connection slave
+SET @old_sql_mode_slave= @@global.sql_mode;
+SET @@global.sql_mode=TRADITIONAL;
+SET @@session.sql_mode=TRADITIONAL;
+
+--connection master
+CREATE TABLE t1 (a INT NOT NULL PRIMARY KEY, b VARCHAR(10), c DATE);
+INSERT INTO t1 VALUES (1, 'master', '0000-00-00');
+SELECT * FROM t1 ORDER BY a;
+
+--sync_slave_with_master
+--error 1292
+INSERT INTO t1 VALUES (1, 'slave', '0000-00-00');
+SELECT * FROM t1 ORDER BY a;
+SET @@global.sql_mode='';
+SET @@session.sql_mode='';
+
+--connection master
+SET @@global.sql_mode='';
+SET @@session.sql_mode='';
+DROP TABLE t1;
+--echo
+
+
+# Clean up
+--echo *** clean up ***
+--connection master
+SET @@global.character_set_database=@restore_master_character_set_database;
+SET @@global.collation_server=@restore_master_collation_server;
+SET @@global.default_storage_engine=@restore_master_storage_engine;
+SET @@global.sql_mode=@old_sql_mode_master;
+--sync_slave_with_master
+SET @@global.character_set_database=@restore_slave_character_set_database;
+SET @@global.collation_server=@restore_slave_collation_server;
+SET @@global.max_heap_table_size=@restore_slave_max_heap_table_size;
+SET @@global.default_storage_engine=@restore_slave_storage_engine;
+SET @@global.sql_mode=@old_sql_mode_slave;
+
+# Put at the end since the test otherwise emptied the table.
+remove_file $MYSQLTEST_VARDIR/tmp/words.dat;
+remove_file $MYSQLTEST_VARDIR/tmp/words2.dat;
+--echo
+call mtr.add_suppression("The table 't[12]' is full");
+
+# End of 5.1 test
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_special_charset.opt b/mysql-test/suite/rpl/t/rpl_special_charset.opt
new file mode 100644
index 00000000..b071fb20
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_special_charset.opt
@@ -0,0 +1 @@
+--character-set-server=utf16
diff --git a/mysql-test/suite/rpl/t/rpl_special_charset.test b/mysql-test/suite/rpl/t/rpl_special_charset.test
new file mode 100644
index 00000000..641aa483
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_special_charset.test
@@ -0,0 +1,32 @@
+#
+# This include file is used by more than one test suite
+# (currently rpl and binlog_encryption).
+# Please check all dependent tests after modifying it
+#
+
+################################################################################
+# Bug#19855907 IO THREAD AUTHENTICATION ISSUE WITH SOME CHARACTER SETS
+# Problem: IO thread fails to connect to master if servers are configured with
+# special character sets like utf16, utf32, ucs2.
+#
+# Analysis: MySQL server does not support few special character sets like
+# utf16,utf32 and ucs2 as "client's character set"(eg: utf16,utf32, ucs2).
+# When IO thread is trying to connect to Master, it sets server's character
+# set as client's character set. When Slave server is started with these
+# special character sets, IO thread (a connection to Master) fails because
+# of the above said reason.
+#
+# Fix: If server's character set is not supported as client's character set,
+# then set default's client character set(latin1) as client's character set.
+###############################################################################
+--source include/master-slave.inc
+call mtr.add_suppression("'utf16' can not be used as client character set");
+CREATE TABLE t1(i VARCHAR(20));
+INSERT INTO t1 VALUES (0xFFFF);
+--sync_slave_with_master
+--let diff_tables=master:t1, slave:t1
+--source include/diff_tables.inc
+# Cleanup
+--connection master
+DROP TABLE t1;
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_sporadic_master-master.opt b/mysql-test/suite/rpl/t/rpl_sporadic_master-master.opt
new file mode 100644
index 00000000..5f038b69
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_sporadic_master-master.opt
@@ -0,0 +1 @@
+--debug-sporadic-binlog-dump-fail --debug-max-binlog-dump-events=2
diff --git a/mysql-test/suite/rpl/t/rpl_sporadic_master.test b/mysql-test/suite/rpl/t/rpl_sporadic_master.test
new file mode 100644
index 00000000..ad4c44cb
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_sporadic_master.test
@@ -0,0 +1,32 @@
+#
+# This include file is used by more than one test suite
+# (currently rpl and binlog_encryption).
+# Please check all dependent tests after modifying it
+#
+
+# test to see if replication can continue when master sporadically fails on
+# COM_BINLOG_DUMP and additionally limits the number of events per dump
+
+source include/master-slave.inc;
+
+create table t2(n int);
+create table t1(n int not null auto_increment primary key);
+insert into t1 values (NULL),(NULL);
+truncate table t1;
+# We have to use 4 in the following to make this test work with all table types
+insert into t1 values (4),(NULL);
+sync_slave_with_master;
+--source include/stop_slave.inc
+--source include/start_slave.inc
+connection master;
+insert into t1 values (NULL),(NULL);
+flush logs;
+truncate table t1;
+insert into t1 values (10),(NULL),(NULL),(NULL),(NULL),(NULL);
+sync_slave_with_master;
+select * from t1 ORDER BY n;
+connection master;
+drop table t1,t2;
+sync_slave_with_master;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_sql_thd_start_errno_cleared.test b/mysql-test/suite/rpl/t/rpl_sql_thd_start_errno_cleared.test
new file mode 100644
index 00000000..f6dcfd91
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_sql_thd_start_errno_cleared.test
@@ -0,0 +1,93 @@
+#
+# Ensure that when the slave restarts, the last error code displayed by
+# SHOW SLAVE STATUS is cleared before Slave_SQL_Running is set.
+#
+# To ensure that, this test uses the debug_sync mechanism to pause an errored
+# and restarting slave's SQL thread after it has set its running state to YES,
+# and then ensures that Last_SQL_Errno is 0. The slave error is a forced innodb
+# row lock timeout.
+#
+#
+# References
+# MDEV-31177: SHOW SLAVE STATUS Last_SQL_Errno Race Condition on Errored
+# Slave Restart
+#
+source include/have_binlog_format_row.inc;
+source include/have_innodb.inc;
+source include/have_debug.inc;
+source include/have_debug_sync.inc;
+source include/master-slave.inc;
+
+--connection master
+create table t1 (a int primary key, b int) engine=innodb;
+insert t1 values (1,1);
+--source include/save_master_gtid.inc
+
+--connection slave
+--source include/sync_with_master_gtid.inc
+--source include/stop_slave.inc
+set @save_innodb_lock_wait_timeout= @@global.innodb_lock_wait_timeout;
+set @save_slave_trans_retries= @@global.slave_transaction_retries;
+set @@global.innodb_lock_wait_timeout= 1;
+set @@global.slave_transaction_retries= 0;
+
+--connection master
+update t1 set b=b+10 where a=1;
+--source include/save_master_gtid.inc
+
+--connection slave1
+BEGIN;
+--eval SELECT * FROM t1 WHERE a=1 FOR UPDATE
+
+--connection slave
+--source include/start_slave.inc
+
+--let $slave_sql_errno= 1205
+--source include/wait_for_slave_sql_error.inc
+
+--connection slave1
+ROLLBACK;
+
+--connection slave
+set @save_dbug = @@global.debug_dbug;
+set @@global.debug_dbug= "+d,delay_sql_thread_after_release_run_lock";
+--source include/start_slave.inc
+set debug_sync= "now wait_for sql_thread_run_lock_released";
+
+--let $sql_running = query_get_value("SHOW SLAVE STATUS", Slave_SQL_Running, 1)
+--echo # Validating that the SQL thread is running..
+if (`SELECT strcmp("$sql_running", "YES") != 0`)
+{
+ --echo # ..failed
+ --echo # Slave_SQL_Running: $sql_running
+ --die Slave SQL thread is not running
+}
+--echo # ..success
+
+--let $last_error = query_get_value("SHOW SLAVE STATUS", Last_SQL_Errno, 1)
+--echo # Validating that Last_SQL_Errno is cleared..
+if ($last_error)
+{
+ --echo # ..failed
+ --echo # Last_SQL_Errno: $last_error
+ --die SHOW SLAVE STATUS shows the error from the last session on startup
+}
+--echo # ..success
+
+set debug_sync= "now signal sql_thread_continue";
+
+set @@global.debug_dbug= @saved_dbug;
+set debug_sync= "RESET";
+
+--echo # Cleanup
+--connection master
+drop table t1;
+
+--connection slave
+--source include/stop_slave.inc
+set @@global.innodb_lock_wait_timeout= @save_innodb_lock_wait_timeout;
+set @@global.slave_transaction_retries= @save_slave_trans_retries;
+--source include/start_slave.inc
+
+--source include/rpl_end.inc
+--echo # End of rpl_sql_thd_start_errno_cleared.test
diff --git a/mysql-test/suite/rpl/t/rpl_ssl.test b/mysql-test/suite/rpl/t/rpl_ssl.test
new file mode 100644
index 00000000..0420a6c8
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_ssl.test
@@ -0,0 +1,116 @@
+#
+# This include file is used by more than one test suite
+# (currently rpl and binlog_encryption).
+# Please check all dependent tests after modifying it
+#
+
+source include/no_valgrind_without_big.inc;
+source include/have_ssl_communication.inc;
+source include/master-slave.inc;
+
+# create a user for replication that requires ssl encryption
+connection master;
+create user replssl@localhost;
+grant replication slave on *.* to replssl@localhost require ssl;
+create table t1 (t int auto_increment, KEY(t));
+
+sync_slave_with_master;
+
+# Set slave to use SSL for connection to master
+stop slave;
+--replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR
+eval change master to
+ master_user='replssl',
+ master_password='',
+ master_ssl=1,
+ master_ssl_ca ='$MYSQL_TEST_DIR/std_data/cacert.pem',
+ master_ssl_cert='$MYSQL_TEST_DIR/std_data/client-cert.pem',
+ master_ssl_key='$MYSQL_TEST_DIR/std_data/client-key.pem';
+start slave;
+
+# Switch to master and insert one record, then sync it to slave
+connection master;
+insert into t1 values(1);
+sync_slave_with_master;
+
+# The record should now be on slave
+select * from t1;
+
+# The slave is synced and waiting/reading from master
+# SHOW SLAVE STATUS will show "Waiting for master to send event"
+let $status_items= Master_SSL_Allowed, Master_SSL_CA_Path, Master_SSL_CA_File, Master_SSL_Crl, Master_SSL_Crlpath, Master_SSL_Cert, Master_SSL_Key;
+source include/show_slave_status.inc;
+source include/check_slave_is_running.inc;
+
+# Stop the slave, as reported in bug#21871 it would hang
+STOP SLAVE;
+
+select * from t1;
+
+# Do the same thing a number of times
+disable_query_log;
+disable_result_log;
+# 2007-11-27 mats Bug #32756 Starting and stopping the slave in a loop can lose rows
+# After discussions with Engineering, I'm disabling this part of the test to avoid it causing
+# red trees.
+disable_parsing;
+let $i= 100;
+while ($i)
+{
+ start slave;
+ connection master;
+ insert into t1 values (NULL);
+ select * from t1; # Some variance
+ connection slave;
+ select * from t1; # Some variance
+ stop slave;
+ dec $i;
+}
+enable_parsing;
+START SLAVE;
+enable_query_log;
+enable_result_log;
+connection master;
+# INSERT one more record to make sure
+# the sync has something to do
+insert into t1 values (NULL);
+let $master_count= `select count(*) from t1`;
+
+sync_slave_with_master;
+--source include/wait_for_slave_to_start.inc
+source include/show_slave_status.inc;
+source include/check_slave_is_running.inc;
+
+let $slave_count= `select count(*) from t1`;
+
+if ($slave_count != $master_count)
+{
+ echo master and slave differed in number of rows;
+ echo master: $master_count;
+ echo slave: $slave_count;
+
+ connection master;
+ select count(*) t1;
+ select * from t1;
+ connection slave;
+ select count(*) t1;
+ select * from t1;
+ query_vertical show slave status;
+}
+
+connection master;
+drop user replssl@localhost;
+drop table t1;
+sync_slave_with_master;
+
+--source include/stop_slave.inc
+CHANGE MASTER TO
+ master_user = 'root',
+ master_ssl = 0,
+ master_ssl_ca = '',
+ master_ssl_cert = '',
+ master_ssl_key = '';
+
+--echo End of 5.0 tests
+--let $rpl_only_running_threads= 1
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_ssl1.test b/mysql-test/suite/rpl/t/rpl_ssl1.test
new file mode 100644
index 00000000..d994dd21
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_ssl1.test
@@ -0,0 +1,110 @@
+source include/have_ssl_communication.inc;
+source include/master-slave.inc;
+
+# We don't test all types of ssl auth params here since it's a bit hard
+# until problems with OpenSSL 0.9.7 are unresolved
+
+# creating replication user for whom ssl auth is required
+# preparing playground
+connection master;
+create user replssl@localhost;
+grant replication slave on *.* to replssl@localhost require ssl;
+create table t1 (t int);
+
+sync_slave_with_master;
+
+#trying to use this user without ssl
+stop slave;
+--source include/wait_for_slave_to_stop.inc
+change master to master_user='replssl',master_password='';
+start slave;
+
+#showing that replication don't work
+connection master;
+insert into t1 values (1);
+#reasonable timeout for changes to propagate to slave
+let $wait_condition= SELECT COUNT(*) = 1 FROM t1;
+source include/wait_condition.inc;
+connection slave;
+select * from t1;
+
+#showing that replication could work with ssl params
+stop slave;
+--source include/wait_for_slave_to_stop.inc
+--replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR
+eval change master to master_ssl=1 , master_ssl_ca ='$MYSQL_TEST_DIR/std_data/cacert.pem', master_ssl_cert='$MYSQL_TEST_DIR/std_data/client-cert.pem', master_ssl_key='$MYSQL_TEST_DIR/std_data/client-key.pem';
+start slave;
+--source include/wait_for_slave_to_start.inc
+
+#avoiding unneeded sleeps
+connection master;
+sync_slave_with_master;
+
+#checking that replication is ok
+select * from t1;
+
+#checking show slave status
+let $status_items= Master_SSL_Allowed, Master_SSL_CA_Path, Master_SSL_CA_File, Master_SSL_Cert, Master_SSL_Key;
+source include/show_slave_status.inc;
+source include/check_slave_is_running.inc;
+
+#checking if replication works without ssl also performing clean up
+stop slave;
+--source include/wait_for_slave_to_stop.inc
+change master to master_user='root',master_password='', master_ssl=0;
+start slave;
+--source include/wait_for_slave_to_start.inc
+connection master;
+drop user replssl@localhost;
+drop table t1;
+
+sync_slave_with_master;
+source include/show_slave_status.inc;
+source include/check_slave_is_running.inc;
+# End of 4.1 tests
+
+# Start replication with ssl_verify_server_cert turned on
+connection slave;
+stop slave;
+--source include/wait_for_slave_to_stop.inc
+--replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR
+eval change master to
+ master_host="localhost",
+ master_ssl=1 ,
+ master_ssl_ca ='$MYSQL_TEST_DIR/std_data/cacert.pem',
+ master_ssl_cert='$MYSQL_TEST_DIR/std_data/client-cert.pem',
+ master_ssl_key='$MYSQL_TEST_DIR/std_data/client-key.pem',
+ master_ssl_verify_server_cert=1;
+start slave;
+--source include/wait_for_slave_to_start.inc
+
+connection master;
+create table t1 (t int);
+insert into t1 values (1);
+
+sync_slave_with_master;
+
+echo on slave;
+#checking that replication is ok
+select * from t1;
+
+#checking show slave status
+source include/show_slave_status.inc;
+--source include/check_slave_is_running.inc
+
+# ==== Clean up ====
+
+connection master;
+drop table t1;
+sync_slave_with_master;
+--source include/stop_slave.inc
+CHANGE MASTER TO
+ master_host="127.0.0.1",
+ master_ssl_ca ='',
+ master_ssl_cert='',
+ master_ssl_key='',
+ master_ssl_verify_server_cert=0,
+ master_ssl=0;
+
+--let $rpl_only_running_threads= 1
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_start_alter_1.test b/mysql-test/suite/rpl/t/rpl_start_alter_1.test
new file mode 100644
index 00000000..9ce061f1
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_start_alter_1.test
@@ -0,0 +1,33 @@
+#
+# Start Alter with Legacy Replication
+#
+--source include/have_innodb.inc
+--source include/have_debug.inc
+--source include/master-slave.inc
+
+--connection master
+--let $binlog_alter_two_phase= `select @@binlog_alter_two_phase`
+set global binlog_alter_two_phase = ON;
+set binlog_alter_two_phase = ON;
+--connection slave
+--let $gtid_strict_mode= `select @@gtid_strict_mode`
+set global gtid_strict_mode=1;
+
+--echo # Legacy Master Slave
+--let $domain_1=0
+--let $domain_2=0
+--let $M_port= $MASTER_MYPORT
+--let $S_port= $SLAVE_MYPORT
+--let $sync_slave=1
+
+--source include/start_alter_include.inc
+--connection master
+--source include/save_master_gtid.inc
+
+--connection slave
+--source include/sync_with_master_gtid.inc
+--eval set global gtid_strict_mode = $gtid_strict_mode;
+
+--connection master
+--eval set global binlog_alter_two_phase=$binlog_alter_two_phase;
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_start_alter_2.test b/mysql-test/suite/rpl/t/rpl_start_alter_2.test
new file mode 100644
index 00000000..457409c5
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_start_alter_2.test
@@ -0,0 +1,53 @@
+#
+# Start Alter with Parallel Replication
+# 1 domain id
+# |Concurrent alters| < |Parallel workers on slave|
+# |x| denotes number of entities it encloses
+#
+--source include/have_innodb.inc
+--source include/have_debug.inc
+--source include/master-slave.inc
+--connection master
+--let $binlog_alter_two_phase= `select @@binlog_alter_two_phase`
+set global binlog_alter_two_phase = ON;
+set binlog_alter_two_phase = ON;
+--connection slave
+--let $gtid_strict_mode= `select @@gtid_strict_mode`
+--let $slave_parallel_threads= `select @@slave_parallel_threads`
+--let $slave_parallel_mode= `select @@slave_parallel_mode`
+set global gtid_strict_mode=1;
+
+
+--connection slave
+--source include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=10;
+set global slave_parallel_mode=optimistic;
+change master to master_use_gtid=slave_pos;
+--source include/start_slave.inc
+
+--echo # Parallel Slave
+--connection master
+--let $master_server= "master"
+--let $domain_1=0
+--let $domain_2=0
+--let $M_port= $MASTER_MYPORT
+--let $S_port= $SLAVE_MYPORT
+--let $sync_slave=1
+--source include/start_alter_include.inc
+--connection master
+--source include/save_master_gtid.inc
+
+--connection slave
+--source include/sync_with_master_gtid.inc
+
+--echo # cleanup
+--source include/stop_slave.inc
+--eval set global slave_parallel_threads = $slave_parallel_threads;
+--eval set global slave_parallel_mode = $slave_parallel_mode;
+--eval set global gtid_strict_mode = $gtid_strict_mode;
+set global gtid_domain_id= 0;
+--source include/start_slave.inc
+
+--connection master
+--eval set global binlog_alter_two_phase=$binlog_alter_two_phase;
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_start_alter_3.test b/mysql-test/suite/rpl/t/rpl_start_alter_3.test
new file mode 100644
index 00000000..b280aeb9
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_start_alter_3.test
@@ -0,0 +1,54 @@
+#
+# Start Alter with Parallel Replication
+# 1 domain id
+# |Concurrent alters| >= |Parallel workers on slave|
+# |x| denotes number of entities it encloses
+#
+--source include/have_log_bin.inc
+--source include/have_innodb.inc
+--source include/master-slave.inc
+--source include/have_debug.inc
+--connection master
+--let $binlog_alter_two_phase= `select @@binlog_alter_two_phase`
+set global binlog_alter_two_phase = ON;
+set binlog_alter_two_phase = ON;
+--connection slave
+--let $gtid_strict_mode= `select @@gtid_strict_mode`
+--let $slave_parallel_threads= `select @@slave_parallel_threads`
+--let $slave_parallel_mode= `select @@slave_parallel_mode`
+set global gtid_strict_mode=1;
+
+
+--connection slave
+--source include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=4;
+set global slave_parallel_mode=optimistic;
+change master to master_use_gtid=slave_pos;
+--source include/start_slave.inc
+
+--echo # Parallel Slave
+--connection master
+--let $master_server= "master"
+--let $domain_1=0
+--let $domain_2=0
+--let $M_port= $MASTER_MYPORT
+--let $S_port= $SLAVE_MYPORT
+--let $sync_slave=1
+--source include/start_alter_include.inc
+--connection master
+--source include/save_master_gtid.inc
+
+--connection slave
+--source include/sync_with_master_gtid.inc
+
+--echo # cleanup
+--source include/stop_slave.inc
+--eval set global slave_parallel_threads = $slave_parallel_threads;
+--eval set global slave_parallel_mode = $slave_parallel_mode;
+--eval set global gtid_strict_mode = $gtid_strict_mode;
+set global gtid_domain_id= 0;
+--source include/start_slave.inc
+
+--connection master
+--eval set global binlog_alter_two_phase=$binlog_alter_two_phase;
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_start_alter_4.test b/mysql-test/suite/rpl/t/rpl_start_alter_4.test
new file mode 100644
index 00000000..8c67b50a
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_start_alter_4.test
@@ -0,0 +1,54 @@
+#
+# Start Alter with Parallel Replication
+# 2 domain id
+# |Concurrent alters| < |Parallel workers on slave|
+# |x| denotes number of entities it encloses
+#
+--source include/have_log_bin.inc
+--source include/have_innodb.inc
+--source include/master-slave.inc
+--source include/have_debug.inc
+--connection master
+--let $binlog_alter_two_phase= `select @@binlog_alter_two_phase`
+set global binlog_alter_two_phase = ON;
+set binlog_alter_two_phase = ON;
+--connection slave
+--let $gtid_strict_mode= `select @@gtid_strict_mode`
+--let $slave_parallel_threads= `select @@slave_parallel_threads`
+--let $slave_parallel_mode= `select @@slave_parallel_mode`
+set global gtid_strict_mode=1;
+
+--connection slave
+--source include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=10;
+set global slave_parallel_mode=optimistic;
+change master to master_use_gtid=slave_pos;
+--source include/start_slave.inc
+
+--echo # Parallel Slave
+--connection master
+--let $master_server= "master"
+--let $domain_1=11
+--let $domain_2=12
+--let $M_port= $MASTER_MYPORT
+--let $S_port= $SLAVE_MYPORT
+--let $sync_slave=1
+--source include/start_alter_include.inc
+--connection master
+--source include/save_master_gtid.inc
+
+--connection slave
+--source include/sync_with_master_gtid.inc
+
+--echo # cleanup
+--source include/stop_slave.inc
+--eval set global slave_parallel_threads = $slave_parallel_threads;
+--eval set global slave_parallel_mode = $slave_parallel_mode;
+--eval set global gtid_strict_mode = $gtid_strict_mode;
+set global gtid_domain_id= 0;
+--source include/start_slave.inc
+
+--connection master
+--eval set global binlog_alter_two_phase=$binlog_alter_two_phase;
+set global gtid_domain_id= 0;
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_start_alter_5.test b/mysql-test/suite/rpl/t/rpl_start_alter_5.test
new file mode 100644
index 00000000..10d0d523
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_start_alter_5.test
@@ -0,0 +1,54 @@
+#
+# Start Alter with Parallel Replication
+# 2 domain id
+# |Concurrent alters| >= |Parallel workers on slave|
+# |x| denotes number of entities it encloses
+#
+--source include/have_log_bin.inc
+--source include/have_innodb.inc
+--source include/master-slave.inc
+--source include/have_debug.inc
+--connection master
+--let $binlog_alter_two_phase= `select @@binlog_alter_two_phase`
+set global binlog_alter_two_phase = ON;
+set binlog_alter_two_phase = ON;
+--connection slave
+--let $gtid_strict_mode= `select @@gtid_strict_mode`
+--let $slave_parallel_threads= `select @@slave_parallel_threads`
+--let $slave_parallel_mode= `select @@slave_parallel_mode`
+set global gtid_strict_mode=1;
+
+--connection slave
+--source include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=4;
+set global slave_parallel_mode=optimistic;
+change master to master_use_gtid=slave_pos;
+--source include/start_slave.inc
+
+--echo # Parallel Slave
+--connection master
+--let $master_server= "master"
+--let $domain_1=11
+--let $domain_2=12
+--let $M_port= $MASTER_MYPORT
+--let $S_port= $SLAVE_MYPORT
+--let $sync_slave=1
+--source include/start_alter_include.inc
+--connection master
+--source include/save_master_gtid.inc
+
+--connection slave
+--source include/sync_with_master_gtid.inc
+
+--echo # cleanup
+--source include/stop_slave.inc
+--eval set global slave_parallel_threads = $slave_parallel_threads;
+--eval set global slave_parallel_mode = $slave_parallel_mode;
+--eval set global gtid_strict_mode = $gtid_strict_mode;
+set global gtid_domain_id= 0;
+--source include/start_slave.inc
+
+--connection master
+--eval set global binlog_alter_two_phase=$binlog_alter_two_phase;
+set global gtid_domain_id= 0;
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_start_alter_6.test b/mysql-test/suite/rpl/t/rpl_start_alter_6.test
new file mode 100644
index 00000000..fc49ea4a
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_start_alter_6.test
@@ -0,0 +1,58 @@
+#
+# Start Alter with Parallel Replication
+# 2 domain id
+# |Concurrent alters| < |Parallel workers on slave|
+# |x| denotes number of entities it encloses
+# slave_domain_parallel_threads < |Concurrent Alters|
+#
+--source include/have_log_bin.inc
+--source include/have_innodb.inc
+--source include/master-slave.inc
+--source include/have_debug.inc
+--connection master
+--let $binlog_alter_two_phase= `select @@binlog_alter_two_phase`
+set global binlog_alter_two_phase = ON;
+set binlog_alter_two_phase = ON;
+--connection slave
+--let $gtid_strict_mode= `select @@gtid_strict_mode`
+--let $slave_parallel_threads= `select @@slave_parallel_threads`
+--let $slave_parallel_mode= `select @@slave_parallel_mode`
+--let $slave_domain_parallel_threads= `select @@slave_domain_parallel_threads`
+set global gtid_strict_mode=1;
+
+--connection slave
+--source include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=10;
+set global slave_parallel_mode=optimistic;
+set global slave_domain_parallel_threads=3;
+change master to master_use_gtid=slave_pos;
+--source include/start_slave.inc
+
+--echo # Parallel Slave
+--connection master
+--let $master_server= "master"
+--let $domain_1=11
+--let $domain_2=12
+--let $M_port= $MASTER_MYPORT
+--let $S_port= $SLAVE_MYPORT
+--let $sync_slave=1
+--source include/start_alter_include.inc
+--connection master
+--source include/save_master_gtid.inc
+
+--connection slave
+--source include/sync_with_master_gtid.inc
+
+--echo # cleanup
+--source include/stop_slave.inc
+--eval set global slave_parallel_threads = $slave_parallel_threads;
+--eval set global slave_parallel_mode = $slave_parallel_mode;
+--eval set global gtid_strict_mode = $gtid_strict_mode;
+--eval set global slave_domain_parallel_threads = $slave_domain_parallel_threads;
+set global gtid_domain_id= 0;
+--source include/start_slave.inc
+
+--connection master
+--eval set global binlog_alter_two_phase=$binlog_alter_two_phase;
+set global gtid_domain_id= 0;
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_start_alter_7.cnf b/mysql-test/suite/rpl/t/rpl_start_alter_7.cnf
new file mode 100644
index 00000000..a0f6dc57
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_start_alter_7.cnf
@@ -0,0 +1,19 @@
+!include ../my.cnf
+
+[mysqld.1]
+log-bin
+log-slave-updates
+
+[mysqld.2]
+log-bin
+log-slave-updates
+
+[mysqld.3]
+log-bin
+log-slave-updates
+
+
+[ENV]
+SERVER_MYPORT_1= @mysqld.1.port
+SERVER_MYPORT_2= @mysqld.2.port
+SERVER_MYPORT_3= @mysqld.3.port
diff --git a/mysql-test/suite/rpl/t/rpl_start_alter_7.test b/mysql-test/suite/rpl/t/rpl_start_alter_7.test
new file mode 100644
index 00000000..7225c075
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_start_alter_7.test
@@ -0,0 +1,112 @@
+#
+# Start Alter with Parallel Replication, With 2 sources
+# 2 domain id (From 2 sources)
+# |Concurrent alters| >= |Parallel workers on slave|
+# |x| denotes number of entities it encloses
+#
+--source include/have_log_bin.inc
+--source include/have_innodb.inc
+--source include/have_debug.inc
+--connect (server_1,127.0.0.1,root,,,$SERVER_MYPORT_1)
+--connect (server_2,127.0.0.1,root,,,$SERVER_MYPORT_2)
+--connect (server_3,127.0.0.1,root,,,$SERVER_MYPORT_3)
+
+--connection server_1
+--let $binlog_alter_two_phase= `select @@binlog_alter_two_phase`
+set global binlog_alter_two_phase = ON;
+set binlog_alter_two_phase = ON;
+
+--connection server_2
+stop slave;
+set global binlog_alter_two_phase=true;
+
+--connection server_3
+--let $gtid_strict_mode= `select @@gtid_strict_mode`
+--let $slave_parallel_threads= `select @@slave_parallel_threads`
+--let $slave_parallel_mode= `select @@slave_parallel_mode`
+SET GLOBAL slave_parallel_threads=8;
+set global slave_parallel_mode=optimistic;
+set global gtid_strict_mode=1;
+
+
+--disable_warnings
+--disable_query_log
+--replace_result $SERVER_MYPORT_1 MYPORT_1
+eval change master 'm1' to master_port=$SERVER_MYPORT_1 , master_host='127.0.0.1', master_user='root', master_use_gtid=slave_pos;
+--replace_result $SERVER_MYPORT_2 MYPORT_2
+eval change master 'm2' to master_port=$SERVER_MYPORT_2 , master_host='127.0.0.1', master_user='root', master_use_gtid=slave_pos;
+--enable_query_log
+--enable_warnings
+
+--connection server_1
+set gtid_domain_id= 11;
+create database s1;
+use s1;
+--let $domain_1=11
+--let $domain_2=11
+--let $M_port= $SERVER_MYPORT_1
+--let $S_port= $SERVER_MYPORT_3
+--let $sync_slave=0
+--let $db_name=s1
+--source include/start_alter_include.inc
+--connection server_1
+drop database s1;
+select @@gtid_binlog_pos;
+--let $master_pos_1= `SELECT @@gtid_binlog_pos`
+
+--connection server_2
+set gtid_domain_id= 12;
+create database s2;
+use s2;
+--let $domain_1=12
+--let $domain_2=12
+--let $M_port= $SERVER_MYPORT_2
+--let $S_port= $SERVER_MYPORT_3
+--let $sync_slave=0
+--let $db_name=s2
+--source include/start_alter_include.inc
+--connection server_2
+drop database s2;
+select @@gtid_binlog_pos;
+--let $master_pos_2= `SELECT @@gtid_binlog_pos`
+
+--connection server_3
+start all slaves;
+set default_master_connection = 'm1';
+--source include/wait_for_slave_to_start.inc
+set default_master_connection = 'm2';
+--source include/wait_for_slave_to_start.inc
+
+set default_master_connection = 'm1';
+--let $master_pos= $master_pos_1
+--source include/sync_with_master_gtid.inc
+set default_master_connection = 'm2';
+--let $master_pos= $master_pos_2
+--source include/sync_with_master_gtid.inc
+
+--echo # cleanup
+--connection server_3
+set default_master_connection = 'm1';
+--source include/stop_slave.inc
+set default_master_connection = 'm2';
+--source include/stop_slave.inc
+--eval set global slave_parallel_threads = $slave_parallel_threads;
+--eval set global slave_parallel_mode = $slave_parallel_mode;
+--eval set global gtid_strict_mode = $gtid_strict_mode;
+set global gtid_domain_id= 0;
+reset master;
+RESET SLAVE ALL;
+SET GLOBAL gtid_slave_pos= '';
+
+--connection server_1
+--eval set global binlog_alter_two_phase=$binlog_alter_two_phase;
+set global gtid_domain_id= 0;
+reset master;
+--connection server_2
+set global gtid_domain_id= 0;
+--eval set global binlog_alter_two_phase=$binlog_alter_two_phase
+reset master;
+
+--disconnect server_1
+--disconnect server_2
+--disconnect server_3
diff --git a/mysql-test/suite/rpl/t/rpl_start_alter_8.cnf b/mysql-test/suite/rpl/t/rpl_start_alter_8.cnf
new file mode 100644
index 00000000..a0f6dc57
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_start_alter_8.cnf
@@ -0,0 +1,19 @@
+!include ../my.cnf
+
+[mysqld.1]
+log-bin
+log-slave-updates
+
+[mysqld.2]
+log-bin
+log-slave-updates
+
+[mysqld.3]
+log-bin
+log-slave-updates
+
+
+[ENV]
+SERVER_MYPORT_1= @mysqld.1.port
+SERVER_MYPORT_2= @mysqld.2.port
+SERVER_MYPORT_3= @mysqld.3.port
diff --git a/mysql-test/suite/rpl/t/rpl_start_alter_8.test b/mysql-test/suite/rpl/t/rpl_start_alter_8.test
new file mode 100644
index 00000000..4ab8e2b0
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_start_alter_8.test
@@ -0,0 +1,109 @@
+#
+# Start Alter with Parallel Replication, With 2 sources
+# 2 domain id (From 2 sources)
+# |Concurrent alters| < |Parallel workers on slave|
+# |x| denotes number of entities it encloses
+#
+--source include/have_log_bin.inc
+--source include/have_innodb.inc
+--source include/have_debug.inc
+--connect (server_1,127.0.0.1,root,,,$SERVER_MYPORT_1)
+--connect (server_2,127.0.0.1,root,,,$SERVER_MYPORT_2)
+--connect (server_3,127.0.0.1,root,,,$SERVER_MYPORT_3)
+
+--connection server_1
+--let $binlog_alter_two_phase= `select @@binlog_alter_two_phase`
+set global binlog_alter_two_phase = ON;
+set binlog_alter_two_phase = ON;
+
+--connection server_2
+stop slave;
+set global binlog_alter_two_phase=true;
+
+--connection server_3
+--let $gtid_strict_mode= `select @@gtid_strict_mode`
+--let $slave_parallel_threads= `select @@slave_parallel_threads`
+--let $slave_parallel_mode= `select @@slave_parallel_mode`
+SET GLOBAL slave_parallel_threads=20;
+set global slave_parallel_mode=optimistic;
+set global gtid_strict_mode=1;
+
+--disable_warnings
+--disable_query_log
+--replace_result $SERVER_MYPORT_1 MYPORT_1
+eval change master 'm1' to master_port=$SERVER_MYPORT_1 , master_host='127.0.0.1', master_user='root', master_use_gtid=slave_pos;
+--replace_result $SERVER_MYPORT_2 MYPORT_2
+eval change master 'm2' to master_port=$SERVER_MYPORT_2 , master_host='127.0.0.1', master_user='root', master_use_gtid=slave_pos;
+--enable_query_log
+--enable_warnings
+
+--connection server_1
+set gtid_domain_id= 11;
+create database s1;
+use s1;
+--let $domain_1=11
+--let $domain_2=11
+--let $M_port= $SERVER_MYPORT_1
+--let $S_port= $SERVER_MYPORT_3
+--let $sync_slave=0
+--let $db_name=s1
+--source include/start_alter_include.inc
+--connection server_1
+drop database s1;
+--let $master_pos_1= `SELECT @@gtid_binlog_pos`
+
+--connection server_2
+set gtid_domain_id= 12;
+create database s2;
+use s2;
+--let $domain_1=12
+--let $domain_2=12
+--let $M_port= $SERVER_MYPORT_2
+--let $S_port= $SERVER_MYPORT_3
+--let $sync_slave=0
+--let $db_name=s2
+--source include/start_alter_include.inc
+--connection server_2
+drop database s2;
+--let $master_pos_2= `SELECT @@gtid_binlog_pos`
+
+--connection server_3
+start all slaves;
+set default_master_connection = 'm1';
+--source include/wait_for_slave_to_start.inc
+set default_master_connection = 'm2';
+--source include/wait_for_slave_to_start.inc
+
+set default_master_connection = 'm1';
+--let $master_pos= $master_pos_1
+--source include/sync_with_master_gtid.inc
+set default_master_connection = 'm2';
+--let $master_pos= $master_pos_2
+--source include/sync_with_master_gtid.inc
+
+--echo # cleanup
+--connection server_3
+set default_master_connection = 'm1';
+--source include/stop_slave.inc
+set default_master_connection = 'm2';
+--source include/stop_slave.inc
+--eval set global slave_parallel_threads = $slave_parallel_threads;
+--eval set global slave_parallel_mode = $slave_parallel_mode;
+--eval set global gtid_strict_mode = $gtid_strict_mode;
+set global gtid_domain_id= 0;
+reset master;
+RESET SLAVE ALL;
+SET GLOBAL gtid_slave_pos= '';
+
+--connection server_1
+--eval set global binlog_alter_two_phase=$binlog_alter_two_phase;
+set global gtid_domain_id= 0;
+reset master;
+--connection server_2
+set global gtid_domain_id= 0;
+--eval set global binlog_alter_two_phase=$binlog_alter_two_phase;
+reset master;
+
+--disconnect server_1
+--disconnect server_2
+--disconnect server_3
diff --git a/mysql-test/suite/rpl/t/rpl_start_alter_bugs.test b/mysql-test/suite/rpl/t/rpl_start_alter_bugs.test
new file mode 100644
index 00000000..52eef9fb
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_start_alter_bugs.test
@@ -0,0 +1,47 @@
+#
+# MDEV-22985 Assertion `!(thd->rgi_slave && thd->rgi_slave->did_mark_start_commit)' failed in ha_rollback_trans#
+#
+#
+
+--source include/have_log_bin.inc
+--source include/have_innodb.inc
+--source include/master-slave.inc
+
+--connection master
+set global binlog_alter_two_phase=true;
+
+--connection slave
+stop slave;
+SET global slave_parallel_threads=2;
+set global slave_parallel_mode=optimistic;
+start slave;
+--connection master
+
+CREATE TABLE t1 (i int primary key) ENGINE = InnoDB;
+--connection master1
+ALTER TABLE t1 DROP PRIMARY KEY;
+ALTER TABLE t1 ADD UNIQUE KEY ui (i);
+ALTER TABLE t1 ADD PRIMARY KEY (i);
+
+--sync_slave_with_master
+
+ #MENT 1274
+--connection master
+drop table t1;
+CREATE TABLE t1 (a int)engine=innodb;
+ALTER TABLE t1 add column b int, LOCK=EXCLUSIVE;
+drop table t1;
+CREATE TABLE t1 (pk int)engine=innodb;
+--error ER_CANT_DROP_FIELD_OR_KEY
+ALTER TABLE t1 DROP FOREIGN KEY y, LOCK=EXCLUSIVE;
+drop table t1;
+--sync_slave_with_master
+--connection master
+set global binlog_alter_two_phase=false;
+
+--connection slave
+--source include/stop_slave.inc
+SET global slave_parallel_threads=0;
+--source include/start_slave.inc
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_start_alter_chain_basic.cnf b/mysql-test/suite/rpl/t/rpl_start_alter_chain_basic.cnf
new file mode 100644
index 00000000..498d8ed1
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_start_alter_chain_basic.cnf
@@ -0,0 +1,24 @@
+!include ../my.cnf
+
+[mysqld.1]
+log-slave-updates
+loose-innodb
+
+[mysqld.2]
+log-slave-updates
+loose-innodb
+
+[mysqld.3]
+log-slave-updates
+binlog_alter_two_phase=1
+loose-innodb
+
+[mysqld.4]
+loose-innodb
+
+[ENV]
+SERVER_MYPORT_3= @mysqld.3.port
+SERVER_MYSOCK_3= @mysqld.3.socket
+
+SERVER_MYPORT_4= @mysqld.4.port
+SERVER_MYSOCK_4= @mysqld.4.socket
diff --git a/mysql-test/suite/rpl/t/rpl_start_alter_chain_basic.test b/mysql-test/suite/rpl/t/rpl_start_alter_chain_basic.test
new file mode 100644
index 00000000..2c6f9c0f
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_start_alter_chain_basic.test
@@ -0,0 +1,54 @@
+#
+# MENT-662 Lag Free alter for slave
+# In this we will see if chain replication works as
+# M->S(Legacy)->S(Parallel)->S(Legacy, without log-slave-upadates)
+#
+--source include/have_innodb.inc
+--let $rpl_topology=1->2->3->4
+--source include/rpl_init.inc
+
+--connection server_3
+--let $gtid_strict_mode= `select @@gtid_strict_mode`
+--let $slave_parallel_threads= `select @@slave_parallel_threads`
+--let $slave_parallel_mode= `select @@slave_parallel_mode`
+set global gtid_strict_mode=1;
+
+--source include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=10;
+set global slave_parallel_mode=optimistic;
+change master to master_use_gtid=slave_pos;
+--source include/start_slave.inc
+
+
+--connection server_1
+--let $binlog_alter_two_phase= `select @@binlog_alter_two_phase`
+set global binlog_alter_two_phase=ON;
+set binlog_alter_two_phase=ON;
+--let $engine=innodb
+--let $sync_slave= 1
+connect(master_node,127.0.0.1,root,,$db_name, $SERVER_MYPORT_1);
+connect(slave_node,127.0.0.1,root,,test, $SERVER_MYPORT_2);
+--source include/start_alter_basic.inc
+--disconnect master_node
+--disconnect slave_node
+--connection server_1
+--eval set global binlog_alter_two_phase=$binlog_alter_two_phase
+--source include/rpl_sync.inc
+
+
+--connection server_2
+select domain_id, seq_no from mysql.gtid_slave_pos order by seq_no desc limit 1;
+
+--connection server_3
+select domain_id, seq_no from mysql.gtid_slave_pos order by seq_no desc limit 1;
+--source include/stop_slave.inc
+--eval set global slave_parallel_threads = $slave_parallel_threads;
+--eval set global slave_parallel_mode = $slave_parallel_mode;
+--eval set global gtid_strict_mode = $gtid_strict_mode;
+--source include/start_slave.inc
+select @@slave_parallel_threads;
+
+--connection server_4
+select domain_id, seq_no from mysql.gtid_slave_pos order by seq_no desc limit 1;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_start_alter_ftwrl.test b/mysql-test/suite/rpl/t/rpl_start_alter_ftwrl.test
new file mode 100644
index 00000000..a8528cc6
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_start_alter_ftwrl.test
@@ -0,0 +1,91 @@
+#
+# MDEV-11675 Two phase ALTER binlogging
+#
+# Prove that FTWRL in the middle of START and "COMPLETE" parts of ALTER
+# is safe.
+
+--source include/have_debug.inc
+--source include/have_innodb.inc
+--source include/master-slave.inc
+
+--connection slave
+--let $slave_parallel_threads= `select @@slave_parallel_threads`
+--let $slave_parallel_mode= `select @@slave_parallel_mode`
+--let $debug = `SELECT @@global.debug_dbug`
+
+--source include/stop_slave.inc
+
+SET @@global.slave_parallel_threads=4;
+SET @@global.slave_parallel_mode=optimistic;
+CHANGE MASTER TO master_use_gtid=slave_pos;
+
+SET @@global.debug_dbug="+d,at_write_start_alter";
+--source include/start_slave.inc
+
+--connection master
+SET @@session.binlog_alter_two_phase=true;
+
+CREATE TABLE t1 (a INT) ENGINE=innodb;
+--source include/save_master_gtid.inc
+
+# Make sure the table exists on slave now.
+--connection slave
+--source include/sync_with_master_gtid.inc
+
+--connection master
+SET @@session.alter_algorithm='INSTANT';
+SET @@session.gtid_domain_id=11;
+ALTER TABLE t1 ADD COLUMN b int;
+
+
+--echo # START Alter having exclusive lock is waiting for the signal
+--connection slave
+--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE = 'debug sync point: now'
+--source include/wait_condition.inc
+
+--echo # FTWRL is sent first to wait for SA
+--connection slave1
+--send FLUSH TABLES WITH READ LOCK
+
+--echo # SA completes
+# First wait for the FTWRL arrival.
+--connection slave
+--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE INFO = 'FLUSH TABLES WITH READ LOCK' and STATE = 'Waiting for worker threads to pause for global read lock'
+--source include/wait_condition.inc
+
+set DEBUG_SYNC= "now signal alter_cont";
+
+--connection slave1
+--reap
+
+# Commit ALTER is hanging now
+--connection slave
+--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE COMMAND = 'Slave_worker' AND STATE = 'Waiting for backup lock'
+--source include/wait_condition.inc
+
+--echo # Release CA
+--connection slave1
+UNLOCK TABLES;
+
+--connection master
+--sync_slave_with_master
+
+SHOW CREATE TABLE t1;
+--source include/show_binlog_events.inc
+
+--connection master
+DROP TABLE t1;
+
+--sync_slave_with_master
+
+--echo # cleanup
+--connection slave
+set DEBUG_SYNC = RESET;
+--source include/stop_slave.inc
+--eval set global slave_parallel_threads = $slave_parallel_threads
+--eval set global slave_parallel_mode = $slave_parallel_mode
+--eval set @@global.debug_dbug = "$debug"
+--source include/start_slave.inc
+
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_start_alter_instant.test b/mysql-test/suite/rpl/t/rpl_start_alter_instant.test
new file mode 100644
index 00000000..ecb62e04
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_start_alter_instant.test
@@ -0,0 +1,30 @@
+# MDEV-11675
+# Prove that "fast" ALTER options also combine with @@binlog_alter_two_phase.
+--source include/have_innodb.inc
+--source include/master-slave.inc
+
+--connection master
+set binlog_alter_two_phase=true;
+CREATE OR REPLACE TABLE tab (
+ a int PRIMARY KEY,
+ b varchar(50),
+ c varchar(50)
+) CHARACTER SET=latin1 engine=innodb;
+
+SET SESSION alter_algorithm='INSTANT';
+ALTER TABLE tab MODIFY COLUMN b varchar(100);
+SET SESSION alter_algorithm='NOCOPY';
+ALTER TABLE tab MODIFY COLUMN c varchar(100);
+SHOW CREATE TABLE tab;
+--source include/show_binlog_events.inc
+
+--sync_slave_with_master
+SHOW CREATE TABLE tab;
+--source include/show_binlog_events.inc
+
+--connection master
+DROP TABLE tab;
+
+--sync_slave_with_master
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_start_alter_mysqlbinlog_1.test b/mysql-test/suite/rpl/t/rpl_start_alter_mysqlbinlog_1.test
new file mode 100644
index 00000000..f655d3c1
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_start_alter_mysqlbinlog_1.test
@@ -0,0 +1,38 @@
+#
+# Start Alter with binlog applied using mysqlbinlog
+# single master with only one domain id
+#
+--source include/have_innodb.inc
+--source include/have_debug.inc
+--source include/master-slave.inc
+
+--connection master
+set global binlog_alter_two_phase=true;
+--connection slave
+--source include/stop_slave.inc
+set global gtid_strict_mode=1;
+
+--echo # Legacy Master Slave
+--let $domain_1=0
+--let $domain_2=0
+--let $M_port= $MASTER_MYPORT
+--let $S_port= $SLAVE_MYPORT
+--let $sync_slave=0
+
+--source include/start_alter_include.inc
+--connection master
+--let $MYSQLD_DATADIR= `select @@datadir;`
+--exec $MYSQL_BINLOG $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/master.sql
+select @@gtid_binlog_state;
+RESET master;
+
+--connection slave
+--exec $MYSQL --host=127.0.0.1 --port=$SLAVE_MYPORT -e "source $MYSQLTEST_VARDIR/tmp/master.sql"
+select @@gtid_binlog_state;
+set global gtid_strict_mode=0;
+--source include/start_slave.inc
+
+--connection master
+set global binlog_alter_two_phase=false;
+remove_file $MYSQLTEST_VARDIR/tmp/master.sql;
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_start_alter_mysqlbinlog_2.cnf b/mysql-test/suite/rpl/t/rpl_start_alter_mysqlbinlog_2.cnf
new file mode 100644
index 00000000..a0f6dc57
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_start_alter_mysqlbinlog_2.cnf
@@ -0,0 +1,19 @@
+!include ../my.cnf
+
+[mysqld.1]
+log-bin
+log-slave-updates
+
+[mysqld.2]
+log-bin
+log-slave-updates
+
+[mysqld.3]
+log-bin
+log-slave-updates
+
+
+[ENV]
+SERVER_MYPORT_1= @mysqld.1.port
+SERVER_MYPORT_2= @mysqld.2.port
+SERVER_MYPORT_3= @mysqld.3.port
diff --git a/mysql-test/suite/rpl/t/rpl_start_alter_mysqlbinlog_2.test b/mysql-test/suite/rpl/t/rpl_start_alter_mysqlbinlog_2.test
new file mode 100644
index 00000000..c7d5bd66
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_start_alter_mysqlbinlog_2.test
@@ -0,0 +1,164 @@
+#
+# MENT-662 Lag Free Alter On Slave
+#
+
+# Start Alter with Parallel Replication, With 2 sources
+# 2 domain id (From 2 sources)
+# |Concurrent alters| < |Parallel workers on slave|
+# |x| denotes number of entities it encloses
+# And then binary log from slave is replayed to slave again to check if
+# binlog output is okay.
+#
+
+--source include/have_log_bin.inc
+--source include/have_innodb.inc
+--source include/have_debug.inc
+--connect (server_1,127.0.0.1,root,,,$SERVER_MYPORT_1)
+--connect (server_2,127.0.0.1,root,,,$SERVER_MYPORT_2)
+--connect (server_3,127.0.0.1,root,,,$SERVER_MYPORT_3)
+
+--connection server_1
+SET @save_binlog_alter_two_phase= @@GLOBAL.binlog_alter_two_phase;
+SET GLOBAL binlog_alter_two_phase = ON;
+SET binlog_alter_two_phase = ON;
+--echo # Create table and perform CA and RA
+CREATE TABLE t1( a INT, b INT) ENGINE=InnoDB;
+INSERT INTO t1 VALUES(1,1);
+INSERT INTO t1 VALUES(2,2);
+--echo # Normal Alter
+ALTER TABLE t1 ADD COLUMN c INT;
+--echo # Failed Alter
+INSERT INTO t1 VALUES(1,1, NULL);
+--error ER_DUP_ENTRY
+ALTER TABLE t1 CHANGE a a INT UNIQUE;
+SHOW CREATE TABLE t1;
+SELECT @@gtid_binlog_state;
+
+--echo # apply the binlog
+let MYSQLD_DATADIR= `select @@datadir;`;
+--exec $MYSQL_BINLOG $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/master_1.sql
+DROP TABLE t1;
+--echo # reset the binlog
+RESET MASTER;
+
+--echo # execute the binlog
+--exec $MYSQL --port=$SERVER_MYPORT_1 --host=127.0.0.1 -e "source $MYSQLTEST_VARDIR/tmp/master_1.sql"
+SELECT @@gtid_binlog_state;
+--echo # Same as before
+SHOW CREATE TABLE t1;
+DROP TABLE t1;
+--echo # reset the binlog
+RESET MASTER;
+RESET SLAVE;
+remove_file $MYSQLTEST_VARDIR/tmp/master_1.sql;
+
+--connection server_2
+SET @save_binlog_alter_two_phase= @@GLOBAL.binlog_alter_two_phase;
+SET GLOBAL binlog_alter_two_phase = ON;
+
+--connection server_3
+SET @save_gtid_strict_mode= @@GLOBAL.gtid_strict_mode;
+SET @slave_parallel_threads= @@GLOBAL.slave_parallel_threads;
+SET @slave_parallel_mode= @@GLOBAL.slave_parallel_mode;
+SET GLOBAL slave_parallel_threads=20;
+SET GLOBAL slave_parallel_mode=optimistic;
+SET GLOBAL gtid_strict_mode=1;
+
+--disable_warnings
+--disable_query_log
+--replace_result $SERVER_MYPORT_1 MYPORT_1
+eval CHANGE MASTER 'm1' TO MASTER_PORT=$SERVER_MYPORT_1, MASTER_HOST='127.0.0.1', MASTER_USER='root', MASTER_USE_GTID=slave_pos;
+--replace_result $SERVER_MYPORT_2 MYPORT_2
+eval CHANGE MASTER 'm2' TO MASTER_PORT=$SERVER_MYPORT_2, MASTER_HOST='127.0.0.1', MASTER_USER='root', MASTER_USE_GTID=slave_pos;
+--enable_query_log
+--enable_warnings
+
+--connection server_1
+SET gtid_domain_id= 11;
+CREATE DATABASE s1;
+USE s1;
+--let $domain_1=11
+--let $domain_2=11
+--let $M_port= $SERVER_MYPORT_1
+--let $S_port= $SERVER_MYPORT_3
+--let $sync_slave=0
+--let $db_name=s1
+--source include/start_alter_include.inc
+
+--connection server_1
+DROP DATABASE s1;
+--let $master_pos_1= `SELECT @@gtid_binlog_pos`
+
+--connection server_2
+SET gtid_domain_id= 12;
+CREATE DATABASE s2;
+USE s2;
+--let $domain_1=12
+--let $domain_2=12
+--let $M_port= $SERVER_MYPORT_2
+--let $S_port= $SERVER_MYPORT_3
+--let $sync_slave=0
+--let $db_name=s2
+--source include/start_alter_include.inc
+--connection server_2
+DROP DATABASE s2;
+--let $master_pos_2= `SELECT @@gtid_binlog_pos`
+
+--connection server_3
+START ALL SLAVES;
+SET default_master_connection = 'm1';
+--source include/wait_for_slave_to_start.inc
+SET default_master_connection = 'm2';
+--source include/wait_for_slave_to_start.inc
+
+SET default_master_connection = 'm1';
+--let $master_pos= $master_pos_1
+--source include/sync_with_master_gtid.inc
+SET default_master_connection = 'm2';
+--let $master_pos= $master_pos_2
+--source include/sync_with_master_gtid.inc
+
+--echo # Stop slaves and apply binlog
+--connection server_3
+SET default_master_connection = 'm1';
+--source include/stop_slave.inc
+SET default_master_connection = 'm2';
+--source include/stop_slave.inc
+SET GLOBAL slave_parallel_threads = @slave_parallel_threads;
+SET GLOBAL slave_parallel_mode = @slave_parallel_mode;
+SET GLOBAL gtid_strict_mode = @save_gtid_strict_mode;
+SET GLOBAL gtid_domain_id= 0;
+SELECT @@gtid_binlog_state;
+
+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=$SERVER_MYPORT_3 --host=127.0.0.1 -e "source $MYSQLTEST_VARDIR/tmp/slave_1.sql"
+SELECT @@gtid_binlog_state;
+
+--echo # 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=$SERVER_MYPORT_3 --host=127.0.0.1 -e "source $MYSQLTEST_VARDIR/tmp/slave_2.sql"
+SELECT @@gtid_binlog_state;
+remove_file $MYSQLTEST_VARDIR/tmp/slave_1.sql;
+remove_file $MYSQLTEST_VARDIR/tmp/slave_2.sql;
+RESET MASTER;
+RESET SLAVE ALL;
+SET GLOBAL gtid_slave_pos= '';
+
+--connection server_1
+SET GLOBAL binlog_alter_two_phase=@save_binlog_alter_two_phase;
+SET GLOBAL gtid_domain_id= 0;
+RESET MASTER;
+--connection server_2
+SET GLOBAL gtid_domain_id= 0;
+SET GLOBAL binlog_alter_two_phase=@save_binlog_alter_two_phase;
+RESET MASTER;
+
+--disconnect server_1
+--disconnect server_2
+--disconnect server_3
diff --git a/mysql-test/suite/rpl/t/rpl_start_alter_optimize.test b/mysql-test/suite/rpl/t/rpl_start_alter_optimize.test
new file mode 100644
index 00000000..528f2b52
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_start_alter_optimize.test
@@ -0,0 +1,25 @@
+# MDEV-11675 two phase logged ALTER
+#
+# The tests verifies execution of non-ALTER queries that are handled
+# through mysql_alter_table function.
+
+--source include/have_log_bin.inc
+--source include/have_innodb.inc
+--source include/master-slave.inc
+
+--connection master
+set binlog_alter_two_phase = ON;
+
+--connection master
+CREATE TABLE t1 (i int) engine=innodb;
+CREATE TABLE t2 (i int) engine=innodb;
+
+ALTER TABLE t1 DROP CONSTRAINT IF EXISTS y;
+OPTIMIZE TABLE t2;
+
+--sync_slave_with_master
+
+--connection master
+drop table t1,t2;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_start_alter_options.test b/mysql-test/suite/rpl/t/rpl_start_alter_options.test
new file mode 100644
index 00000000..12125b49
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_start_alter_options.test
@@ -0,0 +1,31 @@
+# This test will test all the option related to the Alter Table command
+# NOTE not all alter statements will follow alter_algorithm since for some statements
+# copy is only option
+# parameters
+# $alter_algorithm {DEFAULT|INPLACE|COPY|NOCOPY|INSTANT}
+# $show_binlog
+#
+
+--source include/have_partition.inc
+--source include/have_innodb.inc
+--source include/master-slave.inc
+
+--let $alter_algorithm= default
+#--let $show_binlog= false
+--source include/start_alter_options.inc
+
+--let $alter_algorithm= inplace
+--source include/start_alter_options.inc
+
+--let $alter_algorithm= copy
+--source include/start_alter_options.inc
+
+--echo # Prove formal support for nocopy and instant
+--let $alter_algorithm= instant
+--source include/start_alter_options.inc
+
+--let $alter_algorithm= nocopy
+--source include/start_alter_options.inc
+
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_start_alter_para_to_seq.test b/mysql-test/suite/rpl/t/rpl_start_alter_para_to_seq.test
new file mode 100644
index 00000000..37e25313
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_start_alter_para_to_seq.test
@@ -0,0 +1,24 @@
+# MDEV-11675 binlog_alter_two_phase
+# MDEV-27511 Assertion `rgi->gtid_ev_flags_extra & Gtid_log_event::FL_COMMIT_ALTER_E1' failed
+# in write_bin_log_start_alter
+#
+--source include/have_log_bin.inc
+--source include/master-slave.inc
+
+# The test proves the assert is not hit anymore.
+--connection master
+CREATE TABLE t1 (a1 int, d1 int DEFAULT 0);
+INSERT INTO t1 VALUES (1,1) ;
+SET binlog_alter_two_phase = ON;
+ALTER TABLE t1 WAIT 9 RENAME COLUMN a1 TO a2;
+SET binlog_alter_two_phase = OFF;
+ALTER TABLE t1 ALTER COLUMN d1 DROP DEFAULT;
+
+--sync_slave_with_master
+
+# Cleanup
+--connection master
+drop table t1;
+--sync_slave_with_master
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_start_alter_restart_master.test b/mysql-test/suite/rpl/t/rpl_start_alter_restart_master.test
new file mode 100644
index 00000000..aac3af6f
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_start_alter_restart_master.test
@@ -0,0 +1,81 @@
+# Test crashing of master after writing start alter into binary log.
+# And the doing the same alter again, to test on slave if that is successful
+# ====> SA Crash SA CA Case
+#
+--source include/have_log_bin.inc
+--source include/have_binlog_format_mixed.inc
+--source include/have_innodb.inc
+--source include/master-slave.inc
+--source include/have_debug.inc
+--source include/no_valgrind_without_big.inc
+
+--connection slave
+--source include/stop_slave.inc
+CHANGE MASTER TO MASTER_USE_GTID=NO;
+--source include/start_slave.inc
+
+--connection slave
+SET @old_debug_slave= @@global.debug;
+stop slave;
+--let $gtid_strict_mode= `select @@gtid_strict_mode`
+--let $slave_parallel_threads= `select @@slave_parallel_threads`
+--let $slave_parallel_mode= `select @@slave_parallel_mode`
+SET GLOBAL slave_parallel_threads=4;
+set global slave_parallel_mode=optimistic;
+set global gtid_strict_mode=1;
+start slave;
+
+--connection master
+call mtr.add_suppression("ALTER query started at .+ could not be completed");
+
+SET @old_debug_master= @@global.debug;
+--let $binlog_alter_two_phase= `select @@binlog_alter_two_phase`
+set binlog_alter_two_phase=true;
+create table t3( a int primary key, b int) engine=innodb;
+
+--connection master
+--sync_slave_with_master
+--source include/stop_slave.inc
+
+
+--connection master
+--exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
+SET SESSION debug_dbug="d,start_alter_kill_after_binlog";
+--error 2013
+alter table t3 add column d int;
+
+--let $rpl_server_number= 1
+--source include/rpl_reconnect.inc
+set binlog_alter_two_phase= true;
+alter table t3 add column d int;
+show create table t3;
+--source include/show_binlog_events.inc
+--let $binlog_file=master-bin.000002
+--source include/show_binlog_events.inc
+--let $binlog_file=
+
+--connection slave
+--source include/start_slave.inc
+
+--connection master
+--sync_slave_with_master
+--source include/show_binlog_events.inc
+show create table t3;
+
+
+--connection master
+SET GLOBAL debug_dbug= @old_debug_master;
+drop table t3;
+--eval set global binlog_alter_two_phase = $binlog_alter_two_phase
+
+--sync_slave_with_master
+SET GLOBAL debug_dbug= @old_debug_slave;
+stop slave;
+--eval set global slave_parallel_threads = $slave_parallel_threads;
+--eval set global slave_parallel_mode = $slave_parallel_mode;
+--eval set global gtid_strict_mode = $gtid_strict_mode;
+start slave;
+--connection master
+let MYSQLD_DATADIR= `select @@datadir;`;
+--remove_files_wildcard $MYSQLD_DATADIR/test #sql*.frm
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_start_alter_restart_slave.test b/mysql-test/suite/rpl/t/rpl_start_alter_restart_slave.test
new file mode 100644
index 00000000..df028ff1
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_start_alter_restart_slave.test
@@ -0,0 +1,121 @@
+# This test will restart the slave in middle of start alter commit alter processing
+# slave will be restarted after start alter and before binlogging of commit alter,
+# Then we will recieved commit alter from the master.
+# Commit alter will act like standalone alter
+# =====> SA SA CA(Stop Slave before binlogging) CA
+#
+--source include/have_log_bin.inc
+--source include/have_innodb.inc
+--source include/master-slave.inc
+--source include/have_debug.inc
+
+--connection slave
+SET @old_debug_slave= @@global.debug;
+--source include/stop_slave.inc
+--let $gtid_strict_mode= `select @@gtid_strict_mode`
+--let $slave_parallel_threads= `select @@slave_parallel_threads`
+--let $slave_parallel_mode= `select @@slave_parallel_mode`
+SET GLOBAL slave_parallel_threads=4;
+set global slave_parallel_mode=optimistic;
+set global gtid_strict_mode=1;
+
+set global debug_dbug="+d,rpl_slave_stop_CA_before_binlog";
+
+--source include/start_slave.inc
+#
+# SLAVE Shutdown
+--connection master
+SET @old_debug_master= @@global.debug;
+set global debug_dbug="+d,start_alter_delay_master";
+--let $binlog_alter_two_phase= `select @@binlog_alter_two_phase`
+set global binlog_alter_two_phase=true;
+create table t1( a int primary key, b int) engine=myisam;
+create table t2( a int primary key, b int) engine=myisam;
+
+--connect (con1,localhost,root,,)
+--send alter table t1 add column c int;
+
+--connection master
+--echo # Get into binlog first and wait
+--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE = 'debug sync point: now';
+--source include/wait_condition.inc
+--let $master_gtid_state = `select @@gtid_binlog_state`
+--echo # master gtid state is $master_gtid_state
+
+--connect (con2,localhost,root,,)
+--send alter table t2 add column c int;
+
+--connection master
+--echo # Get into binlog next and wait as well
+--let $wait_condition = SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE = 'debug sync point: now';
+--source include/wait_condition.inc
+--let $master_gtid_state = `select @@gtid_binlog_state`
+--echo # master gtid state is $master_gtid_state
+
+# Memorize for slave's next sync with master
+--let $master_pos=$master_gtid_state
+
+set DEBUG_SYNC= "now signal alter_cont";
+
+--connection con1
+--reap
+--connection con2
+--reap
+create table t3( a int primary key, b int) engine=innodb;
+--let $master_gtid_state = `select @@gtid_binlog_state`
+--echo # master gtid state is $master_gtid_state
+--let $replace_regexp=/alter table t[12]/alter table <t>/ /id=[0-9]+/id=<seq_no>/
+--source include/show_binlog_events2.inc
+
+--echo # Stop Slave
+--echo # As master binlog is SA SA CA CA
+--echo # let's stop at first CA processing (in process_commit_alter)
+
+--connection slave
+--source include/sync_with_master_gtid.inc
+# set debug_sync="now wait_for CA_1_processing";
+connect(extra_slave,127.0.0.1,root,,test,$SLAVE_MYPORT);
+--send stop slave;
+--connection slave
+# set debug_sync="now signal proceed_CA_1";
+--connection extra_slave
+--reap
+SET GLOBAL debug_dbug= @old_debug_slave;
+
+--connection slave
+--source include/wait_for_slave_sql_to_stop.inc
+--echo # The list of events after the slave has stopped must have just one CA:
+--let $replace_regexp=/alter table t[12]/alter table <t>/ /id=[0-9]+/id=<seq_no>/
+--source include/show_binlog_events2.inc
+
+select domain_id, seq_no from mysql.gtid_slave_pos order by seq_no desc limit 1;
+--source include/start_slave.inc
+--connection master
+--sync_slave_with_master
+--echo # Everything from the master binlog must have been applied now:
+select domain_id, seq_no from mysql.gtid_slave_pos order by seq_no desc limit 1;
+--let $slave_gtid_state = `select @@gtid_binlog_state`
+--echo # slave gtid state is $slave_gtid_state
+if (`select $master_gtid_state <> $slave_gtid_state`)
+{
+ --echo Gtid state mismatch: $master_gtid_state <> $slave_gtid_state
+ --die
+}
+--echo # The list of events after the slave has synchronized must have both CA:
+--let $replace_regexp=/alter table t[12]/alter table <t>/ /id=[0-9]+/id=<seq_no>/
+--source include/show_binlog_events2.inc
+
+--connection master
+drop table t1,t2,t3;
+--eval set global binlog_alter_two_phase = $binlog_alter_two_phase
+SET GLOBAL debug_dbug= @old_debug_master;
+set DEBUG_SYNC= 'RESET';
+
+--sync_slave_with_master
+stop slave;
+--eval set global slave_parallel_threads = $slave_parallel_threads;
+--eval set global slave_parallel_mode = $slave_parallel_mode;
+--eval set global gtid_strict_mode = $gtid_strict_mode;
+set DEBUG_SYNC= 'RESET';
+start slave;
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_start_stop_slave-slave.opt b/mysql-test/suite/rpl/t/rpl_start_stop_slave-slave.opt
new file mode 100644
index 00000000..c7cdc20f
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_start_stop_slave-slave.opt
@@ -0,0 +1 @@
+--loose-innodb-lock-wait-timeout=60
diff --git a/mysql-test/suite/rpl/t/rpl_start_stop_slave.test b/mysql-test/suite/rpl/t/rpl_start_stop_slave.test
new file mode 100644
index 00000000..23b25b1b
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_start_stop_slave.test
@@ -0,0 +1,65 @@
+#
+#BUG#11752315 : STOP SLAVE UNABLE TO COMPLETE WHEN SLAVE THREAD IS TRYING
+# TO RECONNECT TO
+#
+# ==== Purpose ====
+#
+#Tests that the slave does not go to a sleep for a long duration after the
+#master is killed and we do a START_SLAVE and STOP_SLAVE.
+#
+# ==== Method ====
+#
+#This is a new functionality of having an interruptable sleep of the slave.
+#We find the thread id for the slave thread. On finding the thread ID of the
+#slave thread we kill the slave thread. A successful kill in less than 60 sec
+#should serve the purpose of checking the functionality.
+#
+
+--source include/have_log_bin.inc
+--source include/master-slave.inc
+
+connection slave;
+--let $connection_id=`SELECT id FROM information_schema.processlist where state LIKE 'Waiting for master to send event'`
+
+if(!$connection_id)
+{
+ # Something went wrong (timing)
+ # Show process list so that we can debug. In this case we will abort with
+ # wrong result
+ -- echo "Could not find connect id. Dumping process list for debugging"
+ SELECT * FROM information_schema.processlist;
+ exit;
+}
+
+set @time_before_kill := (select CURRENT_TIMESTAMP);
+
+--echo [Time before the query]
+--echo [Connection ID of the slave I/O thread found]
+
+--replace_regex /kill [0-9]*/kill <connection_id>/
+--eval kill $connection_id
+--source include/wait_for_slave_io_to_stop.inc
+
+set @time_after_kill := (select CURRENT_TIMESTAMP);
+
+--echo [Time after the query]
+
+if(`select TIMESTAMPDIFF(SECOND,@time_after_kill, @time_before_kill) > 60`)
+{
+--echo # assert : The difference between the timestamps 'time_after_kill' and 'time_before_kill' should be less than 60sec.
+--die
+}
+--echo [Killing of the slave IO thread was successful]
+
+START SLAVE IO_THREAD;
+--source include/wait_for_slave_io_to_start.inc
+
+# Ensure that the slave io thread started properly
+connection master;
+create table t1 (a int primary key);
+sync_slave_with_master;
+connection master;
+drop table t1;
+
+# End of test
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_stm_000001.test b/mysql-test/suite/rpl/t/rpl_stm_000001.test
new file mode 100644
index 00000000..3851e618
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_stm_000001.test
@@ -0,0 +1,118 @@
+# Requires binlog_format=statement format since query involving
+# get_lock() is logged in row format if binlog_format=mixed or row.
+-- source include/have_binlog_format_statement.inc
+-- source include/master-slave.inc
+
+CALL mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT");
+
+# Load some data into t1
+create table t1 (word char(20) not null);
+load data infile '../../std_data/words.dat' into table t1;
+--replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR
+eval load data local infile '$MYSQL_TEST_DIR/std_data/words.dat' into table t1;
+select * from t1 limit 10;
+
+#
+# Test slave with wrong password
+#
+sync_slave_with_master;
+stop slave;
+connection master;
+create temporary table tmp select * from mysql.global_priv where host="localhost" and user="root";
+set password for root@"localhost" = password('foo');
+connection slave;
+start slave;
+connection master;
+#
+# Give slave time to do at last one failed connect retry
+# This one must be short so that the slave will not stop retrying
+real_sleep 2;
+replace into mysql.global_priv select * from tmp;
+drop temporary table tmp;
+flush privileges;
+# Give slave time to connect (will retry every second)
+sleep 2;
+
+create table t3(n int);
+insert into t3 values(1),(2);
+sync_slave_with_master;
+select * from t3;
+select sum(length(word)) from t1;
+connection master;
+drop table t1,t3;
+sync_slave_with_master;
+
+# Test if the slave SQL thread can be more than 16K behind the slave
+# I/O thread (> IO_SIZE)
+
+connection master;
+# we'll use table-level locking to delay slave SQL thread
+eval create table t1 (n int);
+sync_slave_with_master;
+connection master;
+reset master;
+connection slave;
+stop slave;
+--source include/reset_slave.inc
+
+connection master;
+let $1=5000;
+# Generate 16K of relay log
+disable_query_log;
+while ($1)
+{
+ eval insert into t1 values($1);
+ dec $1;
+}
+enable_query_log;
+
+# Try to cause a large relay log lag on the slave by locking t1
+connection slave;
+lock tables t1 read;
+start slave;
+connection master;
+--source include/sync_slave_io_with_master.inc
+unlock tables;
+
+#test handling of aborted connection in the middle of update
+
+connection master;
+create table t2(id int);
+insert into t2 values(connection_id());
+
+connection master1;
+# Avoid generating result
+create temporary table t3(n int);
+--disable_warnings
+insert into t3 select get_lock('crash_lock%20C', 1) from t2;
+--enable_warnings
+
+connection master;
+send update t1 set n = n + get_lock('crash_lock%20C', 2);
+connection master1;
+let $wait_condition= SELECT count(*) > 0 FROM information_schema.processlist WHERE info LIKE 'update%' AND state='User lock';
+source include/wait_condition.inc;
+select (@id := id) - id from t2;
+kill @id;
+drop table t2;
+drop temporary table t3;
+connection master;
+# The get_lock function causes warning for unsafe statement.
+--disable_warnings
+# 2013 = CR_SERVER_LOST
+--error ER_QUERY_INTERRUPTED,ER_CONNECTION_KILLED,2013
+reap;
+--enable_warnings
+connection slave;
+# The SQL slave thread should now have stopped because the query was killed on
+# the master (so it has a non-zero error code in the binlog).
+# 1927 = ER_CONNECTION_KILLED
+--let $slave_sql_errno= 1927
+--source include/wait_for_slave_sql_error_and_skip.inc
+
+select count(*) from t1;
+connection master1;
+drop table t1;
+
+# End of 4.1 tests
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_stm_EE_err2.test b/mysql-test/suite/rpl/t/rpl_stm_EE_err2.test
new file mode 100644
index 00000000..07b1000c
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_stm_EE_err2.test
@@ -0,0 +1,8 @@
+#############################
+# Author: JBM
+# Date: 2006-01-11
+# Purpose: Engine Wrapper for rpl_stm_EE_err2.test
+##############################
+-- source include/have_binlog_format_mixed_or_statement.inc
+let $engine_type=myisam;
+-- source include/rpl_stm_EE_err2.test
diff --git a/mysql-test/suite/rpl/t/rpl_stm_auto_increment_bug33029.test b/mysql-test/suite/rpl/t/rpl_stm_auto_increment_bug33029.test
new file mode 100644
index 00000000..280cfcc5
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_stm_auto_increment_bug33029.test
@@ -0,0 +1,106 @@
+# BUG#33029 5.0 to 5.1 replication fails on dup key when inserting
+# using a trig in SP
+
+# For all 5.0 up to 5.0.58 exclusive, and 5.1 up to 5.1.12 exclusive,
+# if one statement in a SP generated AUTO_INCREMENT value by the top
+# statement, all statements after it would be considered generated
+# AUTO_INCREMENT value by the top statement, and a erroneous INSERT_ID
+# value might be associated with these statement, which could cause
+# duplicate entry error and stop the slave.
+
+source include/have_binlog_format_statement.inc;
+source include/master-slave.inc;
+
+CALL mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT");
+--connection slave
+CALL mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT");
+--connection master
+
+CREATE TABLE t1 (id INT AUTO_INCREMENT PRIMARY KEY);
+CREATE TABLE t2 (id INT AUTO_INCREMENT PRIMARY KEY);
+
+delimiter //;
+
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE ins_count INT DEFAULT 10;
+
+ WHILE ins_count > 0 DO
+ INSERT INTO t1 VALUES (NULL);
+ SET ins_count = ins_count - 1;
+ END WHILE;
+
+ DELETE FROM t1 WHERE id = 1;
+ DELETE FROM t1 WHERE id = 2;
+ DELETE FROM t2 WHERE id = 1;
+ DELETE FROM t2 WHERE id = 2;
+END//
+
+CREATE PROCEDURE p2()
+BEGIN
+ INSERT INTO t1 VALUES (NULL);
+ DELETE FROM t1 WHERE id = f1(3);
+ DELETE FROM t1 WHERE id = f1(4);
+ DELETE FROM t2 WHERE id = 3;
+ DELETE FROM t2 WHERE id = 4;
+END//
+
+CREATE TRIGGER tr1 BEFORE DELETE
+ ON t1 FOR EACH ROW
+ BEGIN
+ INSERT INTO t2 VALUES (NULL);
+ END//
+
+CREATE FUNCTION f1 (i int) RETURNS int
+ BEGIN
+ INSERT INTO t2 VALUES (NULL);
+ RETURN i;
+ END//
+
+delimiter ;//
+
+# the $binlog_start will be used by the show_binlog_events.inc, so
+# that we can skip binlog events we don't care
+let $binlog_start= query_get_value(SHOW MASTER STATUS, Position, 1);
+CALL p1();
+source include/show_binlog_events.inc;
+
+echo # Result on master;
+SELECT * FROM t1;
+SELECT * FROM t2;
+
+sync_slave_with_master;
+
+SELECT * FROM t1;
+SELECT * FROM t2;
+
+connection master;
+
+DROP TRIGGER tr1;
+
+# the $binlog_start will be used by the show_binlog_events.inc, so
+# that we can skip binlog events we don't care
+let $binlog_start= query_get_value(SHOW MASTER STATUS, Position, 1);
+CALL p2();
+source include/show_binlog_events.inc;
+
+echo # Result on master;
+SELECT * FROM t1;
+SELECT * FROM t2;
+
+sync_slave_with_master;
+
+SELECT * FROM t1;
+SELECT * FROM t2;
+
+# clean up
+connection master;
+disable_warnings;
+DROP TABLE IF EXISTS t1, t2;
+DROP PROCEDURE IF EXISTS p1;
+DROP PROCEDURE IF EXISTS p2;
+DROP FUNCTION IF EXISTS f1;
+DROP TRIGGER IF EXISTS tr1;
+enable_warnings;
+sync_slave_with_master;
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_stm_binlog_direct-master.opt b/mysql-test/suite/rpl/t/rpl_stm_binlog_direct-master.opt
new file mode 100644
index 00000000..561902d0
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_stm_binlog_direct-master.opt
@@ -0,0 +1 @@
+--binlog-direct-non-transactional-updates
diff --git a/mysql-test/suite/rpl/t/rpl_stm_binlog_max_cache_size.test b/mysql-test/suite/rpl/t/rpl_stm_binlog_max_cache_size.test
new file mode 100644
index 00000000..f893f909
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_stm_binlog_max_cache_size.test
@@ -0,0 +1,8 @@
+--source include/have_innodb.inc
+--source include/not_embedded.inc
+--source include/not_windows.inc
+--source include/have_binlog_format_statement.inc
+--source include/master-slave.inc
+
+--source include/rpl_binlog_max_cache_size.test
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_stm_conflicts.test b/mysql-test/suite/rpl/t/rpl_stm_conflicts.test
new file mode 100644
index 00000000..a4f59253
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_stm_conflicts.test
@@ -0,0 +1,6 @@
+source include/have_binlog_format_mixed_or_statement.inc;
+source include/master-slave.inc;
+
+source include/rpl_conflicts.test;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_stm_drop_create_temp_table.test b/mysql-test/suite/rpl/t/rpl_stm_drop_create_temp_table.test
new file mode 100644
index 00000000..b971af71
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_stm_drop_create_temp_table.test
@@ -0,0 +1,12 @@
+###################################################################################
+# This test cases evaluates the mixture of non-transactional and transcational
+# tables. Specifically when drop temporary tables and create temporary tables
+# are used.
+###################################################################################
+--source include/big_test.inc
+--source include/have_binlog_format_statement.inc
+--source include/have_innodb.inc
+--source include/master-slave.inc
+
+--source include/rpl_drop_create_temp_table.test
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_stm_flsh_tbls.test b/mysql-test/suite/rpl/t/rpl_stm_flsh_tbls.test
new file mode 100644
index 00000000..70178c2e
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_stm_flsh_tbls.test
@@ -0,0 +1,6 @@
+# depends on the binlog output
+--source include/have_binlog_format_mixed_or_statement.inc
+--source include/binlog_start_pos.inc
+
+let $rename_event_pos= `select @binlog_start_pos + 578`;
+-- source include/rpl_flsh_tbls.test
diff --git a/mysql-test/suite/rpl/t/rpl_stm_found_rows.test b/mysql-test/suite/rpl/t/rpl_stm_found_rows.test
new file mode 100644
index 00000000..c1b7e023
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_stm_found_rows.test
@@ -0,0 +1,124 @@
+source include/have_binlog_format_statement.inc;
+source include/master-slave.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;
+
+# It is not possible to replicate FOUND_ROWS() using statement-based
+# replication, but there is a workaround that stores the result of
+# FOUND_ROWS() into a user variable and then replicates this instead.
+#
+# The purpose of this test case is to test that the workaround works
+# properly even when inside stored programs (i.e., stored routines and
+# triggers).
+
+--echo ==== Initialize ====
+
+connection master;
+CREATE TABLE t1 (a INT);
+CREATE TABLE logtbl (sect INT, test INT, count INT);
+
+INSERT INTO t1 VALUES (1),(2),(3);
+INSERT INTO t1 SELECT 2*a+3 FROM t1;
+INSERT INTO t1 SELECT 2*a+3 FROM t1;
+INSERT INTO t1 SELECT 2*a+3 FROM t1;
+INSERT INTO t1 SELECT 2*a+3 FROM t1;
+INSERT INTO t1 SELECT 2*a+3 FROM t1;
+INSERT INTO t1 SELECT 2*a+3 FROM t1;
+
+
+--echo ==== Simple test ====
+
+SELECT SQL_CALC_FOUND_ROWS * FROM t1 WHERE a > 5 ORDER BY a LIMIT 1;
+
+# Instead of
+# INSERT INTO logtbl VALUES(1, 1, FOUND_ROWS());
+# we write
+--disable_ps2_protocol
+SELECT FOUND_ROWS() INTO @a;
+--enable_ps2_protocol
+INSERT INTO logtbl VALUES(1,1,@a);
+
+SELECT SQL_CALC_FOUND_ROWS * FROM t1 WHERE a < 5 ORDER BY a LIMIT 1;
+# Instead of
+# INSERT INTO logtbl VALUES(1, 2, FOUND_ROWS());
+# we write
+--disable_ps2_protocol
+SELECT FOUND_ROWS() INTO @a;
+--enable_ps2_protocol
+INSERT INTO logtbl VALUES(1,2,@a);
+
+SELECT * FROM logtbl WHERE sect = 1 ORDER BY sect,test;
+sync_slave_with_master;
+SELECT * FROM logtbl WHERE sect = 1 ORDER BY sect,test;
+
+
+--echo ==== Stored procedure ====
+
+# Here we do both the calculation and the logging. We also do it twice
+# to make sure that there are no limitations on how many times it can
+# be used.
+
+connection master;
+--delimiter $$
+CREATE PROCEDURE calc_and_log(sect INT, test INT) BEGIN
+ DECLARE cnt INT;
+ SELECT SQL_CALC_FOUND_ROWS * FROM t1 WHERE a < 5 ORDER BY a LIMIT 1;
+ SELECT FOUND_ROWS() INTO cnt;
+ INSERT INTO logtbl VALUES(sect,test,cnt);
+ SELECT SQL_CALC_FOUND_ROWS * FROM t1 WHERE a > 5 ORDER BY a LIMIT 1;
+ SELECT FOUND_ROWS() INTO cnt;
+ INSERT INTO logtbl VALUES(sect,test+1,cnt);
+END $$
+--delimiter ;
+
+CALL calc_and_log(2,1);
+
+--delimiter $$
+CREATE PROCEDURE just_log(sect INT, test INT, found_rows INT) BEGIN
+ INSERT INTO logtbl VALUES (sect,test,found_rows);
+END $$
+--delimiter ;
+
+SELECT SQL_CALC_FOUND_ROWS * FROM t1 WHERE a > 5 ORDER BY a LIMIT 1;
+--disable_ps2_protocol
+SELECT FOUND_ROWS() INTO @found_rows;
+--enable_ps2_protocol
+CALL just_log(2,3,@found_rows);
+
+SELECT * FROM logtbl WHERE sect = 2 ORDER BY sect,test;
+sync_slave_with_master;
+SELECT * FROM logtbl WHERE sect = 2 ORDER BY sect,test;
+
+
+--echo ==== Stored functions ====
+connection master;
+--delimiter $$
+CREATE FUNCTION log_rows(sect INT, test INT, found_rows INT)
+ RETURNS INT
+BEGIN
+ INSERT INTO logtbl VALUES(sect,test,found_rows);
+ RETURN found_rows;
+END $$
+--delimiter ;
+
+SELECT SQL_CALC_FOUND_ROWS * FROM t1 WHERE a > 5 ORDER BY a LIMIT 1;
+--disable_ps2_protocol
+SELECT FOUND_ROWS() INTO @found_rows;
+SELECT log_rows(3,1,@found_rows), log_rows(3,2,@found_rows);
+--enable_ps2_protocol
+
+SELECT * FROM logtbl WHERE sect = 3 ORDER BY sect,test;
+sync_slave_with_master;
+SELECT * FROM logtbl WHERE sect = 3 ORDER BY sect,test;
+
+
+--echo ==== Cleanup ====
+connection master;
+DROP TABLE t1, logtbl;
+DROP PROCEDURE just_log;
+DROP PROCEDURE calc_and_log;
+DROP FUNCTION log_rows;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_stm_implicit_commit_binlog.test b/mysql-test/suite/rpl/t/rpl_stm_implicit_commit_binlog.test
new file mode 100644
index 00000000..6b127182
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_stm_implicit_commit_binlog.test
@@ -0,0 +1,12 @@
+################################################################################
+# Check file include/rpl_implicit_commit_binlog.test
+################################################################################
+--source include/have_udf.inc
+--source include/have_binlog_format_statement.inc
+--source include/have_innodb.inc
+--source include/master-slave.inc
+
+--let $engine=Innodb
+set session default_storage_engine=innodb;
+--source include/rpl_implicit_commit_binlog.test
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_stm_innodb.test b/mysql-test/suite/rpl/t/rpl_stm_innodb.test
new file mode 100644
index 00000000..dbfbc7f6
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_stm_innodb.test
@@ -0,0 +1,9 @@
+# File for specialities regarding replication from or to InnoDB
+# tables.
+
+source include/have_innodb.inc;
+source include/have_binlog_format_mixed_or_statement.inc;
+source include/master-slave.inc;
+
+source include/rpl_innodb.test;
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_stm_lcase_tblnames-slave.opt b/mysql-test/suite/rpl/t/rpl_stm_lcase_tblnames-slave.opt
new file mode 100644
index 00000000..8be29bbe
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_stm_lcase_tblnames-slave.opt
@@ -0,0 +1 @@
+--replicate-do-db=bug_37656 --replicate-ignore-table=bug_37656.t1 --replicate-do-table=bug_37656.t2 --replicate-do-table=bug_37656.t3 --lower-case-table-names=1
diff --git a/mysql-test/suite/rpl/t/rpl_stm_lcase_tblnames.test b/mysql-test/suite/rpl/t/rpl_stm_lcase_tblnames.test
new file mode 100644
index 00000000..3809cd89
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_stm_lcase_tblnames.test
@@ -0,0 +1,12 @@
+# BUG#37656
+#
+# For details look into extra/rpl_tests/rpl_lower_case_table_names.test
+#
+
+-- source include/not_windows.inc
+-- source include/have_innodb.inc
+-- source include/have_binlog_format_mixed_or_statement.inc
+-- source include/master-slave.inc
+
+-- let $engine=InnoDB
+-- source include/rpl_lower_case_table_names.test
diff --git a/mysql-test/suite/rpl/t/rpl_stm_loaddata_concurrent.test b/mysql-test/suite/rpl/t/rpl_stm_loaddata_concurrent.test
new file mode 100644
index 00000000..4409a1a8
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_stm_loaddata_concurrent.test
@@ -0,0 +1,14 @@
+-- source include/have_log_bin.inc
+-- source include/have_binlog_format_statement.inc
+RESET MASTER;
+
+let $binlog_start= query_get_value(SHOW MASTER STATUS, Position, 1);
+CREATE TABLE t1 (c1 char(50)) ENGINE=MyISAM;
+LOAD DATA INFILE '../../std_data/words.dat' INTO TABLE t1;
+LOAD DATA CONCURRENT INFILE '../../std_data/words.dat' INTO TABLE t1;
+-- source include/show_binlog_events.inc
+DROP TABLE t1;
+
+let $lock_option= CONCURRENT;
+let $engine_type=MyISAM;
+-- source include/rpl_loaddata.test
diff --git a/mysql-test/suite/rpl/t/rpl_stm_loadfile.test b/mysql-test/suite/rpl/t/rpl_stm_loadfile.test
new file mode 100644
index 00000000..5ff3846d
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_stm_loadfile.test
@@ -0,0 +1,24 @@
+#############################################################################
+# Original Author: JBM #
+# Original Date: Aug/18/2005 #
+#############################################################################
+# TEST: To test the LOAD_FILE() in rbr #
+#############################################################################
+# Change Author: JBM
+# Change Date: 2006-01-16
+# Change: Split the original test file. This one forces STATEMENT only because
+# when in STATEMENT mode, the load_file will issue a warning, whereas
+# in RBR or MIXED mode it does not (by lsoares).
+##########
+
+# Includes
+-- source include/have_binlog_format_statement.inc
+-- source include/master-slave.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;
+
+-- source include/rpl_loadfile.test
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_stm_log-slave.opt b/mysql-test/suite/rpl/t/rpl_stm_log-slave.opt
new file mode 100644
index 00000000..203fc228
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_stm_log-slave.opt
@@ -0,0 +1 @@
+--log-slave-updates
diff --git a/mysql-test/suite/rpl/t/rpl_stm_log.test b/mysql-test/suite/rpl/t/rpl_stm_log.test
new file mode 100644
index 00000000..4a0df442
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_stm_log.test
@@ -0,0 +1,8 @@
+# Requires statement logging
+-- source include/have_binlog_format_statement.inc
+-- source include/master-slave.inc
+let $engine_type=MyISAM;
+-- source include/rpl_log.test
+
+# End of 4.1 tests
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_stm_maria.test b/mysql-test/suite/rpl/t/rpl_stm_maria.test
new file mode 100644
index 00000000..d5a4c5c3
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_stm_maria.test
@@ -0,0 +1,59 @@
+# Test of Maria-specific replication bugs
+
+--source include/have_maria.inc
+--source include/have_binlog_format_mixed_or_statement.inc
+--source include/master-slave.inc
+
+# Suppress warnings that rand() is unsafe in statement binlog mode
+CALL mtr.add_suppression('Unsafe statement written to the binary log using statement format');
+
+--disable_warnings
+DROP TABLE IF EXISTS t1;
+DROP TABLE IF EXISTS t2;
+DROP TABLE IF EXISTS t3;
+--enable_warnings
+
+# This one taken from rpl_trigger.test (from BUG#12482)
+# used to segfault slave in execution of row-based events
+
+# Need an explicit ENGINE= clause as @@STORAGE_ENGINE is not replicated
+create table t1 (a int auto_increment, primary key (a), b int,
+rand_value double not null) engine=maria;
+create table t2 (a int auto_increment, primary key (a), b int) engine=maria;
+create table t3 (a int auto_increment, primary key (a), name
+varchar(64) not null, old_a int, old_b int, rand_value double not
+null) engine=maria;
+
+delimiter |;
+create trigger t1 before insert on t1 for each row
+begin
+ insert into t3 values (NULL, "t1", new.a, new.b, rand());
+end|
+
+create trigger t2 after insert on t2 for each row
+begin
+ insert into t3 values (NULL, "t2", new.a, new.b, rand());
+end|
+delimiter ;|
+
+insert into t3 values(100,"log",0,0,0);
+
+SET @@RAND_SEED1=658490765, @@RAND_SEED2=635893186;
+
+--disable_warnings
+insert into t1 values(1,1,rand()),(NULL,2,rand());
+insert into t2 (b) values(last_insert_id());
+insert into t2 values(3,0),(NULL,0);
+insert into t2 values(NULL,0),(500,0);
+--enable_warnings
+
+select a,b, truncate(rand_value,4) from t1;
+select * from t2;
+select a,name, old_a, old_b, truncate(rand_value,4) from t3;
+sync_slave_with_master;
+connection master;
+drop table t1,t2,t3;
+sync_slave_with_master;
+
+# End of tests
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_stm_max_relay_size.test b/mysql-test/suite/rpl/t/rpl_stm_max_relay_size.test
new file mode 100644
index 00000000..bea51ed2
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_stm_max_relay_size.test
@@ -0,0 +1,8 @@
+# Test of options max_binlog_size and max_relay_log_size and
+# how they act (if max_relay_log_size == 0, use max_binlog_size
+# for relay logs too).
+# Test of manual relay log rotation with FLUSH LOGS.
+
+# Requires statement logging
+-- source include/have_binlog_format_mixed_or_statement.inc
+-- source include/rpl_max_relay_size.test
diff --git a/mysql-test/suite/rpl/t/rpl_stm_mix_show_relaylog_events.test b/mysql-test/suite/rpl/t/rpl_stm_mix_show_relaylog_events.test
new file mode 100644
index 00000000..ab823799
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_stm_mix_show_relaylog_events.test
@@ -0,0 +1,19 @@
+# BUG#28777 SHOW BINLOG EVENTS does not work on relay log files
+#
+# GOAL
+# ====
+#
+# Test that SHOW BINLOG EVENTS and the new SHOW RELAYLOG EVENTS works after
+# the patch, both on master and slave.
+#
+# HOW
+# ===
+#
+# This test issues SHOW [BINLOG|RELAYLOG] EVENTS both on master and slave after
+# some statements have been issued.
+
+-- source include/have_binlog_format_mixed_or_statement.inc
+-- source include/master-slave.inc
+
+-- source include/rpl_show_relaylog_events.inc
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_stm_mixing_engines.test b/mysql-test/suite/rpl/t/rpl_stm_mixing_engines.test
new file mode 100644
index 00000000..e8b52885
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_stm_mixing_engines.test
@@ -0,0 +1,50 @@
+###################################################################################
+# This test cases evaluates the mixture of non-transactional and transcational
+# tables. For further details, please, read WL#2687 and WL#5072.
+###################################################################################
+--source include/have_binlog_format_statement.inc
+--source include/have_innodb.inc
+# MDEV-31790 FIXME: This test is extremely slow
+--source include/not_msan.inc
+--source include/master-slave.inc
+
+let $engine_type=Innodb;
+let $database_name=test;
+--source include/rpl_mixing_engines.test
+
+#
+# BUG#49522: Replication problem with mixed MyISAM/InnoDB
+#
+
+--source include/rpl_reset.inc
+-- connection master
+
+CREATE TABLE `t1` (
+ `c1` int(10) unsigned NOT NULL AUTO_INCREMENT,
+ `c2` tinyint(1) unsigned DEFAULT NULL,
+ `c3` varchar(300) DEFAULT NULL,
+ `c4` int(10) unsigned NOT NULL,
+ `c5` int(10) unsigned DEFAULT NULL,
+ PRIMARY KEY (`c1`)) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+
+-- sync_slave_with_master
+ALTER TABLE `t1` Engine=InnoDB;
+
+-- connection master
+SET AUTOCOMMIT=0;
+
+INSERT INTO t1 (c1,c2,c3,c4,c5) VALUES (1, 1, 'X', 1, NULL);
+COMMIT;
+ROLLBACK;
+SET AUTOCOMMIT=1;
+
+-- sync_slave_with_master
+
+-- let $diff_tables= master:t1, slave:t1
+-- source include/diff_tables.inc
+
+-- connection master
+DROP TABLE `t1`;
+-- sync_slave_with_master
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_stm_multi_query.test b/mysql-test/suite/rpl/t/rpl_stm_multi_query.test
new file mode 100644
index 00000000..2a593efd
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_stm_multi_query.test
@@ -0,0 +1,7 @@
+# Test for BUG#8436: verify that a multi-query (i.e. one query
+# containing several queries (assuming client has
+# CLIENT_MULTI_STATEMENTS) will be binlogged ONE-query-per-event (not
+# one binlog event containing all queries)
+
+-- source include/have_binlog_format_mixed_or_statement.inc
+-- source include/rpl_multi_query.test
diff --git a/mysql-test/suite/rpl/t/rpl_stm_no_op.test b/mysql-test/suite/rpl/t/rpl_stm_no_op.test
new file mode 100644
index 00000000..1605b177
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_stm_no_op.test
@@ -0,0 +1,94 @@
+# It's true only in statement-based replication that a statement which
+# updates no rows (UPDATE/DELETE) is binlogged; in row-based
+# replication, as we log modified rows, nothing is binlogged in this
+# case. So this test is meaningul only in statement-based (and if it was
+# enabled in row-based, it would fail as expected).
+
+-- source include/have_binlog_format_mixed_or_statement.inc
+
+source include/master-slave.inc;
+
+# see if DROP DATABASE is binlogged even if no effect
+connection slave;
+create database mysqltest;
+connection master;
+drop database if exists mysqltest;
+sync_slave_with_master;
+# can't read dir
+--replace_result "Errcode: 1" "Errcode: X" "Errcode: 2" "Errcode: X" \\ /
+--error 1049
+show tables from mysqltest;
+
+# see if DROP TABLE is binlogged even if no effect
+connection slave;
+create table t1 (a int);
+connection master;
+drop table if exists t1;
+sync_slave_with_master;
+# table does not exist
+--error 1146
+select * from t1;
+
+# see if single-table DELETE is binlogged even if no effect
+connection master;
+create table t1 (a int, b int);
+sync_slave_with_master;
+insert into t1 values(1,1);
+connection master;
+delete from t1;
+sync_slave_with_master;
+select * from t1;
+
+# see if single-table UPDATE is binlogged even if no effect
+insert into t1 values(1,1);
+connection master;
+insert into t1 values(2,1);
+update t1 set a=2;
+sync_slave_with_master;
+select * from t1;
+
+# End of 4.1 tests
+
+# see if multi-table UPDATE is binlogged even if no effect (BUG#13348)
+
+connection master;
+create table t2 (a int, b int);
+delete from t1;
+insert into t1 values(1,1);
+insert into t2 values(1,1);
+
+sync_slave_with_master;
+# force a difference to see if master's multi-UPDATE will correct it
+update t1 set a=2;
+
+connection master;
+UPDATE t1, t2 SET t1.a = t2.a;
+
+sync_slave_with_master;
+select * from t1;
+select * from t2;
+
+# See if multi-table DELETE is binlogged even if no effect
+
+connection master;
+delete from t1;
+delete from t2;
+
+sync_slave_with_master;
+# force a difference to see if master's multi-DELETE will correct it
+insert into t1 values(1,1);
+insert into t2 values(1,1);
+
+connection master;
+DELETE t1.*, t2.* from t1, t2;
+
+sync_slave_with_master;
+select * from t1;
+select * from t2;
+
+
+# cleanup
+connection master;
+drop table t1, t2;
+sync_slave_with_master;
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_stm_relay_ign_space-slave.opt b/mysql-test/suite/rpl/t/rpl_stm_relay_ign_space-slave.opt
new file mode 100644
index 00000000..f780540a
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_stm_relay_ign_space-slave.opt
@@ -0,0 +1 @@
+--relay-log-space-limit=8192 --relay-log-purge --max-relay-log-size=4096
diff --git a/mysql-test/suite/rpl/t/rpl_stm_relay_ign_space.test b/mysql-test/suite/rpl/t/rpl_stm_relay_ign_space.test
new file mode 100644
index 00000000..654a5d47
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_stm_relay_ign_space.test
@@ -0,0 +1,107 @@
+#
+# This include file is used by more than one test suite
+# (currently rpl and binlog_encryption).
+# Please check all dependent tests after modifying it
+#
+
+#
+# BUG#12400313 / BUG#64503 test case
+#
+#
+# Description
+# -----------
+#
+# This test case starts the slave server with:
+# --relay-log-space-limit=8192 --relay-log-purge --max-relay-log-size=4096
+#
+# Then it issues some queries that will cause the slave to reach
+# relay-log-space-limit. We lock the table so that the SQL thread is
+# not able to purge the log and then we issue some more statements.
+#
+# The purpose is to show that the IO thread will honor the limits
+# while the SQL thread is not able to purge the relay logs, which did
+# not happen before this patch. In addition we assert that while
+# ignoring the limit (SQL thread needs to rotate before purging), the
+# IO thread does not do it in an uncontrolled manner.
+
+--source include/have_binlog_format_statement.inc
+--source include/have_innodb.inc
+--source include/master-slave.inc
+
+--disable_query_log
+CREATE TABLE t1 (c1 TEXT) engine=InnoDB;
+
+INSERT INTO t1 VALUES ('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx');
+INSERT INTO t1 VALUES ('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx');
+INSERT INTO t1 VALUES ('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx');
+INSERT INTO t1 VALUES ('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx');
+
+--sync_slave_with_master
+
+# wait for the SQL thread to sleep
+--let $show_statement= SHOW PROCESSLIST
+--let $field= State
+--let $condition= = 'Slave has read all relay log; waiting for more updates'
+--source include/wait_show_condition.inc
+
+# now the io thread has set rli->ignore_space_limit
+# lets lock the table so that once the SQL thread awakes
+# it blocks there and does not set rli->ignore_space_limit
+# back to zero
+LOCK TABLE t1 WRITE;
+
+# now issue more statements that will overflow the
+# rli->log_space_limit (in this case ~10K)
+--connection master
+
+INSERT INTO t1 VALUES ('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx');
+INSERT INTO t1 VALUES ('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx');
+INSERT INTO t1 VALUES ('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx');
+INSERT INTO t1 VALUES ('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx');
+INSERT INTO t1 VALUES ('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx');
+INSERT INTO t1 VALUES ('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx');
+INSERT INTO t1 VALUES ('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx');
+INSERT INTO t1 VALUES ('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx');
+INSERT INTO t1 VALUES ('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx');
+INSERT INTO t1 VALUES ('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx');
+
+--connection slave
+
+# ASSERT that the IO thread waits for the SQL thread to release some
+# space before continuing
+--let $show_statement= SHOW PROCESSLIST
+--let $field= State
+--let $condition= LIKE 'Waiting for %'
+# before the patch (IO would have transfered everything)
+#--let $condition= = 'Waiting for master to send event'
+# after the patch (now it waits for space to be freed)
+#--let $condition= = 'Waiting for the slave SQL thread to free enough relay log space'
+--source include/wait_show_condition.inc
+
+# without the patch we can uncomment the following two lines and
+# watch the IO thread synchronize with the master, thus writing
+# relay logs way over the space limit
+#--connection master
+#--source include/sync_slave_io_with_master.inc
+
+## ASSERT that the IO thread has honored the limit+few bytes required to be able to purge
+--let $relay_log_space_while_sql_is_executing = query_get_value(SHOW SLAVE STATUS, Relay_Log_Space, 1)
+--let $relay_log_space_limit = query_get_value(SHOW VARIABLES LIKE "relay_log_space_limit", Value, 1)
+--let $assert_text= Assert that relay log space is close to the limit
+--let $assert_cond= $relay_log_space_while_sql_is_executing <= $relay_log_space_limit * 1.15
+--source include/assert.inc
+
+# unlock the table and let SQL thread continue applying events
+UNLOCK TABLES;
+
+--connection master
+--sync_slave_with_master
+--let $diff_tables=master:test.t1,slave:test.t1
+--source include/diff_tables.inc
+
+--connection master
+DROP TABLE t1;
+--enable_query_log
+--sync_slave_with_master
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_stm_reset_slave.test b/mysql-test/suite/rpl/t/rpl_stm_reset_slave.test
new file mode 100644
index 00000000..e32b0a78
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_stm_reset_slave.test
@@ -0,0 +1,6 @@
+# TBF - difference in row level logging
+-- source include/have_binlog_format_mixed_or_statement.inc
+-- source include/rpl_reset_slave.test
+
+# End of 4.1 tests
+#
diff --git a/mysql-test/suite/rpl/t/rpl_stm_sp.test b/mysql-test/suite/rpl/t/rpl_stm_sp.test
new file mode 100644
index 00000000..b99906b8
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_stm_sp.test
@@ -0,0 +1,30 @@
+--source include/have_binlog_format_statement.inc
+--source include/master-slave.inc
+
+--echo #
+--echo # MDEV-11815 SP variables of temporal data types do not replicate correctly
+--echo #
+
+connection master;
+CREATE TABLE t1(a INT);
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE a TIME DEFAULT '01:01:01';
+ INSERT INTO t1 VALUES (a=10101);
+END;
+$$
+DELIMITER ;$$
+CALL p1;
+SELECT * FROM t1;
+
+sync_slave_with_master;
+SELECT * FROM t1;
+
+connection master;
+DROP TABLE t1;
+DROP PROCEDURE p1;
+sync_slave_with_master;
+
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_stm_sql_mode.test b/mysql-test/suite/rpl/t/rpl_stm_sql_mode.test
new file mode 100644
index 00000000..56821621
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_stm_sql_mode.test
@@ -0,0 +1,25 @@
+-- source include/have_binlog_format_statement.inc
+-- source include/master-slave.inc
+
+#
+# Bug #51055 Replication failure on duplicate key + traditional SQL mode
+#
+
+CREATE TABLE t1 (pk integer auto_increment , primary key (pk));
+
+SET SESSION SQL_MODE='traditional';
+
+-- echo # **** [MASTER] *****
+-- echo # action: raise DUP KEY error (error code should be set in the
+-- echo # query log event)
+-- error ER_DUP_ENTRY
+INSERT INTO t1 (`pk`) VALUES (1), (1);
+
+DROP TABLE t1;
+
+-- echo # **** [ sync slave with master ] ****
+-- echo # assertion: sync slave with master makes slave not to stop with
+-- echo # duplicate key error (because it has received event
+-- echo # with expected error code).
+-- sync_slave_with_master
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_stm_start_stop_slave.test b/mysql-test/suite/rpl/t/rpl_stm_start_stop_slave.test
new file mode 100644
index 00000000..f401db33
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_stm_start_stop_slave.test
@@ -0,0 +1,26 @@
+################################################################################
+# Please, check ./include/rpl_start_stop_slave.test
+################################################################################
+--source include/have_binlog_format_statement.inc
+--source include/have_innodb.inc
+--source include/master-slave.inc
+
+# make innodb updates run fast
+--connection slave
+SET @old_innodb_flush_log_at_trx_commit= @@global.innodb_flush_log_at_trx_commit;
+SET @@global.innodb_flush_log_at_trx_commit= 0;
+--connection master
+SET @old_innodb_flush_log_at_trx_commit= @@global.innodb_flush_log_at_trx_commit;
+SET @@global.innodb_flush_log_at_trx_commit= 0;
+
+SET @@session.binlog_direct_non_transactional_updates= FALSE;
+--source ./include/rpl_start_stop_slave.test
+
+# clean up
+--connection slave
+SET @@global.innodb_flush_log_at_trx_commit= @old_innodb_flush_log_at_trx_commit;
+call mtr.add_suppression("Slave SQL.*Request to stop slave SQL Thread received while applying a group that has non-transactional changes; waiting for completion of the group");
+--connection master
+SET @@global.innodb_flush_log_at_trx_commit= @old_innodb_flush_log_at_trx_commit;
+--let $rpl_only_running_threads= 1
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_stm_stop_middle_group.test b/mysql-test/suite/rpl/t/rpl_stm_stop_middle_group.test
new file mode 100644
index 00000000..f2315f5e
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_stm_stop_middle_group.test
@@ -0,0 +1,11 @@
+###################################################################################
+# Please, check include/rpl_stop_middle_group.test.
+###################################################################################
+-- source include/have_debug.inc
+-- source include/have_innodb.inc
+-- source include/have_binlog_format_statement.inc
+-- source include/master-slave.inc
+
+SET @@session.binlog_direct_non_transactional_updates= FALSE;
+-- source include/rpl_stop_middle_group.test
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_stm_until.test b/mysql-test/suite/rpl/t/rpl_stm_until.test
new file mode 100644
index 00000000..ebfd355b
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_stm_until.test
@@ -0,0 +1,184 @@
+# ==== Purpose ====
+#
+# Verify that START SLAVE UNTIL replicates until the given binlog
+# position but not longer. Verify that START SLAVE UNTIL with various
+# incorrect arguments gives an error.
+#
+# ==== Method ====
+#
+# On master, create a table and insert some rows. On slave, START
+# SLAVE UNTIL so that it reads one event at a time, and check the
+# table and the slave status each time.
+#
+# Then, on slave, run START SLAVE UNTIL with incorrect arguments and
+# verify that it gives an error.
+#
+# ==== Related bugs ====
+#
+# Bug in this test: BUG#37717: rpl.rpl_stm_until 'stmt' fails sporadically on pushbuild
+
+-- source include/have_binlog_format_mixed_or_statement.inc
+-- source include/master-slave.inc
+--let $master_use_gtid_option= No
+-- source include/rpl_reset.inc
+
+# Test is dependent on binlog positions
+call mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT");
+
+# prepare version for substitutions
+let $VERSION=`select version()`;
+
+# Stop slave before it starts replication. Also sync with master
+# to avoid nondeterministic behaviour.
+sync_slave_with_master;
+--source include/stop_slave.inc
+
+--echo ==== Create some events on master ====
+
+connection master;
+create table t1(n int not null auto_increment primary key);
+insert into t1 values (1),(2),(3),(4);
+let $master_log_pos_1= query_get_value(SHOW MASTER STATUS, Position, 1);
+let $master_log_file= query_get_value(SHOW MASTER STATUS, File, 1);
+drop table t1;
+create table t2(n int not null auto_increment primary key);
+insert into t2 values (1),(2);
+let $master_log_pos_2= query_get_value(SHOW MASTER STATUS, Position, 1);
+insert into t2 values (3),(4);
+drop table t2;
+
+--echo ==== Replicate one event at a time on slave ====
+
+# try to replicate all queries until drop of t1
+connection slave;
+--replace_result $master_log_file MASTER_LOG_FILE $master_log_pos_1 MASTER_LOG_POS
+eval start slave until master_log_file='$master_log_file', master_log_pos=$master_log_pos_1;
+--source include/wait_for_slave_io_to_start.inc
+--source include/wait_for_slave_sql_to_stop.inc
+# here table should be still not deleted
+select * from t1;
+--let $slave_param= Exec_Master_Log_Pos
+--let $slave_param_value= $master_log_pos_1
+--source include/check_slave_param.inc
+
+# this should fail right after start
+start slave until master_log_file='master-no-such-bin.000001', master_log_pos=291;
+--source include/wait_for_slave_io_to_start.inc
+--source include/wait_for_slave_sql_to_stop.inc
+# again this table should be still not deleted
+select * from t1;
+--let $slave_param= Exec_Master_Log_Pos
+--let $slave_param_value= $master_log_pos_1
+--source include/check_slave_param.inc
+
+let $relay_log_file= slave-relay-bin.000003;
+let $master_log_pos= $master_log_pos_2;
+source include/get_relay_log_pos.inc;
+# try replicate all up to and not including the second insert to t2;
+--replace_result $relay_log_pos RELAY_LOG_POS
+eval start slave until relay_log_file='$relay_log_file', relay_log_pos=$relay_log_pos;
+--source include/wait_for_slave_io_to_start.inc
+--source include/wait_for_slave_sql_to_stop.inc
+select * from t2;
+--let $slave_param= Exec_Master_Log_Pos
+--let $slave_param_value= $master_log_pos
+--source include/check_slave_param.inc
+
+# clean up
+start slave;
+connection master;
+sync_slave_with_master;
+--source include/stop_slave.inc
+
+--let $exec_log_pos_1= query_get_value(SHOW SLAVE STATUS, Exec_Master_Log_Pos, 1)
+# this should stop immediately as we are already there
+--replace_result $master_log_file MASTER_LOG_FILE $master_log_pos_2 MASTER_LOG_POS
+eval start slave until master_log_file='$master_log_file', master_log_pos=$master_log_pos_2;
+--source include/wait_for_slave_io_to_start.inc
+--source include/wait_for_slave_sql_to_stop.inc
+--let $slave_param= Exec_Master_Log_Pos
+--let $slave_param_value= $exec_log_pos_1
+--source include/check_slave_param.inc
+
+--echo ==== Test various error conditions ====
+
+--error 1277
+start slave until master_log_file='master-bin', master_log_pos=561;
+--error 1277
+start slave until master_log_file='master-bin.000001', master_log_pos=561, relay_log_pos=12;
+--error 1277
+start slave until master_log_file='master-bin.000001';
+--error 1277
+start slave until relay_log_file='slave-relay-bin.000002';
+--error 1277
+start slave until relay_log_file='slave-relay-bin.000002', master_log_pos=561;
+# Warning should be given for second command
+start slave sql_thread;
+start slave until master_log_file='master-bin.000001', master_log_pos=776;
+
+#
+# bug#47210 first execution of "start slave until" stops too early
+#
+# testing that a slave rotate event that is caused by stopping the slave
+# does not intervene anymore in UNTIL condition.
+#
+
+connection slave;
+source include/stop_slave.inc;
+--disable_warnings
+drop table if exists t1;
+--enable_warnings
+--source include/reset_slave.inc
+--replace_result $MASTER_MYPORT MASTER_PORT
+eval change master to master_host='127.0.0.1',master_port=$MASTER_MYPORT, master_user='root';
+
+connection master;
+--disable_warnings
+drop table if exists t1;
+--enable_warnings
+reset master;
+create table t1 (a int primary key auto_increment);
+save_master_pos;
+let $master_pos= query_get_value(SHOW MASTER STATUS, Position, 1);
+
+connection slave;
+start slave;
+sync_with_master;
+
+# at this point slave will close the relay log stamping it with its own
+# Rotate log event. This event won't be examined on matter of the master
+# UNTIL pos anymore.
+source include/stop_slave.inc;
+let $slave_exec_pos= query_get_value(SHOW SLAVE STATUS, Exec_Master_Log_Pos, 1);
+
+--echo master and slave are in sync now
+let $diff_pos= `select $master_pos - $slave_exec_pos`;
+eval select $diff_pos as zero;
+
+connection master;
+insert into t1 set a=null;
+let $until_pos= query_get_value(SHOW MASTER STATUS, Position, 1);
+insert into t1 set a=null;
+select count(*) as two from t1;
+
+connection slave;
+--replace_result $master_log_file MASTER_LOG_FILE $until_pos UNTIL_POS;
+eval start slave until master_log_file='$master_log_file', master_log_pos= $until_pos;
+source include/wait_for_slave_sql_to_stop.inc;
+let $slave_exec_pos= query_get_value(SHOW SLAVE STATUS, Exec_Master_Log_Pos, 1);
+--echo slave stopped at the prescribed position
+let $diff_pos= `select $until_pos - $slave_exec_pos`;
+eval select $diff_pos as zero;
+select count(*) as one from t1;
+
+
+connection master;
+drop table t1;
+
+connection slave;
+start slave;
+sync_with_master;
+
+# End of tests
+--let $rpl_only_running_threads= 1
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_stm_user_variables.test b/mysql-test/suite/rpl/t/rpl_stm_user_variables.test
new file mode 100644
index 00000000..18b90658
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_stm_user_variables.test
@@ -0,0 +1,202 @@
+#
+# BUG#49562: SBR out of sync when using numeric data types + user variable
+#
+
+-- source include/have_binlog_format_statement.inc
+-- source include/master-slave.inc
+
+## Setup user variables for several numeric types, so that we get
+## coverage on the User_var_log_event different val types
+
+-- 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;
+
+-- disable_warnings
+
+-- echo ### insert max unsigned
+-- echo ### a) declarative
+-- 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);
+
+-- echo #########################################
+-- query_vertical SELECT * FROM t1
+-- sync_slave_with_master
+-- query_vertical SELECT * FROM t1
+-- echo #########################################
+-- connection master
+-- echo ## assertion: master and slave tables are in sync
+-- let $diff_tables=master:t1,slave:t1
+-- source include/diff_tables.inc
+-- connection master
+TRUNCATE t1;
+
+-- echo ### b) user var
+INSERT IGNORE INTO t1 VALUES (@positive,
+ @positive,
+ @positive,
+ @positive,
+ @positive,
+ @positive,
+ @positive,
+ @positive,
+ @positive,
+ @positive,
+ @positive,
+ @positive,
+ @positive,
+ @positive);
+
+-- echo #########################################
+-- query_vertical SELECT * FROM t1
+-- sync_slave_with_master
+-- query_vertical SELECT * FROM t1
+-- echo #########################################
+-- connection master
+-- echo ## assertion: master and slave tables are in sync
+-- let $diff_tables=master:t1,slave:t1
+-- source include/diff_tables.inc
+-- connection master
+TRUNCATE t1;
+
+
+-- echo ### insert min signed
+-- echo ### a) declarative
+-- 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);
+
+-- echo #########################################
+-- query_vertical SELECT * FROM t1
+-- sync_slave_with_master
+-- query_vertical SELECT * FROM t1
+-- echo #########################################
+-- connection master
+-- echo ## assertion: master and slave tables are in sync
+-- let $diff_tables=master:t1,slave:t1
+-- source include/diff_tables.inc
+-- connection master
+TRUNCATE t1;
+
+-- echo ### b) user var
+INSERT IGNORE INTO t1 VALUES (@negative,
+ @negative,
+ @negative,
+ @negative,
+ @negative,
+ @negative,
+ @negative,
+ @negative,
+ @negative,
+ @negative,
+ @negative,
+ @negative,
+ @negative,
+ @negative);
+
+-- echo #########################################
+-- query_vertical SELECT * FROM t1
+-- sync_slave_with_master
+-- query_vertical SELECT * FROM t1
+-- echo #########################################
+-- connection master
+
+-- echo ## assertion: master and slave tables are in sync
+-- let $diff_tables=master:t1,slave:t1
+-- source include/diff_tables.inc
+-- connection master
+TRUNCATE t1;
+
+-- echo ## check: contents of both tables master's and slave's
+-- enable_warnings
+
+## cleanup
+-- connection master
+DROP TABLE t1;
+-- sync_slave_with_master
+
+#####################################################################
+#
+# BUG#51426
+#
+#####################################################################
+--source include/rpl_reset.inc
+-- connection master
+SET sql_mode = 'NO_ENGINE_SUBSTITUTION';
+CREATE TABLE t1 ( c INT, PRIMARY KEY (c)) Engine=MyISAM;
+
+# offending trigger that would reset the unsigned flag for aux before
+# binlogging of User_var_log_event would take place.
+CREATE TRIGGER tr1 AFTER INSERT ON t1 FOR EACH ROW SET @aux = -1 ;
+
+SET @aux = 10294947273192243200;
+SET @aux1= @aux;
+-- error ER_DUP_ENTRY
+INSERT INTO t1 VALUES (@aux) , (@aux1);
+SET sql_mode = DEFAULT;
+
+-- sync_slave_with_master
+
+-- echo ## assertion: master and slave tables are in sync
+-- let $diff_tables=master:t1,slave:t1
+-- source include/diff_tables.inc
+
+--connection master
+DROP TRIGGER tr1;
+DROP TABLE t1;
+
+-- sync_slave_with_master
+
+--echo
+--echo # The GET DIAGNOSTICS itself is not replicated, but it can set
+--echo # variables which can be used in statements that are replicated.
+--echo
+
+--source include/rpl_reset.inc
+connection master;
+
+CREATE TABLE t1 (a INT, b INT);
+GET DIAGNOSTICS @var1 = NUMBER;
+INSERT INTO t1 VALUES (@var1, 0), (@var1, 0);
+
+DELIMITER |;
+CREATE PROCEDURE p1()
+LANGUAGE SQL
+BEGIN
+ DECLARE count INT;
+ UPDATE t1 SET b = 2 WHERE a = 0;
+ GET DIAGNOSTICS count = ROW_COUNT;
+ INSERT INTO t1 VALUES (1, count);
+END|
+DELIMITER ;|
+
+CALL p1();
+
+-- sync_slave_with_master
+
+connection slave;
+--echo # check if the statement was replicated.
+SELECT * FROM t1 ORDER BY a;
+
+connection master;
+--echo # Show events and cleanup
+--source include/show_binlog_events.inc
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+-- sync_slave_with_master
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_stop_slave.test b/mysql-test/suite/rpl/t/rpl_stop_slave.test
new file mode 100644
index 00000000..14c6641f
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_stop_slave.test
@@ -0,0 +1,146 @@
+source include/have_innodb.inc;
+source include/have_debug.inc;
+source include/have_debug_sync.inc;
+source include/have_binlog_format_mixed_or_statement.inc;
+source include/master-slave.inc;
+
+--connection slave
+--source include/stop_slave.inc
+CHANGE MASTER TO MASTER_USE_GTID=NO;
+--source include/start_slave.inc
+--connection master
+
+--echo
+--echo # BUG#56118 STOP SLAVE does not wait till trx with CREATE TMP TABLE ends
+--echo #
+--echo # If a temporary table is created or dropped, the transaction should be
+--echo # regarded similarly that a non-transactional table is modified. So
+--echo # STOP SLAVE should wait until the transaction has finished.
+
+CREATE TABLE t1(c1 INT) ENGINE=InnoDB;
+CREATE TABLE t2(c1 INT) ENGINE=InnoDB;
+
+sync_slave_with_master;
+SET DEBUG_SYNC= 'RESET';
+source include/stop_slave.inc;
+
+--echo
+--echo # Suspend the INSERT statement in current transaction on SQL thread.
+--echo # It guarantees that SQL thread is applying the transaction when
+--echo # STOP SLAVE command launchs.
+SET @saved_dbug = @@GLOBAL.debug_dbug;
+set global debug_dbug= '+d,after_mysql_insert';
+source include/start_slave.inc;
+
+--echo
+--echo # CREATE TEMPORARY TABLE with InnoDB engine
+--echo # -----------------------------------------
+let $tmp_table_stm= CREATE TEMPORARY TABLE tt1(c1 INT) ENGINE = InnoDB;
+source include/rpl_stop_slave.test;
+
+--echo
+--echo # CREATE TEMPORARY TABLE ... SELECT with InnoDB engine
+--echo # ----------------------------------------------------
+let $tmp_table_stm= CREATE TEMPORARY TABLE tt1(c1 INT) ENGINE = InnoDB
+ SELECT c1 FROM t2;
+source include/rpl_stop_slave.test;
+
+# Don't need to verify 'CREATE TEMPORARY TABLE' with MyIASM engine, as it
+# never is binlogged into a transaction since 5.5.
+
+--echo
+--echo # Test end
+SET @@GLOBAL.debug_dbug = @saved_dbug;
+source include/restart_slave_sql.inc;
+
+connection slave;
+call mtr.add_suppression("Slave SQL.*Request to stop slave SQL Thread received while applying a group that has non-transactional changes; waiting for completion of the group");
+connection master;
+
+DROP TABLE t1, t2;
+
+--echo
+--echo # Bug#58546 test rpl_packet timeout failure sporadically on PB
+--echo # ----------------------------------------------------------------------
+--echo # STOP SLAVE stopped IO thread first and then stopped SQL thread. It was
+--echo # possible that IO thread stopped after replicating part of a transaction
+--echo # which SQL thread was executing. SQL thread would be hung if the
+--echo # transaction could not be rolled back safely.
+--echo # It caused some sporadic failures on PB2.
+--echo #
+--echo # This test verifies that when 'STOP SLAVE' is issued by a user, IO
+--echo # thread will continue to fetch the rest events of the transaction which
+--echo # is being executed by SQL thread and is not able to be rolled back safely.
+
+CREATE TABLE t1 (c1 INT KEY, c2 INT) ENGINE=InnoDB;
+CREATE TABLE t2 (c1 INT) ENGINE=MyISAM;
+INSERT INTO t1 VALUES(1, 1);
+
+sync_slave_with_master;
+--source include/stop_slave.inc
+
+connection master;
+# make sure that there are no zombie threads
+--source include/stop_dump_threads.inc
+
+SET @saved_dbug = @@GLOBAL.debug_dbug;
+set global debug_dbug= '+d,dump_thread_wait_before_send_xid';
+
+connection slave;
+--source include/start_slave.inc
+
+BEGIN;
+UPDATE t1 SET c2 = 2 WHERE c1 = 1;
+
+connection master;
+BEGIN;
+INSERT INTO t1 VALUES(2, 2);
+INSERT INTO t2 VALUES(1);
+UPDATE t1 SET c2 = 3 WHERE c1 = 1;
+COMMIT;
+
+# wait for the dump thread reach the sync point
+--let $wait_condition= select count(*)=1 from information_schema.processlist where state LIKE '%debug sync point%' and command='Binlog Dump'
+--source include/wait_condition.inc
+
+connection slave1;
+let $show_statement= SHOW PROCESSLIST;
+let $field= Info;
+let $condition= = 'UPDATE t1 SET c2 = 3 WHERE c1 = 1';
+source include/wait_show_condition.inc;
+
+send STOP SLAVE;
+
+connection slave;
+ROLLBACK;
+
+connection master;
+
+SET DEBUG_SYNC= 'now SIGNAL signal.continue';
+SET DEBUG_SYNC= 'now WAIT_FOR signal.continued';
+
+connection slave;
+source include/wait_for_slave_to_stop.inc;
+
+connection slave1;
+reap;
+
+# Slave has stopped, thence lets make sure that
+# we kill the zombie dump threads. Also, make
+# sure that we disable the DBUG_EXECUTE_IF
+# that would set the dump thread to wait
+connection master;
+SET @@GLOBAL.debug_dbug = @saved_dbug;
+# make sure that there are no zombie threads
+--source include/stop_dump_threads.inc
+
+connection slave1;
+# now the dump thread on the master will start
+# from a clean slate, i.e. without the
+# DBUG_EXECUTE_IF set
+source include/start_slave.inc;
+
+connection master;
+DROP TABLE t1, t2;
+--source include/rpl_end.inc
+SET DEBUG_SYNC= 'RESET';
diff --git a/mysql-test/suite/rpl/t/rpl_stop_slave_error-slave.opt b/mysql-test/suite/rpl/t/rpl_stop_slave_error-slave.opt
new file mode 100644
index 00000000..32c4527a
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_stop_slave_error-slave.opt
@@ -0,0 +1 @@
+--log-error=$MYSQLTEST_VARDIR/tmp/slave_log.err
diff --git a/mysql-test/suite/rpl/t/rpl_stop_slave_error.test b/mysql-test/suite/rpl/t/rpl_stop_slave_error.test
new file mode 100644
index 00000000..10d7c773
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_stop_slave_error.test
@@ -0,0 +1,16 @@
+#
+# MDEV-8345 STOP SLAVE should not cause an ERROR to be logged to the error log
+#
+source include/have_binlog_format_mixed.inc; # don't repeat the test three times
+source include/master-slave.inc;
+
+connection master;
+sync_slave_with_master;
+source include/stop_slave.inc;
+let SEARCH_FILE=$MYSQLTEST_VARDIR/tmp/slave_log.err;
+let SEARCH_PATTERN=Error reading packet from server: Lost connection;
+source include/search_pattern_in_file.inc;
+
+source include/start_slave.inc;
+source include/rpl_end.inc;
+
diff --git a/mysql-test/suite/rpl/t/rpl_strict_password_validation.test b/mysql-test/suite/rpl/t/rpl_strict_password_validation.test
new file mode 100644
index 00000000..c4dda1e1
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_strict_password_validation.test
@@ -0,0 +1,24 @@
+if (!$SIMPLE_PASSWORD_CHECK_SO) {
+ skip No SIMPLE_PASSWORD_CHECK plugin;
+}
+
+--source include/master-slave.inc
+
+
+--connection slave
+install soname "simple_password_check";
+select @@strict_password_validation;
+
+--connection master
+create user foo1 identified by password '11111111111111111111111111111111111111111';
+set password for foo1 = PASSWORD('PLAINtext-password!!99');
+drop user foo1;
+--sync_slave_with_master
+
+--connection slave
+--error ER_OPTION_PREVENTS_STATEMENT
+create user foo1 identified by password '11111111111111111111111111111111111111111';
+
+uninstall plugin simple_password_check;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_switch_stm_row_mixed.test b/mysql-test/suite/rpl/t/rpl_switch_stm_row_mixed.test
new file mode 100644
index 00000000..6b28e344
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_switch_stm_row_mixed.test
@@ -0,0 +1,651 @@
+#
+# This include file is used by more than one test suite
+# (currently rpl and binlog_encryption).
+# Please check all dependent tests after modifying it
+#
+
+#
+# rpl_switch_stm_row_mixed tests covers
+#
+# - Master is switching explicitly between STATEMENT, ROW, and MIXED
+# binlog format showing when it is possible and when not.
+# - Master switching from MIXED to RBR implicitly listing all use
+# cases, e.g a query invokes SYS_GUID(), thereafter to serve as the
+# definition of MIXED binlog format
+# - correctness of execution
+
+
+-- source include/have_binlog_format_mixed_or_row.inc
+-- source include/master-slave.inc
+
+# Since this test generates row-based events in the binary log, the
+# slave SQL thread cannot be in STATEMENT mode to execute this test,
+# so we only execute it for MIXED and ROW as default value of
+# BINLOG_FORMAT.
+
+connection slave;
+
+connection master;
+--disable_warnings
+drop database if exists mysqltest1;
+create database mysqltest1;
+--enable_warnings
+use mysqltest1;
+
+# Save binlog format
+set @my_binlog_format= @@global.binlog_format;
+
+# play with switching
+set session binlog_format=mixed;
+show session variables like "binlog_format%";
+set session binlog_format=statement;
+show session variables like "binlog_format%";
+set session binlog_format=row;
+show session variables like "binlog_format%";
+
+set global binlog_format=DEFAULT;
+show global variables like "binlog_format%";
+set global binlog_format=MIXED;
+show global variables like "binlog_format%";
+set global binlog_format=STATEMENT;
+show global variables like "binlog_format%";
+set global binlog_format=ROW;
+show global variables like "binlog_format%";
+show session variables like "binlog_format%";
+select @@global.binlog_format, @@session.binlog_format;
+
+CREATE TABLE t1 (a varchar(100));
+
+prepare stmt1 from 'insert into t1 select concat(SYS_GUID(),?)';
+set @string="emergency_1_";
+insert into t1 values("work_2_");
+execute stmt1 using @string;
+deallocate prepare stmt1;
+
+prepare stmt1 from 'insert into t1 select ?';
+insert into t1 values(concat(SYS_GUID(),"work_3_"));
+execute stmt1 using @string;
+deallocate prepare stmt1;
+
+insert into t1 values(concat("for_4_",SYS_GUID()));
+insert into t1 select "yesterday_5_";
+
+# verify that temp tables prevent a switch to SBR
+create temporary table tmp(a char(100));
+insert into tmp values("see_6_");
+--error ER_TEMP_TABLE_PREVENTS_SWITCH_OUT_OF_RBR
+set binlog_format=statement;
+insert into t1 select * from tmp;
+drop temporary table tmp;
+
+# Now we go to SBR
+set binlog_format=statement;
+show global variables like "binlog_format%";
+show session variables like "binlog_format%";
+select @@global.binlog_format, @@session.binlog_format;
+set global binlog_format=statement;
+show global variables like "binlog_format%";
+show session variables like "binlog_format%";
+select @@global.binlog_format, @@session.binlog_format;
+
+prepare stmt1 from 'insert into t1 select ?';
+set @string="emergency_7_";
+insert into t1 values("work_8_");
+execute stmt1 using @string;
+deallocate prepare stmt1;
+
+prepare stmt1 from 'insert into t1 select ?';
+insert into t1 values("work_9_");
+execute stmt1 using @string;
+deallocate prepare stmt1;
+
+insert into t1 values("for_10_");
+insert into t1 select "yesterday_11_";
+
+# test statement (is not default after wl#3368)
+set binlog_format=statement;
+select @@global.binlog_format, @@session.binlog_format;
+set global binlog_format=statement;
+select @@global.binlog_format, @@session.binlog_format;
+
+prepare stmt1 from 'insert into t1 select ?';
+set @string="emergency_12_";
+insert into t1 values("work_13_");
+execute stmt1 using @string;
+deallocate prepare stmt1;
+
+prepare stmt1 from 'insert into t1 select ?';
+insert into t1 values("work_14_");
+execute stmt1 using @string;
+deallocate prepare stmt1;
+
+insert into t1 values("for_15_");
+insert into t1 select "yesterday_16_";
+
+# and now the mixed mode
+
+set global binlog_format=mixed;
+select @@global.binlog_format, @@session.binlog_format;
+set binlog_format=default;
+select @@global.binlog_format, @@session.binlog_format;
+
+prepare stmt1 from 'insert into t1 select concat(SYS_GUID(),?)';
+set @string="emergency_17_";
+insert into t1 values("work_18_");
+execute stmt1 using @string;
+deallocate prepare stmt1;
+
+prepare stmt1 from 'insert into t1 select ?';
+insert into t1 values(concat(SYS_GUID(),"work_19_"));
+execute stmt1 using @string;
+deallocate prepare stmt1;
+
+insert into t1 values(concat("for_20_",SYS_GUID()));
+insert into t1 select "yesterday_21_";
+
+prepare stmt1 from 'insert into t1 select ?';
+insert into t1 values(concat(SYS_GUID(),"work_22_"));
+execute stmt1 using @string;
+deallocate prepare stmt1;
+
+insert into t1 values(concat("for_23_",SYS_GUID()));
+insert into t1 select "yesterday_24_";
+
+# Test of CREATE TABLE SELECT
+
+create table t2 ENGINE=MyISAM select rpad(SYS_GUID(),100,' ');
+create table t3 select 1 union select SYS_GUID();
+--disable_warnings
+SET STATEMENT sql_mode = 'NO_ENGINE_SUBSTITUTION' FOR
+create table t4 select * from t1 where 3 in (select 1 union select 2 union select SYS_GUID() union select 3);
+--enable_warnings
+SET STATEMENT sql_mode = 'NO_ENGINE_SUBSTITUTION' FOR
+create table t5 select * from t1 where 3 in (select 1 union select 2 union select curdate() union select 3);
+# what if SYS_GUID() is first:
+--disable_warnings
+insert ignore into t5 select SYS_GUID() from t1 where 3 in (select 1 union select 2 union select 3 union select * from t4);
+--enable_warnings
+
+# inside a stored procedure
+
+delimiter |;
+create procedure foo()
+begin
+insert into t1 values("work_25_");
+insert into t1 values(concat("for_26_",SYS_GUID()));
+insert into t1 select "yesterday_27_";
+end|
+create procedure foo2()
+begin
+insert into t1 values(concat("emergency_28_",SYS_GUID()));
+insert into t1 values("work_29_");
+insert into t1 values(concat("for_30_",SYS_GUID()));
+set session binlog_format=row; # accepted for stored procs
+insert into t1 values("more work_31_");
+set session binlog_format=mixed;
+end|
+create function foo3() returns bigint unsigned
+begin
+ set session binlog_format=row; # rejected for stored funcs
+ insert into t1 values("alarm");
+ return 100;
+end|
+create procedure foo4(x varchar(100))
+begin
+insert into t1 values(concat("work_250_",x));
+insert into t1 select "yesterday_270_";
+end|
+delimiter ;|
+call foo();
+call foo2();
+call foo4("hello");
+call foo4(SYS_GUID());
+call foo4("world");
+
+# test that can't SET in a stored function
+--error ER_STORED_FUNCTION_PREVENTS_SWITCH_BINLOG_FORMAT
+select foo3();
+select * from t1 where a="alarm";
+
+# Tests of stored functions/triggers/views for BUG#20930 "Mixed
+# binlogging mode does not work with stored functions, triggers,
+# views"
+
+# Function which calls procedure
+drop function foo3;
+delimiter |;
+create function foo3() returns bigint unsigned
+begin
+ insert into t1 values("foo3_32_");
+ call foo();
+ return 100;
+end|
+delimiter ;|
+insert into t2 select foo3();
+
+prepare stmt1 from 'insert into t2 select foo3()';
+execute stmt1;
+execute stmt1;
+deallocate prepare stmt1;
+
+# Test if stored function calls stored function which calls procedure
+# which requires row-based.
+
+delimiter |;
+create function foo4() returns bigint unsigned
+begin
+ insert into t2 select foo3();
+ return 100;
+end|
+delimiter ;|
+--disable_ps2_protocol
+select foo4();
+--enable_ps2_protocol
+
+prepare stmt1 from 'select foo4()';
+execute stmt1;
+execute stmt1;
+deallocate prepare stmt1;
+
+# A simple stored function
+delimiter |;
+create function foo5() returns bigint unsigned
+begin
+ insert into t2 select SYS_GUID();
+ return 100;
+end|
+delimiter ;|
+--disable_ps2_protocol
+select foo5();
+--enable_ps2_protocol
+
+prepare stmt1 from 'select foo5()';
+execute stmt1;
+execute stmt1;
+deallocate prepare stmt1;
+
+# A simple stored function where SYS_GUID() is in the argument
+delimiter |;
+create function foo6(x varchar(100)) returns bigint unsigned
+begin
+ insert into t2 select x;
+ return 100;
+end|
+delimiter ;|
+--disable_ps2_protocol
+select foo6("foo6_1_");
+select foo6(concat("foo6_2_",SYS_GUID()));
+--enable_ps2_protocol
+
+prepare stmt1 from 'select foo6(concat("foo6_3_",SYS_GUID()))';
+execute stmt1;
+execute stmt1;
+deallocate prepare stmt1;
+
+
+# Test of views using SYS_GUID()
+
+create view v1 as select SYS_GUID();
+create table t11 (data varchar(255));
+insert into t11 select * from v1;
+# Test of querying INFORMATION_SCHEMA which parses the view's body,
+# to verify that it binlogs statement-based (is not polluted by
+# the parsing of the view's body).
+insert into t11 select TABLE_NAME from INFORMATION_SCHEMA.TABLES where TABLE_SCHEMA='mysqltest1' and TABLE_NAME IN ('v1','t11');
+prepare stmt1 from "insert into t11 select TABLE_NAME from INFORMATION_SCHEMA.TABLES where TABLE_SCHEMA='mysqltest1' and TABLE_NAME IN ('v1','t11')";
+execute stmt1;
+execute stmt1;
+deallocate prepare stmt1;
+
+# Test of triggers with SYS_GUID()
+delimiter |;
+create trigger t11_bi before insert on t11 for each row
+begin
+ set NEW.data = concat(NEW.data,SYS_GUID());
+end|
+delimiter ;|
+insert into t11 values("try_560_");
+
+# Test that INSERT DELAYED works in mixed mode (BUG#20649)
+insert delayed into t2 values("delay_1_");
+insert delayed into t2 values(concat("delay_2_",SYS_GUID()));
+insert delayed into t2 values("delay_6_");
+
+# Test for BUG#20633 (INSERT DELAYED RAND()/user_variable does not
+# replicate fine in statement-based ; we test that in mixed mode it
+# works).
+insert delayed into t2 values(rand());
+set @a=2.345;
+insert delayed into t2 values(@a);
+
+# With INSERT DELAYED, rows are written to the binlog after they are
+# written to the table. Therefore, it is not enough to wait until the
+# rows make it to t2 on the master (the rows may not be in the binlog
+# at that time, and may still not be in the binlog when
+# sync_slave_with_master is later called). Instead, we wait until the
+# rows make it to t2 on the slave. We first call
+# sync_slave_with_master, so that we are sure that t2 has been created
+# on the slave.
+sync_slave_with_master;
+let $wait_condition= SELECT COUNT(*) = 19 FROM mysqltest1.t2;
+--source include/wait_condition.inc
+connection master;
+
+# If you want to do manual testing of the mixed mode regarding UDFs (not
+# testable automatically as quite platform- and compiler-dependent),
+# you just need to set the variable below to 1, and to
+# "make udf_example.so" in sql/, and to copy sql/udf_example.so to
+# MYSQL_TEST_DIR/lib/mysql.
+let $you_want_to_test_UDF=0;
+if ($you_want_to_test_UDF)
+{
+ CREATE FUNCTION metaphon RETURNS STRING SONAME 'udf_example.so';
+ prepare stmt1 from 'insert into t1 select metaphon(?)';
+ set @string="emergency_133_";
+ insert into t1 values("work_134_");
+ execute stmt1 using @string;
+ deallocate prepare stmt1;
+ prepare stmt1 from 'insert into t1 select ?';
+ insert into t1 values(metaphon("work_135_"));
+ execute stmt1 using @string;
+ deallocate prepare stmt1;
+ insert into t1 values(metaphon("for_136_"));
+ insert into t1 select "yesterday_137_";
+ create table t6 select metaphon("for_138_");
+ create table t7 select 1 union select metaphon("for_139_");
+ create table t8 select * from t1 where 3 in (select 1 union select 2 union select metaphon("for_140_") union select 3);
+ create table t9 select * from t1 where 3 in (select 1 union select 2 union select curdate() union select 3);
+}
+
+create table t20 select * from t1; # save for comparing later
+create table t21 select * from t2;
+create table t22 select * from t3;
+drop table t1,t2,t3;
+
+# This tests the fix to
+# BUG#19630 stored function inserting into two auto_increment breaks statement-based binlog
+# We verify that under the mixed binlog mode, a stored function
+# modifying at least two tables having an auto_increment column,
+# is binlogged row-based. Indeed in statement-based binlogging,
+# only the auto_increment value generated for the first table
+# is recorded in the binlog, the value generated for the 2nd table
+# lacking.
+
+create table t1 (a int primary key auto_increment, b varchar(100));
+create table t2 (a int primary key auto_increment, b varchar(100));
+create table t3 (b varchar(100));
+delimiter |;
+create function f (x varchar(100)) returns int deterministic
+begin
+ insert into t1 values(null,x);
+ insert into t2 values(null,x);
+ return 1;
+end|
+delimiter ;|
+--disable_ps2_protocol
+select f("try_41_");
+--enable_ps2_protocol
+# Two operations which compensate each other except that their net
+# effect is that they advance the auto_increment counter of t2 on slave:
+sync_slave_with_master;
+use mysqltest1;
+insert into t2 values(2,null),(3,null),(4,null);
+delete from t2 where a>=2;
+
+connection master;
+# this is the call which didn't replicate well
+--disable_ps2_protocol
+select f("try_42_");
+--enable_ps2_protocol
+sync_slave_with_master;
+
+# now use prepared statement and test again, just to see that the RBB
+# mode isn't set at PREPARE but at EXECUTE.
+
+insert into t2 values(3,null),(4,null);
+delete from t2 where a>=3;
+
+connection master;
+prepare stmt1 from 'select f(?)';
+set @string="try_43_";
+insert into t1 values(null,"try_44_"); # should be SBB
+execute stmt1 using @string; # should be RBB
+deallocate prepare stmt1;
+sync_slave_with_master;
+
+# verify that if only one table has auto_inc, it does not trigger RBB
+# (we'll check in binlog further below)
+
+connection master;
+create table t12 select * from t1; # save for comparing later
+drop table t1;
+create table t1 (a int, b varchar(100), key(a));
+--disable_ps2_protocol
+select f("try_45_");
+--enable_ps2_protocol
+
+# restore table's key
+create table t13 select * from t1;
+drop table t1;
+create table t1 (a int primary key auto_increment, b varchar(100));
+
+# now test if it's two functions, each of them inserts in one table
+
+drop function f;
+# we need a unique key to have sorting of rows by mysqldump
+create table t14 (unique (a)) select * from t2;
+truncate table t2;
+delimiter |;
+create function f1 (x varchar(100)) returns int deterministic
+begin
+ insert into t1 values(null,x);
+ return 1;
+end|
+create function f2 (x varchar(100)) returns int deterministic
+begin
+ insert into t2 values(null,x);
+ return 1;
+end|
+delimiter ;|
+--disable_ps2_protocol
+select f1("try_46_"),f2("try_47_");
+--enable_ps2_protocol
+
+sync_slave_with_master;
+insert into t2 values(2,null),(3,null),(4,null);
+delete from t2 where a>=2;
+
+connection master;
+# Test with SELECT and INSERT
+--disable_ps2_protocol
+select f1("try_48_"),f2("try_49_");
+--enable_ps2_protocol
+insert into t3 values(concat("try_50_",f1("try_51_"),f2("try_52_")));
+sync_slave_with_master;
+
+# verify that if f2 does only read on an auto_inc table, this does not
+# switch to RBB
+connection master;
+drop function f2;
+delimiter |;
+create function f2 (x varchar(100)) returns int deterministic
+begin
+ declare y int;
+ insert into t1 values(null,x);
+ set y = (select count(*) from t2);
+ return y;
+end|
+delimiter ;|
+--disable_ps2_protocol
+select f1("try_53_"),f2("try_54_");
+--enable_ps2_protocol
+sync_slave_with_master;
+
+# And now, a normal statement with a trigger (no stored functions)
+
+connection master;
+drop function f2;
+delimiter |;
+create trigger t1_bi before insert on t1 for each row
+begin
+ insert into t2 values(null,"try_55_");
+end|
+delimiter ;|
+insert into t1 values(null,"try_56_");
+# and now remove one auto_increment and verify SBB
+alter table t1 modify a int, drop primary key;
+insert into t1 values(null,"try_57_");
+sync_slave_with_master;
+
+# Test for BUG#20499 "mixed mode with temporary table breaks binlog"
+# Slave used to have only 2 rows instead of 3.
+connection master;
+CREATE TEMPORARY TABLE t15 SELECT SYS_GUID();
+create table t16 like t15;
+INSERT INTO t16 SELECT * FROM t15;
+# we'll verify that this one is done RBB
+insert into t16 values("try_65_");
+drop table t15;
+# we'll verify that this one is done SBB
+insert into t16 values("try_66_");
+sync_slave_with_master;
+
+# and now compare:
+
+connection master;
+
+# first check that data on master is sensible
+select count(*) from t1;
+select count(*) from t2;
+select count(*) from t3;
+select count(*) from t4;
+select count(*) from t5;
+select count(*) from t11;
+select count(*) from t20;
+select count(*) from t21;
+select count(*) from t22;
+select count(*) from t12;
+select count(*) from t13;
+select count(*) from t14;
+select count(*) from t16;
+if ($you_want_to_test_UDF)
+{
+ select count(*) from t6;
+ select count(*) from t7;
+ select count(*) from t8;
+ select count(*) from t9;
+}
+
+sync_slave_with_master;
+
+#
+# Bug#20863 If binlog format is changed between update and unlock of
+# tables, wrong binlog
+#
+
+connection master;
+DROP TABLE IF EXISTS t11;
+SET SESSION BINLOG_FORMAT=STATEMENT;
+CREATE TABLE t11 (song VARCHAR(255));
+LOCK TABLES t11 WRITE;
+SET SESSION BINLOG_FORMAT=ROW;
+INSERT INTO t11 VALUES('Several Species of Small Furry Animals Gathered Together in a Cave and Grooving With a Pict');
+SET SESSION BINLOG_FORMAT=STATEMENT;
+INSERT INTO t11 VALUES('Careful With That Axe, Eugene');
+UNLOCK TABLES;
+
+--query_vertical SELECT * FROM t11
+sync_slave_with_master;
+USE mysqltest1;
+--query_vertical SELECT * FROM t11
+
+connection master;
+DROP TABLE IF EXISTS t12;
+SET SESSION BINLOG_FORMAT=MIXED;
+CREATE TABLE t12 (data LONG);
+LOCK TABLES t12 WRITE;
+INSERT INTO t12 VALUES(SYS_GUID());
+UNLOCK TABLES;
+sync_slave_with_master;
+
+#
+# BUG#28086: SBR of USER() becomes corrupted on slave
+#
+
+connection master;
+
+# Just to get something that is non-trivial, albeit still simple, we
+# stuff the result of USER() and CURRENT_USER() into a variable.
+--delimiter $$
+CREATE FUNCTION my_user()
+ RETURNS CHAR(64)
+BEGIN
+ DECLARE user CHAR(64);
+ SELECT USER() INTO user;
+ RETURN user;
+END $$
+--delimiter ;
+
+--delimiter $$
+CREATE FUNCTION my_current_user()
+ RETURNS CHAR(64)
+BEGIN
+ DECLARE user CHAR(64);
+ SELECT CURRENT_USER() INTO user;
+ RETURN user;
+END $$
+--delimiter ;
+
+DROP TABLE IF EXISTS t13;
+CREATE TABLE t13 (data CHAR(64));
+INSERT INTO t13 VALUES (USER());
+INSERT INTO t13 VALUES (my_user());
+INSERT INTO t13 VALUES (CURRENT_USER());
+INSERT INTO t13 VALUES (my_current_user());
+
+sync_slave_with_master;
+
+# as we're using SYS_GUID we don't SELECT but use "diff" like in rpl_row_UUID
+--exec $MYSQL_DUMP --compact --order-by-primary --skip-extended-insert --no-create-info mysqltest1 > $MYSQLTEST_VARDIR/tmp/rpl_switch_stm_row_mixed_master.sql
+--exec $MYSQL_DUMP_SLAVE --compact --order-by-primary --skip-extended-insert --no-create-info mysqltest1 > $MYSQLTEST_VARDIR/tmp/rpl_switch_stm_row_mixed_slave.sql
+
+# Let's compare. Note: If they match test will pass, if they do not match
+# the test will show that the diff statement failed and not reject file
+# will be created. You will need to go to the mysql-test dir and diff
+# the files your self to see what is not matching
+
+diff_files $MYSQLTEST_VARDIR/tmp/rpl_switch_stm_row_mixed_master.sql $MYSQLTEST_VARDIR/tmp/rpl_switch_stm_row_mixed_slave.sql;
+
+connection master;
+
+# Now test that mysqlbinlog works fine on a binlog generated by the
+# mixed mode
+
+# BUG#11312 "DELIMITER is not written to the binary log that causes
+# syntax error" makes that mysqlbinlog will fail if we pass it the
+# text of queries; this forces us to use --base64-output here.
+
+# BUG#20929 "BINLOG command causes invalid free plus assertion
+# failure" makes mysqld segfault when receiving --base64-output
+
+# So I can't enable this piece of test
+# SIGH
+
+if ($enable_when_11312_or_20929_fixed)
+{
+--exec $MYSQL_BINLOG --base64-output $MYSQLTEST_VARDIR/log/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/mysqlbinlog_mixed.sql
+drop database mysqltest1;
+--exec $MYSQL < $MYSQLTEST_VARDIR/tmp/mysqlbinlog_mixed.sql
+--exec $MYSQL_DUMP --compact --order-by-primary --skip-extended-insert --no-create-info mysqltest1 > $MYSQLTEST_VARDIR/tmp/rpl_switch_stm_row_mixed_master.sql
+# the old mysqldump output on slave is the same as what it was on
+# master before restoring on master.
+diff_files $MYSQLTEST_VARDIR/tmp/rpl_switch_stm_row_mixed_master.sql $MYSQLTEST_VARDIR/tmp/rpl_switch_stm_row_mixed_slave.sql;
+}
+
+drop database mysqltest1;
+sync_slave_with_master;
+
+connection master;
+# Restore binlog format setting
+set global binlog_format =@my_binlog_format;
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_sync-master.opt b/mysql-test/suite/rpl/t/rpl_sync-master.opt
new file mode 100644
index 00000000..04b06bfa
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_sync-master.opt
@@ -0,0 +1,2 @@
+--default-storage-engine=MyISAM
+--loose-innodb-file-per-table=0
diff --git a/mysql-test/suite/rpl/t/rpl_sync-slave.opt b/mysql-test/suite/rpl/t/rpl_sync-slave.opt
new file mode 100644
index 00000000..fc560657
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_sync-slave.opt
@@ -0,0 +1,2 @@
+--sync-relay-log-info=1 --relay-log-recovery=1 --default-storage-engine=MyISAM --loose-innodb-file-per-table=0
+--skip-core-file
diff --git a/mysql-test/suite/rpl/t/rpl_sync.test b/mysql-test/suite/rpl/t/rpl_sync.test
new file mode 100644
index 00000000..1e2ec2ca
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_sync.test
@@ -0,0 +1,159 @@
+#
+# This include file is used by more than one test suite
+# (currently rpl and binlog_encryption).
+# Please check all dependent tests after modifying it
+#
+
+########################################################################################
+# This test verifies the options --sync-relay-log-info and --relay-log-recovery by
+# crashing the slave in two different situations:
+# (case-1) - Corrupt the relay log with changes which were not processed by
+# the SQL Thread and crashes it.
+# (case-2) - Corrupt the master.info with wrong coordinates and crashes it.
+#
+# Case 1:
+# 1 - Stops the SQL Thread
+# 2 - Inserts new records into the master.
+# 3 - Corrupts the relay-log.bin* which most likely has such changes.
+# 4 - Crashes the slave
+# 5 - Verifies if the slave is sync with the master which means that the information
+# loss was circumvented by the recovery process.
+#
+# Case 2:
+# 1 - Stops the SQL/IO Threads
+# 2 - Inserts new records into the master.
+# 3 - Corrupts the master.info with wrong coordinates.
+# 4 - Crashes the slave
+# 5 - Verifies if the slave is sync with the master which means that the information
+# loss was circumvented by the recovery process.
+########################################################################################
+
+########################################################################################
+# Configuring the environment
+########################################################################################
+--echo =====Configuring the enviroment=======;
+--source include/not_embedded.inc
+--source include/not_valgrind.inc
+--source include/have_debug.inc
+--source include/have_innodb.inc
+--source include/not_crashrep.inc
+--source include/master-slave.inc
+
+call mtr.add_suppression('Attempting backtrace');
+call mtr.add_suppression("Recovery from master pos .* and file master-bin.000001");
+# Use innodb so we do not get "table should be repaired" issues.
+ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
+flush tables;
+CREATE TABLE t1(a INT, PRIMARY KEY(a)) engine=innodb;
+
+insert into t1(a) values(1);
+insert into t1(a) values(2);
+insert into t1(a) values(3);
+
+########################################################################################
+# Case 1: Corrupt a relay-log.bin*
+########################################################################################
+--echo =====Inserting data on the master but without the SQL Thread being running=======;
+sync_slave_with_master;
+
+connection slave;
+let $MYSQLD_SLAVE_DATADIR= `select @@datadir`;
+--replace_result $MYSQLD_SLAVE_DATADIR MYSQLD_SLAVE_DATADIR
+--copy_file $MYSQLD_SLAVE_DATADIR/master.info $MYSQLD_SLAVE_DATADIR/master.backup
+--source include/stop_slave_sql.inc
+
+connection master;
+insert into t1(a) values(4);
+insert into t1(a) values(5);
+insert into t1(a) values(6);
+
+--echo =====Removing relay log files and crashing/recoverying the slave=======;
+connection slave;
+--source include/stop_slave_io.inc
+
+let $file= query_get_value("SHOW SLAVE STATUS", Relay_Log_File, 1);
+
+--let FILE_TO_CORRUPT= $MYSQLD_SLAVE_DATADIR/$file
+perl;
+$file= $ENV{'FILE_TO_CORRUPT'};
+open(FILE, ">$file") || die "Unable to open $file.";
+truncate(FILE,0);
+print FILE "failure";
+close ($file);
+EOF
+
+--exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.2.expect
+SET SESSION debug_dbug="d,crash_before_rotate_relaylog";
+--error 2013
+FLUSH LOGS;
+
+--let $rpl_server_number= 2
+--source include/rpl_reconnect.inc
+
+--echo =====Dumping and comparing tables=======;
+--source include/start_slave.inc
+
+connection master;
+sync_slave_with_master;
+
+let $diff_tables=master:t1,slave:t1;
+source include/diff_tables.inc;
+
+########################################################################################
+# Case 2: Corrupt a master.info
+########################################################################################
+--echo =====Corrupting the master.info=======;
+connection slave;
+--source include/stop_slave.inc
+
+connection master;
+FLUSH LOGS;
+
+insert into t1(a) values(7);
+insert into t1(a) values(8);
+insert into t1(a) values(9);
+
+connection slave;
+let MYSQLD_SLAVE_DATADIR=`select @@datadir`;
+
+--perl
+use strict;
+use warnings;
+my $src= "$ENV{'MYSQLD_SLAVE_DATADIR'}/master.backup";
+my $dst= "$ENV{'MYSQLD_SLAVE_DATADIR'}/master.info";
+open(FILE, "<", $src) or die;
+my @content= <FILE>;
+close FILE;
+open(FILE, ">", $dst) or die;
+binmode FILE;
+print FILE @content;
+close FILE;
+EOF
+
+--exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.2.expect
+SET SESSION debug_dbug="d,crash_before_rotate_relaylog";
+--error 2013
+FLUSH LOGS;
+
+--let $rpl_server_number= 2
+--source include/rpl_reconnect.inc
+
+--echo =====Dumping and comparing tables=======;
+--source include/start_slave.inc
+
+connection master;
+sync_slave_with_master;
+
+let $diff_tables=master:t1,slave:t1;
+source include/diff_tables.inc;
+
+########################################################################################
+# Clean up
+########################################################################################
+--echo =====Clean up=======;
+connection master;
+drop table t1;
+
+--remove_file $MYSQLD_SLAVE_DATADIR/master.backup
+--source include/rpl_end.inc
+
diff --git a/mysql-test/suite/rpl/t/rpl_table_options.test b/mysql-test/suite/rpl/t/rpl_table_options.test
new file mode 100644
index 00000000..335bf8d8
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_table_options.test
@@ -0,0 +1,38 @@
+--source include/not_windows_embedded.inc
+--source include/have_example_plugin.inc
+--source include/master-slave.inc
+
+--replace_regex /\.dll/.so/
+eval install plugin example soname '$HA_EXAMPLE_SO';
+set default_storage_engine=example;
+
+sync_slave_with_master;
+connection master;
+
+#
+# only master has example engine installed,
+# the slave will have the table created in myisam,
+# that does not have ULL table option.
+# but because the table was created by the replication
+# slave thread, the table will be created anyway, even if
+# the option is unknown.
+#
+create table t1 (a int not null) ull=12340;
+alter table t1 ull=12350;
+show create table t1;
+
+sync_slave_with_master;
+connection slave;
+show create table t1;
+set sql_mode=ignore_bad_table_options;
+show create table t1;
+
+connection master;
+drop table t1;
+set default_storage_engine=default;
+select 1;
+
+# Cleanup
+uninstall plugin example;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_temp_table.test b/mysql-test/suite/rpl/t/rpl_temp_table.test
new file mode 100644
index 00000000..8b3af5d5
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_temp_table.test
@@ -0,0 +1,85 @@
+# drop table t1 t2 t3 are included int master-slave.inc
+# meaningful only in statement-based:
+
+-- source include/have_binlog_format_mixed_or_statement.inc
+-- source include/master-slave.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
+
+create table t2 (n int, PRIMARY KEY(n));
+create temporary table t1 (n int);
+create temporary table t3 (n int not null);
+
+insert into t1 values(1),(2),(3),(100),(25),(26),(200),(300);
+--disable_warnings
+insert into t2 select * from t1;
+--enable_warnings
+alter table t3 add primary key(n);
+
+flush logs;
+insert into t3 values (1010);
+--disable_warnings
+insert into t2 select * from t3;
+--enable_warnings
+
+drop table if exists t3;
+insert into t2 values (1012);
+
+connection master1;
+create temporary table t1 (n int);
+insert into t1 values (4),(5);
+--disable_warnings
+insert into t2 select * from t1;
+--enable_warnings
+
+save_master_pos;
+disconnect master;
+
+connection slave;
+#add 1 to the saved position, so we will catch drop table on disconnect
+#for sure
+sync_with_master 1;
+
+connection master1;
+insert into t2 values(61);
+
+save_master_pos;
+disconnect master1;
+
+connection slave;
+#same trick - make sure we catch drop of temporary table on disconnect
+sync_with_master 1;
+
+select * from t2;
+select count(*) from t2;
+select sum(n) from t2;
+show status like 'Slave_open_temp_tables';
+
+--echo *** MDEV-8016: Replication aborts on DROP /*!40005 TEMPORARY */ TABLE IF EXISTS ***
+connect (master2,localhost,root,,);
+INSERT INTO t2 VALUES (2000), (2001);
+CREATE FUNCTION f() RETURNS INTEGER RETURN 1;
+CREATE TEMPORARY TABLE t3 AS SELECT f() AS col FROM t2;
+--let $gtid=`SELECT @@gtid_binlog_pos`
+--disconnect master2
+--connection default
+# Wait for implicit DROP TEMPORARY TABLE tmp to be binlogged.
+--let $wait_condition= SELECT @@gtid_binlog_pos != '$gtid'
+--source include/wait_condition.inc
+
+--sync_slave_with_master
+
+
+#
+# Clean up
+#
+connect (master2,localhost,root,,);
+connection master2;
+drop table if exists t1,t2;
+drop function f;
+sync_slave_with_master;
+
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_temp_table_mix_row.test b/mysql-test/suite/rpl/t/rpl_temp_table_mix_row.test
new file mode 100644
index 00000000..766acb14
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_temp_table_mix_row.test
@@ -0,0 +1,206 @@
+# ==== Purpose ====
+#
+# Test that temporary tables are correctly replicated after switching to ROW format in MIX mode.
+# This test case will test the condition of the bug#40013.
+# The test step is:
+# 1: create temp table on connection 'master';
+# 2: switch to ROW format using 'INSERT INTO t1 VALUES (SYS_GUID());'
+# 3: disconnect 'master' and connect to a new connection 'master1';
+# 4: sync to slave and check the number of temp tables on slave.
+#
+
+source include/have_binlog_format_mixed.inc;
+source include/have_innodb.inc;
+source include/master-slave.inc;
+
+--echo ==== Initialize ====
+
+--connection master
+
+CREATE TABLE t1 (a CHAR(48));
+CREATE TEMPORARY TABLE t1_tmp1(a INT);
+INSERT INTO t1 VALUES (SYS_GUID());
+
+sync_slave_with_master;
+
+--echo ==== Verify results on slave ====
+SHOW STATUS LIKE "Slave_open_temp_tables";
+
+--connection master
+
+disconnect master;
+--connection master1
+
+# waiting DROP TEMPORARY TABLE event to be written into binlog
+let $wait_binlog_event= DROP;
+source include/wait_for_binlog_event.inc;
+
+sync_slave_with_master;
+
+--echo ==== Verify results on slave ====
+SHOW STATUS LIKE "Slave_open_temp_tables";
+
+--echo ==== Clean up ====
+
+--let $rpl_connection_name= master
+--let $rpl_server_number= 1
+--source include/rpl_connect.inc
+--connection master
+DROP TABLE t1;
+
+sync_slave_with_master;
+
+#
+# BUG#43046: mixed mode switch to row format with temp table lead to wrong
+# result
+#
+# NOTES
+# =====
+#
+# 1. Temporary tables cannot be logged using the row-based
+# format. Thus, once row-based logging is used, all subsequent
+# statements using that table are unsafe, and we approximate this
+# condition by treating all statements made by that client as
+# unsafe until the client no longer holds any temporary tables.
+#
+# 2. Two different connections can use the same temporary table
+# name without conflicting with each other or with an
+# existing non-TEMPORARY table of the same name.
+#
+# DESCRIPTION
+# ===========
+#
+# The test is implemented as follows:
+# 1. create regular tables
+# 2. create a temporary table t1_tmp: should be logged as statement
+# 3. issue an alter table: should be logged as statement
+# 4. issue statement that forces switch to RBR
+# 5. create another temporary table t2_tmp: should not be logged
+# 6. issue alter table on t1_tmp: should not be logged
+# 7. drop t1_tmp and regular table on same statement: should log both in
+# statement format (but different statements)
+# 8. issue deterministic insert: logged as row (because t2_tmp still
+# exists).
+# 9. drop t2_tmp and issue deterministic statement: should log drop and
+# query in statement format (show switch back to STATEMENT format)
+# 10. in the end the slave should not have open temp tables.
+#
+
+--source include/rpl_reset.inc
+-- connection master
+
+# action: setup environment
+CREATE TABLE t1 (a int) engine=innodb;
+CREATE TABLE t2 ( i1 INT NOT NULL AUTO_INCREMENT, PRIMARY KEY (i1) )
+ engine=innodb;
+CREATE TABLE t3 ( i1 INT NOT NULL AUTO_INCREMENT, PRIMARY KEY (i1) );
+CREATE TRIGGER tr1 AFTER DELETE ON t2 FOR EACH ROW INSERT INTO t3 () VALUES ();
+
+# assertion: assert that CREATE is logged as STATEMENT
+CREATE TEMPORARY TABLE t1_tmp (i1 int);
+
+# assertion: assert that ALTER TABLE is logged as STATEMENT
+ALTER TABLE t1_tmp ADD COLUMN b INT;
+
+# action: force switch to RBR
+INSERT INTO t1 values(1);
+INSERT INTO t2 (i1) select * from t1;
+
+# assertion: assert that t2_tmp will not make into the binlog (RBR logging atm)
+CREATE TEMPORARY TABLE t2_tmp (a int);
+
+# assertion: assert that ALTER TABLE on t1_tmp will not make into the binlog
+ALTER TABLE t1_tmp ADD COLUMN c INT;
+
+-- echo ### assertion: assert that there is one open temp table on slave
+-- sync_slave_with_master
+SHOW STATUS LIKE 'Slave_open_temp_tables';
+
+-- connection master
+
+# assertion: assert that both drops are logged
+DROP TABLE t1_tmp, t2;
+
+# assertion: assert that statement is logged as row (master still has one
+# opened temporary table - t2_tmp.
+INSERT INTO t1 VALUES (1);
+
+# assertion: assert that DROP TABLE *is* logged despite CREATE is not.
+DROP TEMPORARY TABLE t2_tmp;
+
+# assertion: assert that statement is now logged as STMT (mixed mode switches
+# back to STATEMENT).
+INSERT INTO t1 VALUES (2);
+
+-- sync_slave_with_master
+
+-- echo ### assertion: assert that slave has no temporary tables opened
+SHOW STATUS LIKE 'Slave_open_temp_tables';
+
+-- connection master
+
+# action: drop remaining tables
+DROP TABLE t3, t1;
+
+-- sync_slave_with_master
+
+-- source include/show_binlog_events.inc
+
+--echo
+--echo # Bug#55478 Row events wrongly apply on the temporary table of the same name
+--echo # ==========================================================================
+connection master;
+
+let $binlog_file= query_get_value(SHOW MASTER STATUS, File, 1);
+let $binlog_start= query_get_value(SHOW MASTER STATUS, Position, 1);
+
+--echo # The statement should be binlogged
+CREATE TEMPORARY TABLE t1(c1 INT) ENGINE=InnoDB;
+
+--echo
+--echo # Case 1: CREATE TABLE t1 ... SELECT
+--echo # ----------------------------------
+let $binlog_file= query_get_value(SHOW MASTER STATUS, File, 1);
+let $binlog_start= query_get_value(SHOW MASTER STATUS, Position, 1);
+
+--echo
+--echo # The statement generates row events on t1. And the rows events should
+--echo # be inserted into the base table on slave.
+CREATE TABLE t1 ENGINE=MyISAM SELECT rand();
+
+source include/show_binlog_events.inc;
+let $binlog_file= query_get_value(SHOW MASTER STATUS, File, 1);
+let $binlog_start= query_get_value(SHOW MASTER STATUS, Position, 1);
+
+--echo
+--echo # Case 2: DROP TEMPORARY TABLE in a transacation
+--echo # ----------------------------------------------
+--echo
+
+BEGIN;
+DROP TEMPORARY TABLE t1;
+
+# The patch for BUG#55478 fixed the problem only on RBR. The problem on SBR
+# will be fixed by the patch for bug#55709. So This statement cannot be
+# executed until Bug#55709 is fixed
+#
+# INSERT INTO t1 VALUES(1);
+
+--echo # The rows event will binlogged after 'INSERT INTO t1 VALUES(1)'
+--disable_warnings
+INSERT IGNORE INTO t1 VALUES(SYS_GUID()+0);
+--enable_warnings
+COMMIT;
+
+source include/show_binlog_events.inc;
+
+--sync_slave_with_master
+
+--echo # Compare the base table.
+--let $diff_tables= master:t1, slave:t1
+--source include/diff_tables.inc
+
+--echo
+connection master;
+DROP TABLE t1;
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_temporal_format_default_to_default.test b/mysql-test/suite/rpl/t/rpl_temporal_format_default_to_default.test
new file mode 100644
index 00000000..6728ff55
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_temporal_format_default_to_default.test
@@ -0,0 +1,82 @@
+#
+# This include file is used by more than one test suite
+# (currently rpl and binlog_encryption).
+# Please check all dependent tests after modifying it
+#
+
+--source include/master-slave.inc
+
+if ($force_master_mysql56_temporal_format)
+{
+ connection master;
+ eval SET @@global.mysql56_temporal_format=$force_master_mysql56_temporal_format;
+}
+
+if ($force_slave_mysql56_temporal_format)
+{
+ connection slave;
+ eval SET @@global.mysql56_temporal_format=$force_slave_mysql56_temporal_format;
+}
+
+connection master;
+SELECT @@global.mysql56_temporal_format AS on_master;
+connection slave;
+SELECT @@global.mysql56_temporal_format AS on_slave;
+connection master;
+
+CREATE TABLE t1
+(
+ c0 TIME(0),
+ c1 TIME(1),
+ c2 TIME(2),
+ c3 TIME(3),
+ c4 TIME(4),
+ c5 TIME(5),
+ c6 TIME(6)
+);
+CREATE TABLE t2
+(
+ c0 TIMESTAMP(0),
+ c1 TIMESTAMP(1),
+ c2 TIMESTAMP(2),
+ c3 TIMESTAMP(3),
+ c4 TIMESTAMP(4),
+ c5 TIMESTAMP(5),
+ c6 TIMESTAMP(6)
+);
+
+CREATE TABLE t3
+(
+ c0 DATETIME(0),
+ c1 DATETIME(1),
+ c2 DATETIME(2),
+ c3 DATETIME(3),
+ c4 DATETIME(4),
+ c5 DATETIME(5),
+ c6 DATETIME(6)
+);
+INSERT INTO t1 VALUES ('01:01:01','01:01:01.1','01:01:01.11','01:01:01.111','01:01:01.1111','01:01:01.11111','01:01:01.111111');
+INSERT INTO t2 VALUES ('2001-01-01 01:01:01','2001-01-01 01:01:01.1','2001-01-01 01:01:01.11','2001-01-01 01:01:01.111','2001-01-01 01:01:01.1111','2001-01-01 01:01:01.11111','2001-01-01 01:01:01.111111');
+INSERT INTO t3 VALUES ('2001-01-01 01:01:01','2001-01-01 01:01:01.1','2001-01-01 01:01:01.11','2001-01-01 01:01:01.111','2001-01-01 01:01:01.1111','2001-01-01 01:01:01.11111','2001-01-01 01:01:01.111111');
+SELECT TABLE_NAME, TABLE_ROWS, AVG_ROW_LENGTH,DATA_LENGTH FROM INFORMATION_SCHEMA.TABLES
+WHERE TABLE_NAME RLIKE 't[1-3]' ORDER BY TABLE_NAME;
+sync_slave_with_master;
+
+connection slave;
+--query_vertical SELECT * FROM t1;
+--query_vertical SELECT * FROM t2;
+--query_vertical SELECT * FROM t3;
+SELECT TABLE_NAME, TABLE_ROWS, AVG_ROW_LENGTH,DATA_LENGTH FROM INFORMATION_SCHEMA.TABLES
+WHERE TABLE_NAME RLIKE 't[1-3]' ORDER BY TABLE_NAME;
+
+connection master;
+DROP TABLE t1;
+DROP TABLE t2;
+DROP TABLE t3;
+
+connection slave;
+SET @@global.mysql56_temporal_format=DEFAULT;
+connection master;
+SET @@global.mysql56_temporal_format=DEFAULT;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_temporal_format_mariadb53_to_mariadb53.test b/mysql-test/suite/rpl/t/rpl_temporal_format_mariadb53_to_mariadb53.test
new file mode 100644
index 00000000..058ad017
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_temporal_format_mariadb53_to_mariadb53.test
@@ -0,0 +1,4 @@
+--let $force_master_mysql56_temporal_format=false;
+--let $force_slave_mysql56_temporal_format=false;
+
+--source rpl_temporal_format_default_to_default.test
diff --git a/mysql-test/suite/rpl/t/rpl_temporal_format_mariadb53_to_mysql56.test b/mysql-test/suite/rpl/t/rpl_temporal_format_mariadb53_to_mysql56.test
new file mode 100644
index 00000000..547b0831
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_temporal_format_mariadb53_to_mysql56.test
@@ -0,0 +1,14 @@
+#
+# MariaDB-5.3 fractional temporal types do not store metadata
+# when running with --binlog-format=row, thus can replicate
+# only into a field with exactly the same data type and format.
+#
+# Skip when running with --binlog-format=row.
+# But mixed and statement formats should work without problems.
+#
+-- source include/have_binlog_format_mixed_or_statement.inc
+
+--let $force_master_mysql56_temporal_format=false;
+--let $force_slave_mysql56_temporal_format=true;
+
+--source rpl_temporal_format_default_to_default.test
diff --git a/mysql-test/suite/rpl/t/rpl_temporal_format_mariadb53_to_mysql56_dst.test b/mysql-test/suite/rpl/t/rpl_temporal_format_mariadb53_to_mysql56_dst.test
new file mode 100644
index 00000000..511bdc15
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_temporal_format_mariadb53_to_mysql56_dst.test
@@ -0,0 +1,37 @@
+#
+# MDEV-12672 Replicated TIMESTAMP fields given wrong value near DST change
+#
+source include/have_binlog_format_row.inc;
+source include/master-slave.inc;
+
+connection slave;
+set global time_zone='Europe/Moscow';
+set time_zone='UTC';
+stop slave;
+start slave;
+
+connection master;
+set global mysql56_temporal_format=false;
+set global time_zone='Europe/Moscow';
+set time_zone='UTC';
+
+create table t1 (pk int primary key, t timestamp not null);
+set timestamp = 1288477526;
+insert into t1 values (1,null);
+set timestamp = 1288481126;
+insert into t1 values (2,null);
+
+sync_slave_with_master;
+
+select pk, t, unix_timestamp(t) from t1;
+set time_zone=default;
+select pk, t, unix_timestamp(t) from t1;
+
+set global time_zone=default;
+
+connection master;
+drop table t1;
+set global time_zone=default;
+set global mysql56_temporal_format=default;
+
+source include/rpl_end.inc;
diff --git a/mysql-test/suite/rpl/t/rpl_temporal_format_mysql56_to_mariadb53.test b/mysql-test/suite/rpl/t/rpl_temporal_format_mysql56_to_mariadb53.test
new file mode 100644
index 00000000..dbee9f05
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_temporal_format_mysql56_to_mariadb53.test
@@ -0,0 +1,4 @@
+--let $force_master_mysql56_temporal_format=true;
+--let $force_slave_mysql56_temporal_format=false;
+
+--source rpl_temporal_format_default_to_default.test
diff --git a/mysql-test/suite/rpl/t/rpl_temporal_format_mysql56_to_mysql56.test b/mysql-test/suite/rpl/t/rpl_temporal_format_mysql56_to_mysql56.test
new file mode 100644
index 00000000..9c7994b6
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_temporal_format_mysql56_to_mysql56.test
@@ -0,0 +1,4 @@
+--let $force_master_mysql56_temporal_format=true;
+--let $force_slave_mysql56_temporal_format=true;
+
+--source rpl_temporal_format_default_to_default.test
diff --git a/mysql-test/suite/rpl/t/rpl_temporal_mysql56.test b/mysql-test/suite/rpl/t/rpl_temporal_mysql56.test
new file mode 100644
index 00000000..f21f125b
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_temporal_mysql56.test
@@ -0,0 +1,48 @@
+--source include/master-slave.inc
+
+connection master;
+SET TIME_ZONE='+00:00';
+let $MYSQLD_MASTER_DATADIR= `select @@datadir`;
+
+connection slave;
+SET TIME_ZONE='+00:00';
+let $MYSQLD_SLAVE_DATADIR= `select @@datadir`;
+
+--copy_file std_data/mysql56time.frm $MYSQLD_MASTER_DATADIR/test/mysql56time.frm
+--copy_file std_data/mysql56time.MYD $MYSQLD_MASTER_DATADIR/test/mysql56time.MYD
+--copy_file std_data/mysql56time.MYI $MYSQLD_MASTER_DATADIR/test/mysql56time.MYI
+--copy_file std_data/mysql56time.frm $MYSQLD_SLAVE_DATADIR/test/mysql56time.frm
+--copy_file std_data/mysql56time.MYD $MYSQLD_SLAVE_DATADIR/test/mysql56time.MYD
+--copy_file std_data/mysql56time.MYI $MYSQLD_SLAVE_DATADIR/test/mysql56time.MYI
+
+--copy_file std_data/mysql56datetime.frm $MYSQLD_MASTER_DATADIR/test/mysql56datetime.frm
+--copy_file std_data/mysql56datetime.MYD $MYSQLD_MASTER_DATADIR/test/mysql56datetime.MYD
+--copy_file std_data/mysql56datetime.MYI $MYSQLD_MASTER_DATADIR/test/mysql56datetime.MYI
+--copy_file std_data/mysql56datetime.frm $MYSQLD_SLAVE_DATADIR/test/mysql56datetime.frm
+--copy_file std_data/mysql56datetime.MYD $MYSQLD_SLAVE_DATADIR/test/mysql56datetime.MYD
+--copy_file std_data/mysql56datetime.MYI $MYSQLD_SLAVE_DATADIR/test/mysql56datetime.MYI
+
+--copy_file std_data/mysql56timestamp.frm $MYSQLD_MASTER_DATADIR/test/mysql56timestamp.frm
+--copy_file std_data/mysql56timestamp.MYD $MYSQLD_MASTER_DATADIR/test/mysql56timestamp.MYD
+--copy_file std_data/mysql56timestamp.MYI $MYSQLD_MASTER_DATADIR/test/mysql56timestamp.MYI
+--copy_file std_data/mysql56timestamp.frm $MYSQLD_SLAVE_DATADIR/test/mysql56timestamp.frm
+--copy_file std_data/mysql56timestamp.MYD $MYSQLD_SLAVE_DATADIR/test/mysql56timestamp.MYD
+--copy_file std_data/mysql56timestamp.MYI $MYSQLD_SLAVE_DATADIR/test/mysql56timestamp.MYI
+
+connection master;
+INSERT INTO mysql56time VALUES ('01:01:01','01:01:01.1','01:01:01.11','01:01:01.111','01:01:01.1111','01:01:01.11111','01:01:01.111111');
+INSERT INTO mysql56datetime VALUES ('2001-01-01 01:01:01','2001-01-01 01:01:01.1','2001-01-01 01:01:01.11','2001-01-01 01:01:01.111','2001-01-01 01:01:01.1111','2001-01-01 01:01:01.11111','2001-01-01 01:01:01.111111');
+INSERT INTO mysql56timestamp VALUES ('2001-01-01 01:01:01','2001-01-01 01:01:01.1','2001-01-01 01:01:01.11','2001-01-01 01:01:01.111','2001-01-01 01:01:01.1111','2001-01-01 01:01:01.11111','2001-01-01 01:01:01.111111');
+sync_slave_with_master;
+
+connection slave;
+--query_vertical SELECT * FROM mysql56time
+--query_vertical SELECT * FROM mysql56datetime
+--query_vertical SELECT * FROM mysql56timestamp
+
+connection master;
+DROP TABLE mysql56time;
+DROP TABLE mysql56datetime;
+DROP TABLE mysql56timestamp;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_temporal_mysql56_to_mariadb.test b/mysql-test/suite/rpl/t/rpl_temporal_mysql56_to_mariadb.test
new file mode 100644
index 00000000..efbff934
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_temporal_mysql56_to_mariadb.test
@@ -0,0 +1,55 @@
+--source include/master-slave.inc
+
+if ($force_slave_mysql56_temporal_format)
+{
+ connection slave;
+ eval SET @@global.mysql56_temporal_format=$force_slave_mysql56_temporal_format;
+ connection master;
+}
+
+
+--echo #
+--echo # Testing replication from MariaDB-10.0 master
+--echo # started over MySQL-5.6 data directory
+--echo # to MariaDB-10.0 slave running with natively created tables
+--echo #
+
+connection master;
+SET TIME_ZONE='+00:00';
+let $MYSQLD_MASTER_DATADIR= `select @@datadir`;
+
+--copy_file std_data/temporal_upgrade/mysql050614_temporal0.frm $MYSQLD_MASTER_DATADIR/test/mysql050614_temporal0.frm
+--copy_file std_data/temporal_upgrade/mysql050614_temporal0.MYD $MYSQLD_MASTER_DATADIR/test/mysql050614_temporal0.MYD
+--copy_file std_data/temporal_upgrade/mysql050614_temporal0.MYI $MYSQLD_MASTER_DATADIR/test/mysql050614_temporal0.MYI
+
+--copy_file std_data/temporal_upgrade/mysql050614_temporal1.frm $MYSQLD_MASTER_DATADIR/test/mysql050614_temporal1.frm
+--copy_file std_data/temporal_upgrade/mysql050614_temporal1.MYD $MYSQLD_MASTER_DATADIR/test/mysql050614_temporal1.MYD
+--copy_file std_data/temporal_upgrade/mysql050614_temporal1.MYI $MYSQLD_MASTER_DATADIR/test/mysql050614_temporal1.MYI
+SHOW CREATE TABLE mysql050614_temporal0;
+SHOW CREATE TABLE mysql050614_temporal1;
+
+connection slave;
+SELECT @@mysql56_temporal_format;
+SET TIME_ZONE='+00:00';
+CREATE TABLE mysql050614_temporal0 (a time(0), b datetime(0), c timestamp(0)) engine=myisam;
+CREATE TABLE mysql050614_temporal1 (a time(1), b datetime(1), c timestamp(1)) engine=myisam;
+
+connection master;
+INSERT INTO mysql050614_temporal0 VALUES ('00:00:02','2001-01-01 00:00:02','2001-01-01 00:00:02');
+INSERT INTO mysql050614_temporal1 VALUES ('00:00:02.1','2001-01-01 00:00:02.2','2001-01-01 00:00:02.3');
+SELECT TABLE_NAME, TABLE_ROWS, AVG_ROW_LENGTH, DATA_LENGTH FROM INFORMATION_SCHEMA.TABLES
+WHERE TABLE_NAME LIKE 'mysql050614_temporal%' ORDER BY TABLE_NAME;
+sync_slave_with_master;
+
+connection slave;
+SELECT * FROM mysql050614_temporal0;
+SELECT * FROM mysql050614_temporal1;
+SELECT TABLE_NAME, TABLE_ROWS, AVG_ROW_LENGTH,DATA_LENGTH FROM INFORMATION_SCHEMA.TABLES
+WHERE TABLE_NAME LIKE 'mysql050614_temporal%' ORDER BY TABLE_NAME;
+SET @@global.mysql56_temporal_format=DEFAULT;
+
+connection master;
+DROP TABLE mysql050614_temporal0;
+DROP TABLE mysql050614_temporal1;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_temporal_mysql56_to_mariadb53.test b/mysql-test/suite/rpl/t/rpl_temporal_mysql56_to_mariadb53.test
new file mode 100644
index 00000000..435dad57
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_temporal_mysql56_to_mariadb53.test
@@ -0,0 +1,2 @@
+--let $force_slave_mysql56_temporal_format=false;
+--source rpl_temporal_mysql56_to_mariadb.test
diff --git a/mysql-test/suite/rpl/t/rpl_temporal_round.test b/mysql-test/suite/rpl/t/rpl_temporal_round.test
new file mode 100644
index 00000000..c13c18bd
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_temporal_round.test
@@ -0,0 +1,35 @@
+--source include/master-slave.inc
+
+SET sql_mode=TIME_ROUND_FRACTIONAL;
+SET time_zone='+00:00';
+SET timestamp=UNIX_TIMESTAMP('2010-12-31 23:59:59.999999');
+
+CREATE TABLE t1 (id SERIAL, a TIMESTAMP(4));
+INSERT INTO t1 (a) VALUES (now(6));
+INSERT INTO t1 (a) VALUES ('2011-01-01 23:59:59.999999');
+
+CREATE TABLE t2 (id SERIAL, a DATETIME(4));
+INSERT INTO t2 (a) VALUES (now(6));
+INSERT INTO t2 (a) VALUES ('2011-01-01 23:59:59.999999');
+
+CREATE TABLE t3 (id SERIAL, a TIME(4));
+INSERT INTO t3 (a) VALUES (now(6));
+INSERT INTO t3 (a) VALUES ('2011-01-01 23:59:59.999999');
+
+SELECT * FROM t1;
+SELECT * FROM t2;
+SELECT * FROM t3;
+
+sync_slave_with_master;
+connection slave;
+SET time_zone='+00:00';
+SELECT * FROM t1;
+SELECT * FROM t2;
+SELECT * FROM t3;
+
+connection master;
+DROP TABLE t1;
+DROP TABLE t2;
+DROP TABLE t3;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_temporary.test b/mysql-test/suite/rpl/t/rpl_temporary.test
new file mode 100644
index 00000000..0ec57715
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_temporary.test
@@ -0,0 +1,420 @@
+# Test need anonymous user when connection are made as "zedjzlcsjhd"
+# But we only need it on the master, not the slave.
+SET sql_log_bin = 0;
+source include/add_anonymous_users.inc;
+SET sql_log_bin = 1;
+
+-- source include/master-slave.inc
+
+# Clean up old slave's binlogs.
+# The slave is started with --log-slave-updates
+# and this test does SHOW BINLOG EVENTS on the slave's
+# binlog. But previous tests can influence the current test's
+# binlog (e.g. a temporary table in the previous test has not
+# been explicitly deleted, or it has but the slave hasn't had
+# enough time to catch it before STOP SLAVE,
+# and at the beginning of the current
+# test the slave immediately writes DROP TEMPORARY TABLE this_old_table).
+# We wait for the slave to have written all he wants to the binlog
+# (otherwise RESET MASTER may come too early).
+save_master_pos;
+connection slave;
+
+sync_with_master;
+reset master;
+
+# ##################################################################
+# BUG#41725: slave crashes when inserting into temporary table after
+# stop/start slave
+#
+# This test checks that both reported issues (assertion failure and
+# crash) go away. It is implemented as follows:
+#
+# case 1: assertion failure
+# i) create and insert into temporary table on master
+# ii) sync slave with master
+# iii) stop and restart slave
+# iv) insert into master another value
+# v) sync slave with master
+#
+#
+# case 2: crash (SIGSEV)
+# i) create and insert into temporary table on master (insert
+# produces warnings)
+# ii) sync slave with master
+# iii) stop and restart slave
+# iv) insert into master more values
+# v) sync slave with master
+
+# case 1: Assertion in Field_string::store() failed because current
+# thread reference differed from table->in_use after slave
+# restart
+
+connection 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
+
+disable_warnings;
+DROP TABLE IF EXISTS t1;
+enable_warnings;
+
+CREATE TEMPORARY TABLE t1 (a char(1));
+INSERT INTO t1 VALUES ('a');
+sync_slave_with_master;
+
+source include/stop_slave.inc;
+source include/start_slave.inc;
+
+connection master;
+INSERT INTO t1 VALUES ('b');
+sync_slave_with_master;
+
+# case 2: crash on sp_rcontext::find_handler because it used
+# reference to invalid THD object after slave restart
+
+connection master;
+
+disable_warnings;
+DROP TABLE IF EXISTS t1;
+enable_warnings;
+CREATE TEMPORARY TABLE `t1`(`a` tinyint,`b` char(1))engine=myisam;
+INSERT IGNORE INTO `t1` set `a`=128,`b`='128';
+
+sync_slave_with_master;
+
+source include/stop_slave.inc;
+source include/start_slave.inc;
+
+connection master;
+INSERT IGNORE INTO `t1` set `a`=128,`b`='128';
+sync_slave_with_master;
+
+# cleanup
+
+connection master;
+DROP TABLE t1;
+sync_slave_with_master;
+
+connection master;
+
+create user zedjzlcsjhd@localhost;
+GRANT ALL on test.* to zedjzlcsjhd@localhost;
+
+connect (con1,localhost,root,,);
+connect (con2,localhost,root,,);
+# We want to connect as an unprivileged user. But if we use user="" then this
+# will pick the Unix login, which will cause problems if you're running the test
+# as root.
+connect (con3,localhost,zedjzlcsjhd,,);
+
+# We are going to use SET PSEUDO_THREAD_ID in this test;
+# check that it requires the SUPER privilege.
+
+connection con3;
+SET @save_select_limit=@@session.sql_select_limit;
+--error 1227
+SET @@session.sql_select_limit=10, @@session.pseudo_thread_id=100;
+SELECT @@session.sql_select_limit = @save_select_limit; #shouldn't have changed
+# While we are here we also test that SQL_LOG_BIN can't be set
+--error 1227
+SET @@session.sql_select_limit=10, @@session.sql_log_bin=0;
+SELECT @@session.sql_select_limit = @save_select_limit; #shouldn't have changed
+# Now as root, to be sure it works
+connection con2;
+SET @save_conn_id= connection_id();
+SET @@session.pseudo_thread_id=100;
+SET @@session.pseudo_thread_id=connection_id();
+SET @@session.pseudo_thread_id=@save_conn_id;
+SET @@session.sql_log_bin=0;
+SET @@session.sql_log_bin=1;
+
+connection con3;
+let $VERSION=`select version()`;
+
+--disable_warnings
+drop table if exists t1,t2;
+--enable_warnings
+
+create table t1(f int);
+create table t2(f int);
+insert into t1 values (1),(2),(3),(4),(5),(6),(7),(8),(9),(10);
+# Auxiliary select (We want that all rows are in the table)
+SELECT COUNT(*) FROM t1;
+
+connection con1;
+create temporary table t3(f int);
+--disable_warnings
+insert into t3 select * from t1 where f<6;
+--enable_warnings
+let $wait_condition= SELECT COUNT(*) = 5 FROM t3;
+--source include/wait_condition.inc
+
+connection con2;
+create temporary table t3(f int);
+
+connection con1;
+--disable_warnings
+insert into t2 select count(*) from t3;
+--enable_warnings
+let $wait_condition= SELECT COUNT(*) = 1 FROM t2;
+--source include/wait_condition.inc
+
+connection con2;
+--disable_warnings
+insert into t3 select * from t1 where f>=4;
+--enable_warnings
+let $wait_condition= SELECT COUNT(*) = 7 FROM t3;
+--source include/wait_condition.inc
+
+connection con1;
+drop temporary table t3;
+
+connection con2;
+--disable_warnings
+insert into t2 select count(*) from t3;
+--enable_warnings
+drop temporary table t3;
+
+select * from t2 ORDER BY f;
+
+# Commented out 8/30/2005 to make compatable with both sbr and rbr
+#--replace_result $VERSION VERSION
+#--replace_column 2 # 5 #
+#show binlog events;
+
+drop table t1, t2;
+drop user zedjzlcsjhd@localhost;
+
+use test;
+SET TIMESTAMP=1040323920;
+create table t1(f int);
+SET TIMESTAMP=1040323931;
+create table t2(f int);
+SET TIMESTAMP=1040323938;
+insert into t1 values (1),(2),(3),(4),(5),(6),(7),(8),(9),(10);
+
+SET TIMESTAMP=1040323945;
+SET @@session.pseudo_thread_id=1;
+create temporary table t3(f int);
+SET TIMESTAMP=1040323952;
+SET @@session.pseudo_thread_id=1;
+--disable_warnings
+insert into t3 select * from t1 where f<6;
+--enable_warnings
+SET TIMESTAMP=1040324145;
+SET @@session.pseudo_thread_id=2;
+create temporary table t3(f int);
+SET TIMESTAMP=1040324186;
+SET @@session.pseudo_thread_id=1;
+--disable_warnings
+insert into t2 select count(*) from t3;
+--enable_warnings
+SET TIMESTAMP=1040324200;
+SET @@session.pseudo_thread_id=2;
+--disable_warnings
+insert into t3 select * from t1 where f>=4;
+--enable_warnings
+SET TIMESTAMP=1040324211;
+SET @@session.pseudo_thread_id=1;
+drop temporary table t3;
+SET TIMESTAMP=1040324219;
+SET @@session.pseudo_thread_id=2;
+--disable_warnings
+insert into t2 select count(*) from t3;
+--enable_warnings
+SET TIMESTAMP=1040324224;
+SET @@session.pseudo_thread_id=2;
+drop temporary table t3;
+
+select * from t2 ORDER BY f;
+drop table t1,t2;
+
+# Create last a temporary table that is not dropped at end to ensure that we
+# don't get any memory leaks for this
+
+create temporary table t3 (f int);
+sync_slave_with_master;
+
+# The server will now close done
+
+#
+# Bug#17284 erroneous temp table cleanup on slave
+# The test targets at verifying that reconnected slave
+# retained the former session's temporary tables
+#
+connection master;
+create temporary table t4 (f int);
+create table t5 (f int);
+sync_slave_with_master;
+# connection slave
+stop slave; # to prepare for reconnecting w/o waiting for timeout
+connection master;
+--disable_warnings
+insert into t5 select * from t4;
+--enable_warnings
+save_master_pos;
+
+connection slave;
+start slave;
+sync_with_master;
+select * from t5 /* must be 1 after reconnection */;
+
+connection master;
+drop temporary table t4;
+drop table t5;
+
+#
+# BUG#17263 incorrect generation DROP temp tables
+# Temporary tables of connection are dropped in batches
+# where a batch correspond to pseudo_thread_id
+# value was set up at the moment of temp table creation
+#
+connection con1;
+set @@session.pseudo_thread_id=100;
+create temporary table t101 (id int);
+create temporary table t102 (id int);
+set @@session.pseudo_thread_id=200;
+create temporary table t201 (id int);
+create temporary table `t``201` (id int);
+# emulate internal temp table not to come to binlog
+create temporary table `#sql_not_user_table202` (id int);
+set @@session.pseudo_thread_id=300;
+create temporary table t301 (id int);
+create temporary table t302 (id int);
+create temporary table `#sql_not_user_table303` (id int);
+disconnect con1;
+
+#now do something to show that slave is ok after DROP temp tables
+connection master;
+create table t1(f int);
+insert into t1 values (1);
+
+sync_slave_with_master;
+#connection slave;
+select * from t1 /* must be 1 */;
+
+connection master;
+drop table t1;
+
+#
+#14157: utf8 encoding in binlog without set character_set_client
+#
+--write_file $MYSQLTEST_VARDIR/tmp/bug14157.sql
+create table t1 (a int);
+set names latin1;
+create temporary table `äöüÄÖÜ` (a int);
+insert into `äöüÄÖÜ` values (1);
+insert into t1 select * from `äöüÄÖÜ`
+EOF
+--exec $MYSQL --character-sets-dir=../sql/share/charsets/ --default-character-set=latin1 test < $MYSQLTEST_VARDIR/tmp/bug14157.sql
+
+sync_slave_with_master;
+#connection slave;
+select * from t1;
+
+connection master;
+drop table t1;
+--remove_file $MYSQLTEST_VARDIR/tmp/bug14157.sql
+
+--sync_slave_with_master
+
+# Delete the anonymous users.
+--source include/stop_slave.inc
+source include/delete_anonymous_users.inc;
+--connection master
+source include/delete_anonymous_users.inc;
+--let $rpl_only_running_threads= 1
+--source include/rpl_reset.inc
+
+
+#
+# Bug#43748: crash when non-super user tries to kill the replication threads
+#
+
+--echo -- Bug#43748
+
+--echo -- make a user on the slave that can list but not kill system threads.
+connection slave;
+
+FLUSH PRIVILEGES;
+GRANT USAGE ON *.* TO user43748@127.0.0.1 IDENTIFIED BY 'meow';
+GRANT PROCESS ON *.* TO user43748@127.0.0.1;
+
+--echo -- try to KILL system-thread as that non-privileged user (on slave).
+connect (cont43748,127.0.0.1,user43748,meow,"*NO-ONE*",$SLAVE_MYPORT,);
+connection cont43748;
+
+SELECT id INTO @id FROM information_schema.processlist WHERE user='system user' LIMIT 1;
+
+--error ER_KILL_DENIED_ERROR,ER_NO_SUCH_THREAD
+KILL @id;
+
+disconnect cont43748;
+
+--echo -- throw out test-user on slave.
+connection slave;
+
+DROP USER user43748@127.0.0.1;
+
+--echo #
+--echo # MDEV-10216: Assertion `strcmp(share->unique_file_name,filename) ||
+--echo # share->last_version' failed in myisam/mi_open.c:67: test_if_reopen
+--echo #
+
+connection master;
+CREATE TEMPORARY TABLE t1(i INT PRIMARY KEY) ENGINE=MYISAM;
+INSERT INTO t1 VALUES(1);
+SELECT COUNT(*)=1 FROM t1;
+
+ALTER TABLE t1 RENAME t2;
+SELECT COUNT(*)=1 FROM t2;
+ALTER TABLE t2 RENAME t1;
+
+ALTER TABLE t1 DISABLE KEYS;
+ALTER TABLE t1 ENABLE KEYS;
+
+# LOCK TABLES is ignored for temporary tables.
+LOCK TABLES t1 WRITE;
+ALTER TABLE t1 RENAME t2;
+SELECT COUNT(*)=1 FROM t2;
+ALTER TABLE t2 RENAME t1;
+ALTER TABLE t1 DISABLE KEYS;
+ALTER TABLE t1 ENABLE KEYS;
+UNLOCK TABLES;
+
+LOCK TABLES t1 READ;
+ALTER TABLE t1 RENAME t2;
+SELECT COUNT(*)=1 FROM t2;
+ALTER TABLE t2 RENAME t1;
+ALTER TABLE t1 DISABLE KEYS;
+ALTER TABLE t1 ENABLE KEYS;
+UNLOCK TABLES;
+
+FLUSH TABLES WITH READ LOCK;
+ALTER TABLE t1 RENAME t2;
+SELECT COUNT(*)=1 FROM t2;
+ALTER TABLE t2 RENAME t1;
+ALTER TABLE t1 DISABLE KEYS;
+ALTER TABLE t1 ENABLE KEYS;
+UNLOCK TABLES;
+
+ALTER TABLE t1 RENAME t2, LOCK SHARED;
+ALTER TABLE t2 RENAME t1, LOCK EXCLUSIVE;
+
+DROP TABLE t1;
+
+--echo #
+--echo # MDEV-10320: NO-OP ALTER TABLE on temporary tables getting logged
+--echo # under row binlog format
+--echo #
+connection master;
+CREATE TEMPORARY TABLE t1(i INT PRIMARY KEY) ENGINE=MYISAM;
+ALTER TABLE t1;
+ALTER TABLE t1 ADD COLUMN IF NOT EXISTS I INT;
+DROP TABLE t1;
+
+--echo End of 5.1 tests
+--let $rpl_only_running_threads= 1
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_temporary_error2.test b/mysql-test/suite/rpl/t/rpl_temporary_error2.test
new file mode 100644
index 00000000..49194c5d
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_temporary_error2.test
@@ -0,0 +1,79 @@
+--source include/have_innodb.inc
+--source include/master-slave.inc
+
+call mtr.add_suppression("Deadlock found when trying to get lock; try restarting transaction");
+
+--echo *** Provoke a deadlock on the slave, check that transaction retry succeeds. ***
+--connection master
+CREATE TABLE t1 (a INT PRIMARY KEY, b INT) ENGINE=InnoDB;
+CREATE TABLE t2 (a INT) ENGINE=InnoDB;
+INSERT INTO t1(a) VALUES (1), (2), (3), (4), (5);
+
+--sync_slave_with_master
+SELECT * FROM t1 ORDER BY a;
+# Use MyISAM for t2 on the slave, so we have a way to see how far the
+# slave replication thread has proceeded in the transaction.
+SET sql_log_bin=0;
+ALTER TABLE t2 ENGINE=MyISAM;
+SET sql_log_bin=1;
+let $old_retry= query_get_value(SHOW STATUS LIKE 'Slave_retried_transactions', Value, 1);
+
+# Setup a separate connection that can deadlock with the replication thread.
+# Docs say that InnoDB will try to roll back the smaller transaction. So
+# let us make this transaction a big one, so the one in the replication
+# thread will be selected for rollback and retry.
+--connect (con_temp1,127.0.0.1,root,,test,$SERVER_MYPORT_2,)
+--connection con_temp1
+BEGIN;
+UPDATE t1 SET b=2 WHERE a=4;
+--disable_query_log
+--let $count=200
+while ($count)
+{
+ eval INSERT INTO t1(a) VALUES ($count + 10);
+ dec $count;
+}
+--enable_query_log
+# Note that InnoDB also (undocumented?) tries to avoid rolling back a
+# "transaction" that modified non-transactional tables. So be sure to also
+# touch the MyISAM table in this transaction.
+INSERT INTO t2 VALUES (2);
+DELETE FROM t2 WHERE a=2;
+
+# Create the transaction that should participate in the deadlock on the slave.
+--connection master
+BEGIN;
+UPDATE t1 SET b=1 WHERE a=2;
+INSERT INTO t2 VALUES (1);
+UPDATE t1 SET b=1 WHERE a=4;
+COMMIT;
+--save_master_pos
+
+--connection slave
+# Wait until replication thread has gone to wait on the a=4 row lock.
+--let $wait_condition= SELECT COUNT(*) = 1 FROM t2 WHERE a=1
+--source include/wait_condition.inc
+
+# Now provoke the deadlock by waiting on the a=2 row lock while the
+# other thread is waiting for our a=4 row lock.
+--connection con_temp1
+UPDATE t1 SET b=2 WHERE a=2;
+SELECT * FROM t1 WHERE a<10 ORDER BY a;
+ROLLBACK;
+
+--connection slave
+--sync_with_master
+SELECT * FROM t1 ORDER BY a;
+--echo * There will be two rows in t2 due to the retry.
+SELECT * FROM t2 ORDER BY a;
+let $new_retry= query_get_value(SHOW STATUS LIKE 'Slave_retried_transactions', Value, 1);
+--disable_query_log
+eval SELECT $new_retry - $old_retry AS retries;
+--enable_query_log
+--let $status_items= Last_SQL_Errno, Last_SQL_Error
+--source include/show_slave_status.inc
+
+--connection master
+DROP TABLE t1;
+DROP TABLE t2;
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_temporary_errors-slave.opt b/mysql-test/suite/rpl/t/rpl_temporary_errors-slave.opt
new file mode 100644
index 00000000..5c5164c6
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_temporary_errors-slave.opt
@@ -0,0 +1 @@
+--loose-debug-dbug="+d,all_errors_are_temporary_errors" --slave-transaction-retries=2
diff --git a/mysql-test/suite/rpl/t/rpl_temporary_errors.test b/mysql-test/suite/rpl/t/rpl_temporary_errors.test
new file mode 100644
index 00000000..85e16afa
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_temporary_errors.test
@@ -0,0 +1,116 @@
+source include/have_binlog_format_row.inc;
+source include/have_innodb.inc;
+source include/master-slave.inc;
+
+call mtr.add_suppression("Deadlock found");
+call mtr.add_suppression("Can't find record in 't.'");
+
+connection master;
+CREATE TABLE t1 (a INT PRIMARY KEY, b INT) ENGINE=innodb;
+INSERT INTO t1 VALUES (1,1), (2,2), (3,3), (4,4);
+sync_slave_with_master;
+SHOW STATUS LIKE 'Slave_retried_transactions';
+# since bug#31552/31609 idempotency is not default any longer. In order
+# the following UPDATE t1 to pass the mode is switched temprorarily
+set @@global.slave_exec_mode= 'IDEMPOTENT';
+UPDATE t1 SET a = 5, b = 47 WHERE a = 1;
+SELECT * FROM t1 ORDER BY a;
+connection master;
+UPDATE t1 SET a = 5, b = 5 WHERE a = 1;
+SELECT * FROM t1 ORDER BY a;
+#SHOW BINLOG EVENTS;
+sync_slave_with_master;
+set @@global.slave_exec_mode= default;
+SHOW STATUS LIKE 'Slave_retried_transactions';
+SELECT * FROM t1 ORDER BY a;
+source include/check_slave_is_running.inc;
+
+connection slave;
+call mtr.add_suppression("Slave SQL.*Could not execute Update_rows event on table test.t1");
+call mtr.add_suppression("Slave SQL for channel '': worker thread retried transaction");
+call mtr.add_suppression("The slave coordinator and worker threads are stopped");
+#
+# Bug#24764800 REPLICATION FAILING ON SLAVE WITH XAER_RMFAIL ERROR
+#
+# Verify that a temporary failing replicated xa transaction completes
+# upon slave applier restart after previous
+# @@global.slave_transaction_retries number of retries in vain.
+#
+connection slave;
+
+set @save_innodb_lock_wait_timeout=@@global.innodb_lock_wait_timeout;
+set @save_slave_transaction_retries=@@global.slave_transaction_retries;
+
+# Slave applier parameters for the failed retry
+set @@global.innodb_lock_wait_timeout=1;
+set @@global.slave_transaction_retries=2;
+--source include/restart_slave_sql.inc
+
+# Temporary error implement: a record is blocked by slave local trx
+connection slave1;
+BEGIN;
+INSERT INTO t1 SET a = 6, b = 7;
+
+connection master;
+INSERT INTO t1 SET a = 99, b = 99; # slave applier warm up trx
+XA START 'xa1';
+INSERT INTO t1 SET a = 6, b = 6; # this record eventually must be found on slave
+XA END 'xa1';
+XA PREPARE 'xa1';
+
+connection slave;
+# convert_error(ER_LOCK_WAIT_TIMEOUT)
+--let $err_timeout= 1205
+# convert_error(ER_LOCK_DEADLOCK)
+--let $err_deadlock= 1213
+--let $slave_sql_errno=$err_deadlock,$err_timeout
+--let $show_slave_sql_error=
+--source include/wait_for_slave_sql_error.inc
+
+# b. Slave applier parameters for successful retry after restart
+set @@global.innodb_lock_wait_timeout=1;
+set @@global.slave_transaction_retries=100;
+
+--source include/restart_slave_sql.inc
+
+--let $last_retries= query_get_value(SHOW GLOBAL STATUS LIKE 'Slave_retried_transactions', Value, 1)
+--let $status_type=GLOBAL
+--let $status_var=Slave_retried_transactions
+--let $status_var_value=`SELECT 1 + $last_retries`
+--let $$status_var_comparsion= >
+--source include/wait_for_status_var.inc
+
+# Release the record after just one retry
+connection slave1;
+ROLLBACK;
+
+connection master;
+XA COMMIT 'xa1';
+
+--source include/sync_slave_sql_with_master.inc
+
+# Proof of correctness: the committed XA is on the slave
+connection slave;
+--let $assert_text=XA transaction record must be in the table
+--let $assert_cond=count(*)=1 FROM t1 WHERE a=6 AND b=6
+--source include/assert.inc
+
+# Bug#24764800 cleanup:
+set @@global.innodb_lock_wait_timeout=@save_innodb_lock_wait_timeout;
+set @@global.slave_transaction_retries= @save_slave_transaction_retries;
+
+#
+# Total cleanup:
+#
+connection master;
+DROP TABLE t1;
+--sync_slave_with_master
+--connection master
+
+# We must wait for the slave to stop.
+# Otherwise the warnings in the error log about deadlock may be written to
+# the error log only during shutdown, and currently the suppression of
+# "Deadlock found" set in this test case is not effective during server
+# shutdown.
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_test_framework.cnf b/mysql-test/suite/rpl/t/rpl_test_framework.cnf
new file mode 100644
index 00000000..755e3622
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_test_framework.cnf
@@ -0,0 +1,28 @@
+!include ../my.cnf
+[mysqld.1]
+log-slave-updates
+[mysqld.2]
+log-slave-updates
+[mysqld.3]
+log-slave-updates
+[mysqld.4]
+log-slave-updates
+[mysqld.5]
+log-slave-updates
+[mysqld.6]
+log-slave-updates
+[mysqld.7]
+log-slave-updates
+[mysqld.8]
+log-slave-updates
+[mysqld.9]
+log-slave-updates
+
+[ENV]
+SERVER_MYPORT_3= @mysqld.3.port
+SERVER_MYPORT_4= @mysqld.4.port
+SERVER_MYPORT_5= @mysqld.5.port
+SERVER_MYPORT_6= @mysqld.6.port
+SERVER_MYPORT_7= @mysqld.7.port
+SERVER_MYPORT_8= @mysqld.8.port
+SERVER_MYPORT_9= @mysqld.9.port
diff --git a/mysql-test/suite/rpl/t/rpl_test_framework.test b/mysql-test/suite/rpl/t/rpl_test_framework.test
new file mode 100644
index 00000000..cf559072
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_test_framework.test
@@ -0,0 +1,143 @@
+# ==== Purpose ====
+#
+# Test that the sync chain generated by
+# include/rpl_change_topology.inc (sourced from include/rpl_init.inc)
+# is correct.
+#
+# We test a number of different topologies. Each topology is tested
+# in include/rpl_test_framework.inc. See
+# include/rpl_test_framework.inc for details on how the sync
+# chain is tested.
+#
+# ==== Related bugs ====
+#
+# BUG#49978: Replication tests don't clean up replication state at the end
+
+
+# We only need to execute this test once. Also, we rely on 'DELETE
+# FROM t1' to remove rows in slave tables that don't exist in master
+# tables (see include/rpl_test_framework.inc for details).
+--source include/have_binlog_format_statement.inc
+
+
+--echo ==== Create t1 on all servers. ====
+if ($mtr_supports_more_than_10_servers)
+{
+ --let $rpl_server_count= 15
+ --let $rpl_topology= 1->2->3->4->5->6->7->8->9->10->11->12->13->14->15
+}
+if (!$mtr_supports_more_than_10_servers)
+{
+ --let $rpl_server_count= 9
+ --let $rpl_topology= 1->2->3->4->5->6->7->8->9
+}
+--source include/rpl_init.inc
+CREATE TABLE t1 (a INT);
+--source include/rpl_end.inc
+
+# Initialize $next_number before first call to
+# include/rpl_test_framework.text
+--let $next_number= 0
+
+
+--echo ==== Test 3-server topologies ====
+
+--let $rpl_server_count= 3
+
+--let $rpl_topology= 1 -> 2
+--let $masters= 1,3
+--source include/rpl_test_framework.inc
+
+--let $rpl_topology= 2 -> 3
+--let $masters= 1,2
+--source include/rpl_test_framework.inc
+
+--let $rpl_topology= none
+--let $masters= 1,2,3
+--source include/rpl_test_framework.inc
+
+--let $rpl_topology= 1->2, 2->1
+--let $masters= 1,3
+--source include/rpl_test_framework.inc
+
+--let $rpl_topology= 1->2->1
+--let $masters= 2,3
+--source include/rpl_test_framework.inc
+
+--let $rpl_topology= 2->1->2
+--let $masters= 1,3
+--source include/rpl_test_framework.inc
+
+--let $rpl_topology= 1->2->3
+--let $masters= 1
+--source include/rpl_test_framework.inc
+
+--let $rpl_topology= 2->3->2->1
+--let $masters= 3
+--source include/rpl_test_framework.inc
+
+--let $rpl_topology= 1->2,2->3,3->1
+--let $masters= 3
+--source include/rpl_test_framework.inc
+
+--let $rpl_topology= 1->3->2->1
+--let $masters= 3
+--source include/rpl_test_framework.inc
+
+
+--echo ==== Test 6-server topologies ====
+
+--let $rpl_server_count= 6
+
+--let $rpl_topology= 1->2->3->4->1->5->6
+--let $masters= 1
+--source include/rpl_test_framework.inc
+
+--let $rpl_topology= 3->4->5->6->3->1->2
+--let $masters= 4
+--source include/rpl_test_framework.inc
+
+--let $rpl_topology= 6->5->4->3->2->1
+--let $masters= 6
+--source include/rpl_test_framework.inc
+
+--let $rpl_topology= 1->2->3->1,4->5->6
+--let $masters= 3,4
+--source include/rpl_test_framework.inc
+
+
+--echo ==== Test 9-server topology ====
+
+--let $rpl_server_count= 9
+
+--let $rpl_topology= 1->2, 2->3, 3->4, 4->5, 5->1, 1->6, 6->7, 6->8, 8->9
+--let $masters= 2
+--source include/rpl_test_framework.inc
+
+if ($mtr_supports_more_than_10_servers) {
+--echo ==== Test 15-server topologies ====
+
+--let $rpl_server_count= 15
+
+--let $rpl_topology= 1->2->3->4->5->6->7->8->9->10->11->12->13->14->15->1
+--let $masters= 2
+--source include/rpl_test_framework.inc
+
+# This is a binary tree
+--let $rpl_topology= 1->2->4->8,1->3->6->12,2->5->10,3->7->14,4->9,5->11,6->13,7->15
+--let $masters= 1
+--source include/rpl_test_framework.inc
+}
+
+--echo ==== Clean up ====
+
+if ($mtr_supports_more_than_10_servers) {
+ --let $rpl_topology= 1->2->3->4->5->6->7->8->9->10->11->12->13->14->15
+}
+if (!$mtr_supports_more_than_10_servers) {
+ --let $rpl_topology= 1->2->3->4->5->6->7->8->9
+}
+--source include/rpl_init.inc
+--connection server_1
+DROP TABLE t1;
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_timestamp.test b/mysql-test/suite/rpl/t/rpl_timestamp.test
new file mode 100644
index 00000000..a3f4010f
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_timestamp.test
@@ -0,0 +1,18 @@
+source include/master-slave.inc;
+
+set timestamp=1656940000;
+set explicit_defaults_for_timestamp=!@@explicit_defaults_for_timestamp;
+connection master;
+
+create table t1 (f1 timestamp, f2 timestamp);
+show create table t1;
+sync_slave_with_master;
+show create table t1;
+connection master;
+drop table t1;
+flush binary logs;
+
+let $datadir=`select @@datadir`;
+exec $MYSQL_BINLOG -s $datadir/master-bin.000001;
+
+source include/rpl_end.inc;
diff --git a/mysql-test/suite/rpl/t/rpl_timezone-master.opt b/mysql-test/suite/rpl/t/rpl_timezone-master.opt
new file mode 100644
index 00000000..8e43bfbb
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_timezone-master.opt
@@ -0,0 +1 @@
+--default-time-zone=Europe/Moscow
diff --git a/mysql-test/suite/rpl/t/rpl_timezone-slave.opt b/mysql-test/suite/rpl/t/rpl_timezone-slave.opt
new file mode 100644
index 00000000..191182c3
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_timezone-slave.opt
@@ -0,0 +1 @@
+--default-time-zone=Japan
diff --git a/mysql-test/suite/rpl/t/rpl_timezone.test b/mysql-test/suite/rpl/t/rpl_timezone.test
new file mode 100644
index 00000000..4b5778ca
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_timezone.test
@@ -0,0 +1,211 @@
+#######################################
+# Change Author: JBM
+# Change Date: 2006-01-17
+# Change: Added order by
+#######################################
+# Test of replication of time zones.
+######################################
+# There is currently some bug possibly in prepared statements (this
+# test fails with --ps-protocol): sys_var_thd_time_zone::value_ptr()
+# is called only at prepare time, not at execution time. So,
+# thd->time_zone_used is not equal to 1 (it is back to 0, because of
+# reset_thd_for_next_command called at execution time), so the
+# timezone used in CONVERT_TZ is not binlogged. To debug (by Guilhem
+# and possibly Konstantin).
+
+source include/master-slave.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_ps_protocol
+
+# Save original timezone
+set @my_time_zone= @@global.time_zone;
+
+# Some preparations
+let $VERSION=`select version()`;
+set timestamp=100000000; # for fixed output of mysqlbinlog
+create table t1 (t timestamp, n int not null auto_increment, PRIMARY KEY(n));
+create table t2 (t char(32), n int not null auto_increment, PRIMARY KEY(n));
+
+connection slave;
+select @@time_zone;
+#set time_zone='UTC';
+#select @@time_zone;
+#
+# Let us check how well replication works when we are saving datetime
+# value in TIMESTAMP field.
+#
+connection master;
+select @@time_zone;
+#set time_zone='UTC';
+#select @@time_zone;
+insert into t1 values ('20050101000000', NULL), ('20050611093902',NULL);
+insert into t1 values ('20040101000000',NULL), ('20040611093902',NULL);
+SELECT * FROM t1 ORDER BY n;
+sync_slave_with_master;
+#set time_zone='UTC';
+SELECT * FROM t1 ORDER BY n;
+
+# Let us check also that setting of time_zone back to default also works
+# well
+connection master;
+delete from t1;
+set time_zone='Europe/Moscow';
+insert into t1 values ('20040101000000',NULL), ('20040611093902',NULL);
+SELECT * FROM t1 ORDER BY n;
+sync_slave_with_master;
+set time_zone='Europe/Moscow';
+SELECT * FROM t1 ORDER BY n;
+connection master;
+# Change Author: JBM
+# Change Date: 2005-12-22
+# Change: Comment out the exec of the binlog so test works for both SBR and RBR
+#--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
+#--exec $MYSQL_BINLOG --short-form $MYSQLTEST_VARDIR/log/master-bin.000001
+
+# Let us check with LOAD DATA INFILE
+# (we do it after mysqlbinlog because the temp files names are not constant)
+connection master;
+delete from t1;
+set time_zone='UTC';
+load data infile '../../std_data/rpl_timezone2.dat' ignore into table t1;
+SELECT * FROM t1 ORDER BY n;
+sync_slave_with_master;
+set time_zone='UTC';
+SELECT * FROM t1 ORDER BY n;
+set time_zone='Europe/Moscow';
+
+# Put back values of before the LOAD
+connection master;
+set time_zone='Europe/Moscow';
+delete from t1;
+insert into t1 values ('20040101000000',NULL), ('20040611093902',NULL);
+
+#
+# Now let us check how well we replicate statments reading TIMESTAMP fields
+# (We should see the same data on master and on slave but it should differ
+# from originally inserted)
+#
+set time_zone='MET';
+--disable_warnings ONCE
+insert into t2 (select * from t1);
+SELECT * FROM t1 ORDER BY n;
+sync_slave_with_master;
+SELECT * FROM t2 ORDER BY n;
+
+#
+# Now let us check how well we replicate various CURRENT_* functions
+#
+connection master;
+delete from t2;
+set timestamp=1000072000;
+insert into t2 values (current_timestamp,NULL), (current_date,NULL), (current_time,NULL);
+sync_slave_with_master;
+SELECT * FROM t2 ORDER BY n;
+
+#
+# At last let us check replication of FROM_UNIXTIME/UNIX_TIMESTAMP functions.
+#
+connection master;
+delete from t2;
+insert into t2 values (from_unixtime(1000000000),NULL),
+ (unix_timestamp('2001-09-09 03:46:40'),NULL);
+SELECT * FROM t2 ORDER BY n;
+sync_slave_with_master;
+# We should get same result on slave as on master
+SELECT * FROM t2 ORDER BY n;
+
+#
+# Let us check that we are allowing to set global time_zone with
+# replication
+#
+connection master;
+set global time_zone='MET';
+
+#
+# Let us see if CONVERT_TZ(@@time_zone) replicates
+#
+delete from t2;
+set time_zone='UTC';
+insert into t2 values(convert_tz('2004-01-01 00:00:00','MET',@@time_zone),NULL);
+insert into t2 values(convert_tz('2005-01-01 00:00:00','MET','Japan'),NULL);
+SELECT * FROM t2 ORDER BY n;
+sync_slave_with_master;
+SELECT * FROM t2 ORDER BY n;
+
+# Clean up
+connection master;
+drop table t1, t2;
+sync_slave_with_master;
+
+
+# Restore original timezone
+connection master;
+set global time_zone= @my_time_zone;
+
+--echo End of 4.1 tests
+
+#
+# Bug #29536: timestamp inconsistent in replication around 1970
+#
+connection master;
+
+CREATE TABLE t1 (a INT, b TIMESTAMP);
+INSERT INTO t1 VALUES (1, NOW());
+
+SET @@session.time_zone='Japan';
+--disable_warnings
+UPDATE IGNORE t1 SET b= '1970-01-01 08:59:59' WHERE a= 1;
+--enable_warnings
+SELECT * FROM t1 ORDER BY a;
+
+sync_slave_with_master;
+SET @@session.time_zone='Japan';
+# must procdure the same result as the SELECT on the master
+SELECT * FROM t1 ORDER BY a;
+
+SET @@session.time_zone = default;
+connection master;
+DROP TABLE t1;
+SET @@session.time_zone = default;
+--sync_slave_with_master
+--source include/stop_slave.inc
+
+# Bug#41719 delayed INSERT into timestamp col needs set time_zone for concurrent binlogging
+# To test that time_zone is correctly binloging for 'insert delayed' statement
+# Insert 2 values into timestamp col with different time_zone. Check result.
+
+--connection master
+reset master;
+CREATE TABLE t1 (date timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP, a int(11) default NULL);
+
+SET @@session.time_zone='+01:00';
+insert into t1 values('2008-12-23 19:39:39',1);
+
+--connection master1
+SET @@session.time_zone='+02:00';
+insert delayed into t1 values ('2008-12-23 19:39:39',2);
+
+# wait for the delayed insert to be executed
+let $wait_condition= SELECT date FROM t1 WHERE a=2;
+--source include/wait_condition.inc
+
+flush table t1;
+flush logs;
+select * from t1;
+DROP TABLE t1;
+
+let $MYSQLD_DATADIR= `select @@datadir;`;
+--exec $MYSQL_BINLOG $MYSQLD_DATADIR/master-bin.000001 | $MYSQL
+--connection master1
+select * from t1 order by a;
+DROP TABLE t1;
+SET @@session.time_zone = default;
+
+--let $rpl_only_running_threads= 1
+--source include/rpl_end.inc
+
+--echo End of 5.0 tests
diff --git a/mysql-test/suite/rpl/t/rpl_tmp_table_and_DDL.test b/mysql-test/suite/rpl/t/rpl_tmp_table_and_DDL.test
new file mode 100644
index 00000000..7029729d
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_tmp_table_and_DDL.test
@@ -0,0 +1,169 @@
+#
+# Bug#49132
+# This test verifies if executing DDL statement before trying to manipulate
+# a temporary table causes row-based replication to break with error 'table
+# does not exist' base on myisam engine.
+#
+
+source include/have_binlog_format_row.inc;
+source include/master-slave.inc;
+
+LET $ENGINE_TYPE= MyISAM;
+source include/rpl_tmp_table_and_DDL.test;
+sync_slave_with_master;
+
+#
+# BUG #51839
+# The test makes sure the binlog format is not changed
+# after a execution of DDL with a table locked, so that
+# the following DML statements will not cause the slave
+# to stop.
+#
+
+--connection master
+--disable_abort_on_error
+
+CREATE TABLE t1 (a CHAR(30));
+CREATE TEMPORARY TABLE t2 (b CHAR(60));
+
+# CREATE FUNCTION when a table is locked.
+LOCK TABLE t1 WRITE;
+CREATE FUNCTION f1 () RETURNS TINYINT RETURN 13;
+INSERT INTO t2 VALUES ("CREATE FUNCTION f1 with table locked");
+
+UNLOCK TABLE;
+CREATE FUNCTION f2 () RETURNS TINYINT RETURN 13;
+
+# ALTER FUNCTION when a table is locked.
+LOCK TABLE t1 WRITE;
+ALTER FUNCTION f2 SQL SECURITY INVOKER;
+INSERT INTO t2 VALUES ("ALTER FUNCTION f2 with table locked");
+
+# DROP FUNCTION when a table is locked.
+LOCK TABLE t1 WRITE;
+DROP FUNCTION f2;
+INSERT INTO t2 VALUES ("DROP FUNCTION f2 with table locked");
+
+
+# CREATE PROCEDURE when a table is locked.
+CREATE PROCEDURE p1() SELECT 1;
+INSERT INTO t2 VALUES ("CREATE PROCEDURE p1 with table locked");
+
+UNLOCK TABLE;
+CREATE PROCEDURE p2() SELECT 1;
+
+# ALTER PROCEDURE when a table is locked.
+LOCK TABLE t1 WRITE;
+ALTER PROCEDURE p2 SQL SECURITY INVOKER;
+INSERT INTO t2 VALUES ("ALTER PROCEDURE P2 with table locked");
+
+# DROP PROCEDURE when a table is locked.
+DROP PROCEDURE p2;
+INSERT INTO t2 VALUES ("DROP PROCEDURE p2 with table locked");
+
+
+# CREATE EVENT when a table is locked.
+CREATE EVENT e1 ON SCHEDULE EVERY 10 HOUR DO SELECT 1;
+INSERT INTO t2 VALUES ("CREATE EVENT e1 with table locked");
+
+UNLOCK TABLE;
+CREATE EVENT e2 ON SCHEDULE EVERY 10 HOUR DO SELECT 1;
+
+# ALTER EVENT when a table is locked.
+LOCK TABLE t1 WRITE;
+ALTER EVENT e2 ON SCHEDULE EVERY 20 HOUR DO SELECT 1;
+INSERT INTO t2 VALUES ("ALTER EVENT e2 with table locked");
+
+# DROP EVENT when a table is locked.
+DROP EVENT e2;
+INSERT INTO t2 VALUES ("DROP EVENT e2 with table locked");
+
+
+# CREATE DATABASE when a table is locked.
+CREATE DATABASE mysqltest1;
+INSERT INTO t2 VALUES ("CREATE DATABASE mysqltest1 with table locked");
+
+UNLOCK TABLE;
+CREATE DATABASE mysqltest2;
+
+# DROP DATABASE when a table is locked.
+LOCK TABLE t1 WRITE;
+DROP DATABASE mysqltest2;
+INSERT INTO t2 VALUES ("DROP DATABASE mysqltest2 with table locked");
+
+UNLOCK TABLE;
+DROP DATABASE mysqltest2;
+
+# CREATE USER when a table is locked.
+LOCK TABLE t1 WRITE;
+CREATE USER test_1@localhost;
+INSERT INTO t2 VALUES ("CREATE USER test_1@localhost with table locked");
+
+UNLOCK TABLE;
+CREATE USER test_2@localhost;
+
+# GRANT select on table to user when a table is locked.
+LOCK TABLE t1 WRITE;
+GRANT SELECT ON t1 TO test_2@localhost;
+INSERT INTO t2 VALUES ("GRANT select on table to user with table locked");
+
+# GRANT all on function to user when a table is locked.
+GRANT ALL ON f2 TO test_2@localhost;
+INSERT INTO t2 VALUES ("GRANT ALL ON f2 TO test_2 with table locked");
+
+# GRANT all on procdure to user when a table is locked.
+GRANT ALL ON p2 TO test_2@localhost;
+INSERT INTO t2 VALUES ("GRANT ALL ON p2 TO test_2 with table locked");
+
+# GRANT USAGE ON *.* to user when a table is locked.
+GRANT USAGE ON *.* TO test_2@localhost;
+INSERT INTO t2 VALUES ("GRANT USAGE ON *.* TO test_2 with table locked");
+
+
+# REVOKE ALL PRIVILEGES on function to user when a table is locked.
+REVOKE ALL PRIVILEGES ON f2 FROM test_2@localhost;
+INSERT INTO t2 VALUES ("REVOKE ALL PRIVILEGES on function to user with table locked");
+
+# REVOKE ALL PRIVILEGES on procedure to user when a table is locked.
+REVOKE ALL PRIVILEGES ON p2 FROM test_2@localhost;
+INSERT INTO t2 VALUES ("REVOKE ALL PRIVILEGES on procedure to user with table locked");
+
+# REVOKE ALL PRIVILEGES on table to user when a table is locked.
+REVOKE ALL PRIVILEGES ON t1 FROM test_2@localhost;
+INSERT INTO t2 VALUES ("REVOKE ALL PRIVILEGES on table to user with table locked");
+
+# REVOKE USAGE ON *.* to user when a table is locked.
+REVOKE USAGE ON *.* FROM test_2@localhost;
+INSERT INTO t2 VALUES ("REVOKE USAGE ON *.* TO test_2 with table locked");
+
+
+# RENAME USER when a table is locked.
+RENAME USER test_2@localhost TO test_3@localhost;
+INSERT INTO t2 VALUES ("RENAME USER test_2 TO test_3 with table locked");
+
+UNLOCK TABLE;
+RENAME USER test_2@localhost TO test_3@localhost;
+
+# DROP USER when a table is locked.
+LOCK TABLE t1 WRITE;
+DROP USER test_3@localhost;
+INSERT INTO t2 VALUES ("DROP USER test_3@localhost with table locked");
+
+UNLOCK TABLE;
+
+# Bug #20439913 CREATE TABLE DB.TABLE LIKE TMPTABLE IS
+# BINLOGGED INCORRECTLY - BREAKS A SLAVE
+CREATE DATABASE db;
+CREATE TABLE db.t1 LIKE t2;
+CREATE TABLE t3 LIKE t2;
+DROP TABLE t3;
+DROP DATABASE db;
+# end of Bug #20439913 test
+
+DROP USER test_3@localhost;
+DROP FUNCTION f2;
+DROP PROCEDURE p2;
+DROP EVENT e2;
+DROP TABLE t1, t2;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_tmp_table_and_DDL_innodb.test b/mysql-test/suite/rpl/t/rpl_tmp_table_and_DDL_innodb.test
new file mode 100644
index 00000000..1a09b685
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_tmp_table_and_DDL_innodb.test
@@ -0,0 +1,55 @@
+source include/have_innodb.inc;
+source include/have_binlog_format_row.inc;
+source include/master-slave.inc;
+#
+# BUG#20574550
+# CREATE TABLE LIKE <TEMP_TABLE> does not preserve original table storage
+# engine when using row based replication
+#
+--connection master
+
+# Define temp_t1 and temp_t2 storage engines
+--let $engine_temp_t1= InnoDB
+--let $engine_temp_t2= MyISAM
+
+# Create the two temporary tables
+--eval CREATE TEMPORARY TABLE temp_t1 (c1 INT) ENGINE=$engine_temp_t1
+--eval CREATE TEMPORARY TABLE temp_t2 (c1 INT) ENGINE=$engine_temp_t2
+
+# Create t1 and t2 based on temporary tables
+CREATE TABLE t1 LIKE temp_t1;
+CREATE TABLE t2 LIKE temp_t2;
+--sync_slave_with_master
+
+# On master
+--connection master
+# Assert that t1 and t2 have the same storage engines as temp_t1 and temp_t2
+--let $engine_t1= query_get_value(SHOW TABLE STATUS WHERE Name='t1', Engine, 1)
+--let $assert_cond= "$engine_t1" = "$engine_temp_t1"
+--let $assert_text= "t1 on master and temp_t1 have the same storage engine"
+--source include/assert.inc
+
+--let $engine_t2= query_get_value(SHOW TABLE STATUS WHERE Name='t2', Engine, 1)
+--let $assert_cond= "$engine_t2" = "$engine_temp_t2"
+--let $assert_text= "t2 on master and temp_t2 have the same storage engine"
+--source include/assert.inc
+
+# On slave
+--connection slave
+# Assert that t1 and t2 have the same storage engines as temp_t1 and temp_t2
+--let $engine_t1= query_get_value(SHOW TABLE STATUS WHERE Name='t1', Engine, 1)
+--let $assert_cond= "$engine_t1" = "$engine_temp_t1"
+--let $assert_text= "t1 on slave and temp_t1 have the same storage engine"
+--source include/assert.inc
+
+--let $engine_t2= query_get_value(SHOW TABLE STATUS WHERE Name='t2', Engine, 1)
+--let $assert_cond= "$engine_t2" = "$engine_temp_t2"
+--let $assert_text= "t2 on slave and temp_t2 have the same storage engine"
+--source include/assert.inc
+
+# Cleanup
+--connection master
+DROP TEMPORARY TABLE temp_t1, temp_t2;
+DROP TABLE t1, t2;
+--source include/rpl_end.inc
+
diff --git a/mysql-test/suite/rpl/t/rpl_trans_no_trans.test b/mysql-test/suite/rpl/t/rpl_trans_no_trans.test
new file mode 100644
index 00000000..f6e3731d
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_trans_no_trans.test
@@ -0,0 +1,72 @@
+#
+# Test mixing transactional and non transactional tables
+#
+
+--source include/master-slave.inc
+--source include/have_innodb.inc
+--source include/have_binlog_format_row.inc
+
+#
+# Test updating conditionally a non transactinal table in a function
+# This verifies that we don't write only a table map for a non transactional,
+# without any row events
+# The original bug caused a crash on the slave when doing a sync_slave
+#
+
+create or replace table t1(id int)engine=innodb;
+create or replace table t3(id int)engine=myisam;
+
+delimiter //;
+create or replace function t99 (a int)
+returns int(10)
+MODIFIES SQL DATA
+begin
+ if (a > 100)
+ then
+ insert into t3 values (a);
+ end if;
+ return a;
+end//
+delimiter ;//
+begin;
+insert into t1 values(t99(1));
+insert into t1 values(t99(101));
+commit;
+select * from t1;
+select * from t3;
+insert into t1 values(t99(1));
+
+drop function t99;
+drop table t1,t3;
+
+sync_slave_with_master;
+connection master;
+
+#
+# MDEV-8203
+# Assertion `!current_stmt_is_commit || !rgi->tables_to_lock' failed in
+# Query_log_event::do_apply_event(rpl_group_info*, const char*, uint32)
+#
+
+CREATE TABLE t1 (i INT) ENGINE=InnoDB;
+CREATE TABLE t2 (j INT) ENGINE=MyISAM;
+
+--delimiter ||
+CREATE TRIGGER tr AFTER INSERT ON t1 FOR EACH ROW
+BEGIN
+ SET @a = unknown_column_just_to_raise_an_error;
+ INSERT INTO t2 VALUES (NULL) ;
+END||
+--delimiter ;
+
+--error ER_BAD_FIELD_ERROR
+INSERT INTO t1 VALUES (1);
+--sync_slave_with_master
+
+connection master;
+
+drop trigger tr;
+drop table t1,t2;
+
+# End of 4.1 tests
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_trigger.test b/mysql-test/suite/rpl/t/rpl_trigger.test
new file mode 100644
index 00000000..e442ed94
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_trigger.test
@@ -0,0 +1,596 @@
+#
+# Test of triggers with replication
+# Adding statement include due to Bug 12574
+# TODO: Remove statement include once 12574 is patched
+--source include/have_binlog_format_mixed_or_statement.inc
+--source include/have_innodb.inc
+--source include/master-slave.inc
+
+connection slave;
+--source include/stop_slave.inc
+CHANGE MASTER TO MASTER_USE_GTID=NO;
+--source include/start_slave.inc
+
+connection 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;
+
+--disable_warnings
+DROP TABLE IF EXISTS t1;
+DROP TABLE IF EXISTS t2;
+DROP TABLE IF EXISTS t3;
+
+--enable_warnings
+
+#
+# #12482: Triggers has side effects with auto_increment values
+#
+
+create table t1 (a int auto_increment, primary key (a), b int, rand_value double not null);
+create table t2 (a int auto_increment, primary key (a), b int) engine=innodb;
+create table t3 (a int auto_increment, primary key (a), name varchar(64) not null, old_a int, old_b int, rand_value double not null);
+
+delimiter |;
+create trigger t1 before insert on t1 for each row
+begin
+ insert into t3 values (NULL, "t1", new.a, new.b, rand());
+end|
+
+create trigger t2 after insert on t2 for each row
+begin
+ insert into t3 values (NULL, "t2", new.a, new.b, rand());
+end|
+delimiter ;|
+
+insert into t3 values(100,"log",0,0,0);
+
+# Ensure we always have same random numbers
+SET @@RAND_SEED1=658490765, @@RAND_SEED2=635893186;
+
+# Emulate that we have rows 2-9 deleted on the slave
+--disable_warnings
+insert into t1 values(1,1,rand()),(NULL,2,rand());
+insert into t2 (b) values(last_insert_id());
+insert into t2 values(3,0),(NULL,0);
+insert into t2 values(NULL,0),(500,0);
+--enable_warnings
+
+select a,b, truncate(rand_value,4) from t1;
+select * from t2;
+select a,name, old_a, old_b, truncate(rand_value,4) from t3;
+sync_slave_with_master;
+select a,b, truncate(rand_value,4) from t1;
+select * from t2;
+select a,name, old_a, old_b, truncate(rand_value,4) from t3;
+connection master;
+drop table t1,t2,t3;
+
+#
+# #12480: NOW() is not constant in a trigger
+# #12481: Using NOW() in a stored function breaks statement based replication
+#
+
+# Start by getting a lock on 'bug12480' to be able to use get_lock() as sleep()
+connect (con2,localhost,root,,);
+connection con2;
+select get_lock("bug12480",2);
+connection default;
+
+create table t1 (a datetime,b datetime, c datetime);
+--disable_warnings
+drop function if exists bug12480;
+--enable_warnings
+
+delimiter |;
+
+create function bug12480() returns datetime
+begin
+ set @a=get_lock("bug12480",2);
+ return now();
+end|
+
+create trigger t1_first before insert on t1
+for each row begin
+ set @a=get_lock("bug12480",2);
+ set new.b= now();
+ set new.c= bug12480();
+end
+|
+
+delimiter ;|
+# The trigger causes a warning for unsafe statement when
+# binlog_format=statement since it uses get_lock.
+--disable_warnings
+insert into t1 set a = now();
+--enable_warnings
+select a=b && a=c from t1;
+let $time=`select a from t1`;
+
+# Check that definer attribute is replicated properly:
+# - dump definers on the master;
+# - wait for the slave to synchronize with the master;
+# - dump definers on the slave;
+
+SELECT routine_name, definer
+FROM information_schema.routines
+WHERE routine_name = 'bug12480';
+
+SELECT trigger_name, definer
+FROM information_schema.triggers
+WHERE trigger_name = 't1_first';
+
+sync_slave_with_master;
+
+# XXX: Definers of stored procedures and functions are not replicated. WL#2897
+# (Complete definer support in the stored routines) addresses this issue. So,
+# the result file is expected to be changed after implementation of this WL
+# item.
+
+SELECT routine_name, definer
+FROM information_schema.routines
+WHERE routine_name = 'bug12480';
+
+SELECT trigger_name, definer
+FROM information_schema.triggers
+WHERE trigger_name = 't1_first';
+
+select a=b && a=c from t1;
+--disable_query_log
+eval select a='$time' as 'test' from t1;
+--enable_query_log
+
+connection master;
+disconnect con2;
+
+truncate table t1;
+drop trigger t1_first;
+
+# The trigger causes a warning for unsafe statement when
+# binlog_format=statement since it uses get_lock.
+--disable_warnings
+insert into t1 values ("2003-03-03","2003-03-03","2003-03-03"),(bug12480(),bug12480(),bug12480()),(now(),now(),now());
+--enable_warnings
+select a=b && a=c from t1;
+
+drop function bug12480;
+drop table t1;
+
+#
+# #14614: Replication of tables with trigger generates error message if databases is changed
+# Note. The error message is emitted by _myfree() using fprintf() to the stderr
+# and because of that does not fall into the .result file.
+#
+
+create table t1 (i int);
+create table t2 (i int);
+
+delimiter |;
+create trigger tr1 before insert on t1 for each row
+begin
+ insert into t2 values (1);
+end|
+delimiter ;|
+
+create database other;
+use other;
+insert into test.t1 values (1);
+
+sync_slave_with_master;
+
+connection master;
+use test;
+drop table t1,t2;
+drop database other;
+
+
+#
+# Test specific triggers including SELECT into var with replication
+# BUG#13227:
+# slave performs an update to the replicatable table, t1,
+# and modifies its local data, t3, by mean of its local trigger that uses
+# another local table t2.
+# Expected values are commented into queries.
+#
+# Body of the test executes in a loop since the problem occurred randomly.
+#
+
+let $max_rows=5;
+let $rnd=10;
+
+--echo test case for BUG#13227
+while ($rnd)
+{
+ --echo -------------------
+ echo $rnd;
+ --echo -------------------
+
+### SETUP
+
+--disable_warnings
+ connection master;
+ eval drop table if exists t1$rnd;
+ connection slave;
+ eval drop table if exists t2$rnd,t3$rnd;
+--enable_warnings
+
+ connection master;
+ eval create table t1$rnd (f1 int) /* 2 replicate */;
+ let $i=$max_rows;
+ while ($i)
+ {
+ eval insert into t1$rnd values (-$i);
+ dec $i;
+ }
+
+ sync_slave_with_master;
+#connection slave;
+ eval select * from t1$rnd;
+ delimiter |;
+ eval create trigger trg1$rnd before update on t1$rnd /* slave local */
+ for each row
+ begin
+ DECLARE r integer;
+ SELECT f2 INTO r FROM t2$rnd where f1=NEW.f1;
+ INSERT INTO t3$rnd values (r);
+ end|
+ delimiter ;|
+ eval create table t2$rnd (f1 int, f2 int) /* slave local */;
+ eval create table t3$rnd (f3 int) /* slave local */;
+ let $i=$max_rows;
+ while ($i)
+ {
+ eval insert into t2$rnd values ($i, $i*100);
+ dec $i;
+ }
+
+### Test
+
+#connection slave;
+
+# trigger works as specified when updates from slave
+ eval select * from t2$rnd;
+ eval UPDATE t1$rnd SET f1=$max_rows where f1=-$max_rows;
+ eval SELECT * from t1$rnd /* must be f1 $max_rows, 1 - $max_rows 2 - $max_rows ... -1 */;
+ eval SELECT * from t3$rnd /* must be f3 $max_rows*100 */;
+
+ connection master;
+ let $i=$max_rows;
+ while ($i)
+ {
+ eval UPDATE t1$rnd SET f1=$i where f1=-$i;
+ dec $i;
+ }
+
+ sync_slave_with_master;
+#connection slave;
+ eval SELECT * from t1$rnd /* must be f1 $max_rows ... 1 */;
+ eval SELECT * from t3$rnd /* must be f3 $max_rows * 100 ... 100 */;
+
+### CLEANUP
+#connection slave;
+ eval drop trigger trg1$rnd;
+ eval drop table t2$rnd,t3$rnd;
+
+ connection master;
+ eval drop table t1$rnd;
+ sync_slave_with_master;
+ connection master;
+
+ dec $rnd;
+}
+
+
+#
+# BUG#16266: Definer is not fully qualified error during replication.
+#
+# The idea of this test is to emulate replication of a trigger from the old
+# master (master w/o "DEFINER in triggers" support) to the new slave and check
+# that:
+# 1. the trigger on the slave will be replicated w/o errors;
+# 2. the trigger on the slave will be non-SUID (will have no DEFINER);
+# 3. the trigger can be activated later on the slave w/o errors.
+#
+# In order to emulate this kind of replication, we make the slave playing the binlog,
+# recorded by 5.0.16 master. This binlog contains the following statements:
+# CREATE TABLE t1(c INT);
+# CREATE TABLE t2(s CHAR(200));
+# CREATE TRIGGER trg1 AFTER INSERT ON t1
+# FOR EACH ROW
+# INSERT INTO t2 VALUES(CURRENT_USER());
+# INSERT INTO t1 VALUES(1);
+#
+
+# 1. Check that the trigger's replication is succeeded.
+
+# Stop the slave.
+
+connection slave;
+STOP SLAVE;
+
+# Replace master's binlog.
+
+connection master;
+let $MYSQLD_DATADIR= `select @@datadir`;
+FLUSH LOGS;
+
+# Stop master server
+--let $rpl_server_number= 1
+--source include/rpl_stop_server.inc
+
+# Replace binlog
+remove_file $MYSQLD_DATADIR/master-bin.000001;
+copy_file $MYSQL_TEST_DIR/std_data/bug16266.000001 $MYSQLD_DATADIR/master-bin.000001;
+
+--let $rpl_server_number= 1
+--source include/rpl_start_server.inc
+
+let $binlog_version= query_get_value(SHOW BINLOG EVENTS, Info, 1);
+
+
+# Make the slave to replay the new binlog.
+--echo --> Master binlog: $binlog_version
+
+# Make the slave to replay the new binlog.
+
+connection slave;
+--let $master_use_gtid_option= No
+--source include/reset_slave.inc
+START SLAVE;
+
+SELECT MASTER_POS_WAIT('master-bin.000001', 513) >= 0;
+
+# Check that the replication succeeded.
+
+SHOW TABLES LIKE 't_';
+--replace_column 6 #
+SHOW TRIGGERS;
+SELECT * FROM t1;
+SELECT * FROM t2;
+
+# 2. Check that the trigger is non-SUID on the slave;
+# 3. Check that the trigger can be activated on the slave.
+#
+# We disable warnings here since it affects the result file in
+# different ways depending on the mode being used.
+
+disable_warnings;
+INSERT INTO t1 VALUES(2);
+enable_warnings;
+
+SELECT * FROM t1;
+SELECT * FROM t2;
+
+# That's all, cleanup.
+
+DROP TRIGGER trg1;
+DROP TABLE t1;
+DROP TABLE t2;
+
+STOP SLAVE;
+--source include/reset_slave.inc
+
+# The master should be clean.
+
+connection master;
+SHOW TABLES LIKE 't_';
+--replace_column 6 #
+SHOW TRIGGERS;
+
+RESET MASTER;
+
+# Restart slave.
+
+connection slave;
+START SLAVE;
+
+
+#
+# BUG#20438: CREATE statements for views, stored routines and triggers can be
+# not replicable.
+#
+
+--echo
+--echo ---> Test for BUG#20438
+
+# Prepare environment.
+
+--echo
+--echo ---> Preparing environment...
+--connection master
+
+--disable_warnings
+DROP TABLE IF EXISTS t1;
+DROP TABLE IF EXISTS t2;
+--enable_warnings
+
+--echo
+--echo ---> Synchronizing slave with master...
+
+--sync_slave_with_master
+
+--echo
+--connection master
+
+# Test.
+
+--echo
+--echo ---> Creating objects...
+
+CREATE TABLE t1(c INT);
+CREATE TABLE t2(c INT);
+
+/*!50003 CREATE TRIGGER t1_bi BEFORE INSERT ON t1
+ FOR EACH ROW
+ INSERT INTO t2 VALUES(NEW.c * 10) */;
+
+--echo
+--echo ---> Inserting value...
+
+INSERT INTO t1 VALUES(1);
+
+--echo
+--echo ---> Checking on master...
+
+SELECT * FROM t1;
+SELECT * FROM t2;
+
+--echo
+--echo ---> Synchronizing slave with master...
+
+--sync_slave_with_master
+
+--echo
+--echo ---> Checking on slave...
+
+SELECT * FROM t1;
+SELECT * FROM t2;
+
+# Cleanup.
+
+--echo
+--connection master
+
+--echo
+--echo ---> Cleaning up...
+
+DROP TABLE t1;
+DROP TABLE t2;
+
+--sync_slave_with_master
+--connection master
+
+#
+# BUG#23703: DROP TRIGGER needs an IF EXISTS
+#
+
+connection master;
+
+--disable_warnings
+drop table if exists t1;
+--enable_warnings
+
+create table t1(a int, b varchar(50));
+
+-- error ER_TRG_DOES_NOT_EXIST
+drop trigger not_a_trigger;
+
+drop trigger if exists not_a_trigger;
+
+create trigger t1_bi before insert on t1
+for each row set NEW.b := "In trigger t1_bi";
+
+insert into t1 values (1, "a");
+drop trigger if exists t1_bi;
+insert into t1 values (2, "b");
+drop trigger if exists t1_bi;
+insert into t1 values (3, "c");
+
+select * from t1;
+sync_slave_with_master;
+select * from t1;
+
+connection master;
+
+drop table t1;
+sync_slave_with_master;
+
+#
+# Bug#40116: Uncommited changes are replicated and stay on slave after
+# rollback on master
+#
+
+connection master;
+--source include/rpl_reset.inc
+
+connection slave;
+--source include/stop_slave.inc
+CHANGE MASTER TO MASTER_USE_GTID=NO;
+--source include/start_slave.inc
+
+connection master;
+
+create table t1 ( f int ) engine = innodb;
+create table log ( r int ) engine = myisam;
+create trigger tr
+ after insert on t1
+ for each row insert into log values ( new.f );
+
+set autocommit = 0;
+--disable_warnings
+insert into t1 values ( 1 );
+--enable_warnings
+rollback;
+sync_slave_with_master;
+
+let $diff_tables= master:t1, slave:t1;
+--source include/diff_tables.inc
+
+let $diff_tables= master:log, slave:log;
+--source include/diff_tables.inc
+
+connection master;
+drop table t1, log;
+sync_slave_with_master;
+
+#
+# MDEV-6769 DROP TRIGGER IF NOT EXIST binlogged on master but not on slave
+#
+let $slave_pos= query_get_value(SHOW MASTER STATUS, Position, 1);
+connection master;
+let $binlog_start= query_get_value(SHOW MASTER STATUS, Position, 1);
+drop trigger if exists notexistent;
+source include/show_binlog_events.inc;
+sync_slave_with_master;
+let $binlog_start= $slave_pos;
+source include/show_binlog_events.inc;
+connection master;
+
+#
+# MDEV-6112 multiple triggers per table
+#
+
+create table t1 (a int primary key, b int);
+create trigger tr3
+ before insert on t1
+ for each row set NEW.b := (NEW.b+1)*4;
+create trigger tr1
+ before insert on t1
+ for each row precedes tr3 set NEW.b := (NEW.b+1)*2;
+create trigger tr2
+ before insert on t1
+ for each row follows tr1 set NEW.b := (NEW.b+1)*3;
+
+--replace_column 6 #
+show triggers;
+insert into t1 values (1,1);
+select * from t1;
+sync_slave_with_master;
+--replace_column 6 #
+show triggers;
+select * from t1;
+connection master;
+drop table t1;
+
+#
+# MDEV-10924 CREATE OR REPLACE TRIGGER which fails on PRECEDES/FOLLOWS drops
+# the trigger, but isn't written to binlog; replication fails
+#
+
+CREATE TABLE t1 (i INT);
+CREATE OR REPLACE TRIGGER tr BEFORE INSERT ON t1 FOR EACH ROW SET @a=1;
+--error ER_REFERENCED_TRG_DOES_NOT_EXIST
+CREATE OR REPLACE TRIGGER tr BEFORE DELETE ON t1 FOR EACH ROW PRECEDES non_existing_trigger SET @a=2;
+--replace_column 6 #
+SHOW TRIGGERS;
+--sync_slave_with_master
+--replace_column 6 #
+SHOW TRIGGERS;
+connection master;
+drop table t1;
+
+#
+# End of tests
+#
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_trunc_temp.test b/mysql-test/suite/rpl/t/rpl_trunc_temp.test
new file mode 100644
index 00000000..1ef0fced
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_trunc_temp.test
@@ -0,0 +1,57 @@
+# ==== Purpose ====
+#
+# Verify that Slave_open_temp_tables is increased when a temporary
+# table is opened on the slave, and decreased when a temporary table
+# is closed on the slave, and that it is preserved during 'DELETE FROM
+# table' and 'TRUNCATE table'.
+#
+# ==== Method ====
+#
+# Create a temporary table on master, insert rows, and try:
+# - delete rows from the table
+# - truncate the table
+# - drop the table
+#
+# ==== Related bugs ====
+#
+# BUG#17137 Running "truncate table" on temporary table leaves the table open on a slave
+#
+# Bug in this test: BUG#37493: rpl_trunc_temp.test nondeterministic
+
+
+# Requires statement-based logging since temporary tables are not
+# logged in row-based logging
+-- source include/have_binlog_format_mixed_or_statement.inc
+
+source include/master-slave.inc;
+
+create temporary table t1 (n int);
+insert into t1 values(1);
+sync_slave_with_master;
+show status like 'Slave_open_temp_tables';
+
+# Perform a delete from temp table
+connection master;
+delete from t1;
+sync_slave_with_master;
+show status like 'Slave_open_temp_tables';
+
+# Perform truncate on temp table
+connection master;
+truncate t1;
+sync_slave_with_master;
+show status like 'Slave_open_temp_tables';
+
+# Disconnect the master, temp table on slave should disappear
+disconnect master;
+
+connection slave;
+
+# Wait until drop of temp tables appers in slave's binlog
+let $wait_binlog_event= DROP;
+source include/wait_for_binlog_event.inc;
+
+show status like 'Slave_open_temp_tables';
+
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_truncate_2myisam.test b/mysql-test/suite/rpl/t/rpl_truncate_2myisam.test
new file mode 100644
index 00000000..e8b55b86
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_truncate_2myisam.test
@@ -0,0 +1,2 @@
+let $engine=MyISAM;
+--source include/rpl_truncate.test
diff --git a/mysql-test/suite/rpl/t/rpl_truncate_3innodb.test b/mysql-test/suite/rpl/t/rpl_truncate_3innodb.test
new file mode 100644
index 00000000..bac911b9
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_truncate_3innodb.test
@@ -0,0 +1,3 @@
+--source include/have_innodb.inc
+let $engine=InnoDB;
+--source include/rpl_truncate.test
diff --git a/mysql-test/suite/rpl/t/rpl_typeconv-slave.opt b/mysql-test/suite/rpl/t/rpl_typeconv-slave.opt
new file mode 100644
index 00000000..48457b17
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_typeconv-slave.opt
@@ -0,0 +1 @@
+--loose-innodb
diff --git a/mysql-test/suite/rpl/t/rpl_typeconv.test b/mysql-test/suite/rpl/t/rpl_typeconv.test
new file mode 100644
index 00000000..9e566258
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_typeconv.test
@@ -0,0 +1,78 @@
+#
+# This include file is used by more than one test suite
+# (currently rpl and binlog_encryption suite).
+# Please check all dependent tests after modifying it
+#
+
+--source include/have_binlog_format_row.inc
+--source include/master-slave.inc
+
+connection slave;
+set @saved_slave_type_conversions = @@global.slave_type_conversions;
+CREATE TABLE type_conversions (
+ TestNo INT AUTO_INCREMENT PRIMARY KEY,
+ Source TEXT,
+ Target TEXT,
+ Flags TEXT,
+ On_Master LONGTEXT,
+ On_Slave LONGTEXT,
+ Expected LONGTEXT,
+ Compare INT,
+ Error TEXT);
+
+SELECT @@global.slave_type_conversions;
+SET GLOBAL SLAVE_TYPE_CONVERSIONS='';
+SELECT @@global.slave_type_conversions;
+SET GLOBAL SLAVE_TYPE_CONVERSIONS='ALL_NON_LOSSY';
+SELECT @@global.slave_type_conversions;
+SET GLOBAL SLAVE_TYPE_CONVERSIONS='ALL_LOSSY';
+SELECT @@global.slave_type_conversions;
+SET GLOBAL SLAVE_TYPE_CONVERSIONS='ALL_LOSSY,ALL_NON_LOSSY';
+SELECT @@global.slave_type_conversions;
+--error ER_WRONG_VALUE_FOR_VAR
+SET GLOBAL SLAVE_TYPE_CONVERSIONS='ALL_LOSSY,ALL_NON_LOSSY,NONEXISTING_BIT';
+SELECT @@global.slave_type_conversions;
+
+# Checking strict interpretation of type conversions
+connection slave;
+SET GLOBAL SLAVE_TYPE_CONVERSIONS='';
+source suite/rpl/include/type_conversions.test;
+
+# Checking lossy integer type conversions
+connection slave;
+SET GLOBAL SLAVE_TYPE_CONVERSIONS='ALL_NON_LOSSY';
+source suite/rpl/include/type_conversions.test;
+
+# Checking non-lossy integer type conversions
+connection slave;
+SET GLOBAL SLAVE_TYPE_CONVERSIONS='ALL_LOSSY';
+source suite/rpl/include/type_conversions.test;
+
+# Checking all type conversions
+connection slave;
+SET GLOBAL SLAVE_TYPE_CONVERSIONS='ALL_LOSSY,ALL_NON_LOSSY';
+source suite/rpl/include/type_conversions.test;
+
+connection slave;
+--echo **** Result of conversions ****
+disable_query_log;
+SELECT RPAD(Source, 15, ' ') AS Source_Type,
+ RPAD(Target, 15, ' ') AS Target_Type,
+ RPAD(Flags, 25, ' ') AS All_Type_Conversion_Flags,
+ IF(Compare IS NULL AND Error IS NOT NULL, '<Correct error>',
+ IF(Compare, '<Correct value>',
+ CONCAT("'", On_Slave, "' != '", Expected, "'")))
+ AS Value_On_Slave
+ FROM type_conversions;
+enable_query_log;
+DROP TABLE type_conversions;
+
+call mtr.add_suppression("Slave SQL.*Column 1 of table .test.t1. cannot be converted from type.* error.* 1677");
+
+connection master;
+DROP TABLE t1;
+sync_slave_with_master;
+
+set global slave_type_conversions = @saved_slave_type_conversions;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_typeconv_innodb.test b/mysql-test/suite/rpl/t/rpl_typeconv_innodb.test
new file mode 100644
index 00000000..ba217210
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_typeconv_innodb.test
@@ -0,0 +1,26 @@
+--source include/have_binlog_format_row.inc
+--source include/have_innodb.inc
+--source include/master-slave.inc
+
+#
+# BUG#49618: Field length stored incorrectly in binary log for InnoDB
+#
+
+connection slave;
+SET @saved_slave_type_conversions = @@GLOBAL.SLAVE_TYPE_CONVERSIONS;
+SET GLOBAL SLAVE_TYPE_CONVERSIONS = '';
+
+connection master;
+CREATE TABLE t1(b1 BIT(1), b2 BIT(2), b3 BIT(3)) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (b'0', b'01', b'101');
+sync_slave_with_master;
+
+let $diff_tables= master:t1, slave:t1;
+source include/diff_tables.inc;
+
+connection master;
+DROP TABLE t1;
+sync_slave_with_master;
+
+SET GLOBAL SLAVE_TYPE_CONVERSIONS = @saved_slave_type_conversions;
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_udf.test b/mysql-test/suite/rpl/t/rpl_udf.test
new file mode 100644
index 00000000..cda99ace
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_udf.test
@@ -0,0 +1,11 @@
+###################################################################
+# Author: Chuck Bell #
+# Date: 2006-12-21 #
+# Purpose: To test that UDFs are replicated in both row based and #
+# statement based format. This tests work completed in WL#3629. #
+###################################################################
+
+let $engine_type= MyISAM;
+--source include/rpl_udf.inc
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_unsafe_statements.test b/mysql-test/suite/rpl/t/rpl_unsafe_statements.test
new file mode 100644
index 00000000..40c9b9bb
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_unsafe_statements.test
@@ -0,0 +1,215 @@
+################################################################################
+# Bug#17047208 REPLICATION DIFFERENCE FOR MULTIPLE TRIGGERS
+# Problem: If DML invokes a trigger or a stored function that inserts into an
+# AUTO_INCREMENT column, that DML has to be marked as 'unsafe' statement. If the
+# tables are locked in the transaction prior to DML statement (using LOCK
+# TABLES), then the DML statement is not marked as 'unsafe' statement.
+
+# Steps to reproduce the reported test case (BINLOG_STMT_UNSAFE_AUTOINC_COLUMNS)
+# Case-1:
+# > Create a trigger on a table and do a insert in the trigger that updates
+# auto increment column
+# > A DML that executes the trigger in step.1 and check that DML is marked
+# as unsafe and DML is written into binlog using row format (in MBR)
+# > Execute the step 2 by locking the required tables prior to DML and check
+# that DML is marked as unsafe and DML is written into binlog using row
+# format (in MBR)
+#
+# This test script also adds test cases to cover few other unsafe statements.
+# Case-2: BINLOG_STMT_UNSAFE_WRITE_AUTOINC_SELECT
+# Case-3: BINLOG_STMT_UNSAFE_AUTOINC_NOT_FIRST
+# Case-4: BINLOG_STMT_UNSAFE_INSERT_TWO_KEYS
+# Case-5: BINLOG_STMT_UNSAFE_SKIP_LOCKED
+################################################################################
+
+--source include/have_innodb.inc
+--source include/have_binlog_format_mixed.inc
+--source include/master-slave.inc
+
+# Case-1: BINLOG_STMT_UNSAFE_AUTOINC_COLUMNS
+# Statement is unsafe because it invokes a trigger or a
+# stored function that inserts into an AUTO_INCREMENT column.
+
+# Step-1.1: Create two tables, one with AUTO_INCREMENT column.
+CREATE TABLE t1(id INT AUTO_INCREMENT, i INT, PRIMARY KEY (id)) ENGINE=INNODB;
+CREATE TABLE t2(id INT AUTO_INCREMENT, i INT, PRIMARY KEY (id)) ENGINE=INNODB;
+
+# Step-1.2: Create a trigger that inserts into an AUTO_INCREMENT column.
+CREATE TRIGGER trig1 AFTER INSERT ON t1
+FOR EACH ROW
+ INSERT INTO t2(i) VALUES(new.i);
+
+# Step-1.3: Create some gap in auto increment value on master's t2 table
+# but not on slave (by doing rollback). Just in case if the unsafe statements
+# are written in statement format, diff tables will fail.
+START TRANSACTION;
+INSERT INTO t2(i) VALUES (1);
+ROLLBACK;
+
+# Step-1.4: Insert a tuple into table t1 that triggers trig1 which inserts
+# into an AUTO_INCREMENT column.
+INSERT INTO t1(i) VALUES(2);
+
+# Step-1.5: Repeat step 1.4 but using 'LOCK TABLES' logic.
+START TRANSACTION;
+LOCK TABLES t1 WRITE, t2 WRITE;
+INSERT INTO t1(i) VALUES(3);
+UNLOCK TABLES;
+COMMIT;
+
+# Step-1.6: Sync slave with master
+--sync_slave_with_master
+
+# Step-1.7: Diff master-slave tables to make sure everything is in sync.
+--let $diff_tables=master:t1, slave:t1
+--source include/diff_tables.inc
+
+--let $diff_tables=master:t2, slave:t2
+--source include/diff_tables.inc
+
+# Step-1.8: Cleanup
+--connection master
+DROP TABLE t1,t2;
+
+# Case-2: BINLOG_STMT_UNSAFE_WRITE_AUTOINC_SELECT
+# Statements writing to a table with an auto-increment column after selecting
+# from another table are unsafe because the order in which rows are retrieved
+# determines what (if any) rows will be written. This order cannot be
+# predicted and may differ on master and the slave.
+
+# Step-2.1: Create two tables, one with AUTO_INCREMENT column.
+CREATE TABLE t1(i INT) ENGINE=INNODB;
+CREATE TABLE t2(id INT AUTO_INCREMENT, i INT, PRIMARY KEY (id)) ENGINE=INNODB;
+
+# Step-2.2: Create some tuples in table t1.
+INSERT INTO t1 values (1), (2), (3);
+
+# Step-2.3: Create some gap in auto increment value on master's t2 table
+# but not on slave (by doing rollback). Just in case if the unsafe statements
+# are written in statement format, diff tables will fail.
+START TRANSACTION;
+INSERT INTO t2(i) VALUES (1);
+ROLLBACK;
+
+# Step-2.4: Insert into t2 (table with an auto-increment) by selecting tuples
+# from table t1.
+INSERT INTO t2(i) SELECT i FROM t1;
+
+# Step-2.5: Repeat step 2.4 but now with 'LOCK TABLES' logic.
+START TRANSACTION;
+LOCK TABLES t2 WRITE, t1 READ;
+INSERT INTO t2(i) SELECT i FROM t1;
+UNLOCK TABLES;
+COMMIT;
+
+# Step-2.6: Sync slave with master
+--sync_slave_with_master
+
+# Step-2.7: Diff master-slave tables to make sure everything is in sync.
+--let $diff_tables=master:t1, slave:t1
+--source include/diff_tables.inc
+
+--let $diff_tables=master:t2, slave:t2
+--source include/diff_tables.inc
+
+# Step-2.8: Cleanup
+--connection master
+DROP TABLE t1,t2;
+
+# Case-3: BINLOG_STMT_UNSAFE_AUTOINC_NOT_FIRST
+# INSERT into autoincrement field which is not the first part in the
+# composed primary key is unsafe
+#
+# Step-3.1: Create a table with auto increment column and a composed primary key
+# (second column is auto increment column). Such a definition is allowed only
+# with 'myisam' engine.
+CREATE TABLE t1(i int, id INT AUTO_INCREMENT, PRIMARY KEY (i, id)) ENGINE=MYISAM;
+
+# Step-3.2: Inserting into such a table is unsafe.
+INSERT INTO t1 (i) values (1);
+
+# Step-3.3: Repeat step 3.2, now with 'LOCK TABLES' logic.
+START TRANSACTION;
+LOCK TABLES t1 WRITE;
+INSERT INTO t1 (i) values (2);
+UNLOCK TABLES;
+COMMIT;
+
+# Step-3.4: Sync slave with master
+--sync_slave_with_master
+
+# Step-3.5: Diff master-slave tables to make sure everything is in sync.
+--let $diff_tables=master:t1, slave:t1
+--source include/diff_tables.inc
+
+# Step-3.6: Cleanup
+--connection master
+DROP TABLE t1;
+
+# Case-4: BINLOG_STMT_UNSAFE_INSERT_TWO_KEYS
+# INSERT... ON DUPLICATE KEY UPDATE on a table with more than one UNIQUE KEY
+# is unsafe Statement
+
+# Step-4.1: Create a table with two unique keys
+CREATE TABLE t1(i INT, j INT, UNIQUE KEY(i), UNIQUE KEY(j)) ENGINE=INNODB;
+
+# Step-4.2: Inserting into such a table is unsafe.
+INSERT INTO t1 (i,j) VALUES (1,2) ON DUPLICATE KEY UPDATE j=j+1;
+
+# Step-4.3: Repeat step 3.2, now with 'LOCK TABLES' logic.
+START TRANSACTION;
+LOCK TABLES t1 WRITE;
+INSERT INTO t1 (i,j) VALUES (1,2) ON DUPLICATE KEY UPDATE j=j+1;
+UNLOCK TABLES;
+COMMIT;
+
+# Step-4.4: Sync slave with master
+--sync_slave_with_master
+
+# Step-4.5: Diff master-slave tables to make sure everything is in sync.
+--let $diff_tables=master:t1, slave:t1
+--source include/diff_tables.inc
+
+# Step-4.6: Cleanup
+--connection master
+DROP TABLE t1;
+
+# Case-5: BINLOG_STMT_UNSAFE_SKIP_LOCKED
+# INSERT... ON KEY UPDATE SKIP LOCKED is unsafe Statement
+
+# Step-5.1: Create a table some index
+CREATE TABLE t1(i INT,PRIMARY KEY(i)) ENGINE=INNODB;
+CREATE TABLE t2(i INT,PRIMARY KEY(i)) ENGINE=INNODB;
+
+# Step-5.2: Inserting some values
+INSERT INTO t1 (i) VALUES (1),(2),(3),(4),(5);
+
+# Step-5.3: Lock one of the values
+connect (con1, localhost, root,);
+START TRANSACTION;
+SELECT i FROM t1 WHERE i=3 FOR UPDATE;
+
+# Step-5.4: Create non-deterministic inserts/tables
+--connection master
+INSERT INTO t2 SELECT i FROM t1 LOCK IN SHARE MODE SKIP LOCKED;
+CREATE TABLE t3 AS SELECT i FROM t1 LOCK IN SHARE MODE SKIP LOCKED;
+SELECT * FROM t2 ORDER BY i;
+SELECT * FROM t3 ORDER BY i;
+
+# Step-5.5: Sync slave with master
+--sync_slave_with_master
+
+# Step-5.6: Diff master-replica tables insert statements are in sync
+--let $diff_tables=master:t2, slave:t2
+--source include/diff_tables.inc
+
+# Step-5.7: Diff master-replica tables create select table is in sync
+--let $diff_tables=master:t3, slave:t3
+--source include/diff_tables.inc
+
+# Step-5.8: Cleanup
+--disconnect con1
+--connection master
+DROP TABLE t1, t2, t3;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_update.test b/mysql-test/suite/rpl/t/rpl_update.test
new file mode 100644
index 00000000..b3807877
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_update.test
@@ -0,0 +1,15 @@
+source include/master-slave.inc;
+
+#
+# MDEV-13417 UPDATE produces wrong values if an updated column is later used as an update source
+#
+set sql_mode=simultaneous_assignment;
+create table t1 (a int, b int);
+insert into t1 values(1, 2);
+update t1 set a=b, b=a;
+select * from t1;
+sync_slave_with_master;
+select * from t1;
+connection master;
+drop table t1;
+source include/rpl_end.inc;
diff --git a/mysql-test/suite/rpl/t/rpl_upgrade_master_info.test b/mysql-test/suite/rpl/t/rpl_upgrade_master_info.test
new file mode 100644
index 00000000..fb0e3cf4
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_upgrade_master_info.test
@@ -0,0 +1,167 @@
+--source include/master-slave.inc
+
+--echo *** MDEV-9383: Server fails to read master.info after upgrade 10.0 -> 10.1 ***
+
+--connection slave
+--source include/stop_slave.inc
+--let $datadir= `SELECT @@datadir`
+
+--let $rpl_server_number= 2
+--source include/rpl_stop_server.inc
+
+--remove_file $datadir/master.info
+--copy_file $MYSQL_TEST_DIR/std_data/bad_master.info $datadir/master.info
+
+--let $rpl_server_number= 2
+--source include/rpl_start_server.inc
+
+--source include/wait_until_connected_again.inc
+
+--connection master
+CREATE TABLE t1 (a INT PRIMARY KEY);
+INSERT INTO t1 VALUES (1);
+--source include/save_master_gtid.inc
+
+--connection slave
+# Fix the port after we replaced master.info.
+--replace_result $SERVER_MYPORT_1 SERVER_MYPORT_1
+eval CHANGE MASTER TO master_host='127.0.0.1', master_port=$SERVER_MYPORT_1;
+--source include/start_slave.inc
+--source include/sync_with_master_gtid.inc
+FLUSH NO_WRITE_TO_BINLOG TABLES;
+SELECT * FROM t1;
+
+--source include/stop_slave.inc
+
+--let $rpl_server_number= 2
+--source include/rpl_stop_server.inc
+
+--remove_file $datadir/master.info
+--copy_file $MYSQL_TEST_DIR/std_data/bad2_master.info $datadir/master.info
+
+--let $rpl_server_number= 2
+--source include/rpl_start_server.inc
+
+--source include/wait_until_connected_again.inc
+
+--connection master
+INSERT INTO t1 VALUES (2);
+--source include/save_master_gtid.inc
+
+--connection slave
+# Fix the port after we replaced master.info.
+--replace_result $SERVER_MYPORT_1 SERVER_MYPORT_1
+eval CHANGE MASTER TO master_host='127.0.0.1', master_port=$SERVER_MYPORT_1;
+--source include/start_slave.inc
+--source include/sync_with_master_gtid.inc
+FLUSH NO_WRITE_TO_BINLOG TABLES;
+SELECT * FROM t1 ORDER BY a;
+
+--source include/stop_slave.inc
+
+--let $rpl_server_number= 2
+--source include/rpl_stop_server.inc
+
+--remove_file $datadir/master.info
+--copy_file $MYSQL_TEST_DIR/std_data/bad3_master.info $datadir/master.info
+
+--let $rpl_server_number= 2
+--source include/rpl_start_server.inc
+
+--source include/wait_until_connected_again.inc
+
+--connection master
+INSERT INTO t1 VALUES (3);
+--source include/save_master_gtid.inc
+
+--connection slave
+# Fix the port after we replaced master.info.
+--replace_result $SERVER_MYPORT_1 SERVER_MYPORT_1
+eval CHANGE MASTER TO master_host='127.0.0.1', master_port=$SERVER_MYPORT_1;
+--source include/start_slave.inc
+--source include/sync_with_master_gtid.inc
+FLUSH NO_WRITE_TO_BINLOG TABLES;
+SELECT * FROM t1 ORDER BY a;
+
+--source include/stop_slave.inc
+
+--let $rpl_server_number= 2
+--source include/rpl_stop_server.inc
+
+--remove_file $datadir/master.info
+--copy_file $MYSQL_TEST_DIR/std_data/bad4_master.info $datadir/master.info
+
+--let $rpl_server_number= 2
+--source include/rpl_start_server.inc
+
+--source include/wait_until_connected_again.inc
+
+--connection master
+INSERT INTO t1 VALUES (4);
+--source include/save_master_gtid.inc
+
+--connection slave
+# Fix the port after we replaced master.info.
+--replace_result $SERVER_MYPORT_1 SERVER_MYPORT_1
+eval CHANGE MASTER TO master_host='127.0.0.1', master_port=$SERVER_MYPORT_1;
+--source include/start_slave.inc
+--source include/sync_with_master_gtid.inc
+FLUSH NO_WRITE_TO_BINLOG TABLES;
+SELECT * FROM t1 ORDER BY a;
+
+--source include/stop_slave.inc
+
+--let $rpl_server_number= 2
+--source include/rpl_stop_server.inc
+
+--remove_file $datadir/master.info
+--copy_file $MYSQL_TEST_DIR/std_data/bad5_master.info $datadir/master.info
+
+--let $rpl_server_number= 2
+--source include/rpl_start_server.inc
+
+--source include/wait_until_connected_again.inc
+
+--connection master
+INSERT INTO t1 VALUES (5);
+--source include/save_master_gtid.inc
+
+--connection slave
+# Fix the port after we replaced master.info.
+--replace_result $SERVER_MYPORT_1 SERVER_MYPORT_1
+eval CHANGE MASTER TO master_host='127.0.0.1', master_port=$SERVER_MYPORT_1;
+--source include/start_slave.inc
+--source include/sync_with_master_gtid.inc
+FLUSH NO_WRITE_TO_BINLOG TABLES;
+SELECT * FROM t1 ORDER BY a;
+
+--source include/stop_slave.inc
+
+--let $rpl_server_number= 2
+--source include/rpl_stop_server.inc
+
+--remove_file $datadir/master.info
+--copy_file $MYSQL_TEST_DIR/std_data/bad6_master.info $datadir/master.info
+
+--let $rpl_server_number= 2
+--source include/rpl_start_server.inc
+
+--source include/wait_until_connected_again.inc
+
+--connection master
+INSERT INTO t1 VALUES (6);
+--source include/save_master_gtid.inc
+
+--connection slave
+# Fix the port after we replaced master.info.
+--replace_result $SERVER_MYPORT_1 SERVER_MYPORT_1
+eval CHANGE MASTER TO master_host='127.0.0.1', master_port=$SERVER_MYPORT_1;
+--source include/start_slave.inc
+--source include/sync_with_master_gtid.inc
+SELECT * FROM t1 ORDER BY a;
+
+
+# Cleanup
+--connection master
+DROP TABLE t1;
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_user.test b/mysql-test/suite/rpl/t/rpl_user.test
new file mode 100644
index 00000000..079c2bf2
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_user.test
@@ -0,0 +1,73 @@
+# BUG#33862 completely failed DROP USER statement gets replicated
+
+--source include/master-slave.inc
+
+#
+# remove all users will be used in the test
+#
+connection master;
+set session sql_log_bin=0;
+delete from mysql.user where Host='fakehost';
+set session sql_log_bin=1;
+
+connection slave;
+set session sql_log_bin=0;
+delete from mysql.user where Host='fakehost';
+set session sql_log_bin=1;
+
+#
+# Test create user
+#
+connection master;
+create user 'foo'@'fakehost';
+--error ER_CANNOT_USER
+create user 'foo'@'fakehost', 'bar'@'fakehost';
+--error ER_CANNOT_USER
+create user 'foo'@'fakehost', 'bar'@'fakehost';
+
+sync_slave_with_master;
+select Host,User from mysql.user where Host='fakehost';
+
+#
+# Test rename user
+#
+connection master;
+rename user 'foo'@'fakehost' to 'foofoo'@'fakehost';
+--error ER_CANNOT_USER
+rename user 'not_exist_user1'@'fakehost' to 'foobar'@'fakehost', 'bar'@'fakehost' to 'barbar'@'fakehost';
+--error ER_CANNOT_USER
+rename user 'not_exist_user1'@'fakehost' to 'foobar'@'fakehost', 'not_exist_user2'@'fakehost' to 'barfoo'@'fakehost';
+
+sync_slave_with_master;
+select Host,User from mysql.user where Host='fakehost';
+
+#
+# Test alter user
+#
+connection master;
+alter user 'foofoo'@'fakehost' identified by 'foo';
+--error ER_CANNOT_USER
+alter user 'non_exist_user1'@'fakehost' identified by 'foo', 'barbar'@'fakehost' identified by 'bar';
+--error ER_CANNOT_USER
+alter user 'non_exist_user1'@'fakehost' identified by 'foo', 'non_exist_user2'@'fakehost' identified by 'bar';
+sync_slave_with_master;
+
+#
+# Test drop user
+#
+connection master;
+drop user 'foofoo'@'fakehost';
+--error ER_CANNOT_USER
+drop user 'not_exist_user1'@'fakehost', 'barbar'@'fakehost';
+--error ER_CANNOT_USER
+drop user 'not_exist_user1'@'fakehost', 'not_exist_user2'@'fakehost';
+
+sync_slave_with_master;
+select Host,User from mysql.user where Host='fakehost';
+
+#
+# show the binlog events on the master
+#
+connection master;
+source include/show_binlog_events.inc;
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_user_variables.test b/mysql-test/suite/rpl/t/rpl_user_variables.test
new file mode 100644
index 00000000..08d9b4ae
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_user_variables.test
@@ -0,0 +1,385 @@
+###################################
+#
+# Test of replicating user variables
+#
+###################################
+
+-- source include/master-slave.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 PS as the log positions differs
+--disable_ps_protocol
+
+
+# Clean up old slave's binlogs.
+# The slave is started with --log-slave-updates
+# and this test does SHOW BINLOG EVENTS on the slave's
+# binlog. But previous tests can influence the current test's
+# binlog (e.g. a temporary table in the previous test has not
+# been explicitly deleted, or it has but the slave hasn't had
+# enough time to catch it before STOP SLAVE,
+# and at the beginning of the current
+# test the slave immediately writes DROP TEMPORARY TABLE this_old_table).
+# We wait for the slave to have written all he wants to the binlog
+# (otherwise RESET MASTER may come too early).
+sync_slave_with_master;
+reset master;
+connection master;
+
+create table t1(n char(30));
+set @i1:=12345678901234, @i2:=-12345678901234, @i3:=0, @i4:=-1;
+set @s1:='This is a test', @r1:=12.5, @r2:=-12.5;
+set @n1:=null;
+set @s2:='', @s3:='abc\'def', @s4:= 'abc\\def', @s5:= 'abc''def';
+insert into t1 values (@i1), (@i2), (@i3), (@i4);
+insert into t1 values (@r1), (@r2);
+insert into t1 values (@s1), (@s2), (@s3), (@s4), (@s5);
+insert into t1 values (@n1);
+insert into t1 values (@n2); # not explicitly set before
+insert into t1 values (@a:=0), (@a:=@a+1), (@a:=@a+1);
+insert into t1 values (@a+(@b:=@a+1));
+set @q:='abc';
+insert t1 values (@q), (@q:=concat(@q, 'n1')), (@q:=concat(@q, 'n2'));
+set @a:=5;
+insert into t1 values (@a),(@a);
+# To flush the pending event, we add the following statement. RBR can
+# concatenate the result of several statements, which SBR cannot.
+select * from t1 where n = '<nonexistant>';
+connection master1; # see if variable is reset in binlog when thread changes
+insert into t1 values (@a),(@a),(@a*5);
+SELECT * FROM t1 ORDER BY n;
+sync_slave_with_master;
+SELECT * FROM t1 ORDER BY n;
+connection master;
+insert into t1 select * FROM (select @var1 union select @var2) AS t2;
+drop table t1;
+--echo End of 4.1 tests.
+
+# BUG#20141
+# The following tests ensure that if user-defined variables are used in SF/Triggers
+# that they are replicated correctly. These tests should be run in both SBR and RBR
+# modes.
+
+# This test uses a procedure that inserts data values based on the value of a
+# user-defined variable. It also has a trigger that inserts data based on the
+# same variable. Successful test runs show that the @var is replicated
+# properly and that the procedure and trigger insert the correct data on the
+# slave.
+#
+# The test of stored procedure was included for completeness. Replication of stored
+# procedures was not directly affected by BUG#20141.
+#
+# This test was constructed for BUG#20141
+
+--disable_warnings
+DROP TABLE IF EXISTS t20;
+DROP TABLE IF EXISTS t21;
+DROP PROCEDURE IF EXISTS test.insert;
+--enable_warnings
+
+CREATE TABLE t20 (a VARCHAR(20));
+CREATE TABLE t21 (a VARCHAR(20));
+DELIMITER |;
+
+# Create a procedure that uses the @var for flow control
+
+CREATE PROCEDURE test.insert()
+BEGIN
+ IF (@VAR)
+ THEN
+ INSERT INTO test.t20 VALUES ('SP_TRUE');
+ ELSE
+ INSERT INTO test.t20 VALUES ('SP_FALSE');
+ END IF;
+END|
+
+# Create a trigger that uses the @var for flow control
+
+CREATE TRIGGER test.insert_bi BEFORE INSERT
+ ON test.t20 FOR EACH ROW
+ BEGIN
+ IF (@VAR)
+ THEN
+ INSERT INTO test.t21 VALUES ('TRIG_TRUE');
+ ELSE
+ INSERT INTO test.t21 VALUES ('TRIG_FALSE');
+ END IF;
+ END|
+DELIMITER ;|
+
+sync_slave_with_master;
+connection master;
+
+# Set @var and call the procedure, repeat with different values
+
+SET @VAR=0;
+CALL test.insert();
+SET @VAR=1;
+CALL test.insert();
+
+--echo Check the tables for correct data
+
+SELECT * FROM t20;
+SELECT * FROM t21;
+
+sync_slave_with_master;
+
+--echo Check the tables for correct data and it matches master
+
+SELECT * FROM t20;
+SELECT * FROM t21;
+connection master;
+
+# Cleanup
+
+DROP TABLE t20;
+DROP TABLE t21;
+DROP PROCEDURE test.insert;
+
+# This test uses a stored function that uses user-defined variables to return data
+# This test was constructed for BUG#20141
+
+--disable_warnings
+DROP TABLE IF EXISTS t1;
+DROP FUNCTION IF EXISTS test.square;
+--enable_warnings
+
+CREATE TABLE t1 (i INT);
+
+# Create function that returns a value from @var. In this case, the square function
+
+CREATE FUNCTION test.square() RETURNS INTEGER DETERMINISTIC RETURN
+(@var * @var);
+
+# Set the @var to different values and insert them into a table
+
+SET @var = 1;
+INSERT INTO t1 VALUES (square());
+SET @var = 2;
+INSERT INTO t1 VALUES (square());
+SET @var = 3;
+INSERT INTO t1 VALUES (square());
+SET @var = 4;
+INSERT INTO t1 VALUES (square());
+SET @var = 5;
+INSERT INTO t1 VALUES (square());
+
+--echo Retrieve the values from the table
+
+SELECT * FROM t1;
+
+sync_slave_with_master;
+
+--echo Retrieve the values from the table and verify they are the same as on master
+
+SELECT * FROM t1;
+
+connection master;
+
+# Cleanup
+
+DROP TABLE t1;
+DROP FUNCTION test.square;
+
+# This test uses stored functions that uses user-defined variables to return data
+# based on the use of @vars inside a function body.
+# This test was constructed for BUG#14914
+
+--disable_warnings
+DROP TABLE IF EXISTS t1;
+DROP FUNCTION IF EXISTS f1;
+DROP FUNCTION IF EXISTS f2;
+--enable_warnings
+
+CREATE TABLE t1(a int);
+DELIMITER |;
+
+# Create a function that simply returns the value of an @var.
+# Create a function that uses an @var for flow control, creates and uses another
+# @var and sets its value to a value based on another @var.
+
+CREATE FUNCTION f1() returns int deterministic BEGIN
+ return @a;
+END |
+
+CREATE FUNCTION f2() returns int deterministic BEGIN
+ IF (@b > 0) then
+ SET @c = (@a + @b);
+ else
+ SET @c = (@a - 1);
+ END if;
+ return @c;
+END |
+DELIMITER ;|
+
+sync_slave_with_master;
+connection master;
+
+# Set an @var to a value and insert data into a table using the first function.
+# Set two more @vars to some values and insert data into a table using the second function.
+
+SET @a=500;
+INSERT INTO t1 values(f1());
+SET @b = 125;
+SET @c = 1;
+INSERT INTO t1 values(f2());
+
+--echo Retrieve the values from the table
+
+sync_slave_with_master;
+connection master;
+
+SELECT * from t1;
+
+connection slave;
+
+--echo Check the tables for correct data and it matches master
+
+SELECT * from t1;
+
+connection master;
+
+# Cleanup
+
+DROP TABLE t1;
+DROP FUNCTION f1;
+DROP FUNCTION f2;
+
+# This test uses a function that changes a user-defined variable in its body. This test
+# will ensure the @vars are replicated when needed and not interrupt the normal execution
+# of the function on the slave. This also applies to procedures and triggers.
+
+# This test was constructed for BUG#25167
+
+--disable_warnings
+DROP TABLE IF EXISTS t1;
+DROP TABLE IF EXISTS t2;
+--enable_warnings
+CREATE TABLE t1 (i int);
+CREATE TABLE t2 (k int);
+DELIMITER |;
+
+# Create a trigger that inserts data into another table, changes the @var then inserts
+# another row with the modified value.
+
+CREATE trigger t1_bi before INSERT on t1 for each row BEGIN
+ INSERT INTO t2 values (@a);
+ SET @a:=42;
+ INSERT INTO t2 values (@a);
+END |
+DELIMITER ;|
+
+sync_slave_with_master;
+connection master;
+
+# Set the @var to a value then insert data into first table.
+
+SET @a:=100;
+INSERT INTO t1 values (5);
+
+--echo Check to see that data was inserted correctly in both tables
+
+SELECT * from t1;
+SELECT * from t2;
+
+sync_slave_with_master;
+
+--echo Check the tables for correct data and it matches master
+
+SELECT * from t1;
+SELECT * from t2;
+
+connection master;
+drop table t1, t2;
+
+#
+# Bug #12826: Possible to get inconsistent slave using SQL syntax Prepared Statements
+#
+connection master;
+create table t1(a int, b int);
+prepare s1 from 'insert into t1 values (@x:=@x+1, ?)';
+set @x=1; execute s1 using @x;
+select * from t1;
+sync_slave_with_master;
+connection slave;
+select * from t1;
+connection master;
+drop table t1;
+
+#
+# Bug#33851: Passing UNSIGNED param to EXECUTE returns ERROR 1210
+#
+
+connection master;
+create table t1(a int);
+insert into t1 values (1),(2);
+prepare s1 from 'insert into t1 select a from t1 limit ?';
+set @x='1.1';
+--disable_warnings
+execute s1 using @x;
+--enable_warnings
+select * from t1;
+sync_slave_with_master;
+connection slave;
+select * from t1;
+connection master;
+drop table t1;
+
+--echo End of 5.0 tests.
+
+# This test uses a stored function that uses user-defined variables to return data
+# The test ensures the value of the user-defined variable is replicated correctly
+# and in the correct order of assignment.
+
+# This test was constructed for BUG#20141
+
+--disable_warnings
+DROP FUNCTION IF EXISTS f1;
+DROP FUNCTION IF EXISTS f2;
+--enable_warnings
+
+CREATE TABLE t1 (i INT);
+
+# Create two functions. One simply returns the user-defined variable. The other
+# returns a value based on the user-defined variable.
+
+CREATE FUNCTION f1() RETURNS INT RETURN @a; DELIMITER |; CREATE
+FUNCTION f2() RETURNS INT BEGIN
+ INSERT INTO t1 VALUES (10 + @a);
+ RETURN 0;
+END|
+DELIMITER ;|
+
+sync_slave_with_master;
+connection master;
+
+# Set the variable and execute the functions.
+
+SET @a:=123;
+SELECT f1(), f2();
+
+--echo Check to see that data was inserted correctly
+
+INSERT INTO t1 VALUES(f1());
+SELECT * FROM t1;
+
+sync_slave_with_master;
+
+--echo Check the table for correct data and it matches master
+
+SELECT * FROM t1;
+
+connection master;
+
+# Cleanup
+
+DROP FUNCTION f1;
+DROP FUNCTION f2;
+DROP TABLE t1;
+
+sync_slave_with_master;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_using_gtid_default.test b/mysql-test/suite/rpl/t/rpl_using_gtid_default.test
new file mode 100644
index 00000000..eab5b4dd
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_using_gtid_default.test
@@ -0,0 +1,303 @@
+#
+# Purpose:
+# This test ensures that a replica's default value for Using_Gtid is set
+# correctly. Specifically, it should default to 'Slave_Pos' unless the primary
+# server does not support GTIDs (if its version is less than 10), in which case
+# the replica should fall back to 'No'.
+#
+# Methodology:
+# Validate the value of Using_Gtid on replica initialization and after
+# RESET SLAVE commands. Specifically, we validate the following use cases:
+#
+# Case 1) A replica will initialize with Slave_Pos if the primary supports
+# GTIDs
+# Case 2) A replica configured with the Using_Gtid=Slave_Pos issued
+# RESET SLAVE will preserve Using_Gtid without any informational
+# messages.
+# Case 3) A replica configured with Using_Gtid=No against a master which
+# supports GTIDs will revert to Using_Gtid=Slave_Pos after issued
+# RESET SLAVE and provide an informational note
+# Case 4) A fresh replica targeting a primary which does not support GTIDs
+# will fall back to Using_Gtid=No when starting. An informational
+# message should be logged.
+# Case 5) A replica connected to a primary which does not support GTIDs
+# should preserve Using_Gtid=No when issued RESET SLAVE. No message
+# should be provided to the user.
+# Case 6) A replica configured with Using_Gtid=Current_Pos should revert
+# to Slave_Pos when issued RESET SLAVE. An informational message
+# should be provided to the user.
+# Case 7) The MTR include file rpl_change_topology.inc should implicitly
+# set MASTER_USE_GTID=NO when provided with $rpl_master_log_file
+# Case 8) The MTR include file reset_slave.inc should keep/delete GTID state
+# when reset_slave_keep_gtid_state is set, respectively.
+# Case 9) A replica issued CHANGE MASTER TO specified with log coordinates
+# but not master_use_gtid=No should warn the user that Using_Gtid is
+# being changed to No.
+# Case 10) A replica issued CHANGE MASTER TO specified with log coordinates
+# and master_use_gtid=Slave_Pos should warn the user that the log
+# coordinates will be ignored.
+#
+# References:
+# MDEV-19801: Change defaults for CHANGE MASTER TO so that GTID-based
+# replication is used by default if master supports it
+#
+--source include/have_debug.inc
+--source include/master-slave.inc
+
+# Format independent test so just use one
+--source include/have_binlog_format_mixed.inc
+
+--echo #
+--echo # Slave default configuration should be Slave_Pos
+--let $expected_default_using_gtid= Slave_Pos
+--connection slave
+--let $using_gtid= query_get_value(SHOW SLAVE STATUS, Using_Gtid, 1)
+if ($using_gtid != $expected_default_using_gtid)
+{
+ --die Using_Gtid had wrong default value of '$using_gtid' when it should have been '$expected_default_using_gtid'
+}
+
+--echo #
+--echo # Ensure that a slave configured with Using_Gtid=Slave_Pos will remain
+--echo # as Slave_Pos after RESET SLAVE
+--source include/stop_slave.inc
+RESET SLAVE;
+--echo # No warning should be given because Slave_Pos never changed
+SHOW WARNINGS;
+--source include/start_slave.inc
+--let $using_gtid= query_get_value(SHOW SLAVE STATUS, Using_Gtid, 1)
+if ($using_gtid != $expected_default_using_gtid)
+{
+ --die Using_Gtid has wrong value of '$using_gtid' when it should be '$expected_default_using_gtid'
+}
+
+
+--echo #
+--echo # Ensure that a slave configured with Using_Gtid=No will revert to its
+--echo # default of Slave_Pos after RESET SLAVE for a master which supports
+--echo # GTIDs
+
+--source include/stop_slave.inc
+CHANGE MASTER TO MASTER_USE_GTID=NO;
+--source include/start_slave.inc
+--source include/stop_slave.inc
+RESET SLAVE;
+--echo # A notification that Using_Gtid was reverted should exist
+SHOW WARNINGS;
+--source include/start_slave.inc
+--let $using_gtid= query_get_value(SHOW SLAVE STATUS, Using_Gtid, 1)
+if ($using_gtid != $expected_default_using_gtid)
+{
+ --die Using_Gtid has wrong value of '$using_gtid' when it should be '$expected_default_using_gtid'
+}
+
+--echo # Clear SHOW WARNINGS
+--disable_query_log
+set SQL_LOG_BIN=0;
+CREATE TABLE t1 (a int);
+DROP TABLE t1;
+set SQL_LOG_BIN=1;
+--enable_query_log
+
+
+--echo #
+--echo # If the primary does not support GTIDs (version < 10), the replica
+--echo # should fall back to Using_Gtid=No on slave start, and should not
+--echo # revert Using_Gtid to Slave_Pos after RESET SLAVE
+
+--source include/stop_slave.inc
+RESET SLAVE ALL;
+
+--replace_result $MASTER_MYPORT MASTER_MYPORT
+--eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=$MASTER_MYPORT, MASTER_USER='root', MASTER_CONNECT_RETRY=1
+SET @saved_dbug= @@GLOBAL.debug_dbug;
+set @@global.debug_dbug= "d,mock_mariadb_primary_v5_in_get_master_version";
+--source include/start_slave.inc
+
+--echo # Replica should detect at start that the primary does not support GTIDs
+--echo # and fall-back to Using_Gtid=No
+--let $using_gtid= query_get_value(SHOW SLAVE STATUS, Using_Gtid, 1)
+if ($using_gtid != 'No')
+{
+ --die Using_Gtid has wrong value of '$using_gtid' when it should be 'No'
+}
+
+--echo # Replica should have an informational message stating it is falling
+--echo # back to Using_Gtid=No
+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.2.err;
+}
+--let SEARCH_FILE=$log_error_
+--let SEARCH_PATTERN=Falling back to Using_Gtid=No because master does not support GTIDs
+--source include/search_pattern_in_file.inc
+
+--source include/stop_slave.inc
+RESET SLAVE;
+
+--echo # Replica should know that the primary does not support GTIDs and
+--echo # preserve Using_Gtid=No
+--let $using_gtid= query_get_value(SHOW SLAVE STATUS, Using_Gtid, 1)
+if ($using_gtid != 'No')
+{
+ --die Using_Gtid has wrong value of '$using_gtid' when it should be 'No'
+}
+--echo # 'No' was not reverted and therefore no note should be added
+SHOW WARNINGS;
+set @@global.debug_dbug= @saved_dbug;
+--source include/start_slave.inc
+
+
+--echo #
+--echo # Ensure that a slave configured with Using_Gtid=Current_Pos will revert
+--echo # to its default of Slave_Pos after RESET SLAVE.
+
+--source include/stop_slave.inc
+CHANGE MASTER TO MASTER_USE_GTID=Current_Pos;
+--source include/start_slave.inc
+--source include/stop_slave.inc
+RESET SLAVE;
+--echo # A notification that Using_Gtid was reverted should exist
+SHOW WARNINGS;
+--source include/start_slave.inc
+--let $using_gtid= query_get_value(SHOW SLAVE STATUS, Using_Gtid, 1)
+if ($using_gtid != $expected_default_using_gtid)
+{
+ --die Using_Gtid has wrong value of '$using_gtid' when it should be '$expected_default_using_gtid'
+}
+
+--echo # Clear SHOW WARNINGS
+--disable_query_log
+set SQL_LOG_BIN=0;
+CREATE TABLE t1 (a int);
+DROP TABLE t1;
+set SQL_LOG_BIN=1;
+--enable_query_log
+
+--echo # The MTR include file rpl_change_topology.inc should implicitly set
+--echo # MASTER_USE_GTID=NO when provided with \$rpl_master_log_file. Note that
+--echo # this will switch master and slave roles.
+--connection slave
+--source include/stop_slave.inc
+--let $pos_c= query_get_value(SHOW SLAVE STATUS, Exec_Master_Log_Pos, 1)
+--let $file_c= query_get_value(SHOW SLAVE STATUS, Master_Log_File, 1)
+--let $rpl_master_log_file= 2:$file_c
+--let $rpl_master_log_pos= 2:$pos_c
+--let $rpl_topology= 2->1
+--source include/rpl_change_topology.inc
+
+--echo # connection 'master' is the slave in this comparison
+--connection master
+--let $using_gtid= query_get_value(SHOW SLAVE STATUS, Using_Gtid, 1)
+--echo # Validating Using_Gtid=No..
+if (`SELECT strcmp("$using_gtid","No") != 0`)
+{
+ --die Using_Gtid should be No when calling rpl_change_topology with \$rpl_master_log_file set
+}
+--echo # ..success
+
+--let $rpl_master_log_file=
+--let $rpl_topology= 1->2
+--source include/rpl_change_topology.inc
+
+--echo # connection 'slave' is back to slave role
+--connection slave
+--let $using_gtid= query_get_value(SHOW SLAVE STATUS, Using_Gtid, 1)
+--echo # Validating Using_Gtid=$expected_default_using_gtid..
+if (`SELECT strcmp("$using_gtid","$expected_default_using_gtid")!= 0`)
+{
+ --die Using_Gtid should be back to $expected_default_using_gtid with empty \$rpl_master_log_file
+}
+--echo # ..success
+--source include/start_slave.inc
+
+--echo #
+--echo # The MTR include file reset_slave.inc should keep/delete GTID state
+--echo # when reset_slave_keep_gtid_state is set, respectively.
+--echo #
+--connection master
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (1);
+DROP TABLE t1;
+--source include/save_master_gtid.inc
+
+--connection slave
+--source include/sync_with_master_gtid.inc
+--source include/stop_slave.inc
+
+--echo # Tagging gtid_slave_pos before reset_slave.inc as old_slave_pos
+--let $old_slave_pos= `SELECT @@gtid_slave_pos`
+if (`SELECT strcmp("$old_slave_pos","") = 0`)
+{
+ die gtid_slave_pos is empty but should not be;
+}
+
+--echo # Using reset_slave_keep_gtid_state=1 should preserve GTID state
+--let $master_use_gtid_option=Slave_Pos
+--let $reset_slave_keep_gtid_state=1
+--source include/reset_slave.inc
+
+--echo # Tagging gtid_slave_pos after reset_slave.inc as new_slave_pos
+--let $new_slave_pos= `SELECT @@gtid_slave_pos`
+--echo # Validating old_slave_pos == new_slave_pos..
+if ($old_slave_pos != $new_slave_pos)
+{
+ die gtid_slave_pos unexpectedly changed after running reset_slave.inc;
+}
+--echo # ..success
+
+--echo # Using reset_slave_keep_gtid_state=0 should empty GTID state
+--let $master_use_gtid_option=Slave_Pos
+--let $reset_slave_keep_gtid_state=0
+--source include/reset_slave.inc
+
+--echo # Tagging gtid_slave_pos as new_slave_pos
+--let $new_slave_pos= `SELECT @@gtid_slave_pos`
+--echo # Validating new_slave_pos is empty..
+if (`SELECT strcmp("$new_slave_pos","") != 0`)
+{
+ die gtid_slave_pos should be empty after reset_slave.inc without keeping gtid state;
+}
+--echo # ..success
+--replace_result $old_slave_pos old_slave_pos
+eval set global gtid_slave_pos="$old_slave_pos";
+--source include/start_slave.inc
+
+--echo #
+--echo # A replica issued CHANGE MASTER TO specified with log coordinates but
+--echo # not master_use_gtid=no should warn the user that Using_Gtid is being
+--echo # changed to No.
+--echo #
+--connection slave
+--let $io_log_pos= query_get_value('SHOW SLAVE STATUS', Read_Master_Log_Pos, 1)
+--let $io_log_file= query_get_value('SHOW SLAVE STATUS', Master_Log_File, 1)
+--source include/stop_slave.inc
+--replace_result $io_log_file io_log_file $io_log_pos io_log_pos
+--eval CHANGE MASTER TO master_log_pos=$io_log_pos, master_log_file='$io_log_file'
+--source include/start_slave.inc
+
+
+--echo #
+--echo # A replica issued CHANGE MASTER TO specified with log coordinates and
+--echo # master_use_gtid=Slave_Pos should warn the user that the log
+--echo # coordinates will be ignored.
+--echo #
+--connection slave
+--let $io_log_pos= query_get_value('SHOW SLAVE STATUS', Read_Master_Log_Pos, 1)
+--let $io_log_file= query_get_value('SHOW SLAVE STATUS', Master_Log_File, 1)
+--let $relay_log_pos= 4
+--let $relay_log_file= slave-relay-bin.000001
+--source include/stop_slave.inc
+--replace_result $io_log_file io_log_file $io_log_pos io_log_pos
+--eval CHANGE MASTER TO master_log_pos=$io_log_pos, master_log_file='$io_log_file', master_use_gtid=Slave_Pos
+--replace_result $relay_log_file relay_log_file $relay_log_pos relay_log_pos
+--eval CHANGE MASTER TO relay_log_pos=$relay_log_pos, relay_log_file='$relay_log_file', master_use_gtid=Slave_Pos
+--source include/start_slave.inc
+
+--source include/rpl_end.inc
+
+--echo #
+--echo # End of rpl_using_gtid_default.test
diff --git a/mysql-test/suite/rpl/t/rpl_variables.test b/mysql-test/suite/rpl/t/rpl_variables.test
new file mode 100644
index 00000000..f6e88c5a
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_variables.test
@@ -0,0 +1,739 @@
+# ==== Purpose ====
+#
+# Test that queries referencing variables are replicated correctly in
+# mixed and row-based logging mode.
+#
+#
+# ==== Method ====
+#
+# The test simply does a lot of "INSERT INTO t1 VALUES (@@variable)"
+# and checks the result on the slave.
+#
+# Statements referencing a variable only replicate correctly in mixed
+# and row mode: in row mode, the values inserted are replicated. In
+# mixed mode, statements referencing a variable are marked as unsafe,
+# meaning they will be replicated by row. In statement mode, the
+# slave's value will be used and replication will break. (Except in a
+# small number of special cases: random seeds, insert_id, and
+# auto_increment are replicated).
+#
+# We test the following variable scopes:
+# - server system variables
+# - server session variables
+# - server "both" variables
+# - user variables
+#
+# For each scope, we use variables of the following types if they
+# exist:
+# - boolean
+# - numeric
+# - string
+# - enumeration variables
+#
+# We use these types of variables in the following contexts:
+# - directly
+# - from a stored procedure
+# - from a stored function
+# - from a trigger
+# - from a prepared statement
+#
+# For all variables where it is possible, we set the variable to one
+# value on slave, and insert it on the master with two distinct
+# values.
+#
+# The same insertions are made in four different tables using direct
+# insert, stored procedure, stored function, or trigger. Then all
+# eight resulting tables on master and slave are compared.
+#
+#
+# ==== Related bugs ====
+#
+# BUG#31168: @@hostname does not replicate
+#
+#
+# ==== Related test cases ====
+#
+# binlog.binlog_unsafe tests that a warning is issued if system
+# variables are replicated in statement mode.
+#
+# rpl.rpl_variables_stm tests the small subset of variables that
+# actually can be replicated safely in statement mode.
+
+
+source include/have_binlog_format_mixed_or_row.inc;
+source include/master-slave.inc;
+
+
+--echo ==== Initialization ====
+
+# Backup the values of global variables so that they can be restored
+# later.
+connection master;
+SET @m_default_week_format= @@global.default_week_format;
+SET @m_init_slave= @@global.init_slave;
+SET @m_lc_time_names= @@global.lc_time_names;
+SET @m_low_priority_updates= @@global.low_priority_updates;
+SET @m_relay_log_purge= @@global.relay_log_purge;
+SET @m_slave_exec_mode= @@global.slave_exec_mode;
+SET @m_sql_mode= @@global.sql_mode;
+SET @m_sync_binlog= @@global.sync_binlog;
+
+connection slave;
+SET @s_default_week_format= @@global.default_week_format;
+SET @s_init_slave= @@global.init_slave;
+SET @s_lc_time_names= @@global.lc_time_names;
+SET @s_low_priority_updates= @@global.low_priority_updates;
+SET @s_relay_log_purge= @@global.relay_log_purge;
+SET @s_slave_exec_mode= @@global.slave_exec_mode;
+SET @s_sql_mode= @@global.sql_mode;
+SET @s_sync_binlog= @@global.sync_binlog;
+
+# Set global variables on slave to something different than on master.
+SET @@global.relay_log_purge = OFF;
+SET @@global.sync_binlog = 1000000;
+SET @@global.slave_exec_mode = 'STRICT';
+SET @@sql_big_selects = OFF;
+SET @@last_insert_id = 10;
+SET @@global.low_priority_updates = OFF;
+SET @@local.low_priority_updates = OFF;
+SET @@global.default_week_format = 1;
+SET @@local.default_week_format = 2;
+SET @@global.lc_time_names = 'zh_HK';
+SET @@local.lc_time_names = 'zh_TW';
+SET @@global.sql_mode = 'ALLOW_INVALID_DATES';
+SET @@local.sql_mode = 'ANSI_QUOTES,ERROR_FOR_DIVISION_BY_ZERO,HIGH_NOT_PRECEDENCE';
+SET @user_num = 10;
+SET @user_text = 'Alunda';
+
+# Stop slave so that we get a fresh sql thread, reading the slave's
+# global values of variables into its local copies.
+--source include/stop_slave.inc
+--source include/start_slave.inc
+
+# We would have wanted to set this together with the other variables
+# above, but can't because it affects how the slave works.
+SET @@global.init_slave = 'SELECT 1';
+
+
+connection master;
+# checking values of read-only variables
+--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
+query_vertical SELECT @@pid_file, @@datadir;
+--echo **** Relay log variables
+--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
+query_vertical SELECT @@relay_log, @@relay_log_index, @@relay_log_basename;
+--echo **** Binary log variables
+--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
+query_vertical SELECT @@log_bin, @@log_bin_index, @@log_bin_basename;
+
+connection slave;
+# checking values of read-only variables
+--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
+query_vertical SELECT @@pid_file, @@datadir;
+--echo **** Relay log variables
+--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
+query_vertical SELECT @@relay_log, @@relay_log_index, @@relay_log_basename;
+--echo **** Binary log variables
+--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
+query_vertical SELECT @@log_bin, @@log_bin_index, @@log_bin_basename;
+
+connection master;
+
+# Tables where everything happens.
+CREATE TABLE tstmt (id INT AUTO_INCREMENT PRIMARY KEY,
+ truth BOOLEAN,
+ num INT,
+ text VARCHAR(100));
+CREATE TABLE tproc LIKE tstmt;
+CREATE TABLE tfunc LIKE tstmt;
+CREATE TABLE ttrig LIKE tstmt;
+CREATE TABLE tprep LIKE tstmt;
+
+# Table on which we put a trigger.
+CREATE TABLE trigger_table (text CHAR(4));
+
+
+--echo ==== Insert variables directly ====
+
+--echo ---- global variables ----
+
+# boolean
+SET @@global.relay_log_purge = ON;
+INSERT INTO tstmt(truth) VALUES (@@global.relay_log_purge);
+SET @@global.relay_log_purge = OFF;
+INSERT INTO tstmt(truth) VALUES (@@global.relay_log_purge);
+
+# numeric
+SET @@global.sync_binlog = 2000000;
+INSERT INTO tstmt(num) VALUES (@@global.sync_binlog);
+SET @@global.sync_binlog = 3000000;
+INSERT INTO tstmt(num) VALUES (@@global.sync_binlog);
+
+# string
+SET @@global.init_slave = 'SELECT 2';
+INSERT INTO tstmt(text) VALUES (@@global.init_slave);
+SET @@global.init_slave = 'SELECT 3';
+INSERT INTO tstmt(text) VALUES (@@global.init_slave);
+
+# enumeration
+SET @@global.slave_exec_mode = 'IDEMPOTENT';
+INSERT INTO tstmt(text) VALUES (@@global.slave_exec_mode);
+SET @@global.slave_exec_mode = 'STRICT';
+INSERT INTO tstmt(text) VALUES (@@global.slave_exec_mode);
+
+
+--echo ---- session variables ----
+
+# boolean
+SET @@sql_big_selects = ON;
+INSERT INTO tstmt(truth) VALUES (@@sql_big_selects);
+SET @@sql_big_selects = OFF;
+INSERT INTO tstmt(truth) VALUES (@@sql_big_selects);
+
+# numeric
+SET @@last_insert_id = 20;
+INSERT INTO tstmt(num) VALUES (@@last_insert_id);
+SET @@last_insert_id = 30;
+INSERT INTO tstmt(num) VALUES (@@last_insert_id);
+
+--echo ---- global and session variables ----
+
+# boolean
+SET @@global.low_priority_updates = ON;
+SET @@local.low_priority_updates = OFF;
+INSERT INTO tstmt(truth) VALUES (@@global.low_priority_updates);
+INSERT INTO tstmt(truth) VALUES (@@local.low_priority_updates);
+SET @@global.low_priority_updates = OFF;
+SET @@local.low_priority_updates = ON;
+INSERT INTO tstmt(truth) VALUES (@@global.low_priority_updates);
+INSERT INTO tstmt(truth) VALUES (@@local.low_priority_updates);
+
+# numeric
+SET @@global.default_week_format = 3;
+SET @@local.default_week_format = 4;
+INSERT INTO tstmt(num) VALUES (@@global.default_week_format);
+INSERT INTO tstmt(num) VALUES (@@local.default_week_format);
+SET @@global.default_week_format = 5;
+SET @@local.default_week_format = 6;
+INSERT INTO tstmt(num) VALUES (@@global.default_week_format);
+INSERT INTO tstmt(num) VALUES (@@local.default_week_format);
+
+# string
+SET @@global.lc_time_names = 'sv_SE';
+SET @@local.lc_time_names = 'sv_FI';
+INSERT INTO tstmt(text) VALUES (@@global.lc_time_names);
+INSERT INTO tstmt(text) VALUES (@@local.lc_time_names);
+SET @@global.lc_time_names = 'ar_TN';
+SET @@local.lc_time_names = 'ar_IQ';
+INSERT INTO tstmt(text) VALUES (@@global.lc_time_names);
+INSERT INTO tstmt(text) VALUES (@@local.lc_time_names);
+
+# enum
+SET @@global.sql_mode = '';
+SET @@local.sql_mode = 'IGNORE_SPACE,NO_AUTO_CREATE_USER';
+INSERT INTO tstmt(text) VALUES (@@global.sql_mode);
+INSERT INTO tstmt(text) VALUES (@@local.sql_mode);
+SET @@global.sql_mode = 'NO_AUTO_VALUE_ON_ZERO,NO_BACKSLASH_ESCAPES,NO_DIR_IN_CREATE,NO_ENGINE_SUBSTITUTION';
+SET @@local.sql_mode = 'NO_FIELD_OPTIONS,NO_KEY_OPTIONS,NO_TABLE_OPTIONS';
+INSERT INTO tstmt(text) VALUES (@@global.sql_mode);
+INSERT INTO tstmt(text) VALUES (@@local.sql_mode);
+
+--echo ---- user variables ----
+
+# numeric
+SET @user_num = 20;
+INSERT INTO tstmt(num) VALUES (@user_num);
+SET @user_num = 30;
+INSERT INTO tstmt(num) VALUES (@user_num);
+
+# string
+SET @user_text = 'Bergsbrunna';
+INSERT INTO tstmt(text) VALUES (@user_text);
+SET @user_text = 'Centrum';
+INSERT INTO tstmt(text) VALUES (@user_text);
+
+
+--echo ==== Insert variables from a stored procedure ====
+
+DELIMITER |;
+CREATE PROCEDURE proc()
+BEGIN
+
+ # GLOBAL
+
+ # boolean
+ SET @@global.relay_log_purge = ON;
+ INSERT INTO tproc(truth) VALUES (@@global.relay_log_purge);
+ SET @@global.relay_log_purge = OFF;
+ INSERT INTO tproc(truth) VALUES (@@global.relay_log_purge);
+
+ # numeric
+ SET @@global.sync_binlog = 2000000;
+ INSERT INTO tproc(num) VALUES (@@global.sync_binlog);
+ SET @@global.sync_binlog = 3000000;
+ INSERT INTO tproc(num) VALUES (@@global.sync_binlog);
+
+ # string
+ SET @@global.init_slave = 'SELECT 2';
+ INSERT INTO tproc(text) VALUES (@@global.init_slave);
+ SET @@global.init_slave = 'SELECT 3';
+ INSERT INTO tproc(text) VALUES (@@global.init_slave);
+
+ # enumeration
+ SET @@global.slave_exec_mode = 'IDEMPOTENT';
+ INSERT INTO tproc(text) VALUES (@@global.slave_exec_mode);
+ SET @@global.slave_exec_mode = 'STRICT';
+ INSERT INTO tproc(text) VALUES (@@global.slave_exec_mode);
+
+ # SESSION
+
+ # boolean
+ SET @@sql_big_selects = ON;
+ INSERT INTO tproc(truth) VALUES (@@sql_big_selects);
+ SET @@sql_big_selects = OFF;
+ INSERT INTO tproc(truth) VALUES (@@sql_big_selects);
+
+ # numeric
+ SET @@last_insert_id = 20;
+ INSERT INTO tproc(num) VALUES (@@last_insert_id);
+ SET @@last_insert_id = 30;
+ INSERT INTO tproc(num) VALUES (@@last_insert_id);
+
+ # BOTH
+
+ # boolean
+ SET @@global.low_priority_updates = ON;
+ SET @@local.low_priority_updates = OFF;
+ INSERT INTO tproc(truth) VALUES (@@global.low_priority_updates);
+ INSERT INTO tproc(truth) VALUES (@@local.low_priority_updates);
+ SET @@global.low_priority_updates = OFF;
+ SET @@local.low_priority_updates = ON;
+ INSERT INTO tproc(truth) VALUES (@@global.low_priority_updates);
+ INSERT INTO tproc(truth) VALUES (@@local.low_priority_updates);
+
+ # numeric
+ SET @@global.default_week_format = 3;
+ SET @@local.default_week_format = 4;
+ INSERT INTO tproc(num) VALUES (@@global.default_week_format);
+ INSERT INTO tproc(num) VALUES (@@local.default_week_format);
+ SET @@global.default_week_format = 5;
+ SET @@local.default_week_format = 6;
+ INSERT INTO tproc(num) VALUES (@@global.default_week_format);
+ INSERT INTO tproc(num) VALUES (@@local.default_week_format);
+
+ # text
+ SET @@global.lc_time_names = 'sv_SE';
+ SET @@local.lc_time_names = 'sv_FI';
+ INSERT INTO tproc(text) VALUES (@@global.lc_time_names);
+ INSERT INTO tproc(text) VALUES (@@local.lc_time_names);
+ SET @@global.lc_time_names = 'ar_TN';
+ SET @@local.lc_time_names = 'ar_IQ';
+ INSERT INTO tproc(text) VALUES (@@global.lc_time_names);
+ INSERT INTO tproc(text) VALUES (@@local.lc_time_names);
+
+ # enum
+ SET @@global.sql_mode = '';
+ SET @@local.sql_mode = 'IGNORE_SPACE,NO_AUTO_CREATE_USER';
+ INSERT INTO tproc(text) VALUES (@@global.sql_mode);
+ INSERT INTO tproc(text) VALUES (@@local.sql_mode);
+ SET @@global.sql_mode = 'NO_AUTO_VALUE_ON_ZERO,NO_BACKSLASH_ESCAPES,NO_DIR_IN_CREATE,NO_ENGINE_SUBSTITUTION';
+ SET @@local.sql_mode = 'NO_FIELD_OPTIONS,NO_KEY_OPTIONS,NO_TABLE_OPTIONS';
+ INSERT INTO tproc(text) VALUES (@@global.sql_mode);
+ INSERT INTO tproc(text) VALUES (@@local.sql_mode);
+
+ # USER
+
+ # numeric
+ SET @user_num = 20;
+ INSERT INTO tproc(num) VALUES (@user_num);
+ SET @user_num = 30;
+ INSERT INTO tproc(num) VALUES (@user_num);
+
+ # string
+ SET @user_text = 'Bergsbrunna';
+ INSERT INTO tproc(text) VALUES (@user_text);
+ SET @user_text = 'Centrum';
+ INSERT INTO tproc(text) VALUES (@user_text);
+
+END|
+DELIMITER ;|
+
+CALL proc();
+
+
+--echo ==== Insert variables from a stored function ====
+
+DELIMITER |;
+CREATE FUNCTION func()
+RETURNS INT
+BEGIN
+
+ # GLOBAL
+
+ # boolean
+ SET @@global.relay_log_purge = ON;
+ INSERT INTO tfunc(truth) VALUES (@@global.relay_log_purge);
+ SET @@global.relay_log_purge = OFF;
+ INSERT INTO tfunc(truth) VALUES (@@global.relay_log_purge);
+
+ # numeric
+ SET @@global.sync_binlog = 2000000;
+ INSERT INTO tfunc(num) VALUES (@@global.sync_binlog);
+ SET @@global.sync_binlog = 3000000;
+ INSERT INTO tfunc(num) VALUES (@@global.sync_binlog);
+
+ # string
+ SET @@global.init_slave = 'SELECT 2';
+ INSERT INTO tfunc(text) VALUES (@@global.init_slave);
+ SET @@global.init_slave = 'SELECT 3';
+ INSERT INTO tfunc(text) VALUES (@@global.init_slave);
+
+ # enumeration
+ SET @@global.slave_exec_mode = 'IDEMPOTENT';
+ INSERT INTO tfunc(text) VALUES (@@global.slave_exec_mode);
+ SET @@global.slave_exec_mode = 'STRICT';
+ INSERT INTO tfunc(text) VALUES (@@global.slave_exec_mode);
+
+ # SESSION
+
+ # boolean
+ SET @@sql_big_selects = ON;
+ INSERT INTO tfunc(truth) VALUES (@@sql_big_selects);
+ SET @@sql_big_selects = OFF;
+ INSERT INTO tfunc(truth) VALUES (@@sql_big_selects);
+
+ # numeric
+ SET @@last_insert_id = 20;
+ INSERT INTO tfunc(num) VALUES (@@last_insert_id);
+ SET @@last_insert_id = 30;
+ INSERT INTO tfunc(num) VALUES (@@last_insert_id);
+
+ # BOTH
+
+ # boolean
+ SET @@global.low_priority_updates = ON;
+ SET @@local.low_priority_updates = OFF;
+ INSERT INTO tfunc(truth) VALUES (@@global.low_priority_updates);
+ INSERT INTO tfunc(truth) VALUES (@@local.low_priority_updates);
+ SET @@global.low_priority_updates = OFF;
+ SET @@local.low_priority_updates = ON;
+ INSERT INTO tfunc(truth) VALUES (@@global.low_priority_updates);
+ INSERT INTO tfunc(truth) VALUES (@@local.low_priority_updates);
+
+ # numeric
+ SET @@global.default_week_format = 3;
+ SET @@local.default_week_format = 4;
+ INSERT INTO tfunc(num) VALUES (@@global.default_week_format);
+ INSERT INTO tfunc(num) VALUES (@@local.default_week_format);
+ SET @@global.default_week_format = 5;
+ SET @@local.default_week_format = 6;
+ INSERT INTO tfunc(num) VALUES (@@global.default_week_format);
+ INSERT INTO tfunc(num) VALUES (@@local.default_week_format);
+
+ # text
+ SET @@global.lc_time_names = 'sv_SE';
+ SET @@local.lc_time_names = 'sv_FI';
+ INSERT INTO tfunc(text) VALUES (@@global.lc_time_names);
+ INSERT INTO tfunc(text) VALUES (@@local.lc_time_names);
+ SET @@global.lc_time_names = 'ar_TN';
+ SET @@local.lc_time_names = 'ar_IQ';
+ INSERT INTO tfunc(text) VALUES (@@global.lc_time_names);
+ INSERT INTO tfunc(text) VALUES (@@local.lc_time_names);
+
+ # enum
+ SET @@global.sql_mode = '';
+ SET @@local.sql_mode = 'IGNORE_SPACE,NO_AUTO_CREATE_USER';
+ INSERT INTO tfunc(text) VALUES (@@global.sql_mode);
+ INSERT INTO tfunc(text) VALUES (@@local.sql_mode);
+ SET @@global.sql_mode = 'NO_AUTO_VALUE_ON_ZERO,NO_BACKSLASH_ESCAPES,NO_DIR_IN_CREATE,NO_ENGINE_SUBSTITUTION';
+ SET @@local.sql_mode = 'NO_FIELD_OPTIONS,NO_KEY_OPTIONS,NO_TABLE_OPTIONS';
+ INSERT INTO tfunc(text) VALUES (@@global.sql_mode);
+ INSERT INTO tfunc(text) VALUES (@@local.sql_mode);
+
+ # USER
+
+ # numeric
+ SET @user_num = 20;
+ INSERT INTO tfunc(num) VALUES (@user_num);
+ SET @user_num = 30;
+ INSERT INTO tfunc(num) VALUES (@user_num);
+
+ # string
+ SET @user_text = 'Bergsbrunna';
+ INSERT INTO tfunc(text) VALUES (@user_text);
+ SET @user_text = 'Centrum';
+ INSERT INTO tfunc(text) VALUES (@user_text);
+
+ RETURN 0;
+END|
+DELIMITER ;|
+
+--disable_ps2_protocol
+SELECT func();
+--enable_ps2_protocol
+
+--echo ==== Insert variables from a trigger ====
+
+DELIMITER |;
+CREATE TRIGGER trig
+BEFORE INSERT ON trigger_table
+FOR EACH ROW
+BEGIN
+
+ # GLOBAL
+
+ # boolean
+ SET @@global.relay_log_purge = ON;
+ INSERT INTO ttrig(truth) VALUES (@@global.relay_log_purge);
+ SET @@global.relay_log_purge = OFF;
+ INSERT INTO ttrig(truth) VALUES (@@global.relay_log_purge);
+
+ # numeric
+ SET @@global.sync_binlog = 2000000;
+ INSERT INTO ttrig(num) VALUES (@@global.sync_binlog);
+ SET @@global.sync_binlog = 3000000;
+ INSERT INTO ttrig(num) VALUES (@@global.sync_binlog);
+
+ # string
+ SET @@global.init_slave = 'SELECT 2';
+ INSERT INTO ttrig(text) VALUES (@@global.init_slave);
+ SET @@global.init_slave = 'SELECT 3';
+ INSERT INTO ttrig(text) VALUES (@@global.init_slave);
+
+ # enumeration
+ SET @@global.slave_exec_mode = 'IDEMPOTENT';
+ INSERT INTO ttrig(text) VALUES (@@global.slave_exec_mode);
+ SET @@global.slave_exec_mode = 'STRICT';
+ INSERT INTO ttrig(text) VALUES (@@global.slave_exec_mode);
+
+ # SESSION
+
+ # boolean
+ SET @@sql_big_selects = ON;
+ INSERT INTO ttrig(truth) VALUES (@@sql_big_selects);
+ SET @@sql_big_selects = OFF;
+ INSERT INTO ttrig(truth) VALUES (@@sql_big_selects);
+
+ # numeric
+ SET @@last_insert_id = 20;
+ INSERT INTO ttrig(num) VALUES (@@last_insert_id);
+ SET @@last_insert_id = 30;
+ INSERT INTO ttrig(num) VALUES (@@last_insert_id);
+
+ # BOTH
+
+ # boolean
+ SET @@global.low_priority_updates = ON;
+ SET @@local.low_priority_updates = OFF;
+ INSERT INTO ttrig(truth) VALUES (@@global.low_priority_updates);
+ INSERT INTO ttrig(truth) VALUES (@@local.low_priority_updates);
+ SET @@global.low_priority_updates = OFF;
+ SET @@local.low_priority_updates = ON;
+ INSERT INTO ttrig(truth) VALUES (@@global.low_priority_updates);
+ INSERT INTO ttrig(truth) VALUES (@@local.low_priority_updates);
+
+ # numeric
+ SET @@global.default_week_format = 3;
+ SET @@local.default_week_format = 4;
+ INSERT INTO ttrig(num) VALUES (@@global.default_week_format);
+ INSERT INTO ttrig(num) VALUES (@@local.default_week_format);
+ SET @@global.default_week_format = 5;
+ SET @@local.default_week_format = 6;
+ INSERT INTO ttrig(num) VALUES (@@global.default_week_format);
+ INSERT INTO ttrig(num) VALUES (@@local.default_week_format);
+
+ # text
+ SET @@global.lc_time_names = 'sv_SE';
+ SET @@local.lc_time_names = 'sv_FI';
+ INSERT INTO ttrig(text) VALUES (@@global.lc_time_names);
+ INSERT INTO ttrig(text) VALUES (@@local.lc_time_names);
+ SET @@global.lc_time_names = 'ar_TN';
+ SET @@local.lc_time_names = 'ar_IQ';
+ INSERT INTO ttrig(text) VALUES (@@global.lc_time_names);
+ INSERT INTO ttrig(text) VALUES (@@local.lc_time_names);
+
+ # enum
+ SET @@global.sql_mode = '';
+ SET @@local.sql_mode = 'IGNORE_SPACE,NO_AUTO_CREATE_USER';
+ INSERT INTO ttrig(text) VALUES (@@global.sql_mode);
+ INSERT INTO ttrig(text) VALUES (@@local.sql_mode);
+ SET @@global.sql_mode = 'NO_AUTO_VALUE_ON_ZERO,NO_BACKSLASH_ESCAPES,NO_DIR_IN_CREATE,NO_ENGINE_SUBSTITUTION';
+ SET @@local.sql_mode = 'NO_FIELD_OPTIONS,NO_KEY_OPTIONS,NO_TABLE_OPTIONS';
+ INSERT INTO ttrig(text) VALUES (@@global.sql_mode);
+ INSERT INTO ttrig(text) VALUES (@@local.sql_mode);
+
+ # USER
+
+ # numeric
+ SET @user_num = 20;
+ INSERT INTO ttrig(num) VALUES (@user_num);
+ SET @user_num = 30;
+ INSERT INTO ttrig(num) VALUES (@user_num);
+
+ # string
+ SET @user_text = 'Bergsbrunna';
+ INSERT INTO ttrig(text) VALUES (@user_text);
+ SET @user_text = 'Centrum';
+ INSERT INTO ttrig(text) VALUES (@user_text);
+END|
+DELIMITER ;|
+
+INSERT INTO trigger_table VALUES ('bye.');
+
+
+--echo ==== Insert variables from a prepared statement ====
+
+# GLOBAL
+
+# boolean
+PREPARE p1 FROM 'SET @@global.relay_log_purge = ON';
+PREPARE p2 FROM 'INSERT INTO tprep(truth) VALUES (@@global.relay_log_purge)';
+PREPARE p3 FROM 'SET @@global.relay_log_purge = OFF';
+PREPARE p4 FROM 'INSERT INTO tprep(truth) VALUES (@@global.relay_log_purge)';
+
+# numeric
+PREPARE p5 FROM 'SET @@global.sync_binlog = 2000000';
+PREPARE p6 FROM 'INSERT INTO tprep(num) VALUES (@@global.sync_binlog)';
+PREPARE p7 FROM 'SET @@global.sync_binlog = 3000000';
+PREPARE p8 FROM 'INSERT INTO tprep(num) VALUES (@@global.sync_binlog)';
+
+# string
+PREPARE p9 FROM 'SET @@global.init_slave = \'SELECT 2\'';
+PREPARE p10 FROM 'INSERT INTO tprep(text) VALUES (@@global.init_slave)';
+PREPARE p11 FROM 'SET @@global.init_slave = \'SELECT 3\'';
+PREPARE p12 FROM 'INSERT INTO tprep(text) VALUES (@@global.init_slave)';
+
+# enumeration
+PREPARE p13 FROM 'SET @@global.slave_exec_mode = \'IDEMPOTENT\'';
+PREPARE p14 FROM 'INSERT INTO tprep(text) VALUES (@@global.slave_exec_mode)';
+PREPARE p15 FROM 'SET @@global.slave_exec_mode = \'STRICT\'';
+PREPARE p16 FROM 'INSERT INTO tprep(text) VALUES (@@global.slave_exec_mode)';
+
+# SESSION
+
+# boolean
+PREPARE p17 FROM 'SET @@sql_big_selects = ON';
+PREPARE p18 FROM 'INSERT INTO tprep(truth) VALUES (@@sql_big_selects)';
+PREPARE p19 FROM 'SET @@sql_big_selects = OFF';
+PREPARE p20 FROM 'INSERT INTO tprep(truth) VALUES (@@sql_big_selects)';
+
+# numeric
+PREPARE p21 FROM 'SET @@last_insert_id = 20';
+PREPARE p22 FROM 'INSERT INTO tprep(num) VALUES (@@last_insert_id)';
+PREPARE p23 FROM 'SET @@last_insert_id = 30';
+PREPARE p24 FROM 'INSERT INTO tprep(num) VALUES (@@last_insert_id)';
+
+# BOTH
+
+# boolean
+PREPARE p25 FROM 'SET @@global.low_priority_updates = ON';
+PREPARE p26 FROM 'SET @@local.low_priority_updates = OFF';
+PREPARE p27 FROM 'INSERT INTO tprep(truth) VALUES (@@global.low_priority_updates)';
+PREPARE p28 FROM 'INSERT INTO tprep(truth) VALUES (@@local.low_priority_updates)';
+PREPARE p29 FROM 'SET @@global.low_priority_updates = OFF';
+PREPARE p30 FROM 'SET @@local.low_priority_updates = ON';
+PREPARE p31 FROM 'INSERT INTO tprep(truth) VALUES (@@global.low_priority_updates)';
+PREPARE p32 FROM 'INSERT INTO tprep(truth) VALUES (@@local.low_priority_updates)';
+
+# numeric
+PREPARE p33 FROM 'SET @@global.default_week_format = 3';
+PREPARE p34 FROM 'SET @@local.default_week_format = 4';
+PREPARE p35 FROM 'INSERT INTO tprep(num) VALUES (@@global.default_week_format)';
+PREPARE p36 FROM 'INSERT INTO tprep(num) VALUES (@@local.default_week_format)';
+PREPARE p37 FROM 'SET @@global.default_week_format = 5';
+PREPARE p38 FROM 'SET @@local.default_week_format = 6';
+PREPARE p39 FROM 'INSERT INTO tprep(num) VALUES (@@global.default_week_format)';
+PREPARE p40 FROM 'INSERT INTO tprep(num) VALUES (@@local.default_week_format)';
+
+# text
+PREPARE p41 FROM 'SET @@global.lc_time_names = \'sv_SE\'';
+PREPARE p42 FROM 'SET @@local.lc_time_names = \'sv_FI\'';
+PREPARE p43 FROM 'INSERT INTO tprep(text) VALUES (@@global.lc_time_names)';
+PREPARE p44 FROM 'INSERT INTO tprep(text) VALUES (@@local.lc_time_names)';
+PREPARE p45 FROM 'SET @@global.lc_time_names = \'ar_TN\'';
+PREPARE p46 FROM 'SET @@local.lc_time_names = \'ar_IQ\'';
+PREPARE p47 FROM 'INSERT INTO tprep(text) VALUES (@@global.lc_time_names)';
+PREPARE p48 FROM 'INSERT INTO tprep(text) VALUES (@@local.lc_time_names)';
+
+# enum
+PREPARE p49 FROM 'SET @@global.sql_mode = \'\'';
+PREPARE p50 FROM 'SET @@local.sql_mode = \'IGNORE_SPACE,NO_AUTO_CREATE_USER\'';
+PREPARE p51 FROM 'INSERT INTO tprep(text) VALUES (@@global.sql_mode)';
+PREPARE p52 FROM 'INSERT INTO tprep(text) VALUES (@@local.sql_mode)';
+PREPARE p53 FROM 'SET @@global.sql_mode = \'NO_AUTO_VALUE_ON_ZERO,NO_BACKSLASH_ESCAPES,NO_DIR_IN_CREATE,NO_ENGINE_SUBSTITUTION\'';
+PREPARE p54 FROM 'SET @@local.sql_mode = \'NO_FIELD_OPTIONS,NO_KEY_OPTIONS,NO_TABLE_OPTIONS\'';
+PREPARE p55 FROM 'INSERT INTO tprep(text) VALUES (@@global.sql_mode)';
+PREPARE p56 FROM 'INSERT INTO tprep(text) VALUES (@@local.sql_mode)';
+
+# USER
+
+# numeric
+PREPARE p57 FROM 'SET @user_num = 20';
+PREPARE p58 FROM 'INSERT INTO tprep(num) VALUES (@user_num)';
+PREPARE p59 FROM 'SET @user_num = 30';
+PREPARE p60 FROM 'INSERT INTO tprep(num) VALUES (@user_num)';
+
+# string
+PREPARE p61 FROM 'SET @user_text = \'Bergsbrunna\'';
+PREPARE p62 FROM 'INSERT INTO tprep(text) VALUES (@user_text)';
+PREPARE p63 FROM 'SET @user_text = \'Centrum\'';
+PREPARE p64 FROM 'INSERT INTO tprep(text) VALUES (@user_text)';
+
+EXECUTE p1; EXECUTE p2; EXECUTE p3; EXECUTE p4; EXECUTE p5; EXECUTE p6;
+EXECUTE p7; EXECUTE p8; EXECUTE p9; EXECUTE p10; EXECUTE p11; EXECUTE p12;
+EXECUTE p13; EXECUTE p14; EXECUTE p15; EXECUTE p16; EXECUTE p17; EXECUTE p18;
+EXECUTE p19; EXECUTE p20; EXECUTE p21; EXECUTE p22; EXECUTE p23; EXECUTE p24;
+EXECUTE p25; EXECUTE p26; EXECUTE p27; EXECUTE p28; EXECUTE p29; EXECUTE p30;
+EXECUTE p31; EXECUTE p32; EXECUTE p33; EXECUTE p34; EXECUTE p35; EXECUTE p36;
+EXECUTE p37; EXECUTE p38; EXECUTE p39; EXECUTE p40; EXECUTE p41; EXECUTE p42;
+EXECUTE p43; EXECUTE p44; EXECUTE p45; EXECUTE p46; EXECUTE p47; EXECUTE p48;
+EXECUTE p49; EXECUTE p50; EXECUTE p51; EXECUTE p52; EXECUTE p53; EXECUTE p54;
+EXECUTE p55; EXECUTE p56; EXECUTE p57; EXECUTE p58; EXECUTE p59; EXECUTE p60;
+EXECUTE p61; EXECUTE p62; EXECUTE p63; EXECUTE p64;
+
+--sync_slave_with_master
+--connection master
+
+
+--echo ==== Results ====
+
+# Show the result in table test.tstmt on master...
+SELECT * FROM tstmt ORDER BY id;
+
+--sync_slave_with_master
+
+# ... then compare test.tstmt on master to the other tables on master and slave.
+let $diff_tables= master:tstmt, master:tproc, master:tfunc, master:ttrig, master:tprep, slave:tstmt, slave:tproc, slave:tfunc, slave:ttrig, slave:tprep;
+source include/diff_tables.inc;
+
+
+--echo ==== Clean up ====
+
+connection master;
+DROP PROCEDURE proc;
+DROP FUNCTION func;
+DROP TRIGGER trig;
+DROP TABLE tstmt, tproc, tfunc, ttrig, tprep, trigger_table;
+
+SET @@global.default_week_format= @m_default_week_format;
+SET @@global.init_slave= @m_init_slave;
+SET @@global.lc_time_names= @m_lc_time_names;
+SET @@global.low_priority_updates= @m_low_priority_updates;
+SET @@global.relay_log_purge= @m_relay_log_purge;
+SET @@global.slave_exec_mode= @m_slave_exec_mode;
+SET @@global.sql_mode= @m_sql_mode;
+SET @@global.sync_binlog= @m_sync_binlog;
+
+connection slave;
+SET @@global.default_week_format= @s_default_week_format;
+SET @@global.init_slave= @s_init_slave;
+SET @@global.lc_time_names= @s_lc_time_names;
+SET @@global.low_priority_updates= @s_low_priority_updates;
+SET @@global.relay_log_purge= @s_relay_log_purge;
+SET @@global.slave_exec_mode= @s_slave_exec_mode;
+SET @@global.sql_mode= @s_sql_mode;
+SET @@global.sync_binlog= @s_sync_binlog;
+
+connection master;
+sync_slave_with_master;
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_variables_stm.test b/mysql-test/suite/rpl/t/rpl_variables_stm.test
new file mode 100644
index 00000000..ffbb3e77
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_variables_stm.test
@@ -0,0 +1,618 @@
+# ==== Purpose ====
+#
+# In general, queries referencing @@system_variables are not
+# considered safe to write to the binlog in statement-based logging
+# mode. However, a few special cases are supported.
+#
+# This test verifies that queries referencing these specially
+# supported variables are replicated correctly in statement mode.
+#
+#
+# ==== Method ====
+#
+# The test simply does a lot of "INSERT INTO t1 VALUES (@@variable)"
+# and checks the result on the slave.
+#
+# Statements referencing a variable only replicate correctly in mixed
+# and row mode: in row mode, the values inserted are replicated. In
+# mixed mode, statements referencing a variable are marked as unsafe,
+# meaning they will be replicated by row. In statement mode, the
+# slave's value will be used and replication will break. (Except in a
+# small number of special cases: random seeds, insert_id, and
+# auto_increment are replicated).
+#
+# We test all replicated variables, from each of the following
+# contexts:
+# - directly
+# - from a stored procedure
+# - from a stored function
+# - from a trigger
+# - from a prepared statement
+#
+# For all variables where it is possible, we set the variable to one
+# value on slave, and insert it on the master with two distinct
+# values.
+#
+# The same insertions are made in four different tables using direct
+# insert, stored procedure, stored function, or trigger. Then all
+# eight resulting tables on master and slave are compared.
+#
+#
+# ==== Related bugs ====
+#
+# BUG#31168: @@hostname does not replicate
+#
+#
+# ==== Related test cases ====
+#
+# binlog.binlog_unsafe tests that a warning is issued if system
+# variables are replicated in statement mode.
+#
+# rpl.rpl_variables verifies that variables which cannot be replicated
+# safely in statement mode are replicated correctly in mixed or row
+# mode.
+
+source include/have_binlog_format_mixed_or_statement.inc;
+source include/master-slave.inc;
+
+call mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT");
+
+--echo ==== Initialization ====
+
+# Backup the values of global variables so that they can be restored
+# later.
+
+connection master;
+SET @m_auto_increment_increment= @@global.auto_increment_increment;
+SET @m_auto_increment_offset= @@global.auto_increment_offset;
+SET @m_character_set_client= @@global.character_set_client;
+SET @m_collation_connection= @@global.collation_connection;
+SET @m_collation_server= @@global.collation_server;
+SET @m_time_zone= @@global.time_zone;
+SET @m_lc_time_names= @@global.lc_time_names;
+SET @m_collation_database= @@global.collation_database;
+
+connection slave;
+SET @s_auto_increment_increment= @@global.auto_increment_increment;
+SET @s_auto_increment_offset= @@global.auto_increment_offset;
+SET @s_character_set_client= @@global.character_set_client;
+SET @s_collation_connection= @@global.collation_connection;
+SET @s_collation_server= @@global.collation_server;
+SET @s_time_zone= @@global.time_zone;
+SET @s_lc_time_names= @@global.lc_time_names;
+SET @s_collation_database= @@global.collation_database;
+
+SET @@global.auto_increment_increment=19;
+SET @@global.auto_increment_offset=4;
+SET @@global.character_set_client='latin2';
+SET @@global.collation_connection='latin2_bin';
+SET @@global.collation_server='geostd8_general_ci';
+SET @@global.time_zone='Japan';
+SET @@global.lc_time_names='sv_SE';
+SET @@global.collation_database='geostd8_bin';
+
+connection master;
+
+# Tables where everything happens.
+CREATE TABLE tstmt (id INT AUTO_INCREMENT PRIMARY KEY,
+ num INT,
+ text VARCHAR(100));
+CREATE TABLE tproc LIKE tstmt;
+CREATE TABLE tfunc LIKE tstmt;
+CREATE TABLE ttrig LIKE tstmt;
+CREATE TABLE tprep LIKE tstmt;
+
+# Table on which we put a trigger.
+CREATE TABLE trigger_table (text CHAR(4));
+
+
+--echo ==== Insert variables directly ====
+
+SET @@pseudo_thread_id= 4712;
+INSERT INTO tstmt(num) VALUES (@@session.pseudo_thread_id);
+SET @@pseudo_thread_id= 4713;
+INSERT INTO tstmt(num) VALUES (@@session.pseudo_thread_id);
+
+SET @@foreign_key_checks= 0;
+INSERT INTO tstmt(num) VALUES (@@session.foreign_key_checks);
+SET @@foreign_key_checks= 1;
+INSERT INTO tstmt(num) VALUES (@@session.foreign_key_checks);
+
+SET @@sql_auto_is_null= 0;
+INSERT INTO tstmt(num) VALUES (@@session.sql_auto_is_null);
+SET @@sql_auto_is_null= 1;
+INSERT INTO tstmt(num) VALUES (@@session.sql_auto_is_null);
+
+SET @@unique_checks= 0;
+INSERT INTO tstmt(num) VALUES (@@session.unique_checks);
+SET @@unique_checks= 1;
+INSERT INTO tstmt(num) VALUES (@@session.unique_checks);
+
+SET @@auto_increment_increment= 11;
+INSERT INTO tstmt(num) VALUES (@@session.auto_increment_increment);
+SET @@auto_increment_increment= 19;
+INSERT INTO tstmt(num) VALUES (@@session.auto_increment_increment);
+
+SET @@auto_increment_offset= 13;
+INSERT INTO tstmt(num) VALUES (@@session.auto_increment_offset);
+SET @@auto_increment_offset= 17;
+INSERT INTO tstmt(num) VALUES (@@session.auto_increment_offset);
+
+# reset these as they affect the index column
+SET @@auto_increment_increment= 1;
+SET @@auto_increment_offset= 1;
+
+SET @@character_set_client= 'cp1257';
+INSERT INTO tstmt(text) VALUES (@@session.character_set_client);
+SET @@character_set_client= 'cp1256';
+INSERT INTO tstmt(text) VALUES (@@session.character_set_client);
+
+SET @@collation_connection= 'cp1251_ukrainian_ci';
+INSERT INTO tstmt(text) VALUES (@@session.collation_connection);
+INSERT INTO tstmt(text) VALUES (@@session.character_set_connection);
+SET @@collation_connection= 'cp1251_bulgarian_ci';
+INSERT INTO tstmt(text) VALUES (@@session.collation_connection);
+INSERT INTO tstmt(text) VALUES (@@session.character_set_connection);
+
+SET @@collation_server= 'latin7_bin';
+INSERT INTO tstmt(text) VALUES (@@session.collation_server);
+INSERT INTO tstmt(text) VALUES (@@session.character_set_server);
+SET @@collation_server= 'latin7_general_cs';
+INSERT INTO tstmt(text) VALUES (@@session.collation_server);
+INSERT INTO tstmt(text) VALUES (@@session.character_set_server);
+
+SET @@time_zone= 'Europe/Moscow';
+INSERT INTO tstmt(text) VALUES (@@session.time_zone);
+SET @@time_zone= 'Universal';
+INSERT INTO tstmt(text) VALUES (@@session.time_zone);
+
+SET @@lc_time_names= 'sv_FI';
+INSERT INTO tstmt(text) VALUES (@@session.lc_time_names);
+SET @@lc_time_names= 'no_NO';
+INSERT INTO tstmt(text) VALUES (@@session.lc_time_names);
+
+SET @@collation_database= 'latin7_general_ci';
+INSERT INTO tstmt(text) VALUES (@@session.collation_database);
+INSERT INTO tstmt(text) VALUES (@@session.character_set_database);
+SET @@collation_database= 'latin7_estonian_cs';
+INSERT INTO tstmt(text) VALUES (@@session.collation_database);
+INSERT INTO tstmt(text) VALUES (@@session.character_set_database);
+
+SET @@timestamp= 47114711;
+INSERT INTO tstmt(text) VALUES (@@session.timestamp);
+SET @@timestamp= 47124712;
+INSERT INTO tstmt(text) VALUES (@@session.timestamp);
+
+SET @@last_insert_id= 1616;
+INSERT INTO tstmt(text) VALUES (@@session.last_insert_id);
+SET @@last_insert_id= 1717;
+INSERT INTO tstmt(text) VALUES (@@session.last_insert_id);
+
+
+--echo ==== Insert variables from a stored procedure ====
+
+DELIMITER |;
+CREATE PROCEDURE proc()
+BEGIN
+
+ SET @@pseudo_thread_id= 4712;
+ INSERT INTO tproc(num) VALUES (@@session.pseudo_thread_id);
+ SET @@pseudo_thread_id= 4713;
+ INSERT INTO tproc(num) VALUES (@@session.pseudo_thread_id);
+
+ SET @@foreign_key_checks= 0;
+ INSERT INTO tproc(num) VALUES (@@session.foreign_key_checks);
+ SET @@foreign_key_checks= 1;
+ INSERT INTO tproc(num) VALUES (@@session.foreign_key_checks);
+
+ SET @@sql_auto_is_null= 0;
+ INSERT INTO tproc(num) VALUES (@@session.sql_auto_is_null);
+ SET @@sql_auto_is_null= 1;
+ INSERT INTO tproc(num) VALUES (@@session.sql_auto_is_null);
+
+ SET @@unique_checks= 0;
+ INSERT INTO tproc(num) VALUES (@@session.unique_checks);
+ SET @@unique_checks= 1;
+ INSERT INTO tproc(num) VALUES (@@session.unique_checks);
+
+ SET @@auto_increment_increment= 11;
+ INSERT INTO tproc(num) VALUES (@@session.auto_increment_increment);
+ SET @@auto_increment_increment= 19;
+ INSERT INTO tproc(num) VALUES (@@session.auto_increment_increment);
+
+ SET @@auto_increment_offset= 13;
+ INSERT INTO tproc(num) VALUES (@@session.auto_increment_offset);
+ SET @@auto_increment_offset= 17;
+ INSERT INTO tproc(num) VALUES (@@session.auto_increment_offset);
+
+ # reset these as they affect the index column
+ SET @@auto_increment_increment= 1;
+ SET @@auto_increment_offset= 1;
+
+ SET @@character_set_client= 'cp1257';
+ INSERT INTO tproc(text) VALUES (@@session.character_set_client);
+ SET @@character_set_client= 'cp1256';
+ INSERT INTO tproc(text) VALUES (@@session.character_set_client);
+
+ SET @@collation_connection= 'cp1251_ukrainian_ci';
+ INSERT INTO tproc(text) VALUES (@@session.collation_connection);
+ INSERT INTO tproc(text) VALUES (@@session.character_set_connection);
+ SET @@collation_connection= 'cp1251_bulgarian_ci';
+ INSERT INTO tproc(text) VALUES (@@session.collation_connection);
+ INSERT INTO tproc(text) VALUES (@@session.character_set_connection);
+
+ SET @@collation_server= 'latin7_bin';
+ INSERT INTO tproc(text) VALUES (@@session.collation_server);
+ INSERT INTO tproc(text) VALUES (@@session.character_set_server);
+ SET @@collation_server= 'latin7_general_cs';
+ INSERT INTO tproc(text) VALUES (@@session.collation_server);
+ INSERT INTO tproc(text) VALUES (@@session.character_set_server);
+
+ SET @@time_zone= 'Europe/Moscow';
+ INSERT INTO tproc(text) VALUES (@@session.time_zone);
+ SET @@time_zone= 'Universal';
+ INSERT INTO tproc(text) VALUES (@@session.time_zone);
+
+ SET @@lc_time_names= 'sv_FI';
+ INSERT INTO tproc(text) VALUES (@@session.lc_time_names);
+ SET @@lc_time_names= 'no_NO';
+ INSERT INTO tproc(text) VALUES (@@session.lc_time_names);
+
+ SET @@collation_database= 'latin7_general_ci';
+ INSERT INTO tproc(text) VALUES (@@session.collation_database);
+ INSERT INTO tproc(text) VALUES (@@session.character_set_database);
+ SET @@collation_database= 'latin7_estonian_cs';
+ INSERT INTO tproc(text) VALUES (@@session.collation_database);
+ INSERT INTO tproc(text) VALUES (@@session.character_set_database);
+
+ SET @@timestamp= 47114711;
+ INSERT INTO tproc(text) VALUES (@@session.timestamp);
+ SET @@timestamp= 47124712;
+ INSERT INTO tproc(text) VALUES (@@session.timestamp);
+
+ SET @@last_insert_id= 1616;
+ INSERT INTO tproc(text) VALUES (@@session.last_insert_id);
+ SET @@last_insert_id= 1717;
+ INSERT INTO tproc(text) VALUES (@@session.last_insert_id);
+
+END|
+DELIMITER ;|
+
+CALL proc();
+
+
+--echo ==== Insert variables from a stored function ====
+
+DELIMITER |;
+CREATE FUNCTION func()
+RETURNS INT
+BEGIN
+
+ SET @@pseudo_thread_id= 4712;
+ INSERT INTO tfunc(num) VALUES (@@session.pseudo_thread_id);
+ SET @@pseudo_thread_id= 4713;
+ INSERT INTO tfunc(num) VALUES (@@session.pseudo_thread_id);
+
+ SET @@foreign_key_checks= 0;
+ INSERT INTO tfunc(num) VALUES (@@session.foreign_key_checks);
+ SET @@foreign_key_checks= 1;
+ INSERT INTO tfunc(num) VALUES (@@session.foreign_key_checks);
+
+ SET @@sql_auto_is_null= 0;
+ INSERT INTO tfunc(num) VALUES (@@session.sql_auto_is_null);
+ SET @@sql_auto_is_null= 1;
+ INSERT INTO tfunc(num) VALUES (@@session.sql_auto_is_null);
+
+ SET @@unique_checks= 0;
+ INSERT INTO tfunc(num) VALUES (@@session.unique_checks);
+ SET @@unique_checks= 1;
+ INSERT INTO tfunc(num) VALUES (@@session.unique_checks);
+
+ SET @@auto_increment_increment= 11;
+ INSERT INTO tfunc(num) VALUES (@@session.auto_increment_increment);
+ SET @@auto_increment_increment= 19;
+ INSERT INTO tfunc(num) VALUES (@@session.auto_increment_increment);
+
+ SET @@auto_increment_offset= 13;
+ INSERT INTO tfunc(num) VALUES (@@session.auto_increment_offset);
+ SET @@auto_increment_offset= 17;
+ INSERT INTO tfunc(num) VALUES (@@session.auto_increment_offset);
+
+ # reset these as they affect the index column
+ SET @@auto_increment_increment= 1;
+ SET @@auto_increment_offset= 1;
+
+ SET @@character_set_client= 'cp1257';
+ INSERT INTO tfunc(text) VALUES (@@session.character_set_client);
+ SET @@character_set_client= 'cp1256';
+ INSERT INTO tfunc(text) VALUES (@@session.character_set_client);
+
+ SET @@collation_connection= 'cp1251_ukrainian_ci';
+ INSERT INTO tfunc(text) VALUES (@@session.collation_connection);
+ INSERT INTO tfunc(text) VALUES (@@session.character_set_connection);
+ SET @@collation_connection= 'cp1251_bulgarian_ci';
+ INSERT INTO tfunc(text) VALUES (@@session.collation_connection);
+ INSERT INTO tfunc(text) VALUES (@@session.character_set_connection);
+
+ SET @@collation_server= 'latin7_bin';
+ INSERT INTO tfunc(text) VALUES (@@session.collation_server);
+ INSERT INTO tfunc(text) VALUES (@@session.character_set_server);
+ SET @@collation_server= 'latin7_general_cs';
+ INSERT INTO tfunc(text) VALUES (@@session.collation_server);
+ INSERT INTO tfunc(text) VALUES (@@session.character_set_server);
+
+ SET @@time_zone= 'Europe/Moscow';
+ INSERT INTO tfunc(text) VALUES (@@session.time_zone);
+ SET @@time_zone= 'Universal';
+ INSERT INTO tfunc(text) VALUES (@@session.time_zone);
+
+ SET @@lc_time_names= 'sv_FI';
+ INSERT INTO tfunc(text) VALUES (@@session.lc_time_names);
+ SET @@lc_time_names= 'no_NO';
+ INSERT INTO tfunc(text) VALUES (@@session.lc_time_names);
+
+ SET @@collation_database= 'latin7_general_ci';
+ INSERT INTO tfunc(text) VALUES (@@session.collation_database);
+ INSERT INTO tfunc(text) VALUES (@@session.character_set_database);
+ SET @@collation_database= 'latin7_estonian_cs';
+ INSERT INTO tfunc(text) VALUES (@@session.collation_database);
+ INSERT INTO tfunc(text) VALUES (@@session.character_set_database);
+
+ SET @@timestamp= 47114711;
+ INSERT INTO tfunc(text) VALUES (@@session.timestamp);
+ SET @@timestamp= 47124712;
+ INSERT INTO tfunc(text) VALUES (@@session.timestamp);
+
+ SET @@last_insert_id= 1616;
+ INSERT INTO tfunc(text) VALUES (@@session.last_insert_id);
+ SET @@last_insert_id= 1717;
+ INSERT INTO tfunc(text) VALUES (@@session.last_insert_id);
+
+ RETURN 0;
+END|
+DELIMITER ;|
+
+--disable_ps2_protocol
+--disable_warnings
+SELECT func();
+--enable_warnings
+--enable_ps2_protocol
+
+--echo ==== Insert variables from a trigger ====
+
+DELIMITER |;
+CREATE TRIGGER trig
+BEFORE INSERT ON trigger_table
+FOR EACH ROW
+BEGIN
+
+ SET @@pseudo_thread_id= 4712;
+ INSERT INTO ttrig(num) VALUES (@@session.pseudo_thread_id);
+ SET @@pseudo_thread_id= 4713;
+ INSERT INTO ttrig(num) VALUES (@@session.pseudo_thread_id);
+
+ SET @@foreign_key_checks= 0;
+ INSERT INTO ttrig(num) VALUES (@@session.foreign_key_checks);
+ SET @@foreign_key_checks= 1;
+ INSERT INTO ttrig(num) VALUES (@@session.foreign_key_checks);
+
+ SET @@sql_auto_is_null= 0;
+ INSERT INTO ttrig(num) VALUES (@@session.sql_auto_is_null);
+ SET @@sql_auto_is_null= 1;
+ INSERT INTO ttrig(num) VALUES (@@session.sql_auto_is_null);
+
+ SET @@unique_checks= 0;
+ INSERT INTO ttrig(num) VALUES (@@session.unique_checks);
+ SET @@unique_checks= 1;
+ INSERT INTO ttrig(num) VALUES (@@session.unique_checks);
+
+ SET @@auto_increment_increment= 11;
+ INSERT INTO ttrig(num) VALUES (@@session.auto_increment_increment);
+ SET @@auto_increment_increment= 19;
+ INSERT INTO ttrig(num) VALUES (@@session.auto_increment_increment);
+
+ SET @@auto_increment_offset= 13;
+ INSERT INTO ttrig(num) VALUES (@@session.auto_increment_offset);
+ SET @@auto_increment_offset= 17;
+ INSERT INTO ttrig(num) VALUES (@@session.auto_increment_offset);
+
+ # reset these as they affect the index column
+ SET @@auto_increment_increment= 1;
+ SET @@auto_increment_offset= 1;
+
+ SET @@character_set_client= 'cp1257';
+ INSERT INTO ttrig(text) VALUES (@@session.character_set_client);
+ SET @@character_set_client= 'cp1256';
+ INSERT INTO ttrig(text) VALUES (@@session.character_set_client);
+
+ SET @@collation_connection= 'cp1251_ukrainian_ci';
+ INSERT INTO ttrig(text) VALUES (@@session.collation_connection);
+ INSERT INTO ttrig(text) VALUES (@@session.character_set_connection);
+ SET @@collation_connection= 'cp1251_bulgarian_ci';
+ INSERT INTO ttrig(text) VALUES (@@session.collation_connection);
+ INSERT INTO ttrig(text) VALUES (@@session.character_set_connection);
+
+ SET @@collation_server= 'latin7_bin';
+ INSERT INTO ttrig(text) VALUES (@@session.collation_server);
+ INSERT INTO ttrig(text) VALUES (@@session.character_set_server);
+ SET @@collation_server= 'latin7_general_cs';
+ INSERT INTO ttrig(text) VALUES (@@session.collation_server);
+ INSERT INTO ttrig(text) VALUES (@@session.character_set_server);
+
+ SET @@time_zone= 'Europe/Moscow';
+ INSERT INTO ttrig(text) VALUES (@@session.time_zone);
+ SET @@time_zone= 'Universal';
+ INSERT INTO ttrig(text) VALUES (@@session.time_zone);
+
+ SET @@lc_time_names= 'sv_FI';
+ INSERT INTO ttrig(text) VALUES (@@session.lc_time_names);
+ SET @@lc_time_names= 'no_NO';
+ INSERT INTO ttrig(text) VALUES (@@session.lc_time_names);
+
+ SET @@collation_database= 'latin7_general_ci';
+ INSERT INTO ttrig(text) VALUES (@@session.collation_database);
+ INSERT INTO ttrig(text) VALUES (@@session.character_set_database);
+ SET @@collation_database= 'latin7_estonian_cs';
+ INSERT INTO ttrig(text) VALUES (@@session.collation_database);
+ INSERT INTO ttrig(text) VALUES (@@session.character_set_database);
+
+ SET @@timestamp= 47114711;
+ INSERT INTO ttrig(text) VALUES (@@session.timestamp);
+ SET @@timestamp= 47124712;
+ INSERT INTO ttrig(text) VALUES (@@session.timestamp);
+
+ SET @@last_insert_id= 1616;
+ INSERT INTO ttrig(text) VALUES (@@session.last_insert_id);
+ SET @@last_insert_id= 1717;
+ INSERT INTO ttrig(text) VALUES (@@session.last_insert_id);
+
+END|
+DELIMITER ;|
+
+--disable_warnings
+INSERT INTO trigger_table VALUES ('bye.');
+--enable_warnings
+
+
+--echo ==== Insert variables from a prepared statement ====
+
+# GLOBAL
+
+PREPARE p1 FROM 'SET @@pseudo_thread_id= 4712';
+PREPARE p2 FROM 'INSERT INTO tprep(num) VALUES (@@session.pseudo_thread_id)';
+PREPARE p3 FROM 'SET @@pseudo_thread_id= 4713';
+PREPARE p4 FROM 'INSERT INTO tprep(num) VALUES (@@session.pseudo_thread_id)';
+
+PREPARE p5 FROM 'SET @@foreign_key_checks= 0';
+PREPARE p6 FROM 'INSERT INTO tprep(num) VALUES (@@session.foreign_key_checks)';
+PREPARE p7 FROM 'SET @@foreign_key_checks= 1';
+PREPARE p8 FROM 'INSERT INTO tprep(num) VALUES (@@session.foreign_key_checks)';
+
+PREPARE p9 FROM 'SET @@sql_auto_is_null= 0';
+PREPARE p10 FROM 'INSERT INTO tprep(num) VALUES (@@session.sql_auto_is_null)';
+PREPARE p11 FROM 'SET @@sql_auto_is_null= 1';
+PREPARE p12 FROM 'INSERT INTO tprep(num) VALUES (@@session.sql_auto_is_null)';
+
+PREPARE p13 FROM 'SET @@unique_checks= 0';
+PREPARE p14 FROM 'INSERT INTO tprep(num) VALUES (@@session.unique_checks)';
+PREPARE p15 FROM 'SET @@unique_checks= 1';
+PREPARE p16 FROM 'INSERT INTO tprep(num) VALUES (@@session.unique_checks)';
+
+PREPARE p17 FROM 'SET @@auto_increment_increment= 11';
+PREPARE p18 FROM 'INSERT INTO tprep(num) VALUES (@@session.auto_increment_increment)';
+PREPARE p19 FROM 'SET @@auto_increment_increment= 19';
+PREPARE p20 FROM 'INSERT INTO tprep(num) VALUES (@@session.auto_increment_increment)';
+
+PREPARE p21 FROM 'SET @@auto_increment_offset= 13';
+PREPARE p22 FROM 'INSERT INTO tprep(num) VALUES (@@session.auto_increment_offset)';
+PREPARE p23 FROM 'SET @@auto_increment_offset= 17';
+PREPARE p24 FROM 'INSERT INTO tprep(num) VALUES (@@session.auto_increment_offset)';
+
+# reset these as they affect the index column
+PREPARE p25 FROM 'SET @@auto_increment_increment= 1';
+PREPARE p26 FROM 'SET @@auto_increment_offset= 1';
+
+PREPARE p27 FROM 'SET @@character_set_client= \'cp1257\'';
+PREPARE p28 FROM 'INSERT INTO tprep(text) VALUES (@@session.character_set_client)';
+PREPARE p29 FROM 'SET @@character_set_client= \'cp1256\'';
+PREPARE p30 FROM 'INSERT INTO tprep(text) VALUES (@@session.character_set_client)';
+
+PREPARE p31 FROM 'SET @@collation_connection= \'cp1251_ukrainian_ci\'';
+PREPARE p32 FROM 'INSERT INTO tprep(text) VALUES (@@session.collation_connection)';
+PREPARE p33 FROM 'INSERT INTO tprep(text) VALUES (@@session.character_set_connection)';
+PREPARE p34 FROM 'SET @@collation_connection= \'cp1251_bulgarian_ci\'';
+PREPARE p35 FROM 'INSERT INTO tprep(text) VALUES (@@session.collation_connection)';
+PREPARE p36 FROM 'INSERT INTO tprep(text) VALUES (@@session.character_set_connection)';
+
+PREPARE p37 FROM 'SET @@collation_server= \'latin7_bin\'';
+PREPARE p38 FROM 'INSERT INTO tprep(text) VALUES (@@session.collation_server)';
+PREPARE p39 FROM 'INSERT INTO tprep(text) VALUES (@@session.character_set_server)';
+PREPARE p40 FROM 'SET @@collation_server= \'latin7_general_cs\'';
+PREPARE p41 FROM 'INSERT INTO tprep(text) VALUES (@@session.collation_server)';
+PREPARE p42 FROM 'INSERT INTO tprep(text) VALUES (@@session.character_set_server)';
+
+PREPARE p43 FROM 'SET @@time_zone= \'Europe/Moscow\'';
+PREPARE p44 FROM 'INSERT INTO tprep(text) VALUES (@@session.time_zone)';
+PREPARE p45 FROM 'SET @@time_zone= \'Universal\'';
+PREPARE p46 FROM 'INSERT INTO tprep(text) VALUES (@@session.time_zone)';
+
+PREPARE p47 FROM 'SET @@lc_time_names= \'sv_FI\'';
+PREPARE p48 FROM 'INSERT INTO tprep(text) VALUES (@@session.lc_time_names)';
+PREPARE p49 FROM 'SET @@lc_time_names= \'no_NO\'';
+PREPARE p50 FROM 'INSERT INTO tprep(text) VALUES (@@session.lc_time_names)';
+
+PREPARE p51 FROM 'SET @@collation_database= \'latin7_general_ci\'';
+PREPARE p52 FROM 'INSERT INTO tprep(text) VALUES (@@session.collation_database)';
+PREPARE p53 FROM 'INSERT INTO tprep(text) VALUES (@@session.character_set_database)';
+PREPARE p54 FROM 'SET @@collation_database= \'latin7_estonian_cs\'';
+PREPARE p55 FROM 'INSERT INTO tprep(text) VALUES (@@session.collation_database)';
+PREPARE p56 FROM 'INSERT INTO tprep(text) VALUES (@@session.character_set_database)';
+
+PREPARE p57 FROM 'SET @@timestamp= 47114711';
+PREPARE p58 FROM 'INSERT INTO tprep(text) VALUES (@@session.timestamp)';
+PREPARE p59 FROM 'SET @@timestamp= 47124712';
+PREPARE p60 FROM 'INSERT INTO tprep(text) VALUES (@@session.timestamp)';
+
+PREPARE p61 FROM 'SET @@last_insert_id= 1616';
+PREPARE p62 FROM 'INSERT INTO tprep(text) VALUES (@@session.last_insert_id)';
+PREPARE p63 FROM 'SET @@last_insert_id= 1717';
+PREPARE p64 FROM 'INSERT INTO tprep(text) VALUES (@@session.last_insert_id)';
+
+EXECUTE p1; EXECUTE p2; EXECUTE p3; EXECUTE p4; EXECUTE p5; EXECUTE p6;
+EXECUTE p7; EXECUTE p8; EXECUTE p9; EXECUTE p10; EXECUTE p11; EXECUTE p12;
+EXECUTE p13; EXECUTE p14; EXECUTE p15; EXECUTE p16; EXECUTE p17; EXECUTE p18;
+EXECUTE p19; EXECUTE p20; EXECUTE p21; EXECUTE p22; EXECUTE p23; EXECUTE p24;
+EXECUTE p25; EXECUTE p26; EXECUTE p27; EXECUTE p28; EXECUTE p29; EXECUTE p30;
+EXECUTE p31; EXECUTE p32; EXECUTE p33; EXECUTE p34; EXECUTE p35; EXECUTE p36;
+EXECUTE p37; EXECUTE p38; EXECUTE p39; EXECUTE p40; EXECUTE p41; EXECUTE p42;
+EXECUTE p43; EXECUTE p44; EXECUTE p45; EXECUTE p46; EXECUTE p47; EXECUTE p48;
+EXECUTE p49; EXECUTE p50; EXECUTE p51; EXECUTE p52; EXECUTE p53; EXECUTE p54;
+EXECUTE p55; EXECUTE p56; EXECUTE p57; EXECUTE p58; EXECUTE p59; EXECUTE p60;
+EXECUTE p61; EXECUTE p62; EXECUTE p63; EXECUTE p64;
+
+--sync_slave_with_master
+--connection master
+
+
+--echo ==== Results ====
+
+# Show the result in table test.tstmt on master...
+SELECT * FROM tstmt ORDER BY id;
+
+--sync_slave_with_master
+
+# ... then compare test.tstmt on master to the other tables on master and slave.
+let $diff_tables= master:tstmt, master:tproc, master:tfunc, master:ttrig, master:tprep, slave:tstmt, slave:tproc, slave:tfunc, slave:ttrig, slave:tprep;
+source include/diff_tables.inc;
+
+
+--echo ==== Clean up ====
+
+connection master;
+DROP PROCEDURE proc;
+DROP FUNCTION func;
+DROP TRIGGER trig;
+DROP TABLE tstmt, tproc, tfunc, ttrig, tprep, trigger_table;
+
+SET @@global.auto_increment_increment= @m_auto_increment_increment;
+SET @@global.auto_increment_offset= @m_auto_increment_offset;
+SET @@global.character_set_client= @m_character_set_client;
+SET @@global.collation_connection= @m_collation_connection;
+SET @@global.collation_server= @m_collation_server;
+SET @@global.time_zone= @m_time_zone;
+SET @@global.lc_time_names= @m_lc_time_names;
+SET @@global.collation_database= @m_collation_database;
+
+connection slave;
+SET @@global.auto_increment_increment= @s_auto_increment_increment;
+SET @@global.auto_increment_offset= @s_auto_increment_offset;
+SET @@global.character_set_client= @s_character_set_client;
+SET @@global.collation_connection= @s_collation_connection;
+SET @@global.collation_server= @s_collation_server;
+SET @@global.time_zone= @s_time_zone;
+SET @@global.lc_time_names= @s_lc_time_names;
+SET @@global.collation_database= @s_collation_database;
+
+connection master;
+sync_slave_with_master;
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_view.test b/mysql-test/suite/rpl/t/rpl_view.test
new file mode 100644
index 00000000..987b93a1
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_view.test
@@ -0,0 +1,171 @@
+# NYI - row-based cannot use CREATE ... SELECT
+
+source include/master-slave.inc;
+--disable_warnings
+drop table if exists t1,v1;
+drop view if exists t1,v1;
+sync_slave_with_master;
+reset master;
+--enable_warnings
+
+#
+# Check that creation drop of view is replicated, also check replication of
+# updating of view
+#
+connection master;
+create table t1 (a int);
+insert into t1 values (1);
+create view v1 as select a from t1;
+insert into v1 values (2);
+select * from v1 order by a;
+sync_slave_with_master;
+# view already have to be on slave
+select * from v1 order by a;
+connection master;
+update v1 set a=3 where a=1;
+select * from v1 order by a;
+sync_slave_with_master;
+select * from v1 order by a;
+connection master;
+delete from v1 where a=2;
+select * from v1 order by a;
+sync_slave_with_master;
+select * from v1 order by a;
+connection master;
+# 'alter view' internally maped to creation, but still check that it works
+alter view v1 as select a as b from t1;
+sync_slave_with_master;
+select * from v1 order by 1;
+connection master;
+drop view v1;
+sync_slave_with_master;
+#error, because view have to be removed from slave
+-- error 1146
+select * from v1 order by a;
+connection master;
+drop table t1;
+sync_slave_with_master;
+# Change Author: JBM
+# Change Date: 2005-12-22
+# Change: Commented out binlog events to work with SBR and RBR
+#--replace_column 2 # 5 #
+# show binlog events limit 1,100;
+
+#
+# BUG#20438: CREATE statements for views, stored routines and triggers can be
+# not replicable.
+#
+
+--echo
+--echo ---> Test for BUG#20438
+
+# Prepare environment.
+
+--echo
+--echo ---> Preparing environment...
+--connection master
+
+--disable_warnings
+DROP TABLE IF EXISTS t1;
+DROP VIEW IF EXISTS v1;
+--enable_warnings
+
+--echo
+--echo ---> Synchronizing slave with master...
+
+--sync_slave_with_master
+
+--echo
+--connection master
+
+# Test.
+
+--echo
+--echo ---> Creating objects...
+
+CREATE TABLE t1(c INT);
+
+/*!50003 CREATE VIEW v1 AS SELECT * FROM t1 */;
+
+--echo
+--echo ---> Inserting value...
+
+INSERT INTO t1 VALUES(1);
+
+--echo
+--echo ---> Checking on master...
+
+SELECT * FROM t1;
+
+--echo
+--echo ---> Synchronizing slave with master...
+
+--sync_slave_with_master
+
+SELECT * FROM t1;
+
+# Cleanup.
+
+--connection master
+
+--echo
+--echo ---> Cleaning up...
+
+DROP VIEW v1;
+DROP TABLE t1;
+
+--sync_slave_with_master
+--connection master
+
+#
+# BUG#19419: "VIEW: View that the column name is different
+# by master and slave is made".
+#
+connection master;
+create table t1(a int, b int);
+insert into t1 values (1, 1), (1, 2), (1, 3);
+create view v1(a, b) as select a, sum(b) from t1 group by a;
+
+sync_slave_with_master;
+explain v1;
+show create table v1;
+select * from v1;
+
+connection master;
+drop table t1;
+drop view v1;
+
+sync_slave_with_master;
+
+#
+# BUG#28244 CREATE VIEW breaks replication when view exists
+#
+connection master;
+CREATE TABLE t1(a INT);
+CREATE VIEW v1 AS SELECT * FROM t1;
+--error ER_TABLE_EXISTS_ERROR
+CREATE VIEW v1 AS SELECT * FROM t1;
+DROP VIEW v1;
+DROP TABLE t1;
+sync_slave_with_master;
+
+#
+# Bug#32575 Parse error of stmt with extended comments on slave side
+# Verify that 'CREATE VIEW' with comments is properly logged to binlog
+connection master;
+CREATE TABLE t1 (a INT);
+--echo # create view as output from mysqldump 10.11 (5.0.62)
+/*!50001 CREATE ALGORITHM=UNDEFINED */
+/*!50013 DEFINER=`root`@`localhost` SQL SECURITY DEFINER */
+/*!50001 VIEW `v1` AS select `t1`.`a` AS `a` from `t1` where (`t1`.`a` < 3) */
+/*!50002 WITH CASCADED CHECK OPTION */;
+SHOW CREATE VIEW v1;
+sync_slave_with_master;
+SHOW CREATE VIEW v1;
+connection master;
+DROP VIEW v1;
+DROP TABLE t1;
+sync_slave_with_master;
+
+--echo End of 5.0 tests
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_view_debug.test b/mysql-test/suite/rpl/t/rpl_view_debug.test
new file mode 100644
index 00000000..08036924
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_view_debug.test
@@ -0,0 +1,35 @@
+--source include/have_debug.inc
+--source include/master-slave.inc
+
+--echo #
+--echo # MDEV-6409 CREATE VIEW replication problem if error occurs in mysql_register_view
+--echo #
+--echo # Check the bug where if an error occurs in mysql_register_view the view
+--echo # is still replicated to the slave
+--echo #
+connection master;
+create table t1 (a int);
+insert into t1 values (1);
+create view v1 as select a from t1;
+insert into v1 values (2);
+select * from v1 order by a;
+sync_slave_with_master;
+
+# view already has to be on slave
+show tables;
+connection master;
+SET @saved_dbug = @@SESSION.debug_dbug;
+set @@debug_dbug="d,simulate_register_view_failure";
+
+--error ER_OUT_OF_RESOURCES
+CREATE VIEW v2 as SELECT * FROM t1;
+
+show tables;
+sync_slave_with_master;
+show tables;
+
+connection master;
+DROP VIEW IF EXISTS v1;
+DROP TABLE t1;
+SET debug_dbug= @saved_dbug;
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_view_multi.test b/mysql-test/suite/rpl/t/rpl_view_multi.test
new file mode 100644
index 00000000..50b9c184
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_view_multi.test
@@ -0,0 +1,133 @@
+#
+# This file contains test cases for bugs which involve views, several
+# concurren connections and manifest themselves as wrong binary log
+# sequence which results in broken replication. In principle we are
+# mostly interested in SBR here but this test will also work with RBR.
+#
+--source include/master-slave.inc
+
+--echo #
+--echo # Bug #25144 "replication / binlog with view breaks".
+--echo # Statements that used views didn't ensure that view were not modified
+--echo # during their execution. Indeed this led to incorrect binary log with
+--echo # statement based logging and as result to broken replication.
+--echo #
+#
+# Suppress "unsafe" warnings.
+#
+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_warnings
+drop tables if exists t1, t2;
+drop view if exists v1;
+--enable_warnings
+--echo # Syncing slave with master
+--sync_slave_with_master
+
+--disable_ps2_protocol
+connect (master2,127.0.0.1,root,,test,$MASTER_MYPORT,);
+
+connection master;
+create table t1 (i int);
+create table t2 (i int);
+create view v1 as select * from t1;
+
+--echo # First we try to concurrently execute statement that uses view
+--echo # and statement that drops it. We use "user" locks as means to
+--echo # suspend execution of first statement once it opens our view.
+select get_lock("lock_bg25144", 1);
+
+connection master1;
+--send insert into v1 values (get_lock("lock_bg25144", 100))
+
+connection master2;
+let $wait_condition=
+ select count(*) = 1 from information_schema.processlist
+ where state = "User lock" and info like "insert into v1 %lock_bg25144%";
+--source include/wait_condition.inc
+--send drop view v1
+
+connection master;
+let $wait_condition=
+ select count(*) = 1 from information_schema.processlist
+ where state = "Waiting for table metadata lock" and info = "drop view v1";
+--source include/wait_condition.inc
+
+select release_lock("lock_bg25144");
+
+connection master1;
+--disable_warnings
+--reap
+--enable_warnings
+select release_lock("lock_bg25144");
+
+connection master2;
+--reap
+
+connection master;
+--echo # Check that insertion through view did happen.
+select * from t1;
+--echo # Syncing slave with master
+--sync_slave_with_master
+--echo # Check that slave was able to replicate this sequence
+--echo # which means that we got correct binlog order.
+select * from t1;
+
+connection master;
+--echo # Now we will repeat the test by trying concurrently execute
+--echo # statement that uses a view and statement that alters it.
+create view v1 as select * from t1;
+
+select get_lock("lock_bg25144", 1);
+
+connection master1;
+--send insert into v1 values (get_lock("lock_bg25144", 100))
+
+connection master2;
+let $wait_condition=
+ select count(*) = 1 from information_schema.processlist
+ where state = "User lock" and info like "insert into v1 %lock_bg25144%";
+--source include/wait_condition.inc
+--send alter view v1 as select * from t2
+
+connection master;
+let $wait_condition=
+ select count(*) = 1 from information_schema.processlist
+ where state = "Waiting for table metadata lock" and
+ info = "alter view v1 as select * from t2";
+--source include/wait_condition.inc
+
+select release_lock("lock_bg25144");
+
+connection master1;
+--disable_warnings
+--reap
+--enable_warnings
+select release_lock("lock_bg25144");
+
+connection master2;
+--reap
+
+connection master;
+
+--echo # Second insertion should go to t1 as well.
+select * from t1;
+select * from t2;
+
+--echo # Syncing slave with master
+--sync_slave_with_master
+--echo # Now let us check that statements were logged in proper order
+--echo # So we have same result on slave.
+select * from t1;
+select * from t2;
+--enable_ps2_protocol
+
+connection master;
+drop table t1, t2;
+drop view v1;
+--echo # Syncing slave with master
+--sync_slave_with_master
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_xa-master.opt b/mysql-test/suite/rpl/t/rpl_xa-master.opt
new file mode 100644
index 00000000..6794216d
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_xa-master.opt
@@ -0,0 +1 @@
+--binlog-ignore-db=test_ign
diff --git a/mysql-test/suite/rpl/t/rpl_xa.inc b/mysql-test/suite/rpl/t/rpl_xa.inc
new file mode 100644
index 00000000..d22d2d2e
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_xa.inc
@@ -0,0 +1,433 @@
+#
+# This "body" file checks general properties of XA transaction replication
+# as of MDEV-742.
+# Parameters:
+# --let rpl_xa_check= SELECT ...
+#
+connection master;
+create table t1 (a int, b int) engine=InnoDB;
+insert into t1 values(0, 0);
+xa start 't';
+insert into t1 values(1, 2);
+xa end 't';
+xa prepare 't';
+xa commit 't';
+
+sync_slave_with_master;
+let $diff_tables= master:t1, slave:t1;
+source include/diff_tables.inc;
+
+connection master;
+
+xa start 't';
+insert into t1 values(3, 4);
+xa end 't';
+xa prepare 't';
+xa rollback 't';
+
+sync_slave_with_master;
+let $diff_tables= master:t1, slave:t1;
+source include/diff_tables.inc;
+
+connection master;
+--disable_warnings
+SET pseudo_slave_mode=1;
+--enable_warnings
+create table t2 (a int) engine=InnoDB;
+xa start 't';
+insert into t1 values (5, 6);
+xa end 't';
+xa prepare 't';
+xa start 's';
+insert into t2 values (0);
+xa end 's';
+xa prepare 's';
+--source include/save_master_gtid.inc
+
+connection slave;
+source include/sync_with_master_gtid.inc;
+if ($rpl_xa_check)
+{
+ --eval $rpl_xa_check
+ if ($rpl_xa_verbose)
+ {
+ --eval SELECT $rpl_xa_check_lhs
+ --eval SELECT $rpl_xa_check_rhs
+ }
+}
+sorted_result;
+xa recover;
+
+connection master;
+xa commit 't';
+xa commit 's';
+--disable_warnings
+SET pseudo_slave_mode=0;
+--enable_warnings
+sync_slave_with_master;
+let $diff_tables= master:t1, slave:t1;
+source include/diff_tables.inc;
+let $diff_tables= master:t2, slave:t2;
+source include/diff_tables.inc;
+
+#
+# Read-only XA remains prepared after disconnect and must rollback at XA-complete
+# after recoonect. To the read-only also belongs non-transactional engine XA.
+#
+--connection master
+
+--echo *** At the start of read-only section gtid list is:
+flush logs;
+--let $binlog_file= query_get_value(SHOW MASTER STATUS, File, 1)
+--source include/show_gtid_list.inc
+
+
+set @query1="select 1";
+set @query2="select count(*) into @s2 from t1";
+--let $ro_cases=2
+--let $db=test
+
+# No disconnect
+--let $p_trx=$ro_cases
+while ($p_trx)
+{
+--connection master
+ --let $xid=ro_$p_trx
+ --let $query=`SELECT @query$p_trx`
+ --source rpl_create_xa_prepared.inc
+ --let $complete=`select if(floor(rand()*10)%2,'COMMIT','ROLLBACK')`
+ --error 0
+ --disable_query_log
+ --disable_result_log
+ --eval xa $complete '$xid'
+ --enable_result_log
+ --enable_query_log
+
+ --disconnect master_$xid
+ --source include/wait_until_disconnected.inc
+
+ --dec $p_trx
+}
+
+
+--let $p_trx=$ro_cases
+# With diconnect
+while ($p_trx)
+{
+--connection master
+ --let $xid=ro_$p_trx
+ --let $query=`SELECT @query$p_trx`
+ --source rpl_create_xa_prepared.inc
+
+ --disconnect master_$xid
+ --source include/wait_until_disconnected.inc
+
+ --dec $p_trx
+}
+
+--echo *** $ro_cases prepared xa:s must be in the list:
+--connection master
+sorted_result;
+xa recover;
+
+--let $p_trx=$ro_cases
+while ($p_trx)
+{
+ --let $xid=ro_$p_trx
+ --let $complete=`select if(floor(rand()*10)%2,'COMMIT','ROLLBACK')`
+ --disable_query_log
+ --disable_result_log
+ --error ER_XA_RBROLLBACK
+ --eval xa $complete '$xid'
+ --enable_result_log
+ --enable_query_log
+
+ --dec $p_trx
+}
+--echo *** Zero prepared xa:s must be in the list:
+xa recover;
+
+--echo *** At the end of read-only section gtid list has 0 more compare with previous check:
+flush logs;
+--let $binlog_file= query_get_value(SHOW MASTER STATUS, File, 1)
+--source include/show_gtid_list.inc
+
+
+#
+# XA logging cases while some of XA resources are read-only
+#
+# A1. Binlog filter
+
+
+--let $db=test_ign
+--eval create database $db
+set @@sql_log_bin = 0;
+--eval create table $db.t (a int) engine=InnoDB
+set @@sql_log_bin = 1;
+
+--let $xid=rw_no_binlog
+--let $query=insert into $db.t set a=1
+--source rpl_create_xa_prepared.inc
+--disconnect master_$xid
+--source include/wait_until_disconnected.inc
+
+--echo *** $xid must be in the list:
+--connection master
+xa recover;
+
+--let $complete=`select if(floor(rand()*10)%2,'COMMIT','ROLLBACK')`
+--error 0
+--disable_query_log
+--disable_result_log
+--eval xa $complete '$xid'
+--enable_result_log
+--enable_query_log
+
+--echo *** Zero must be in the list:
+--connection master
+xa recover;
+# restore for the following tests
+--let $db=test
+
+--echo *** At the end of --binlog-ignore-db section gtid list has 2 more:
+flush logs;
+--let $binlog_file= query_get_value(SHOW MASTER STATUS, File, 1)
+--source include/show_gtid_list.inc
+
+#
+# A2. Opposite to A1, ineffective execution in Engine may create a
+# binlog transaction
+#
+connection master;
+create table t3 (a int) engine=innodb;
+
+--echo *** the disconnected prepare case
+--let $xid=rw_binlog_only
+--let $query=delete from t3
+--connect (master_$xid, 127.0.0.1,root,,$db,$MASTER_MYPORT,)
+ set @@binlog_format=statement;
+ # --source rpl_create_xa_prepared.inc
+ --eval xa start '$xid'
+ --eval $query
+ --eval xa end '$xid'
+ --eval xa prepare '$xid'
+
+ --disconnect master_$xid
+ --source include/wait_until_disconnected.inc
+
+connection master;
+--echo *** $xid must be in the list:
+xa recover;
+
+ --let $complete=`select if(floor(rand()*10)%2,'COMMIT','ROLLBACK')`
+ --disable_query_log
+ --disable_result_log
+ --eval xa $complete '$xid'
+ --enable_result_log
+ --enable_query_log
+
+--echo *** Zero must be in the list:
+xa recover;
+
+--echo *** the same connection complete case.
+connection master;
+ --let $xid=rw_binlog_only
+ --let $query=delete from t3
+--connect (master_$xid, 127.0.0.1,root,,$db,$MASTER_MYPORT,)
+ set @@binlog_format=statement;
+ # --source rpl_create_xa_prepared.inc
+ --eval xa start '$xid'
+ --eval $query
+ --eval xa end '$xid'
+ --eval xa prepare '$xid'
+
+--echo *** $xid must be in the list:
+xa recover;
+
+--disable_query_log
+ --disable_result_log
+ --eval xa $complete '$xid'
+ --enable_result_log
+ --enable_query_log
+--disconnect master_$xid
+--source include/wait_until_disconnected.inc
+
+--echo *** Zero must be in the list:
+--connection master
+xa recover;
+
+--echo *** At the end of ineffective in engine section gtid list has 5 more:
+flush logs;
+--let $binlog_file= query_get_value(SHOW MASTER STATUS, File, 1)
+--source include/show_gtid_list.inc
+
+#
+# A3 MyISAM "xa" logs empty XA-prepare group, followed by
+# an XA-complete event
+create table tm (a int) engine=myisam;
+
+# No disconnect
+--connection master
+ --let $xid=rw_myisam
+ --let $query=insert into tm set a=1
+ --source rpl_create_xa_prepared.inc
+ --let $complete=`select if(floor(rand()*10)%2,'COMMIT','ROLLBACK')`
+ --error 0
+ --disable_query_log
+ --disable_result_log
+ --eval xa $complete '$xid'
+ --enable_result_log
+ --enable_query_log
+
+ --disconnect master_$xid
+ --source include/wait_until_disconnected.inc
+
+# With diconnect
+--connection master
+ --source rpl_create_xa_prepared.inc
+ --disconnect master_$xid
+ --source include/wait_until_disconnected.inc
+
+--echo *** $xid prepared must be in the list:
+--connection master
+xa recover;
+
+ --let $complete=`select if(floor(rand()*10)%2,'COMMIT','ROLLBACK')`
+ --disable_query_log
+ --disable_result_log
+ --eval xa $complete '$xid'
+ --enable_result_log
+ --enable_query_log
+
+--echo *** Zero prepared xa:s must be in the list:
+xa recover;
+
+--echo *** At the end of MyISAM "xa" section gtid list has 7 more compare with previous check:
+flush logs;
+--let $binlog_file= query_get_value(SHOW MASTER STATUS, File, 1)
+--source include/show_gtid_list.inc
+
+
+# B. Session binlog disable does not log even empty XA-prepare
+# Therefore XA-complete should be also run in sql_log_bin-OFF environment.
+
+--let $db=test
+--let $xid=skip_binlog
+--let $query=insert into t2 values(1)
+--connect (master_$xid, 127.0.0.1,root,,$db,$MASTER_MYPORT,)
+set @@session.sql_log_bin = OFF;
+--eval xa start '$xid'
+ --eval $query
+--eval xa end '$xid'
+--eval xa prepare '$xid'
+
+--disconnect master_$xid
+--source include/wait_until_disconnected.inc
+
+--echo *** $xid must be in the list:
+--connection master
+xa recover;
+
+# now commit it carefully to avoid binlogging as the prepare part did
+set @@session.sql_log_bin = OFF;
+--eval xa rollback '$xid'
+set @@session.sql_log_bin = ON;
+--source include/save_master_gtid.inc
+
+--echo *** Zero must be in the list:
+--connection master
+xa recover;
+
+--echo *** At the end of skip_log_binb section gtid list has 0 more:
+flush logs;
+--let $binlog_file= query_get_value(SHOW MASTER STATUS, File, 1)
+--source include/show_gtid_list.inc
+
+#
+# sync slave successfully to prove its consistency
+#
+--connection slave
+source include/sync_with_master_gtid.inc;
+
+
+connection master;
+--eval drop database test_ign
+drop table t1, t2, t3, tm;
+
+--echo #
+--echo # MDEV-26682 slave lock timeout with XA and gap locks
+--echo #
+create table t1 (a int primary key, b int unique) engine=innodb;
+insert t1 values (1,1),(3,3),(5,5);
+sync_slave_with_master;
+
+# set a strong isolation level to keep the read view below.
+# alternatively a long-running select can do that too even in read-committed
+set session tx_isolation='repeatable-read';
+start transaction;
+# opens a read view to disable purge on the slave
+select * from t1;
+
+connect m2, localhost, root;
+# now, delete a value, purge it on the master, but not on the slave
+delete from t1 where a=3;
+xa start 'x1';
+# this sets a gap lock on <3>, when it exists (so, on the slave)
+update t1 set b=3 where a=5;
+xa end 'x1';
+xa prepare 'x1';
+
+connect m3, localhost, root;
+# and this tries to insert straight into the locked gap
+insert t1 values (2, 2);
+
+echo -->slave;
+sync_slave_with_master;
+commit;
+select * from t1;
+
+connection m2;
+xa rollback 'x1';
+disconnect m2;
+disconnect m3;
+
+connection master;
+
+drop table t1;
+
+create table t1 (id int auto_increment primary key, c1 int not null unique)
+engine=innodb;
+
+create table t2 (id int auto_increment primary key, c1 int not null,
+foreign key(c1) references t1(c1), unique key(c1)) engine=innodb;
+
+insert t1 values (869,1), (871,3), (873,4), (872,5), (870,6), (877,7);
+insert t2 values (795,6), (800,7);
+
+xa start '1';
+update t2 set id = 9, c1 = 5 where c1 in (null, null, null, null, null, 7, 3);
+
+connect con1, localhost,root;
+xa start '2';
+delete from t1 where c1 like '3%';
+xa end '2';
+xa prepare '2';
+
+connection master;
+xa end '1';
+xa prepare '1';
+
+echo ->slave;
+
+sync_slave_with_master;
+
+connection slave;
+source include/sync_with_master_gtid.inc;
+
+connection con1;
+xa commit '2';
+disconnect con1;
+
+connection master;
+xa commit '1';
+drop table t2, t1;
diff --git a/mysql-test/suite/rpl/t/rpl_xa.test b/mysql-test/suite/rpl/t/rpl_xa.test
new file mode 100644
index 00000000..05a1abe5
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_xa.test
@@ -0,0 +1,5 @@
+source include/have_innodb.inc;
+source include/master-slave.inc;
+
+source rpl_xa.inc;
+source include/rpl_end.inc;
diff --git a/mysql-test/suite/rpl/t/rpl_xa_empty_transaction.cnf b/mysql-test/suite/rpl/t/rpl_xa_empty_transaction.cnf
new file mode 100644
index 00000000..92acd0c7
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_xa_empty_transaction.cnf
@@ -0,0 +1,18 @@
+!include include/default_mysqld.cnf
+
+[mysqld.1]
+log-slave-updates
+innodb
+
+[mysqld.2]
+log-slave-updates
+innodb
+
+[mysqld.3]
+log-slave-updates
+innodb
+
+[ENV]
+SERVER_MYPORT_1= @mysqld.1.port
+SERVER_MYPORT_2= @mysqld.2.port
+SERVER_MYPORT_3= @mysqld.3.port
diff --git a/mysql-test/suite/rpl/t/rpl_xa_empty_transaction.test b/mysql-test/suite/rpl/t/rpl_xa_empty_transaction.test
new file mode 100644
index 00000000..61cc0621
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_xa_empty_transaction.test
@@ -0,0 +1,175 @@
+#
+# Purpose:
+# This test ensures consistency in binlogging behavior for XA transactions
+# that have all statements error and rollback, effectively leaving an "empty"
+# transaction. In such cases, an empty XA transaction should be binlogged. The
+# bug reported by MDEV-25616 revealed that an "empty" XA transaction would
+# binlog an XA ROLLBACK or XA COMMIT event without a preceding setup, i.e.
+# XA START through XA PREPARE. The bug presented differently for XA
+# transactions consisting of transactional and non-transactional statements.
+# Therefore, this test validates that an entire XA transaction is binlogged
+# for different combinations of transactional or non-transactional statements.
+# Note that the behavior changes when binlogging empty XA transactions
+# depending on the binlog_row_format variables. That is, when the content of
+# the transaction consists of errored transactional statements, in row format,
+# an empty XA transaction will be binlogged; however, in mixed and statement
+# formats, nothing will be written into the binary log.
+#
+# Methodology:
+# Create XA transactions with various combinations of erroring transactional
+# or non-transactional statements. The binary log is examined to ensure all
+# XA components are written. Chain replication is used, i.e.
+# (primary->replica->replica), to ensure replica binlogging is consistent with
+# manual execution. The transactional and non-transactional tables use InnoDB
+# and MyISAM, respectively.
+#
+# Parameters
+# $expect_transactional_xa_binlog : Boolean indicating whether or not an
+# errored transactional statement should result in XA statements written
+# into the binary log.
+#
+# References:
+# MDEV-25616: Binlog event for XA COMMIT is generated without matching
+# XA START, replication aborts
+#
+--source include/have_log_bin.inc
+
+--let $rpl_server_count= 3
+--let $rpl_topology= 1->2->3
+--source include/rpl_init.inc
+
+--connection server_1
+-- source include/have_innodb.inc
+--connection server_2
+-- source include/have_innodb.inc
+--connection server_3
+-- source include/have_innodb.inc
+--connection server_1
+
+--echo #
+--echo # Test Case 1: An XA transaction without any statements should not be
+--echo # binlogged
+--let $trx_statements=
+
+--let $xa_completion_action= COMMIT
+--source include/rpl_xa_empty_transaction.inc
+
+--let $xa_completion_action= ROLLBACK
+--source include/rpl_xa_empty_transaction.inc
+
+
+--echo #
+--echo # Test Case 2: An XA transaction consisting of a successfully rolled back
+--echo # statement should not be binlogged
+--let $trx_statements= T
+
+--let $xa_completion_action= COMMIT
+--source include/rpl_xa_empty_transaction.inc
+
+--let $xa_completion_action= ROLLBACK
+--source include/rpl_xa_empty_transaction.inc
+
+
+--echo #
+--echo # Test Case 3: An XA transaction with a statement that cannot be rolled
+--echo # back should be binlogged
+
+# TODO: remove work-around MDEV-24654 when fixed.
+--connection server_1
+set @sav_binlog_format = @@binlog_format;
+set @@binlog_format = row;
+set @@global.binlog_format = row;
+--let $trx_statements= N
+
+--let $xa_completion_action= COMMIT
+--source include/rpl_xa_empty_transaction.inc
+
+--let $xa_completion_action= ROLLBACK
+--source include/rpl_xa_empty_transaction.inc
+
+--connection server_1
+set @@binlog_format = @sav_binlog_format;
+set @@global.binlog_format = @sav_binlog_format;
+
+
+--echo #
+--echo # Test Case 4: An XA transaction with multiple statements that can all
+--echo # be rolled back should not be binlogged
+--let $trx_statements= T,T
+
+--let $xa_completion_action= COMMIT
+--source include/rpl_xa_empty_transaction.inc
+
+--let $xa_completion_action= ROLLBACK
+--source include/rpl_xa_empty_transaction.inc
+
+
+--echo #
+--echo # Test Case 5: A mixed XA transaction consisting of one statement that
+--echo # can successfully be rolled back (first statement), and another that
+--echo # can not (second statement) should be binlogged
+
+--connection server_1
+set @sav_binlog_format = @@binlog_format;
+set @@binlog_format = row;
+set @@global.binlog_format = row;
+--let $trx_statements= T,N
+
+--let $xa_completion_action= COMMIT
+--source include/rpl_xa_empty_transaction.inc
+
+--let $xa_completion_action= ROLLBACK
+--source include/rpl_xa_empty_transaction.inc
+
+--connection server_1
+set @@binlog_format = @sav_binlog_format;
+set @@global.binlog_format = @sav_binlog_format;
+
+
+--echo #
+--echo # Test Case 6: A mixed XA transaction consisting of one statement that
+--echo # cannot successfully be rolled back (first statement), and another that
+--echo # can (second statement) should be binlogged
+
+--connection server_1
+set @sav_binlog_format = @@binlog_format;
+set @@binlog_format = row;
+set @@global.binlog_format = row;
+--let $trx_statements= N,T
+
+--let $xa_completion_action= COMMIT
+--source include/rpl_xa_empty_transaction.inc
+
+--let $xa_completion_action= ROLLBACK
+--source include/rpl_xa_empty_transaction.inc
+
+--connection server_1
+set @@binlog_format = @sav_binlog_format;
+set @@global.binlog_format = @sav_binlog_format;
+
+--echo #
+--echo # Test Case 7: An XA transaction consisting of two failed
+--echo # non-transactional statements should be binlogged
+
+--connection server_1
+set @sav_binlog_format = @@binlog_format;
+set @@binlog_format = row;
+set @@global.binlog_format = row;
+--let $trx_statements= N,N
+
+--let $xa_completion_action= COMMIT
+--source include/rpl_xa_empty_transaction.inc
+
+--let $xa_completion_action= ROLLBACK
+--source include/rpl_xa_empty_transaction.inc
+
+--connection server_1
+set @@binlog_format = @sav_binlog_format;
+set @@global.binlog_format = @sav_binlog_format;
+
+#
+# Cleanup
+--connection server_1
+--source include/rpl_end.inc
+
+--echo # End of rpl_xa_empty_transaction.test
diff --git a/mysql-test/suite/rpl/t/rpl_xa_gap_lock-slave.opt b/mysql-test/suite/rpl/t/rpl_xa_gap_lock-slave.opt
new file mode 100644
index 00000000..4602a43c
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_xa_gap_lock-slave.opt
@@ -0,0 +1 @@
+--transaction-isolation=READ-COMMITTED
diff --git a/mysql-test/suite/rpl/t/rpl_xa_gap_lock.test b/mysql-test/suite/rpl/t/rpl_xa_gap_lock.test
new file mode 100644
index 00000000..29e883a1
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_xa_gap_lock.test
@@ -0,0 +1,137 @@
+# ==== Purpose ====
+#
+# This test will generate two XA transactions on the master in a way that
+# they will block each other on the slave if the transaction isolation level
+# used by the slave applier is more restrictive than the READ COMMITTED one.
+#
+# Consider:
+# E=execute, P=prepare, C=commit;
+# 1=first transaction, 2=second transaction;
+#
+# Master does: E1, E2, P2, P1, C1, C2
+# Slave does: E2, P2, E1, P1, C1, C2
+#
+# The transactions are designed so that, if the applier transaction isolation
+# level is more restrictive than the READ COMMITTED, E1 will be blocked on
+# the slave waiting for gap locks to be released.
+#
+# Step 1
+#
+# The test will verify that the transactions don't block each other because
+# the applier thread automatically changed the isolation level.
+#
+# Step 2
+#
+# The test will verify that applying master's binary log dump in slave doesn't
+# block because mysqlbinlog is informing the isolation level to be used.
+#
+# ==== Related Bugs and Worklogs ====
+#
+# BUG#25040331: INTERLEAVED XA TRANSACTIONS MAY DEADLOCK SLAVE APPLIER WITH
+# REPEATABLE READ
+#
+--source include/have_debug.inc
+--source include/have_innodb.inc
+# The test case only make sense for RBR
+--source include/have_binlog_format_row.inc
+--source include/master-slave.inc
+
+--connection slave
+# To hit the issue, we need to split the data in two pages.
+# This global variable will help us.
+SET @saved_innodb_limit_optimistic_insert_debug = @@GLOBAL.innodb_limit_optimistic_insert_debug;
+SET @@GLOBAL.innodb_limit_optimistic_insert_debug = 2;
+
+#
+# Step 1 - Using async replication
+#
+
+# Let's generate the workload on the master
+--connection master
+CREATE TABLE t1 (
+ c1 INT NOT NULL,
+ KEY(c1)
+) ENGINE=InnoDB;
+
+CREATE TABLE t2 (
+ c1 INT NOT NULL,
+ FOREIGN KEY(c1) REFERENCES t1(c1)
+) ENGINE=InnoDB;
+
+INSERT INTO t1 VALUES (1), (3), (4);
+
+--connection master1
+XA START 'XA1';
+INSERT INTO t1 values(2);
+XA END 'XA1';
+
+# This transaction will reference the gap where XA1
+# was inserted, and will be prepared and committed
+# before XA1, so the slave will prepare it (but will
+# not commit it) before preparing XA1.
+--connection master
+XA START 'XA2';
+INSERT INTO t2 values(3);
+XA END 'XA2';
+
+# The XA2 prepare should be binary logged first
+XA PREPARE 'XA2';
+
+# The XA1 prepare should be binary logged
+# after XA2 prepare and before XA2 commit.
+--connection master1
+XA PREPARE 'XA1';
+
+# The commit order doesn't matter much for the issue being tested.
+XA COMMIT 'XA1';
+--connection master
+XA COMMIT 'XA2';
+
+# Everything is fine if the slave can sync with the master.
+--source include/sync_slave_sql_with_master.inc
+
+#
+# Step 2 - Using mysqlbinlog dump to restore the salve
+#
+--source include/stop_slave.inc
+DROP TABLE t2, t1;
+RESET SLAVE;
+RESET MASTER;
+
+--connection master
+--let $master_data_dir= `SELECT @@datadir`
+--let $master_log_file= query_get_value(SHOW MASTER STATUS, File, 1)
+--let $mysql_server= $MYSQL --defaults-group-suffix=.2
+--echo Restore binary log from the master into the slave
+--exec $MYSQL_BINLOG --force-if-open $master_data_dir/$master_log_file | $mysql_server
+
+--let $diff_tables= master:test.t1, slave:test.t1
+--source include/diff_tables.inc
+--let $diff_tables= master:test.t2, slave:test.t2
+--source include/diff_tables.inc
+
+#
+# Cleanup
+#
+--let $master_file= query_get_value(SHOW MASTER STATUS, File, 1)
+--let $master_pos= query_get_value(SHOW MASTER STATUS, Position, 1)
+DROP TABLE t2, t1;
+
+## When GTID_MODE=OFF, we need to skip already applied transactions
+--connection slave
+#--let $gtid_mode= `SELECT @@GTID_MODE`
+#if ($gtid_mode == OFF)
+#{
+# --disable_query_log
+# --disable_result_log
+# --eval CHANGE MASTER TO MASTER_LOG_FILE='$master_file', MASTER_LOG_POS=$master_pos
+# --enable_result_log
+# --enable_query_log
+#}
+--replace_result $master_file LOG_FILE $master_pos LOG_POS
+--eval CHANGE MASTER TO MASTER_LOG_FILE='$master_file', MASTER_LOG_POS=$master_pos, MASTER_USE_GTID=NO
+
+SET @@GLOBAL.innodb_limit_optimistic_insert_debug = @saved_innodb_limit_optimistic_insert_debug;
+--source include/start_slave.inc
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_xa_gtid_pos_auto_engine-master.opt b/mysql-test/suite/rpl/t/rpl_xa_gtid_pos_auto_engine-master.opt
new file mode 100644
index 00000000..6794216d
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_xa_gtid_pos_auto_engine-master.opt
@@ -0,0 +1 @@
+--binlog-ignore-db=test_ign
diff --git a/mysql-test/suite/rpl/t/rpl_xa_gtid_pos_auto_engine.test b/mysql-test/suite/rpl/t/rpl_xa_gtid_pos_auto_engine.test
new file mode 100644
index 00000000..b8349376
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_xa_gtid_pos_auto_engine.test
@@ -0,0 +1,29 @@
+--source include/have_innodb.inc
+--source include/master-slave.inc
+
+--connection slave
+call mtr.add_suppression("The automatically created table.*name may not be entirely in lowercase");
+
+--source include/stop_slave.inc
+CHANGE MASTER TO master_use_gtid=slave_pos;
+
+SET @@global.gtid_pos_auto_engines="innodb";
+--source include/start_slave.inc
+--let $rpl_xa_check_lhs= @@global.gtid_slave_pos
+--let $rpl_xa_check_rhs= CONCAT(domain_id,"-",server_id,"-",seq_no) FROM mysql.gtid_slave_pos WHERE seq_no = (SELECT DISTINCT max(seq_no) FROM mysql.gtid_slave_pos)
+--let $rpl_xa_check=SELECT $rpl_xa_check_lhs = $rpl_xa_check_rhs
+--source rpl_xa.inc
+
+--connection slave
+--source include/stop_slave.inc
+SET @@global.gtid_pos_auto_engines="";
+SET @@session.sql_log_bin=0;
+DROP TABLE mysql.gtid_slave_pos_InnoDB;
+if (`SHOW COUNT(*) WARNINGS`)
+{
+ show tables in mysql like 'gtid_slave_pos%';
+}
+SET @@session.sql_log_bin=1;
+--source include/start_slave.inc
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_xa_prepare_gtid_fail.test b/mysql-test/suite/rpl/t/rpl_xa_prepare_gtid_fail.test
new file mode 100644
index 00000000..aa1b088e
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_xa_prepare_gtid_fail.test
@@ -0,0 +1,102 @@
+#
+# When handling the replication of an XA PREPARE, the commit phase is
+# bifurcated. First, the prepare is handled by the relevant storage engines.
+# Then second,the GTID slave state is updated as a separate autocommit
+# transaction. If the second stage fails, i.e. we are unable to update the
+# GTID slave state, then the slave should immediately quit in error, without
+# retry.
+#
+# This tests validates the above behavior by forcing a lock-wait timeout on
+# the GTID slave state table during the second part of XA PREPARE's commit, to
+# ensure that the appropriate error is reported and the transaction was never
+# retried.
+#
+#
+# References
+# MDEV-31038: Parallel Replication Breaks if XA PREPARE Fails Updating Slave
+# GTID State
+#
+source include/master-slave.inc;
+source include/have_binlog_format_row.inc;
+source include/have_innodb.inc;
+
+--connection slave
+--source include/stop_slave.inc
+
+set @save_par_thds= @@global.slave_parallel_threads;
+set @save_strict_mode= @@global.gtid_strict_mode;
+set @save_innodb_lock_wait_timeout= @@global.innodb_lock_wait_timeout;
+
+change master to master_use_gtid=slave_pos;
+set @@global.slave_parallel_threads= 4;
+set @@global.slave_parallel_mode= optimistic;
+set @@global.gtid_strict_mode=ON;
+
+set statement sql_log_bin=0 for alter table mysql.gtid_slave_pos engine=innodb;
+--source include/start_slave.inc
+
+--connection master
+create table t1 (a int primary key, b int) engine=innodb;
+insert t1 values (1,1);
+--source include/save_master_gtid.inc
+
+--connection slave
+--source include/sync_with_master_gtid.inc
+--source include/stop_slave.inc
+set @@global.innodb_lock_wait_timeout= 1;
+
+--let $retried_tx_initial= query_get_value(SHOW ALL SLAVES STATUS, Retried_transactions, 1)
+
+--connection master
+--let $gtid_domain_id=`SELECT @@GLOBAL.gtid_domain_id`
+--let $gtid_server_id=`SELECT @@GLOBAL.server_id`
+--let $xap_seq_no=100
+--eval set @@session.gtid_seq_no=$xap_seq_no
+xa start '1';
+update t1 set b=b+10 where a=1;
+xa end '1';
+xa prepare '1';
+--let $new_gtid= `SELECT @@global.gtid_binlog_pos`
+xa commit '1';
+--source include/save_master_gtid.inc
+
+--connection slave1
+BEGIN;
+--eval SELECT * FROM mysql.gtid_slave_pos WHERE seq_no=$xap_seq_no FOR UPDATE
+
+--connection slave
+--source include/start_slave.inc
+
+--let $slave_sql_errno= 1942
+--source include/wait_for_slave_sql_error.inc
+
+# TODO: Remove after fixing MDEV-21777
+# Stop the IO thread too, so the existing relay logs are force purged on slave
+# restart, as to not re-execute the already-prepared transaction
+--source include/stop_slave_io.inc
+
+--let $retried_tx_test= query_get_value(SHOW ALL SLAVES STATUS, Retried_transactions, 1)
+if ($retried_tx_initial != $retried_tx_test)
+{
+ --echo Transaction was retried when a failed XA PREPARE slave GTID update should lead to immediate slave stop without retry
+ --die Transaction was retried when a failed XA PREPARE slave GTID update should lead to immediate slave stop without retry
+}
+
+--connection slave1
+ROLLBACK;
+
+--echo # Cleanup
+
+--connection master
+drop table t1;
+
+--connection slave
+--echo # TODO: Remove after fixing MDEV-21777
+--eval set @@global.gtid_slave_pos= "$new_gtid"
+set @@global.slave_parallel_threads= @save_par_thds;
+set @@global.gtid_strict_mode= @save_strict_mode;
+set @@global.innodb_lock_wait_timeout= @save_innodb_lock_wait_timeout;
+--source include/start_slave.inc
+
+--source include/rpl_end.inc
+--echo # End of rpl_xa_prepare_gtid_fail.test
diff --git a/mysql-test/suite/rpl/t/rpl_xa_survive_disconnect.test b/mysql-test/suite/rpl/t/rpl_xa_survive_disconnect.test
new file mode 100644
index 00000000..e4193a35
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_xa_survive_disconnect.test
@@ -0,0 +1,301 @@
+# BUG #12161 Xa recovery and client disconnection
+# the test verifies that
+# a. disconnection does not lose a prepared transaction
+# so it can be committed from another connection
+# c. the prepared transaction is logged
+# d. interleaved prepared transactions are correctly applied on the slave.
+
+#
+# Both replication format are checked through explict
+# set @@binlog_format in the test.
+#
+--source include/have_innodb.inc
+--source include/have_binlog_format_mixed.inc
+#
+# Prepared XA can't get available to an external connection
+# until a 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.
+#
+--source include/have_perfschema.inc
+--source include/master-slave.inc
+
+--connection master
+call mtr.add_suppression("Found 2 prepared XA transactions");
+CREATE VIEW v_processlist as SELECT * FROM performance_schema.threads where type = 'FOREGROUND';
+
+CREATE DATABASE d1;
+CREATE DATABASE d2;
+
+CREATE TABLE d1.t (a INT) ENGINE=innodb;
+CREATE TABLE d2.t (a INT) ENGINE=innodb;
+
+# MDEV-515 takes X-lock on the table for the first insert.
+# So concurrent DML won't happen on the table
+INSERT INTO d1.t VALUES(100);
+
+connect (master_conn1, 127.0.0.1,root,,test,$MASTER_MYPORT,);
+--let $conn_id=`SELECT connection_id()`
+SET @@session.binlog_format= statement;
+XA START '1-stmt';
+INSERT INTO d1.t VALUES (1);
+XA END '1-stmt';
+XA PREPARE '1-stmt';
+
+--disconnect master_conn1
+
+--connection master
+
+--let $wait_condition= SELECT count(*) = 0 FROM v_processlist WHERE PROCESSLIST_ID = $conn_id
+--source include/wait_condition.inc
+
+connect (master_conn2, 127.0.0.1,root,,test,$MASTER_MYPORT,);
+--let $conn_id=`SELECT connection_id()`
+SET @@session.binlog_format= row;
+XA START '1-row';
+INSERT INTO d2.t VALUES (1);
+XA END '1-row';
+XA PREPARE '1-row';
+
+--disconnect master_conn2
+
+--connection master
+--let $wait_condition= SELECT count(*) = 0 FROM v_processlist WHERE PROCESSLIST_ID = $conn_id
+--source include/wait_condition.inc
+
+XA START '2';
+INSERT INTO d1.t VALUES (2);
+XA END '2';
+XA PREPARE '2';
+XA COMMIT '2';
+
+XA COMMIT '1-row';
+XA COMMIT '1-stmt';
+source include/show_binlog_events.inc;
+
+# the proof: slave is in sync with the table updated by the prepared transactions.
+--source include/sync_slave_sql_with_master.inc
+
+--source include/stop_slave.inc
+
+#
+# Recover with Master server restart
+#
+--connection master
+
+connect (master2, 127.0.0.1,root,,test,$MASTER_MYPORT,);
+--connection master2
+SET @@session.binlog_format= statement;
+XA START '3-stmt';
+INSERT INTO d1.t VALUES (3);
+XA END '3-stmt';
+XA PREPARE '3-stmt';
+--disconnect master2
+
+connect (master2, 127.0.0.1,root,,test,$MASTER_MYPORT,);
+--connection master2
+SET @@session.binlog_format= row;
+XA START '3-row';
+INSERT INTO d2.t VALUES (4);
+XA END '3-row';
+XA PREPARE '3-row';
+--disconnect master2
+
+--connection master
+
+#
+# Testing read-only
+#
+connect (master2, 127.0.0.1,root,,test,$MASTER_MYPORT,);
+--connection master2
+XA START '4';
+SELECT * FROM d1.t;
+XA END '4';
+XA PREPARE '4';
+--disconnect master2
+
+#
+# Logging few disconnected XA:s for replication.
+#
+--let $bulk_trx_num=10
+--let $i = $bulk_trx_num
+
+while($i > 0)
+{
+ --connect (master_bulk_conn$i, 127.0.0.1,root,,test,$MASTER_MYPORT,)
+ --let $conn_id=`SELECT connection_id()`
+
+ --eval XA START 'bulk_trx_$i'
+ --eval INSERT INTO d1.t VALUES ($i)
+ --eval INSERT INTO d2.t VALUES ($i)
+ --eval XA END 'bulk_trx_$i'
+ --eval XA PREPARE 'bulk_trx_$i'
+
+ --disconnect master_bulk_conn$i
+
+ --connection master
+ --let $wait_condition= SELECT count(*) = 0 FROM v_processlist WHERE PROCESSLIST_ID = $conn_id
+ --source include/wait_condition.inc
+
+ --dec $i
+}
+
+#
+# Prove the slave applier is capable to resume the prepared XA:s
+# upon its restart.
+#
+--connection slave
+--source include/start_slave.inc
+--connection master
+--source include/sync_slave_sql_with_master.inc
+--source include/stop_slave.inc
+
+--connection master
+--let $i = $bulk_trx_num
+while($i > 0)
+{
+ --let $command=COMMIT
+ if (`SELECT $i % 2`)
+ {
+ --let $command=ROLLBACK
+ }
+ --eval XA $command 'bulk_trx_$i'
+ --dec $i
+}
+
+--let $rpl_server_number= 1
+--source include/rpl_restart_server.inc
+
+--connection slave
+--source include/start_slave.inc
+
+--connection master
+--echo *** '3-stmt','3-row' xa-transactions must be in the list ***
+XA RECOVER;
+XA COMMIT '3-stmt';
+XA ROLLBACK '3-row';
+
+--source include/sync_slave_sql_with_master.inc
+
+#
+# Testing replication with marginal XID values and in two formats.
+#
+
+--connection master
+--let $wait_condition= SELECT count(*) = 0 FROM v_processlist WHERE PROCESSLIST_ID = $conn_id
+--source include/wait_condition.inc
+
+# Max size XID incl max value of formatID
+--let $formatid_range=`SELECT (1<<31)`
+--let $max_formatid=`SELECT (1<<31) - 1`
+
+connect (master_conn2, 127.0.0.1,root,,test,$MASTER_MYPORT,);
+--let $conn_id=`SELECT connection_id()`
+
+--let $gtrid=0123456789012345678901234567890123456789012345678901234567890124
+--let $bqual=0123456789012345678901234567890123456789012345678901234567890124
+--eval XA START '$gtrid','$bqual',$max_formatid
+ INSERT INTO d1.t VALUES (64);
+--eval XA END '$gtrid','$bqual',$max_formatid
+--eval XA PREPARE '$gtrid','$bqual',$max_formatid
+
+--disconnect master_conn2
+
+--connection master
+--let $wait_condition= SELECT count(*) = 0 FROM v_processlist WHERE PROCESSLIST_ID = $conn_id
+--source include/wait_condition.inc
+
+# Max size XID with non-ascii chars
+connect (master_conn3, 127.0.0.1,root,,test,$MASTER_MYPORT,);
+--let $conn_id=`SELECT connection_id()`
+
+--let $gtrid_hex=FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+--let $bqual_hex=00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+--eval XA START X'$gtrid_hex',X'$bqual_hex',0
+ INSERT INTO d1.t VALUES (0);
+--eval XA END X'$gtrid_hex',X'$bqual_hex',0
+--eval XA PREPARE X'$gtrid_hex',X'$bqual_hex',0
+
+--disconnect master_conn3
+
+--connection master
+--let $wait_condition= SELECT count(*) = 0 FROM v_processlist WHERE PROCESSLIST_ID = $conn_id
+--source include/wait_condition.inc
+
+# Random XID
+--disable_query_log
+
+connect (master_conn4, 127.0.0.1,root,,test,$MASTER_MYPORT,);
+--let $conn_id=`SELECT connection_id()`
+
+--let $gtridlen=`SELECT 2*(1 + round(rand()*100) % 31)`
+--let $bquallen=`SELECT 2*(1 + round(rand()*100) % 31)`
+--let $gtrid_rand=`SELECT substring(concat(MD5(rand()), MD5(rand())), 1, $gtridlen)`
+--let $bqual_rand=`SELECT substring(concat(MD5(rand()), MD5(rand())), 1, $bquallen)`
+--let $formt_rand=`SELECT floor((rand()*10000000000) % $formatid_range)`
+--eval XA START X'$gtrid_rand',X'$bqual_rand',$formt_rand
+ INSERT INTO d1.t VALUES (0);
+--eval XA END X'$gtrid_rand',X'$bqual_rand',$formt_rand
+--eval XA PREPARE X'$gtrid_rand',X'$bqual_rand',$formt_rand
+
+--enable_query_log
+
+--disconnect master_conn4
+
+--connection master
+--let $wait_condition= SELECT count(*) = 0 FROM v_processlist WHERE PROCESSLIST_ID = $conn_id
+--source include/wait_condition.inc
+
+--eval XA COMMIT '$gtrid','$bqual',$max_formatid
+--eval XA COMMIT X'$gtrid_hex',X'$bqual_hex',0
+--disable_query_log
+--echo XA COMMIT 'RANDOM XID'
+--eval XA COMMIT X'$gtrid_rand',X'$bqual_rand',$formt_rand
+--enable_query_log
+
+--source include/sync_slave_sql_with_master.inc
+
+#
+# Testing ONE PHASE
+#
+--let $onephase_trx_num=10
+--let $i = $onephase_trx_num
+while($i > 0)
+{
+ --connect (master_bulk_conn$i, 127.0.0.1,root,,test,$MASTER_MYPORT,)
+
+ --connection master_bulk_conn$i
+ --eval XA START 'one_phase_$i'
+ --eval INSERT INTO d1.t VALUES ($i)
+ --eval INSERT INTO d2.t VALUES ($i)
+ --eval XA END 'one_phase_$i'
+ --eval XA COMMIT 'one_phase_$i' ONE PHASE
+
+ --disconnect master_bulk_conn$i
+ --dec $i
+}
+--connection master
+--source include/sync_slave_sql_with_master.inc
+
+#
+# Overall consistency check
+#
+--let $diff_tables= master:d1.t, slave:d1.t
+--source include/diff_tables.inc
+--let $diff_tables= master:d2.t, slave:d2.t
+--source include/diff_tables.inc
+#
+# cleanup
+#
+--connection master
+
+DELETE FROM d1.t;
+DELETE FROM d2.t;
+DROP TABLE d1.t, d2.t;
+DROP DATABASE d1;
+DROP DATABASE d2;
+DROP VIEW v_processlist;
+
+--source include/sync_slave_sql_with_master.inc
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_xa_survive_disconnect_lsu_off-slave.opt b/mysql-test/suite/rpl/t/rpl_xa_survive_disconnect_lsu_off-slave.opt
new file mode 100644
index 00000000..94c36500
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_xa_survive_disconnect_lsu_off-slave.opt
@@ -0,0 +1,2 @@
+--log-slave-updates=off
+
diff --git a/mysql-test/suite/rpl/t/rpl_xa_survive_disconnect_lsu_off.test b/mysql-test/suite/rpl/t/rpl_xa_survive_disconnect_lsu_off.test
new file mode 100644
index 00000000..df3811df
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_xa_survive_disconnect_lsu_off.test
@@ -0,0 +1,8 @@
+# ==== Purpose ====
+# 'rpl_xa_survive_disconnect_lsu_off' verifies the same properties as the sourced file
+# in conditions of the slave does not log own updates
+# (lsu in the name stands for log_slave_updates).
+# Specifically this mode aims at proving correct operations on the slave
+# mysql.gtid_executed.
+
+--source ./rpl_xa_survive_disconnect.test
diff --git a/mysql-test/suite/rpl/t/rpl_xa_survive_disconnect_mixed_engines.test b/mysql-test/suite/rpl/t/rpl_xa_survive_disconnect_mixed_engines.test
new file mode 100644
index 00000000..f52a9630
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_xa_survive_disconnect_mixed_engines.test
@@ -0,0 +1,68 @@
+# BUG#12161 Xa recovery and client disconnection
+#
+# The test verifies correct XA transaction two phase logging and its applying
+# in a case the transaction updates transactional and non-transactional tables.
+# Transactions are terminated according to specfied parameters to
+# a sourced inc-file.
+
+--source include/have_innodb.inc
+--source include/master-slave.inc
+
+--connection master
+CALL mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT");
+
+--let $command=setup
+--source include/rpl_xa_mixed_engines.inc
+
+--echo === COMMIT ===
+--let $command=run
+--let $xa_terminate=XA COMMIT
+--let $xa_prepare_opt=1
+--source include/rpl_xa_mixed_engines.inc
+
+--source include/sync_slave_sql_with_master.inc
+--connection master
+
+--echo === COMMIT ONE PHASE ===
+
+--let $command=run
+--let $xa_terminate=XA COMMIT
+--let $one_phase=ONE PHASE
+--let $xa_prepare_opt=
+--source include/rpl_xa_mixed_engines.inc
+--let $one_phase=
+--source include/sync_slave_sql_with_master.inc
+--connection master
+
+--echo === ROLLBACK with PREPARE ===
+
+--let $command=run
+--let $xa_terminate=xa rollback
+--let $xa_prepare_opt=1
+--source include/rpl_xa_mixed_engines.inc
+
+--source include/sync_slave_sql_with_master.inc
+--connection master
+
+--echo === ROLLBACK with no PREPARE ===
+
+--let $command=run
+--let $xa_terminate=xa rollback
+--let $xa_prepare_opt=
+--source include/rpl_xa_mixed_engines.inc
+--let $xa_rollback_only=
+
+--source include/sync_slave_sql_with_master.inc
+
+--let $diff_tables= master:tm, slave:tm
+--source include/diff_tables.inc
+
+# Cleanup
+
+--connection master
+--let $command=cleanup
+--source include/rpl_xa_mixed_engines.inc
+
+--source include/sync_slave_sql_with_master.inc
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/sec_behind_master-5114.test b/mysql-test/suite/rpl/t/sec_behind_master-5114.test
new file mode 100644
index 00000000..d1d21bfa
--- /dev/null
+++ b/mysql-test/suite/rpl/t/sec_behind_master-5114.test
@@ -0,0 +1,63 @@
+source include/have_binlog_format_statement.inc;
+source include/master-slave.inc;
+
+call mtr.add_suppression("Unsafe statement written to the binary log");
+
+
+# Make sure that the start time of the first event is certainly different
+# from the next event
+--let $timestamp= `SELECT @@timestamp`
+--disable_query_log
+eval SET TIMESTAMP= $timestamp-100;
+--enable_query_log
+CREATE TABLE t1 (a int);
+
+# Make sure that the slave is done with the first event, and all checks
+# that we'll perform later will be really against the second event
+sync_slave_with_master;
+
+connection master;
+
+# Restore the timestamp now. It doesn't matter that it's not precise,
+# it just needs to be very different from the earlier event
+--disable_query_log
+eval SET TIMESTAMP= $timestamp;
+--enable_query_log
+
+send INSERT INTO t1 VALUES(SLEEP(2));
+
+connection slave;
+
+# When the slave starts executing the event, Seconds_Behind_Master
+# should start growing steadilly. The bugfix ensures that they are
+# calculated based on the start time of the current event, rather
+# than the start time of the previous event. To check it, we only need
+# the first non-zero value
+
+let $run = 20;
+while ($run)
+{
+ dec $run;
+ let $sbm=query_get_value(SHOW SLAVE STATUS, Seconds_Behind_Master, 1);
+ # for debugging uncomment echo and remove the if()
+# echo Seconds_Behind_Master: $sbm;
+ if ($sbm)
+ {
+ let $run = 0;
+ }
+ sleep 0.5;
+}
+
+# Normally the first non-zero value should be 1. However, due to race
+# conditions on slow servers, sometimes the check might miss the value 1,
+# and only catch a higher one. It does not matter, we just need to make
+# sure it didn't start with 100+, as it would have with bug MDEV-5114
+
+--disable_query_log
+eval SELECT $sbm > 0 and $sbm < 99 AS Seconds_Behind_Master_is_less_than_100;
+--enable_query_log
+
+connection master;
+reap;
+drop table t1;
+source include/rpl_end.inc;
diff --git a/mysql-test/suite/rpl/t/semisync_future-7591.test b/mysql-test/suite/rpl/t/semisync_future-7591.test
new file mode 100644
index 00000000..793d8bcc
--- /dev/null
+++ b/mysql-test/suite/rpl/t/semisync_future-7591.test
@@ -0,0 +1,33 @@
+--source include/master-slave.inc
+
+call mtr.add_suppression("Timeout waiting for reply of binlog*");
+create table t1 (i int);
+
+set global rpl_semi_sync_master_enabled = ON;
+
+--connection slave
+--source include/stop_slave.inc
+set global rpl_semi_sync_slave_enabled = ON;
+change master to master_log_file='master-bin.000002', master_log_pos = 320, master_use_gtid=no;
+
+start slave;
+--let $slave_io_errno=1236
+--source include/wait_for_slave_io_error.inc
+
+--connection master
+insert into t1 values (1);
+reset master;
+
+--connection slave
+--source include/stop_slave.inc
+--let $master_use_gtid_option= No
+--source include/reset_slave.inc
+--source include/start_slave.inc
+
+set global rpl_semi_sync_slave_enabled = OFF;
+--connection master
+drop table t1;
+--sync_slave_with_master
+--connection master
+set global rpl_semi_sync_master_enabled = OFF;
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/semisync_memleak_4066.test b/mysql-test/suite/rpl/t/semisync_memleak_4066.test
new file mode 100644
index 00000000..e88e2335
--- /dev/null
+++ b/mysql-test/suite/rpl/t/semisync_memleak_4066.test
@@ -0,0 +1,14 @@
+#
+# MDEV-4066 semisync_master + temporary tables causes memory leaks
+#
+source include/have_binlog_format_row.inc;
+source include/master-slave.inc;
+
+connection master;
+
+--connect (con1,localhost,root,,)
+CREATE TEMPORARY TABLE tmp (i INT);
+--disconnect con1
+
+source include/rpl_end.inc;
+
diff --git a/mysql-test/suite/rpl/t/sequence.cnf b/mysql-test/suite/rpl/t/sequence.cnf
new file mode 100644
index 00000000..58b605ad
--- /dev/null
+++ b/mysql-test/suite/rpl/t/sequence.cnf
@@ -0,0 +1,8 @@
+!include ../my.cnf
+
+[mysqld.3]
+log-slave-updates
+
+[ENV]
+SERVER_MYPORT_3= @mysqld.3.port
+SERVER_MYSOCK_3= @mysqld.3.socket
diff --git a/mysql-test/suite/rpl/t/sequence.test b/mysql-test/suite/rpl/t/sequence.test
new file mode 100644
index 00000000..5c6a8e1e
--- /dev/null
+++ b/mysql-test/suite/rpl/t/sequence.test
@@ -0,0 +1,54 @@
+#
+# Testing sequences with replication
+#
+
+--source include/have_binlog_format_row.inc
+--source include/have_aria.inc
+--source include/have_sequence.inc
+
+--let $rpl_topology= 1->2->3
+--source include/rpl_init.inc
+
+--let $rpl_connection_name= master
+--let $rpl_server_number= 1
+--source include/rpl_connect.inc
+
+--let $rpl_connection_name= slave
+--let $rpl_server_number= 2
+--source include/rpl_connect.inc
+
+--let $rpl_connection_name= slave2
+--let $rpl_server_number= 3
+--source include/rpl_connect.inc
+
+--connection master
+
+set @@default_storage_engine="aria";
+
+CREATE SEQUENCE s1 cache=10;
+create table t1 select * from s1;
+--disable_ps2_protocol
+select NEXT VALUE for s1,seq from seq_1_to_20;
+--enable_ps2_protocol
+insert into t1 select * from s1;
+do setval(s1,5, 1, 0);
+insert into t1 select * from s1;
+do setval(s1, 5000, 1 ,0);
+insert into t1 select * from s1;
+alter sequence s1 minvalue=-1 start=-1 restart=-1;
+insert into t1 select * from s1;
+insert into s1 values(-100,-1000,9223372036854775806,1,1,1000,0,0);
+insert into t1 select * from s1;
+select * from t1;
+--sync_slave_with_master
+select * from t1;
+--sync_slave_with_master slave2
+select * from t1;
+
+--let $binlog_file = LAST
+source include/show_binlog_events.inc;
+
+connection master;
+drop table s1,t1;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/show_status_stop_slave_race-7126.test b/mysql-test/suite/rpl/t/show_status_stop_slave_race-7126.test
new file mode 100644
index 00000000..12794dbd
--- /dev/null
+++ b/mysql-test/suite/rpl/t/show_status_stop_slave_race-7126.test
@@ -0,0 +1,22 @@
+#
+# MDEV-7126 replication slave - deadlock in terminate_slave_thread with stop slave and show variables of replication filters and show global status
+#
+--source include/master-slave.inc
+
+call mtr.add_suppression("Master is configured to log replication events");
+
+--connection slave
+
+
+# If everything is okay, the test will end in several seconds; maybe a minute.
+# If the problem shows up, it will hang until testcase timeout is exceeded.
+--exec $MYSQL_SLAP --silent --host=127.0.0.1 -P $SLAVE_MYPORT -q "START SLAVE; STOP SLAVE; SHOW GLOBAL STATUS" -c 2 --number-of-queries=100 --create-schema=test
+
+# All done.
+
+--connection slave
+--source include/wait_for_slave_to_stop.inc
+start slave;
+
+--connection master
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/temporal_row-9560-master.opt b/mysql-test/suite/rpl/t/temporal_row-9560-master.opt
new file mode 100644
index 00000000..07c4494e
--- /dev/null
+++ b/mysql-test/suite/rpl/t/temporal_row-9560-master.opt
@@ -0,0 +1 @@
+--disable-mysql56-temporal-format
diff --git a/mysql-test/suite/rpl/t/temporal_row-9560.combinations b/mysql-test/suite/rpl/t/temporal_row-9560.combinations
new file mode 100644
index 00000000..b1c360f8
--- /dev/null
+++ b/mysql-test/suite/rpl/t/temporal_row-9560.combinations
@@ -0,0 +1,6 @@
+[old2old]
+--disable-mysql56-temporal-format
+
+[old2new]
+--enable-mysql56-temporal-format
+
diff --git a/mysql-test/suite/rpl/t/temporal_row-9560.test b/mysql-test/suite/rpl/t/temporal_row-9560.test
new file mode 100644
index 00000000..00fb59bc
--- /dev/null
+++ b/mysql-test/suite/rpl/t/temporal_row-9560.test
@@ -0,0 +1,20 @@
+#
+# MDEV-9560 Mariadb 10.1 Crashes when replicating from 10.0
+#
+source include/have_binlog_format_row.inc;
+source include/master-slave.inc;
+
+select @@mysql56_temporal_format;
+create table t1 (ts timestamp(3), t time(3), dt datetime(3));
+insert into t1 values ('2016-02-15 12:50:06.123', '12:50:06.123', '2016-02-15 12:50:06.123');
+
+sync_slave_with_master;
+
+select @@mysql56_temporal_format;
+select * from t1;
+
+connection master;
+drop table t1;
+
+source include/rpl_end.inc;
+