Commit 1a3c03db authored by Alfranio Correia's avatar Alfranio Correia

auto-merge mysql-trunk-bugfixing (local) --> mysql-trunk-bugfixing

parents 7714d4e2 2b89bd9f
...@@ -1767,7 +1767,7 @@ sync_slave_with_master; ...@@ -1767,7 +1767,7 @@ sync_slave_with_master;
--exec $MYSQL_DUMP --compact --order-by-primary --skip-extended-insert --no-create-info test > $MYSQLTEST_VARDIR/tmp/test-nmt-master.sql --exec $MYSQL_DUMP --compact --order-by-primary --skip-extended-insert --no-create-info test > $MYSQLTEST_VARDIR/tmp/test-nmt-master.sql
--exec $MYSQL_DUMP_SLAVE --compact --order-by-primary --skip-extended-insert --no-create-info test > $MYSQLTEST_VARDIR/tmp/test-nmt-slave.sql --exec $MYSQL_DUMP_SLAVE --compact --order-by-primary --skip-extended-insert --no-create-info test > $MYSQLTEST_VARDIR/tmp/test-nmt-slave.sql
if (`select @@session.binlog_format != 'STATEMENT'`) if (`select @@session.binlog_direct_non_transactional_updates = 0 || @@session.binlog_format != 'STATEMENT'`)
{ {
--diff_files $MYSQLTEST_VARDIR/tmp/test-nmt-master.sql $MYSQLTEST_VARDIR/tmp/test-nmt-slave.sql --diff_files $MYSQLTEST_VARDIR/tmp/test-nmt-master.sql $MYSQLTEST_VARDIR/tmp/test-nmt-slave.sql
} }
......
...@@ -8,14 +8,14 @@ INSERT INTO t1b VALUES (1,1), (1,2), (2,1), (2,2); ...@@ -8,14 +8,14 @@ INSERT INTO t1b VALUES (1,1), (1,2), (2,1), (2,2);
INSERT INTO t1m VALUES (1,1), (1,2), (2,1), (2,2); INSERT INTO t1m VALUES (1,1), (1,2), (2,1), (2,2);
UPDATE t1m, t1b SET m = 2, b = 3 WHERE n = c; UPDATE t1m, t1b SET m = 2, b = 3 WHERE n = c;
Warnings: Warnings:
Note 1592 Unsafe statement binlogged in statement format since BINLOG_FORMAT = STATEMENT. Reason for unsafeness: Non-transactional reads or writes are unsafe if they occur after transactional reads or writes inside a transaction. Note 1592 Unsafe statement binlogged in statement format since BINLOG_FORMAT = STATEMENT. Reason for unsafeness: Statements that read from both transactional and non-transactional tables and write to any of them are unsafe.
The last event before the COMMIT is use `test`; UPDATE t1m, t1b SET m = 2, b = 3 WHERE n = c The last event before the COMMIT is use `test`; UPDATE t1m, t1b SET m = 2, b = 3 WHERE n = c
*** Please look in binlog_multi_engine.test if you have a diff here **** *** Please look in binlog_multi_engine.test if you have a diff here ****
START TRANSACTION; START TRANSACTION;
INSERT INTO t1n 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; UPDATE t1m, t1n SET m = 2, e = 3 WHERE n = f;
Warnings: Warnings:
Note 1592 Unsafe statement binlogged in statement format since BINLOG_FORMAT = STATEMENT. Reason for unsafeness: Non-transactional reads or writes are unsafe if they occur after transactional reads or writes inside a transaction. Note 1592 Unsafe statement binlogged in statement format since BINLOG_FORMAT = STATEMENT. Reason for unsafeness: Statements that read from both transactional and non-transactional tables and write to any of them are unsafe.
UPDATE t1n, t1b SET e = 2, b = 3 WHERE f = c; UPDATE t1n, t1b SET e = 2, b = 3 WHERE f = c;
COMMIT; COMMIT;
TRUNCATE t1m; TRUNCATE t1m;
......
...@@ -8,7 +8,7 @@ begin; ...@@ -8,7 +8,7 @@ begin;
insert into t1 values(1); insert into t1 values(1);
insert into t2 select * from t1; insert into t2 select * from t1;
Warnings: Warnings:
Note 1592 Unsafe statement binlogged in statement format since BINLOG_FORMAT = STATEMENT. Reason for unsafeness: Non-transactional reads or writes are unsafe if they occur after transactional reads or writes inside a transaction. Note 1592 Unsafe statement binlogged in statement format since BINLOG_FORMAT = STATEMENT. Reason for unsafeness: Statements that read from both transactional and non-transactional tables and write to any of them are unsafe.
commit; commit;
show binlog events from <binlog_start>; show binlog events from <binlog_start>;
Log_name Pos Event_type Server_id End_log_pos Info Log_name Pos Event_type Server_id End_log_pos Info
...@@ -23,7 +23,7 @@ begin; ...@@ -23,7 +23,7 @@ begin;
insert into t1 values(2); insert into t1 values(2);
insert into t2 select * from t1; insert into t2 select * from t1;
Warnings: Warnings:
Note 1592 Unsafe statement binlogged in statement format since BINLOG_FORMAT = STATEMENT. Reason for unsafeness: Non-transactional reads or writes are unsafe if they occur after transactional reads or writes inside a transaction. Note 1592 Unsafe statement binlogged in statement format since BINLOG_FORMAT = STATEMENT. Reason for unsafeness: Statements that read from both transactional and non-transactional tables and write to any of them are unsafe.
rollback; rollback;
Warnings: Warnings:
Warning 1196 Some non-transactional changed tables couldn't be rolled back Warning 1196 Some non-transactional changed tables couldn't be rolled back
...@@ -42,7 +42,7 @@ savepoint my_savepoint; ...@@ -42,7 +42,7 @@ savepoint my_savepoint;
insert into t1 values(4); insert into t1 values(4);
insert into t2 select * from t1; insert into t2 select * from t1;
Warnings: Warnings:
Note 1592 Unsafe statement binlogged in statement format since BINLOG_FORMAT = STATEMENT. Reason for unsafeness: Non-transactional reads or writes are unsafe if they occur after transactional reads or writes inside a transaction. Note 1592 Unsafe statement binlogged in statement format since BINLOG_FORMAT = STATEMENT. Reason for unsafeness: Statements that read from both transactional and non-transactional tables and write to any of them are unsafe.
rollback to savepoint my_savepoint; rollback to savepoint my_savepoint;
Warnings: Warnings:
Warning 1196 Some non-transactional changed tables couldn't be rolled back Warning 1196 Some non-transactional changed tables couldn't be rolled back
...@@ -65,7 +65,7 @@ savepoint my_savepoint; ...@@ -65,7 +65,7 @@ savepoint my_savepoint;
insert into t1 values(6); insert into t1 values(6);
insert into t2 select * from t1; insert into t2 select * from t1;
Warnings: Warnings:
Note 1592 Unsafe statement binlogged in statement format since BINLOG_FORMAT = STATEMENT. Reason for unsafeness: Non-transactional reads or writes are unsafe if they occur after transactional reads or writes inside a transaction. Note 1592 Unsafe statement binlogged in statement format since BINLOG_FORMAT = STATEMENT. Reason for unsafeness: Statements that read from both transactional and non-transactional tables and write to any of them are unsafe.
rollback to savepoint my_savepoint; rollback to savepoint my_savepoint;
Warnings: Warnings:
Warning 1196 Some non-transactional changed tables couldn't be rolled back Warning 1196 Some non-transactional changed tables couldn't be rolled back
...@@ -95,7 +95,7 @@ begin; ...@@ -95,7 +95,7 @@ begin;
insert into t1 values(8); insert into t1 values(8);
insert into t2 select * from t1; insert into t2 select * from t1;
Warnings: Warnings:
Note 1592 Unsafe statement binlogged in statement format since BINLOG_FORMAT = STATEMENT. Reason for unsafeness: Non-transactional reads or writes are unsafe if they occur after transactional reads or writes inside a transaction. Note 1592 Unsafe statement binlogged in statement format since BINLOG_FORMAT = STATEMENT. Reason for unsafeness: Statements that read from both transactional and non-transactional tables and write to any of them are unsafe.
select get_lock("a",10); select get_lock("a",10);
get_lock("a",10) get_lock("a",10)
1 1
...@@ -111,7 +111,7 @@ reset master; ...@@ -111,7 +111,7 @@ reset master;
insert into t1 values(9); insert into t1 values(9);
insert into t2 select * from t1; insert into t2 select * from t1;
Warnings: Warnings:
Note 1592 Unsafe statement binlogged in statement format since BINLOG_FORMAT = STATEMENT. Reason for unsafeness: Non-transactional reads or writes are unsafe if they occur after transactional reads or writes inside a transaction. Note 1592 Unsafe statement binlogged in statement format since BINLOG_FORMAT = STATEMENT. Reason for unsafeness: Statements that read from both transactional and non-transactional tables and write to any of them are unsafe.
show binlog events from <binlog_start>; show binlog events from <binlog_start>;
Log_name Pos Event_type Server_id End_log_pos Info Log_name Pos Event_type Server_id End_log_pos Info
master-bin.000001 # Query # # BEGIN master-bin.000001 # Query # # BEGIN
...@@ -127,7 +127,7 @@ insert into t1 values(10); ...@@ -127,7 +127,7 @@ insert into t1 values(10);
begin; begin;
insert into t2 select * from t1; insert into t2 select * from t1;
Warnings: Warnings:
Note 1592 Unsafe statement binlogged in statement format since BINLOG_FORMAT = STATEMENT. Reason for unsafeness: Non-transactional reads or writes are unsafe if they occur after transactional reads or writes inside a transaction. Note 1592 Unsafe statement binlogged in statement format since BINLOG_FORMAT = STATEMENT. Reason for unsafeness: Statements that read from both transactional and non-transactional tables and write to any of them are unsafe.
show binlog events from <binlog_start>; show binlog events from <binlog_start>;
Log_name Pos Event_type Server_id End_log_pos Info Log_name Pos Event_type Server_id End_log_pos Info
master-bin.000001 # Query # # BEGIN master-bin.000001 # Query # # BEGIN
...@@ -427,7 +427,7 @@ begin; ...@@ -427,7 +427,7 @@ begin;
insert into t1 values(8); insert into t1 values(8);
insert into t2 select * from t1; insert into t2 select * from t1;
Warnings: Warnings:
Note 1592 Unsafe statement binlogged in statement format since BINLOG_FORMAT = STATEMENT. Reason for unsafeness: Non-transactional reads or writes are unsafe if they occur after transactional reads or writes inside a transaction. Note 1592 Unsafe statement binlogged in statement format since BINLOG_FORMAT = STATEMENT. Reason for unsafeness: Statements that read from both transactional and non-transactional tables and write to any of them are unsafe.
select get_lock("a",10); select get_lock("a",10);
get_lock("a",10) get_lock("a",10)
1 1
...@@ -454,7 +454,7 @@ insert into ti values (1); ...@@ -454,7 +454,7 @@ insert into ti values (1);
insert into ti values (2) ; insert into ti values (2) ;
insert into tt select * from ti; insert into tt select * from ti;
Warnings: Warnings:
Note 1592 Unsafe statement binlogged in statement format since BINLOG_FORMAT = STATEMENT. Reason for unsafeness: Non-transactional reads or writes are unsafe if they occur after transactional reads or writes inside a transaction. Note 1592 Unsafe statement binlogged in statement format since BINLOG_FORMAT = STATEMENT. Reason for unsafeness: Statements that read from both transactional and non-transactional tables and write to any of them are unsafe.
rollback; rollback;
Warnings: Warnings:
Warning 1196 Some non-transactional changed tables couldn't be rolled back Warning 1196 Some non-transactional changed tables couldn't be rolled back
...@@ -473,7 +473,7 @@ count(*) ...@@ -473,7 +473,7 @@ count(*)
0 0
insert into ti select * from tt; insert into ti select * from tt;
Warnings: Warnings:
Note 1592 Unsafe statement binlogged in statement format since BINLOG_FORMAT = STATEMENT. Reason for unsafeness: Non-transactional reads or writes are unsafe if they occur after transactional reads or writes inside a transaction. Note 1592 Unsafe statement binlogged in statement format since BINLOG_FORMAT = STATEMENT. Reason for unsafeness: Statements that read from both transactional and non-transactional tables and write to any of them are unsafe.
select * from ti /* that is what slave would miss - a bug */; select * from ti /* that is what slave would miss - a bug */;
a a
1 1
...@@ -501,7 +501,7 @@ count(*) ...@@ -501,7 +501,7 @@ count(*)
0 0
insert into ti select * from tt; insert into ti select * from tt;
Warnings: Warnings:
Note 1592 Unsafe statement binlogged in statement format since BINLOG_FORMAT = STATEMENT. Reason for unsafeness: Non-transactional reads or writes are unsafe if they occur after transactional reads or writes inside a transaction. Note 1592 Unsafe statement binlogged in statement format since BINLOG_FORMAT = STATEMENT. Reason for unsafeness: Statements that read from both transactional and non-transactional tables and write to any of them are unsafe.
select * from tt /* that is what otherwise slave missed - the bug */; select * from tt /* that is what otherwise slave missed - the bug */;
a a
1 1
...@@ -718,7 +718,7 @@ insert into ti values (1); ...@@ -718,7 +718,7 @@ insert into ti values (1);
insert into ti values (2) ; insert into ti values (2) ;
insert into tt select * from ti; insert into tt select * from ti;
Warnings: Warnings:
Note 1592 Unsafe statement binlogged in statement format since BINLOG_FORMAT = STATEMENT. Reason for unsafeness: Non-transactional reads or writes are unsafe if they occur after transactional reads or writes inside a transaction. Note 1592 Unsafe statement binlogged in statement format since BINLOG_FORMAT = STATEMENT. Reason for unsafeness: Statements that read from both transactional and non-transactional tables and write to any of them are unsafe.
rollback; rollback;
Warnings: Warnings:
Warning 1196 Some non-transactional changed tables couldn't be rolled back Warning 1196 Some non-transactional changed tables couldn't be rolled back
...@@ -737,7 +737,7 @@ count(*) ...@@ -737,7 +737,7 @@ count(*)
0 0
insert into ti select * from tt; insert into ti select * from tt;
Warnings: Warnings:
Note 1592 Unsafe statement binlogged in statement format since BINLOG_FORMAT = STATEMENT. Reason for unsafeness: Non-transactional reads or writes are unsafe if they occur after transactional reads or writes inside a transaction. Note 1592 Unsafe statement binlogged in statement format since BINLOG_FORMAT = STATEMENT. Reason for unsafeness: Statements that read from both transactional and non-transactional tables and write to any of them are unsafe.
select * from ti /* that is what slave would miss - bug#28960 */; select * from ti /* that is what slave would miss - bug#28960 */;
a a
1 1
...@@ -765,7 +765,7 @@ count(*) ...@@ -765,7 +765,7 @@ count(*)
0 0
insert into ti select * from tt; insert into ti select * from tt;
Warnings: Warnings:
Note 1592 Unsafe statement binlogged in statement format since BINLOG_FORMAT = STATEMENT. Reason for unsafeness: Non-transactional reads or writes are unsafe if they occur after transactional reads or writes inside a transaction. Note 1592 Unsafe statement binlogged in statement format since BINLOG_FORMAT = STATEMENT. Reason for unsafeness: Statements that read from both transactional and non-transactional tables and write to any of them are unsafe.
select * from tt /* that is what otherwise slave missed - the bug */; select * from tt /* that is what otherwise slave missed - the bug */;
a a
1 1
......
...@@ -5,9 +5,14 @@ create table t2 (a int) engine= innodb; ...@@ -5,9 +5,14 @@ create table t2 (a int) engine= innodb;
SELECT @@session.binlog_format; SELECT @@session.binlog_format;
@@session.binlog_format @@session.binlog_format
ROW ROW
SELECT @@session.binlog_direct_non_transactional_updates;
@@session.binlog_direct_non_transactional_updates
1
SET AUTOCOMMIT=1; SET AUTOCOMMIT=1;
# Test that the session variable 'binlog_format' # Test that the session variable 'binlog_format' and
# is writable outside a transaction. # '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_format= statement;
set @@session.binlog_direct_non_transactional_updates= TRUE; set @@session.binlog_direct_non_transactional_updates= TRUE;
SELECT @@session.binlog_format; SELECT @@session.binlog_format;
...@@ -17,15 +22,19 @@ SELECT @@session.binlog_direct_non_transactional_updates; ...@@ -17,15 +22,19 @@ SELECT @@session.binlog_direct_non_transactional_updates;
@@session.binlog_direct_non_transactional_updates @@session.binlog_direct_non_transactional_updates
1 1
begin; begin;
# Test that the session variable 'binlog_format' is read-only # Test that the session variable 'binlog_format' and
# inside a transaction with no preceding updates. # '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; set @@session.binlog_format= mixed;
ERROR HY000: Cannot modify @@session.binlog_format inside a transaction ERROR HY000: Cannot modify @@session.binlog_format inside a transaction
set @@session.binlog_direct_non_transactional_updates= FALSE; set @@session.binlog_direct_non_transactional_updates= FALSE;
ERROR HY000: Cannot modify @@session.binlog_direct_non_transactional_updates inside a transaction ERROR HY000: Cannot modify @@session.binlog_direct_non_transactional_updates inside a transaction
insert into t2 values (1); insert into t2 values (1);
# Test that the session variable 'binlog_format' is read-only # Test that the session variable 'binlog_format' and
# inside a transaction with preceding transactional updates. # '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; set @@session.binlog_format= row;
ERROR HY000: Cannot modify @@session.binlog_format inside a transaction ERROR HY000: Cannot modify @@session.binlog_format inside a transaction
set @@session.binlog_direct_non_transactional_updates= FALSE; set @@session.binlog_direct_non_transactional_updates= FALSE;
...@@ -33,15 +42,19 @@ ERROR HY000: Cannot modify @@session.binlog_direct_non_transactional_updates ins ...@@ -33,15 +42,19 @@ ERROR HY000: Cannot modify @@session.binlog_direct_non_transactional_updates ins
commit; commit;
begin; begin;
insert into t1 values (2); insert into t1 values (2);
# Test that the session variable 'binlog_format' is read-only # Test that the session variable 'binlog_format' and
# inside a transaction with preceding non-transactional updates. # 'binlog_direct_non_transactional_updates' are
set @@session.binlog_format= statement; # 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 ERROR HY000: Cannot modify @@session.binlog_format inside a transaction
set @@session.binlog_direct_non_transactional_updates= FALSE; set @@session.binlog_direct_non_transactional_updates= FALSE;
ERROR HY000: Cannot modify @@session.binlog_direct_non_transactional_updates inside a transaction ERROR HY000: Cannot modify @@session.binlog_direct_non_transactional_updates inside a transaction
commit; commit;
# Test that the session variable 'binlog_format' is writable # Test that the session variable 'binlog_format' and
# when AUTOCOMMIT=0, before a transaction has started. # '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 AUTOCOMMIT=0;
set @@session.binlog_format= row; set @@session.binlog_format= row;
set @@session.binlog_direct_non_transactional_updates= FALSE; set @@session.binlog_direct_non_transactional_updates= FALSE;
...@@ -51,9 +64,12 @@ ROW ...@@ -51,9 +64,12 @@ ROW
SELECT @@session.binlog_direct_non_transactional_updates; SELECT @@session.binlog_direct_non_transactional_updates;
@@session.binlog_direct_non_transactional_updates @@session.binlog_direct_non_transactional_updates
0 0
insert into t1 values (4); insert into t1 values (3);
# Test that the session variable 'binlog_format' is read-only inside an # Test that the session variable 'binlog_format' and
# AUTOCOMMIT=0 transaction with preceding non-transactional updates. # '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; set @@session.binlog_format= statement;
ERROR HY000: Cannot modify @@session.binlog_format inside a transaction ERROR HY000: Cannot modify @@session.binlog_format inside a transaction
set @@session.binlog_direct_non_transactional_updates= TRUE; set @@session.binlog_direct_non_transactional_updates= TRUE;
...@@ -65,10 +81,13 @@ SELECT @@session.binlog_direct_non_transactional_updates; ...@@ -65,10 +81,13 @@ SELECT @@session.binlog_direct_non_transactional_updates;
@@session.binlog_direct_non_transactional_updates @@session.binlog_direct_non_transactional_updates
0 0
commit; commit;
insert into t2 values (5); insert into t2 values (4);
# Test that the session variable 'binlog_format' is read-only inside an # Test that the session variable 'binlog_format' and
# AUTOCOMMIT=0 transaction with preceding transactional updates. # 'binlog_direct_non_transactional_updates' are
set @@session.binlog_format= row; # 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 ERROR HY000: Cannot modify @@session.binlog_format inside a transaction
set @@session.binlog_direct_non_transactional_updates= TRUE; set @@session.binlog_direct_non_transactional_updates= TRUE;
ERROR HY000: Cannot modify @@session.binlog_direct_non_transactional_updates inside a transaction ERROR HY000: Cannot modify @@session.binlog_direct_non_transactional_updates inside a transaction
...@@ -80,9 +99,11 @@ SELECT @@session.binlog_direct_non_transactional_updates; ...@@ -80,9 +99,11 @@ SELECT @@session.binlog_direct_non_transactional_updates;
0 0
commit; commit;
begin; begin;
insert into t2 values (6); insert into t2 values (5);
# Test that the global variable 'binlog_format' is writable # Test that the global variable 'binlog_format' and
# inside a transaction. # 'binlog_direct_non_transactional_updates' are
# writable inside a transaction.
# Current session values are ROW and FALSE, respectively.
SELECT @@global.binlog_format; SELECT @@global.binlog_format;
@@global.binlog_format @@global.binlog_format
ROW ROW
...@@ -96,18 +117,19 @@ SELECT @@global.binlog_direct_non_transactional_updates; ...@@ -96,18 +117,19 @@ SELECT @@global.binlog_direct_non_transactional_updates;
1 1
commit; commit;
set @@global.binlog_format= @save_binlog_format; 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 t3(a int, b int) engine= innodb;
create table t4(a int) engine= innodb; create table t4(a int) engine= innodb;
create table t5(a int) engine= innodb; create table t5(a int) engine= innodb;
create trigger tr1 after insert on t3 for each row begin create trigger tr1 after insert on t3 for each row begin
insert into t4(a) values(1); insert into t4(a) values(1);
set @@session.binlog_format= statement; set @@session.binlog_format= statement;
insert into t4(a) values(2); insert into t4(a) values(2);
insert into t5(a) values(3); insert into t5(a) values(3);
end | end |
# Test that the session variable 'binlog_format' is read-only # Test that the session variable 'binlog_format' is read-only
# in sub-statements. # in sub-statements.
# Current session value is ROW.
insert into t3(a,b) values(1,1); insert into t3(a,b) values(1,1);
ERROR HY000: Cannot change the binary logging format inside a stored function or trigger ERROR HY000: Cannot change the binary logging format inside a stored function or trigger
SELECT @@session.binlog_format; SELECT @@session.binlog_format;
...@@ -118,12 +140,14 @@ create table t7(a int) engine= innodb; ...@@ -118,12 +140,14 @@ create table t7(a int) engine= innodb;
create table t8(a int) engine= innodb; create table t8(a int) engine= innodb;
create trigger tr2 after insert on t6 for each row begin create trigger tr2 after insert on t6 for each row begin
insert into t7(a) values(1); 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 t7(a) values(2);
insert into t8(a) values(3); insert into t8(a) values(3);
end | end |
# Test that the session variable 'binlog_format' is read-only # Test that the session variable
# in sub-statements. # 'binlog_direct_non_transactional_updates' is
# read-only in sub-statements.
# Current session value is FALSE.
insert into t6(a,b) values(1,1); insert into t6(a,b) values(1,1);
ERROR HY000: Cannot change the binlog direct flag inside a stored function or trigger ERROR HY000: Cannot change the binlog direct flag inside a stored function or trigger
SELECT @@session.binlog_direct_non_transactional_updates; SELECT @@session.binlog_direct_non_transactional_updates;
......
# #
# BUG#47863 # BUG#47863
# This test verifies if the session variable 'binlog_format' # This test verifies if the session variable 'binlog_format' and
# is read-only inside a transaction and in sub-statements. # 'binlog_direct_non_transactional_updates' are read-only inside
# a transaction and in sub-statements.
# #
source include/have_innodb.inc; source include/have_innodb.inc;
...@@ -13,25 +14,32 @@ create table t1 (a int) engine= myisam; ...@@ -13,25 +14,32 @@ create table t1 (a int) engine= myisam;
create table t2 (a int) engine= innodb; create table t2 (a int) engine= innodb;
SELECT @@session.binlog_format; SELECT @@session.binlog_format;
SELECT @@session.binlog_direct_non_transactional_updates;
SET AUTOCOMMIT=1; SET AUTOCOMMIT=1;
--echo # Test that the session variable 'binlog_format' --echo # Test that the session variable 'binlog_format' and
--echo # is writable outside a transaction. --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_format= statement;
set @@session.binlog_direct_non_transactional_updates= TRUE; set @@session.binlog_direct_non_transactional_updates= TRUE;
SELECT @@session.binlog_format; SELECT @@session.binlog_format;
SELECT @@session.binlog_direct_non_transactional_updates; SELECT @@session.binlog_direct_non_transactional_updates;
begin; begin;
--echo # Test that the session variable 'binlog_format' is read-only --echo # Test that the session variable 'binlog_format' and
--echo # inside a transaction with no preceding updates. --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 --error ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_BINLOG_FORMAT
set @@session.binlog_format= mixed; set @@session.binlog_format= mixed;
--error ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_BINLOG_DIRECT --error ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_BINLOG_DIRECT
set @@session.binlog_direct_non_transactional_updates= FALSE; set @@session.binlog_direct_non_transactional_updates= FALSE;
insert into t2 values (1); insert into t2 values (1);
--echo # Test that the session variable 'binlog_format' is read-only --echo # Test that the session variable 'binlog_format' and
--echo # inside a transaction with preceding transactional updates. --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 --error ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_BINLOG_FORMAT
set @@session.binlog_format= row; set @@session.binlog_format= row;
--error ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_BINLOG_DIRECT --error ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_BINLOG_DIRECT
...@@ -40,25 +48,32 @@ commit; ...@@ -40,25 +48,32 @@ commit;
begin; begin;
insert into t1 values (2); insert into t1 values (2);
--echo # Test that the session variable 'binlog_format' is read-only --echo # Test that the session variable 'binlog_format' and
--echo # inside a transaction with preceding non-transactional updates. --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 --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 --error ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_BINLOG_DIRECT
set @@session.binlog_direct_non_transactional_updates= FALSE; set @@session.binlog_direct_non_transactional_updates= FALSE;
commit; commit;
--echo # Test that the session variable 'binlog_format' is writable --echo # Test that the session variable 'binlog_format' and
--echo # when AUTOCOMMIT=0, before a transaction has started. --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 AUTOCOMMIT=0;
set @@session.binlog_format= row; set @@session.binlog_format= row;
set @@session.binlog_direct_non_transactional_updates= FALSE; set @@session.binlog_direct_non_transactional_updates= FALSE;
SELECT @@session.binlog_format; SELECT @@session.binlog_format;
SELECT @@session.binlog_direct_non_transactional_updates; SELECT @@session.binlog_direct_non_transactional_updates;
insert into t1 values (4); insert into t1 values (3);
--echo # Test that the session variable 'binlog_format' is read-only inside an --echo # Test that the session variable 'binlog_format' and
--echo # AUTOCOMMIT=0 transaction with preceding non-transactional updates. --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 --error ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_BINLOG_FORMAT
set @@session.binlog_format= statement; set @@session.binlog_format= statement;
--error ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_BINLOG_DIRECT --error ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_BINLOG_DIRECT
...@@ -67,11 +82,14 @@ SELECT @@session.binlog_format; ...@@ -67,11 +82,14 @@ SELECT @@session.binlog_format;
SELECT @@session.binlog_direct_non_transactional_updates; SELECT @@session.binlog_direct_non_transactional_updates;
commit; commit;
insert into t2 values (5); insert into t2 values (4);
--echo # Test that the session variable 'binlog_format' is read-only inside an --echo # Test that the session variable 'binlog_format' and
--echo # AUTOCOMMIT=0 transaction with preceding transactional updates. --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 --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 --error ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_BINLOG_DIRECT
set @@session.binlog_direct_non_transactional_updates= TRUE; set @@session.binlog_direct_non_transactional_updates= TRUE;
SELECT @@session.binlog_format; SELECT @@session.binlog_format;
...@@ -79,9 +97,11 @@ SELECT @@session.binlog_direct_non_transactional_updates; ...@@ -79,9 +97,11 @@ SELECT @@session.binlog_direct_non_transactional_updates;
commit; commit;
begin; begin;
insert into t2 values (6); insert into t2 values (5);
--echo # Test that the global variable 'binlog_format' is writable --echo # Test that the global variable 'binlog_format' and
--echo # inside a transaction. --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; SELECT @@global.binlog_format;
set @@global.binlog_format= statement; set @@global.binlog_format= statement;
set @@global.binlog_direct_non_transactional_updates= TRUE; set @@global.binlog_direct_non_transactional_updates= TRUE;
...@@ -90,7 +110,7 @@ begin; ...@@ -90,7 +110,7 @@ begin;
commit; commit;
set @@global.binlog_format= @save_binlog_format; 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 t3(a int, b int) engine= innodb;
create table t4(a int) engine= innodb; create table t4(a int) engine= innodb;
...@@ -98,7 +118,7 @@ create table t5(a int) engine= innodb; ...@@ -98,7 +118,7 @@ create table t5(a int) engine= innodb;
delimiter |; delimiter |;
eval create trigger tr1 after insert on t3 for each row begin eval create trigger tr1 after insert on t3 for each row begin
insert into t4(a) values(1); insert into t4(a) values(1);
set @@session.binlog_format= statement; set @@session.binlog_format= statement;
insert into t4(a) values(2); insert into t4(a) values(2);
insert into t5(a) values(3); insert into t5(a) values(3);
end | end |
...@@ -106,6 +126,7 @@ delimiter ;| ...@@ -106,6 +126,7 @@ delimiter ;|
--echo # Test that the session variable 'binlog_format' is read-only --echo # Test that the session variable 'binlog_format' is read-only
--echo # in sub-statements. --echo # in sub-statements.
--echo # Current session value is ROW.
--error ER_STORED_FUNCTION_PREVENTS_SWITCH_BINLOG_FORMAT --error ER_STORED_FUNCTION_PREVENTS_SWITCH_BINLOG_FORMAT
insert into t3(a,b) values(1,1); insert into t3(a,b) values(1,1);
SELECT @@session.binlog_format; SELECT @@session.binlog_format;
...@@ -116,14 +137,16 @@ create table t8(a int) engine= innodb; ...@@ -116,14 +137,16 @@ create table t8(a int) engine= innodb;
delimiter |; delimiter |;
eval create trigger tr2 after insert on t6 for each row begin eval create trigger tr2 after insert on t6 for each row begin
insert into t7(a) values(1); 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 t7(a) values(2);
insert into t8(a) values(3); insert into t8(a) values(3);
end | end |
delimiter ;| delimiter ;|
--echo # Test that the session variable 'binlog_format' is read-only --echo # Test that the session variable
--echo # in sub-statements. --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 --error ER_STORED_FUNCTION_PREVENTS_SWITCH_BINLOG_DIRECT
insert into t6(a,b) values(1,1); insert into t6(a,b) values(1,1);
SELECT @@session.binlog_direct_non_transactional_updates; SELECT @@session.binlog_direct_non_transactional_updates;
......
...@@ -9,12 +9,12 @@ INSERT INTO t1 VALUES (1,1), (1,2), (2,1), (2,2); ...@@ -9,12 +9,12 @@ INSERT INTO t1 VALUES (1,1), (1,2), (2,1), (2,2);
INSERT INTO t2 VALUES (1,1), (1,2), (2,1), (2,2); INSERT INTO t2 VALUES (1,1), (1,2), (2,1), (2,2);
UPDATE t1, t2 SET m = 2, b = 3 WHERE n = c; UPDATE t1, t2 SET m = 2, b = 3 WHERE n = c;
Warnings: Warnings:
Note 1592 Unsafe statement binlogged in statement format since BINLOG_FORMAT = STATEMENT. Reason for unsafeness: Non-transactional reads or writes are unsafe if they occur after transactional reads or writes inside a transaction. Note 1592 Unsafe statement binlogged in statement format since BINLOG_FORMAT = STATEMENT. Reason for unsafeness: Statements that read from both transactional and non-transactional tables and write to any of them are unsafe.
START TRANSACTION; START TRANSACTION;
INSERT INTO t3 VALUES (1,1), (1,2), (2,1), (2,2); INSERT INTO t3 VALUES (1,1), (1,2), (2,1), (2,2);
UPDATE t1, t3 SET m = 2, e = 3 WHERE n = f; UPDATE t1, t3 SET m = 2, e = 3 WHERE n = f;
Warnings: Warnings:
Note 1592 Unsafe statement binlogged in statement format since BINLOG_FORMAT = STATEMENT. Reason for unsafeness: Non-transactional reads or writes are unsafe if they occur after transactional reads or writes inside a transaction. Note 1592 Unsafe statement binlogged in statement format since BINLOG_FORMAT = STATEMENT. Reason for unsafeness: Statements that read from both transactional and non-transactional tables and write to any of them are unsafe.
UPDATE t3, t2 SET e = 2, b = 3 WHERE f = c; UPDATE t3, t2 SET e = 2, b = 3 WHERE f = c;
COMMIT; COMMIT;
show binlog events from <binlog_start>; show binlog events from <binlog_start>;
......
...@@ -22,7 +22,7 @@ SET AUTOCOMMIT = 1; ...@@ -22,7 +22,7 @@ SET AUTOCOMMIT = 1;
BEGIN; BEGIN;
UPDATE t SET f = 'yellow 2' WHERE i = 3; UPDATE t SET f = 'yellow 2' WHERE i = 3;
Warnings: Warnings:
Note 1592 Unsafe statement binlogged in statement format since BINLOG_FORMAT = STATEMENT. Reason for unsafeness: Non-transactional reads or writes are unsafe if they occur after transactional reads or writes inside a transaction. Note 1592 Unsafe statement binlogged in statement format since BINLOG_FORMAT = STATEMENT. Reason for unsafeness: Statements that read from both transactional and non-transactional tables and write to any of them are unsafe.
SET AUTOCOMMIT = 1; SET AUTOCOMMIT = 1;
BEGIN; BEGIN;
UPDATE t SET f = 'magenta 2' WHERE f = 'red'; UPDATE t SET f = 'magenta 2' WHERE f = 'red';
...@@ -51,7 +51,7 @@ SET AUTOCOMMIT = 1; ...@@ -51,7 +51,7 @@ SET AUTOCOMMIT = 1;
BEGIN; BEGIN;
UPDATE t SET f = 'gray 2' WHERE i = 3; UPDATE t SET f = 'gray 2' WHERE i = 3;
Warnings: Warnings:
Note 1592 Unsafe statement binlogged in statement format since BINLOG_FORMAT = STATEMENT. Reason for unsafeness: Non-transactional reads or writes are unsafe if they occur after transactional reads or writes inside a transaction. Note 1592 Unsafe statement binlogged in statement format since BINLOG_FORMAT = STATEMENT. Reason for unsafeness: Statements that read from both transactional and non-transactional tables and write to any of them are unsafe.
SET AUTOCOMMIT = 1; SET AUTOCOMMIT = 1;
BEGIN; BEGIN;
UPDATE t SET f = 'dark blue 2' WHERE f = 'red'; UPDATE t SET f = 'dark blue 2' WHERE f = 'red';
...@@ -77,7 +77,7 @@ master-bin.000001 # Xid # # COMMIT /* XID */ ...@@ -77,7 +77,7 @@ master-bin.000001 # Xid # # COMMIT /* XID */
SET AUTOCOMMIT = 0; SET AUTOCOMMIT = 0;
UPDATE t SET f = 'yellow 1' WHERE i = 3; UPDATE t SET f = 'yellow 1' WHERE i = 3;
Warnings: Warnings:
Note 1592 Unsafe statement binlogged in statement format since BINLOG_FORMAT = STATEMENT. Reason for unsafeness: Non-transactional reads or writes are unsafe if they occur after transactional reads or writes inside a transaction. Note 1592 Unsafe statement binlogged in statement format since BINLOG_FORMAT = STATEMENT. Reason for unsafeness: Statements that read from both transactional and non-transactional tables and write to any of them are unsafe.
SET AUTOCOMMIT = 0; SET AUTOCOMMIT = 0;
UPDATE t SET f = 'magenta 1' WHERE f = 'red'; UPDATE t SET f = 'magenta 1' WHERE f = 'red';
ERROR HY000: Lock wait timeout exceeded; try restarting transaction ERROR HY000: Lock wait timeout exceeded; try restarting transaction
...@@ -104,7 +104,7 @@ master-bin.000001 # Query # # ROLLBACK ...@@ -104,7 +104,7 @@ master-bin.000001 # Query # # ROLLBACK
SET AUTOCOMMIT = 0; SET AUTOCOMMIT = 0;
UPDATE t SET f = 'gray 1' WHERE i = 3; UPDATE t SET f = 'gray 1' WHERE i = 3;
Warnings: Warnings:
Note 1592 Unsafe statement binlogged in statement format since BINLOG_FORMAT = STATEMENT. Reason for unsafeness: Non-transactional reads or writes are unsafe if they occur after transactional reads or writes inside a transaction. Note 1592 Unsafe statement binlogged in statement format since BINLOG_FORMAT = STATEMENT. Reason for unsafeness: Statements that read from both transactional and non-transactional tables and write to any of them are unsafe.
SET AUTOCOMMIT = 0; SET AUTOCOMMIT = 0;
UPDATE t SET f = 'dark blue 1' WHERE f = 'red'; UPDATE t SET f = 'dark blue 1' WHERE f = 'red';
ERROR HY000: Lock wait timeout exceeded; try restarting transaction ERROR HY000: Lock wait timeout exceeded; try restarting transaction
......
...@@ -40,7 +40,7 @@ Got one of the listed errors ...@@ -40,7 +40,7 @@ Got one of the listed errors
Warnings: Warnings:
Note 1592 Unsafe statement binlogged in statement format since BINLOG_FORMAT = STATEMENT. Reason for unsafeness: Non-transactional reads or writes are unsafe if they occur after transactional reads or writes inside a transaction. Note 1592 Unsafe statement binlogged in statement format since BINLOG_FORMAT = STATEMENT. Reason for unsafeness: Non-transactional reads or writes are unsafe if they occur after transactional reads or writes inside a transaction.
Warnings: Warnings:
Note 1592 Unsafe statement binlogged in statement format since BINLOG_FORMAT = STATEMENT. Reason for unsafeness: Non-transactional reads or writes are unsafe if they occur after transactional reads or writes inside a transaction. Note 1592 Unsafe statement binlogged in statement format since BINLOG_FORMAT = STATEMENT. Reason for unsafeness: Statements that read from both transactional and non-transactional tables and write to any of them are unsafe.
BEGIN; BEGIN;
Got one of the listed errors Got one of the listed errors
Got one of the listed errors Got one of the listed errors
......
...@@ -53,7 +53,7 @@ set @@global.debug="+d,stop_slave_middle_group"; ...@@ -53,7 +53,7 @@ set @@global.debug="+d,stop_slave_middle_group";
set @@global.debug="+d,incomplete_group_in_relay_log"; set @@global.debug="+d,incomplete_group_in_relay_log";
update tm as t1, ti as t2 set t1.a=t1.a * 2, t2.a=t2.a * 2; update tm as t1, ti as t2 set t1.a=t1.a * 2, t2.a=t2.a * 2;
Warnings: Warnings:
Note 1592 Unsafe statement binlogged in statement format since BINLOG_FORMAT = STATEMENT. Reason for unsafeness: Non-transactional reads or writes are unsafe if they occur after transactional reads or writes inside a transaction. Note 1592 Unsafe statement binlogged in statement format since BINLOG_FORMAT = STATEMENT. Reason for unsafeness: Statements that read from both transactional and non-transactional tables and write to any of them are unsafe.
SELECT "Fatal error: ... The slave SQL is stopped, leaving the current group of events unfinished with a non-transaction table changed. If the group consists solely of Row-based events, you can try restarting the slave with --slave-exec-mode=IDEMPOTENT, which ignores duplicate key, key not found, and similar errors (see documentation for details)." AS Last_SQL_Error, @check as `true`; SELECT "Fatal error: ... The slave SQL is stopped, leaving the current group of events unfinished with a non-transaction table changed. If the group consists solely of Row-based events, you can try restarting the slave with --slave-exec-mode=IDEMPOTENT, which ignores duplicate key, key not found, and similar errors (see documentation for details)." AS Last_SQL_Error, @check as `true`;
Last_SQL_Error true Last_SQL_Error true
Fatal error: ... The slave SQL is stopped, leaving the current group of events unfinished with a non-transaction table changed. If the group consists solely of Row-based events, you can try restarting the slave with --slave-exec-mode=IDEMPOTENT, which ignores duplicate key, key not found, and similar errors (see documentation for details). 1 Fatal error: ... The slave SQL is stopped, leaving the current group of events unfinished with a non-transaction table changed. If the group consists solely of Row-based events, you can try restarting the slave with --slave-exec-mode=IDEMPOTENT, which ignores duplicate key, key not found, and similar errors (see documentation for details). 1
......
###################################################################################
# This test cases evaluates the mixture of non-transactional and transcational
# tables. For further details, please, read WL#2687 and WL#5072.
###################################################################################
--source include/have_binlog_format_mixed.inc
--source include/master-slave.inc
--source include/have_innodb.inc
--disable_query_log
SET SESSION binlog_direct_non_transactional_updates = OFF;
--enable_query_log
let $engine_type=Innodb;
--source extra/rpl_tests/rpl_mixing_engines.test
--diff_files suite/rpl/r/rpl_non_direct_mixed_mixing_engines.result suite/rpl/r/rpl_mixed_mixing_engines.result
###################################################################################
# This test cases evaluates the mixture of non-transactional and transcational
# tables. For further details, please, read WL#2687 and WL#5072.
###################################################################################
--source include/have_binlog_format_row.inc
--source include/master-slave.inc
--source include/have_innodb.inc
--disable_query_log
SET SESSION binlog_direct_non_transactional_updates = OFF;
--enable_query_log
let $engine_type=Innodb;
--source extra/rpl_tests/rpl_mixing_engines.test
--diff_files suite/rpl/r/rpl_non_direct_row_mixing_engines.result suite/rpl/r/rpl_row_mixing_engines.result
###################################################################################
# This test cases evaluates the mixture of non-transactional and transcational
# tables. For further details, please, read WL#2687 and WL#5072.
###################################################################################
--source include/have_binlog_format_statement.inc
--source include/master-slave.inc
--source include/have_innodb.inc
--disable_query_log
SET SESSION binlog_direct_non_transactional_updates = OFF;
--enable_query_log
let $engine_type=Innodb;
--source extra/rpl_tests/rpl_mixing_engines.test
...@@ -15,6 +15,7 @@ call mtr.add_suppression("Unsafe statement binlogged in statement format since B ...@@ -15,6 +15,7 @@ call mtr.add_suppression("Unsafe statement binlogged in statement format since B
connection slave; connection slave;
call mtr.add_suppression("Master server does not support semi-sync"); call mtr.add_suppression("Master server does not support semi-sync");
call mtr.add_suppression("Semi-sync slave .* reply"); call mtr.add_suppression("Semi-sync slave .* reply");
call mtr.add_suppression("Unsafe statement binlogged in statement format since BINLOG_FORMAT = STATEMENT.");
enable_query_log; enable_query_log;
connection master; connection master;
......
...@@ -341,6 +341,25 @@ ROLLBACK; ...@@ -341,6 +341,25 @@ ROLLBACK;
Warnings: Warnings:
Warning 1196 Some non-transactional changed tables couldn't be rolled back Warning 1196 Some non-transactional changed tables couldn't be rolled back
SET AUTOCOMMIT = 1; SET AUTOCOMMIT = 1;
---- Mixed statements Innodb ----
BEGIN;
INSERT INTO tndb VALUES (147);
INSERT INTO tinnodb SELECT * FROM tndb ORDER BY a DESC LIMIT 1;
COMMIT;
INSERT INTO tndb VALUES (148);
BEGIN;
INSERT INTO tinnodb SELECT * FROM tndb ORDER BY a DESC LIMIT 1;
INSERT INTO tndb VALUES (149);
COMMIT;
BEGIN;
INSERT INTO tndb VALUES (150);
INSERT INTO tmyisam SELECT * FROM tndb ORDER BY a DESC LIMIT 1;
COMMIT;
INSERT INTO tndb VALUES (151);
BEGIN;
INSERT INTO tmyisam SELECT * FROM tndb ORDER BY a DESC LIMIT 1;
INSERT INTO tndb VALUES (152);
COMMIT;
==== Verify the result ==== ==== Verify the result ====
SELECT * FROM tmyisam ORDER BY a; SELECT * FROM tmyisam ORDER BY a;
a a
...@@ -393,6 +412,8 @@ a ...@@ -393,6 +412,8 @@ a
140 140
142 142
146 146
150
151
SELECT * FROM tinnodb ORDER BY a; SELECT * FROM tinnodb ORDER BY a;
a a
1 1
...@@ -420,6 +441,8 @@ a ...@@ -420,6 +441,8 @@ a
120 120
125 125
127 127
147
148
SELECT * FROM tndb ORDER BY a; SELECT * FROM tndb ORDER BY a;
a a
2 2
...@@ -447,6 +470,12 @@ a ...@@ -447,6 +470,12 @@ a
121 121
123 123
126 126
147
148
149
150
151
152
[on slave] [on slave]
Comparing tables master:test.tmyisam and slave:test.tmyisam Comparing tables master:test.tmyisam and slave:test.tmyisam
Comparing tables master:test.tinnodb and slave:test.tinnodb Comparing tables master:test.tinnodb and slave:test.tinnodb
......
...@@ -418,6 +418,29 @@ ROLLBACK; ...@@ -418,6 +418,29 @@ ROLLBACK;
SET AUTOCOMMIT = 1; SET AUTOCOMMIT = 1;
--echo ---- Mixed statements Innodb ----
BEGIN;
INSERT INTO tndb VALUES (147);
INSERT INTO tinnodb SELECT * FROM tndb ORDER BY a DESC LIMIT 1;
COMMIT;
INSERT INTO tndb VALUES (148);
BEGIN;
INSERT INTO tinnodb SELECT * FROM tndb ORDER BY a DESC LIMIT 1;
INSERT INTO tndb VALUES (149);
COMMIT;
BEGIN;
INSERT INTO tndb VALUES (150);
INSERT INTO tmyisam SELECT * FROM tndb ORDER BY a DESC LIMIT 1;
COMMIT;
INSERT INTO tndb VALUES (151);
BEGIN;
INSERT INTO tmyisam SELECT * FROM tndb ORDER BY a DESC LIMIT 1;
INSERT INTO tndb VALUES (152);
COMMIT;
--echo ==== Verify the result ==== --echo ==== Verify the result ====
......
...@@ -1640,7 +1640,10 @@ binlog_flush_stmt_cache(THD *thd, binlog_cache_mngr *cache_mngr) ...@@ -1640,7 +1640,10 @@ binlog_flush_stmt_cache(THD *thd, binlog_cache_mngr *cache_mngr)
*/ */
bool const is_transactional= FALSE; bool const is_transactional= FALSE;
IO_CACHE *cache_log= &cache_mngr->stmt_cache.cache_log; IO_CACHE *cache_log= &cache_mngr->stmt_cache.cache_log;
thd->binlog_flush_pending_rows_event(TRUE, is_transactional);
if (thd->binlog_flush_pending_rows_event(TRUE, is_transactional))
DBUG_RETURN(1);
Query_log_event qev(thd, STRING_WITH_LEN("COMMIT"), TRUE, FALSE, TRUE, 0); Query_log_event qev(thd, STRING_WITH_LEN("COMMIT"), TRUE, FALSE, TRUE, 0);
if ((error= mysql_bin_log.write(thd, cache_log, &qev, if ((error= mysql_bin_log.write(thd, cache_log, &qev,
cache_mngr->stmt_cache.has_incident()))) cache_mngr->stmt_cache.has_incident())))
...@@ -4189,7 +4192,7 @@ bool MYSQL_BIN_LOG::is_query_in_union(THD *thd, query_id_t query_id_param) ...@@ -4189,7 +4192,7 @@ bool MYSQL_BIN_LOG::is_query_in_union(THD *thd, query_id_t query_id_param)
} }
/** /**
This function checks if a transactional talbe was updated by the This function checks if a transactional table was updated by the
current transaction. current transaction.
@param thd The client thread that executed the current statement. @param thd The client thread that executed the current statement.
...@@ -4202,11 +4205,11 @@ trans_has_updated_trans_table(const THD* thd) ...@@ -4202,11 +4205,11 @@ trans_has_updated_trans_table(const THD* thd)
binlog_cache_mngr *const cache_mngr= binlog_cache_mngr *const cache_mngr=
(binlog_cache_mngr*) thd_get_ha_data(thd, binlog_hton); (binlog_cache_mngr*) thd_get_ha_data(thd, binlog_hton);
return (cache_mngr ? my_b_tell (&cache_mngr->trx_cache.cache_log) : 0); return (cache_mngr ? !cache_mngr->trx_cache.empty() : 0);
} }
/** /**
This function checks if a transactional talbe was updated by the This function checks if a transactional table was updated by the
current statement. current statement.
@param thd The client thread that executed the current statement. @param thd The client thread that executed the current statement.
...@@ -4218,7 +4221,8 @@ stmt_has_updated_trans_table(const THD *thd) ...@@ -4218,7 +4221,8 @@ stmt_has_updated_trans_table(const THD *thd)
{ {
Ha_trx_info *ha_info; Ha_trx_info *ha_info;
for (ha_info= thd->transaction.stmt.ha_list; ha_info; ha_info= ha_info->next()) for (ha_info= thd->transaction.stmt.ha_list; ha_info;
ha_info= ha_info->next())
{ {
if (ha_info->is_trx_read_write() && ha_info->ht() != binlog_hton) if (ha_info->is_trx_read_write() && ha_info->ht() != binlog_hton)
return (TRUE); return (TRUE);
...@@ -4228,11 +4232,14 @@ stmt_has_updated_trans_table(const THD *thd) ...@@ -4228,11 +4232,14 @@ stmt_has_updated_trans_table(const THD *thd)
/** /**
This function checks if either a trx-cache or a non-trx-cache should This function checks if either a trx-cache or a non-trx-cache should
be used. If @c bin_log_direct_non_trans_update is active, the cache be used. If @c bin_log_direct_non_trans_update is active or the format
to be used depends on the flag @c is_transactional. is either MIXED or ROW, the cache to be used depends on the flag @c
is_transactional.
Otherswise, we use the trx-cache if either the @c is_transactional On the other hand, if binlog_format is STMT or direct option is
is true or the trx-cache is not empty. OFF, the trx-cache should be used if and only if the statement is
transactional or the trx-cache is not empty. Otherwise, the
non-trx-cache should be used.
@param thd The client thread. @param thd The client thread.
@param is_transactional The changes are related to a trx-table. @param is_transactional The changes are related to a trx-table.
...@@ -4245,8 +4252,9 @@ bool use_trans_cache(const THD* thd, bool is_transactional) ...@@ -4245,8 +4252,9 @@ bool use_trans_cache(const THD* thd, bool is_transactional)
(binlog_cache_mngr*) thd_get_ha_data(thd, binlog_hton); (binlog_cache_mngr*) thd_get_ha_data(thd, binlog_hton);
return return
(thd->variables.binlog_direct_non_trans_update ? is_transactional : ((thd->variables.binlog_format != BINLOG_FORMAT_STMT ||
(cache_mngr->trx_cache.empty() && !is_transactional ? FALSE : TRUE)); thd->variables.binlog_direct_non_trans_update) ? is_transactional :
(is_transactional || !cache_mngr->trx_cache.empty()));
} }
/* /*
......
...@@ -6330,3 +6330,9 @@ ER_DATA_OUT_OF_RANGE 22003 ...@@ -6330,3 +6330,9 @@ ER_DATA_OUT_OF_RANGE 22003
ER_WRONG_SPVAR_TYPE_IN_LIMIT ER_WRONG_SPVAR_TYPE_IN_LIMIT
eng "A variable of a non-integer type in LIMIT clause" eng "A variable of a non-integer type in LIMIT clause"
ER_BINLOG_UNSAFE_MULTIPLE_ENGINES_AND_SELF_LOGGING_ENGINE
eng "Mixing self-logging and non-self-logging engines in a statement is unsafe."
ER_BINLOG_UNSAFE_MIXED_STATEMENT
eng "Statements that read from both transactional and non-transactional tables and write to any of them are unsafe."
...@@ -3601,13 +3601,33 @@ int THD::decide_logging_format(TABLE_LIST *tables) ...@@ -3601,13 +3601,33 @@ int THD::decide_logging_format(TABLE_LIST *tables)
capabilities, and one with the intersection of all the engine capabilities, and one with the intersection of all the engine
capabilities. capabilities.
*/ */
handler::Table_flags flags_write_some_set= 0;
handler::Table_flags flags_some_set= 0; handler::Table_flags flags_some_set= 0;
handler::Table_flags flags_all_set= handler::Table_flags flags_write_all_set=
HA_BINLOG_ROW_CAPABLE | HA_BINLOG_STMT_CAPABLE; HA_BINLOG_ROW_CAPABLE | HA_BINLOG_STMT_CAPABLE;
my_bool multi_engine= FALSE; /*
my_bool mixed_engine= FALSE; If different types of engines are about to be updated.
my_bool all_trans_engines= TRUE; For example: Innodb and Falcon; Innodb and MyIsam.
*/
my_bool multi_write_engine= FALSE;
/*
If different types of engines are about to be accessed
and any of them is about to be updated. For example:
Innodb and Falcon; Innodb and MyIsam.
*/
my_bool multi_access_engine= FALSE;
/*
If non-transactional and transactional engines are about
to be accessed and any of them is about to be updated.
For example: Innodb and MyIsam.
*/
my_bool trans_non_trans_access_engines= FALSE;
/*
If all engines that are about to be updated are
transactional.
*/
my_bool all_trans_write_engines= TRUE;
TABLE* prev_write_table= NULL; TABLE* prev_write_table= NULL;
TABLE* prev_access_table= NULL; TABLE* prev_access_table= NULL;
...@@ -3633,32 +3653,50 @@ int THD::decide_logging_format(TABLE_LIST *tables) ...@@ -3633,32 +3653,50 @@ int THD::decide_logging_format(TABLE_LIST *tables)
continue; continue;
if (table->table->s->table_category == TABLE_CATEGORY_PERFORMANCE) if (table->table->s->table_category == TABLE_CATEGORY_PERFORMANCE)
lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_SYSTEM_TABLE); lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_SYSTEM_TABLE);
handler::Table_flags const flags= table->table->file->ha_table_flags();
DBUG_PRINT("info", ("table: %s; ha_table_flags: 0x%llx",
table->table_name, flags));
if (table->lock_type >= TL_WRITE_ALLOW_WRITE) if (table->lock_type >= TL_WRITE_ALLOW_WRITE)
{ {
handler::Table_flags const flags= table->table->file->ha_table_flags();
DBUG_PRINT("info", ("table: %s; ha_table_flags: 0x%llx",
table->table_name, flags));
if (prev_write_table && prev_write_table->file->ht != if (prev_write_table && prev_write_table->file->ht !=
table->table->file->ht) table->table->file->ht)
multi_engine= TRUE; multi_write_engine= TRUE;
all_trans_engines= all_trans_engines && all_trans_write_engines= all_trans_write_engines &&
table->table->file->has_transactions(); table->table->file->has_transactions();
prev_write_table= table->table; prev_write_table= table->table;
flags_all_set &= flags; flags_write_all_set &= flags;
flags_some_set |= flags; flags_write_some_set |= flags;
} }
flags_some_set |= flags;
if (prev_access_table && prev_access_table->file->ht != table->table->file->ht) if (prev_access_table && prev_access_table->file->ht != table->table->file->ht)
mixed_engine= mixed_engine || (prev_access_table->file->has_transactions() != {
table->table->file->has_transactions()); multi_access_engine= TRUE;
trans_non_trans_access_engines= trans_non_trans_access_engines ||
(prev_access_table->file->has_transactions() !=
table->table->file->has_transactions());
}
prev_access_table= table->table; prev_access_table= table->table;
} }
DBUG_PRINT("info", ("flags_write_all_set: 0x%llx", flags_write_all_set));
DBUG_PRINT("info", ("flags_write_some_set: 0x%llx", flags_write_some_set));
DBUG_PRINT("info", ("flags_some_set: 0x%llx", flags_some_set));
DBUG_PRINT("info", ("multi_write_engine: %d", multi_write_engine));
DBUG_PRINT("info", ("multi_access_engine: %d", multi_access_engine));
DBUG_PRINT("info", ("trans_non_trans_access_engines: %d",
trans_non_trans_access_engines));
int error= 0;
int unsafe_flags;
/* /*
Set the statement as unsafe if: Set the statement as unsafe if:
. it is a mixed statement, i.e. access transactional and non-transactional . it is a mixed statement, i.e. access transactional and non-transactional
tables, and updates at least one; tables, and update any of them;
or
or:
. an early statement updated a transactional table; . an early statement updated a transactional table;
. and, the current statement updates a non-transactional table. . and, the current statement updates a non-transactional table.
...@@ -3722,32 +3760,26 @@ int THD::decide_logging_format(TABLE_LIST *tables) ...@@ -3722,32 +3760,26 @@ int THD::decide_logging_format(TABLE_LIST *tables)
isolation level but if we have pure repeatable read or serializable the isolation level but if we have pure repeatable read or serializable the
lock history on the slave will be different from the master. lock history on the slave will be different from the master.
*/ */
if (mixed_engine || if (trans_non_trans_access_engines)
(trans_has_updated_trans_table(this) && !all_trans_engines)) lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_MIXED_STATEMENT);
else if (trans_has_updated_trans_table(this) && !all_trans_write_engines)
lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_NONTRANS_AFTER_TRANS); lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_NONTRANS_AFTER_TRANS);
DBUG_PRINT("info", ("flags_all_set: 0x%llx", flags_all_set));
DBUG_PRINT("info", ("flags_some_set: 0x%llx", flags_some_set));
DBUG_PRINT("info", ("multi_engine: %d", multi_engine));
int error= 0;
int unsafe_flags;
/* /*
If more than one engine is involved in the statement and at If more than one engine is involved in the statement and at
least one is doing it's own logging (is *self-logging*), the least one is doing it's own logging (is *self-logging*), the
statement cannot be logged atomically, so we generate an error statement cannot be logged atomically, so we generate an error
rather than allowing the binlog to become corrupt. rather than allowing the binlog to become corrupt.
*/ */
if (multi_engine && if (multi_write_engine &&
(flags_some_set & HA_HAS_OWN_BINLOGGING)) (flags_write_some_set & HA_HAS_OWN_BINLOGGING))
{
my_error((error= ER_BINLOG_MULTIPLE_ENGINES_AND_SELF_LOGGING_ENGINE), my_error((error= ER_BINLOG_MULTIPLE_ENGINES_AND_SELF_LOGGING_ENGINE),
MYF(0)); MYF(0));
} else if (multi_access_engine && flags_some_set & HA_HAS_OWN_BINLOGGING)
lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_MULTIPLE_ENGINES_AND_SELF_LOGGING_ENGINE);
/* both statement-only and row-only engines involved */ /* both statement-only and row-only engines involved */
if ((flags_all_set & (HA_BINLOG_STMT_CAPABLE | HA_BINLOG_ROW_CAPABLE)) == 0) if ((flags_write_all_set & (HA_BINLOG_STMT_CAPABLE | HA_BINLOG_ROW_CAPABLE)) == 0)
{ {
/* /*
1. Error: Binary logging impossible since both row-incapable 1. Error: Binary logging impossible since both row-incapable
...@@ -3756,7 +3788,7 @@ int THD::decide_logging_format(TABLE_LIST *tables) ...@@ -3756,7 +3788,7 @@ int THD::decide_logging_format(TABLE_LIST *tables)
my_error((error= ER_BINLOG_ROW_ENGINE_AND_STMT_ENGINE), MYF(0)); my_error((error= ER_BINLOG_ROW_ENGINE_AND_STMT_ENGINE), MYF(0));
} }
/* statement-only engines involved */ /* statement-only engines involved */
else if ((flags_all_set & HA_BINLOG_ROW_CAPABLE) == 0) else if ((flags_write_all_set & HA_BINLOG_ROW_CAPABLE) == 0)
{ {
if (lex->is_stmt_row_injection()) if (lex->is_stmt_row_injection())
{ {
...@@ -3804,7 +3836,7 @@ int THD::decide_logging_format(TABLE_LIST *tables) ...@@ -3804,7 +3836,7 @@ int THD::decide_logging_format(TABLE_LIST *tables)
*/ */
my_error((error= ER_BINLOG_ROW_INJECTION_AND_STMT_MODE), MYF(0)); my_error((error= ER_BINLOG_ROW_INJECTION_AND_STMT_MODE), MYF(0));
} }
else if ((flags_all_set & HA_BINLOG_STMT_CAPABLE) == 0) else if ((flags_write_all_set & HA_BINLOG_STMT_CAPABLE) == 0)
{ {
/* /*
5. Error: Cannot modify table that uses a storage engine 5. Error: Cannot modify table that uses a storage engine
...@@ -3832,7 +3864,7 @@ int THD::decide_logging_format(TABLE_LIST *tables) ...@@ -3832,7 +3864,7 @@ int THD::decide_logging_format(TABLE_LIST *tables)
else else
{ {
if (lex->is_stmt_unsafe() || lex->is_stmt_row_injection() if (lex->is_stmt_unsafe() || lex->is_stmt_row_injection()
|| (flags_all_set & HA_BINLOG_STMT_CAPABLE) == 0) || (flags_write_all_set & HA_BINLOG_STMT_CAPABLE) == 0)
{ {
/* log in row format! */ /* log in row format! */
set_current_stmt_binlog_format_row_if_mixed(); set_current_stmt_binlog_format_row_if_mixed();
......
...@@ -56,7 +56,9 @@ Query_tables_list::binlog_stmt_unsafe_errcode[BINLOG_STMT_UNSAFE_COUNT] = ...@@ -56,7 +56,9 @@ Query_tables_list::binlog_stmt_unsafe_errcode[BINLOG_STMT_UNSAFE_COUNT] =
ER_BINLOG_UNSAFE_UDF, ER_BINLOG_UNSAFE_UDF,
ER_BINLOG_UNSAFE_SYSTEM_VARIABLE, ER_BINLOG_UNSAFE_SYSTEM_VARIABLE,
ER_BINLOG_UNSAFE_SYSTEM_FUNCTION, ER_BINLOG_UNSAFE_SYSTEM_FUNCTION,
ER_BINLOG_UNSAFE_NONTRANS_AFTER_TRANS ER_BINLOG_UNSAFE_NONTRANS_AFTER_TRANS,
ER_BINLOG_UNSAFE_MULTIPLE_ENGINES_AND_SELF_LOGGING_ENGINE,
ER_BINLOG_UNSAFE_MIXED_STATEMENT,
}; };
......
...@@ -1161,6 +1161,18 @@ public: ...@@ -1161,6 +1161,18 @@ public:
*/ */
BINLOG_STMT_UNSAFE_NONTRANS_AFTER_TRANS, BINLOG_STMT_UNSAFE_NONTRANS_AFTER_TRANS,
/**
Mixing self-logging and non-self-logging engines in a statement
is unsafe.
*/
BINLOG_STMT_UNSAFE_MULTIPLE_ENGINES_AND_SELF_LOGGING_ENGINE,
/**
Statements that read from both transactional and non-transactional
tables and write to any of them are unsafe.
*/
BINLOG_STMT_UNSAFE_MIXED_STATEMENT,
/* The last element of this enumeration type. */ /* The last element of this enumeration type. */
BINLOG_STMT_UNSAFE_COUNT BINLOG_STMT_UNSAFE_COUNT
}; };
......
...@@ -258,6 +258,12 @@ static bool check_has_super(sys_var *self, THD *thd, set_var *var) ...@@ -258,6 +258,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) 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 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. binlog, so we can't toggle to SBR in this connection.
...@@ -289,18 +295,12 @@ static bool binlog_format_check(sys_var *self, THD *thd, set_var *var) ...@@ -289,18 +295,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. 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)); my_error(ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_BINLOG_FORMAT, MYF(0));
return true; 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; return false;
} }
...@@ -329,32 +329,31 @@ static Sys_var_enum Sys_binlog_format( ...@@ -329,32 +329,31 @@ static Sys_var_enum Sys_binlog_format(
static bool binlog_direct_check(sys_var *self, THD *thd, set_var *var) static bool binlog_direct_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;
/* /*
Makes the session variable 'binlog_direct_non_transactional_updates' Makes the session variable 'binlog_direct_non_transactional_updates'
read-only inside a transaction. read-only if within a procedure, trigger or function.
*/ */
if (thd->active_transaction() && (var->type == OPT_SESSION)) if (thd->in_sub_stmt)
{ {
my_error(ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_BINLOG_DIRECT, MYF(0)); my_error(ER_STORED_FUNCTION_PREVENTS_SWITCH_BINLOG_DIRECT, MYF(0));
return 1; return true;
} }
/* /*
Makes the session variable 'binlog_direct_non_transactional_updates' Makes the session variable 'binlog_direct_non_transactional_updates'
read-only if within a procedure, trigger or function. read-only inside a transaction.
*/ */
if (thd->in_sub_stmt) if (thd->active_transaction())
{ {
my_error(ER_STORED_FUNCTION_PREVENTS_SWITCH_BINLOG_DIRECT, MYF(0)); my_error(ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_BINLOG_DIRECT, MYF(0));
return 1; 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<my_bool>(var->save_result.ulonglong_value)))
return false;
return false; return false;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment