merged fixes for BUG#39934 to 5.1-rpl+3

Also renamed current_stmt_binlog_row_based to
current_stmt_binlog_format_row for consistency
This commit is contained in:
Sven Sandberg 2009-09-30 18:00:22 +02:00
commit 31193a632e
123 changed files with 6016 additions and 6594 deletions

View file

@ -0,0 +1,400 @@
# ==== Purpose ====
#
# Creates a stored routine, stored function, trigger, view, or
# prepared statement (commonly referred to as "recursive construct")
# that invokes a given unsafe statement.
#
# Then, it invokes the created recursive construct several times:
#
# - With SQL_LOG_BIN = 1 and binlog_format = STATEMENT, to verify
# that it gives a warning.
#
# - With SQL_LOG_BIN = 0 and binlog_format = STATEMENT, to verify that
# there is no warning and nothing is logged.
#
# - With SQL_LOG_BIN = 1 and binlog_format = MIXED, to verify that it
# writes row events to the binlog.
#
# - In some cases, the recursive construct can be invoked so that it
# has no side-effects but returns a value that may be
# nondeterministic. An example is a function that returns UUID().
# The function does not have side effects but its a return value
# that may differ on slave. Such statements are invoked so that
# the return value is discarded (e.g., SELECT func()), with
# SQL_LOG_BIN = 1 and binlog_format = STATEMENT. In this case, no
# warning should be given and nothing should be written to the
# binlog.
#
# This is an auxiliary file particularly targeted to being used by the
# test binlog_unsafe. In this context, the purpose is to check how
# warnings for unsafe statements are propagated in recursive
# constructs.
#
# The statement to invoke ("input") is described using mtr variables,
# and the resulting recursive construct ("output") is stored in mtr
# variables in a similar fashion. To create several levels of nested
# recursive constructs, source this file once, then copy the values of
# appropriate output variables to the input variables, and then source
# this file again.
#
#
# ==== Usage ====
#
# See binlog_unsafe for an example of how to use this file.
#
# let $CRC_ARG_level= <level>;
# let $CRC_ARG_type= <type>;
# let $CRC_ARG_stmt_sidef= <stmt>;
# let $CRC_ARG_value= <stmt>;
# let $CRC_ARG_sel_retval= <stmt>;
# let $CRC_ARG_sel_sidef= <stmt>;
# let $CRC_ARG_desc= <desc>;
# source extra/rpl_tests/create_recursive_construct.inc;
# let $my_stmt_sidef= $CRC_RET_stmt_sidef;
# let $my_value= $CRC_RET_value;
# let $my_sel_sidef= $CRC_RET_sel_sidef;
# let $my_sel_retval= $CRC_RET_sel_retval;
# let $my_drop= $CRC_RET_drop;
# let $my_is_toplevel= $CRC_RET_top_is_toplevel;
# let $my_desc= $CRC_RET_desc;
#
# $CRC_ARG_* are used as input parameters (arguments) to this file:
#
# $CRC_ARG_level is the recursion depth: 1 for the innermost
# statement created, 2 for a statement that invokes a statement on
# level 1, etc.
#
# $CRC_ARG_type is an integer from 0 to 6, indicating what type of
# statement shall be created:
# 0 - Create a stored function where the return value depends on
# the value of the given statement.
# 1 - Create a stored function that invokes the given statement as
# a side-effect but may not return a value that depends on it.
# 2 - Create a stored routine that invokes the given statement.
# 3 - Create a trigger (on table trigger_table_$CRC_ARG_level) that
# invokes the given statement.
# 4 - Create a view that returns a value that depends on the value
# of the given statement.
# 5 - Create a view that invokes the given statement but may return
# a value that does not depend on it.
# 6 - Create a prepared statement that invokes the given statement.
#
# $CRC_ARG_stmt_sidef is the statement to invoke. It should be a
# statement that can be invoked on its own (not sub-statement),
# which causes something unsafe to be written to the binlog.
#
# $CRC_ARG_value is a sub-statement holding the value of the given
# statement. Can be empty if the given statement does not have a
# value. Typically, this is non-empty if the given statement is a
# function call or user variable, but not if it is a stored routine
# call, INSERT, SELECT, etc (because none of them has a value).
# $CRC_ARG_value is used only when $CRC_ARG_type=6.
#
# $CRC_ARG_sel_sidef is a SELECT sub-statement that invokes the
# statement as a side-effect, but returns a result set that may not
# depend on the statement. Can be empty if the statement cannot
# produce a result set from a SELECT. $CRC_ARG_sel_sidef is used
# only if $CRC_ARG_type=2
#
# $CRC_ARG_sel_retval is a SELECT sub-statement that does not have
# side-effects, but returns a result set that depends on the unsafe
# statement. Can be empty if the statement cannot be invoked from a
# SELECT. $CRC_ARG_sel_retval is used only if $CRC_ARG_type=3.
#
# $CRC_ARG_desc is a human-readable description of the statement to
# invoke.
#
# $CRC_RET_* are used as output parameters (return values) of this
# file:
#
# $CRC_RET_stmt_sidef is a statement invoking the resulting recursive
# construct.
#
# $CRC_RET_value is a sub-statement invoking the resulting recursive
# construct and returning the value of the recursive construct.
# This is the empty string if the resulting recursive construct does
# not have a value. In particular, this is non-empty only if
# $CRC_ARG_value=7.
#
# $CRC_RET_sel_sidef is a SELECT sub-statement that invokes the
# resulting recursive construct as a side-effect but where the
# result set may not depend on the recursive construct. This is the
# empty string if the recursive construct cannot be invoked from a
# SELECT. In particular, this is non-empty only if $CRC_ARG_value=6
# or $CRC_ARG_value=2.
#
# $CRC_RET_sel_retval is a SELECT sub-statement that does not have
# side-effects, but returns a result set depending on the unsafe
# statement. This is the empty string if the recursive construct
# cannot produce a result set from a SELECT. In particular, this is
# non-empty only if $CRC_ARG_value=7 or $CRC_ARG_value=3.
#
# $CRC_RET_drop is a statement that drops the created object. I.e.,
# it is one of 'DROP FUNCTION <func>', 'DROP PROCEDURE <proc>', etc.
#
# $CRC_RET_top_is_toplevel is 0 normally, or 1 if the resulting
# recursive construct can only be called from a top-level statement.
# In particular, this is 1 only when $CRC_ARG_value=1, because
# prepared statements cannot be invoked from other recursive
# constructs.
#
# $CRC_RET_desc is a text string that describes the invokation of
# the recursive construct in a human-readable fashion.
#
# Assumptions
#
# Before sourcing this file with $CRC_ARG_level=X, you need to
# create three tables: tX, taX and trigger_table_X. These are used
# as auxiliary tables.
#--echo debug: >>>>ENTER create_recursive_construct
#--echo debug: level=$CRC_ARG_level
#--echo debug: type=$CRC_ARG_type
#--echo debug: stmt_sidef=$CRC_ARG_stmt_sidef
#--echo debug: value=$CRC_ARG_value
#--echo debug: sel_retval=$CRC_ARG_sel_retval
#--echo debug: sel_sidef=$CRC_ARG_sel_sidef
--let $CRC_RET_stmt_sidef=
--let $CRC_RET_value=
--let $CRC_RET_sel_retval=
--let $CRC_RET_sel_sidef=
--let $CRC_RET_drop=
--let $CRC_RET_is_toplevel= 1
--let $CRC_RET_desc=
--let $CRC_name=
--let $CRC_create=
######## func_retval ########
if (`SELECT $CRC_ARG_type = 0 AND '$CRC_ARG_value' != ''`) {
# It will be safe to call this function and discard the return
# value, but it will be unsafe to use return value (e.g., in
# INSERT...SELECT).
--let $CRC_name= func_retval_$CRC_ARG_level
--let $CRC_create= CREATE FUNCTION $CRC_name() RETURNS VARCHAR(100) BEGIN INSERT INTO ta$CRC_ARG_level VALUES (47); RETURN $CRC_ARG_value; END
--let $CRC_RET_stmt_sidef= INSERT INTO t$CRC_ARG_level VALUES ($CRC_name())
--let $CRC_RET_value= $CRC_name()
--let $CRC_RET_sel_sidef=
--let $CRC_RET_sel_retval= SELECT $CRC_name()
--let $CRC_RET_drop= DROP FUNCTION $CRC_name
--let $CRC_RET_is_toplevel= 0
--let $CRC_RET_desc= function $CRC_name returning value from $CRC_ARG_desc
}
######## func_sidef ########
if (`SELECT $CRC_ARG_type = 1`) {
# It will be unsafe to call func even if you discard return value.
--let $CRC_name= func_sidef_$CRC_ARG_level
--let $CRC_create= CREATE FUNCTION $CRC_name() RETURNS VARCHAR(100) BEGIN INSERT INTO ta$CRC_ARG_level VALUES (47); $CRC_ARG_stmt_sidef; RETURN 0; END
--let $CRC_RET_stmt_sidef= INSERT INTO t$CRC_ARG_level SELECT $CRC_name()
--let $CRC_RET_value=
--let $CRC_RET_sel_retval=
--let $CRC_RET_sel_sidef= SELECT $CRC_name()
--let $CRC_RET_drop= DROP FUNCTION $CRC_name
--let $CRC_RET_is_toplevel= 0
--let $CRC_RET_desc= function $CRC_name invoking $CRC_ARG_desc
}
######## proc ########
if (`SELECT $CRC_ARG_type = 2`) {
# It will be unsafe to call this procedure.
--let $CRC_name= proc_$CRC_ARG_level
--let $CRC_create= CREATE PROCEDURE $CRC_name() BEGIN INSERT INTO ta$CRC_ARG_level VALUES (47); $CRC_ARG_stmt_sidef; END
--let $CRC_RET_stmt_sidef= CALL $CRC_name()
--let $CRC_RET_value=
--let $CRC_RET_sel_retval=
--let $CRC_RET_sel_sidef=
--let $CRC_RET_drop= DROP PROCEDURE $CRC_name
--let $CRC_RET_is_toplevel= 0
--let $CRC_RET_desc= procedure $CRC_name invoking $CRC_ARG_desc
}
######## trig ########
if (`SELECT $CRC_ARG_type = 3`) {
# It will be unsafe to invoke this trigger.
--let $CRC_name= trig_$CRC_ARG_level
--let $CRC_create= CREATE TRIGGER $CRC_name BEFORE INSERT ON trigger_table_$CRC_ARG_level FOR EACH ROW BEGIN INSERT INTO ta$CRC_ARG_level VALUES (47); $CRC_ARG_stmt_sidef; END
--let $CRC_RET_stmt_sidef= INSERT INTO trigger_table_$CRC_ARG_level VALUES (1)
--let $CRC_RET_value=
--let $CRC_RET_sel_retval=
--let $CRC_RET_sel_sidef=
--let $CRC_RET_drop= DROP TRIGGER $CRC_name
--let $CRC_RET_is_toplevel= 0
--let $CRC_RET_desc= trigger $CRC_name invoking $CRC_ARG_desc
}
######## view_retval ########
if (`SELECT $CRC_ARG_type = 4 AND '$CRC_ARG_sel_retval' != ''`) {
# It will be safe to select from this view if you discard the result
# set, but unsafe to use result set (e.g., in INSERT..SELECT).
--let $CRC_name= view_retval_$CRC_ARG_level
--let $CRC_create= CREATE VIEW $CRC_name AS $CRC_ARG_sel_retval
--let $CRC_RET_stmt_sidef= INSERT INTO t$CRC_ARG_LEVEL SELECT * FROM $CRC_name
--let $CRC_RET_value=
--let $CRC_RET_sel_retval= SELECT * FROM $CRC_name
--let $CRC_RET_sel_sidef=
--let $CRC_RET_drop= DROP VIEW $CRC_name
--let $CRC_RET_is_toplevel= 0
--let $CRC_RET_desc= view $CRC_name returning value from $CRC_ARG_desc
}
######## view_sidef ########
if (`SELECT $CRC_ARG_type = 5 AND '$CRC_ARG_sel_sidef' != ''`) {
# It will be unsafe to select from this view, even if you discard
# the return value.
--let $CRC_name= view_sidef_$CRC_ARG_level
--let $CRC_create= CREATE VIEW $CRC_name AS $CRC_ARG_sel_sidef
--let $CRC_RET_stmt_sidef= INSERT INTO t$CRC_ARG_level SELECT * FROM $CRC_name
--let $CRC_RET_value=
--let $CRC_RET_sel_retval=
--let $CRC_RET_sel_sidef= SELECT * FROM $CRC_name
--let $CRC_RET_drop= DROP VIEW $CRC_name
--let $CRC_RET_is_toplevel= 0
--let $CRC_RET_desc= view $CRC_name invoking $CRC_ARG_desc
}
######## prep ########
if (`SELECT $CRC_ARG_type = 6`) {
# It will be unsafe to execute this prepared statement
--let $CRC_name= prep_$CRC_ARG_level
--let $CRC_create= PREPARE $CRC_name FROM "$CRC_ARG_stmt_sidef"
--let $CRC_RET_stmt_sidef= EXECUTE $CRC_name
--let $CRC_RET_value=
--let $CRC_RET_sel_retval=
--let $CRC_RET_sel_sidef=
--let $CRC_RET_drop= DROP PREPARE $CRC_name
--let $CRC_RET_is_toplevel= 1
--let $CRC_RET_desc= prepared statement $CRC_name invoking $CRC_ARG_desc
}
######## no recursive construct: just return the given statement ########
if (`SELECT $CRC_ARG_type = 7`) {
# CRC_ARG_type=7 is a special case. We just set $CRC_RET_x =
# $CRC_ARG_x. This way, the $CRC_ARG_stmt gets executed directly
# (below). In binlog_unsafe.test, it is used to invoke the unsafe
# statement created in the outermost loop directly, without
# enclosing it in a recursive construct.
--let $CRC_RET_stmt_sidef= $CRC_ARG_stmt_sidef
--let $CRC_RET_value= $CRC_ARG_value
--let $CRC_RET_sel_retval= $CRC_ARG_sel_retval
--let $CRC_RET_sel_sidef= $CRC_ARG_sel_sidef
--let $CRC_RET_drop=
--let $CRC_RET_is_toplevel= 1
--let $CRC_RET_desc= $CRC_ARG_desc
}
######## execute! ########
if (`SELECT '$CRC_RET_stmt_sidef' != ''`) {
--echo
--echo Invoking $CRC_RET_desc.
if (`SELECT '$CRC_create' != ''`) {
--eval $CRC_create
}
--echo * binlog_format = STATEMENT: expect $CRC_ARG_expected_number_of_warnings warnings.
--eval $CRC_RET_stmt_sidef
--let $n_warnings= `SHOW COUNT(*) WARNINGS`
if (`SELECT '$n_warnings' != '$CRC_ARG_expected_number_of_warnings'`) {
--echo Failure! Expected $CRC_ARG_expected_number_of_warnings warnings, got $n_warnings warnings.
SHOW WARNINGS;
SHOW BINLOG EVENTS;
--exit
}
# These queries are run without query log, to make result file more
# readable. Debug info is only printed if something abnormal
# happens.
--disable_query_log
--echo * SQL_LOG_BIN = 0: expect nothing logged and no warning.
SET SQL_LOG_BIN = 0;
RESET MASTER;
--eval $CRC_RET_stmt_sidef
--let $n_warnings= `SHOW COUNT(*) WARNINGS`
if (`SELECT '$n_warnings' != '0'`) {
--echo Failure! Expected 0 warnings, got $n_warnings warnings.
SHOW WARNINGS;
SHOW BINLOG EVENTS;
--exit
}
--let $binlog_event= query_get_value(SHOW BINLOG EVENTS, Event_type, 2)
if (`SELECT '$binlog_event' != 'No such row'`) {
--enable_query_log
--echo Failure! Something was written to the binlog despite SQL_LOG_BIN=0:
SHOW BINLOG EVENTS;
--exit
}
SET SQL_LOG_BIN = 1;
--echo * binlog_format = MIXED: expect row events in binlog and no warning.
SET binlog_format = MIXED;
RESET MASTER;
--eval $CRC_RET_stmt_sidef
--let $n_warnings= `SHOW COUNT(*) WARNINGS`
if (`SELECT '$n_warnings' != '0'`) {
--echo Failure! Expected 0 warnings, got $n_warnings warnings.
SHOW WARNINGS;
SHOW BINLOG EVENTS;
--exit
}
# The first event is format_description, the second is
# Query_event('BEGIN'), and the third should be our Table_map.
--let $event_type= query_get_value(SHOW BINLOG EVENTS, Event_type, 3)
if (`SELECT '$event_type' != 'Table_map'`) {
--enable_query_log
--echo Failure! Event number 3 was a '$event_type', not a 'Table_map'.
# Currently, there is a bug causing some statements to be logged
# partially in statement format. Hence, we don't fail here, we
# just print the events (masking out nondeterministic components
# of the output) and continue. When binloggging works perfectly,
# we should instead execute:
#--enable_query_log
#SHOW BINLOG EVENTS;
#--exit
# Here, we should really source
# include/show_binlog_events.inc. But due to BUG#41913, that
# doesn't work, and we have to inline the entire file here. Sigh
# :-(
--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR 106 <binlog_start>
--replace_column 2 # 4 # 5 #
--replace_regex /\/\* xid=.* \*\//\/* XID *\// /table_id: [0-9]+/table_id: #/ /file_id=[0-9]+/file_id=#/ /block_len=[0-9]+/block_len=#/
--eval SHOW BINLOG EVENTS FROM 106
--disable_query_log
}
SET binlog_format = STATEMENT;
--enable_query_log
}
# Invoke created object, discarding the return value. This should not
# give any warning.
if (`SELECT '$CRC_RET_sel_retval' != ''`) {
--echo * Invoke statement so that return value is dicarded: expect no warning.
--disable_result_log
--eval $CRC_RET_sel_retval
--enable_result_log
# Currently, due to a bug, we do get warnings here, so we don't
# fail. When the bug is fixed, we should execute the following.
#--let $n_warnings= `SHOW COUNT(*) WARNINGS`
#if (`SELECT '$n_warnings' != '0'`) {
# --enable_query_log
# --echo Failure! Expected 0 warnings, got $n_warnings warnings.
# SHOW WARNINGS;
# SHOW BINLOG EVENTS;
# --exit
#}
}
#--echo debug: <<<<EXIT create_recursive_construct
#--echo debug: stmt_sidef=$CRC_RET_stmt_sidef
#--echo debug: value=$CRC_RET_value
#--echo debug: sel_retval=$CRC_RET_sel_retval
#--echo debug: sel_sidef=$CRC_RET_sel_sidef
#--echo debug: drop=$CRC_RET_drop
#--echo debug: is_toplevel=$CRC_RET_is_toplevel
#--echo debug: desc=$CRC_RET_desc

View file

@ -47,7 +47,6 @@ insert into t1 set b=1;
insert into t2 set a=1, b=1;
set foreign_key_checks=0;
set @@session.binlog_format=row;
delete from t1;
--echo must sync w/o a problem (could not with the buggy code)

