diff --git a/mysql-test/r/rpl_switch_stm_row_mixed.result b/mysql-test/r/rpl_switch_stm_row_mixed.result index 313037bb9dc..5d320913bfb 100644 --- a/mysql-test/r/rpl_switch_stm_row_mixed.result +++ b/mysql-test/r/rpl_switch_stm_row_mixed.result @@ -18,18 +18,18 @@ select @@global.binlog_format, @@session.binlog_format; ROW ROW CREATE TABLE t1 (a varchar(100)); prepare stmt1 from 'insert into t1 select concat(UUID(),?)'; -set @string="emergency"; -insert into t1 values("work"); +set @string="emergency_1_"; +insert into t1 values("work_2_"); execute stmt1 using @string; deallocate prepare stmt1; prepare stmt1 from 'insert into t1 select ?'; -insert into t1 values(concat(UUID(),"work")); +insert into t1 values(concat(UUID(),"work_3_")); execute stmt1 using @string; deallocate prepare stmt1; -insert into t1 values(concat("for",UUID())); -insert into t1 select "yesterday"; -create temporary table tmp(a char(3)); -insert into tmp values("see"); +insert into t1 values(concat("for_4_",UUID())); +insert into t1 select "yesterday_5_"; +create temporary table tmp(a char(100)); +insert into tmp values("see_6_"); set binlog_format=statement; ERROR HY000: Cannot switch out of the row-based binary log format when the session has open temporary tables insert into t1 select * from tmp; @@ -55,16 +55,16 @@ select @@global.binlog_format, @@session.binlog_format; @@global.binlog_format @@session.binlog_format STATEMENT STATEMENT prepare stmt1 from 'insert into t1 select ?'; -set @string="emergency"; -insert into t1 values("work"); +set @string="emergency_7_"; +insert into t1 values("work_8_"); execute stmt1 using @string; deallocate prepare stmt1; prepare stmt1 from 'insert into t1 select ?'; -insert into t1 values("work"); +insert into t1 values("work_9_"); execute stmt1 using @string; deallocate prepare stmt1; -insert into t1 values("for"); -insert into t1 select "yesterday"; +insert into t1 values("for_10_"); +insert into t1 select "yesterday_11_"; set binlog_format=default; select @@global.binlog_format, @@session.binlog_format; @@global.binlog_format @@session.binlog_format @@ -75,16 +75,16 @@ select @@global.binlog_format, @@session.binlog_format; @@global.binlog_format @@session.binlog_format STATEMENT STATEMENT prepare stmt1 from 'insert into t1 select ?'; -set @string="emergency"; -insert into t1 values("work"); +set @string="emergency_12_"; +insert into t1 values("work_13_"); execute stmt1 using @string; deallocate prepare stmt1; prepare stmt1 from 'insert into t1 select ?'; -insert into t1 values("work"); +insert into t1 values("work_14_"); execute stmt1 using @string; deallocate prepare stmt1; -insert into t1 values("for"); -insert into t1 select "yesterday"; +insert into t1 values("for_15_"); +insert into t1 select "yesterday_16_"; set binlog_format=mixed; select @@global.binlog_format, @@session.binlog_format; @@global.binlog_format @@session.binlog_format @@ -94,40 +94,40 @@ select @@global.binlog_format, @@session.binlog_format; @@global.binlog_format @@session.binlog_format MIXED MIXED prepare stmt1 from 'insert into t1 select concat(UUID(),?)'; -set @string="emergency"; -insert into t1 values("work"); +set @string="emergency_17_"; +insert into t1 values("work_18_"); execute stmt1 using @string; deallocate prepare stmt1; prepare stmt1 from 'insert into t1 select ?'; -insert into t1 values(concat(UUID(),"work")); +insert into t1 values(concat(UUID(),"work_19_")); execute stmt1 using @string; deallocate prepare stmt1; -insert into t1 values(concat("for",UUID())); -insert into t1 select "yesterday"; +insert into t1 values(concat("for_20_",UUID())); +insert into t1 select "yesterday_21_"; prepare stmt1 from 'insert into t1 select ?'; -insert into t1 values(concat(UUID(),"work")); +insert into t1 values(concat(UUID(),"work_22_")); execute stmt1 using @string; deallocate prepare stmt1; -insert into t1 values(concat("for",UUID())); -insert into t1 select "yesterday"; -create table t2 select UUID(); +insert into t1 values(concat("for_23_",UUID())); +insert into t1 select "yesterday_24_"; +create table t2 select rpad(UUID(),100,' '); create table t3 select 1 union select UUID(); create table t4 select * from t1 where 3 in (select 1 union select 2 union select UUID() union select 3); create table t5 select * from t1 where 3 in (select 1 union select 2 union select curdate() union select 3); insert into t5 select UUID() from t1 where 3 in (select 1 union select 2 union select 3 union select * from t4); create procedure foo() begin -insert into t1 values("work"); -insert into t1 values(concat("for",UUID())); -insert into t1 select "yesterday"; +insert into t1 values("work_25_"); +insert into t1 values(concat("for_26_",UUID())); +insert into t1 select "yesterday_27_"; end| create procedure foo2() begin -insert into t1 values(concat("emergency",UUID())); -insert into t1 values("work"); -insert into t1 values(concat("for",UUID())); +insert into t1 values(concat("emergency_28_",UUID())); +insert into t1 values("work_29_"); +insert into t1 values(concat("for_30_",UUID())); set session binlog_format=row; # accepted for stored procs -insert into t1 values("more work"); +insert into t1 values("more work_31_"); set session binlog_format=mixed; end| create function foo3() returns bigint unsigned @@ -136,32 +136,221 @@ set session binlog_format=row; # rejected for stored funcs insert into t1 values("alarm"); return 100; end| +create procedure foo4(x varchar(100)) +begin +insert into t1 values(concat("work_250_",x)); +insert into t1 select "yesterday_270_"; +end| call foo(); call foo2(); +call foo4("hello"); +call foo4(UUID()); +call foo4("world"); select foo3(); ERROR HY000: Cannot change the binary logging format inside a stored function or trigger select * from t1 where a="alarm"; a +drop function foo3; +create function foo3() returns bigint unsigned +begin +insert into t1 values("foo3_32_"); +call foo(); +return 100; +end| +insert into t2 select foo3(); +prepare stmt1 from 'insert into t2 select foo3()'; +execute stmt1; +execute stmt1; +deallocate prepare stmt1; +create function foo4() returns bigint unsigned +begin +insert into t2 select foo3(); +return 100; +end| +select foo4(); +foo4() +100 +prepare stmt1 from 'select foo4()'; +execute stmt1; +foo4() +100 +execute stmt1; +foo4() +100 +deallocate prepare stmt1; +create function foo5() returns bigint unsigned +begin +insert into t2 select UUID(); +return 100; +end| +select foo5(); +foo5() +100 +prepare stmt1 from 'select foo5()'; +execute stmt1; +foo5() +100 +execute stmt1; +foo5() +100 +deallocate prepare stmt1; +create function foo6(x varchar(100)) returns bigint unsigned +begin +insert into t2 select x; +return 100; +end| +select foo6("foo6_1_"); +foo6("foo6_1_") +100 +select foo6(concat("foo6_2_",UUID())); +foo6(concat("foo6_2_",UUID())) +100 +prepare stmt1 from 'select foo6(concat("foo6_3_",UUID()))'; +execute stmt1; +foo6(concat("foo6_3_",UUID())) +100 +execute stmt1; +foo6(concat("foo6_3_",UUID())) +100 +deallocate prepare stmt1; +create view v1 as select uuid(); +create table t11 (data varchar(255)); +insert into t11 select * from v1; +insert into t11 select TABLE_NAME from INFORMATION_SCHEMA.TABLES where TABLE_SCHEMA='mysqltest1' and TABLE_NAME IN ('v1','t11'); +prepare stmt1 from "insert into t11 select TABLE_NAME from INFORMATION_SCHEMA.TABLES where TABLE_SCHEMA='mysqltest1' and TABLE_NAME IN ('v1','t11')"; +execute stmt1; +execute stmt1; +deallocate prepare stmt1; +create trigger t11_bi before insert on t11 for each row +begin +set NEW.data = concat(NEW.data,UUID()); +end| +insert into t11 values("try_560_"); +create table t20 select * from t1; +create table t21 select * from t2; +create table t22 select * from t3; +drop table t1,t2,t3; +create table t1 (a int primary key auto_increment, b varchar(100)); +create table t2 (a int primary key auto_increment, b varchar(100)); +create table t3 (b varchar(100)); +create function f (x varchar(100)) returns int deterministic +begin +insert into t1 values(null,x); +insert into t2 values(null,x); +return 1; +end| +select f("try_41_"); +f("try_41_") +1 +use mysqltest1; +insert into t2 values(2,null),(3,null),(4,null); +delete from t2 where a>=2; +select f("try_42_"); +f("try_42_") +1 +insert into t2 values(3,null),(4,null); +delete from t2 where a>=3; +prepare stmt1 from 'select f(?)'; +set @string="try_43_"; +insert into t1 values(null,"try_44_"); +execute stmt1 using @string; +f(?) +1 +deallocate prepare stmt1; +create table t12 select * from t1; +drop table t1; +create table t1 (a int, b varchar(100), key(a)); +select f("try_45_"); +f("try_45_") +1 +create table t13 select * from t1; +drop table t1; +create table t1 (a int primary key auto_increment, b varchar(100)); +drop function f; +truncate table t2; +create function f1 (x varchar(100)) returns int deterministic +begin +insert into t1 values(null,x); +return 1; +end| +create function f2 (x varchar(100)) returns int deterministic +begin +insert into t2 values(null,x); +return 1; +end| +select f1("try_46_"),f2("try_47_"); +f1("try_46_") f2("try_47_") +1 1 +insert into t2 values(2,null),(3,null),(4,null); +delete from t2 where a>=2; +select f1("try_48_"),f2("try_49_"); +f1("try_48_") f2("try_49_") +1 1 +insert into t3 values(concat("try_50_",f1("try_51_"),f2("try_52_"))); +drop function f2; +create function f2 (x varchar(100)) returns int deterministic +begin +declare y int; +insert into t1 values(null,x); +set y = (select count(*) from t2); +return y; +end| +select f1("try_53_"),f2("try_54_"); +f1("try_53_") f2("try_54_") +1 3 +drop function f2; +create trigger t1_bi before insert on t1 for each row +begin +insert into t2 values(null,"try_55_"); +end| +insert into t1 values(null,"try_56_"); +alter table t1 modify a int, drop primary key; +insert into t1 values(null,"try_57_"); +CREATE TEMPORARY TABLE t15 SELECT UUID(); +create table t16 like t15; +INSERT INTO t16 SELECT * FROM t15; +insert into t16 values("try_65_"); +drop table t15; +insert into t16 values("try_66_"); select count(*) from t1; count(*) -36 +7 select count(*) from t2; count(*) -1 +5 select count(*) from t3; count(*) -2 +1 select count(*) from t4; count(*) 29 select count(*) from t5; count(*) 58 +select count(*) from t11; +count(*) +8 +select count(*) from t20; +count(*) +66 +select count(*) from t21; +count(*) +14 +select count(*) from t22; +count(*) +2 +select count(*) from t12; +count(*) +4 +select count(*) from t13; +count(*) +1 +select count(*) from t16; +count(*) +3 show binlog events from 102; Log_name Pos Event_type Server_id End_log_pos Info master-bin.000001 # Query 1 # drop database if exists mysqltest1 -master-bin.000001 # Table_map 1 # table_id: # (mysql.proc) -master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F master-bin.000001 # Query 1 # create database mysqltest1 master-bin.000001 # Query 1 # use `mysqltest1`; CREATE TABLE t1 (a varchar(100)) master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1) @@ -178,45 +367,41 @@ master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1) master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1) master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F +master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 values("work_8_") +master-bin.000001 # User var 1 # @`string`=_latin1 0x656D657267656E63795F375F COLLATE latin1_swedish_ci +master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 select @'string' +master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 values("work_9_") +master-bin.000001 # User var 1 # @`string`=_latin1 0x656D657267656E63795F375F COLLATE latin1_swedish_ci +master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 select @'string' +master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 values("for_10_") +master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 select "yesterday_11_" +master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 values("work_13_") +master-bin.000001 # User var 1 # @`string`=_latin1 0x656D657267656E63795F31325F COLLATE latin1_swedish_ci +master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 select @'string' +master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 values("work_14_") +master-bin.000001 # User var 1 # @`string`=_latin1 0x656D657267656E63795F31325F COLLATE latin1_swedish_ci +master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 select @'string' +master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 values("for_15_") +master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 select "yesterday_16_" +master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 values("work_18_") master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1) master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1) master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F -master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 values("work") -master-bin.000001 # User var 1 # @`string`=_latin1 0x656D657267656E6379 COLLATE latin1_swedish_ci -master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 select @'string' -master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 values("work") -master-bin.000001 # User var 1 # @`string`=_latin1 0x656D657267656E6379 COLLATE latin1_swedish_ci -master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 select @'string' -master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 values("for") -master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 select "yesterday" -master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 values("work") -master-bin.000001 # User var 1 # @`string`=_latin1 0x656D657267656E6379 COLLATE latin1_swedish_ci -master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 select @'string' -master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 values("work") -master-bin.000001 # User var 1 # @`string`=_latin1 0x656D657267656E6379 COLLATE latin1_swedish_ci -master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 select @'string' -master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 values("for") -master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 select "yesterday" -master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 values("work") -master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1) -master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1) -master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F -master-bin.000001 # User var 1 # @`string`=_latin1 0x656D657267656E6379 COLLATE latin1_swedish_ci +master-bin.000001 # User var 1 # @`string`=_latin1 0x656D657267656E63795F31375F COLLATE latin1_swedish_ci master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 select @'string' master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1) master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F -master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 select "yesterday" +master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 select "yesterday_21_" master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1) master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F -master-bin.000001 # User var 1 # @`string`=_latin1 0x656D657267656E6379 COLLATE latin1_swedish_ci +master-bin.000001 # User var 1 # @`string`=_latin1 0x656D657267656E63795F31375F COLLATE latin1_swedish_ci master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 select @'string' master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1) master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F -master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 select "yesterday" +master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 select "yesterday_24_" master-bin.000001 # Query 1 # use `mysqltest1`; CREATE TABLE `t2` ( - `UUID()` varchar(36) CHARACTER SET utf8 NOT NULL DEFAULT '' + `rpad(UUID(),100,' ')` varchar(100) CHARACTER SET utf8 NOT NULL DEFAULT '' ) master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t2) master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F @@ -239,17 +424,17 @@ master-bin.000001 # Write_rows 1 # table_id: # master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F master-bin.000001 # Query 1 # use `mysqltest1`; CREATE DEFINER=`root`@`localhost` procedure foo() begin -insert into t1 values("work"); -insert into t1 values(concat("for",UUID())); -insert into t1 select "yesterday"; +insert into t1 values("work_25_"); +insert into t1 values(concat("for_26_",UUID())); +insert into t1 select "yesterday_27_"; end master-bin.000001 # Query 1 # use `mysqltest1`; CREATE DEFINER=`root`@`localhost` procedure foo2() begin -insert into t1 values(concat("emergency",UUID())); -insert into t1 values("work"); -insert into t1 values(concat("for",UUID())); +insert into t1 values(concat("emergency_28_",UUID())); +insert into t1 values("work_29_"); +insert into t1 values(concat("for_30_",UUID())); set session binlog_format=row; # accepted for stored procs -insert into t1 values("more work"); +insert into t1 values("more work_31_"); set session binlog_format=mixed; end master-bin.000001 # Query 1 # use `mysqltest1`; CREATE DEFINER=`root`@`localhost` function foo3() returns bigint unsigned @@ -258,15 +443,200 @@ set session binlog_format=row; # rejected for stored funcs insert into t1 values("alarm"); return 100; end -master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 values("work") +master-bin.000001 # Query 1 # use `mysqltest1`; CREATE DEFINER=`root`@`localhost` procedure foo4(x varchar(100)) +begin +insert into t1 values(concat("work_250_",x)); +insert into t1 select "yesterday_270_"; +end +master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 values("work_25_") master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1) master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F -master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 select "yesterday" +master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 select "yesterday_27_" master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1) master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F -master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 values("work") +master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 values("work_29_") master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1) master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1) master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F +master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 values(concat("work_250_", NAME_CONST('x',... +master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 select "yesterday_270_" +master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 values(concat("work_250_", NAME_CONST('x',... +master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 select "yesterday_270_" +master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 values(concat("work_250_", NAME_CONST('x',... +master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 select "yesterday_270_" +master-bin.000001 # Query 1 # use `mysqltest1`; drop function foo3 +master-bin.000001 # Query 1 # use `mysqltest1`; CREATE DEFINER=`root`@`localhost` function foo3() returns bigint unsigned +begin +insert into t1 values("foo3_32_"); +call foo(); +return 100; +end +master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t2) +master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1) +master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1) +master-bin.000001 # Write_rows 1 # table_id: # +master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F +master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t2) +master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1) +master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1) +master-bin.000001 # Write_rows 1 # table_id: # +master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F +master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t2) +master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1) +master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1) +master-bin.000001 # Write_rows 1 # table_id: # +master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F +master-bin.000001 # Query 1 # use `mysqltest1`; CREATE DEFINER=`root`@`localhost` function foo4() returns bigint unsigned +begin +insert into t2 select foo3(); +return 100; +end +master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t2) +master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1) +master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1) +master-bin.000001 # Write_rows 1 # table_id: # +master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F +master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t2) +master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1) +master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1) +master-bin.000001 # Write_rows 1 # table_id: # +master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F +master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t2) +master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1) +master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1) +master-bin.000001 # Write_rows 1 # table_id: # +master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F +master-bin.000001 # Query 1 # use `mysqltest1`; CREATE DEFINER=`root`@`localhost` function foo5() returns bigint unsigned +begin +insert into t2 select UUID(); +return 100; +end +master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t2) +master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F +master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t2) +master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F +master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t2) +master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F +master-bin.000001 # Query 1 # use `mysqltest1`; CREATE DEFINER=`root`@`localhost` function foo6(x varchar(100)) returns bigint unsigned +begin +insert into t2 select x; +return 100; +end +master-bin.000001 # Query 1 # use `mysqltest1`; SELECT `foo6`(_latin1'foo6_1_') +master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t2) +master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F +master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t2) +master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F +master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t2) +master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F +master-bin.000001 # Query 1 # use `mysqltest1`; CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select uuid() +master-bin.000001 # Query 1 # use `mysqltest1`; create table t11 (data varchar(255)) +master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t11) +master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F +master-bin.000001 # Query 1 # use `mysqltest1`; insert into t11 select TABLE_NAME from INFORMATION_SCHEMA.TABLES where TABLE_SCHEMA='mysqltest1' and TABLE_NAME IN ('v1','t11') +master-bin.000001 # Query 1 # use `mysqltest1`; insert into t11 select TABLE_NAME from INFORMATION_SCHEMA.TABLES where TABLE_SCHEMA='mysqltest1' and TABLE_NAME IN ('v1','t11') +master-bin.000001 # Query 1 # use `mysqltest1`; insert into t11 select TABLE_NAME from INFORMATION_SCHEMA.TABLES where TABLE_SCHEMA='mysqltest1' and TABLE_NAME IN ('v1','t11') +master-bin.000001 # Query 1 # use `mysqltest1`; CREATE DEFINER=`root`@`localhost` trigger t11_bi before insert on t11 for each row +begin +set NEW.data = concat(NEW.data,UUID()); +end +master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t11) +master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F +master-bin.000001 # Query 1 # use `mysqltest1`; create table t20 select * from t1 +master-bin.000001 # Query 1 # use `mysqltest1`; create table t21 select * from t2 +master-bin.000001 # Query 1 # use `mysqltest1`; create table t22 select * from t3 +master-bin.000001 # Query 1 # use `mysqltest1`; drop table t1,t2,t3 +master-bin.000001 # Query 1 # use `mysqltest1`; create table t1 (a int primary key auto_increment, b varchar(100)) +master-bin.000001 # Query 1 # use `mysqltest1`; create table t2 (a int primary key auto_increment, b varchar(100)) +master-bin.000001 # Query 1 # use `mysqltest1`; create table t3 (b varchar(100)) +master-bin.000001 # Query 1 # use `mysqltest1`; CREATE DEFINER=`root`@`localhost` function f (x varchar(100)) returns int deterministic +begin +insert into t1 values(null,x); +insert into t2 values(null,x); +return 1; +end +master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t2) +master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1) +master-bin.000001 # Write_rows 1 # table_id: # +master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F +master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t2) +master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1) +master-bin.000001 # Write_rows 1 # table_id: # +master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F +master-bin.000001 # Intvar 1 # INSERT_ID=3 +master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 values(null,"try_44_") +master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t2) +master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1) +master-bin.000001 # Write_rows 1 # table_id: # +master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F +master-bin.000001 # Query 1 # use `mysqltest1`; create table t12 select * from t1 +master-bin.000001 # Query 1 # use `mysqltest1`; drop table t1 +master-bin.000001 # Query 1 # use `mysqltest1`; create table t1 (a int, b varchar(100), key(a)) +master-bin.000001 # Intvar 1 # INSERT_ID=4 +master-bin.000001 # Query 1 # use `mysqltest1`; SELECT `f`(_latin1'try_45_') +master-bin.000001 # Query 1 # use `mysqltest1`; create table t13 select * from t1 +master-bin.000001 # Query 1 # use `mysqltest1`; drop table t1 +master-bin.000001 # Query 1 # use `mysqltest1`; create table t1 (a int primary key auto_increment, b varchar(100)) +master-bin.000001 # Query 1 # use `mysqltest1`; drop function f +master-bin.000001 # Query 1 # use `mysqltest1`; truncate table t2 +master-bin.000001 # Query 1 # use `mysqltest1`; CREATE DEFINER=`root`@`localhost` function f1 (x varchar(100)) returns int deterministic +begin +insert into t1 values(null,x); +return 1; +end +master-bin.000001 # Query 1 # use `mysqltest1`; CREATE DEFINER=`root`@`localhost` function f2 (x varchar(100)) returns int deterministic +begin +insert into t2 values(null,x); +return 1; +end +master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1) +master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t2) +master-bin.000001 # Write_rows 1 # table_id: # +master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F +master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1) +master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t2) +master-bin.000001 # Write_rows 1 # table_id: # +master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F +master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t3) +master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1) +master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t2) +master-bin.000001 # Write_rows 1 # table_id: # +master-bin.000001 # Write_rows 1 # table_id: # +master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F +master-bin.000001 # Query 1 # use `mysqltest1`; drop function f2 +master-bin.000001 # Query 1 # use `mysqltest1`; CREATE DEFINER=`root`@`localhost` function f2 (x varchar(100)) returns int deterministic +begin +declare y int; +insert into t1 values(null,x); +set y = (select count(*) from t2); +return y; +end +master-bin.000001 # Intvar 1 # INSERT_ID=4 +master-bin.000001 # Query 1 # use `mysqltest1`; SELECT `f1`(_latin1'try_53_') +master-bin.000001 # Intvar 1 # INSERT_ID=5 +master-bin.000001 # Query 1 # use `mysqltest1`; SELECT `f2`(_latin1'try_54_') +master-bin.000001 # Query 1 # use `mysqltest1`; drop function f2 +master-bin.000001 # Query 1 # use `mysqltest1`; CREATE DEFINER=`root`@`localhost` trigger t1_bi before insert on t1 for each row +begin +insert into t2 values(null,"try_55_"); +end +master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1) +master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t2) +master-bin.000001 # Write_rows 1 # table_id: # +master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F +master-bin.000001 # Query 1 # use `mysqltest1`; alter table t1 modify a int, drop primary key +master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 values(null,"try_57_") +master-bin.000001 # Query 1 # use `mysqltest1`; CREATE TEMPORARY TABLE `t15` ( + `UUID()` varchar(36) CHARACTER SET utf8 NOT NULL DEFAULT '' +) +master-bin.000001 # Query 1 # use `mysqltest1`; COMMIT +master-bin.000001 # Query 1 # use `mysqltest1`; CREATE TABLE `t16` ( + `UUID()` varchar(36) CHARACTER SET utf8 NOT NULL DEFAULT '' +) +master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t16) +master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F +master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t16) +master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F +master-bin.000001 # Query 1 # use `mysqltest1`; insert into t16 values("try_66_") drop database mysqltest1; diff --git a/mysql-test/t/disabled.def b/mysql-test/t/disabled.def index 6f26847f8d7..a0b61f21047 100644 --- a/mysql-test/t/disabled.def +++ b/mysql-test/t/disabled.def @@ -32,7 +32,6 @@ rpl_ndb_ddl : BUG#18946 result file needs update + test needs to ch rpl_ndb_innodb2ndb : Bug #19710 Cluster replication to partition table fails on DELETE FROM statement #rpl_ndb_log : BUG#18947 2006-03-21 tomas CRBR: order in binlog of create table and insert (on different table) not determ rpl_ndb_myisam2ndb : Bug #19710 Cluster replication to partition table fails on DELETE FROM statement -rpl_switch_stm_row_mixed : BUG#18590 2006-03-28 brian rpl_row_blob_innodb : BUG#18980 2006-04-10 kent Test fails randomly rpl_row_func003 : BUG#19074 2006-13-04 andrei test failed rpl_sp : BUG#16456 2006-02-16 jmiller diff --git a/mysql-test/t/rpl_switch_stm_row_mixed.test b/mysql-test/t/rpl_switch_stm_row_mixed.test index 4a79b3995c4..ee86a769820 100644 --- a/mysql-test/t/rpl_switch_stm_row_mixed.test +++ b/mysql-test/t/rpl_switch_stm_row_mixed.test @@ -15,22 +15,22 @@ select @@global.binlog_format, @@session.binlog_format; CREATE TABLE t1 (a varchar(100)); prepare stmt1 from 'insert into t1 select concat(UUID(),?)'; -set @string="emergency"; -insert into t1 values("work"); +set @string="emergency_1_"; +insert into t1 values("work_2_"); execute stmt1 using @string; deallocate prepare stmt1; prepare stmt1 from 'insert into t1 select ?'; -insert into t1 values(concat(UUID(),"work")); +insert into t1 values(concat(UUID(),"work_3_")); execute stmt1 using @string; deallocate prepare stmt1; -insert into t1 values(concat("for",UUID())); -insert into t1 select "yesterday"; +insert into t1 values(concat("for_4_",UUID())); +insert into t1 select "yesterday_5_"; # verify that temp tables prevent a switch to SBR -create temporary table tmp(a char(3)); -insert into tmp values("see"); +create temporary table tmp(a char(100)); +insert into tmp values("see_6_"); --error ER_TEMP_TABLE_PREVENTS_SWITCH_OUT_OF_RBR set binlog_format=statement; insert into t1 select * from tmp; @@ -47,18 +47,18 @@ show session variables like "binlog_format%"; select @@global.binlog_format, @@session.binlog_format; prepare stmt1 from 'insert into t1 select ?'; -set @string="emergency"; -insert into t1 values("work"); +set @string="emergency_7_"; +insert into t1 values("work_8_"); execute stmt1 using @string; deallocate prepare stmt1; prepare stmt1 from 'insert into t1 select ?'; -insert into t1 values("work"); +insert into t1 values("work_9_"); execute stmt1 using @string; deallocate prepare stmt1; -insert into t1 values("for"); -insert into t1 select "yesterday"; +insert into t1 values("for_10_"); +insert into t1 select "yesterday_11_"; # test SET DEFAULT (=statement at this point of test) set binlog_format=default; @@ -69,18 +69,18 @@ set global binlog_format=default; select @@global.binlog_format, @@session.binlog_format; prepare stmt1 from 'insert into t1 select ?'; -set @string="emergency"; -insert into t1 values("work"); +set @string="emergency_12_"; +insert into t1 values("work_13_"); execute stmt1 using @string; deallocate prepare stmt1; prepare stmt1 from 'insert into t1 select ?'; -insert into t1 values("work"); +insert into t1 values("work_14_"); execute stmt1 using @string; deallocate prepare stmt1; -insert into t1 values("for"); -insert into t1 select "yesterday"; +insert into t1 values("for_15_"); +insert into t1 select "yesterday_16_"; # and now the mixed mode @@ -90,53 +90,52 @@ set global binlog_format=mixed; select @@global.binlog_format, @@session.binlog_format; prepare stmt1 from 'insert into t1 select concat(UUID(),?)'; -set @string="emergency"; -insert into t1 values("work"); +set @string="emergency_17_"; +insert into t1 values("work_18_"); execute stmt1 using @string; deallocate prepare stmt1; prepare stmt1 from 'insert into t1 select ?'; -insert into t1 values(concat(UUID(),"work")); +insert into t1 values(concat(UUID(),"work_19_")); execute stmt1 using @string; deallocate prepare stmt1; -insert into t1 values(concat("for",UUID())); -insert into t1 select "yesterday"; +insert into t1 values(concat("for_20_",UUID())); +insert into t1 select "yesterday_21_"; prepare stmt1 from 'insert into t1 select ?'; -insert into t1 values(concat(UUID(),"work")); +insert into t1 values(concat(UUID(),"work_22_")); execute stmt1 using @string; deallocate prepare stmt1; -insert into t1 values(concat("for",UUID())); -insert into t1 select "yesterday"; +insert into t1 values(concat("for_23_",UUID())); +insert into t1 select "yesterday_24_"; # Test of CREATE TABLE SELECT -create table t2 select UUID(); +create table t2 select rpad(UUID(),100,' '); create table t3 select 1 union select UUID(); create table t4 select * from t1 where 3 in (select 1 union select 2 union select UUID() union select 3); create table t5 select * from t1 where 3 in (select 1 union select 2 union select curdate() union select 3); # what if UUID() is first: insert into t5 select UUID() from t1 where 3 in (select 1 union select 2 union select 3 union select * from t4); -# inside a stored procedure (inside a function or trigger won't -# work) +# inside a stored procedure delimiter |; create procedure foo() begin -insert into t1 values("work"); -insert into t1 values(concat("for",UUID())); -insert into t1 select "yesterday"; +insert into t1 values("work_25_"); +insert into t1 values(concat("for_26_",UUID())); +insert into t1 select "yesterday_27_"; end| create procedure foo2() begin -insert into t1 values(concat("emergency",UUID())); -insert into t1 values("work"); -insert into t1 values(concat("for",UUID())); +insert into t1 values(concat("emergency_28_",UUID())); +insert into t1 values("work_29_"); +insert into t1 values(concat("for_30_",UUID())); set session binlog_format=row; # accepted for stored procs -insert into t1 values("more work"); +insert into t1 values("more work_31_"); set session binlog_format=mixed; end| create function foo3() returns bigint unsigned @@ -145,15 +144,116 @@ begin insert into t1 values("alarm"); return 100; end| +create procedure foo4(x varchar(100)) +begin +insert into t1 values(concat("work_250_",x)); +insert into t1 select "yesterday_270_"; +end| delimiter ;| call foo(); call foo2(); +call foo4("hello"); +call foo4(UUID()); +call foo4("world"); # test that can't SET in a stored function --error ER_STORED_FUNCTION_PREVENTS_SWITCH_BINLOG_FORMAT select foo3(); select * from t1 where a="alarm"; +# Tests of stored functions/triggers/views for BUG#20930 "Mixed +# binlogging mode does not work with stored functions, triggers, +# views" + +# Function which calls procedure +drop function foo3; +delimiter |; +create function foo3() returns bigint unsigned +begin + insert into t1 values("foo3_32_"); + call foo(); + return 100; +end| +delimiter ;| +insert into t2 select foo3(); + +prepare stmt1 from 'insert into t2 select foo3()'; +execute stmt1; +execute stmt1; +deallocate prepare stmt1; + +# Test if stored function calls stored function which calls procedure +# which requires row-based. + +delimiter |; +create function foo4() returns bigint unsigned +begin + insert into t2 select foo3(); + return 100; +end| +delimiter ;| +select foo4(); + +prepare stmt1 from 'select foo4()'; +execute stmt1; +execute stmt1; +deallocate prepare stmt1; + +# A simple stored function +delimiter |; +create function foo5() returns bigint unsigned +begin + insert into t2 select UUID(); + return 100; +end| +delimiter ;| +select foo5(); + +prepare stmt1 from 'select foo5()'; +execute stmt1; +execute stmt1; +deallocate prepare stmt1; + +# A simple stored function where UUID() is in the argument +delimiter |; +create function foo6(x varchar(100)) returns bigint unsigned +begin + insert into t2 select x; + return 100; +end| +delimiter ;| +select foo6("foo6_1_"); +select foo6(concat("foo6_2_",UUID())); + +prepare stmt1 from 'select foo6(concat("foo6_3_",UUID()))'; +execute stmt1; +execute stmt1; +deallocate prepare stmt1; + + +# Test of views using UUID() + +create view v1 as select uuid(); +create table t11 (data varchar(255)); +insert into t11 select * from v1; +# Test of querying INFORMATION_SCHEMA which parses the view's body, +# to verify that it binlogs statement-based (is not polluted by +# the parsing of the view's body). +insert into t11 select TABLE_NAME from INFORMATION_SCHEMA.TABLES where TABLE_SCHEMA='mysqltest1' and TABLE_NAME IN ('v1','t11'); +prepare stmt1 from "insert into t11 select TABLE_NAME from INFORMATION_SCHEMA.TABLES where TABLE_SCHEMA='mysqltest1' and TABLE_NAME IN ('v1','t11')"; +execute stmt1; +execute stmt1; +deallocate prepare stmt1; + +# Test of triggers with UUID() +delimiter |; +create trigger t11_bi before insert on t11 for each row +begin + set NEW.data = concat(NEW.data,UUID()); +end| +delimiter ;| +insert into t11 values("try_560_"); + # If you want to do manual testing of the mixed mode regarding UDFs (not # testable automatically as quite platform- and compiler-dependent), # you just need to set the variable below to 1, and to @@ -164,30 +264,182 @@ if ($you_want_to_test_UDF) { CREATE FUNCTION metaphon RETURNS STRING SONAME 'udf_example.so'; prepare stmt1 from 'insert into t1 select metaphon(?)'; - set @string="emergency"; - insert into t1 values("work"); + set @string="emergency_133_"; + insert into t1 values("work_134_"); execute stmt1 using @string; deallocate prepare stmt1; prepare stmt1 from 'insert into t1 select ?'; - insert into t1 values(metaphon("work")); + insert into t1 values(metaphon("work_135_")); execute stmt1 using @string; deallocate prepare stmt1; - insert into t1 values(metaphon("for")); - insert into t1 select "yesterday"; - create table t6 select metaphon("for"); - create table t7 select 1 union select metaphon("for"); - create table t8 select * from t1 where 3 in (select 1 union select 2 union select metaphon("for") union select 3); + insert into t1 values(metaphon("for_136_")); + insert into t1 select "yesterday_137_"; + create table t6 select metaphon("for_138_"); + create table t7 select 1 union select metaphon("for_139_"); + create table t8 select * from t1 where 3 in (select 1 union select 2 union select metaphon("for_140_") union select 3); create table t9 select * from t1 where 3 in (select 1 union select 2 union select curdate() union select 3); } +create table t20 select * from t1; # save for comparing later +create table t21 select * from t2; +create table t22 select * from t3; +drop table t1,t2,t3; + +# This tests the fix to +# BUG#19630 stored function inserting into two auto_increment breaks statement-based binlog +# We verify that under the mixed binlog mode, a stored function +# modifying at least two tables having an auto_increment column, +# is binlogged row-based. Indeed in statement-based binlogging, +# only the auto_increment value generated for the first table +# is recorded in the binlog, the value generated for the 2nd table +# lacking. + +create table t1 (a int primary key auto_increment, b varchar(100)); +create table t2 (a int primary key auto_increment, b varchar(100)); +create table t3 (b varchar(100)); +delimiter |; +create function f (x varchar(100)) returns int deterministic +begin + insert into t1 values(null,x); + insert into t2 values(null,x); + return 1; +end| +delimiter ;| +select f("try_41_"); +# Two operations which compensate each other except that their net +# effect is that they advance the auto_increment counter of t2 on slave: +sync_slave_with_master; +use mysqltest1; +insert into t2 values(2,null),(3,null),(4,null); +delete from t2 where a>=2; + +connection master; +# this is the call which didn't replicate well +select f("try_42_"); +sync_slave_with_master; + +# now use prepared statement and test again, just to see that the RBB +# mode isn't set at PREPARE but at EXECUTE. + +insert into t2 values(3,null),(4,null); +delete from t2 where a>=3; + +connection master; +prepare stmt1 from 'select f(?)'; +set @string="try_43_"; +insert into t1 values(null,"try_44_"); # should be SBB +execute stmt1 using @string; # should be RBB +deallocate prepare stmt1; +sync_slave_with_master; + +# verify that if only one table has auto_inc, it does not trigger RBB +# (we'll check in binlog further below) + +connection master; +create table t12 select * from t1; # save for comparing later +drop table t1; +create table t1 (a int, b varchar(100), key(a)); +select f("try_45_"); + +# restore table's key +create table t13 select * from t1; +drop table t1; +create table t1 (a int primary key auto_increment, b varchar(100)); + +# now test if it's two functions, each of them inserts in one table + +drop function f; +# Manifestation of BUG#20341! re-enable this line after merging fix +# for that bug +#create table t14 select * from t2; +truncate table t2; +delimiter |; +create function f1 (x varchar(100)) returns int deterministic +begin + insert into t1 values(null,x); + return 1; +end| +create function f2 (x varchar(100)) returns int deterministic +begin + insert into t2 values(null,x); + return 1; +end| +delimiter ;| +select f1("try_46_"),f2("try_47_"); + +sync_slave_with_master; +insert into t2 values(2,null),(3,null),(4,null); +delete from t2 where a>=2; + +connection master; +# Test with SELECT and INSERT +select f1("try_48_"),f2("try_49_"); +insert into t3 values(concat("try_50_",f1("try_51_"),f2("try_52_"))); +sync_slave_with_master; + +# verify that if f2 does only read on an auto_inc table, this does not +# switch to RBB +connection master; +drop function f2; +delimiter |; +create function f2 (x varchar(100)) returns int deterministic +begin + declare y int; + insert into t1 values(null,x); + set y = (select count(*) from t2); + return y; +end| +delimiter ;| +select f1("try_53_"),f2("try_54_"); +sync_slave_with_master; + +# And now, a normal statement with a trigger (no stored functions) + +connection master; +drop function f2; +delimiter |; +create trigger t1_bi before insert on t1 for each row +begin + insert into t2 values(null,"try_55_"); +end| +delimiter ;| +insert into t1 values(null,"try_56_"); +# and now remove one auto_increment and verify SBB +alter table t1 modify a int, drop primary key; +insert into t1 values(null,"try_57_"); +sync_slave_with_master; + +# Test for BUG#20499 "mixed mode with temporary table breaks binlog" +# Slave used to have only 2 rows instead of 3. +connection master; +CREATE TEMPORARY TABLE t15 SELECT UUID(); +create table t16 like t15; +INSERT INTO t16 SELECT * FROM t15; +# we'll verify that this one is done RBB +insert into t16 values("try_65_"); +drop table t15; +# we'll verify that this one is done SBB +insert into t16 values("try_66_"); +sync_slave_with_master; + # and now compare: +connection master; + # first check that data on master is sensible select count(*) from t1; select count(*) from t2; select count(*) from t3; select count(*) from t4; select count(*) from t5; +select count(*) from t11; +select count(*) from t20; +select count(*) from t21; +select count(*) from t22; +select count(*) from t12; +select count(*) from t13; +#select count(*) from t14; +select count(*) from t16; if ($you_want_to_test_UDF) { select count(*) from t6; @@ -196,21 +448,48 @@ if ($you_want_to_test_UDF) select count(*) from t9; } ---replace_column 2 # 5 # ---replace_regex /table_id: [0-9]+/table_id: #/ -show binlog events from 102; sync_slave_with_master; # as we're using UUID we don't SELECT but use "diff" like in rpl_row_UUID --exec $MYSQL_DUMP --compact --order-by-primary --skip-extended-insert --no-create-info mysqltest1 > $MYSQLTEST_VARDIR/tmp/rpl_switch_stm_row_mixed_master.sql --exec $MYSQL_DUMP_SLAVE --compact --order-by-primary --skip-extended-insert --no-create-info mysqltest1 > $MYSQLTEST_VARDIR/tmp/rpl_switch_stm_row_mixed_slave.sql -connection master; -drop database mysqltest1; -sync_slave_with_master; - # Let's compare. Note: If they match test will pass, if they do not match # the test will show that the diff statement failed and not reject file # will be created. You will need to go to the mysql-test dir and diff # the files your self to see what is not matching --exec diff $MYSQLTEST_VARDIR/tmp/rpl_switch_stm_row_mixed_master.sql $MYSQLTEST_VARDIR/tmp/rpl_switch_stm_row_mixed_slave.sql; + +connection master; +# As one stored function's parameter is UUID(), its value ends up in a +# NAME_CONST in the binlog, we must hide it for repeatability +--replace_column 2 # 5 # +--replace_regex /table_id: [0-9]+/table_id: #/ /NAME_CONST\('x',.*/NAME_CONST('x',.../ +show binlog events from 102; + +# Now test that mysqlbinlog works fine on a binlog generated by the +# mixed mode + +# BUG#11312 "DELIMITER is not written to the binary log that causes +# syntax error" makes that mysqlbinlog will fail if we pass it the +# text of queries; this forces us to use --base64-output here. + +# BUG#20929 "BINLOG command causes invalid free plus assertion +# failure" makes mysqld segfault when receiving --base64-output + +# So I can't enable this piece of test +# SIGH + +if ($enable_when_11312_or_20929_fixed) +{ +--exec $MYSQL_BINLOG --base64-output $MYSQLTEST_VARDIR/log/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/mysqlbinlog_mixed.sql +drop database mysqltest1; +--exec $MYSQL < $MYSQLTEST_VARDIR/tmp/mysqlbinlog_mixed.sql +--exec $MYSQL_DUMP --compact --order-by-primary --skip-extended-insert --no-create-info mysqltest1 > $MYSQLTEST_VARDIR/tmp/rpl_switch_stm_row_mixed_master.sql +# the old mysqldump output on slave is the same as what it was on +# master before restoring on master. +--exec diff $MYSQLTEST_VARDIR/tmp/rpl_switch_stm_row_mixed_master.sql $MYSQLTEST_VARDIR/tmp/rpl_switch_stm_row_mixed_slave.sql; +} + +drop database mysqltest1; +sync_slave_with_master; diff --git a/sql/item_create.cc b/sql/item_create.cc index 6eca6209438..bf4af2232f7 100644 --- a/sql/item_create.cc +++ b/sql/item_create.cc @@ -426,7 +426,9 @@ Item *create_func_unhex(Item* a) Item *create_func_uuid(void) { THD *thd= current_thd; - thd->lex->binlog_row_based_if_mixed= 1; +#ifdef HAVE_ROW_BASED_REPLICATION + thd->lex->binlog_row_based_if_mixed= TRUE; +#endif return new(thd->mem_root) Item_func_uuid(); } diff --git a/sql/set_var.cc b/sql/set_var.cc index b0ecc7eccef..cac23673016 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -1343,9 +1343,9 @@ bool sys_var_thd_binlog_format::is_readonly() const return 1; } /* - if in a stored function, it's too late to change mode + if in a stored function/trigger, it's too late to change mode */ - if (thd->spcont && thd->prelocked_mode) + if (thd->in_sub_stmt) { my_error(ER_STORED_FUNCTION_PREVENTS_SWITCH_BINLOG_FORMAT, MYF(0)); return 1; diff --git a/sql/sp.cc b/sql/sp.cc index 93e21170156..eb5bc7ecc14 100644 --- a/sql/sp.cc +++ b/sql/sp.cc @@ -1632,6 +1632,7 @@ sp_cache_routines_and_add_tables_aux(THD *thd, LEX *lex, sp->add_used_tables_to_table_list(thd, &lex->query_tables_last, rt->belong_to_view); } + sp->propagate_attributes(lex); } first= FALSE; } @@ -1729,14 +1730,16 @@ sp_cache_routines_and_add_tables_for_triggers(THD *thd, LEX *lex, { for (int j= 0; j < (int)TRG_ACTION_MAX; j++) { - if (triggers->bodies[i][j]) + sp_head *trigger_body= triggers->bodies[i][j]; + if (trigger_body) { - (void)triggers->bodies[i][j]-> - add_used_tables_to_table_list(thd, &lex->query_tables_last, - table->belong_to_view); + (void)trigger_body-> + add_used_tables_to_table_list(thd, &lex->query_tables_last, + table->belong_to_view); sp_update_stmt_used_routines(thd, lex, - &triggers->bodies[i][j]->m_sroutines, + &trigger_body->m_sroutines, table->belong_to_view); + trigger_body->propagate_attributes(lex); } } } diff --git a/sql/sp_head.cc b/sql/sp_head.cc index 88460337526..b486aad1be4 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -1675,6 +1675,16 @@ sp_head::restore_lex(THD *thd) oldlex->next_state= sublex->next_state; oldlex->trg_table_fields.push_back(&sublex->trg_table_fields); +#ifdef HAVE_ROW_BASED_REPLICATION + /* + If this substatement needs row-based, the entire routine does too (we + cannot switch from statement-based to row-based only for this + substatement). + */ + if (sublex->binlog_row_based_if_mixed) + m_flags|= BINLOG_ROW_BASED_IF_MIXED; +#endif + /* Add routines which are used by statement to respective set for this routine. diff --git a/sql/sp_head.h b/sql/sp_head.h index 791343f0061..0ad0c496b7e 100644 --- a/sql/sp_head.h +++ b/sql/sp_head.h @@ -126,7 +126,8 @@ public: /* Is set if a procedure with COMMIT (implicit or explicit) | ROLLBACK */ HAS_COMMIT_OR_ROLLBACK= 128, LOG_SLOW_STATEMENTS= 256, // Used by events - LOG_GENERAL_LOG= 512 // Used by events + LOG_GENERAL_LOG= 512, // Used by events + BINLOG_ROW_BASED_IF_MIXED= 1024 }; /* TYPE_ENUM_FUNCTION, TYPE_ENUM_PROCEDURE or TYPE_ENUM_TRIGGER */ @@ -351,6 +352,25 @@ public: int show_routine_code(THD *thd); #endif + /* + This method is intended for attributes of a routine which need + to propagate upwards to the LEX of the caller (when a property of a + sp_head needs to "taint" the caller). + */ + void propagate_attributes(LEX *lex) + { +#ifdef HAVE_ROW_BASED_REPLICATION + /* + If this routine needs row-based binary logging, the entire top statement + too (we cannot switch from statement-based to row-based only for this + routine, as in statement-based the top-statement may be binlogged and + the substatements not). + */ + if (m_flags & BINLOG_ROW_BASED_IF_MIXED) + lex->binlog_row_based_if_mixed= TRUE; +#endif + } + private: diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 5b039f6bcc0..98877cd5770 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -49,6 +49,8 @@ static bool open_new_frm(THD *thd, TABLE_SHARE *share, const char *alias, static void close_old_data_files(THD *thd, TABLE *table, bool abort_locks, bool send_refresh); static bool reopen_table(TABLE *table); +static bool +has_two_write_locked_tables_with_auto_increment(TABLE_LIST *tables); extern "C" byte *table_cache_key(const byte *record,uint *length, @@ -3315,6 +3317,18 @@ int lock_tables(THD *thd, TABLE_LIST *tables, uint count, bool *need_reopen) *need_reopen= FALSE; +#ifdef HAVE_ROW_BASED_REPLICATION + /* + CREATE ... SELECT UUID() locks no tables, we have to test here. + Note that we will not do the resetting if inside a stored + function/trigger, because the binlogging of those is decided earlier (by + the caller) and can't be changed afterwards. + */ + thd->reset_current_stmt_binlog_row_based(); + if (thd->lex->binlog_row_based_if_mixed) + thd->set_current_stmt_binlog_row_based_if_mixed(); +#endif /*HAVE_ROW_BASED_REPLICATION*/ + if (!tables) DBUG_RETURN(0); @@ -3345,6 +3359,19 @@ int lock_tables(THD *thd, TABLE_LIST *tables, uint count, bool *need_reopen) { thd->in_lock_tables=1; thd->options|= OPTION_TABLE_LOCK; +#ifdef HAVE_ROW_BASED_REPLICATION + /* + If we have >= 2 different tables to update with auto_inc columns, + statement-based binlogging won't work. We can solve this problem in + mixed mode by switching to row-based binlogging: + */ + if (thd->variables.binlog_format == BINLOG_FORMAT_MIXED && + has_two_write_locked_tables_with_auto_increment(tables)) + { + thd->lex->binlog_row_based_if_mixed= TRUE; + thd->set_current_stmt_binlog_row_based_if_mixed(); + } +#endif } if (! (thd->lock= mysql_lock_tables(thd, start, (uint) (ptr - start), @@ -6477,3 +6504,46 @@ void mysql_wait_completed_table(ALTER_PARTITION_PARAM_TYPE *lpt, TABLE *my_table DBUG_VOID_RETURN; } + +/* + Tells if two (or more) tables have auto_increment columns and we want to + lock those tables with a write lock. + + SYNOPSIS + has_two_write_locked_tables_with_auto_increment + tables Table list + + NOTES: + Call this function only when you have established the list of all tables + which you'll want to update (including stored functions, triggers, views + inside your statement). + + RETURN + 0 No + 1 Yes +*/ + +static bool +has_two_write_locked_tables_with_auto_increment(TABLE_LIST *tables) +{ + char *first_table_name= NULL, *first_db; + for (TABLE_LIST *table= tables; table; table= table->next_global) + { + /* we must do preliminary checks as table->table may be NULL */ + if (!table->placeholder() && !table->schema_table && + table->table->found_next_number_field && + (table->lock_type >= TL_WRITE_ALLOW_WRITE)) + { + if (first_table_name == NULL) + { + first_table_name= table->table_name; + first_db= table->db; + DBUG_ASSERT(first_db); + } + else if (strcmp(first_db, table->db) || + strcmp(first_table_name, table->table_name)) + return 1; + } + } + return 0; +} diff --git a/sql/sql_class.h b/sql/sql_class.h index 5222e75f309..8fa6db4506b 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -1418,7 +1418,17 @@ public: inline void set_current_stmt_binlog_row_based_if_mixed() { #ifdef HAVE_ROW_BASED_REPLICATION - if (variables.binlog_format == BINLOG_FORMAT_MIXED) + /* + If in a stored/function trigger, the caller should already have done the + change. We test in_sub_stmt to prevent introducing bugs where people + wouldn't ensure that, and would switch to row-based mode in the middle + of executing a stored function/trigger (which is too late, see also + reset_current_stmt_binlog_row_based()); this condition will make their + tests fail and so force them to propagate the + lex->binlog_row_based_if_mixed upwards to the caller. + */ + if ((variables.binlog_format == BINLOG_FORMAT_MIXED) && + (in_sub_stmt == 0)) current_stmt_binlog_row_based= TRUE; #endif } @@ -1437,8 +1447,26 @@ public: inline void reset_current_stmt_binlog_row_based() { #ifdef HAVE_ROW_BASED_REPLICATION - current_stmt_binlog_row_based= - test(variables.binlog_format == BINLOG_FORMAT_ROW); + /* + If there are temporary tables, don't reset back to + statement-based. Indeed it could be that: + CREATE TEMPORARY TABLE t SELECT UUID(); # row-based + # and row-based does not store updates to temp tables + # in the binlog. + INSERT INTO u SELECT * FROM t; # stmt-based + and then the INSERT will fail as data inserted into t was not logged. + So we continue with row-based until the temp table is dropped. + If we are in a stored function or trigger, we mustn't reset in the + middle of its execution (as the binary logging way of a stored function + or trigger is decided when it starts executing, depending for example on + the caller (for a stored function: if caller is SELECT or + INSERT/UPDATE/DELETE...). + */ + if ((temporary_tables == NULL) && (in_sub_stmt == 0)) + { + current_stmt_binlog_row_based= + test(variables.binlog_format == BINLOG_FORMAT_ROW); + } #else current_stmt_binlog_row_based= FALSE; #endif diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index f6031a1f2fd..7e24436fc39 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -183,7 +183,6 @@ void lex_start(THD *thd, const uchar *buf, uint length) lex->nest_level=0 ; lex->allow_sum_func= 0; lex->in_sum_func= NULL; - lex->binlog_row_based_if_mixed= 0; DBUG_VOID_RETURN; } @@ -1625,6 +1624,9 @@ void Query_tables_list::reset_query_tables_list(bool init) sroutines_list.empty(); sroutines_list_own_last= sroutines_list.next; sroutines_list_own_elements= 0; +#ifdef HAVE_ROW_BASED_REPLICATION + binlog_row_based_if_mixed= FALSE; +#endif } diff --git a/sql/sql_lex.h b/sql/sql_lex.h index a46aaa0bab7..9d8a918e2a3 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -793,6 +793,16 @@ public: byte **sroutines_list_own_last; uint sroutines_list_own_elements; +#ifdef HAVE_ROW_BASED_REPLICATION + /* + Tells if the parsing stage detected that some items require row-based + binlogging to give a reliable binlog/replication, or if we will use + stored functions or triggers which themselves need require row-based + binlogging. + */ + bool binlog_row_based_if_mixed; +#endif + /* These constructor and destructor serve for creation/destruction of Query_tables_list instances which are used as backup storage. @@ -970,11 +980,7 @@ typedef struct st_lex : public Query_tables_list uint8 create_view_check; bool drop_if_exists, drop_temporary, local_file, one_shot_set; bool in_comment, ignore_space, verbose, no_write_to_binlog; - /* - binlog_row_based_if_mixed tells if the parsing stage detected that some - items require row-based binlogging to give a reliable binlog/replication. - */ - bool tx_chain, tx_release, binlog_row_based_if_mixed; + bool tx_chain, tx_release; /* Special JOIN::prepare mode: changing of query is prohibited. When creating a view, we need to just check its syntax omitting diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 232df095816..1e89e9466ad 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -2503,11 +2503,6 @@ mysql_execute_command(THD *thd) statistic_increment(thd->status_var.com_stat[lex->sql_command], &LOCK_status); -#ifdef HAVE_ROW_BASED_REPLICATION - if (lex->binlog_row_based_if_mixed) - thd->set_current_stmt_binlog_row_based_if_mixed(); -#endif /*HAVE_ROW_BASED_REPLICATION*/ - switch (lex->sql_command) { case SQLCOM_SHOW_EVENTS: if ((res= check_access(thd, EVENT_ACL, thd->lex->select_lex.db, 0, 0, 0, @@ -5166,9 +5161,6 @@ end: */ if (thd->one_shot_set && lex->sql_command != SQLCOM_SET_OPTION) reset_one_shot_variables(thd); -#ifdef HAVE_ROW_BASED_REPLICATION - thd->reset_current_stmt_binlog_row_based(); -#endif /*HAVE_ROW_BASED_REPLICATION*/ /* The return value for ROW_COUNT() is "implementation dependent" if the @@ -5846,6 +5838,11 @@ void mysql_reset_thd_for_next_command(THD *thd) thd->rand_used= 0; thd->sent_row_count= thd->examined_row_count= 0; } +#ifdef HAVE_ROW_BASED_REPLICATION + /* If in a routine, we reset only at end of top statement. */ + thd->reset_current_stmt_binlog_row_based(); +#endif /*HAVE_ROW_BASED_REPLICATION*/ + DBUG_VOID_RETURN; } diff --git a/sql/sql_view.cc b/sql/sql_view.cc index d1e7ba80ecf..c81c4294e1c 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -997,6 +997,15 @@ bool mysql_make_view(THD *thd, File_parser *parser, TABLE_LIST *table) table->next_global= view_tables; } +#ifdef HAVE_ROW_BASED_REPLICATION + /* + If the view's body needs row-based binlogging (e.g. the VIEW is created + from SELECT UUID()), the top statement also needs it. + */ + if (lex->binlog_row_based_if_mixed) + old_lex->binlog_row_based_if_mixed= TRUE; +#endif + /* If we are opening this view as part of implicit LOCK TABLES, then this view serves as simple placeholder and we should not continue diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 0632e2298cd..6d989feb4ce 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -6374,7 +6374,7 @@ simple_expr: if (udf->type == UDFTYPE_AGGREGATE) Select->in_sum_expr--; - Lex->binlog_row_based_if_mixed= 1; + Lex->binlog_row_based_if_mixed= TRUE; switch (udf->returns) { case STRING_RESULT: