diff --git a/mysql-test/suite/binlog/r/binlog_switch_inside_trans.result b/mysql-test/suite/binlog/r/binlog_switch_inside_trans.result index 57feb3f50f0..de224a190c2 100644 --- a/mysql-test/suite/binlog/r/binlog_switch_inside_trans.result +++ b/mysql-test/suite/binlog/r/binlog_switch_inside_trans.result @@ -5,9 +5,14 @@ create table t2 (a int) engine= innodb; SELECT @@session.binlog_format; @@session.binlog_format ROW +SELECT @@session.binlog_direct_non_transactional_updates; +@@session.binlog_direct_non_transactional_updates +1 SET AUTOCOMMIT=1; -# Test that the session variable 'binlog_format' -# is writable outside a transaction. +# Test that the session variable 'binlog_format' and +# 'binlog_direct_non_transactional_updates' are +# writable outside a transaction. +# Current session values are ROW and FALSE, respectively. set @@session.binlog_format= statement; set @@session.binlog_direct_non_transactional_updates= TRUE; SELECT @@session.binlog_format; @@ -17,15 +22,19 @@ SELECT @@session.binlog_direct_non_transactional_updates; @@session.binlog_direct_non_transactional_updates 1 begin; -# Test that the session variable 'binlog_format' is read-only -# inside a transaction with no preceding updates. +# Test that the session variable 'binlog_format' and +# 'binlog_direct_non_transactional_updates' are +# read-only inside a transaction with no preceding updates. +# Current session values are STATEMENT and TRUE, respectively. set @@session.binlog_format= mixed; ERROR HY000: Cannot modify @@session.binlog_format inside a transaction set @@session.binlog_direct_non_transactional_updates= FALSE; ERROR HY000: Cannot modify @@session.binlog_direct_non_transactional_updates inside a transaction insert into t2 values (1); -# Test that the session variable 'binlog_format' is read-only -# inside a transaction with preceding transactional updates. +# Test that the session variable 'binlog_format' and +# 'binlog_direct_non_transactional_updates' are +# read-only inside a transaction with preceding transactional updates. +# Current session values are STATEMENT and TRUE, respectively. set @@session.binlog_format= row; ERROR HY000: Cannot modify @@session.binlog_format inside a transaction set @@session.binlog_direct_non_transactional_updates= FALSE; @@ -33,15 +42,19 @@ ERROR HY000: Cannot modify @@session.binlog_direct_non_transactional_updates ins commit; begin; insert into t1 values (2); -# Test that the session variable 'binlog_format' is read-only -# inside a transaction with preceding non-transactional updates. -set @@session.binlog_format= statement; +# Test that the session variable 'binlog_format' and +# 'binlog_direct_non_transactional_updates' are +# read-only inside a transaction with preceding non-transactional updates. +# Current session values are STATEMENT and TRUE, respectively. +set @@session.binlog_format= mixed; ERROR HY000: Cannot modify @@session.binlog_format inside a transaction set @@session.binlog_direct_non_transactional_updates= FALSE; ERROR HY000: Cannot modify @@session.binlog_direct_non_transactional_updates inside a transaction commit; -# Test that the session variable 'binlog_format' is writable -# when AUTOCOMMIT=0, before a transaction has started. +# Test that the session variable 'binlog_format' and +# 'binlog_direct_non_transactional_updates' are +# writable when AUTOCOMMIT=0, before a transaction has started. +# Current session values are STATEMENT and TRUE, respectively. set AUTOCOMMIT=0; set @@session.binlog_format= row; set @@session.binlog_direct_non_transactional_updates= FALSE; @@ -51,9 +64,12 @@ ROW SELECT @@session.binlog_direct_non_transactional_updates; @@session.binlog_direct_non_transactional_updates 0 -insert into t1 values (4); -# Test that the session variable 'binlog_format' is read-only inside an -# AUTOCOMMIT=0 transaction with preceding non-transactional updates. +insert into t1 values (3); +# Test that the session variable 'binlog_format' and +# 'binlog_direct_non_transactional_updates' are +# read-only inside an AUTOCOMMIT=0 transaction +# with preceding non-transactional updates. +# Current session values are ROW and FALSE, respectively. set @@session.binlog_format= statement; ERROR HY000: Cannot modify @@session.binlog_format inside a transaction set @@session.binlog_direct_non_transactional_updates= TRUE; @@ -65,10 +81,13 @@ SELECT @@session.binlog_direct_non_transactional_updates; @@session.binlog_direct_non_transactional_updates 0 commit; -insert into t2 values (5); -# Test that the session variable 'binlog_format' is read-only inside an -# AUTOCOMMIT=0 transaction with preceding transactional updates. -set @@session.binlog_format= row; +insert into t2 values (4); +# Test that the session variable 'binlog_format' and +# 'binlog_direct_non_transactional_updates' are +# read-only inside an AUTOCOMMIT=0 transaction with +# preceding transactional updates. +# Current session values are ROW and FALSE, respectively. +set @@session.binlog_format= statement; ERROR HY000: Cannot modify @@session.binlog_format inside a transaction set @@session.binlog_direct_non_transactional_updates= TRUE; ERROR HY000: Cannot modify @@session.binlog_direct_non_transactional_updates inside a transaction @@ -80,9 +99,11 @@ SELECT @@session.binlog_direct_non_transactional_updates; 0 commit; begin; -insert into t2 values (6); -# Test that the global variable 'binlog_format' is writable -# inside a transaction. +insert into t2 values (5); +# Test that the global variable 'binlog_format' and +# 'binlog_direct_non_transactional_updates' are +# writable inside a transaction. +# Current session values are ROW and FALSE, respectively. SELECT @@global.binlog_format; @@global.binlog_format ROW @@ -96,18 +117,19 @@ SELECT @@global.binlog_direct_non_transactional_updates; 1 commit; set @@global.binlog_format= @save_binlog_format; -set @@global.binlog_direct_non_transactional_updates= @save_binlog_dirct; +set @@global.binlog_direct_non_transactional_updates= @save_binlog_dirct; create table t3(a int, b int) engine= innodb; create table t4(a int) engine= innodb; create table t5(a int) engine= innodb; create trigger tr1 after insert on t3 for each row begin insert into t4(a) values(1); -set @@session.binlog_format= statement; +set @@session.binlog_format= statement; insert into t4(a) values(2); insert into t5(a) values(3); end | # Test that the session variable 'binlog_format' is read-only # in sub-statements. +# Current session value is ROW. insert into t3(a,b) values(1,1); ERROR HY000: Cannot change the binary logging format inside a stored function or trigger SELECT @@session.binlog_format; @@ -118,12 +140,14 @@ create table t7(a int) engine= innodb; create table t8(a int) engine= innodb; create trigger tr2 after insert on t6 for each row begin insert into t7(a) values(1); -set @@global.binlog_direct_non_transactional_updates= FALSE; +set @@session.binlog_direct_non_transactional_updates= TRUE; insert into t7(a) values(2); insert into t8(a) values(3); end | -# Test that the session variable 'binlog_format' is read-only -# in sub-statements. +# Test that the session variable +# 'binlog_direct_non_transactional_updates' is +# read-only in sub-statements. +# Current session value is FALSE. insert into t6(a,b) values(1,1); ERROR HY000: Cannot change the binlog direct flag inside a stored function or trigger SELECT @@session.binlog_direct_non_transactional_updates; diff --git a/mysql-test/suite/binlog/t/binlog_switch_inside_trans.test b/mysql-test/suite/binlog/t/binlog_switch_inside_trans.test index 7b98b5cd0d5..cdc94198933 100644 --- a/mysql-test/suite/binlog/t/binlog_switch_inside_trans.test +++ b/mysql-test/suite/binlog/t/binlog_switch_inside_trans.test @@ -1,7 +1,8 @@ # # BUG#47863 -# This test verifies if the session variable 'binlog_format' -# is read-only inside a transaction and in sub-statements. +# This test verifies if the session variable 'binlog_format' and +# 'binlog_direct_non_transactional_updates' are read-only inside +# a transaction and in sub-statements. # source include/have_innodb.inc; @@ -13,25 +14,32 @@ create table t1 (a int) engine= myisam; create table t2 (a int) engine= innodb; SELECT @@session.binlog_format; +SELECT @@session.binlog_direct_non_transactional_updates; SET AUTOCOMMIT=1; ---echo # Test that the session variable 'binlog_format' ---echo # is writable outside a transaction. +--echo # Test that the session variable 'binlog_format' and +--echo # 'binlog_direct_non_transactional_updates' are +--echo # writable outside a transaction. +--echo # Current session values are ROW and FALSE, respectively. set @@session.binlog_format= statement; set @@session.binlog_direct_non_transactional_updates= TRUE; SELECT @@session.binlog_format; SELECT @@session.binlog_direct_non_transactional_updates; begin; ---echo # Test that the session variable 'binlog_format' is read-only ---echo # inside a transaction with no preceding updates. +--echo # Test that the session variable 'binlog_format' and +--echo # 'binlog_direct_non_transactional_updates' are +--echo # read-only inside a transaction with no preceding updates. +--echo # Current session values are STATEMENT and TRUE, respectively. --error ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_BINLOG_FORMAT set @@session.binlog_format= mixed; --error ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_BINLOG_DIRECT set @@session.binlog_direct_non_transactional_updates= FALSE; insert into t2 values (1); ---echo # Test that the session variable 'binlog_format' is read-only ---echo # inside a transaction with preceding transactional updates. +--echo # Test that the session variable 'binlog_format' and +--echo # 'binlog_direct_non_transactional_updates' are +--echo # read-only inside a transaction with preceding transactional updates. +--echo # Current session values are STATEMENT and TRUE, respectively. --error ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_BINLOG_FORMAT set @@session.binlog_format= row; --error ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_BINLOG_DIRECT @@ -40,25 +48,32 @@ commit; begin; insert into t1 values (2); ---echo # Test that the session variable 'binlog_format' is read-only ---echo # inside a transaction with preceding non-transactional updates. +--echo # Test that the session variable 'binlog_format' and +--echo # 'binlog_direct_non_transactional_updates' are +--echo # read-only inside a transaction with preceding non-transactional updates. +--echo # Current session values are STATEMENT and TRUE, respectively. --error ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_BINLOG_FORMAT - set @@session.binlog_format= statement; + set @@session.binlog_format= mixed; --error ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_BINLOG_DIRECT set @@session.binlog_direct_non_transactional_updates= FALSE; commit; ---echo # Test that the session variable 'binlog_format' is writable ---echo # when AUTOCOMMIT=0, before a transaction has started. +--echo # Test that the session variable 'binlog_format' and +--echo # 'binlog_direct_non_transactional_updates' are +--echo # writable when AUTOCOMMIT=0, before a transaction has started. +--echo # Current session values are STATEMENT and TRUE, respectively. set AUTOCOMMIT=0; set @@session.binlog_format= row; set @@session.binlog_direct_non_transactional_updates= FALSE; SELECT @@session.binlog_format; SELECT @@session.binlog_direct_non_transactional_updates; -insert into t1 values (4); ---echo # Test that the session variable 'binlog_format' is read-only inside an ---echo # AUTOCOMMIT=0 transaction with preceding non-transactional updates. +insert into t1 values (3); +--echo # Test that the session variable 'binlog_format' and +--echo # 'binlog_direct_non_transactional_updates' are +--echo # read-only inside an AUTOCOMMIT=0 transaction +--echo # with preceding non-transactional updates. +--echo # Current session values are ROW and FALSE, respectively. --error ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_BINLOG_FORMAT set @@session.binlog_format= statement; --error ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_BINLOG_DIRECT @@ -67,11 +82,14 @@ SELECT @@session.binlog_format; SELECT @@session.binlog_direct_non_transactional_updates; commit; -insert into t2 values (5); ---echo # Test that the session variable 'binlog_format' is read-only inside an ---echo # AUTOCOMMIT=0 transaction with preceding transactional updates. +insert into t2 values (4); +--echo # Test that the session variable 'binlog_format' and +--echo # 'binlog_direct_non_transactional_updates' are +--echo # read-only inside an AUTOCOMMIT=0 transaction with +--echo # preceding transactional updates. +--echo # Current session values are ROW and FALSE, respectively. --error ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_BINLOG_FORMAT -set @@session.binlog_format= row; +set @@session.binlog_format= statement; --error ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_BINLOG_DIRECT set @@session.binlog_direct_non_transactional_updates= TRUE; SELECT @@session.binlog_format; @@ -79,9 +97,11 @@ SELECT @@session.binlog_direct_non_transactional_updates; commit; begin; - insert into t2 values (6); ---echo # Test that the global variable 'binlog_format' is writable ---echo # inside a transaction. + insert into t2 values (5); +--echo # Test that the global variable 'binlog_format' and +--echo # 'binlog_direct_non_transactional_updates' are +--echo # writable inside a transaction. +--echo # Current session values are ROW and FALSE, respectively. SELECT @@global.binlog_format; set @@global.binlog_format= statement; set @@global.binlog_direct_non_transactional_updates= TRUE; @@ -90,7 +110,7 @@ begin; commit; set @@global.binlog_format= @save_binlog_format; -set @@global.binlog_direct_non_transactional_updates= @save_binlog_dirct; +set @@global.binlog_direct_non_transactional_updates= @save_binlog_dirct; create table t3(a int, b int) engine= innodb; create table t4(a int) engine= innodb; @@ -98,7 +118,7 @@ create table t5(a int) engine= innodb; delimiter |; eval create trigger tr1 after insert on t3 for each row begin insert into t4(a) values(1); - set @@session.binlog_format= statement; + set @@session.binlog_format= statement; insert into t4(a) values(2); insert into t5(a) values(3); end | @@ -106,6 +126,7 @@ delimiter ;| --echo # Test that the session variable 'binlog_format' is read-only --echo # in sub-statements. +--echo # Current session value is ROW. --error ER_STORED_FUNCTION_PREVENTS_SWITCH_BINLOG_FORMAT insert into t3(a,b) values(1,1); SELECT @@session.binlog_format; @@ -116,14 +137,16 @@ create table t8(a int) engine= innodb; delimiter |; eval create trigger tr2 after insert on t6 for each row begin insert into t7(a) values(1); - set @@global.binlog_direct_non_transactional_updates= FALSE; + set @@session.binlog_direct_non_transactional_updates= TRUE; insert into t7(a) values(2); insert into t8(a) values(3); end | delimiter ;| ---echo # Test that the session variable 'binlog_format' is read-only ---echo # in sub-statements. +--echo # Test that the session variable +--echo # 'binlog_direct_non_transactional_updates' is +--echo # read-only in sub-statements. +--echo # Current session value is FALSE. --error ER_STORED_FUNCTION_PREVENTS_SWITCH_BINLOG_DIRECT insert into t6(a,b) values(1,1); SELECT @@session.binlog_direct_non_transactional_updates; diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc index e14286210b4..76f73765692 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -241,6 +241,12 @@ static bool check_has_super(sys_var *self, THD *thd, set_var *var) } static bool binlog_format_check(sys_var *self, THD *thd, set_var *var) { + if (check_has_super(self, thd, var)) + return true; + + if (var->type == OPT_GLOBAL) + return false; + /* If RBR and open temporary tables, their CREATE TABLE may not be in the binlog, so we can't toggle to SBR in this connection. @@ -272,18 +278,12 @@ static bool binlog_format_check(sys_var *self, THD *thd, set_var *var) /* Make the session variable 'binlog_format' read-only inside a transaction. */ - if (thd->active_transaction() && (var->type == OPT_SESSION)) + if (thd->active_transaction()) { my_error(ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_BINLOG_FORMAT, MYF(0)); return true; } - if (check_has_super(self, thd, var)) - return true; - if (var->type == OPT_GLOBAL || - (thd->variables.binlog_format == var->save_result.ulonglong_value)) - return false; - return false; } @@ -312,15 +312,12 @@ static Sys_var_enum Sys_binlog_format( static bool binlog_direct_check(sys_var *self, THD *thd, set_var *var) { - /* - Makes the session variable 'binlog_direct_non_transactional_updates' - read-only inside a transaction. - */ - if (thd->active_transaction() && (var->type == OPT_SESSION)) - { - my_error(ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_BINLOG_DIRECT, MYF(0)); - return 1; - } + if (check_has_super(self, thd, var)) + return true; + + if (var->type == OPT_GLOBAL) + return false; + /* Makes the session variable 'binlog_direct_non_transactional_updates' read-only if within a procedure, trigger or function. @@ -328,15 +325,17 @@ static bool binlog_direct_check(sys_var *self, THD *thd, set_var *var) if (thd->in_sub_stmt) { my_error(ER_STORED_FUNCTION_PREVENTS_SWITCH_BINLOG_DIRECT, MYF(0)); - return 1; + return true; + } + /* + Makes the session variable 'binlog_direct_non_transactional_updates' + read-only inside a transaction. + */ + if (thd->active_transaction()) + { + my_error(ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_BINLOG_DIRECT, MYF(0)); + return true; } - - if (check_has_super(self, thd, var)) - return true; - if (var->type == OPT_GLOBAL || - (thd->variables.binlog_direct_non_trans_update == - static_cast(var->save_result.ulonglong_value))) - return false; return false; }