View file

@ -38,14 +38,14 @@ connection master;
truncate table t1;
# first scenario: duplicate on first row
insert delayed into t1 values(10, "my name");
if ($binlog_format_statement)
if (`SELECT @@global.binlog_format = 'STATEMENT'`)
{
# statement below will be converted to non-delayed INSERT and so
# will stop at first error, guaranteeing replication.
--error ER_DUP_ENTRY
insert delayed into t1 values(10, "is Bond"), (20, "James Bond");
}
if (!$binlog_format_statement)
if (`SELECT @@global.binlog_format != 'STATEMENT'`)
{
insert delayed into t1 values(10, "is Bond"), (20, "James Bond");
}
@ -59,7 +59,7 @@ select * from t1;
# second scenario: duplicate on second row
connection master;
delete from t1 where id!=10;
if ($binlog_format_statement)
if (`SELECT @@global.binlog_format = 'STATEMENT'`)
{
# statement below will be converted to non-delayed INSERT and so
# will be binlogged with its ER_DUP_ENTRY error code, guaranteeing
@ -67,7 +67,7 @@ if ($binlog_format_statement)
--error ER_DUP_ENTRY
insert delayed into t1 values(20, "is Bond"), (10, "James Bond");
}
if (!$binlog_format_statement)
if (`SELECT @@global.binlog_format != 'STATEMENT'`)
{
insert delayed into t1 values(20, "is Bond"), (10, "James Bond");
}
@ -108,6 +108,7 @@ if (`SELECT @@global.binlog_format != 'ROW'`)
{
#must show two INSERT DELAYED
--replace_column 1 x 2 x 3 x 4 x 5 x
--replace_regex /table_id: [0-9]+/table_id: #/
show binlog events in 'master-bin.000002' LIMIT 2,2;
}
select * from t1;
@ -118,6 +119,7 @@ if (`SELECT @@global.binlog_format != 'ROW'`)
{
#must show two INSERT DELAYED
--replace_column 1 x 2 x 3 x 4 x 5 x
--replace_regex /table_id: [0-9]+/table_id: #/
show binlog events in 'slave-bin.000002' LIMIT 2,2;
}
select * from t1;

View file

@ -141,7 +141,9 @@ let $run= 5;
while ($run)
{
START TRANSACTION;
--disable_warnings
--eval CALL tpcb.trans($rpl_format);
--enable_warnings
eval SET @my_errno= $mysql_errno;
let $run_good= `SELECT @my_errno = 0`;
let $run_bad= `SELECT @my_errno <> 0`;
@ -190,7 +192,9 @@ let $run= 5;
while ($run)
{
START TRANSACTION;
--disable_warnings
--eval CALL tpcb.trans($rpl_format);
--enable_warnings
eval SET @my_errno= $mysql_errno;
let $run_good= `SELECT @my_errno = 0`;
let $run_bad= `SELECT @my_errno <> 0`;
@ -240,7 +244,9 @@ let $run= 5;
while ($run)
{
START TRANSACTION;
--disable_warnings
--eval CALL tpcb.trans($rpl_format);
--enable_warnings
eval SET @my_errno= $mysql_errno;
let $run_good= `SELECT @my_errno = 0`;
let $run_bad= `SELECT @my_errno <> 0`;

View file

@ -1,16 +1,21 @@
#
# Check if server has support for loading udf's
# i.e it will support dlopen
# Check if server has support for loading plugins
#
--require r/have_dynamic_loading.require
disable_query_log;
show variables like 'have_dynamic_loading';
enable_query_log;
if (`SELECT @@have_dynamic_loading != 'YES'`) {
--skip Example plugin requires dynamic loading
}
#
# Check if the variable EXAMPLE_PLUGIN is set
#
--require r/have_example_plugin.require
disable_query_log;
eval select LENGTH('$EXAMPLE_PLUGIN') > 0 as 'have_example_plugin';
if (`SELECT LENGTH('$EXAMPLE_PLUGIN') = 0`) {
--skip Example plugin requires the environment variable \$EXAMPLE_PLUGIN to be set (normally done by mtr)
}
#
# Check if --plugin-dir was setup for exampledb
#
if (`SELECT CONCAT('--plugin-dir=', @@plugin_dir) != '$EXAMPLE_PLUGIN_OPT'`) {
--skip Example plugin requires that --plugin-dir is set to the example plugin dir (either the .opt file does not contain \$EXAMPLE_PLUGIN_OPT or another plugin is in use)
}
enable_query_log;

View file

@ -1,16 +1,20 @@
#
# Check if server has support for loading udf's
# i.e it will support dlopen
# Check if server has support for loading plugins
#
--require r/have_dynamic_loading.require
disable_query_log;
show variables like 'have_dynamic_loading';
enable_query_log;
if (`SELECT @@have_dynamic_loading != 'YES'`) {
--skip simple parser requires dynamic loading
}
#
# Check if the variable SIMPLE_PARSER is set
#
--require r/have_simple_parser.require
disable_query_log;
eval select LENGTH('$SIMPLE_PARSER') > 0 as 'have_simple_parser';
enable_query_log;
if (`SELECT LENGTH('$SIMPLE_PARSER') = 0`) {
--skip simple parser requires the environment variable \$SIMPLE_PARSER to be set (normally done by mtr)
}
#
# Check if --plugin-dir was setup for simple parser
#
if (`SELECT CONCAT('--plugin-dir=', @@plugin_dir) != '$SIMPLE_PARSER_OPT'`) {
--skip simple parser requires that --plugin-dir is set to the udf plugin dir (either the .opt file does not contain \$UDF_EXAMPLE_LIB_OPT or another plugin is in use)
}

View file

@ -1,16 +1,20 @@
#
# Check if server has support for loading udf's
# i.e it will support dlopen
# Check if server has support for loading plugins
#
--require r/have_dynamic_loading.require
disable_query_log;
show variables like 'have_dynamic_loading';
enable_query_log;
if (`SELECT @@have_dynamic_loading != 'YES'`) {
--skip UDF requires dynamic loading
}
#
# Check if the variable UDF_EXAMPLE_LIB is set
#
--require r/have_udf_example.require
disable_query_log;
eval select LENGTH('$UDF_EXAMPLE_LIB') > 0 as 'have_udf_example_lib';
enable_query_log;
if (`SELECT LENGTH('$UDF_EXAMPLE_LIB') = 0`) {
--skip UDF requires the environment variable \$UDF_EXAMPLE_LIB to be set (normally done by mtr)
}
#
# Check if --plugin-dir was setup for udf
#
if (`SELECT CONCAT('--plugin-dir=', @@plugin_dir) != '$UDF_EXAMPLE_LIB_OPT'`) {
--skip UDF requires that --plugin-dir is set to the udf plugin dir (either the .opt file does not contain \$UDF_EXAMPLE_LIB_OPT or another plugin is in use)
}

View file

@ -55,11 +55,13 @@ connection master;
--echo "Running on the master"
--enable_info
eval CREATE TABLE t1(sum INT, price FLOAT(24)) ENGINE=$engine_type;
--disable_warnings
INSERT INTO t1 VALUES(myfunc_int(100), myfunc_double(50.00));
INSERT INTO t1 VALUES(myfunc_int(10), myfunc_double(5.00));
INSERT INTO t1 VALUES(myfunc_int(200), myfunc_double(25.00));
INSERT INTO t1 VALUES(myfunc_int(1), myfunc_double(500.00));
SELECT * FROM t1 ORDER BY sum;
--enable_warnings
--disable_info
sync_slave_with_master;

View file

@ -1,2 +0,0 @@
Variable_name Value
have_dynamic_loading YES

View file

@ -1,2 +0,0 @@
have_example_plugin
1

View file

@ -1,2 +0,0 @@
have_simple_parser
1

View file

@ -1,2 +0,0 @@
have_udf_example_lib
1

View file

@ -42,7 +42,7 @@ id
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
BEGIN;
INSERT INTO t1 VALUES(9);
ERROR HY000: Binary logging not possible. Message: Transaction level 'READ-COMMITTED' in InnoDB is not safe for binlog mode 'STATEMENT'
ERROR HY000: Cannot execute statement: binlogging impossible since BINLOG_FORMAT = STATEMENT and at least one table uses a storage engine limited to row-logging. InnoDB is limited to row-logging when transaction isolation level is READ COMMITTED or READ UNCOMMITTED.
COMMIT;
COMMIT;
DROP TABLE t1;

View file

@ -506,6 +506,8 @@ select count(*)*255 from t3 into table_size;
until table_size > max_table_size*2 end repeat;
end|
call bug14210_fill_table()|
Warnings:
Note 1592 Unsafe statement binlogged in statement format since BINLOG_FORMAT = STATEMENT. Reason: Statement uses a system variable whose value may differ on slave.
drop procedure bug14210_fill_table|
create table t4 like t3|
create procedure bug14210()

View file

@ -14,12 +14,12 @@ SET BINLOG_FORMAT=STATEMENT;
BEGIN;
SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
UPDATE t1 SET b = 1*a WHERE a > 1;
ERROR HY000: Binary logging not possible. Message: Transaction level 'READ-UNCOMMITTED' in InnoDB is not safe for binlog mode 'STATEMENT'
ERROR HY000: Cannot execute statement: binlogging impossible since BINLOG_FORMAT = STATEMENT and at least one table uses a storage engine limited to row-logging. InnoDB is limited to row-logging when transaction isolation level is READ COMMITTED or READ UNCOMMITTED.
COMMIT;
BEGIN;
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
UPDATE t1 SET b = 2*a WHERE a > 2;
ERROR HY000: Binary logging not possible. Message: Transaction level 'READ-COMMITTED' in InnoDB is not safe for binlog mode 'STATEMENT'
ERROR HY000: Cannot execute statement: binlogging impossible since BINLOG_FORMAT = STATEMENT and at least one table uses a storage engine limited to row-logging. InnoDB is limited to row-logging when transaction isolation level is READ COMMITTED or READ UNCOMMITTED.
COMMIT;
BEGIN;
SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;

View file

@ -42,7 +42,7 @@ INSERT INTO t1m VALUES (1,1), (1,2), (2,1), (2,2);
INSERT INTO t1n VALUES (1,1), (1,2), (2,1), (2,2);
UPDATE t1m, t1b SET m = 2, b = 3 WHERE n = c;
UPDATE t1m, t1n SET m = 2, e = 3 WHERE n = f;
ERROR HY000: Binary logging not possible. Message: Statement cannot be written atomically since more than one engine involved and at least one engine is self-logging
ERROR HY000: Cannot execute statement: binlogging impossible since more than one engine is involved and at least one engine is self-logging.
TRUNCATE t1m;
TRUNCATE t1b;
TRUNCATE t1n;
@ -68,9 +68,9 @@ INSERT INTO t1m VALUES (1,1), (1,2), (2,1), (2,2);
INSERT INTO t1b VALUES (1,1), (1,2), (2,1), (2,2);
INSERT INTO t1n VALUES (1,1), (1,2), (2,1), (2,2);
UPDATE t1m, t1n SET m = 2, e = 3 WHERE n = f;
ERROR HY000: Binary logging not possible. Message: Statement cannot be written atomically since more than one engine involved and at least one engine is self-logging
ERROR HY000: Cannot execute statement: binlogging impossible since more than one engine is involved and at least one engine is self-logging.
UPDATE t1n, t1b SET e = 2, b = 3 WHERE f = c;
ERROR HY000: Binary logging not possible. Message: Statement cannot be written atomically since more than one engine involved and at least one engine is self-logging
ERROR HY000: Cannot execute statement: binlogging impossible since more than one engine is involved and at least one engine is self-logging.
show binlog events from <binlog_start>;
Log_name Pos Event_type Server_id End_log_pos Info
mysqld-bin.000001 # Query # # BEGIN

View file

@ -12,7 +12,11 @@ master-bin.000001 # Query # # use `test`; insert delayed into t1 values (null)
master-bin.000001 # Query # # use `test`; insert delayed into t1 values (300)
master-bin.000001 # Query # # use `test`; FLUSH TABLES
insert delayed into t1 values (null),(null),(null),(null);
Warnings:
Note 1592 Unsafe statement binlogged in statement format since BINLOG_FORMAT = STATEMENT. Reason: Statement uses INSERT DELAYED. This is unsafe because the time when rows are inserted cannot be predicted.
insert delayed into t1 values (null),(null),(400),(null);
Warnings:
Note 1592 Unsafe statement binlogged in statement format since BINLOG_FORMAT = STATEMENT. Reason: Statement uses INSERT DELAYED. This is unsafe because the time when rows are inserted cannot be predicted.
select * from t1;
a
207

View file

@ -11,7 +11,7 @@ prepare s from "insert into t1 select 100 limit ?";
set @a=100;
execute s using @a;
Warnings:
Note 1592 Statement may not be safe to log in statement format.
Note 1592 Unsafe statement binlogged in statement format since BINLOG_FORMAT = STATEMENT. Reason: Statement uses a LIMIT clause. This is unsafe because the set of rows included cannot be predicted.
show binlog events from <binlog_start>;
Log_name Pos Event_type Server_id End_log_pos Info
master-bin.000001 # Query # # use `test`; create table t1 (a int)

View file

@ -4,10 +4,10 @@ CREATE TABLE t1 (a int, b int, primary key (a));
INSERT INTO t1 VALUES (1,2), (2,3);
UPDATE t1 SET b='4' WHERE a=1 LIMIT 1;
Warnings:
Note 1592 Statement may not be safe to log in statement format.
Note 1592 Unsafe statement binlogged in statement format since BINLOG_FORMAT = STATEMENT. Reason: Statement uses a LIMIT clause. This is unsafe because the set of rows included cannot be predicted.
UPDATE t1 SET b='5' WHERE a=2 ORDER BY a LIMIT 1;
Warnings:
Note 1592 Statement may not be safe to log in statement format.
Note 1592 Unsafe statement binlogged in statement format since BINLOG_FORMAT = STATEMENT. Reason: Statement uses a LIMIT clause. This is unsafe because the set of rows included cannot be predicted.
DROP TABLE t1;
### NOT filtered database => assertion: binlog disabled and warnings ARE NOT shown
SET SQL_LOG_BIN= 0;
@ -38,11 +38,11 @@ CREATE TABLE t1 (a VARCHAR(36), b VARCHAR(10));
SET GLOBAL LOG_WARNINGS = 0;
INSERT INTO t1 VALUES(UUID(), 'Bug#46265');
Warnings:
Note 1592 Statement may not be safe to log in statement format.
Note 1592 Unsafe statement binlogged in statement format since BINLOG_FORMAT = STATEMENT. Reason: Statement uses a system function whose value may differ on slave.
SET GLOBAL LOG_WARNINGS = 1;
INSERT INTO t1 VALUES(UUID(), 'Bug#46265');
Warnings:
Note 1592 Statement may not be safe to log in statement format.
Note 1592 Unsafe statement binlogged in statement format since BINLOG_FORMAT = STATEMENT. Reason: Statement uses a system function whose value may differ on slave.
DROP TABLE t1;
SET GLOBAL log_warnings = @old_log_warnings;
# Count the number of times the "Unsafe" message was printed

File diff suppressed because it is too large Load diff

View file

@ -27,13 +27,13 @@ SET BINLOG_FORMAT=STATEMENT;
BEGIN;
SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
error ER_BINLOG_LOGGING_IMPOSSIBLE;
error ER_BINLOG_STMT_MODE_AND_ROW_ENGINE;
UPDATE t1 SET b = 1*a WHERE a > 1;
COMMIT;
BEGIN;
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
error ER_BINLOG_LOGGING_IMPOSSIBLE;
error ER_BINLOG_STMT_MODE_AND_ROW_ENGINE;
UPDATE t1 SET b = 2*a WHERE a > 2;
COMMIT;

View file

@ -60,7 +60,7 @@ let $wait_binlog_event= COMMIT;
source include/wait_for_binlog_event.inc;
UPDATE t1m, t1b SET m = 2, b = 3 WHERE n = c;
error ER_BINLOG_LOGGING_IMPOSSIBLE;
error ER_BINLOG_MULTIPLE_ENGINES_AND_SELF_LOGGING_ENGINE;
UPDATE t1m, t1n SET m = 2, e = 3 WHERE n = f;
# Not possible to test this since NDB writes its own binlog, which
@ -84,7 +84,7 @@ INSERT INTO t1m VALUES (1,1), (1,2), (2,1), (2,2);
INSERT INTO t1b VALUES (1,1), (1,2), (2,1), (2,2);
INSERT INTO t1n VALUES (1,1), (1,2), (2,1), (2,2);
error ER_BINLOG_LOGGING_IMPOSSIBLE;
error ER_BINLOG_MULTIPLE_ENGINES_AND_SELF_LOGGING_ENGINE;
UPDATE t1m, t1n SET m = 2, e = 3 WHERE n = f;
# Not possible to test this since NDB writes its own binlog, which
@ -93,7 +93,7 @@ UPDATE t1m, t1n SET m = 2, e = 3 WHERE n = f;
#UPDATE t1m, t1n SET m = 2, e = 3 WHERE n = f;
error ER_BINLOG_LOGGING_IMPOSSIBLE;
error ER_BINLOG_MULTIPLE_ENGINES_AND_SELF_LOGGING_ENGINE;
UPDATE t1n, t1b SET e = 2, b = 3 WHERE f = c;
source include/show_binlog_events.inc;

View file

@ -0,0 +1 @@
$UDF_EXAMPLE_LIB_OPT

View file

@ -1,34 +1,61 @@
# ==== Background ====
#
# Some statements may execute differently on master and slave when
# logged in statement format. Such statements are called unsafe.
# Unsafe statements include:
#
# - statements using @@variables (with a small number of exceptions;
# see below);
# - statements using certain functions, e.g., UUID();
# - statements using LIMIT;
# - INSERT DELAYED;
# - insert into two autoinc columns;
# - statements using UDF's.
# - statements reading from log tables in the mysql database.
#
# Note that statements that use stored functions, stored procedures,
# triggers, views, or prepared statements that invoke unsafe
# statements shall also be unsafe.
#
# Unsafeness of a statement shall have the following consequences:
#
# 1. If the binlogging is on and the unsafe statement is logged:
# - If binlog_format=STATEMENT, the statement shall give a warning.
# - If binlog_format=MIXED or binlog_format=ROW, the statement shall
# be logged in row format.
#
# 2. If binlogging is off or the statement is not logged (e.g. SELECT
# UUID()), no warning shall be issued and the statement shall not
# be logged.
#
# Moreover, when a sub-statement of a recursive construct (i.e.,
# stored function, stored procedure, trigger, view, or prepared
# statement) is unsafe and binlog_format=STATEMENT, then a warning
# shall be issued for every recursive construct. In effect, this
# creates a stack trace from the top-level statement to the unsafe
# statement.
#
#
# ==== Purpose ====
#
# Some statements can not be written to the binlog in a safe manner
# with statement-based replication, either because they rely on
# features that are local to the server they are replicated from
# (e.g., @@variables), or because they include nondeterministic
# queries (e.g., LIMIT), or because the time at which the query is
# executed cannot be determined (e.g., INSERT DELAYED). Such
# statements should be marked unsafe. All unsafe statements should
# give a warning.
# Yet the warning/error message isn't issued when SQL_LOG_BIN is turned off.
# This test verifies that a warning is generated when it should,
# according to the rules above.
#
# This test verifies that a warning is generated for statements that
# should be unsafe, when they are executed under statement mode
# logging.
#
# All variables should be unsafe, with some exceptions. Therefore,
# this test also verifies that the exceptions do *not* generare a
# All @@variables should be unsafe, with some exceptions. Therefore,
# this test also verifies that the exceptions do *not* generate a
# warning.
#
#
# ==== Method ====
#
# We try an INSERT DELAYED statement and verify that a warning is
# issued.
# 1. Each type of statements listed above is executed.
#
# We try to insert unsafe variables into a table in several ways:
# directly with an INSERT statement, from a stored procedure, from a
# stored function, from a trigger, from a prepared statement, and from
# a complicated nesting of triggers, functions, procedures, and
# prepared statements. In all cases, a warning should be issued.
# 2. Each unsafe statement is wrapped in each type of recursive
# construct (stored function, stored procedure, trigger, view, or
# prepared statement).
#
# 3. Each unsafe statement is wrapped in two levels of recursive
# constructs (function invoking trigger invoking UUID(), etc).
#
# We try to insert the variables that should not be unsafe into a
# table, and verify that *no* warning is issued.
@ -38,7 +65,8 @@
# Execute a unsafe statement calling a trigger or stored function
# or neither when @@SQL_LOG_BIN is turned OFF,
# no warning/error is issued
#
#
# ==== Related bugs and worklogs ====
#
# WL#3339: Issue warnings when statement-based replication may fail
@ -47,6 +75,9 @@
# BUG#34768: nondeterministic INSERT using LIMIT logged in stmt mode if binlog_format=mixed
# BUG#41980, SBL, INSERT .. SELECT .. LIMIT = ERROR, even when @@SQL_LOG_BIN is 0
# BUG#42640: mysqld crashes when unsafe statements are executed (STRICT_TRANS_TABLES mode)
# BUG#45825: INSERT DELAYED is not unsafe: logged in statement format
# BUG#45785: LIMIT in SP does not cause RBL if binlog_format=MIXED
#
#
# ==== Related test cases ====
#
@ -57,192 +88,311 @@
# rpl.rpl_variables_stm tests the small subset of variables that
# actually can be replicated safely in statement mode.
#
#
# ==== Todo ====
#
# There are several other ways to create unsafe statements: see, e.g.,
# WL#3339, BUG#34768.
# rpl_ndb.rpl_ndb_binlog_format_errors tests all errors and warnings
# related to logging format (not just 'Unsafe statement binlogged in
# statement mode since BINLOG_FORMAT = STATEMENT').
source include/have_log_bin.inc;
source include/have_binlog_format_statement.inc;
--source include/have_udf.inc
--source include/have_log_bin.inc
--source include/have_binlog_format_statement.inc
--echo ==== Setup tables ====
--echo #### Setup tables ####
CREATE TABLE t1 (a INT);
CREATE TABLE t2 (a CHAR(40));
CREATE TABLE t3 (a INT AUTO_INCREMENT PRIMARY KEY);
CREATE TABLE trigger_table (a CHAR(7));
CREATE TABLE trigger_table2 (a INT);
CREATE TABLE t0 (a CHAR(100));
CREATE TABLE t1 (a CHAR(100));
CREATE TABLE t2 (a CHAR(100));
CREATE TABLE t3 (a CHAR(100));
CREATE TABLE ta0 (a CHAR(100));
CREATE TABLE ta1 (a CHAR(100));
CREATE TABLE ta2 (a CHAR(100));
CREATE TABLE ta3 (a CHAR(100));
CREATE TABLE autoinc_table (a INT PRIMARY KEY AUTO_INCREMENT);
CREATE TABLE data_table (a CHAR(100));
INSERT INTO data_table VALUES ('foo');
CREATE TABLE trigger_table_1 (a INT);
CREATE TABLE trigger_table_2 (a INT);
CREATE TABLE trigger_table_3 (a INT);
CREATE TABLE double_autoinc_table (a INT PRIMARY KEY AUTO_INCREMENT);
--echo ==== Non-deterministic statements ====
INSERT DELAYED INTO t1 VALUES (5);
--echo ==== Some variables that *should* be unsafe ====
--echo ---- Insert directly ----
INSERT INTO t1 VALUES (@@global.sync_binlog);
INSERT INTO t1 VALUES (@@session.insert_id);
INSERT INTO t1 VALUES (@@global.auto_increment_increment);
INSERT INTO t2 SELECT UUID();
INSERT INTO t2 VALUES (@@session.sql_mode);
INSERT INTO t2 VALUES (@@global.init_slave);
INSERT INTO t2 VALUES (@@hostname);
--echo ---- Insert from stored procedure ----
DELIMITER |;
CREATE PROCEDURE proc()
--DELIMITER |
CREATE TRIGGER double_autoinc_trig
BEFORE INSERT ON double_autoinc_table FOR EACH ROW
BEGIN
INSERT INTO t1 VALUES (@@global.sync_binlog);
INSERT INTO t1 VALUES (@@session.insert_id);
INSERT INTO t1 VALUES (@@global.auto_increment_increment);
INSERT INTO t2 SELECT UUID();
INSERT INTO t2 VALUES (@@session.sql_mode);
INSERT INTO t2 VALUES (@@global.init_slave);
INSERT INTO t2 VALUES (@@hostname);
END|
DELIMITER ;|
CALL proc();
--echo ---- Insert from stored function ----
DELIMITER |;
CREATE FUNCTION func()
RETURNS INT
BEGIN
INSERT INTO t1 VALUES (@@global.sync_binlog);
INSERT INTO t1 VALUES (@@session.insert_id);
INSERT INTO t1 VALUES (@@global.auto_increment_increment);
INSERT INTO t2 SELECT UUID();
INSERT INTO t2 VALUES (@@session.sql_mode);
INSERT INTO t2 VALUES (@@global.init_slave);
INSERT INTO t2 VALUES (@@hostname);
RETURN 0;
END|
DELIMITER ;|
SELECT func();
--echo ---- Insert from trigger ----
DELIMITER |;
CREATE TRIGGER trig
BEFORE INSERT ON trigger_table
FOR EACH ROW
BEGIN
INSERT INTO t1 VALUES (@@global.sync_binlog);
INSERT INTO t1 VALUES (@@session.insert_id);
INSERT INTO t1 VALUES (@@global.auto_increment_increment);
INSERT INTO t2 SELECT UUID();
INSERT INTO t2 VALUES (@@session.sql_mode);
INSERT INTO t2 VALUES (@@global.init_slave);
INSERT INTO t2 VALUES (@@hostname);
END|
DELIMITER ;|
INSERT INTO trigger_table VALUES ('bye.');
--echo ---- Insert from prepared statement ----
PREPARE p1 FROM 'INSERT INTO t1 VALUES (@@global.sync_binlog)';
PREPARE p2 FROM 'INSERT INTO t1 VALUES (@@session.insert_id)';
PREPARE p3 FROM 'INSERT INTO t1 VALUES (@@global.auto_increment_increment)';
PREPARE p4 FROM 'INSERT INTO t2 SELECT UUID()';
PREPARE p5 FROM 'INSERT INTO t2 VALUES (@@session.sql_mode)';
PREPARE p6 FROM 'INSERT INTO t2 VALUES (@@global.init_slave)';
PREPARE p7 FROM 'INSERT INTO t2 VALUES (@@hostname)';
EXECUTE p1; EXECUTE p2; EXECUTE p3; EXECUTE p4; EXECUTE p5;
EXECUTE p6; EXECUTE p7;
--echo ---- Insert from nested call of triggers / functions / procedures ----
DELIMITER |;
# proc1: cause trigger 'trig' above to be triggered.
CREATE PROCEDURE proc1()
INSERT INTO trigger_table VALUES ('ha!')|
# func2: call proc1 above.
CREATE FUNCTION func2()
RETURNS INT
BEGIN
CALL proc1();
RETURN 0;
INSERT INTO autoinc_table VALUES (NULL);
END|
# trig3: call func2 above
CREATE TRIGGER trig3
BEFORE INSERT ON trigger_table2
FOR EACH ROW
CREATE FUNCTION multi_unsafe_func() RETURNS INT
BEGIN
DECLARE tmp INT;
SELECT func2() INTO tmp;
INSERT INTO t0 VALUES(CONCAT(@@hostname, @@hostname));
INSERT INTO t0 VALUES(0);
INSERT INTO t0 VALUES(CONCAT(UUID(), @@hostname));
RETURN 1;
END|
--DELIMITER ;
# proc4: cause trig3 above to be triggered.
CREATE PROCEDURE proc4()
INSERT INTO trigger_table2 VALUES (1)|
--replace_result $UDF_EXAMPLE_LIB UDF_EXAMPLE_LIB
--eval CREATE FUNCTION myfunc_int RETURNS INTEGER SONAME "$UDF_EXAMPLE_LIB"
# func5: call proc4 above.
CREATE FUNCTION func5()
RETURNS INT
BEGIN
CALL proc4;
RETURN 0;
END|
# In each iteration of this loop, we select one method to make the
# statement unsafe.
--let $unsafe_type= 0
while (`SELECT $unsafe_type < 9`) {
# prep6: call func5() above.
PREPARE prep6 FROM 'SELECT func5()'|
--echo
DELIMITER ;|
if (`SELECT $unsafe_type = 0`) {
--echo ==== Testing UUID() unsafeness ====
--let $desc_0= unsafe UUID() function
--let $stmt_sidef_0= INSERT INTO t0 VALUES (UUID())
--let $value_0= UUID()
--let $sel_sidef_0=
--let $sel_retval_0= SELECT UUID()
--let $CRC_ARG_expected_number_of_warnings= 1
}
# try a complicated call path to trigger 'trig'.
EXECUTE prep6;
if (`SELECT $unsafe_type = 1`) {
--echo ==== Testing @@hostname unsafeness ====
--let $desc_0= unsafe @@hostname variable
--let $stmt_sidef_0= INSERT INTO t0 VALUES (@@hostname)
--let $value_0= @@hostname
--let $sel_sidef_0=
# $sel_retval is going to be used in views. Views cannot execute
# statements that refer to @@variables. Hence, we set $set_retval
# to empty instead of SELECT @@hostname.
--let $sel_retval_0=
--let $CRC_ARG_expected_number_of_warnings= 1
}
if (`SELECT $unsafe_type = 2`) {
--echo ==== Testing SELECT...LIMIT unsafeness ====
--let $desc_0= unsafe SELECT...LIMIT statement
--let $stmt_sidef_0= INSERT INTO t0 SELECT * FROM data_table LIMIT 1
--let $value_0=
--let $sel_sidef_0=
--let $sel_retval_0= SELECT * FROM data_table LIMIT 1
--let $CRC_ARG_expected_number_of_warnings= 1
}
if (`SELECT $unsafe_type = 3`) {
--echo ==== Testing INSERT DELAYED unsafeness ====
--let $desc_0= unsafe INSERT DELAYED statement
--let $stmt_sidef_0= INSERT DELAYED INTO t0 VALUES (1), (2)
--let $value_0=
--let $sel_sidef_0=
--let $sel_retval_0=
--let $CRC_ARG_expected_number_of_warnings= 1
}
if (`SELECT $unsafe_type = 4`) {
--echo ==== Testing unsafeness of insert of two autoinc values ====
--let $desc_0= unsafe update of two autoinc columns
--let $stmt_sidef_0= INSERT INTO double_autoinc_table VALUES (NULL)
--let $value_0=
--let $sel_sidef_0=
--let $sel_retval_0=
# Note: we will expect 1 warning when BUG#45827 is fixed.
--let $CRC_ARG_expected_number_of_warnings= 0
}
if (`SELECT $unsafe_type = 5`) {
--echo ==== Testing unsafeness of UDF's ====
--let $desc_0= unsafe UDF
--let $stmt_sidef_0= INSERT INTO t0 VALUES (myfunc_int(10))
--let $value_0= myfunc_int(10)
--let $sel_sidef_0= SELECT myfunc_int(10)
--let $sel_retval_0=
--let $CRC_ARG_expected_number_of_warnings= 1
}
if (`SELECT $unsafe_type = 6`) {
--echo ==== Testing unsafeness of access to mysql.general_log ====
--let $desc_0= unsafe use of mysql.general_log
--let $stmt_sidef_0= INSERT INTO t0 SELECT COUNT(*) FROM mysql.general_log
--let $value_0=
--let $sel_sidef_0=
--let $sel_retval_0= SELECT COUNT(*) FROM mysql.general_log
--let $CRC_ARG_expected_number_of_warnings= 1
}
if (`SELECT $unsafe_type = 7`) {
--echo ==== Testing a statement that is unsafe in many ways ====
--let $desc_0= statement that is unsafe in many ways
# Concatenate three unsafe values, and then concatenate NULL to
# that so that the result is NULL and we instead use autoinc.
--let $stmt_sidef_0= INSERT DELAYED INTO double_autoinc_table SELECT CONCAT(UUID(), @@hostname, myfunc_int(), NULL) FROM mysql.general_log LIMIT 1
--let $value_0=
--let $sel_sidef_0=
--let $sel_retval_0=
# Note: we will expect 7 warnings when BUG#45827 is fixed.
--let $CRC_ARG_expected_number_of_warnings= 6
}
if (`SELECT $unsafe_type = 8`) {
--echo ==== Testing a statement that is unsafe several times ====
--let $desc_0= statement that is unsafe several times
--let $stmt_sidef_0= INSERT INTO ta0 VALUES (multi_unsafe_func())
--let $value_0=
--let $sel_sidef_0= SELECT multi_unsafe_func()
--let $sel_retval_0=
--let $CRC_ARG_expected_number_of_warnings= 2
}
# In each iteration of the following loop, we select one way to
# enclose the unsafe statement as a sub-statement of a recursive
# construct (i.e., a function, procedure, trigger, view, or prepared
# statement).
#
# In the last iteration, $call_type_1=7, we don't create a recursive
# construct. Instead, we just invoke the unsafe statement directly.
--let $call_type_1= 0
while (`SELECT $call_type_1 < 8`) {
#--echo debug: level 1, types $call_type_1 -> $unsafe_type
--let $CRC_ARG_level= 1
--let $CRC_ARG_type= $call_type_1
--let $CRC_ARG_stmt_sidef= $stmt_sidef_0
--let $CRC_ARG_value= $value_0
--let $CRC_ARG_sel_sidef= $sel_sidef_0
--let $CRC_ARG_sel_retval= $sel_retval_0
--let $CRC_ARG_desc= $desc_0
--source extra/rpl_tests/create_recursive_construct.inc
--let $stmt_sidef_1= $CRC_RET_stmt_sidef
--let $value_1= $CRC_RET_value
--let $sel_sidef_1= $CRC_RET_sel_sidef
--let $sel_retval_1= $CRC_RET_sel_retval
--let $is_toplevel_1= $CRC_RET_is_toplevel
--let $drop_1= $CRC_RET_drop
--let $desc_1= $CRC_RET_desc
# Some statements must be top-level statements, i.e., cannot be
# called as a sub-statement of any recursive construct. (One
# example is 'EXECUTE prepared_stmt'). When
# create_recursive_construct.inc creates a top-level statement, it
# sets $CRC_RET_is_toplevel=1.
if (!$is_toplevel_1) {
# In each iteration of this loop, we select one way to enclose
# the previous recursive construct in another recursive
# construct.
--let $call_type_2= 0
while (`SELECT $call_type_2 < 7`) {
#--echo debug: level 2, types $call_type_2 -> $call_type_1 -> $unsafe_type
--let $CRC_ARG_level= 2
--let $CRC_ARG_type= $call_type_2
--let $CRC_ARG_stmt_sidef= $stmt_sidef_1
--let $CRC_ARG_value= $value_1
--let $CRC_ARG_sel_sidef= $sel_sidef_1
--let $CRC_ARG_sel_retval= $sel_retval_1
--let $CRC_ARG_desc= $desc_1
--source extra/rpl_tests/create_recursive_construct.inc
--let $stmt_sidef_2= $CRC_RET_stmt_sidef
--let $value_2= $CRC_RET_value
--let $sel_sidef_2= $CRC_RET_sel_sidef
--let $sel_retval_2= $CRC_RET_sel_retval
--let $is_toplevel_2= $CRC_RET_is_toplevel
--let $drop_2= $CRC_RET_drop
--let $desc_2= $CRC_RET_desc
if (!$is_toplevel_2) {
# Conditioned out since it makes result file really big.
if (0) {
# In each iteration of this loop, we select one way to enclose
# the previous recursive construct in another recursive
# construct.
--let $call_type_3= 0
while (`SELECT $call_type_3 < 7`) {
#--echo debug: level 3, types $call_type_2 -> $call_type_2 -> $call_type_1 -> $unsafe_type
--let $CRC_ARG_level= 3
--let $CRC_ARG_type= $call_type_3
--let $CRC_ARG_stmt_sidef= $stmt_sidef_2
--let $CRC_ARG_value= $value_2
--let $CRC_ARG_sel_sidef= $sel_sidef_2
--let $CRC_ARG_sel_retval= $sel_retval_2
--let $CRC_ARG_desc= $desc_2
--source extra/rpl_tests/create_recursive_construct.inc
# Drop created object.
if (`SELECT '$drop_3' != ''`) {
--eval $drop_3
}
--inc $call_type_3
} # while (call_type_3)
} # if (0)
} # if (!is_toplevel_2)
# Drop created object.
if (`SELECT '$drop_2' != ''`) {
--eval $drop_2
}
--inc $call_type_2
} # while (call_type_2)
} # if (!is_toplevel_1)
# Drop created object.
if (`SELECT '$drop_1' != ''`) {
--eval $drop_1
}
--inc $call_type_1
} # while (call_type_1)
--inc $unsafe_type
} # while (unsafe_type)
DROP TRIGGER double_autoinc_trig;
DROP TABLE t0, t1, t2, t3, ta0, ta1, ta2, ta3,
autoinc_table, double_autoinc_table,
data_table,
trigger_table_1, trigger_table_2, trigger_table_3;
DROP FUNCTION myfunc_int;
DROP FUNCTION multi_unsafe_func;
--echo ==== Variables that should *not* be unsafe ====
--echo ==== Special system variables that should *not* be unsafe ====
CREATE TABLE t1 (a VARCHAR(1000));
CREATE TABLE autoinc_table (a INT PRIMARY KEY AUTO_INCREMENT);
INSERT INTO t1 VALUES (@@session.pseudo_thread_id);
INSERT INTO t1 VALUES (@@session.pseudo_thread_id);
INSERT INTO t1 VALUES (@@session.foreign_key_checks);
INSERT INTO t1 VALUES (@@session.sql_auto_is_null);
INSERT INTO t1 VALUES (@@session.unique_checks);
INSERT INTO t1 VALUES (@@session.auto_increment_increment);
INSERT INTO t1 VALUES (@@session.auto_increment_offset);
INSERT INTO t2 VALUES (@@session.character_set_client);
INSERT INTO t2 VALUES (@@session.collation_connection);
INSERT INTO t2 VALUES (@@session.collation_server);
INSERT INTO t2 VALUES (@@session.time_zone);
INSERT INTO t2 VALUES (@@session.lc_time_names);
INSERT INTO t2 VALUES (@@session.collation_database);
INSERT INTO t2 VALUES (@@session.timestamp);
INSERT INTO t2 VALUES (@@session.last_insert_id);
INSERT INTO t1 VALUES (@@session.character_set_client);
INSERT INTO t1 VALUES (@@session.character_set_connection);
INSERT INTO t1 VALUES (@@session.character_set_database);
INSERT INTO t1 VALUES (@@session.character_set_server);
INSERT INTO t1 VALUES (@@session.collation_connection);
INSERT INTO t1 VALUES (@@session.collation_database);
INSERT INTO t1 VALUES (@@session.collation_server);
INSERT INTO t1 VALUES (@@session.foreign_key_checks);
INSERT INTO t1 VALUES (@@session.identity);
INSERT INTO t1 VALUES (@@session.last_insert_id);
INSERT INTO t1 VALUES (@@session.lc_time_names);
INSERT INTO t1 VALUES (@@session.pseudo_thread_id);
INSERT INTO t1 VALUES (@@session.sql_auto_is_null);
INSERT INTO t1 VALUES (@@session.timestamp);
INSERT INTO t1 VALUES (@@session.time_zone);
INSERT INTO t1 VALUES (@@session.unique_checks);
SET @my_var= 4711;
INSERT INTO t1 VALUES (@my_var);
# using insert_id implicitly should be ok.
SET insert_id=12;
INSERT INTO t3 VALUES (NULL);
SET insert_id= 12;
INSERT INTO autoinc_table VALUES (NULL);
# See set_var.cc for explanation.
--echo The following variables *should* give a warning, despite they are replicated.
INSERT INTO t1 VALUES (@@session.sql_mode);
INSERT INTO t1 VALUES (@@session.insert_id);
--echo ==== Clean up ====
DROP TABLE t1, autoinc_table;
DROP PROCEDURE proc;
DROP FUNCTION func;
DROP TRIGGER trig;
DROP PROCEDURE proc1;
DROP FUNCTION func2;
DROP TRIGGER trig3;
DROP PROCEDURE proc4;
DROP FUNCTION func5;
DROP PREPARE prep6;
DROP TABLE t1, t2, t3, trigger_table, trigger_table2;
#
# BUG#34768 - nondeterministic INSERT using LIMIT logged in stmt mode if
# binlog_format=mixed
@ -388,4 +538,41 @@ DELETE FROM t1 LIMIT 1;
DROP TABLE t1, t2;
SET @@SESSION.SQL_MODE = @save_sql_mode;
#
# BUG#45825: INSERT DELAYED is not unsafe: logged in statement format
# BUG#45785: LIMIT in SP does not cause RBL if binlog_format=MIXED
#
SET @old_binlog_format = @@session.binlog_format;
SET binlog_format = MIXED;
CREATE TABLE t1 (a INT);
CREATE TABLE t2 (a INT);
INSERT INTO t2 VALUES (1), (2);
--DELIMITER |
CREATE PROCEDURE proc_insert_delayed ()
BEGIN
INSERT DELAYED INTO t1 VALUES (1), (2);
END|
CREATE FUNCTION func_limit ()
RETURNS INT
BEGIN
INSERT INTO t1 SELECT * FROM t2 LIMIT 1;
RETURN 1;
END|
--DELIMITER ;
RESET MASTER;
CALL proc_insert_delayed();
SELECT func_limit();
source include/show_binlog_events.inc;
SET @@session.binlog_format = @old_binlog_format;
DROP TABLE t1, t2;
DROP PROCEDURE proc_insert_delayed;
DROP FUNCTION func_limit;
--echo "End of tests"

View file

@ -11,6 +11,17 @@ SET SESSION binlog_format = 'ROW';
select @@global.binlog_format, @@session.binlog_format;
@@global.binlog_format ROW
@@session.binlog_format ROW
[on slave]
set @old_global_binlog_format= @@global.binlog_format;
set @old_session_binlog_format= @@session.binlog_format;
SET GLOBAL binlog_format = 'ROW';
SET SESSION binlog_format = 'ROW';
select @@global.binlog_format, @@session.binlog_format;
@@global.binlog_format ROW
@@session.binlog_format ROW
include/stop_slave.inc
include/start_slave.inc
[on master]
DROP TABLE IF EXISTS t1, t2, t3;
DROP PROCEDURE IF EXISTS p1;
DROP PROCEDURE IF EXISTS p2;
@ -189,3 +200,6 @@ DROP TABLE t1, t2, t3;
DROP PROCEDURE IF EXISTS p1;
DROP PROCEDURE IF EXISTS p2;
DROP PROCEDURE IF EXISTS p3;
[on slave]
set @@global.binlog_format= @old_global_binlog_format;
set @@session.binlog_format= @old_session_binlog_format;

View file

@ -11,6 +11,19 @@ set @old_session_binlog_format= @@session.binlog_format;
SET GLOBAL binlog_format = 'ROW';
SET SESSION binlog_format = 'ROW';
select @@global.binlog_format, @@session.binlog_format;
--echo [on slave]
connection slave;
set @old_global_binlog_format= @@global.binlog_format;
set @old_session_binlog_format= @@session.binlog_format;
SET GLOBAL binlog_format = 'ROW';
SET SESSION binlog_format = 'ROW';
select @@global.binlog_format, @@session.binlog_format;
# restart slave so that slave sql thread's binlog format is re-read
# from @@global.binlog_format
--source include/stop_slave.inc
--source include/start_slave.inc
--echo [on master]
connection master;
--disable_warnings
DROP TABLE IF EXISTS t1, t2, t3;
@ -158,8 +171,9 @@ DROP TABLE t1, t2, t3;
DROP PROCEDURE IF EXISTS p1;
DROP PROCEDURE IF EXISTS p2;
DROP PROCEDURE IF EXISTS p3;
save_master_pos;
connection slave;
sync_with_master;
--echo [on slave]
sync_slave_with_master;
set @@global.binlog_format= @old_global_binlog_format;
set @@session.binlog_format= @old_session_binlog_format;
# End of 5.1 tests

View file

@ -6,96 +6,6 @@ drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
start slave;
SET @old_event_scheduler = @@global.event_scheduler;
set global event_scheduler=1;
set binlog_format=row;
DROP EVENT IF EXISTS test.justonce;
drop table if exists t1,t2;
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`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
INSERT INTO t1 (id, c) VALUES (1, 'manually');
"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');
"Checking event is active on master"
SELECT db, name, status, originator FROM mysql.event WHERE db = 'test' AND name = 'justonce';
db name status originator
test justonce ENABLED 1
"Checking event data on the master"
ONE
1
"Checking event data on the slave"
ZERO
0
"Checking event is inactive on slave"
SELECT db, name, status, originator FROM mysql.event WHERE db = 'test' AND name = 'justonce';
db name status originator
test justonce SLAVESIDE_DISABLED 1
"Dropping event test.slave_once on the slave"
DROP EVENT IF EXISTS test.slave_once;
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');
"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';
db name status originator
test slave_once ENABLED 2
"Dropping event test.slave_once on the slave"
DROP EVENT IF EXISTS test.slave_once;
"Dropping event test.justonce on the master"
DROP EVENT IF EXISTS test.justonce;
"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');
"Checking event status on the master"
SELECT db, name, status, originator, body FROM mysql.event WHERE db = 'test' AND name = 'er';
db name status originator body
test er ENABLED 1 INSERT IGNORE INTO t1(id, c) VALUES (4, 'from er')
"Checking event status on the slave"
SELECT db, name, status, originator, body FROM mysql.event WHERE db = 'test' AND name = 'er';
db name status originator body
test er SLAVESIDE_DISABLED 1 INSERT IGNORE INTO t1(id, c) VALUES (4, 'from er')
"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');
"Checking event status on the master"
SELECT db, name, status, originator, body FROM mysql.event WHERE db = 'test' AND name = 'er';
db name status originator body
test er ENABLED 1 INSERT IGNORE INTO t1(id, c) VALUES (5, 'from alter er')
"Checking event status on the slave"
SELECT db, name, status, originator, body FROM mysql.event WHERE db = 'test' AND name = 'er';
db name status originator body
test er SLAVESIDE_DISABLED 1 INSERT IGNORE INTO t1(id, c) VALUES (5, 'from alter er')
"Dropping event test.er on the master"
DROP EVENT test.er;
"Checking event status on the master"
SELECT db, name, status, originator FROM mysql.event WHERE db = 'test';
db name status originator
"Checking event status on the slave"
SELECT db, name, status, originator FROM mysql.event WHERE db = 'test';
db name status originator
"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');
"Checking event status on the slave"
SELECT db, name, status, originator FROM mysql.event WHERE db = 'test' AND name = 'slave_terminate';
db name status originator
test slave_terminate ENABLED 2
"Dropping event test.slave_terminate on the slave"
DROP EVENT test.slave_terminate;
"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');
"Checking event status on the slave"
SELECT db, name, status, originator FROM mysql.event WHERE db = 'test' AND name = 'slave_terminate';
db name status originator
test slave_terminate SLAVESIDE_DISABLED 2
"Dropping event test.slave_terminate on the slave"
DROP EVENT test.slave_terminate;
"Cleanup"
DROP TABLE t1;
set binlog_format=statement;
DROP EVENT IF EXISTS test.justonce;
drop table if exists t1,t2;
CREATE TABLE `t1` (

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -46,7 +46,6 @@ engine = INNODB;
insert into t1 set b=1;
insert into t2 set a=1, b=1;
set foreign_key_checks=0;
set @@session.binlog_format=row;
delete from t1;
must sync w/o a problem (could not with the buggy code)
select count(*) from t1 /* must be zero */;

View file

@ -6,11 +6,12 @@ drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
start slave;
call mtr.add_suppression("Slave: Can\'t find record in \'t1\' Error_code: 1032");
call mtr.add_suppression("Slave: Cannot add or update a child row: a foreign key constraint fails .* Error_code: 1452");
SET @old_slave_exec_mode= @@global.slave_exec_mode;
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);
SET @old_slave_exec_mode= @@global.slave_exec_mode;
SET @@global.slave_exec_mode= IDEMPOTENT;
DELETE FROM t1 WHERE a = -2;
DELETE FROM t2 WHERE a = -2;
DELETE FROM t1 WHERE a = -2;
@ -72,158 +73,4 @@ a
Last_SQL_Error
0
DROP TABLE t1, t2;
select @@global.slave_exec_mode /* must be IDEMPOTENT */;
@@global.slave_exec_mode
IDEMPOTENT
create table ti1 (b int primary key) engine = innodb;
create table ti2 (a int primary key, b int, foreign key (b) references ti1(b))
engine = innodb;
set foreign_key_checks=1 /* ensure the check */;
insert into ti1 values (1),(2),(3);
insert into ti2 set a=2, b=2;
select * from ti1 order by b /* must be (1),(2),(3) */;
b
1
2
3
insert into ti2 set a=1, b=1;
select * from ti2 order by b /* must be (1,1) (2,2) */;
a b
1 1
2 2
set @save_binlog_format= @@session.binlog_format;
set @@session.binlog_format= row;
delete from ti1 where b=1;
select * from ti1 order by b /* must be (2),(3) */;
b
2
3
select * from ti1 order by b /* must stays as were on master (1),(2),(3) */;
b
1
2
3
delete from ti1 where b=3;
insert into ti2 set a=3, b=3;
select * from ti2 order by b /* must be (1,1),(2,2) - not inserted */;
a b
1 1
2 2
set global slave_exec_mode='IDEMPOTENT';
set global slave_exec_mode='STRICT';
set global slave_exec_mode='IDEMPOTENT,STRICT';
ERROR HY000: Ambiguous slave modes combination.
select @@global.slave_exec_mode /* must be STRICT */;
@@global.slave_exec_mode
STRICT
*** foreign keys errors as above now forces to stop
set foreign_key_checks=0;
drop table ti2, ti1;
create table ti1 (b int primary key) engine = innodb;
create table ti2 (a int primary key, b int, foreign key (b) references ti1(b))
engine = innodb;
set foreign_key_checks=1 /* ensure the check */;
insert into ti1 values (1),(2),(3);
insert into ti2 set a=2, b=2;
select * from ti1 order by b /* must be (1),(2),(3) */;
b
1
2
3
*** conspire future problem
insert into ti2 set a=1, b=1;
select * from ti2 order by b /* must be (1,1) (2,2) */;
a b
1 1
2 2
delete from ti1 where b=1 /* offending delete event */;
select * from ti1 order by b /* must be (2),(3) */;
b
2
3
*** slave must stop (Trying to delete a referenced foreing key)
Last_SQL_Error
1451
select * from ti1 order by b /* must be (1),(2),(3) - not deleted */;
b
1
2
3
set foreign_key_checks= 0;
delete from ti2 where b=1;
set foreign_key_checks= 1;
set global slave_exec_mode='IDEMPOTENT';
start slave sql_thread;
set global slave_exec_mode='STRICT';
*** conspire the following insert failure
*** conspire future problem
delete from ti1 where b=3;
insert into ti2 set a=3, b=3 /* offending write event */;
*** slave must stop (Trying to insert an invalid foreign key)
Last_SQL_Error
1452
select * from ti2 order by b /* must be (2,2) */;
a b
2 2
set foreign_key_checks= 0;
insert into ti1 set b=3;
set foreign_key_checks= 1;
set global slave_exec_mode='IDEMPOTENT';
start slave sql_thread;
set global slave_exec_mode='STRICT';
select * from ti2 order by b /* must be (2,2),(3,3) */;
a b
2 2
3 3
*** other errors
*** conspiring query
insert into ti1 set b=1;
insert into ti1 set b=1 /* offending write event */;
*** slave must stop (Trying to insert a dupliacte key)
Last_SQL_Error
1062
set foreign_key_checks= 0;
delete from ti1 where b=1;
set foreign_key_checks= 1;
set global slave_exec_mode='IDEMPOTENT';
start slave sql_thread;
set global slave_exec_mode='STRICT';
CREATE TABLE t1 (a INT PRIMARY KEY);
CREATE TABLE t2 (a INT);
INSERT INTO t1 VALUES (-1),(-2),(-3);
INSERT INTO t2 VALUES (-1),(-2),(-3);
DELETE FROM t1 WHERE a = -2;
DELETE FROM t2 WHERE a = -2;
DELETE FROM t1 WHERE a = -2;
*** slave must stop (Key was not found)
Last_SQL_Error
1032
set global slave_exec_mode='IDEMPOTENT';
start slave sql_thread;
set global slave_exec_mode='STRICT';
DELETE FROM t2 WHERE a = -2;
*** slave must stop (Key was not found)
Last_SQL_Error
1032
set global slave_exec_mode='IDEMPOTENT';
start slave sql_thread;
set global slave_exec_mode='STRICT';
UPDATE t1 SET a = 1 WHERE a = -1;
UPDATE t2 SET a = 1 WHERE a = -1;
UPDATE t1 SET a = 1 WHERE a = -1;
*** slave must stop (Key was not found)
Last_SQL_Error
1032
set global slave_exec_mode='IDEMPOTENT';
start slave sql_thread;
set global slave_exec_mode='STRICT';
UPDATE t2 SET a = 1 WHERE a = -1;
*** slave must stop (Key was not found)
Last_SQL_Error
1032
set global slave_exec_mode='IDEMPOTENT';
start slave sql_thread;
SET @@global.slave_exec_mode= @old_slave_exec_mode;
set @@session.binlog_format= @save_binlog_format;
drop table t1,t2,ti2,ti1;
*** end of tests

View file

@ -4,8 +4,7 @@ reset master;
reset slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
start slave;
==== 0. Setting it all up ====
SET BINLOG_FORMAT=STATEMENT;
==== Initialize ====
**** On Master ****
CREATE TABLE t1 (a INT);
CREATE TABLE logtbl (sect INT, test INT, count INT);
@ -16,106 +15,12 @@ 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;
#### 1. Using statement mode ####
==== 1.1. Simple test ====
SELECT SQL_CALC_FOUND_ROWS * FROM t1 WHERE a > 5 ORDER BY a LIMIT 1;
a
7
SELECT FOUND_ROWS() INTO @a;
INSERT INTO logtbl VALUES(1,1,@a);
SELECT SQL_CALC_FOUND_ROWS * FROM t1 WHERE a < 5 ORDER BY a LIMIT 1;
a
1
SELECT FOUND_ROWS() INTO @a;
INSERT INTO logtbl VALUES(1,2,@a);
SELECT * FROM logtbl WHERE sect = 1 ORDER BY sect,test;
sect test count
1 1 183
1 2 3
**** On Slave ****
SELECT * FROM logtbl WHERE sect = 1 ORDER BY sect,test;
sect test count
1 1 183
1 2 3
==== 1.2. Stored procedure ====
==== Checking a procedure ====
**** On Master ****
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 $$
CALL calc_and_log(2,1);
a
1
a
7
CREATE PROCEDURE just_log(sect INT, test INT, found_rows INT) BEGIN
INSERT INTO logtbl VALUES (sect,test,found_rows);
END $$
SELECT SQL_CALC_FOUND_ROWS * FROM t1 WHERE a > 5 ORDER BY a LIMIT 1;
a
7
SELECT FOUND_ROWS() INTO @found_rows;
CALL just_log(2,3,@found_rows);
SELECT * FROM logtbl WHERE sect = 2 ORDER BY sect,test;
sect test count
2 1 3
2 2 183
2 3 183
**** On Slave ****
SELECT * FROM logtbl WHERE sect = 2 ORDER BY sect,test;
sect test count
2 1 3
2 2 183
2 3 183
==== 1.3. Stored functions ====
**** On Master ****
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 $$
SELECT SQL_CALC_FOUND_ROWS * FROM t1 WHERE a > 5 ORDER BY a LIMIT 1;
a
7
SELECT FOUND_ROWS() INTO @found_rows;
SELECT log_rows(3,1,@found_rows), log_rows(3,2,@found_rows);
log_rows(3,1,@found_rows) log_rows(3,2,@found_rows)
183 183
SELECT * FROM logtbl WHERE sect = 3 ORDER BY sect,test;
sect test count
3 1 183
3 2 183
**** On Slave ****
SELECT * FROM logtbl WHERE sect = 3 ORDER BY sect,test;
sect test count
3 1 183
3 2 183
==== 1.9. Cleanup ====
**** On Master ****
DELETE FROM logtbl;
DROP PROCEDURE just_log;
DROP PROCEDURE calc_and_log;
DROP FUNCTION log_rows;
**** Resetting master and slave ****
include/stop_slave.inc
RESET SLAVE;
RESET MASTER;
include/start_slave.inc
#### 2. Using mixed mode ####
==== 2.1. Checking a procedure ====
**** On Master ****
SET BINLOG_FORMAT=MIXED;
CREATE PROCEDURE just_log(sect INT, test INT) BEGIN
INSERT INTO logtbl VALUES (sect,test,FOUND_ROWS());
END $$
**** On Master 1 ****
SET BINLOG_FORMAT=MIXED;
SELECT SQL_CALC_FOUND_ROWS * FROM t1 WHERE a > 5 ORDER BY a LIMIT 1;
a
7
@ -148,7 +53,7 @@ sect test count
1 2 183
1 3 3
1 4 183
==== 2.1. Checking a stored function ====
==== Checking a stored function ====
**** On Master ****
CREATE FUNCTION log_rows(sect INT, test INT)
RETURNS INT

View file

@ -0,0 +1,71 @@
stop slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
reset master;
reset slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
start slave;
CREATE SCHEMA IF NOT EXISTS mysqlslap;
USE mysqlslap;
select @@global.binlog_format;
@@global.binlog_format
MIXED
CREATE TABLE t1 (id INT primary key auto_increment, name VARCHAR(64));
FLUSH TABLE t1;
SELECT COUNT(*) FROM t1;
COUNT(*)
5000
use mysqlslap;
SELECT COUNT(*) FROM t1;
COUNT(*)
5000
truncate table t1;
insert delayed into t1 values(10, "my name");
insert delayed into t1 values(10, "is Bond"), (20, "James Bond");
flush table t1;
select * from t1;
id name
10 my name
20 James Bond
select * from t1;
id name
10 my name
20 James Bond
delete from t1 where id!=10;
insert delayed into t1 values(20, "is Bond"), (10, "James Bond");
flush table t1;
select * from t1;
id name
10 my name
20 is Bond
select * from t1;
id name
10 my name
20 is Bond
USE test;
DROP SCHEMA mysqlslap;
use test;
FLUSH LOGS;
FLUSH LOGS;
CREATE TABLE t1(a int, UNIQUE(a));
INSERT DELAYED IGNORE INTO t1 VALUES(1);
INSERT DELAYED IGNORE INTO t1 VALUES(1);
flush table t1;
show binlog events in 'master-bin.000002' LIMIT 2,2;
Log_name Pos Event_type Server_id End_log_pos Info
x x x x x BEGIN
x x x x x table_id: # (test.t1)
select * from t1;
a
1
On slave
show binlog events in 'slave-bin.000002' LIMIT 2,2;
Log_name Pos Event_type Server_id End_log_pos Info
x x x x x BEGIN
x x x x x table_id: # (test.t1)
select * from t1;
a
1
drop table t1;
FLUSH LOGS;
FLUSH LOGS;
End of 5.0 tests

View file

@ -4,12 +4,6 @@ reset master;
reset slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
start slave;
SET @old_binlog_format= @@global.binlog_format;
SET BINLOG_FORMAT=MIXED;
SET GLOBAL BINLOG_FORMAT=MIXED;
SELECT @@GLOBAL.BINLOG_FORMAT, @@SESSION.BINLOG_FORMAT;
@@GLOBAL.BINLOG_FORMAT @@SESSION.BINLOG_FORMAT
MIXED MIXED
**** On Master ****
CREATE TABLE t1 (a INT, b LONG);
INSERT INTO t1 VALUES (1,1), (2,2);
@ -73,4 +67,3 @@ slave-bin.000001 # Table_map 1 # table_id: # (test.t1)
slave-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
slave-bin.000001 # Query 1 # COMMIT
DROP TABLE IF EXISTS t1;
SET @@global.binlog_format= @old_binlog_format;

View file

@ -0,0 +1,160 @@
stop slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
reset master;
reset slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
start slave;
set @old_slave_exec_mode= @@global.slave_exec_mode;
set @@global.slave_exec_mode= IDEMPOTENT;
create table ti1 (b int primary key) engine = innodb;
create table ti2 (a int primary key, b int, foreign key (b) references ti1(b))
engine = innodb;
set foreign_key_checks=1 /* ensure the check */;
insert into ti1 values (1),(2),(3);
insert into ti2 set a=2, b=2;
select * from ti1 order by b /* must be (1),(2),(3) */;
b
1
2
3
insert into ti2 set a=1, b=1;
select * from ti2 order by b /* must be (1,1) (2,2) */;
a b
1 1
2 2
set @save_binlog_format= @@session.binlog_format;
set @@session.binlog_format= row;
delete from ti1 where b=1;
select * from ti1 order by b /* must be (2),(3) */;
b
2
3
select * from ti1 order by b /* must stays as were on master (1),(2),(3) */;
b
1
2
3
delete from ti1 where b=3;
insert into ti2 set a=3, b=3;
select * from ti2 order by b /* must be (1,1),(2,2) - not inserted */;
a b
1 1
2 2
set global slave_exec_mode='IDEMPOTENT';
set global slave_exec_mode='STRICT';
set global slave_exec_mode='IDEMPOTENT,STRICT';
ERROR HY000: Ambiguous slave modes combination.
select @@global.slave_exec_mode /* must be STRICT */;
@@global.slave_exec_mode
STRICT
*** foreign keys errors as above now forces to stop
set foreign_key_checks=0;
drop table ti2, ti1;
create table ti1 (b int primary key) engine = innodb;
create table ti2 (a int primary key, b int, foreign key (b) references ti1(b))
engine = innodb;
set foreign_key_checks=1 /* ensure the check */;
insert into ti1 values (1),(2),(3);
insert into ti2 set a=2, b=2;
select * from ti1 order by b /* must be (1),(2),(3) */;
b
1
2
3
*** conspire future problem
insert into ti2 set a=1, b=1;
select * from ti2 order by b /* must be (1,1) (2,2) */;
a b
1 1
2 2
delete from ti1 where b=1 /* offending delete event */;
select * from ti1 order by b /* must be (2),(3) */;
b
2
3
*** slave must stop (Trying to delete a referenced foreing key)
Last_SQL_Error
1451
select * from ti1 order by b /* must be (1),(2),(3) - not deleted */;
b
1
2
3
set foreign_key_checks= 0;
delete from ti2 where b=1;
set foreign_key_checks= 1;
set global slave_exec_mode='IDEMPOTENT';
start slave sql_thread;
set global slave_exec_mode='STRICT';
*** conspire the following insert failure
*** conspire future problem
delete from ti1 where b=3;
insert into ti2 set a=3, b=3 /* offending write event */;
*** slave must stop (Trying to insert an invalid foreign key)
Last_SQL_Error
1452
select * from ti2 order by b /* must be (2,2) */;
a b
2 2
set foreign_key_checks= 0;
insert into ti1 set b=3;
set foreign_key_checks= 1;
set global slave_exec_mode='IDEMPOTENT';
start slave sql_thread;
set global slave_exec_mode='STRICT';
select * from ti2 order by b /* must be (2,2),(3,3) */;
a b
2 2
3 3
*** other errors
*** conspiring query
insert into ti1 set b=1;
insert into ti1 set b=1 /* offending write event */;
*** slave must stop (Trying to insert a dupliacte key)
Last_SQL_Error
1062
set foreign_key_checks= 0;
delete from ti1 where b=1;
set foreign_key_checks= 1;
set global slave_exec_mode='IDEMPOTENT';
start slave sql_thread;
set global slave_exec_mode='STRICT';
CREATE TABLE t1 (a INT PRIMARY KEY);
CREATE TABLE t2 (a INT);
INSERT INTO t1 VALUES (-1),(-2),(-3);
INSERT INTO t2 VALUES (-1),(-2),(-3);
DELETE FROM t1 WHERE a = -2;
DELETE FROM t2 WHERE a = -2;
DELETE FROM t1 WHERE a = -2;
*** slave must stop (Key was not found)
Last_SQL_Error
1032
set global slave_exec_mode='IDEMPOTENT';
start slave sql_thread;
set global slave_exec_mode='STRICT';
DELETE FROM t2 WHERE a = -2;
*** slave must stop (Key was not found)
Last_SQL_Error
1032
set global slave_exec_mode='IDEMPOTENT';
start slave sql_thread;
set global slave_exec_mode='STRICT';
UPDATE t1 SET a = 1 WHERE a = -1;
UPDATE t2 SET a = 1 WHERE a = -1;
UPDATE t1 SET a = 1 WHERE a = -1;
*** slave must stop (Key was not found)
Last_SQL_Error
1032
set global slave_exec_mode='IDEMPOTENT';
start slave sql_thread;
set global slave_exec_mode='STRICT';
UPDATE t2 SET a = 1 WHERE a = -1;
*** slave must stop (Key was not found)
Last_SQL_Error
1032
set global slave_exec_mode='IDEMPOTENT';
start slave sql_thread;
SET @@global.slave_exec_mode= @old_slave_exec_mode;
drop table t1,t2,ti2,ti1;
set @@global.slave_exec_mode= @old_slave_exec_mode;
*** end of tests

View file

@ -4,8 +4,6 @@ reset master;
reset slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
start slave;
set @old_global_binlog_format = @@global.binlog_format;
set @@global.binlog_format = row;
CREATE SCHEMA IF NOT EXISTS mysqlslap;
USE mysqlslap;
select @@global.binlog_format;
@ -59,4 +57,3 @@ a
1
drop table t1;
End of 5.0 tests
set @@global.binlog_format = @old_global_binlog_format;

View file

@ -0,0 +1,110 @@
stop slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
reset master;
reset slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
start slave;
==== Initialize ====
**** On 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;
==== Simple test ====
SELECT SQL_CALC_FOUND_ROWS * FROM t1 WHERE a > 5 ORDER BY a LIMIT 1;
a
7
SELECT FOUND_ROWS() INTO @a;
INSERT INTO logtbl VALUES(1,1,@a);
SELECT SQL_CALC_FOUND_ROWS * FROM t1 WHERE a < 5 ORDER BY a LIMIT 1;
a
1
SELECT FOUND_ROWS() INTO @a;
INSERT INTO logtbl VALUES(1,2,@a);
SELECT * FROM logtbl WHERE sect = 1 ORDER BY sect,test;
sect test count
1 1 183
1 2 3
**** On Slave ****
SELECT * FROM logtbl WHERE sect = 1 ORDER BY sect,test;
sect test count
1 1 183
1 2 3
==== Stored procedure ====
**** On Master ****
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 $$
CALL calc_and_log(2,1);
a
1
a
7
Warnings:
Note 1592 Unsafe statement binlogged in statement format since BINLOG_FORMAT = STATEMENT. Reason: Statement uses a LIMIT clause. This is unsafe because the set of rows included cannot be predicted.
Note 1592 Unsafe statement binlogged in statement format since BINLOG_FORMAT = STATEMENT. Reason: Statement uses a system function whose value may differ on slave.
CREATE PROCEDURE just_log(sect INT, test INT, found_rows INT) BEGIN
INSERT INTO logtbl VALUES (sect,test,found_rows);
END $$
SELECT SQL_CALC_FOUND_ROWS * FROM t1 WHERE a > 5 ORDER BY a LIMIT 1;
a
7
SELECT FOUND_ROWS() INTO @found_rows;
CALL just_log(2,3,@found_rows);
SELECT * FROM logtbl WHERE sect = 2 ORDER BY sect,test;
sect test count
2 1 3
2 2 183
2 3 183
**** On Slave ****
SELECT * FROM logtbl WHERE sect = 2 ORDER BY sect,test;
sect test count
2 1 3
2 2 183
2 3 183
==== Stored functions ====
**** On Master ****
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 $$
SELECT SQL_CALC_FOUND_ROWS * FROM t1 WHERE a > 5 ORDER BY a LIMIT 1;
a
7
SELECT FOUND_ROWS() INTO @found_rows;
SELECT log_rows(3,1,@found_rows), log_rows(3,2,@found_rows);
log_rows(3,1,@found_rows) log_rows(3,2,@found_rows)
183 183
SELECT * FROM logtbl WHERE sect = 3 ORDER BY sect,test;
sect test count
3 1 183
3 2 183
**** On Slave ****
SELECT * FROM logtbl WHERE sect = 3 ORDER BY sect,test;
sect test count
3 1 183
3 2 183
==== Cleanup ====
**** On Master ****
DROP TABLE t1, logtbl;
DROP PROCEDURE just_log;
DROP PROCEDURE calc_and_log;
DROP FUNCTION log_rows;
**** Resetting master and slave ****
include/stop_slave.inc
RESET SLAVE;
RESET MASTER;
include/start_slave.inc

View file

@ -4,8 +4,6 @@ reset master;
reset slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
start slave;
set @old_global_binlog_format = @@global.binlog_format;
set @@global.binlog_format = statement;
CREATE SCHEMA IF NOT EXISTS mysqlslap;
USE mysqlslap;
select @@global.binlog_format;
@ -71,70 +69,3 @@ drop table t1;
FLUSH LOGS;
FLUSH LOGS;
End of 5.0 tests
set @@global.binlog_format = mixed;
CREATE SCHEMA IF NOT EXISTS mysqlslap;
USE mysqlslap;
select @@global.binlog_format;
@@global.binlog_format
MIXED
CREATE TABLE t1 (id INT primary key auto_increment, name VARCHAR(64));
FLUSH TABLE t1;
SELECT COUNT(*) FROM t1;
COUNT(*)
5000
use mysqlslap;
SELECT COUNT(*) FROM t1;
COUNT(*)
5000
truncate table t1;
insert delayed into t1 values(10, "my name");
insert delayed into t1 values(10, "is Bond"), (20, "James Bond");
flush table t1;
select * from t1;
id name
10 my name
20 James Bond
select * from t1;
id name
10 my name
20 James Bond
delete from t1 where id!=10;
insert delayed into t1 values(20, "is Bond"), (10, "James Bond");
flush table t1;
select * from t1;
id name
10 my name
20 is Bond
select * from t1;
id name
10 my name
20 is Bond
USE test;
DROP SCHEMA mysqlslap;
use test;
FLUSH LOGS;
FLUSH LOGS;
CREATE TABLE t1(a int, UNIQUE(a));
INSERT DELAYED IGNORE INTO t1 VALUES(1);
INSERT DELAYED IGNORE INTO t1 VALUES(1);
flush table t1;
show binlog events in 'master-bin.000002' LIMIT 2,2;
Log_name Pos Event_type Server_id End_log_pos Info
x x x x x use `test`; INSERT DELAYED IGNORE INTO t1 VALUES(1)
x x x x x use `test`; INSERT DELAYED IGNORE INTO t1 VALUES(1)
select * from t1;
a
1
On slave
show binlog events in 'slave-bin.000002' LIMIT 2,2;
Log_name Pos Event_type Server_id End_log_pos Info
x x x x x use `test`; INSERT DELAYED IGNORE INTO t1 VALUES(1)
x x x x x use `test`; INSERT DELAYED IGNORE INTO t1 VALUES(1)
select * from t1;
a
1
drop table t1;
FLUSH LOGS;
FLUSH LOGS;
End of 5.0 tests
set @@global.binlog_format = @old_global_binlog_format;

View file

@ -10,7 +10,7 @@ CREATE TABLE test.t1 (a INT, blob_column LONGBLOB, PRIMARY KEY(a));
INSERT INTO test.t1 VALUES(1,'test');
UPDATE test.t1 SET blob_column=LOAD_FILE('../../std_data/words2.dat') WHERE a=1;
Warnings:
Note 1592 Statement may not be safe to log in statement format.
Note 1592 Unsafe statement binlogged in statement format since BINLOG_FORMAT = STATEMENT. Reason: Statement uses a system function whose value may differ on slave.
create procedure test.p1()
begin
INSERT INTO test.t1 VALUES(2,'test');
@ -18,7 +18,7 @@ UPDATE test.t1 SET blob_column=LOAD_FILE('../../std_data/words2.dat') WHERE a=2;
end|
CALL test.p1();
Warnings:
Note 1592 Statement may not be safe to log in statement format.
Note 1592 Unsafe statement binlogged in statement format since BINLOG_FORMAT = STATEMENT. Reason: Statement uses a system function whose value may differ on slave.
SELECT * FROM test.t1 ORDER BY blob_column;
a blob_column
1 abase

View file

@ -6,7 +6,6 @@ drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
start slave;
call mtr.add_suppression("Deadlock found");
**** On Master ****
SET SESSION BINLOG_FORMAT=ROW;
CREATE TABLE t1 (a INT PRIMARY KEY, b INT);
INSERT INTO t1 VALUES (1,1), (2,2), (3,3), (4,4);
**** On Slave ****

View file

@ -4,7 +4,6 @@ reset master;
reset slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
start slave;
set binlog_format=row;
drop table if exists t1;
"*** Test 1) Test UDFs via loadable libraries ***
"Running on the master"
@ -156,163 +155,3 @@ affected rows: 0
"Running on the master"
DROP TABLE t1;
affected rows: 0
set binlog_format=statement;
drop table if exists t1;
"*** Test 1) Test UDFs via loadable libraries ***
"Running on the master"
CREATE FUNCTION myfunc_double RETURNS REAL SONAME "UDF_EXAMPLE_LIB";
affected rows: 0
CREATE FUNCTION myfunc_int RETURNS INTEGER SONAME "UDF_EXAMPLE_LIB";
affected rows: 0
CREATE FUNCTION myfunc_nonexist RETURNS INTEGER SONAME "UDF_EXAMPLE_LIB";
ERROR HY000: Can't find symbol 'myfunc_nonexist' in library
SELECT * FROM mysql.func ORDER BY name;
name ret dl type
myfunc_double 1 UDF_LIB function
myfunc_int 2 UDF_LIB function
affected rows: 2
"Running on the slave"
SELECT * FROM mysql.func ORDER BY name;
name ret dl type
myfunc_double 1 UDF_LIB function
myfunc_int 2 UDF_LIB function
affected rows: 2
"Running on the master"
CREATE TABLE t1(sum INT, price FLOAT(24)) ENGINE=MyISAM;
affected rows: 0
INSERT INTO t1 VALUES(myfunc_int(100), myfunc_double(50.00));
Warnings:
Note 1592 Statement may not be safe to log in statement format.
affected rows: 1
INSERT INTO t1 VALUES(myfunc_int(10), myfunc_double(5.00));
Warnings:
Note 1592 Statement may not be safe to log in statement format.
affected rows: 1
INSERT INTO t1 VALUES(myfunc_int(200), myfunc_double(25.00));
Warnings:
Note 1592 Statement may not be safe to log in statement format.
affected rows: 1
INSERT INTO t1 VALUES(myfunc_int(1), myfunc_double(500.00));
Warnings:
Note 1592 Statement may not be safe to log in statement format.
affected rows: 1
SELECT * FROM t1 ORDER BY sum;
sum price
1 48.5
10 48.75
100 48.6
200 49
affected rows: 4
"Running on the slave"
SELECT * FROM t1 ORDER BY sum;
sum price
1 48.5
10 48.75
100 48.6
200 49
affected rows: 4
SELECT myfunc_int(25);
myfunc_int(25)
25
affected rows: 1
SELECT myfunc_double(75.00);
myfunc_double(75.00)
50.00
affected rows: 1
"Running on the master"
DROP FUNCTION myfunc_double;
affected rows: 0
DROP FUNCTION myfunc_int;
affected rows: 0
SELECT * FROM mysql.func ORDER BY name;
name ret dl type
affected rows: 0
"Running on the slave"
SELECT * FROM mysql.func ORDER BY name;
name ret dl type
affected rows: 0
"Running on the master"
DROP TABLE t1;
affected rows: 0
"*** Test 2) Test UDFs with SQL body ***
"Running on the master"
CREATE FUNCTION myfuncsql_int(i INT) RETURNS INTEGER DETERMINISTIC RETURN i;
affected rows: 0
CREATE FUNCTION myfuncsql_double(d DOUBLE) RETURNS INTEGER DETERMINISTIC RETURN d * 2.00;
affected rows: 0
SELECT db, name, type, param_list, body, comment FROM mysql.proc WHERE db = 'test' AND name LIKE 'myfuncsql%' ORDER BY name;
db name type param_list body comment
test myfuncsql_double FUNCTION d DOUBLE RETURN d * 2.00
test myfuncsql_int FUNCTION i INT RETURN i
affected rows: 2
"Running on the slave"
SELECT db, name, type, param_list, body, comment FROM mysql.proc WHERE db = 'test' AND name LIKE 'myfuncsql%' ORDER BY name;
db name type param_list body comment
test myfuncsql_double FUNCTION d DOUBLE RETURN d * 2.00
test myfuncsql_int FUNCTION i INT RETURN i
affected rows: 2
"Running on the master"
CREATE TABLE t1(sum INT, price FLOAT(24)) ENGINE=MyISAM;
affected rows: 0
INSERT INTO t1 VALUES(myfuncsql_int(100), myfuncsql_double(50.00));
affected rows: 1
INSERT INTO t1 VALUES(myfuncsql_int(10), myfuncsql_double(5.00));
affected rows: 1
INSERT INTO t1 VALUES(myfuncsql_int(200), myfuncsql_double(25.00));
affected rows: 1
INSERT INTO t1 VALUES(myfuncsql_int(1), myfuncsql_double(500.00));
affected rows: 1
SELECT * FROM t1 ORDER BY sum;
sum price
1 1000
10 10
100 100
200 50
affected rows: 4
"Running on the slave"
SELECT * FROM t1 ORDER BY sum;
sum price
1 1000
10 10
100 100
200 50
affected rows: 4
"Running on the master"
ALTER FUNCTION myfuncsql_int COMMENT "This was altered.";
affected rows: 0
ALTER FUNCTION myfuncsql_double COMMENT "This was altered.";
affected rows: 0
SELECT db, name, type, param_list, body, comment FROM mysql.proc WHERE db = 'test' AND name LIKE 'myfuncsql%' ORDER BY name;
db name type param_list body comment
test myfuncsql_double FUNCTION d DOUBLE RETURN d * 2.00 This was altered.
test myfuncsql_int FUNCTION i INT RETURN i This was altered.
affected rows: 2
"Running on the slave"
SELECT db, name, type, param_list, body, comment FROM mysql.proc WHERE db = 'test' AND name LIKE 'myfuncsql%' ORDER BY name;
db name type param_list body comment
test myfuncsql_double FUNCTION d DOUBLE RETURN d * 2.00 This was altered.
test myfuncsql_int FUNCTION i INT RETURN i This was altered.
affected rows: 2
SELECT myfuncsql_int(25);
myfuncsql_int(25)
25
affected rows: 1
SELECT myfuncsql_double(75.00);
myfuncsql_double(75.00)
150
affected rows: 1
"Running on the master"
DROP FUNCTION myfuncsql_double;
affected rows: 0
DROP FUNCTION myfuncsql_int;
affected rows: 0
SELECT db, name, type, param_list, body, comment FROM mysql.proc WHERE db = 'test' AND name LIKE 'myfuncsql%' ORDER BY name;
db name type param_list body comment
affected rows: 0
"Running on the slave"
SELECT db, name, type, param_list, body, comment FROM mysql.proc WHERE db = 'test' AND name LIKE 'myfuncsql%' ORDER BY name;
db name type param_list body comment
affected rows: 0
"Running on the master"
DROP TABLE t1;
affected rows: 0

View file

@ -1,3 +1,4 @@
source include/have_binlog_format_mixed_or_row.inc;
source include/master-slave.inc;
CREATE DATABASE track;

View file

@ -1,11 +1,9 @@
##################################################################
# Author: Giuseppe #
# Date: 2006-12-20 #
# Purpose: To test that event effects are replicated #
# in both row based and statement based format #
# Purpose: To test that event effects are replicated. #
##################################################################
--source include/not_embedded.inc
--source include/master-slave.inc
SET @old_event_scheduler = @@global.event_scheduler;
@ -13,14 +11,6 @@ set global event_scheduler=1;
let $engine_type= MyISAM;
set binlog_format=row;
# Embedded server doesn't support binlogging
--source include/rpl_events.inc
set binlog_format=statement;
# Embedded server doesn't support binlogging
--source include/rpl_events.inc
#

View file

@ -1,16 +1,9 @@
#############################################################
# Purpose: To test having extra columns on the master WL#3915
#############################################################
-- source include/have_binlog_format_row.inc
-- source include/master-slave.inc
-- source include/have_innodb.inc
let $engine_type = 'InnoDB';
set binlog_format=row;
-- source extra/rpl_tests/rpl_extraMaster_Col.test
set binlog_format=statement;
-- source extra/rpl_tests/rpl_extraMaster_Col.test
set binlog_format=mixed;
-- source extra/rpl_tests/rpl_extraMaster_Col.test
--source extra/rpl_tests/rpl_extraMaster_Col.test

View file

@ -1,15 +1,8 @@
#############################################################
# 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';
set binlog_format=row;
-- source extra/rpl_tests/rpl_extraMaster_Col.test
set binlog_format=statement;
-- source extra/rpl_tests/rpl_extraMaster_Col.test
set binlog_format=mixed;
-- source extra/rpl_tests/rpl_extraMaster_Col.test
--source extra/rpl_tests/rpl_extraMaster_Col.test

View file

@ -1 +0,0 @@
--slave-exec-mode=IDEMPOTENT

View file

@ -2,17 +2,11 @@
# work the same way under statement based as under row based.
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("Slave: Can\'t find record in \'t1\' Error_code: 1032");
call mtr.add_suppression("Slave: Cannot add or update a child row: a foreign key constraint fails .* Error_code: 1452");
SET @old_slave_exec_mode= @@global.slave_exec_mode;
connection master;
CREATE TABLE t1 (a INT PRIMARY KEY);
CREATE TABLE t2 (a INT);
@ -20,6 +14,9 @@ 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
@ -57,6 +54,7 @@ disable_query_log;
eval SELECT "$last_error" AS Last_SQL_Error;
enable_query_log;
# BUG#19958: RBR idempotency issue for UPDATE and DELETE
# Statement-based and row-based replication have different behaviour
@ -88,316 +86,4 @@ connection master;
DROP TABLE t1, t2;
sync_slave_with_master;
# bug#31609 Not all RBR slave errors reported as errors
# bug#31552 Replication breaks when deleting rows from out-of-sync table
# without PK
#
# Idempotent applying is not default any longer.
# The default for slave-exec-mode option and server
# variable slave_exec_mode is 'STRICT'.
# When 'STRICT' mode is set, the slave SQL thread will stop whenever
# the row to change is not found. In 'IDEMPOTENT' mode, the SQL thread
# will continue running and apply the row - replace if it's Write_rows event -
# or skip to the next event.
# the previous part of the tests was with IDEMPOTENT slave's mode.
#
# Other than above idempotent errors dealing with foreign keys constraint
#
select @@global.slave_exec_mode /* must be IDEMPOTENT */;
connection master;
create table ti1 (b int primary key) engine = innodb;
create table ti2 (a int primary key, b int, foreign key (b) references ti1(b))
engine = innodb;
set foreign_key_checks=1 /* ensure the check */;
insert into ti1 values (1),(2),(3);
insert into ti2 set a=2, b=2;
sync_slave_with_master;
#connection slave;
select * from ti1 order by b /* must be (1),(2),(3) */;
insert into ti2 set a=1, b=1;
select * from ti2 order by b /* must be (1,1) (2,2) */;
connection master;
# from now on checking rbr specific idempotent errors
set @save_binlog_format= @@session.binlog_format;
set @@session.binlog_format= row;
delete from ti1 where b=1;
select * from ti1 order by b /* must be (2),(3) */;
# slave must catch up (expect some warnings in error.log)
sync_slave_with_master;
#connection slave;
select * from ti1 order by b /* must stays as were on master (1),(2),(3) */;
delete from ti1 where b=3;
connection master;
insert into ti2 set a=3, b=3;
# slave must catch up (expect some warnings in error.log)
sync_slave_with_master;
#connection slave;
select * from ti2 order by b /* must be (1,1),(2,2) - not inserted */;
#
# Checking the new global sys variable
#
connection slave;
set global slave_exec_mode='IDEMPOTENT';
set global slave_exec_mode='STRICT';
# checking mutual exclusion for the options
--error ER_SLAVE_AMBIGOUS_EXEC_MODE
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;
set @@session.binlog_format= @save_binlog_format;
drop table t1,t2,ti2,ti1;
--source include/master-slave-end.inc
--echo *** end of tests

View file

@ -1,16 +1,15 @@
source include/master-slave.inc;
source include/have_binlog_format_mixed.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).
# The purpose of this test case is to test that the workaround
# function properly even when inside stored programs (i.e., stored
# routines and triggers).
--echo ==== 0. Setting it all up ====
SET BINLOG_FORMAT=STATEMENT;
--echo ==== Initialize ====
--echo **** On Master ****
connection master;
@ -25,106 +24,10 @@ 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 #### 1. Using statement mode ####
--echo ==== 1.1. 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
SELECT FOUND_ROWS() INTO @a;
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
SELECT FOUND_ROWS() INTO @a;
INSERT INTO logtbl VALUES(1,2,@a);
SELECT * FROM logtbl WHERE sect = 1 ORDER BY sect,test;
--echo **** On Slave ****
sync_slave_with_master;
SELECT * FROM logtbl WHERE sect = 1 ORDER BY sect,test;
--echo ==== 1.2. 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.
--echo ==== Checking a procedure ====
--echo **** On Master ****
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;
SELECT FOUND_ROWS() INTO @found_rows;
CALL just_log(2,3,@found_rows);
SELECT * FROM logtbl WHERE sect = 2 ORDER BY sect,test;
--echo **** On Slave ****
sync_slave_with_master;
SELECT * FROM logtbl WHERE sect = 2 ORDER BY sect,test;
--echo ==== 1.3. Stored functions ====
--echo **** On Master ****
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;
SELECT FOUND_ROWS() INTO @found_rows;
SELECT log_rows(3,1,@found_rows), log_rows(3,2,@found_rows);
SELECT * FROM logtbl WHERE sect = 3 ORDER BY sect,test;
--echo **** On Slave ****
sync_slave_with_master;
SELECT * FROM logtbl WHERE sect = 3 ORDER BY sect,test;
--echo ==== 1.9. Cleanup ====
--echo **** On Master ****
connection master;
DELETE FROM logtbl;
DROP PROCEDURE just_log;
DROP PROCEDURE calc_and_log;
DROP FUNCTION log_rows;
sync_slave_with_master;
source include/reset_master_and_slave.inc;
--echo #### 2. Using mixed mode ####
--echo ==== 2.1. Checking a procedure ====
--echo **** On Master ****
connection master;
SET BINLOG_FORMAT=MIXED;
# We will now check some stuff that will not work in statement-based
# replication, but which should cause the binary log to switch to
@ -139,7 +42,6 @@ sync_slave_with_master;
--echo **** On Master 1 ****
connection master1;
SET BINLOG_FORMAT=MIXED;
SELECT SQL_CALC_FOUND_ROWS * FROM t1 WHERE a > 5 ORDER BY a LIMIT 1;
CALL just_log(1,1);
@ -167,7 +69,7 @@ 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 ==== 2.1. Checking a stored function ====
--echo ==== Checking a stored function ====
--echo **** On Master ****
connection master;
--delimiter $$

View file

@ -0,0 +1,5 @@
--source include/have_binlog_format_mixed.inc
--source include/master-slave.inc
--source include/not_embedded.inc
--source include/not_windows.inc
--source extra/rpl_tests/rpl_insert_delayed.test

View file

@ -1,15 +1,9 @@
-- source include/have_binlog_format_mixed_or_statement.inc
-- source include/have_binlog_format_mixed.inc
-- source include/not_ndb_default.inc
-- source include/master-slave.inc
# Test that the slave temporarily switches to ROW when seeing binrow
# events when it is in STATEMENT or MIXED mode
SET @old_binlog_format= @@global.binlog_format;
SET BINLOG_FORMAT=MIXED;
SET GLOBAL BINLOG_FORMAT=MIXED;
SELECT @@GLOBAL.BINLOG_FORMAT, @@SESSION.BINLOG_FORMAT;
# Test that the slave temporarily switches to ROW when seeing row
# events when it is in MIXED mode
--echo **** On Master ****
CREATE TABLE t1 (a INT, b LONG);
@ -35,7 +29,6 @@ SHOW BINLOG EVENTS;
connection master;
DROP TABLE IF EXISTS t1;
SET @@global.binlog_format= @old_binlog_format;
# 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

View file

@ -0,0 +1,325 @@
# 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;
# 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_SLAVE_AMBIGOUS_EXEC_MODE
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;
--source include/master-slave-end.inc
--echo *** end of tests

View file

@ -2,13 +2,4 @@
--source include/master-slave.inc
--source include/not_embedded.inc
--source include/not_windows.inc
connection master;
set @old_global_binlog_format = @@global.binlog_format;
let $binlog_format_statement=0;
set @@global.binlog_format = row;
--source extra/rpl_tests/rpl_insert_delayed.test
connection master;
set @@global.binlog_format = @old_global_binlog_format;

View file

@ -1,3 +1,9 @@
# 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/master-slave.inc;
source include/have_innodb.inc;

View file

@ -0,0 +1,121 @@
source include/have_binlog_format_statement.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 ====
--echo **** On Master ****
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
SELECT FOUND_ROWS() INTO @a;
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
SELECT FOUND_ROWS() INTO @a;
INSERT INTO logtbl VALUES(1,2,@a);
SELECT * FROM logtbl WHERE sect = 1 ORDER BY sect,test;
--echo **** On Slave ****
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.
--echo **** On Master ****
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;
SELECT FOUND_ROWS() INTO @found_rows;
CALL just_log(2,3,@found_rows);
SELECT * FROM logtbl WHERE sect = 2 ORDER BY sect,test;
--echo **** On Slave ****
sync_slave_with_master;
SELECT * FROM logtbl WHERE sect = 2 ORDER BY sect,test;
--echo ==== Stored functions ====
--echo **** On Master ****
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;
SELECT FOUND_ROWS() INTO @found_rows;
SELECT log_rows(3,1,@found_rows), log_rows(3,2,@found_rows);
SELECT * FROM logtbl WHERE sect = 3 ORDER BY sect,test;
--echo **** On Slave ****
sync_slave_with_master;
SELECT * FROM logtbl WHERE sect = 3 ORDER BY sect,test;
--echo ==== Cleanup ====
--echo **** On Master ****
connection master;
DROP TABLE t1, logtbl;
DROP PROCEDURE just_log;
DROP PROCEDURE calc_and_log;
DROP FUNCTION log_rows;
sync_slave_with_master;
source include/reset_master_and_slave.inc;

View file

@ -1,20 +1,5 @@
# we run first in statement-based then in mixed binlogging
--source include/have_binlog_format_mixed_or_statement.inc
--source include/have_binlog_format_statement.inc
--source include/master-slave.inc
--source include/not_embedded.inc
--source include/not_windows.inc
connection master;
set @old_global_binlog_format = @@global.binlog_format;
let $binlog_format_statement=1;
set @@global.binlog_format = statement;
--source extra/rpl_tests/rpl_insert_delayed.test
let $binlog_format_statement=0;
set @@global.binlog_format = mixed;
--source extra/rpl_tests/rpl_insert_delayed.test
connection master;
set @@global.binlog_format = @old_global_binlog_format;

View file

@ -1,17 +1,25 @@
#
# rpl_switch_stm_row_mixed tests covers
#
# - switching explicitly between STATEMENT, ROW, and MIXED binlog format
# showing when it is possible and when not.
# - switching from MIXED to RBR implicitly listing all use cases,
# e.g a query invokes UUID(), thereafter to serve as the definition
# of MIXED binlog format
# - 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 UUID(), thereafter to serve as the
# definition of MIXED binlog format
# - correctness of execution
-- source include/not_ndb_default.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;
-- source include/have_binlog_format_mixed_or_row.inc
connection master;
--disable_warnings
drop database if exists mysqltest1;

View file

@ -1,10 +1,10 @@
source include/have_binlog_format_row.inc;
source include/master-slave.inc;
call mtr.add_suppression("Deadlock found");
--echo **** On Master ****
connection master;
SET SESSION BINLOG_FORMAT=ROW;
CREATE TABLE t1 (a INT PRIMARY KEY, b INT);
INSERT INTO t1 VALUES (1,1), (2,2), (3,3), (4,4);
--echo **** On Slave ****

View file

@ -5,18 +5,7 @@
# statement based format. This tests work completed in WL#3629. #
###################################################################
--source include/not_embedded.inc
--source include/master-slave.inc
let $engine_type= MyISAM;
set binlog_format=row;
# Embedded server doesn't support binlogging
--source include/rpl_udf.inc
set binlog_format=statement;
# Embedded server doesn't support binlogging
--source include/rpl_udf.inc

View file

@ -0,0 +1,8 @@
[row]
binlog-format=row
[stmt]
binlog-format=statement
[mix]
binlog-format=mixed

View file

@ -0,0 +1,130 @@
stop slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
reset master;
reset slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
start slave;
==== Initialize ====
[on slave]
SET @old_binlog_format= @@global.binlog_format;
INSTALL PLUGIN example SONAME 'ha_example.so';
[on master]
SET @old_binlog_format= @@global.binlog_format;
INSTALL PLUGIN example SONAME 'ha_example.so';
CREATE TABLE t (a VARCHAR(100)) ENGINE = MYISAM;
CREATE TABLE t_self_logging (a VARCHAR(100)) ENGINE = NDB;
CREATE TABLE t_row (a VARCHAR(100)) ENGINE = INNODB;
CREATE TABLE t_stmt (a VARCHAR(100)) ENGINE = EXAMPLE;
CREATE TABLE t_slave_stmt (a VARCHAR(100)) ENGINE = MYISAM;
CREATE DATABASE other;
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
[on slave]
DROP TABLE t_slave_stmt;
CREATE TABLE t_slave_stmt (a INT) ENGINE = EXAMPLE;
[on master]
BINLOG '
1gRVSg8BAAAAZgAAAGoAAAABAAQANS4xLjM2LWRlYnVnLWxvZwAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAADWBFVKEzgNAAgAEgAEBAQEEgAAUwAEGggAAAAICAgC
';
==== Test ====
---- binlog_format=row ----
* Modify tables of more than one engine, one of which is self-logging
CREATE TRIGGER trig_1 AFTER INSERT ON t_self_logging FOR EACH ROW BEGIN INSERT INTO t VALUES (1); END;
INSERT INTO t_self_logging VALUES (1);
ERROR HY000: Cannot execute statement: binlogging impossible since more than one engine is involved and at least one engine is self-logging.
DROP trigger trig_1;
* Modify both row-only and stmt-only table
CREATE TRIGGER trig_2 AFTER INSERT ON t_stmt FOR EACH ROW BEGIN INSERT INTO t_row VALUES(1); END;
INSERT INTO t_stmt VALUES (1);
ERROR HY000: Cannot execute statement: binlogging impossible since both row-incapable engines and statement-incapable engines are involved.
DROP TRIGGER trig_2;
* Stmt-only table and binlog_format=row
INSERT INTO t_stmt VALUES (1);
ERROR HY000: Cannot execute statement: binlogging impossible since BINLOG_FORMAT = ROW and at least one table uses a storage engine limited to statement-logging.
* Row injection and stmt-only table: in slave sql thread
INSERT INTO t_slave_stmt VALUES (1);
[on slave]
--source include/wait_for_slave_sql_error_and_skip.inc
Last_SQL_Error = Error 'Cannot execute row injection: binlogging impossible since at least one table uses a storage engine limited to statement-logging.' on opening tables
set global sql_slave_skip_counter=1;
include/start_slave.inc
* Row injection and stmt-only table: use BINLOG statement
BINLOG '
1gRVShMBAAAALwAAAEABAAAAABcAAAAAAAAABHRlc3QABnRfc3RtdAABDwJkAAE=
1gRVShcBAAAAIAAAAGABAAAQABcAAAAAAAEAAf/+ATE=
';
ERROR HY000: Cannot execute row injection: binlogging impossible since at least one table uses a storage engine limited to statement-logging.
---- binlog_format=mixed ----
[on slave]
include/stop_slave.inc
SET @@global.binlog_format = MIXED;
include/start_slave.inc
[on master]
SET @@global.binlog_format = MIXED;
SET @@session.binlog_format = MIXED;
* Unsafe statement and stmt-only engine
INSERT INTO t_stmt VALUES (UUID());
Warnings:
Note 1641 Unsafe statement binlogged as statement since storage engine is limited to statement-logging. Reason: Statement uses a system function whose value may differ on slave.
---- binlog_format=statement ----
[on slave]
include/stop_slave.inc
SET @@global.binlog_format = STATEMENT;
include/start_slave.inc
[on master]
SET @@global.binlog_format = STATEMENT;
SET @@session.binlog_format = STATEMENT;
* Row-only engine and binlog_format=statement: innodb-specific message
INSERT INTO t_row VALUES (1);
ERROR HY000: Cannot execute statement: binlogging impossible since BINLOG_FORMAT = STATEMENT and at least one table uses a storage engine limited to row-logging. InnoDB is limited to row-logging when transaction isolation level is READ COMMITTED or READ UNCOMMITTED.
* Row-only engine and binlog_format=statement: generic message
SET @@session.debug= '+d,no_innodb_binlog_errors';
INSERT INTO t_row VALUES (1);
ERROR HY000: Cannot execute statement: binlogging impossible since BINLOG_FORMAT = STATEMENT and at least one table uses a storage engine limited to row-logging.
* Same statement, but db filtered out - no error
USE other;
INSERT INTO test.t_row VALUES (1);
USE test;
SET @@session.debug= '';
* Row injection and binlog_format=statement: BINLOG statement
BINLOG '
cNpVShMBAAAAKgAAADYBAAAAABcAAAAAAAAABHRlc3QAAXQAAQ8CZAAB
cNpVShcBAAAAIAAAAFYBAAAQABcAAAAAAAEAAf/+ATE=
';
ERROR HY000: Cannot execute row injection: binlogging impossible since BINLOG_FORMAT = STATEMENT.
* Same statement, but db filtered out - no error
USE other;
BINLOG '
cNpVShMBAAAAKgAAADYBAAAAABcAAAAAAAAABHRlc3QAAXQAAQ8CZAAB
cNpVShcBAAAAIAAAAFYBAAAQABcAAAAAAAEAAf/+ATE=
';
USE test;
* Unsafe statement and binlog_format=statement
INSERT INTO t VALUES (UUID());
Warnings:
Note 1592 Unsafe statement binlogged in statement format since BINLOG_FORMAT = STATEMENT. Reason: Statement uses a system function whose value may differ on slave.
* Same statement, but db filtered out - no message
USE other;
INSERT INTO test.t VALUES (UUID());
USE test;
---- master: binlog_format=mixed, slave: binlog_format=statement ----
SET @@global.binlog_format = MIXED;
SET @@session.binlog_format = MIXED;
* Row injection and binlog_format=statement: in slave sql thread
INSERT INTO t VALUES (UUID());
[on slave]
--source include/wait_for_slave_sql_error_and_skip.inc
Last_SQL_Error = Error 'Cannot execute row injection: binlogging impossible since BINLOG_FORMAT = STATEMENT.' on opening tables
set global sql_slave_skip_counter=1;
include/start_slave.inc
[on master]
==== Clean up ====
DROP TABLE t, t_self_logging, t_row, t_stmt, t_slave_stmt;
DROP DATABASE other;
SET @@global.binlog_format = @old_binlog_format;
SET @@session.binlog_format = @old_binlog_format;
UNINSTALL PLUGIN example;
[on slave]
SET @@global.binlog_format = @old_binlog_format;
SET @@session.binlog_format = @old_binlog_format;
UNINSTALL PLUGIN example;

View file

@ -102,3 +102,4 @@ Last_IO_Errno #
Last_IO_Error #
Last_SQL_Errno 0
Last_SQL_Error
DROP TABLE t1;

View file

@ -8,6 +8,9 @@
# test and to have control over the tests.
##############################################################
-- source include/have_ndb.inc
# Since the master generates row-based events, the slave must be in
# ROW or MIXED mode to accept the events.
-- source include/have_binlog_format_mixed_or_row.inc
-- source include/master-slave.inc
-- connection slave

View file

@ -8,6 +8,9 @@
# test and to have control over the tests.
##############################################################
-- source include/have_ndb.inc
# Since the master generates row-based events, the slave must be in
# ROW or MIXED mode to accept the events.
-- source include/have_binlog_format_mixed_or_row.inc
-- source include/master-slave.inc
-- connection slave

View file

@ -1,4 +1,7 @@
--source include/have_ndb.inc
# Since the master generates row-based events, the slave must be in
# ROW or MIXED mode to accept the events.
--source include/have_binlog_format_mixed_or_row.inc
--source include/ndb_master-slave.inc

View file

@ -0,0 +1 @@
--innodb $EXAMPLE_PLUGIN_OPT --binlog-ignore-db=other

View file

@ -0,0 +1 @@
--innodb $EXAMPLE_PLUGIN_OPT

View file

@ -0,0 +1,225 @@
# ==== Purpose ====
#
# Verify that errors or warnings are issued for all error conditions
# related to deciding the binlog format of a statement. The possible
# errors are listed in a comment above decide_logging_format() in
# sql_base.cc.
#
# ==== Method ====
#
# Each error condition is executed; we verify that there is an error.
#
# ==== Related bugs ====
#
# BUG#39934: Slave stops for engine that only support row-based logging
# BUG#42829: binlogging enabled for all schemas regardless of binlog-db-db / binlog-ignore-db
#
# ==== Related test cases ====
#
# binlog.binlog_unsafe verifies more thoroughly that a warning is
# given for the case when an unsafe statement is executed and
# binlog_format = STATEMENT.
# Need debug so that 'SET @@session.debug' works.
--source include/have_debug.inc
# Need example plugin because it is the only statement-only engine.
--source include/have_example_plugin.inc
# The test changes binlog_format, so there is no reason to run it
# under more than one binlog format.
--source include/have_binlog_format_row.inc
--source include/have_ndb.inc
--source include/have_innodb.inc
--source include/ndb_master-slave.inc
--echo ==== Initialize ====
--echo [on slave]
--connection slave
SET @old_binlog_format= @@global.binlog_format;
INSTALL PLUGIN example SONAME 'ha_example.so';
--echo [on master]
--connection master
SET @old_binlog_format= @@global.binlog_format;
INSTALL PLUGIN example SONAME 'ha_example.so';
CREATE TABLE t (a VARCHAR(100)) ENGINE = MYISAM;
CREATE TABLE t_self_logging (a VARCHAR(100)) ENGINE = NDB;
CREATE TABLE t_row (a VARCHAR(100)) ENGINE = INNODB;
CREATE TABLE t_stmt (a VARCHAR(100)) ENGINE = EXAMPLE;
CREATE TABLE t_slave_stmt (a VARCHAR(100)) ENGINE = MYISAM;
CREATE DATABASE other;
# This makes the innodb table row-only
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
--echo [on slave]
--sync_slave_with_master
DROP TABLE t_slave_stmt;
CREATE TABLE t_slave_stmt (a INT) ENGINE = EXAMPLE;
--echo [on master]
--connection master
# This is a format description event. It is needed because any BINLOG
# statement containing a row event must be preceded by a BINLOG
# statement containing a format description event.
BINLOG '
1gRVSg8BAAAAZgAAAGoAAAABAAQANS4xLjM2LWRlYnVnLWxvZwAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAADWBFVKEzgNAAgAEgAEBAQEEgAAUwAEGggAAAAICAgC
';
--echo ==== Test ====
--echo ---- binlog_format=row ----
--echo * Modify tables of more than one engine, one of which is self-logging
--eval CREATE TRIGGER trig_1 AFTER INSERT ON t_self_logging FOR EACH ROW BEGIN INSERT INTO t VALUES (1); END
--error ER_BINLOG_MULTIPLE_ENGINES_AND_SELF_LOGGING_ENGINE
INSERT INTO t_self_logging VALUES (1);
DROP trigger trig_1;
--echo * Modify both row-only and stmt-only table
--eval CREATE TRIGGER trig_2 AFTER INSERT ON t_stmt FOR EACH ROW BEGIN INSERT INTO t_row VALUES(1); END
--error ER_BINLOG_ROW_ENGINE_AND_STMT_ENGINE
INSERT INTO t_stmt VALUES (1);
DROP TRIGGER trig_2;
--echo * Stmt-only table and binlog_format=row
--error ER_BINLOG_ROW_MODE_AND_STMT_ENGINE
INSERT INTO t_stmt VALUES (1);
--echo * Row injection and stmt-only table: in slave sql thread
INSERT INTO t_slave_stmt VALUES (1);
--echo [on slave]
--connection slave
# 1642 = ER_BINLOG_ROW_INJECTION_AND_STMT_ENGINE
--let $slave_sql_errno= 1642
--let $show_sql_error= 1
--source include/wait_for_slave_sql_error_and_skip.inc
--echo * Row injection and stmt-only table: use BINLOG statement
# This is a Table_map_event and a Write_rows_event. Together, they are
# equivalent to 'INSERT INTO t_stmt VALUES (1)'
--error ER_BINLOG_ROW_INJECTION_AND_STMT_ENGINE
BINLOG '
1gRVShMBAAAALwAAAEABAAAAABcAAAAAAAAABHRlc3QABnRfc3RtdAABDwJkAAE=
1gRVShcBAAAAIAAAAGABAAAQABcAAAAAAAEAAf/+ATE=
';
--echo ---- binlog_format=mixed ----
--echo [on slave]
--sync_slave_with_master
--source include/stop_slave.inc
SET @@global.binlog_format = MIXED;
--source include/start_slave.inc
--echo [on master]
--connection master
SET @@global.binlog_format = MIXED;
SET @@session.binlog_format = MIXED;
--echo * Unsafe statement and stmt-only engine
# This will give a warning.
INSERT INTO t_stmt VALUES (UUID());
--echo ---- binlog_format=statement ----
--echo [on slave]
--sync_slave_with_master
--source include/stop_slave.inc
SET @@global.binlog_format = STATEMENT;
--source include/start_slave.inc
--echo [on master]
--connection master
SET @@global.binlog_format = STATEMENT;
SET @@session.binlog_format = STATEMENT;
--echo * Row-only engine and binlog_format=statement: innodb-specific message
--error ER_BINLOG_STMT_MODE_AND_ROW_ENGINE
INSERT INTO t_row VALUES (1);
# Commented out since innodb gives an error (this is a bug)
#--echo * Same statement, but db filtered out - no error
#USE other;
#INSERT INTO test.t_row VALUES (1);
#USE test;
--echo * Row-only engine and binlog_format=statement: generic message
SET @@session.debug= '+d,no_innodb_binlog_errors';
--error ER_BINLOG_STMT_MODE_AND_ROW_ENGINE
INSERT INTO t_row VALUES (1);
--echo * Same statement, but db filtered out - no error
USE other;
INSERT INTO test.t_row VALUES (1);
USE test;
SET @@session.debug= '';
--echo * Row injection and binlog_format=statement: BINLOG statement
# This is a Table_map_event and a Write_rows_event. Together, they are
# equivalent to 'INSERT INTO t VALUES (1)'.
--error ER_BINLOG_ROW_INJECTION_AND_STMT_MODE
BINLOG '
cNpVShMBAAAAKgAAADYBAAAAABcAAAAAAAAABHRlc3QAAXQAAQ8CZAAB
cNpVShcBAAAAIAAAAFYBAAAQABcAAAAAAAEAAf/+ATE=
';
--echo * Same statement, but db filtered out - no error
# This is a Table_map_event and a Write_rows_event. Together, they are
# equivalent to 'INSERT INTO t VALUES (1)'.
USE other;
BINLOG '
cNpVShMBAAAAKgAAADYBAAAAABcAAAAAAAAABHRlc3QAAXQAAQ8CZAAB
cNpVShcBAAAAIAAAAFYBAAAQABcAAAAAAAEAAf/+ATE=
';
USE test;
--echo * Unsafe statement and binlog_format=statement
# This will give a warning.
INSERT INTO t VALUES (UUID());
--echo * Same statement, but db filtered out - no message
USE other;
INSERT INTO test.t VALUES (UUID());
USE test;
--echo ---- master: binlog_format=mixed, slave: binlog_format=statement ----
SET @@global.binlog_format = MIXED;
SET @@session.binlog_format = MIXED;
--echo * Row injection and binlog_format=statement: in slave sql thread
INSERT INTO t VALUES (UUID());
--echo [on slave]
--connection slave
# 1644 = ER_BINLOG_ROW_INJECTION_AND_STMT_MODE
--let $slave_sql_errno= 1644
--let $show_sql_error= 1
--source include/wait_for_slave_sql_error_and_skip.inc
--echo [on master]
--connection master
--echo ==== Clean up ====
DROP TABLE t, t_self_logging, t_row, t_stmt, t_slave_stmt;
DROP DATABASE other;
SET @@global.binlog_format = @old_binlog_format;
SET @@session.binlog_format = @old_binlog_format;
UNINSTALL PLUGIN example;
--echo [on slave]
--sync_slave_with_master
SET @@global.binlog_format = @old_binlog_format;
SET @@session.binlog_format = @old_binlog_format;
UNINSTALL PLUGIN example;

View file

@ -1,4 +1,7 @@
--source include/have_ndb.inc
# Since the master generates row-based events, the slave must be in
# ROW or MIXED mode to accept the events.
--source include/have_binlog_format_mixed_or_row.inc
--source include/ndb_master-slave.inc
#

View file

@ -3,6 +3,11 @@
# Using wrapper to share test #
# code between engine tests #
#################################
#
# Since the master generates row-based events, the slave may not be in
# STATEMENT mode to accept the events.
#
-- source include/have_binlog_format_mixed_or_row.inc
-- source include/have_ndb.inc
-- source include/ndb_master-slave.inc
let $engine_type=NDBCLUSTER;

View file

@ -1,4 +1,7 @@
--source include/have_ndb.inc
# Since the master generates row-based events, the slave must be in
# ROW or MIXED mode to accept the events.
--source include/have_binlog_format_mixed_or_row.inc
--source include/ndb_master-slave.inc
# set up circular replication

View file

@ -1,4 +1,7 @@
--source include/have_ndb.inc
# Since the master generates row-based events, the slave must be in
# ROW or MIXED mode to accept the events.
--source include/have_binlog_format_mixed_or_row.inc
--source include/ndb_master-slave.inc
connection master;
@ -78,3 +81,7 @@ SELECT * FROM t1 ORDER BY a;
--replace_result $MASTER_MYPORT MASTER_PORT
--replace_column 1 # 7 # 8 # 9 # 22 # 23 # 33 # 35 # 36 #
query_vertical SHOW SLAVE STATUS;
connection master;
DROP TABLE t1;
sync_slave_with_master;

View file

@ -4,6 +4,10 @@
# Different engines #
# By JBM 2004-02-15 #
#####################################
# Since the master generates row-based events, the slave must be in
# ROW or MIXED mode to accept the events.
-- source include/have_binlog_format_mixed_or_row.inc
-- source include/have_ndb.inc
-- source include/ndb_master-slave.inc
let $engine_type=NDB;

View file

@ -1,5 +1,8 @@
--source include/have_ucs2.inc
--source include/have_ndb.inc
# Since the master generates row-based events, the slave must be in
# ROW or MIXED mode to accept the events.
--source include/have_binlog_format_mixed_or_row.inc
--source include/ndb_master-slave.inc
#

View file

@ -3,6 +3,9 @@
# Share test code between engine tests #
#########################################
--source include/have_ndb.inc
# Since the master generates row-based events, the slave must be in
# ROW or MIXED mode to accept the events.
--source include/have_binlog_format_mixed_or_row.inc
-- source include/ndb_master-slave.inc
let $engine_type=NDB;
-- source extra/rpl_tests/rpl_delete_no_where.test

View file

@ -6,6 +6,9 @@
##########################################################
--source include/have_ndb.inc
# Since the master generates row-based events, the slave must be in
# ROW or MIXED mode to accept the events.
--source include/have_binlog_format_mixed_or_row.inc
--source include/ndb_master-slave.inc
--disable_warnings

View file

@ -6,6 +6,9 @@
##########################################################
--source include/have_ndb.inc
# Since the master generates row-based events, the slave must be in
# ROW or MIXED mode to accept the events.
--source include/have_binlog_format_mixed_or_row.inc
--source include/ndb_master-slave.inc
--disable_warnings

View file

@ -7,6 +7,9 @@
# reduce test case code #
###################################
-- source include/have_ndb.inc
# Since the master generates row-based events, the slave must be in
# ROW or MIXED mode to accept the events.
-- source include/have_binlog_format_mixed_or_row.inc
-- source include/ndb_master-slave.inc
let $engine_type=NDB;
-- source extra/rpl_tests/rpl_row_func003.test

View file

@ -2,6 +2,9 @@
-- source include/have_ndb.inc
-- source include/have_innodb.inc
# Since the master generates row-based events, the slave must be in
# ROW or MIXED mode to accept the events.
-- source include/have_binlog_format_mixed_or_row.inc
-- source include/ndb_master-slave.inc
create table t1 (a int, unique(a)) engine=ndbcluster;

View file

@ -2,6 +2,9 @@
# Wrapper for rpl_insert_ignore.test#
#####################################
-- source include/have_ndb.inc
# Since the master generates row-based events, the slave must be in
# ROW or MIXED mode to accept the events.
-- source include/have_binlog_format_mixed_or_row.inc
-- source include/ndb_master-slave.inc
let $engine_type=NDB;
let $engine_type2=myisam;

View file

@ -23,6 +23,9 @@
source include/have_ndb.inc;
# Since the master generates row-based events, the slave must be in
# ROW or MIXED mode to accept the events.
source include/have_binlog_format_mixed_or_row.inc;
source include/ndb_master-slave.inc;
source include/have_innodb.inc;

View file

@ -3,6 +3,9 @@
# to reuse test code between engine runs #
############################################################
-- source include/have_ndb.inc
# Since the master generates row-based events, the slave must be in
# ROW or MIXED mode to accept the events.
-- source include/have_binlog_format_mixed_or_row.inc
-- source include/ndb_master-slave.inc
let $engine_type=NDB;
-- source extra/rpl_tests/rpl_multi_update3.test

View file

@ -7,6 +7,9 @@
##########################################################
--source include/have_ndb.inc
# Since the master generates row-based events, the slave must be in
# ROW or MIXED mode to accept the events.
--source include/have_binlog_format_mixed_or_row.inc
--source include/ndb_master-slave.inc
--disable_warnings

View file

@ -2,6 +2,9 @@
# By JBM 2005-02-15 Wrapped to allow reuse of test code#
########################################################
--source include/have_ndb.inc
# Since the master generates row-based events, the slave must be in
# ROW or MIXED mode to accept the events.
--source include/have_binlog_format_mixed_or_row.inc
-- source include/ndb_master-slave.inc
let $engine_type=NDB;
-- source extra/rpl_tests/rpl_row_001.test

View file

@ -5,6 +5,9 @@
# For different engines #
#################################
-- source include/have_ndb.inc
# Since the master generates row-based events, the slave must be in
# ROW or MIXED mode to accept the events.
-- source include/have_binlog_format_mixed_or_row.inc
-- source include/ndb_master-slave.inc
let $engine_type=NDBCLUSTER;
-- source extra/rpl_tests/rpl_row_sp003.test

View file

@ -5,6 +5,9 @@
# For different engines #
#################################
-- source include/have_ndb.inc
# Since the master generates row-based events, the slave must be in
# ROW or MIXED mode to accept the events.
-- source include/have_binlog_format_mixed_or_row.inc
-- source include/ndb_master-slave.inc
let $engine_type=NDBCLUSTER;
-- source extra/rpl_tests/rpl_row_sp006.test

View file

@ -8,6 +8,9 @@
# Includes
-- source include/have_ndb.inc
# Since the master generates row-based events, the slave must be in
# ROW or MIXED mode to accept the events.
-- source include/have_binlog_format_mixed_or_row.inc
-- source include/ndb_master-slave.inc
let $engine_type=NDB;
-- source extra/rpl_tests/rpl_trig004.test

View file

@ -875,8 +875,13 @@ select * from t1;
create view v1 as
select * from v3 where b in (1, 2, 3, 4, 5, 6, 7);
# Disable warnings since LIMIT warning for unsafe statement if
# binlog_format = STATEMENT. Note: after BUG#45832, the warning should
# not be issued.
--disable_warnings
create view v2 as
select v3.a from v3, v1 where v1.a=v3.a and v3.b=3 limit 1;
--enable_warnings
--exec $MYSQL_DUMP --skip-comments test

View file

@ -50,7 +50,7 @@ connection con1;
--echo # connection con1
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
BEGIN;
--error ER_BINLOG_LOGGING_IMPOSSIBLE
--error ER_BINLOG_STMT_MODE_AND_ROW_ENGINE
INSERT INTO t1 VALUES(9);
COMMIT;

View file

@ -1034,8 +1034,8 @@ update_timing_fields_for_event(THD *thd,
Turn off row binlogging of event timing updates. These are not used
for RBR of events replicated to the slave.
*/
if (thd->current_stmt_binlog_row_based)
thd->clear_current_stmt_binlog_row_based();
if (thd->is_current_stmt_binlog_format_row())
thd->clear_current_stmt_binlog_format_row();
DBUG_ASSERT(thd->security_ctx->master_access & SUPER_ACL);

View file

@ -430,8 +430,8 @@ Events::create_event(THD *thd, Event_parse_data *parse_data,
Turn off row binlogging of this statement and use statement-based
so that all supporting tables are updated for CREATE EVENT command.
*/
if (thd->current_stmt_binlog_row_based)
thd->clear_current_stmt_binlog_row_based();
if (thd->is_current_stmt_binlog_format_row())
thd->clear_current_stmt_binlog_format_row();
pthread_mutex_lock(&LOCK_event_metadata);
@ -563,8 +563,8 @@ Events::update_event(THD *thd, Event_parse_data *parse_data,
Turn off row binlogging of this statement and use statement-based
so that all supporting tables are updated for UPDATE EVENT command.
*/
if (thd->current_stmt_binlog_row_based)
thd->clear_current_stmt_binlog_row_based();
if (thd->is_current_stmt_binlog_format_row())
thd->clear_current_stmt_binlog_format_row();
pthread_mutex_lock(&LOCK_event_metadata);
@ -660,8 +660,8 @@ Events::drop_event(THD *thd, LEX_STRING dbname, LEX_STRING name, bool if_exists)
Turn off row binlogging of this statement and use statement-based so
that all supporting tables are updated for DROP EVENT command.
*/
if (thd->current_stmt_binlog_row_based)
thd->clear_current_stmt_binlog_row_based();
if (thd->is_current_stmt_binlog_format_row())
thd->clear_current_stmt_binlog_format_row();
pthread_mutex_lock(&LOCK_event_metadata);
/* On error conditions my_error() is called so no need to handle here */

View file

@ -302,6 +302,7 @@ static void run_query(THD *thd, char *buf, char *end,
thd->transaction.all= save_thd_transaction_all;
thd->transaction.stmt= save_thd_transaction_stmt;
thd->net= save_thd_net;
thd->set_current_stmt_binlog_format_row();
if (thd == injector_thd)
{
@ -3647,6 +3648,7 @@ pthread_handler_t ndb_binlog_thread_func(void *arg)
thd= new THD; /* note that contructor of THD uses DBUG_ */
THD_CHECK_SENTRY(thd);
thd->set_current_stmt_binlog_format_row();
/* We need to set thd->thread_id before thd->store_globals, or it will
set an invalid value for thd->variables.pseudo_thread_id.

View file

@ -6195,7 +6195,7 @@ void ha_partition::get_auto_increment(ulonglong offset, ulonglong increment,
if (!auto_increment_safe_stmt_log_lock &&
thd->lex->sql_command != SQLCOM_INSERT &&
mysql_bin_log.is_open() &&
!thd->current_stmt_binlog_row_based &&
!thd->is_current_stmt_binlog_format_row() &&
(thd->options & OPTION_BIN_LOG))
{
DBUG_PRINT("info", ("locking auto_increment_safe_stmt_log_lock"));

View file

@ -2416,7 +2416,7 @@ int handler::update_auto_increment()
variables->auto_increment_increment);
auto_inc_intervals_count++;
/* Row-based replication does not need to store intervals in binlog */
if (mysql_bin_log.is_open() && !thd->current_stmt_binlog_row_based)
if (mysql_bin_log.is_open() && !thd->is_current_stmt_binlog_format_row())
thd->auto_inc_intervals_in_cur_stmt_for_binlog.append(auto_inc_interval_for_cur_row.minimum(),
auto_inc_interval_for_cur_row.values(),
variables->auto_increment_increment);
@ -4447,7 +4447,7 @@ static bool check_table_binlog_row_based(THD *thd, TABLE *table)
DBUG_ASSERT(table->s->cached_row_logging_check == 0 ||
table->s->cached_row_logging_check == 1);
return (thd->current_stmt_binlog_row_based &&
return (thd->is_current_stmt_binlog_format_row() &&
table->s->cached_row_logging_check &&
(thd->options & OPTION_BIN_LOG) &&
mysql_bin_log.is_open());

View file

@ -2375,10 +2375,11 @@ Create_udf_func::create(THD *thd, udf_func *udf, List<Item> *item_list)
Item *func= NULL;
int arg_count= 0;
DBUG_ENTER("Create_udf_func::create");
if (item_list != NULL)
arg_count= item_list->elements;
thd->lex->set_stmt_unsafe();
thd->lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_UDF);
DBUG_ASSERT( (udf->type == UDFTYPE_FUNCTION)
|| (udf->type == UDFTYPE_AGGREGATE));
@ -2462,7 +2463,7 @@ Create_udf_func::create(THD *thd, udf_func *udf, List<Item> *item_list)
}
}
thd->lex->safe_to_cache_query= 0;
return func;
DBUG_RETURN(func);
}
#endif
@ -3363,9 +3364,10 @@ Create_func_found_rows Create_func_found_rows::s_singleton;
Item*
Create_func_found_rows::create(THD *thd)
{
thd->lex->set_stmt_unsafe();
DBUG_ENTER("Create_func_found_rows::create");
thd->lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_SYSTEM_FUNCTION);
thd->lex->safe_to_cache_query= 0;
return new (thd->mem_root) Item_func_found_rows();
DBUG_RETURN(new (thd->mem_root) Item_func_found_rows());
}
@ -3791,9 +3793,10 @@ Create_func_load_file Create_func_load_file::s_singleton;
Item*
Create_func_load_file::create(THD *thd, Item *arg1)
{
thd->lex->set_stmt_unsafe();
DBUG_ENTER("Create_func_load_file::create");
thd->lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_SYSTEM_FUNCTION);
thd->lex->uncacheable(UNCACHEABLE_SIDEEFFECT);
return new (thd->mem_root) Item_load_file(arg1);
DBUG_RETURN(new (thd->mem_root) Item_load_file(arg1));
}
@ -4260,9 +4263,10 @@ Create_func_row_count Create_func_row_count::s_singleton;
Item*
Create_func_row_count::create(THD *thd)
{
thd->lex->set_stmt_unsafe();
DBUG_ENTER("Create_func_row_count::create");
thd->lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_SYSTEM_FUNCTION);
thd->lex->safe_to_cache_query= 0;
return new (thd->mem_root) Item_func_row_count();
DBUG_RETURN(new (thd->mem_root) Item_func_row_count());
}
@ -4569,9 +4573,10 @@ Create_func_uuid Create_func_uuid::s_singleton;
Item*
Create_func_uuid::create(THD *thd)
{
thd->lex->set_stmt_unsafe();
DBUG_ENTER("Create_func_uuid::create");
thd->lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_SYSTEM_FUNCTION);
thd->lex->safe_to_cache_query= 0;
return new (thd->mem_root) Item_func_uuid();
DBUG_RETURN(new (thd->mem_root) Item_func_uuid());
}
@ -4580,9 +4585,10 @@ Create_func_uuid_short Create_func_uuid_short::s_singleton;
Item*
Create_func_uuid_short::create(THD *thd)
{
thd->lex->set_stmt_unsafe();
DBUG_ENTER("Create_func_uuid_short::create");
thd->lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_SYSTEM_FUNCTION);
thd->lex->safe_to_cache_query= 0;
return new (thd->mem_root) Item_func_uuid_short();
DBUG_RETURN(new (thd->mem_root) Item_func_uuid_short());
}

View file

@ -3837,7 +3837,7 @@ int THD::binlog_write_table_map(TABLE *table, bool is_trans)
table->s->table_map_id));
/* Pre-conditions */
DBUG_ASSERT(current_stmt_binlog_row_based && mysql_bin_log.is_open());
DBUG_ASSERT(is_current_stmt_binlog_format_row() && mysql_bin_log.is_open());
DBUG_ASSERT(table->s->table_map_id != ULONG_MAX);
Table_map_log_event::flag_set const
@ -4114,7 +4114,7 @@ bool MYSQL_BIN_LOG::write(Log_event *event_info)
*/
if (thd)
{
if (!thd->current_stmt_binlog_row_based)
if (!thd->is_current_stmt_binlog_format_row())
{
if (thd->stmt_depends_on_first_successful_insert_id_in_prev_stmt)
{

View file

@ -7223,7 +7223,7 @@ int Rows_log_event::do_apply_event(Relay_log_info const *rli)
We also call the mysql_reset_thd_for_next_command(), since this
is the logical start of the next "statement". Note that this
call might reset the value of current_stmt_binlog_row_based, so
call might reset the value of current_stmt_binlog_format, so
we need to do any changes to that value after this function.
*/
lex_start(thd);
@ -7235,16 +7235,12 @@ int Rows_log_event::do_apply_event(Relay_log_info const *rli)
*/
thd->transaction.stmt.modified_non_trans_table= FALSE;
/*
Check if the slave is set to use SBR. If so, it should switch
to using RBR until the end of the "statement", i.e., next
STMT_END_F or next error.
This is a row injection, so we flag the "statement" as
such. Note that this code is called both when the slave does row
injections and when the BINLOG statement is used to do row
injections.
*/
if (!thd->current_stmt_binlog_row_based &&
mysql_bin_log.is_open() && (thd->options & OPTION_BIN_LOG))
{
thd->set_current_stmt_binlog_row_based();
}
thd->lex->set_stmt_row_injection();
/*
There are a few flags that are replicated with each row event.
@ -7492,7 +7488,14 @@ int Rows_log_event::do_apply_event(Relay_log_info const *rli)
slave_rows_error_report(ERROR_LEVEL, error, rli, thd, table,
get_type_str(),
RPL_LOG_NAME, (ulong) log_pos);
thd->reset_current_stmt_binlog_row_based();
/*
@todo We should probably not call
reset_current_stmt_binlog_format_row() from here.
Note: this applies to log_event_old.cc too.
/Sven
*/
thd->reset_current_stmt_binlog_format_row();
const_cast<Relay_log_info*>(rli)->cleanup_context(thd, error);
thd->is_slave_error= 1;
}
@ -7593,7 +7596,17 @@ static int rows_event_stmt_cleanup(Relay_log_info const *rli, THD * thd)
event flushed.
*/
thd->reset_current_stmt_binlog_row_based();
/*
@todo We should probably not call
reset_current_stmt_binlog_format_row() from here.
Note: this applies to log_event_old.cc too
Btw, the previous comment about transactional engines does not
seem related to anything that happens here.
/Sven
*/
thd->reset_current_stmt_binlog_format_row();
const_cast<Relay_log_info*>(rli)->cleanup_context(thd, 0);
}

View file

@ -59,22 +59,19 @@ Old_rows_log_event::do_apply_event(Old_rows_log_event *ev, const Relay_log_info
We also call the mysql_reset_thd_for_next_command(), since this
is the logical start of the next "statement". Note that this
call might reset the value of current_stmt_binlog_row_based, so
call might reset the value of current_stmt_binlog_format, so
we need to do any changes to that value after this function.
*/
lex_start(thd);
mysql_reset_thd_for_next_command(thd);
/*
Check if the slave is set to use SBR. If so, it should switch
to using RBR until the end of the "statement", i.e., next
STMT_END_F or next error.
This is a row injection, so we flag the "statement" as
such. Note that this code is called both when the slave does row
injections and when the BINLOG statement is used to do row
injections.
*/
if (!thd->current_stmt_binlog_row_based &&
mysql_bin_log.is_open() && (thd->options & OPTION_BIN_LOG))
{
thd->set_current_stmt_binlog_row_based();
}
thd->lex->set_stmt_row_injection();
if (simple_open_n_lock_tables(thd, rli->tables_to_lock))
{
@ -263,7 +260,7 @@ Old_rows_log_event::do_apply_event(Old_rows_log_event *ev, const Relay_log_info
thread is certainly going to stop.
rollback at the caller along with sbr.
*/
thd->reset_current_stmt_binlog_row_based();
thd->reset_current_stmt_binlog_format_row();
const_cast<Relay_log_info*>(rli)->cleanup_context(thd, error);
thd->is_slave_error= 1;
DBUG_RETURN(error);
@ -1781,7 +1778,7 @@ int Old_rows_log_event::do_apply_event(Relay_log_info const *rli)
thread is certainly going to stop.
rollback at the caller along with sbr.
*/
thd->reset_current_stmt_binlog_row_based();
thd->reset_current_stmt_binlog_format_row();
const_cast<Relay_log_info*>(rli)->cleanup_context(thd, error);
thd->is_slave_error= 1;
DBUG_RETURN(error);
@ -1881,7 +1878,7 @@ Old_rows_log_event::do_update_pos(Relay_log_info *rli)
event flushed.
*/
thd->reset_current_stmt_binlog_row_based();
thd->reset_current_stmt_binlog_format_row();
rli->cleanup_context(thd, 0);
if (error == 0)
{

View file

@ -1566,7 +1566,6 @@ TABLE *open_n_lock_single_table(THD *thd, TABLE_LIST *table_l,
thr_lock_type lock_type);
bool open_normal_and_derived_tables(THD *thd, TABLE_LIST *tables, uint flags);
int lock_tables(THD *thd, TABLE_LIST *tables, uint counter, bool *need_reopen);
int decide_logging_format(THD *thd, TABLE_LIST *tables);
TABLE *open_temporary_table(THD *thd, const char *path, const char *db,
const char *table_name, bool link_in_list);
bool rm_temporary_table(handlerton *base, char *path);

View file

@ -36,8 +36,6 @@ injector::transaction::transaction(MYSQL_BIN_LOG *log, THD *thd)
m_start_pos.m_file_pos= log_info.pos;
begin_trans(m_thd);
thd->set_current_stmt_binlog_row_based();
}
injector::transaction::~transaction()

View file

@ -1292,7 +1292,12 @@ bool sys_var_thd_binlog_format::is_readonly() const
void fix_binlog_format_after_update(THD *thd, enum_var_type type)
{
thd->reset_current_stmt_binlog_row_based();
/*
@todo This function should be eliminated. We should not set the
current binlog format anywhere else than in decide_logging_format.
/Sven
*/
thd->reset_current_stmt_binlog_format_row();
}

Some files were not shown because too many files have changed in this diff Show more