diff --git a/mysql-test/extra/rpl_tests/rpl_log.test b/mysql-test/extra/rpl_tests/rpl_log.test index b3a0b513705..b68cebdbf64 100644 --- a/mysql-test/extra/rpl_tests/rpl_log.test +++ b/mysql-test/extra/rpl_tests/rpl_log.test @@ -108,7 +108,7 @@ show binlog events in 'slave-bin.000001' from 4; show binlog events in 'slave-bin.000002' from 4; --replace_result $MASTER_MYPORT MASTER_PORT --replace_column 1 # 8 # 9 # 16 # 23 # 33 # -show slave status; +--query_vertical show slave status; # Need to recode the following diff --git a/mysql-test/r/rpl_colSize.result b/mysql-test/r/rpl_colSize.result new file mode 100644 index 00000000000..91456742833 --- /dev/null +++ b/mysql-test/r/rpl_colSize.result @@ -0,0 +1,179 @@ +stop slave; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +reset master; +reset slave; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +start slave; +DROP TABLE IF EXISTS t1; +**** Testing WL#3228 changes. **** +*** Create "wider" table on slave *** +STOP SLAVE; +RESET SLAVE; +CREATE TABLE t1 ( +a float (47), +b double (143,9), +c decimal (65,30), +d numeric (4,0), +e bit (32), +f char (21), +g varchar (1300), +h binary (33), +j varbinary (200), +k enum ('5','6','7', '8','9','0'), +l set ('1','2','3','4','5','6','7','8','9','0','11','12','13','14','15','16','17','18','19','21','22','23','24','25','26','27','28','29'), +m TINYBLOB, +n BLOB, +o MEDIUMBLOB, +p LONGBLOB, +q TINYTEXT, +r TEXT, +s MEDIUMTEXT, +t LONGTEXT +); +*** Create same table on master but with narrow columns *** +CREATE TABLE t1 ( +a float (44), +b double (10,3), +c decimal (10,2), +d numeric (3,0), +e bit (16), +f char (10), +g varchar (100), +h binary (20), +j varbinary (20), +k enum ('5','6','7'), +l set ('1','2','3','4','5','6','7','8','9','0'), +m TINYBLOB, +n BLOB, +o MEDIUMBLOB, +p LONGBLOB, +q TINYTEXT, +r TEXT, +s MEDIUMTEXT, +t LONGTEXT +); +RESET MASTER; +*** Start replication *** +START SLAVE; +*** Insert data on master and display it. *** +INSERT INTO t1 () VALUES ( +17.567, +2.123, +10.20, +125, +hex(64), +'TEST', +'This is a test', +'binary data', +'more binary data', +'6', +'7', +"blob 1", +"blob 2", +"blob 3", +"blob 4", +"text 1", +"text 2", +"text 3", +"text 4"); +SELECT * FROM t1 ORDER BY a; +a b c d e f g h j k l m n o p q r s t +17.567 2.123 10.20 125 # TEST This is a test # more binary data 6 7 blob 1 blob 2 blob 3 blob 4 text 1 text 2 text 3 text 4 +*** Select data from slave to compare *** +SELECT * FROM t1 ORDER BY a; +a b c d e f g h j k l m n o p q r s t +17.567 2.123000000 10.200000000000000000000000000000 125 # TEST This is a test # more binary data 6 7 blob 1 blob 2 blob 3 blob 4 text 1 text 2 text 3 text 4 +DROP TABLE t1; +Create varchar table on master +CREATE TABLE t1 ( +a VARCHAR(50), +b VARCHAR(100), +c VARCHAR(300), +d CHAR(5) +); +Alter varchar table on slave +ALTER TABLE t1 CHANGE COLUMN a a VARCHAR(100); +ALTER TABLE t1 CHANGE COLUMN b b VARCHAR(400); +ALTER TABLE t1 CHANGE COLUMN c c VARCHAR(500); +ALTER TABLE t1 CHANGE COLUMN d d CHAR(100); +Insert some values and select them on master +INSERT INTO t1 VALUES ("This is a test of col a.", +"This is another test of col b.", +"This is a test of the large col c.", +"Col d"); +SELECT * FROM t1; +a b c d +This is a test of col a. This is another test of col b. This is a test of the large col c. Col d +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` varchar(50) DEFAULT NULL, + `b` varchar(100) DEFAULT NULL, + `c` varchar(300) DEFAULT NULL, + `d` char(5) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +Insert some values and select them on slave +SELECT * FROM t1; +a b c d +This is a test of col a. This is another test of col b. This is a test of the large col c. Col d +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` varchar(100) DEFAULT NULL, + `b` varchar(400) DEFAULT NULL, + `c` varchar(500) DEFAULT NULL, + `d` char(100) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +DROP TABLE t1; +Create bit table on master +CREATE TABLE t1 ( +a BIT(7), +b BIT(8), +c BIT(21), +d BIT(11), +e BIT(11) +); +Create bit table on slave +DROP TABLE t1; +CREATE TABLE t1 ( +a BIT(16), +b BIT(22), +c BIT(54), +d BIT(25), +e BIT(13) +); +Insert some values and select them on master +INSERT INTO t1 VALUES ( +b'1010101', +b'10101011', +b'101010110101010101111', +b'10101010101', +b'10101011111' + ); +SELECT BIN(a), BIN(b), BIN(c), BIN(d), BIN(e) FROM t1; +BIN(a) BIN(b) BIN(c) BIN(d) BIN(e) +1010101 10101011 101010110101010101111 10101010101 10101011111 +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` bit(7) DEFAULT NULL, + `b` bit(8) DEFAULT NULL, + `c` bit(21) DEFAULT NULL, + `d` bit(11) DEFAULT NULL, + `e` bit(11) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +Insert some values and select them on master +SELECT BIN(a), BIN(b), BIN(c), BIN(d), BIN(e) FROM t1; +BIN(a) BIN(b) BIN(c) BIN(d) BIN(e) +1010101 10101011 101010110101010101111 10101010101 10101011111 +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` bit(16) DEFAULT NULL, + `b` bit(22) DEFAULT NULL, + `c` bit(54) DEFAULT NULL, + `d` bit(25) DEFAULT NULL, + `e` bit(13) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +*** Cleanup *** +DROP TABLE t1; diff --git a/mysql-test/r/rpl_ndb_log.result b/mysql-test/r/rpl_ndb_log.result index db2ce27d43b..272c8dfea6d 100644 --- a/mysql-test/r/rpl_ndb_log.result +++ b/mysql-test/r/rpl_ndb_log.result @@ -88,12 +88,12 @@ master-bin.000002 # Write_rows 1 # table_id: # flags: STMT_END_F master-bin.000002 # Query 1 # COMMIT show binary logs; Log_name File_size -master-bin.000001 1775 -master-bin.000002 617 +master-bin.000001 1789 +master-bin.000002 623 start slave; show binary logs; Log_name File_size -slave-bin.000001 1870 +slave-bin.000001 1884 slave-bin.000002 202 show binlog events in 'slave-bin.000001' from 4; Log_name Pos Event_type Server_id End_log_pos Info @@ -128,7 +128,7 @@ slave-bin.000002 # Write_rows 1 # table_id: # flags: STMT_END_F slave-bin.000002 # Query 2 # COMMIT show slave status; Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master Master_SSL_Verify_Server_Cert -# 127.0.0.1 root MASTER_PORT 1 master-bin.000002 617 # # master-bin.000002 Yes Yes # 0 0 617 # None 0 No # No +# 127.0.0.1 root MASTER_PORT 1 master-bin.000002 623 # # master-bin.000002 Yes Yes # 0 0 623 # None 0 No # No show binlog events in 'slave-bin.000005' from 4; ERROR HY000: Error when executing command SHOW BINLOG EVENTS: Could not find target log DROP TABLE t1; diff --git a/mysql-test/r/rpl_rbr_to_sbr.result b/mysql-test/r/rpl_rbr_to_sbr.result index 47adb70bcf5..175a277b744 100644 --- a/mysql-test/r/rpl_rbr_to_sbr.result +++ b/mysql-test/r/rpl_rbr_to_sbr.result @@ -28,7 +28,7 @@ Master_User root Master_Port MASTER_PORT Connect_Retry 1 Master_Log_File master-bin.000001 -Read_Master_Log_Pos 454 +Read_Master_Log_Pos 457 Relay_Log_File # Relay_Log_Pos # Relay_Master_Log_File master-bin.000001 @@ -43,7 +43,7 @@ Replicate_Wild_Ignore_Table Last_Errno 0 Last_Error Skip_Counter 0 -Exec_Master_Log_Pos 454 +Exec_Master_Log_Pos 457 Relay_Log_Space # Until_Condition None Until_Log_File diff --git a/mysql-test/r/rpl_row_basic_11bugs.result b/mysql-test/r/rpl_row_basic_11bugs.result index 1025b965589..3cdaf137240 100644 --- a/mysql-test/r/rpl_row_basic_11bugs.result +++ b/mysql-test/r/rpl_row_basic_11bugs.result @@ -56,8 +56,8 @@ SHOW BINLOG EVENTS; Log_name Pos Event_type Server_id End_log_pos Info master-bin.000001 4 Format_desc 1 106 Server ver: SERVER_VERSION, Binlog ver: 4 master-bin.000001 106 Query 1 192 use `test`; CREATE TABLE t1 (a INT) -master-bin.000001 192 Table_map 1 231 table_id: # (test.t1) -master-bin.000001 231 Write_rows 1 270 table_id: # flags: STMT_END_F +master-bin.000001 192 Table_map 1 233 table_id: # (test.t1) +master-bin.000001 233 Write_rows 1 272 table_id: # flags: STMT_END_F DROP TABLE t1; ================ Test for BUG#17620 ================ drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; diff --git a/mysql-test/r/rpl_row_create_table.result b/mysql-test/r/rpl_row_create_table.result index e76ce5b962d..84881e82702 100644 --- a/mysql-test/r/rpl_row_create_table.result +++ b/mysql-test/r/rpl_row_create_table.result @@ -127,7 +127,7 @@ NULL 5 10 NULL 6 12 CREATE TABLE t7 (UNIQUE(b)) SELECT a,b FROM tt3; ERROR 23000: Duplicate entry '2' for key 'b' -SHOW BINLOG EVENTS FROM 1098; +SHOW BINLOG EVENTS FROM 1100; Log_name Pos Event_type Server_id End_log_pos Info CREATE TABLE t7 (a INT, b INT UNIQUE); INSERT INTO t7 SELECT a,b FROM tt3; @@ -137,11 +137,11 @@ a b 1 2 2 4 3 6 -SHOW BINLOG EVENTS FROM 1098; +SHOW BINLOG EVENTS FROM 1100; Log_name Pos Event_type Server_id End_log_pos Info -# 1098 Query # 1198 use `test`; CREATE TABLE t7 (a INT, b INT UNIQUE) -# 1198 Table_map # 1238 table_id: # (test.t7) -# 1238 Write_rows # 1294 table_id: # flags: STMT_END_F +# 1100 Query # 1200 use `test`; CREATE TABLE t7 (a INT, b INT UNIQUE) +# 1200 Table_map # 1242 table_id: # (test.t7) +# 1242 Write_rows # 1298 table_id: # flags: STMT_END_F SELECT * FROM t7 ORDER BY a,b; a b 1 2 @@ -154,10 +154,10 @@ INSERT INTO t7 SELECT a,b FROM tt4; ROLLBACK; Warnings: Warning 1196 Some non-transactional changed tables couldn't be rolled back -SHOW BINLOG EVENTS FROM 1294; +SHOW BINLOG EVENTS FROM 1298; Log_name Pos Event_type Server_id End_log_pos Info -# 1294 Table_map # 1334 table_id: # (test.t7) -# 1334 Write_rows # 1390 table_id: # flags: STMT_END_F +# 1298 Table_map # 1340 table_id: # (test.t7) +# 1340 Write_rows # 1396 table_id: # flags: STMT_END_F SELECT * FROM t7 ORDER BY a,b; a b 1 2 @@ -192,10 +192,10 @@ Create Table CREATE TABLE `t9` ( `a` int(11) DEFAULT NULL, `b` int(11) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 -SHOW BINLOG EVENTS FROM 1390; +SHOW BINLOG EVENTS FROM 1396; Log_name Pos Event_type Server_id End_log_pos Info -# 1390 Query # 1476 use `test`; CREATE TABLE t8 LIKE t4 -# 1476 Query # 1615 use `test`; CREATE TABLE `t9` ( +# 1396 Query # 1482 use `test`; CREATE TABLE t8 LIKE t4 +# 1482 Query # 1621 use `test`; CREATE TABLE `t9` ( `a` int(11) DEFAULT NULL, `b` int(11) DEFAULT NULL ) @@ -276,31 +276,31 @@ SHOW BINLOG EVENTS; Log_name Pos Event_type Server_id End_log_pos Info # 4 Format_desc # 106 Server ver: #, Binlog ver: # # 106 Query # 192 use `test`; CREATE TABLE t1 (a INT) -# 192 Table_map # 231 table_id: # (test.t1) -# 231 Write_rows # 275 table_id: # flags: STMT_END_F -# 275 Query # 343 use `test`; BEGIN -# 343 Query # 125 use `test`; CREATE TABLE `t2` ( +# 192 Table_map # 233 table_id: # (test.t1) +# 233 Write_rows # 277 table_id: # flags: STMT_END_F +# 277 Query # 345 use `test`; BEGIN +# 345 Query # 125 use `test`; CREATE TABLE `t2` ( `a` int(11) DEFAULT NULL ) ENGINE=InnoDB -# 468 Table_map # 164 table_id: # (test.t2) -# 507 Write_rows # 208 table_id: # flags: STMT_END_F -# 551 Xid # 578 COMMIT /* XID */ -# 578 Query # 646 use `test`; BEGIN -# 646 Query # 125 use `test`; CREATE TABLE `t3` ( +# 470 Table_map # 166 table_id: # (test.t2) +# 511 Write_rows # 210 table_id: # flags: STMT_END_F +# 555 Xid # 582 COMMIT /* XID */ +# 582 Query # 650 use `test`; BEGIN +# 650 Query # 125 use `test`; CREATE TABLE `t3` ( `a` int(11) DEFAULT NULL ) ENGINE=InnoDB -# 771 Table_map # 164 table_id: # (test.t3) -# 810 Write_rows # 208 table_id: # flags: STMT_END_F -# 854 Xid # 881 COMMIT /* XID */ -# 881 Query # 949 use `test`; BEGIN -# 949 Query # 125 use `test`; CREATE TABLE `t4` ( +# 775 Table_map # 166 table_id: # (test.t3) +# 816 Write_rows # 210 table_id: # flags: STMT_END_F +# 860 Xid # 887 COMMIT /* XID */ +# 887 Query # 955 use `test`; BEGIN +# 955 Query # 125 use `test`; CREATE TABLE `t4` ( `a` int(11) DEFAULT NULL ) ENGINE=InnoDB -# 1074 Table_map # 164 table_id: # (test.t4) -# 1113 Write_rows # 208 table_id: # flags: STMT_END_F -# 1157 Xid # 1184 COMMIT /* XID */ -# 1184 Table_map # 1223 table_id: # (test.t1) -# 1223 Write_rows # 1267 table_id: # flags: STMT_END_F +# 1080 Table_map # 166 table_id: # (test.t4) +# 1121 Write_rows # 210 table_id: # flags: STMT_END_F +# 1165 Xid # 1192 COMMIT /* XID */ +# 1192 Table_map # 1233 table_id: # (test.t1) +# 1233 Write_rows # 1277 table_id: # flags: STMT_END_F SHOW TABLES; Tables_in_test t1 @@ -367,15 +367,15 @@ SHOW BINLOG EVENTS; Log_name Pos Event_type Server_id End_log_pos Info # 4 Format_desc # 106 Server ver: #, Binlog ver: # # 106 Query # 192 use `test`; CREATE TABLE t1 (a INT) -# 192 Table_map # 231 table_id: # (test.t1) -# 231 Write_rows # 275 table_id: # flags: STMT_END_F -# 275 Query # 375 use `test`; CREATE TABLE t2 (a INT) ENGINE=INNODB -# 375 Query # 443 use `test`; BEGIN -# 443 Table_map # 39 table_id: # (test.t2) -# 482 Write_rows # 83 table_id: # flags: STMT_END_F -# 526 Table_map # 122 table_id: # (test.t2) -# 565 Write_rows # 161 table_id: # flags: STMT_END_F -# 604 Xid # 631 COMMIT /* XID */ +# 192 Table_map # 233 table_id: # (test.t1) +# 233 Write_rows # 277 table_id: # flags: STMT_END_F +# 277 Query # 377 use `test`; CREATE TABLE t2 (a INT) ENGINE=INNODB +# 377 Query # 445 use `test`; BEGIN +# 445 Table_map # 41 table_id: # (test.t2) +# 486 Write_rows # 85 table_id: # flags: STMT_END_F +# 530 Table_map # 126 table_id: # (test.t2) +# 571 Write_rows # 165 table_id: # flags: STMT_END_F +# 610 Xid # 637 COMMIT /* XID */ SELECT * FROM t2 ORDER BY a; a 1 @@ -394,10 +394,10 @@ INSERT INTO t2 SELECT a+2 FROM tt2; ROLLBACK; SELECT * FROM t2 ORDER BY a; a -SHOW BINLOG EVENTS FROM 631; +SHOW BINLOG EVENTS FROM 637; Log_name Pos Event_type Server_id End_log_pos Info -# 631 Query # 80 use `test`; TRUNCATE TABLE t2 -# 711 Xid # 738 COMMIT /* XID */ +# 637 Query # 80 use `test`; TRUNCATE TABLE t2 +# 717 Xid # 744 COMMIT /* XID */ SELECT * FROM t2 ORDER BY a; a DROP TABLE t1,t2; diff --git a/mysql-test/r/rpl_row_flsh_tbls.result b/mysql-test/r/rpl_row_flsh_tbls.result index 942a6b83bf6..072f15cbbd3 100644 --- a/mysql-test/r/rpl_row_flsh_tbls.result +++ b/mysql-test/r/rpl_row_flsh_tbls.result @@ -12,13 +12,13 @@ create table t4 (a int); insert into t4 select * from t3; rename table t1 to t5, t2 to t1; flush no_write_to_binlog tables; -SHOW BINLOG EVENTS FROM 619 ; +SHOW BINLOG EVENTS FROM 623 ; Log_name Pos Event_type Server_id End_log_pos Info master-bin.000001 # Query 1 # use `test`; rename table t1 to t5, t2 to t1 select * from t3; a flush tables; -SHOW BINLOG EVENTS FROM 619 ; +SHOW BINLOG EVENTS FROM 623 ; Log_name Pos Event_type Server_id End_log_pos Info master-bin.000001 # Query 1 # use `test`; rename table t1 to t5, t2 to t1 master-bin.000001 # Query 1 # use `test`; flush tables diff --git a/mysql-test/r/rpl_row_inexist_tbl.result b/mysql-test/r/rpl_row_inexist_tbl.result index 4412a1fa75c..4065809a63e 100644 --- a/mysql-test/r/rpl_row_inexist_tbl.result +++ b/mysql-test/r/rpl_row_inexist_tbl.result @@ -39,7 +39,7 @@ Replicate_Wild_Ignore_Table Last_Errno 1146 Last_Error Error 'Table 'test.t1' doesn't exist' on opening table `test`.`t1` Skip_Counter 0 -Exec_Master_Log_Pos 524 +Exec_Master_Log_Pos 530 Relay_Log_Space # Until_Condition None Until_Log_File diff --git a/mysql-test/r/rpl_row_log.result b/mysql-test/r/rpl_row_log.result index 9de0d3d0ebb..b8121a9c24f 100644 --- a/mysql-test/r/rpl_row_log.result +++ b/mysql-test/r/rpl_row_log.result @@ -66,13 +66,13 @@ master-bin.000002 # Table_map 1 # table_id: # (test.t2) master-bin.000002 # Write_rows 1 # table_id: # flags: STMT_END_F show binary logs; Log_name File_size -master-bin.000001 1260 -master-bin.000002 377 +master-bin.000001 1266 +master-bin.000002 379 start slave; show binary logs; Log_name File_size -slave-bin.000001 1358 -slave-bin.000002 278 +slave-bin.000001 1364 +slave-bin.000002 280 show binlog events in 'slave-bin.000001' from 4; Log_name Pos Event_type Server_id End_log_pos Info slave-bin.000001 # Format_desc 2 # Server ver: VERSION, Binlog ver: 4 @@ -91,9 +91,41 @@ slave-bin.000002 # Format_desc 2 # Server ver: VERSION, Binlog ver: 4 slave-bin.000002 # Query 1 # use `test`; create table t2 (n int)ENGINE=MyISAM slave-bin.000002 # Table_map 1 # table_id: # (test.t2) slave-bin.000002 # Write_rows 1 # table_id: # flags: STMT_END_F -show slave status; -Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master Master_SSL_Verify_Server_Cert -# 127.0.0.1 root MASTER_PORT 1 master-bin.000002 377 # # master-bin.000002 Yes Yes # 0 0 377 # None 0 No # No +show slave status;; +Slave_IO_State # +Master_Host 127.0.0.1 +Master_User root +Master_Port MASTER_PORT +Connect_Retry 1 +Master_Log_File master-bin.000002 +Read_Master_Log_Pos 379 +Relay_Log_File # +Relay_Log_Pos # +Relay_Master_Log_File master-bin.000002 +Slave_IO_Running Yes +Slave_SQL_Running Yes +Replicate_Do_DB +Replicate_Ignore_DB +Replicate_Do_Table +Replicate_Ignore_Table # +Replicate_Wild_Do_Table +Replicate_Wild_Ignore_Table +Last_Errno 0 +Last_Error +Skip_Counter 0 +Exec_Master_Log_Pos 379 +Relay_Log_Space # +Until_Condition None +Until_Log_File +Until_Log_Pos 0 +Master_SSL_Allowed No +Master_SSL_CA_File +Master_SSL_CA_Path +Master_SSL_Cert +Master_SSL_Cipher +Master_SSL_Key +Seconds_Behind_Master # +Master_SSL_Verify_Server_Cert No show binlog events in 'slave-bin.000005' from 4; ERROR HY000: Error when executing command SHOW BINLOG EVENTS: Could not find target log DROP TABLE t1; diff --git a/mysql-test/r/rpl_row_log_innodb.result b/mysql-test/r/rpl_row_log_innodb.result index 4d8175142b2..92bffcd9f34 100644 --- a/mysql-test/r/rpl_row_log_innodb.result +++ b/mysql-test/r/rpl_row_log_innodb.result @@ -71,13 +71,13 @@ master-bin.000002 # Write_rows 1 # table_id: # flags: STMT_END_F master-bin.000002 # Xid 1 # COMMIT /* XID */ show binary logs; Log_name File_size -master-bin.000001 1314 -master-bin.000002 404 +master-bin.000001 1320 +master-bin.000002 406 start slave; show binary logs; Log_name File_size -slave-bin.000001 1412 -slave-bin.000002 305 +slave-bin.000001 1418 +slave-bin.000002 307 show binlog events in 'slave-bin.000001' from 4; Log_name Pos Event_type Server_id End_log_pos Info slave-bin.000001 # Format_desc 2 # Server ver: VERSION, Binlog ver: 4 @@ -99,9 +99,41 @@ slave-bin.000002 # Query 1 # use `test`; create table t2 (n int)ENGINE=InnoDB slave-bin.000002 # Table_map 1 # table_id: # (test.t2) slave-bin.000002 # Write_rows 1 # table_id: # flags: STMT_END_F slave-bin.000002 # Xid 1 # COMMIT /* XID */ -show slave status; -Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master Master_SSL_Verify_Server_Cert -# 127.0.0.1 root MASTER_PORT 1 master-bin.000002 404 # # master-bin.000002 Yes Yes # 0 0 404 # None 0 No # No +show slave status;; +Slave_IO_State # +Master_Host 127.0.0.1 +Master_User root +Master_Port MASTER_PORT +Connect_Retry 1 +Master_Log_File master-bin.000002 +Read_Master_Log_Pos 406 +Relay_Log_File # +Relay_Log_Pos # +Relay_Master_Log_File master-bin.000002 +Slave_IO_Running Yes +Slave_SQL_Running Yes +Replicate_Do_DB +Replicate_Ignore_DB +Replicate_Do_Table +Replicate_Ignore_Table # +Replicate_Wild_Do_Table +Replicate_Wild_Ignore_Table +Last_Errno 0 +Last_Error +Skip_Counter 0 +Exec_Master_Log_Pos 406 +Relay_Log_Space # +Until_Condition None +Until_Log_File +Until_Log_Pos 0 +Master_SSL_Allowed No +Master_SSL_CA_File +Master_SSL_CA_Path +Master_SSL_Cert +Master_SSL_Cipher +Master_SSL_Key +Seconds_Behind_Master # +Master_SSL_Verify_Server_Cert No show binlog events in 'slave-bin.000005' from 4; ERROR HY000: Error when executing command SHOW BINLOG EVENTS: Could not find target log DROP TABLE t1; diff --git a/mysql-test/r/rpl_row_max_relay_size.result b/mysql-test/r/rpl_row_max_relay_size.result index cb1692568fc..9aca60a8ad7 100644 --- a/mysql-test/r/rpl_row_max_relay_size.result +++ b/mysql-test/r/rpl_row_max_relay_size.result @@ -30,7 +30,7 @@ Master_User root Master_Port MASTER_PORT Connect_Retry 1 Master_Log_File master-bin.000001 -Read_Master_Log_Pos 58668 +Read_Master_Log_Pos 60268 Relay_Log_File # Relay_Log_Pos # Relay_Master_Log_File master-bin.000001 @@ -45,7 +45,7 @@ Replicate_Wild_Ignore_Table Last_Errno 0 Last_Error Skip_Counter 0 -Exec_Master_Log_Pos 58668 +Exec_Master_Log_Pos 60268 Relay_Log_Space # Until_Condition None Until_Log_File @@ -74,7 +74,7 @@ Master_User root Master_Port MASTER_PORT Connect_Retry 1 Master_Log_File master-bin.000001 -Read_Master_Log_Pos 58668 +Read_Master_Log_Pos 60268 Relay_Log_File # Relay_Log_Pos # Relay_Master_Log_File master-bin.000001 @@ -89,7 +89,7 @@ Replicate_Wild_Ignore_Table Last_Errno 0 Last_Error Skip_Counter 0 -Exec_Master_Log_Pos 58668 +Exec_Master_Log_Pos 60268 Relay_Log_Space # Until_Condition None Until_Log_File @@ -118,7 +118,7 @@ Master_User root Master_Port MASTER_PORT Connect_Retry 1 Master_Log_File master-bin.000001 -Read_Master_Log_Pos 58668 +Read_Master_Log_Pos 60268 Relay_Log_File # Relay_Log_Pos # Relay_Master_Log_File master-bin.000001 @@ -133,7 +133,7 @@ Replicate_Wild_Ignore_Table Last_Errno 0 Last_Error Skip_Counter 0 -Exec_Master_Log_Pos 58668 +Exec_Master_Log_Pos 60268 Relay_Log_Space # Until_Condition None Until_Log_File @@ -201,7 +201,7 @@ Master_User root Master_Port MASTER_PORT Connect_Retry 1 Master_Log_File master-bin.000001 -Read_Master_Log_Pos 58754 +Read_Master_Log_Pos 60354 Relay_Log_File # Relay_Log_Pos # Relay_Master_Log_File master-bin.000001 @@ -216,7 +216,7 @@ Replicate_Wild_Ignore_Table Last_Errno 0 Last_Error Skip_Counter 0 -Exec_Master_Log_Pos 58754 +Exec_Master_Log_Pos 60354 Relay_Log_Space # Until_Condition None Until_Log_File @@ -241,7 +241,7 @@ Master_User root Master_Port MASTER_PORT Connect_Retry 1 Master_Log_File master-bin.000001 -Read_Master_Log_Pos 58830 +Read_Master_Log_Pos 60430 Relay_Log_File # Relay_Log_Pos # Relay_Master_Log_File master-bin.000001 @@ -256,7 +256,7 @@ Replicate_Wild_Ignore_Table Last_Errno 0 Last_Error Skip_Counter 0 -Exec_Master_Log_Pos 58830 +Exec_Master_Log_Pos 60430 Relay_Log_Space # Until_Condition None Until_Log_File diff --git a/mysql-test/r/rpl_row_until.result b/mysql-test/r/rpl_row_until.result index c691185650a..c232dfcbc9f 100644 --- a/mysql-test/r/rpl_row_until.result +++ b/mysql-test/r/rpl_row_until.result @@ -21,7 +21,7 @@ n 4 show slave status; Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master Master_SSL_Verify_Server_Cert -# 127.0.0.1 root MASTER_MYPORT 1 master-bin.000001 744 slave-relay-bin.000004 # master-bin.000001 # No 0 0 315 # Master master-bin.000001 311 No # No +# 127.0.0.1 root MASTER_MYPORT 1 master-bin.000001 750 slave-relay-bin.000004 # master-bin.000001 # No 0 0 317 # Master master-bin.000001 311 No # No start slave until master_log_file='master-no-such-bin.000001', master_log_pos=291; select * from t1; n @@ -31,7 +31,7 @@ n 4 show slave status; Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master Master_SSL_Verify_Server_Cert -# 127.0.0.1 root MASTER_MYPORT 1 master-bin.000001 744 slave-relay-bin.000004 # master-bin.000001 # No 0 0 315 # Master master-no-such-bin.000001 291 No # No +# 127.0.0.1 root MASTER_MYPORT 1 master-bin.000001 750 slave-relay-bin.000004 # master-bin.000001 # No 0 0 317 # Master master-no-such-bin.000001 291 No # No start slave until relay_log_file='slave-relay-bin.000004', relay_log_pos=728; select * from t2; n @@ -39,13 +39,13 @@ n 2 show slave status; Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master Master_SSL_Verify_Server_Cert -# 127.0.0.1 root MASTER_MYPORT 1 master-bin.000001 744 slave-relay-bin.000004 # master-bin.000001 # No 0 0 590 # Relay slave-relay-bin.000004 728 No # No +# 127.0.0.1 root MASTER_MYPORT 1 master-bin.000001 750 slave-relay-bin.000004 # master-bin.000001 # No 0 0 594 # Relay slave-relay-bin.000004 728 No # No start slave; stop slave; start slave until master_log_file='master-bin.000001', master_log_pos=740; show slave status; Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master Master_SSL_Verify_Server_Cert -# 127.0.0.1 root MASTER_MYPORT 1 master-bin.000001 744 slave-relay-bin.000004 # master-bin.000001 Yes No 0 0 744 # Master master-bin.000001 740 No # No +# 127.0.0.1 root MASTER_MYPORT 1 master-bin.000001 750 slave-relay-bin.000004 # master-bin.000001 Yes No 0 0 750 # Master master-bin.000001 740 No # No start slave until master_log_file='master-bin', master_log_pos=561; ERROR HY000: Incorrect parameter or combination of parameters for START SLAVE UNTIL start slave until master_log_file='master-bin.000001', master_log_pos=561, relay_log_pos=12; diff --git a/mysql-test/r/rpl_stm_log.result b/mysql-test/r/rpl_stm_log.result index 3ee2d990159..07f66475e56 100644 --- a/mysql-test/r/rpl_stm_log.result +++ b/mysql-test/r/rpl_stm_log.result @@ -89,9 +89,41 @@ Log_name Pos Event_type Server_id End_log_pos Info slave-bin.000002 # Format_desc 2 # Server ver: VERSION, Binlog ver: 4 slave-bin.000002 # Query 1 # use `test`; create table t2 (n int)ENGINE=MyISAM slave-bin.000002 # Query 1 # use `test`; insert into t2 values (1) -show slave status; -Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master Master_SSL_Verify_Server_Cert -# 127.0.0.1 root MASTER_PORT 1 master-bin.000002 392 # # master-bin.000002 Yes Yes # 0 0 392 # None 0 No # No +show slave status;; +Slave_IO_State # +Master_Host 127.0.0.1 +Master_User root +Master_Port MASTER_PORT +Connect_Retry 1 +Master_Log_File master-bin.000002 +Read_Master_Log_Pos 392 +Relay_Log_File # +Relay_Log_Pos # +Relay_Master_Log_File master-bin.000002 +Slave_IO_Running Yes +Slave_SQL_Running Yes +Replicate_Do_DB +Replicate_Ignore_DB +Replicate_Do_Table +Replicate_Ignore_Table # +Replicate_Wild_Do_Table +Replicate_Wild_Ignore_Table +Last_Errno 0 +Last_Error +Skip_Counter 0 +Exec_Master_Log_Pos 392 +Relay_Log_Space # +Until_Condition None +Until_Log_File +Until_Log_Pos 0 +Master_SSL_Allowed No +Master_SSL_CA_File +Master_SSL_CA_Path +Master_SSL_Cert +Master_SSL_Cipher +Master_SSL_Key +Seconds_Behind_Master # +Master_SSL_Verify_Server_Cert No show binlog events in 'slave-bin.000005' from 4; ERROR HY000: Error when executing command SHOW BINLOG EVENTS: Could not find target log DROP TABLE t1; diff --git a/mysql-test/r/rpl_truncate_7ndb.result b/mysql-test/r/rpl_truncate_7ndb.result index 62ace911e45..0b3b655b0aa 100644 --- a/mysql-test/r/rpl_truncate_7ndb.result +++ b/mysql-test/r/rpl_truncate_7ndb.result @@ -32,14 +32,14 @@ Log_name Pos Event_type Server_id End_log_pos Info master-bin.000001 4 Format_desc 1 106 Server ver: SERVER_VERSION, Binlog ver: 4 master-bin.000001 106 Query 1 223 use `test`; CREATE TABLE t1 (a INT PRIMARY KEY, b LONG) ENGINE=NDB master-bin.000001 223 Query 1 287 BEGIN -master-bin.000001 287 Table_map 1 40 table_id: # (test.t1) -master-bin.000001 327 Table_map 1 98 table_id: # (mysql.ndb_apply_status) -master-bin.000001 385 Write_rows 1 157 table_id: # -master-bin.000001 444 Write_rows 1 195 table_id: # -master-bin.000001 482 Write_rows 1 233 table_id: # flags: STMT_END_F -master-bin.000001 520 Query 1 585 COMMIT -master-bin.000001 585 Query 1 665 use `test`; TRUNCATE TABLE t1 -master-bin.000001 665 Query 1 741 use `test`; DROP TABLE t1 +master-bin.000001 287 Table_map 1 43 table_id: # (test.t1) +master-bin.000001 330 Table_map 1 105 table_id: # (mysql.ndb_apply_status) +master-bin.000001 392 Write_rows 1 164 table_id: # +master-bin.000001 451 Write_rows 1 202 table_id: # +master-bin.000001 489 Write_rows 1 240 table_id: # flags: STMT_END_F +master-bin.000001 527 Query 1 592 COMMIT +master-bin.000001 592 Query 1 672 use `test`; TRUNCATE TABLE t1 +master-bin.000001 672 Query 1 748 use `test`; DROP TABLE t1 **** On Master **** CREATE TABLE t1 (a INT PRIMARY KEY, b LONG) ENGINE=NDB; INSERT INTO t1 VALUES (1,1), (2,2); @@ -69,27 +69,27 @@ Log_name Pos Event_type Server_id End_log_pos Info master-bin.000001 4 Format_desc 1 106 Server ver: SERVER_VERSION, Binlog ver: 4 master-bin.000001 106 Query 1 223 use `test`; CREATE TABLE t1 (a INT PRIMARY KEY, b LONG) ENGINE=NDB master-bin.000001 223 Query 1 287 BEGIN -master-bin.000001 287 Table_map 1 40 table_id: # (test.t1) -master-bin.000001 327 Table_map 1 98 table_id: # (mysql.ndb_apply_status) -master-bin.000001 385 Write_rows 1 157 table_id: # -master-bin.000001 444 Write_rows 1 195 table_id: # -master-bin.000001 482 Write_rows 1 233 table_id: # flags: STMT_END_F -master-bin.000001 520 Query 1 585 COMMIT -master-bin.000001 585 Query 1 665 use `test`; TRUNCATE TABLE t1 -master-bin.000001 665 Query 1 741 use `test`; DROP TABLE t1 -master-bin.000001 741 Query 1 858 use `test`; CREATE TABLE t1 (a INT PRIMARY KEY, b LONG) ENGINE=NDB -master-bin.000001 858 Query 1 922 BEGIN -master-bin.000001 922 Table_map 1 40 table_id: # (test.t1) -master-bin.000001 962 Table_map 1 98 table_id: # (mysql.ndb_apply_status) -master-bin.000001 1020 Write_rows 1 157 table_id: # -master-bin.000001 1079 Write_rows 1 195 table_id: # -master-bin.000001 1117 Write_rows 1 233 table_id: # flags: STMT_END_F -master-bin.000001 1155 Query 1 1220 COMMIT -master-bin.000001 1220 Query 1 1284 BEGIN -master-bin.000001 1284 Table_map 1 40 table_id: # (test.t1) -master-bin.000001 1324 Table_map 1 98 table_id: # (mysql.ndb_apply_status) -master-bin.000001 1382 Write_rows 1 157 table_id: # -master-bin.000001 1441 Delete_rows 1 191 table_id: # -master-bin.000001 1475 Delete_rows 1 225 table_id: # flags: STMT_END_F -master-bin.000001 1509 Query 1 1574 COMMIT -master-bin.000001 1574 Query 1 1650 use `test`; DROP TABLE t1 +master-bin.000001 287 Table_map 1 43 table_id: # (test.t1) +master-bin.000001 330 Table_map 1 105 table_id: # (mysql.ndb_apply_status) +master-bin.000001 392 Write_rows 1 164 table_id: # +master-bin.000001 451 Write_rows 1 202 table_id: # +master-bin.000001 489 Write_rows 1 240 table_id: # flags: STMT_END_F +master-bin.000001 527 Query 1 592 COMMIT +master-bin.000001 592 Query 1 672 use `test`; TRUNCATE TABLE t1 +master-bin.000001 672 Query 1 748 use `test`; DROP TABLE t1 +master-bin.000001 748 Query 1 865 use `test`; CREATE TABLE t1 (a INT PRIMARY KEY, b LONG) ENGINE=NDB +master-bin.000001 865 Query 1 929 BEGIN +master-bin.000001 929 Table_map 1 43 table_id: # (test.t1) +master-bin.000001 972 Table_map 1 105 table_id: # (mysql.ndb_apply_status) +master-bin.000001 1034 Write_rows 1 164 table_id: # +master-bin.000001 1093 Write_rows 1 202 table_id: # +master-bin.000001 1131 Write_rows 1 240 table_id: # flags: STMT_END_F +master-bin.000001 1169 Query 1 1234 COMMIT +master-bin.000001 1234 Query 1 1298 BEGIN +master-bin.000001 1298 Table_map 1 43 table_id: # (test.t1) +master-bin.000001 1341 Table_map 1 105 table_id: # (mysql.ndb_apply_status) +master-bin.000001 1403 Write_rows 1 164 table_id: # +master-bin.000001 1462 Delete_rows 1 198 table_id: # +master-bin.000001 1496 Delete_rows 1 232 table_id: # flags: STMT_END_F +master-bin.000001 1530 Query 1 1595 COMMIT +master-bin.000001 1595 Query 1 1671 use `test`; DROP TABLE t1 diff --git a/mysql-test/t/binlog_row_mix_innodb_myisam.test b/mysql-test/t/binlog_row_mix_innodb_myisam.test index 335a05be146..03475f5bf3b 100644 --- a/mysql-test/t/binlog_row_mix_innodb_myisam.test +++ b/mysql-test/t/binlog_row_mix_innodb_myisam.test @@ -20,7 +20,7 @@ # ER_SERVER_SHUTDOWN (i.e. disconnection just rolls back transaction # and does not make slave to stop) flush logs; ---exec $MYSQL_BINLOG --start-position=520 $MYSQLTEST_VARDIR/log/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/mix_innodb_myisam_binlog.output +--exec $MYSQL_BINLOG --start-position=524 $MYSQLTEST_VARDIR/log/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/mix_innodb_myisam_binlog.output --replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR eval select (@a:=load_file("$MYSQLTEST_VARDIR/tmp/mix_innodb_myisam_binlog.output")) diff --git a/mysql-test/t/rpl_colSize.test b/mysql-test/t/rpl_colSize.test new file mode 100644 index 00000000000..44fb878d4d2 --- /dev/null +++ b/mysql-test/t/rpl_colSize.test @@ -0,0 +1,216 @@ +################################################################## +# rpl_colSize # +# # +# This test is designed to test the changes included in WL#3228. # +# The changes include the ability to replicate with the master # +# having columns that are smaller (shorter) than the slave. # +################################################################## + +-- source include/master-slave.inc + +--disable_warnings +DROP TABLE IF EXISTS t1; +--enable_warnings + +--echo **** Testing WL#3228 changes. **** +--echo *** Create "wider" table on slave *** +sync_slave_with_master; +STOP SLAVE; +RESET SLAVE; + +eval CREATE TABLE t1 ( + a float (47), + b double (143,9), + c decimal (65,30), + d numeric (4,0), + e bit (32), + f char (21), + g varchar (1300), + h binary (33), + j varbinary (200), + k enum ('5','6','7', '8','9','0'), + l set ('1','2','3','4','5','6','7','8','9','0','11','12','13','14','15','16','17','18','19','21','22','23','24','25','26','27','28','29'), + m TINYBLOB, + n BLOB, + o MEDIUMBLOB, + p LONGBLOB, + q TINYTEXT, + r TEXT, + s MEDIUMTEXT, + t LONGTEXT +); + +--echo *** Create same table on master but with narrow columns *** +connection master; +eval CREATE TABLE t1 ( + a float (44), + b double (10,3), + c decimal (10,2), + d numeric (3,0), + e bit (16), + f char (10), + g varchar (100), + h binary (20), + j varbinary (20), + k enum ('5','6','7'), + l set ('1','2','3','4','5','6','7','8','9','0'), + m TINYBLOB, + n BLOB, + o MEDIUMBLOB, + p LONGBLOB, + q TINYTEXT, + r TEXT, + s MEDIUMTEXT, + t LONGTEXT +); + +RESET MASTER; + +--echo *** Start replication *** +connection slave; +START SLAVE; + +--echo *** Insert data on master and display it. *** +connection master; + +INSERT INTO t1 () VALUES ( + 17.567, + 2.123, + 10.20, + 125, + hex(64), + 'TEST', + 'This is a test', + 'binary data', + 'more binary data', + '6', + '7', + "blob 1", + "blob 2", + "blob 3", + "blob 4", + "text 1", + "text 2", + "text 3", + "text 4"); + +# Replace values in columns that display differently between SBR & RBR +--replace_column 5 # 8 # +SELECT * FROM t1 ORDER BY a; + +--echo *** Select data from slave to compare *** +sync_slave_with_master; +connection slave; + +# Replace values in columns that display differently between SBR & RBR +--replace_column 5 # 8 # +SELECT * FROM t1 ORDER BY a; + +# Test boundary limits of varchar and char fields +# Master/Slave +# <256/<256 with m < s, m > s, and m == s <-- col a +# >255/<256 with m < s, m > s, and m == s <-- error will be caught in BUG#22086 +# <256/>255 with m < s, m > s, and m == s <-- col b +# >255/>255 with m < s, m > s, and m == s <-- col c +# +# Test boundary limits of CHAR fields +# Master/Slave +# <256/<256 with m < s, m > s, and m == s <-- col d +# >255/<256 with m < s, m > s, and m == s <-- error char limited to 255 chars +# <256/>255 with m < s, m > s, and m == s <-- error char limited to 255 chars +# >255/>255 with m < s, m > s, and m == s <-- error char limited to 255 chars + +connection master; +DROP TABLE t1; + +--echo Create varchar table on master +CREATE TABLE t1 ( + a VARCHAR(50), + b VARCHAR(100), + c VARCHAR(300), + d CHAR(5) +); + +sync_slave_with_master slave; + +--echo Alter varchar table on slave +ALTER TABLE t1 CHANGE COLUMN a a VARCHAR(100); +ALTER TABLE t1 CHANGE COLUMN b b VARCHAR(400); +ALTER TABLE t1 CHANGE COLUMN c c VARCHAR(500); +ALTER TABLE t1 CHANGE COLUMN d d CHAR(100); + +connection master; + +--echo Insert some values and select them on master +INSERT INTO t1 VALUES ("This is a test of col a.", + "This is another test of col b.", + "This is a test of the large col c.", + "Col d"); +SELECT * FROM t1; +SHOW CREATE TABLE t1; + +sync_slave_with_master slave; + +--echo Insert some values and select them on slave +SELECT * FROM t1; +SHOW CREATE TABLE t1; + + +# Test boundary limits of bit fields +# m < s, m % 8 != 0, and s % 8 == 0 col a +# m < s, m % 8 == 0, and s % 8 != 0 col b +# m < s, m % 8 != 0, and s % 8 != 0 col c +# m > s, m % 8 != 0, and s % 8 == 0 <-- error will be caught in BUG#22086 +# m > s, m % 8 == 0, and s % 8 != 0 <-- error will be caught in BUG#22086 +# m > s, m % 8 != 0, and s % 8 != 0 <-- error will be caught in BUG#22086 + +connection master; +DROP TABLE t1; + +--echo Create bit table on master +CREATE TABLE t1 ( + a BIT(7), + b BIT(8), + c BIT(21), + d BIT(11), + e BIT(11) +); + +sync_slave_with_master slave; + +--echo Create bit table on slave +DROP TABLE t1; +CREATE TABLE t1 ( + a BIT(16), + b BIT(22), + c BIT(54), + d BIT(25), + e BIT(13) +); + +connection master; + +--echo Insert some values and select them on master +INSERT INTO t1 VALUES ( + b'1010101', + b'10101011', + b'101010110101010101111', + b'10101010101', + b'10101011111' + ); + +SELECT BIN(a), BIN(b), BIN(c), BIN(d), BIN(e) FROM t1; +SHOW CREATE TABLE t1; + +sync_slave_with_master slave; + +--echo Insert some values and select them on master +SELECT BIN(a), BIN(b), BIN(c), BIN(d), BIN(e) FROM t1; +SHOW CREATE TABLE t1; + +--echo *** Cleanup *** +connection master; +DROP TABLE t1; +sync_slave_with_master; + +# END 5.1 Test Case diff --git a/mysql-test/t/rpl_row_create_table.test b/mysql-test/t/rpl_row_create_table.test index d1b26f9e3f4..d41f6b0bf69 100644 --- a/mysql-test/t/rpl_row_create_table.test +++ b/mysql-test/t/rpl_row_create_table.test @@ -72,7 +72,7 @@ CREATE TABLE t7 (UNIQUE(b)) SELECT a,b FROM tt3; # Shouldn't be written to the binary log --replace_column 1 # 4 # --replace_regex /\/\* xid=.* \*\//\/* XID *\// /table_id: [0-9]+/table_id: #/ -SHOW BINLOG EVENTS FROM 1098; +SHOW BINLOG EVENTS FROM 1100; # Test that INSERT-SELECT works the same way as for SBR. CREATE TABLE t7 (a INT, b INT UNIQUE); @@ -82,7 +82,7 @@ SELECT * FROM t7 ORDER BY a,b; # Should be written to the binary log --replace_column 1 # 4 # --replace_regex /\/\* xid=.* \*\//\/* XID *\// /table_id: [0-9]+/table_id: #/ -SHOW BINLOG EVENTS FROM 1098; +SHOW BINLOG EVENTS FROM 1100; sync_slave_with_master; SELECT * FROM t7 ORDER BY a,b; @@ -94,7 +94,7 @@ INSERT INTO t7 SELECT a,b FROM tt4; ROLLBACK; --replace_column 1 # 4 # --replace_regex /\/\* xid=.* \*\//\/* XID *\// /table_id: [0-9]+/table_id: #/ -SHOW BINLOG EVENTS FROM 1294; +SHOW BINLOG EVENTS FROM 1298; SELECT * FROM t7 ORDER BY a,b; sync_slave_with_master; SELECT * FROM t7 ORDER BY a,b; @@ -110,7 +110,7 @@ CREATE TEMPORARY TABLE tt7 SELECT 1; --query_vertical SHOW CREATE TABLE t9 --replace_column 1 # 4 # --replace_regex /\/\* xid=.* \*\//\/* XID *\// /table_id: [0-9]+/table_id: #/ -SHOW BINLOG EVENTS FROM 1390; +SHOW BINLOG EVENTS FROM 1396; sync_slave_with_master; --echo **** On Slave **** --query_vertical SHOW CREATE TABLE t8 @@ -227,7 +227,7 @@ ROLLBACK; SELECT * FROM t2 ORDER BY a; --replace_column 1 # 4 # --replace_regex /\/\* xid=.* \*\//\/* XID *\// /Server ver: .*, Binlog ver: .*/Server ver: #, Binlog ver: #/ /table_id: [0-9]+/table_id: #/ -SHOW BINLOG EVENTS FROM 631; +SHOW BINLOG EVENTS FROM 637; sync_slave_with_master; SELECT * FROM t2 ORDER BY a; diff --git a/mysql-test/t/rpl_row_flsh_tbls.test b/mysql-test/t/rpl_row_flsh_tbls.test index a2f9e31fc5d..bfa356fbfb4 100644 --- a/mysql-test/t/rpl_row_flsh_tbls.test +++ b/mysql-test/t/rpl_row_flsh_tbls.test @@ -1,7 +1,7 @@ # depends on the binlog output -- source include/have_binlog_format_row.inc -let $rename_event_pos= 619; +let $rename_event_pos= 623; # Bug#18326: Do not lock table for writing during prepare of statement # The use of the ps protocol causes extra table maps in the binlog, so diff --git a/sql/field.cc b/sql/field.cc index fa25871fe61..d9aa822b93f 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -1358,6 +1358,49 @@ bool Field::send_binary(Protocol *protocol) } +/** + Unpack a field from row data. + + This method is used to unpack a field from a master whose size + of the field is less than that of the slave. + + @param to Destination of the data + @param from Source of the data + @param param_data Pack length of the field data + + @return New pointer into memory based on from + length of the data +*/ +const char *Field::unpack(char* to, const char *from, uint param_data) +{ + uint length=pack_length(); + int from_type= 0; + /* + If from length is > 255, it has encoded data in the upper bits. Need + to mask it out. + */ + if (param_data > 255) + { + from_type= (param_data & 0xff00) >> 8U; // real_type. + param_data= param_data & 0x00ff; // length. + } + uint len= (param_data && (param_data < length)) ? + param_data : length; + /* + If the length is the same, use old unpack method. + If the param_data is 0, use the old unpack method. + This is possible if the table map was generated from a down-level + master or if the data was not available on the master. + If the real_types are not the same, use the old unpack method. + */ + if ((length == param_data) || + (param_data == 0) || + (from_type != real_type())) + return(unpack(to, from)); + memcpy(to, from, param_data > length ? length : len); + return from+len; +} + + my_decimal *Field::val_decimal(my_decimal *decimal) { /* This never have to be called */ @@ -2635,6 +2678,51 @@ uint Field_new_decimal::is_equal(create_field *new_field) (new_field->decimals == dec)); } +/** + Unpack a decimal field from row data. + + This method is used to unpack a decimal or numeric field from a master + whose size of the field is less than that of the slave. + + @param to Destination of the data + @param from Source of the data + @param param_data Precision (upper) and decimal (lower) values + + @return New pointer into memory based on from + length of the data +*/ +const char *Field_new_decimal::unpack(char* to, + const char *from, + uint param_data) +{ + uint from_precision= (param_data & 0xff00) >> 8U; + uint from_decimal= param_data & 0x00ff; + uint length=pack_length(); + uint from_pack_len= my_decimal_get_binary_size(from_precision, from_decimal); + uint len= (param_data && (from_pack_len < length)) ? + from_pack_len : length; + if (from_pack_len && (from_pack_len < length)) + { + /* + If the master's data is smaller than the slave, we need to convert + the binary to decimal then resize the decimal converting it back to + a decimal and write that to the raw data buffer. + */ + decimal_digit_t dec_buf[DECIMAL_MAX_PRECISION]; + decimal_t dec; + dec.len= from_precision; + dec.buf= dec_buf; + /* + Note: bin2decimal does not change the length of the field. So it is + just the first step the resizing operation. The second step does the + resizing using the precision and decimals from the slave. + */ + bin2decimal((char *)from, &dec, from_precision, from_decimal); + decimal2bin(&dec, to, precision, decimals()); + } + else + memcpy(to, from, len); // Sizes are the same, just copy the data. + return from+len; +} /**************************************************************************** ** tiny int @@ -6294,6 +6382,37 @@ char *Field_string::pack(char *to, const char *from, uint max_length) } +/** + Unpack a string field from row data. + + This method is used to unpack a string field from a master whose size + of the field is less than that of the slave. Note that there can be a + variety of field types represented with this class. Certain types like + ENUM or SET are processed differently. Hence, the upper byte of the + @c param_data argument contains the result of field->real_type() from + the master. + + @param to Destination of the data + @param from Source of the data + @param param_data Real type (upper) and length (lower) values + + @return New pointer into memory based on from + length of the data +*/ +const char *Field_string::unpack(char *to, + const char *from, + uint param_data) +{ + uint from_len= param_data & 0x00ff; // length. + uint length= 0; + uint f_length= (from_len < field_length) ? from_len : field_length; + DBUG_ASSERT(f_length <= 255); + length= (uint) *from++; + bitmap_set_bit(table->write_set,field_index); + store(from, length, system_charset_info); + return from+length; +} + + const char *Field_string::unpack(char *to, const char *from) { uint length; @@ -6782,6 +6901,44 @@ char *Field_varstring::pack_key_from_key_image(char *to, const char *from, } +/** + Unpack a varstring field from row data. + + This method is used to unpack a varstring field from a master + whose size of the field is less than that of the slave. + + @param to Destination of the data + @param from Source of the data + @param param_data Length bytes from the master's field data + + @return New pointer into memory based on from + length of the data +*/ +const char *Field_varstring::unpack(char *to, + const char *from, + uint param_data) +{ + uint length; + uint l_bytes= (param_data && (param_data < field_length)) ? + (param_data <= 255) ? 1 : 2 : length_bytes; + if (l_bytes == 1) + { + to[0]= *from++; + length= to[0]; + if (length_bytes == 2) + to[1]= 0; + } + else + { + length= uint2korr(from); + to[0]= *from++; + to[1]= *from++; + } + if (length) + memcpy(to+ length_bytes, from, length); + return from+length; +} + + /* unpack field packed with Field_varstring::pack() */ @@ -7473,6 +7630,29 @@ char *Field_blob::pack(char *to, const char *from, uint max_length) } +/** + Unpack a blob field from row data. + + This method is used to unpack a blob field from a master whose size of + the field is less than that of the slave. Note: This method is included + to satisfy inheritance rules, but is not needed for blob fields. It + simply is used as a pass-through to the original unpack() method for + blob fields. + + @param to Destination of the data + @param from Source of the data + @param param_data + + @return New pointer into memory based on from + length of the data +*/ +const char *Field_blob::unpack(char *to, + const char *from, + uint param_data) +{ + return unpack(to, from); +} + + const char *Field_blob::unpack(char *to, const char *from) { memcpy(to,from,packlength); @@ -8510,6 +8690,58 @@ char *Field_bit::pack(char *to, const char *from, uint max_length) } +/** + Unpack a bit field from row data. + + This method is used to unpack a bit field from a master whose size + of the field is less than that of the slave. + + @param to Destination of the data + @param from Source of the data + @param param_data Bit length (upper) and length (lower) values + + @return New pointer into memory based on from + length of the data +*/ +const char *Field_bit::unpack(char *to, + const char *from, + uint param_data) +{ + uint const from_len= (param_data >> 8U) & 0x00ff; + uint const from_bit_len= param_data & 0x00ff; + /* + If the master and slave have the same sizes, then use the old + unpack() method. + */ + if ((from_bit_len == bit_len) && + (from_len == bytes_in_rec)) + return(unpack(to, from)); + /* + We are converting a smaller bit field to a larger one here. + To do that, we first need to construct a raw value for the original + bit value stored in the from buffer. Then that needs to be converted + to the larger field then sent to store() for writing to the field. + Lastly the odd bits need to be masked out if the bytes_in_rec > 0. + Otherwise stray bits can cause spurious values. + */ + uint new_len= (field_length + 7) / 8; + char *value= (char *)my_alloca(new_len); + bzero(value, new_len); + uint len= from_len + ((from_bit_len > 0) ? 1 : 0); + memcpy(value + (new_len - len), from, len); + /* + Mask out the unused bits in the partial byte. + TODO: Add code to the master to always mask these bits and remove + the following. + */ + if ((from_bit_len > 0) && (from_len > 0)) + value[new_len - len]= value[new_len - len] & ((1U << from_bit_len) - 1); + bitmap_set_bit(table->write_set,field_index); + store(value, new_len, system_charset_info); + my_afree(value); + return from + len; +} + + const char *Field_bit::unpack(char *to, const char *from) { if (bit_len > 0) diff --git a/sql/field.h b/sql/field.h index 2c2640a8262..545e34bd551 100644 --- a/sql/field.h +++ b/sql/field.h @@ -342,6 +342,7 @@ public: memcpy(to,from,length); return to+length; } + virtual const char *unpack(char* to, const char *from, uint param_data); virtual const char *unpack(char* to, const char *from) { uint length=pack_length(); @@ -613,6 +614,7 @@ public: uint size_of() const { return sizeof(*this); } uint32 pack_length() const { return (uint32) bin_size; } uint is_equal(create_field *new_field); + virtual const char *unpack(char* to, const char *from, uint param_data); }; @@ -1154,6 +1156,7 @@ public: void sort_string(char *buff,uint length); void sql_type(String &str) const; char *pack(char *to, const char *from, uint max_length=~(uint) 0); + virtual const char *unpack(char* to, const char *from, uint param_data); const char *unpack(char* to, const char *from); int pack_cmp(const char *a,const char *b,uint key_length, my_bool insert_or_update); @@ -1224,6 +1227,7 @@ public: char *pack(char *to, const char *from, uint max_length=~(uint) 0); char *pack_key(char *to, const char *from, uint max_length); char *pack_key_from_key_image(char* to, const char *from, uint max_length); + virtual const char *unpack(char* to, const char *from, uint param_data); const char *unpack(char* to, const char *from); const char *unpack_key(char* to, const char *from, uint max_length); int pack_cmp(const char *a, const char *b, uint key_length, @@ -1279,6 +1283,9 @@ public: l_char_length <= 16777215 ? 3 : 4; } } + Field_blob(uint32 packlength_arg) + :Field_longstr((char*) 0, 0, (uchar*) "", 0, NONE, "temp", system_charset_info), + packlength(packlength_arg) {} enum_field_types type() const { return MYSQL_TYPE_BLOB;} enum ha_base_keytype key_type() const { return binary() ? HA_KEYTYPE_VARBINARY2 : HA_KEYTYPE_VARTEXT2; } @@ -1300,6 +1307,17 @@ public: void sort_string(char *buff,uint length); uint32 pack_length() const { return (uint32) (packlength+table->s->blob_ptr_size); } + + /** + Return the packed length without the pointer size added. + + This is used to determine the size of the actual data in the row + buffer. + + @retval The length of the raw data itself without the pointer. + */ + uint32 pack_length_no_ptr() const + { return (uint32) (packlength); } uint32 sort_length() const; inline uint32 max_data_length() const { @@ -1316,6 +1334,17 @@ public: store_length(ptr, packlength, number); } + /** + Return the packed length plus the length of the data. + + This is used to determine the size of the data plus the + packed length portion in the row data. + + @retval The length in the row plus the size of the data. + */ + uint32 get_packed_size(const uchar *ptr) + {return packlength + get_length((uint)ptr);} + inline uint32 get_length(uint row_offset=0) { return get_length(ptr+row_offset); } uint32 get_length(const char *ptr); @@ -1360,6 +1389,7 @@ public: char *pack(char *to, const char *from, uint max_length= ~(uint) 0); char *pack_key(char *to, const char *from, uint max_length); char *pack_key_from_key_image(char* to, const char *from, uint max_length); + virtual const char *unpack(char *to, const char *from, uint param_data); const char *unpack(char *to, const char *from); const char *unpack_key(char* to, const char *from, uint max_length); int pack_cmp(const char *a, const char *b, uint key_length, @@ -1534,6 +1564,7 @@ public: uint32 pack_length_in_rec() const { return bytes_in_rec; } void sql_type(String &str) const; char *pack(char *to, const char *from, uint max_length=~(uint) 0); + virtual const char *unpack(char *to, const char *from, uint param_data); const char *unpack(char* to, const char *from); virtual void set_default(); diff --git a/sql/log_event.cc b/sql/log_event.cc index 6565278e6d3..eb1f6aeeaf9 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -5976,11 +5976,8 @@ int Rows_log_event::do_apply_event(RELAY_LOG_INFO const *rli) #ifdef HAVE_QUERY_CACHE query_cache.invalidate_locked_for_write(rli->tables_to_lock); #endif - const_cast(rli)->clear_tables_to_lock(); } - DBUG_ASSERT(rli->tables_to_lock == NULL && rli->tables_to_lock_count == 0); - TABLE* table= const_cast(rli)->m_table_map.get_table(m_table_id); if (table) @@ -6076,6 +6073,13 @@ int Rows_log_event::do_apply_event(RELAY_LOG_INFO const *rli) } } + /* + We need to delay this clear until the table def is no longer needed. + The table def is needed in unpack_row(). + */ + if (rli->tables_to_lock && get_flags(STMT_END_F)) + const_cast(rli)->clear_tables_to_lock(); + if (error) { /* error has occured during the transaction */ slave_print_msg(ERROR_LEVEL, rli, thd->net.last_errno, @@ -6314,6 +6318,163 @@ void Rows_log_event::print_helper(FILE *file, Table_map_log_event member functions and support functions **************************************************************************/ +/** + * Calculate field metadata size based on the real_type of the field. + * + * @returns int Size of field metadata. + */ +#if !defined(MYSQL_CLIENT) +const int Table_map_log_event::calc_field_metadata_size() +{ + DBUG_ENTER("Table_map_log_event::calc_field_metadata_size"); + int size= 0; + for (unsigned int i= 0 ; i < m_table->s->fields ; i++) + { + switch (m_table->s->field[i]->real_type()) { + case MYSQL_TYPE_TINY_BLOB: + case MYSQL_TYPE_BLOB: + case MYSQL_TYPE_MEDIUM_BLOB: + case MYSQL_TYPE_LONG_BLOB: + case MYSQL_TYPE_DOUBLE: + case MYSQL_TYPE_FLOAT: + { + size++; // Store one byte here. + break; + } + case MYSQL_TYPE_BIT: + case MYSQL_TYPE_NEWDECIMAL: + case MYSQL_TYPE_ENUM: + case MYSQL_TYPE_STRING: + case MYSQL_TYPE_VARCHAR: + case MYSQL_TYPE_SET: + { + size= size + sizeof(short int); // Store short int here. + break; + } + default: + break; + } + } + m_field_metadata_size= size; + DBUG_PRINT("info", ("Table_map_log_event: %d bytes in field metadata.", + (int)m_field_metadata_size)); + DBUG_RETURN(m_field_metadata_size); +} +#endif /* !defined(MYSQL_CLIENT) */ + +/** + @page How replication of field metadata works. + + When a table map is created, the master first calls + Table_map_log_event::get_field_metadata_size() which calculates how many + values will be in the field metadata. Only those fields that require the + extra data are added (see table above). The master then loops through all + of the fields in the table calling the method + Table_map_log_event::get_field_metadata() which returns the values for the + field that will be saved in the metadata and replicated to the slave. Once + all fields have been processed, the table map is written to the binlog + adding the size of the field metadata and the field metadata to the end of + the body of the table map. + + When a table map is read on the slave, the field metadata is read from the + table map and passed to the table_def class constructor which saves the + field metadata from the table map into an array based on the type of the + field. Field metadata values not present (those fields that do not use extra + data) in the table map are initialized as zero (0). The array size is the + same as the columns for the table on the slave. + +*/ + +/** + Save the field metadata based on the real_type of the field. + The metadata saved depends on the type of the field. Some fields + store a single byte for pack_length() while others store two bytes + for field_length (max length). + + @retval 0 Ok. + + TODO: We may want to consider changing the encoding of the information. + Currently, the code attempts to minimize the number of bytes written to + the tablemap. There are at least two other alternatives; 1) using + net_store_length() to store the data allowing it to choose the number of + bytes that are appropriate thereby making the code much easier to + maintain (only 1 place to change the encoding), or 2) use a fixed number + of bytes for each field. The problem with option 1 is that net_store_length() + will use one byte if the value < 251, but 3 bytes if it is > 250. Thus, + for fields like CHAR which can be no larger than 255 characters, the method + will use 3 bytes when the value is > 250. Further, every value that is + encoded using 2 parts (e.g., pack_length, field_length) will be numerically + > 250 therefore will use 3 bytes for eah value. The problem with option 2 + is less wasteful for space but does waste 1 byte for every field that does + not encode 2 parts. +*/ +#if !defined(MYSQL_CLIENT) +int Table_map_log_event::save_field_metadata() +{ + DBUG_ENTER("Table_map_log_event::save_field_metadata"); + int index= 0; + for (unsigned int i= 0 ; i < m_table->s->fields ; i++) + { + switch (m_table->s->field[i]->real_type()) { + case MYSQL_TYPE_NEWDECIMAL: + { + m_field_metadata[index++]= + (uchar)((Field_new_decimal *)m_table->s->field[i])->precision; + m_field_metadata[index++]= + (uchar)((Field_new_decimal *)m_table->s->field[i])->decimals(); + break; + } + case MYSQL_TYPE_TINY_BLOB: + case MYSQL_TYPE_BLOB: + case MYSQL_TYPE_MEDIUM_BLOB: + case MYSQL_TYPE_LONG_BLOB: + { + m_field_metadata[index++]= + (uchar)((Field_blob *)m_table->s->field[i])->pack_length_no_ptr(); + break; + } + case MYSQL_TYPE_DOUBLE: + case MYSQL_TYPE_FLOAT: + { + m_field_metadata[index++]= (uchar)m_table->s->field[i]->pack_length(); + break; + } + case MYSQL_TYPE_BIT: + { + m_field_metadata[index++]= + (uchar)((Field_bit *)m_table->s->field[i])->bit_len; + m_field_metadata[index++]= + (uchar)((Field_bit *)m_table->s->field[i])->bytes_in_rec; + break; + } + case MYSQL_TYPE_VARCHAR: + { + short int *x= (short int *)&m_field_metadata[index]; + int2store(x, m_table->s->field[i]->field_length); + index= index + sizeof(short int); + break; + } + case MYSQL_TYPE_STRING: + { + m_field_metadata[index++]= (uchar)m_table->s->field[i]->real_type(); + m_field_metadata[index++]= m_table->s->field[i]->field_length; + break; + } + case MYSQL_TYPE_ENUM: + case MYSQL_TYPE_SET: + { + m_field_metadata[index++]= (uchar)m_table->s->field[i]->real_type(); + m_field_metadata[index++]= m_table->s->field[i]->pack_length(); + break; + } + default: + break; + } + } + DBUG_RETURN(0); +} +#endif /* !defined(MYSQL_CLIENT) */ + /* Constructor used to build an event for writing to the binary log. Mats says tbl->s lives longer than this event so it's ok to copy pointers @@ -6328,9 +6489,8 @@ Table_map_log_event::Table_map_log_event(THD *thd, TABLE *tbl, ulong tid, m_dblen(m_dbnam ? tbl->s->db.length : 0), m_tblnam(tbl->s->table_name.str), m_tbllen(tbl->s->table_name.length), - m_colcnt(tbl->s->fields), m_coltype(0), - m_table_id(tid), - m_flags(flags) + m_colcnt(tbl->s->fields), m_field_metadata(0), + m_table_id(tid), m_null_bits(0), m_flags(flags) { DBUG_ASSERT(m_table_id != ~0UL); /* @@ -6349,6 +6509,16 @@ Table_map_log_event::Table_map_log_event(THD *thd, TABLE *tbl, ulong tid, m_data_size+= m_dblen + 2; // Include length and terminating \0 m_data_size+= m_tbllen + 2; // Include length and terminating \0 m_data_size+= 1 + m_colcnt; // COLCNT and column types + m_field_metadata_size= calc_field_metadata_size(); + + /* + Now set the size of the data to the size of the field metadata array + plus one or two bytes for number of elements in the field metadata array. + */ + if (m_field_metadata_size > 255) + m_data_size+= m_field_metadata_size + 2; + else + m_data_size+= m_field_metadata_size + 1; /* If malloc fails, catched in is_valid() */ if ((m_memory= my_malloc(m_colcnt, MYF(MY_WME)))) @@ -6357,6 +6527,28 @@ Table_map_log_event::Table_map_log_event(THD *thd, TABLE *tbl, ulong tid, for (unsigned int i= 0 ; i < m_table->s->fields ; ++i) m_coltype[i]= m_table->field[i]->type(); } + + /* + Calculate a bitmap for the results of maybe_null() for all columns. + The bitmap is used to determine when there is a column from the master + that is not on the slave and is null and thus not in the row data during + replication. + */ + uint num_null_bytes= (m_table->s->fields + 7) / 8; + m_data_size+= num_null_bytes; + m_meta_memory= my_multi_malloc(MYF(MY_WME), + &m_null_bits, num_null_bytes, + &m_field_metadata, m_field_metadata_size, + NULL); + bzero(m_null_bits, num_null_bytes); + for (unsigned int i= 0 ; i < m_table->s->fields ; ++i) + if (m_table->field[i]->maybe_null()) + m_null_bits[(i / 8)]+= 1 << (i % 8); + + /* + Create an array for the field metadata and store it. + */ + save_field_metadata(); } #endif /* !defined(MYSQL_CLIENT) */ @@ -6372,8 +6564,10 @@ Table_map_log_event::Table_map_log_event(const char *buf, uint event_len, #ifndef MYSQL_CLIENT m_table(NULL), #endif - m_memory(NULL) + m_memory(NULL), + m_field_metadata(0), m_field_metadata_size(0) { + unsigned int bytes_read= 0; DBUG_ENTER("Table_map_log_event::Table_map_log_event(const char*,uint,...)"); uint8 common_header_len= description_event->common_header_len; @@ -6444,6 +6638,22 @@ Table_map_log_event::Table_map_log_event(const char *buf, uint event_len, strncpy(const_cast(m_dbnam), (const char*)ptr_dblen + 1, m_dblen + 1); strncpy(const_cast(m_tblnam), (const char*)ptr_tbllen + 1, m_tbllen + 1); memcpy(m_coltype, ptr_after_colcnt, m_colcnt); + + ptr_after_colcnt= ptr_after_colcnt + m_colcnt; + bytes_read= ptr_after_colcnt - (uchar *)buf; + DBUG_PRINT("info", ("Bytes read: %d.\n", bytes_read)); + if (bytes_read < event_len) + { + m_field_metadata_size= net_field_length(&ptr_after_colcnt); + uint num_null_bytes= (m_colcnt + 7) / 8; + m_meta_memory= my_multi_malloc(MYF(MY_WME), + &m_null_bits, num_null_bytes, + &m_field_metadata, m_field_metadata_size, + NULL); + memcpy(m_field_metadata, ptr_after_colcnt, m_field_metadata_size); + ptr_after_colcnt= (uchar*)ptr_after_colcnt + m_field_metadata_size; + memcpy(m_null_bits, ptr_after_colcnt, num_null_bytes); + } } DBUG_VOID_RETURN; @@ -6452,6 +6662,7 @@ Table_map_log_event::Table_map_log_event(const char *buf, uint event_len, Table_map_log_event::~Table_map_log_event() { + my_free(m_meta_memory, MYF(MY_ALLOW_ZERO_PTR)); my_free(m_memory, MYF(MY_ALLOW_ZERO_PTR)); } @@ -6585,7 +6796,8 @@ int Table_map_log_event::do_apply_event(RELAY_LOG_INFO const *rli) inside st_relay_log_info::clear_tables_to_lock() by calling the table_def destructor explicitly. */ - new (&table_list->m_tabledef) table_def(m_coltype, m_colcnt); + new (&table_list->m_tabledef) table_def(m_coltype, m_colcnt, + m_field_metadata, m_field_metadata_size, m_null_bits); table_list->m_tabledef_valid= TRUE; /* @@ -6644,13 +6856,22 @@ bool Table_map_log_event::write_data_body(IO_CACHE *file) char *const cbuf_end= net_store_length((char*) cbuf, (uint) m_colcnt); DBUG_ASSERT(static_cast(cbuf_end - cbuf) <= sizeof(cbuf)); + /* + Store the size of the field metadata. + */ + char mbuf[sizeof(m_field_metadata_size)]; + char *const mbuf_end= net_store_length(mbuf, (size_t) m_field_metadata_size); + return (my_b_safe_write(file, dbuf, sizeof(dbuf)) || my_b_safe_write(file, (const byte*)m_dbnam, m_dblen+1) || my_b_safe_write(file, tbuf, sizeof(tbuf)) || my_b_safe_write(file, (const byte*)m_tblnam, m_tbllen+1) || my_b_safe_write(file, reinterpret_cast(cbuf), cbuf_end - (char*) cbuf) || - my_b_safe_write(file, reinterpret_cast(m_coltype), m_colcnt)); + my_b_safe_write(file, reinterpret_cast(m_coltype), m_colcnt) || + my_b_safe_write(file, reinterpret_cast(mbuf), (size_t) (mbuf_end - mbuf)) || + my_b_safe_write(file, reinterpret_cast(m_field_metadata), m_field_metadata_size), + my_b_safe_write(file, reinterpret_cast(m_null_bits), (m_colcnt + 7) / 8)); } #endif diff --git a/sql/log_event.h b/sql/log_event.h index 4e43822cb38..0ac17e304ca 100644 --- a/sql/log_event.h +++ b/sql/log_event.h @@ -2048,6 +2048,8 @@ public: virtual int get_data_size() { return m_data_size; } #ifndef MYSQL_CLIENT + virtual const int calc_field_metadata_size(); + virtual int save_field_metadata(); virtual bool write_data_header(IO_CACHE *file); virtual bool write_data_body(IO_CACHE *file); virtual const char *get_db() { return m_dbnam; } @@ -2083,6 +2085,14 @@ private: flag_set m_flags; my_size_t m_data_size; + + uchar *m_field_metadata; // buffer for field metadata + /* + The size of field metadata buffer set by calling calc_field_metadata_size() + */ + ulong m_field_metadata_size; + uchar *m_null_bits; + gptr m_meta_memory; }; diff --git a/sql/rpl_record.cc b/sql/rpl_record.cc index 4c6686cf446..d33d60300fd 100644 --- a/sql/rpl_record.cc +++ b/sql/rpl_record.cc @@ -16,6 +16,8 @@ #include "mysql_priv.h" #include "rpl_record.h" #include "slave.h" // Need to pull in slave_print_msg +#include "rpl_utility.h" +#include "rpl_rli.h" /** Pack a record of data for a table into a format suitable for @@ -190,7 +192,9 @@ unpack_row(RELAY_LOG_INFO const *rli, unsigned int null_mask= 1U; // The "current" null bits unsigned int null_bits= *null_ptr++; - for (field_ptr= begin_ptr ; field_ptr < end_ptr ; ++field_ptr) + uint i= 0; + table_def *tabledef= ((RELAY_LOG_INFO*)rli)->get_tabledef(table); + for (field_ptr= begin_ptr ; field_ptr < end_ptr && *field_ptr ; ++field_ptr) { Field *const f= *field_ptr; @@ -219,14 +223,20 @@ unpack_row(RELAY_LOG_INFO const *rli, f->set_notnull(); /* - We only unpack the field if it was non-null - */ - pack_ptr= f->unpack(f->ptr, pack_ptr); + We only unpack the field if it was non-null. + Use the master's size information if available else call + normal unpack operation. + */ + if (tabledef && tabledef->field_metadata(i)) + pack_ptr= f->unpack(f->ptr, pack_ptr, tabledef->field_metadata(i)); + else + pack_ptr= f->unpack(f->ptr, pack_ptr); } bitmap_set_bit(rw_set, f->field_index); null_mask <<= 1; } + i++; } /* diff --git a/sql/rpl_rli.h b/sql/rpl_rli.h index fada45722f6..b30f8599f6a 100644 --- a/sql/rpl_rli.h +++ b/sql/rpl_rli.h @@ -19,6 +19,7 @@ #define MAX_SLAVE_ERRMSG 1024 #include "rpl_tblmap.h" +#include "rpl_utility.h" struct RPL_TABLE_LIST; @@ -305,6 +306,15 @@ typedef struct st_relay_log_info uint tables_to_lock_count; /* RBR: Count of tables to lock */ table_mapping m_table_map; /* RBR: Mapping table-id to table */ + inline table_def *get_tabledef(TABLE *tbl) + { + table_def *td= 0; + for (TABLE_LIST *ptr= tables_to_lock; ptr && !td; ptr= ptr->next_global) + if (ptr->table == tbl) + td= &((RPL_TABLE_LIST *)ptr)->m_tabledef; + return (td); + } + /* Last charset (6 bytes) seen by slave SQL thread is cached here; it helps the thread save 3 get_charset() per Query_log_event if the charset is not diff --git a/sql/rpl_utility.cc b/sql/rpl_utility.cc index 1d7cc808f0c..143251991b5 100644 --- a/sql/rpl_utility.cc +++ b/sql/rpl_utility.cc @@ -15,17 +15,46 @@ #include "rpl_utility.h" -uint32 -field_length_from_packed(enum_field_types const field_type, - byte const *const data) + +/********************************************************************* + * table_def member definitions * + *********************************************************************/ + +/* + This function returns the field size in raw bytes based on the type + and the encoded field data from the master's raw data. +*/ +uint32 table_def::calc_field_size(uint col, uchar *master_data) { uint32 length; - switch (field_type) { - case MYSQL_TYPE_DECIMAL: + switch (type(col)) { case MYSQL_TYPE_NEWDECIMAL: - length= ~(uint32) 0; + length= my_decimal_get_binary_size(m_field_metadata[col] >> 8, + m_field_metadata[col] - ((m_field_metadata[col] >> 8) << 8)); break; + case MYSQL_TYPE_DECIMAL: + case MYSQL_TYPE_FLOAT: + case MYSQL_TYPE_DOUBLE: + length= m_field_metadata[col]; + break; + case MYSQL_TYPE_SET: + case MYSQL_TYPE_ENUM: + case MYSQL_TYPE_STRING: + { + if (((m_field_metadata[col] & 0xff00) == (MYSQL_TYPE_SET << 8)) || + ((m_field_metadata[col] & 0xff00) == (MYSQL_TYPE_ENUM << 8))) + length= m_field_metadata[col] & 0x00ff; + else + { + length= m_field_metadata[col] & 0x00ff; + if (length > 255) + length= uint2korr(master_data) + 2; + else + length= (uint) *master_data + 1; + } + break; + } case MYSQL_TYPE_YEAR: case MYSQL_TYPE_TINY: length= 1; @@ -44,12 +73,6 @@ field_length_from_packed(enum_field_types const field_type, length= 8; break; #endif - case MYSQL_TYPE_FLOAT: - length= sizeof(float); - break; - case MYSQL_TYPE_DOUBLE: - length= sizeof(double); - break; case MYSQL_TYPE_NULL: length= 0; break; @@ -57,8 +80,6 @@ field_length_from_packed(enum_field_types const field_type, length= 3; break; case MYSQL_TYPE_DATE: - length= 4; - break; case MYSQL_TYPE_TIME: length= 3; break; @@ -68,41 +89,33 @@ field_length_from_packed(enum_field_types const field_type, case MYSQL_TYPE_DATETIME: length= 8; break; - break; case MYSQL_TYPE_BIT: - length= ~(uint32) 0; + { + uint from_len= (m_field_metadata[col] >> 8U) & 0x00ff; + uint from_bit_len= m_field_metadata[col] & 0x00ff; + length= from_len + ((from_bit_len > 0) ? 1 : 0); break; - default: - /* This case should never be chosen */ - DBUG_ASSERT(0); - /* If something goes awfully wrong, it's better to get a string than die */ - case MYSQL_TYPE_STRING: - length= uint2korr(data); - break; - - case MYSQL_TYPE_ENUM: - case MYSQL_TYPE_SET: - case MYSQL_TYPE_VAR_STRING: + } case MYSQL_TYPE_VARCHAR: - length= ~(uint32) 0; // NYI + length= m_field_metadata[col] > 255 ? 2 : 1; // c&p of Field_varstring::data_length() + length+= length == 1 ? (uint32) *master_data : uint2korr(master_data); break; - case MYSQL_TYPE_TINY_BLOB: case MYSQL_TYPE_MEDIUM_BLOB: case MYSQL_TYPE_LONG_BLOB: case MYSQL_TYPE_BLOB: case MYSQL_TYPE_GEOMETRY: - length= ~(uint32) 0; // NYI + { + Field_blob fb(m_field_metadata[col]); + length= fb.get_packed_size(master_data); break; } - + default: + length= -1; + } return length; } -/********************************************************************* - * table_def member definitions * - *********************************************************************/ - /* Is the definition compatible with a table? @@ -135,8 +148,14 @@ table_def::compatible_with(RELAY_LOG_INFO const *rli_arg, TABLE *table) tsh->fields); } + /* + We now check for column type and size compatibility. + */ for (uint col= 0 ; col < cols_to_check ; ++col) { + /* + Checking types. + */ if (table->field[col]->type() != type(col)) { DBUG_ASSERT(col < size() && col < tsh->fields); diff --git a/sql/rpl_utility.h b/sql/rpl_utility.h index 82992eec690..b4707a4c7bd 100644 --- a/sql/rpl_utility.h +++ b/sql/rpl_utility.h @@ -21,13 +21,11 @@ #endif #include "mysql_priv.h" +#include "my_bitmap.h" struct st_relay_log_info; typedef st_relay_log_info RELAY_LOG_INFO; -uint32 -field_length_from_packed(enum_field_types field_type, byte const *data); - /** A table definition from the master. @@ -57,19 +55,90 @@ public: @param types Array of types @param size Number of elements in array 'types' + @param field_metadata Array of extra information about fields + @param metadata_size Size of the field_metadata array + @param null_bitmap The bitmap of fields that can be null */ - table_def(field_type *types, my_size_t size) - : m_size(size), m_type(new unsigned char [size]) + table_def(field_type *types, ulong size, uchar *field_metadata, + int metadata_size, uchar *null_bitmap) + : m_size(size), m_type(0), + m_field_metadata(0), m_null_bits(0), m_memory(NULL) { + m_memory= my_multi_malloc(MYF(MY_WME), + &m_type, size, + &m_field_metadata, size * sizeof(short), + &m_null_bits, (m_size + 7) / 8, + NULL); if (m_type) memcpy(m_type, types, size); else m_size= 0; + /* + Extract the data from the table map into the field metadata array + iff there is field metadata. The variable metadata_size will be + 0 if we are replicating from an older version server since no field + metadata was written to the table map. This can also happen if + there were no fields in the master that needed extra metadata. + */ + if (m_size && metadata_size) + { + int index= 0; + for (unsigned int i= 0; i < m_size; i++) + { + switch (m_type[i]) { + case MYSQL_TYPE_TINY_BLOB: + case MYSQL_TYPE_BLOB: + case MYSQL_TYPE_MEDIUM_BLOB: + case MYSQL_TYPE_LONG_BLOB: + case MYSQL_TYPE_DOUBLE: + case MYSQL_TYPE_FLOAT: + { + /* + These types store a single byte. + */ + m_field_metadata[i]= (uchar)field_metadata[index]; + index++; + break; + } + case MYSQL_TYPE_SET: + case MYSQL_TYPE_ENUM: + case MYSQL_TYPE_STRING: + { + short int x= field_metadata[index++] << 8U; // real_type + x = x + field_metadata[index++]; // pack or field length + m_field_metadata[i]= x; + break; + } + case MYSQL_TYPE_BIT: + case MYSQL_TYPE_VARCHAR: + { + /* + These types store two bytes. + */ + short int *x= (short int *)&field_metadata[index]; + m_field_metadata[i]= sint2korr(x); + index= index + sizeof(short int); + break; + } + case MYSQL_TYPE_NEWDECIMAL: + { + short int x= field_metadata[index++] << 8U; // precision + x = x + field_metadata[index++]; // decimals + m_field_metadata[i]= x; + break; + } + default: + m_field_metadata[i]= 0; + break; + } + } + } + if (m_size && null_bitmap) + memcpy(m_null_bits, null_bitmap, (m_size + 7) / 8); } ~table_def() { - if (m_type) - delete [] m_type; + my_free(m_memory, MYF(0)); #ifndef DBUG_OFF m_type= 0; m_size= 0; @@ -100,6 +169,47 @@ public: return m_type[index]; } + /* + This function allows callers to get the extra field data from the + table map for a given field. If there is no metadata for that field + or there is no extra metadata at all, the function returns 0. + + The function returns the value for the field metadata for column at + position indicated by index. As mentioned, if the field was a type + that stores field metadata, that value is returned else zero (0) is + returned. This method is used in the unpack() methods of the + corresponding fields to properly extract the data from the binary log + in the event that the master's field is smaller than the slave. + */ + uint16 field_metadata(uint index) const + { + DBUG_ASSERT(index < m_size); + if (m_field_metadata) + return m_field_metadata[index]; + else + return 0; + } + + /* + This function returns whether the field on the master can be null. + This value is derived from field->maybe_null(). + */ + my_bool maybe_null(uint index) const + { + DBUG_ASSERT(index < m_size); + return ((m_null_bits[(index / 8)] & + (1 << (index % 8))) == (1 << (index %8))); + } + + /* + This function returns the field size in raw bytes based on the type + and the encoded field data from the master's raw data. This method can + be used for situations where the slave needs to skip a column (e.g., + WL#3915) or needs to advance the pointer for the fields in the raw + data from the master to a specific column. + */ + uint32 calc_field_size(uint col, uchar *master_data); + /** Decide if the table definition is compatible with a table. @@ -122,6 +232,9 @@ public: private: my_size_t m_size; // Number of elements in the types array field_type *m_type; // Array of type descriptors + short int *m_field_metadata; + uchar *m_null_bits; + gptr m_memory; }; /**