summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mysql-test/suite/binlog/r/binlog_stm_mix_innodb_myisam.result131
-rw-r--r--mysql-test/suite/binlog/t/binlog_stm_mix_innodb_myisam.test140
-rw-r--r--mysql-test/suite/rpl/r/rpl_packet.result42
-rw-r--r--mysql-test/suite/rpl/t/rpl_packet.test16
-rw-r--r--sql/field.cc1
-rw-r--r--sql/log_event.cc10
-rw-r--r--sql/rpl_utility.cc36
-rw-r--r--sql/rpl_utility.h14
-rw-r--r--sql/sql_delete.cc6
-rw-r--r--sql/sql_insert.cc106
-rw-r--r--sql/sql_load.cc2
-rw-r--r--sql/sql_update.cc2
12 files changed, 386 insertions, 120 deletions
diff --git a/mysql-test/suite/binlog/r/binlog_stm_mix_innodb_myisam.result b/mysql-test/suite/binlog/r/binlog_stm_mix_innodb_myisam.result
index 5ef36861c30..564fa8d86bd 100644
--- a/mysql-test/suite/binlog/r/binlog_stm_mix_innodb_myisam.result
+++ b/mysql-test/suite/binlog/r/binlog_stm_mix_innodb_myisam.result
@@ -380,7 +380,7 @@ select
@a like "%#%error_code=0%ROLLBACK/*!*/;%ROLLBACK /* added by mysqlbinlog */;%" @a not like "%#%error_code=%error_code=%"
1 1
drop table t1, t2;
-create table tt (a int unique);
+create temporary table tt (a int unique);
create table ti (a int) engine=innodb;
reset master;
show master status;
@@ -399,18 +399,18 @@ count(*)
show master status;
File Position Binlog_Do_DB Binlog_Ignore_DB
master-bin.000001 515
-show binlog events from 106;
+show binlog events from <binlog_start>;
Log_name Pos Event_type Server_id End_log_pos Info
-master-bin.000001 # Query 1 # use `test`; BEGIN
-master-bin.000001 # Query 1 # use `test`; insert into ti values (1)
-master-bin.000001 # Query 1 # use `test`; insert into ti values (2)
-master-bin.000001 # Query 1 # use `test`; insert into tt select * from ti
-master-bin.000001 # Query 1 # use `test`; ROLLBACK
+master-bin.000001 # Query # # use `test`; BEGIN
+master-bin.000001 # Query # # use `test`; insert into ti values (1)
+master-bin.000001 # Query # # use `test`; insert into ti values (2)
+master-bin.000001 # Query # # use `test`; insert into tt select * from ti
+master-bin.000001 # Query # # use `test`; ROLLBACK
select count(*) from ti /* zero */;
count(*)
0
insert into ti select * from tt;
-select * from ti /* that is what slave would miss - a bug */;
+select * from ti /* that is what slave would miss - bug#28960 */;
a
1
2
@@ -431,13 +431,13 @@ Warning 1196 Some non-transactional changed tables couldn't be rolled back
show master status;
File Position Binlog_Do_DB Binlog_Ignore_DB
master-bin.000001 589
-show binlog events from 106;
+show binlog events from <binlog_start>;
Log_name Pos Event_type Server_id End_log_pos Info
-master-bin.000001 # Query 1 # use `test`; BEGIN
-master-bin.000001 # Query 1 # use `test`; insert into ti values (1)
-master-bin.000001 # Query 1 # use `test`; insert into ti values (2) /* to make the dup error in the following */
-master-bin.000001 # Query 1 # use `test`; insert into tt select * from ti /* one affected and error */
-master-bin.000001 # Query 1 # use `test`; ROLLBACK
+master-bin.000001 # Query # # use `test`; BEGIN
+master-bin.000001 # Query # # use `test`; insert into ti values (1)
+master-bin.000001 # Query # # use `test`; insert into ti values (2) /* to make the dup error in the following */
+master-bin.000001 # Query # # use `test`; insert into tt select * from ti /* one affected and error */
+master-bin.000001 # Query # # use `test`; ROLLBACK
select count(*) from ti /* zero */;
count(*)
0
@@ -446,7 +446,7 @@ select * from tt /* that is what otherwise slave missed - the bug */;
a
1
2
-drop table ti,tt;
+drop table ti;
drop function if exists bug27417;
drop table if exists t1,t2;
CREATE TABLE t1 (a int NOT NULL auto_increment primary key) ENGINE=MyISAM;
@@ -463,6 +463,11 @@ insert into t2 select bug27417(2);
reset master;
insert into t2 values (bug27417(2));
ERROR 23000: Duplicate entry '2' for key 'PRIMARY'
+show binlog events from <binlog_start>;
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Table_map # # table_id: # (test.t2)
+master-bin.000001 # Table_map # # table_id: # (test.t1)
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
select count(*) from t1 /* must be 3 */;
count(*)
3
@@ -474,6 +479,11 @@ delete from t2 where a=bug27417(3);
select count(*) from t2 /* nothing got deleted */;
count(*)
2
+show binlog events from <binlog_start>;
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Table_map # # table_id: # (test.t2)
+master-bin.000001 # Table_map # # table_id: # (test.t1)
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
select count(*) from t1 /* must be 5 */;
count(*)
5
@@ -482,6 +492,95 @@ affected rows: 0
select count(*) from t1 /* must be 7 */;
count(*)
7
-drop function bug27417;
drop table t1,t2;
+CREATE TABLE t1 (a int NOT NULL auto_increment primary key) ENGINE=MyISAM;
+CREATE TABLE t2 (a int, PRIMARY KEY (a)) ENGINE=InnoDB;
+CREATE TABLE t3 (a int, PRIMARY KEY (a), b int unique);
+insert into t2 values (1);
+reset master;
+insert into t2 values (bug27417(1));
+ERROR 23000: Duplicate entry '1' for key 'PRIMARY'
+show binlog events from <binlog_start>;
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Table_map # # table_id: # (test.t2)
+master-bin.000001 # Table_map # # table_id: # (test.t1)
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Query # # use `test`; ROLLBACK
+select count(*) from t1 /* must be 1 */;
+count(*)
+1
+delete from t1;
+delete from t2;
+insert into t2 values (2);
+reset master;
+insert into t2 select bug27417(1) union select bug27417(2);
+ERROR 23000: Duplicate entry '2' for key 'PRIMARY'
+show binlog events from <binlog_start>;
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Table_map # # table_id: # (test.t2)
+master-bin.000001 # Table_map # # table_id: # (test.t1)
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Query # # use `test`; ROLLBACK
+select count(*) from t1 /* must be 2 */;
+count(*)
+2
+delete from t1;
+insert into t3 values (1,1),(2,3),(3,4);
+reset master;
+update t3 set b=b+bug27417(1);
+ERROR 23000: Duplicate entry '4' for key 'b'
+show binlog events from <binlog_start>;
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Table_map # # table_id: # (test.t3)
+master-bin.000001 # Table_map # # table_id: # (test.t1)
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Update_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+select count(*) from t1 /* must be 2 */;
+count(*)
+2
+delete from t1;
+delete from t2;
+delete from t3;
+insert into t2 values (1);
+insert into t3 values (1,1);
+create trigger trg_del before delete on t2 for each row
+insert into t3 values (bug27417(1), 2);
+reset master;
+delete from t2;
+ERROR 23000: Duplicate entry '1' for key 'PRIMARY'
+show binlog events from <binlog_start>;
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Table_map # # table_id: # (test.t2)
+master-bin.000001 # Table_map # # table_id: # (test.t3)
+master-bin.000001 # Table_map # # table_id: # (test.t1)
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Query # # use `test`; ROLLBACK
+select count(*) from t1 /* must be 1 */;
+count(*)
+1
+delete from t1;
+create table t4 (a int default 0, b int primary key) engine=innodb;
+insert into t4 values (0, 17);
+reset master;
+load data infile '../std_data_ln/rpl_loaddata.dat' into table t4 (a, @b) set b= @b + bug27417(2);
+ERROR 23000: Duplicate entry '17' for key 'PRIMARY'
+select * from t4;
+a b
+0 17
+select count(*) from t1 /* must be 2 */;
+count(*)
+2
+show binlog events from <binlog_start>;
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Table_map # # table_id: # (test.t4)
+master-bin.000001 # Table_map # # table_id: # (test.t1)
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Query # # use `test`; ROLLBACK
+drop trigger trg_del;
+drop table t1,t2,t3,t4;
+drop function bug27417;
end of tests
diff --git a/mysql-test/suite/binlog/t/binlog_stm_mix_innodb_myisam.test b/mysql-test/suite/binlog/t/binlog_stm_mix_innodb_myisam.test
index 1815f3deb34..14397f85c38 100644
--- a/mysql-test/suite/binlog/t/binlog_stm_mix_innodb_myisam.test
+++ b/mysql-test/suite/binlog/t/binlog_stm_mix_innodb_myisam.test
@@ -36,7 +36,7 @@ drop table t1, t2;
# prepare
-create table tt (a int unique);
+create temporary table tt (a int unique);
create table ti (a int) engine=innodb;
reset master;
show master status;
@@ -53,11 +53,10 @@ rollback;
select count(*) from tt /* 2 */;
show master status;
---replace_column 2 # 5 #
-show binlog events from 106;
+source include/show_binlog_events.inc;
select count(*) from ti /* zero */;
insert into ti select * from tt;
-select * from ti /* that is what slave would miss - a bug */;
+select * from ti /* that is what slave would miss - bug#28960 */;
## send_error() branch
@@ -78,13 +77,12 @@ rollback;
# check
show master status;
---replace_column 2 # 5 #
-show binlog events from 106;
+source include/show_binlog_events.inc;
select count(*) from ti /* zero */;
insert into ti select * from tt;
select * from tt /* that is what otherwise slave missed - the bug */;
-drop table ti,tt;
+drop table ti;
#
@@ -122,17 +120,15 @@ insert into t2 select bug27417(2);
reset master;
--error ER_DUP_ENTRY
-insert into t2 values (bug27417(2));
-#TODO: Andrei: enable this test after 23333 is pushed
-#show master status; /* only (!) with fixes for #23333 will show there is the query */;
+insert into t2 values (bug27417(2));
+source include/show_binlog_events.inc; #only (!) with fixes for #23333 will show there is the query
select count(*) from t1 /* must be 3 */;
reset master;
select count(*) from t2;
delete from t2 where a=bug27417(3);
select count(*) from t2 /* nothing got deleted */;
-#TODO: Andrei: enable this test after 23333 is pushed
-#show master status; /* the query must be in regardless of #23333 */;
+source include/show_binlog_events.inc; # the query must be in regardless of #23333
select count(*) from t1 /* must be 5 */;
--enable_info
@@ -140,7 +136,125 @@ delete t2 from t2 where t2.a=bug27417(100) /* must not affect t2 */;
--disable_info
select count(*) from t1 /* must be 7 */;
-drop function bug27417;
+# function bug27417 remains for the following testing of bug#23333
drop table t1,t2;
+#
+# Bug#23333 using the patch (and the test) for bug#27471
+# throughout the bug tests
+# t1 - non-trans side effects gatherer;
+# t2 - transactional table;
+#
+CREATE TABLE t1 (a int NOT NULL auto_increment primary key) ENGINE=MyISAM;
+CREATE TABLE t2 (a int, PRIMARY KEY (a)) ENGINE=InnoDB;
+CREATE TABLE t3 (a int, PRIMARY KEY (a), b int unique);
+
+
+#
+# INSERT
+#
+
+# prepare
+
+ insert into t2 values (1);
+ reset master;
+
+# execute
+
+ --error ER_DUP_ENTRY
+ insert into t2 values (bug27417(1));
+
+# check
+
+ source include/show_binlog_events.inc; # must be event of the query
+ select count(*) from t1 /* must be 1 */;
+
+#
+# INSERT SELECT
+#
+
+# prepare
+ delete from t1;
+ delete from t2;
+ insert into t2 values (2);
+ reset master;
+
+# execute
+
+ --error ER_DUP_ENTRY
+ insert into t2 select bug27417(1) union select bug27417(2);
+
+# check
+
+ source include/show_binlog_events.inc; # must be events of the query
+ select count(*) from t1 /* must be 2 */;
+
+#
+# UPDATE (multi-update see bug#27716)
+#
+
+# prepare
+ delete from t1;
+ insert into t3 values (1,1),(2,3),(3,4);
+ reset master;
+
+# execute
+ --error ER_DUP_ENTRY
+ update t3 set b=b+bug27417(1);
+
+# check
+ source include/show_binlog_events.inc; # must be events of the query
+ select count(*) from t1 /* must be 2 */;
+
+
+#
+# DELETE (for multi-delete see Bug #29136)
+#
+
+# prepare
+ delete from t1;
+ delete from t2;
+ delete from t3;
+ insert into t2 values (1);
+ insert into t3 values (1,1);
+ create trigger trg_del before delete on t2 for each row
+ insert into t3 values (bug27417(1), 2);
+ reset master;
+
+# execute
+ --error ER_DUP_ENTRY
+ delete from t2;
+# check
+ source include/show_binlog_events.inc; # must be events of the query
+ select count(*) from t1 /* must be 1 */;
+
+
+#
+# LOAD DATA
+#
+
+# prepare
+ delete from t1;
+ create table t4 (a int default 0, b int primary key) engine=innodb;
+ insert into t4 values (0, 17);
+ reset master;
+
+# execute
+ --error ER_DUP_ENTRY
+ load data infile '../std_data_ln/rpl_loaddata.dat' into table t4 (a, @b) set b= @b + bug27417(2);
+# check
+ select * from t4;
+ select count(*) from t1 /* must be 2 */;
+ source include/show_binlog_events.inc; # must be events of the query
+
+#
+# bug#23333 cleanup
+#
+
+
+drop trigger trg_del;
+drop table t1,t2,t3,t4;
+drop function bug27417;
+
+
--echo end of tests
diff --git a/mysql-test/suite/rpl/r/rpl_packet.result b/mysql-test/suite/rpl/r/rpl_packet.result
index 981c234d380..dd56eb0471c 100644
--- a/mysql-test/suite/rpl/r/rpl_packet.result
+++ b/mysql-test/suite/rpl/r/rpl_packet.result
@@ -27,6 +27,42 @@ STOP SLAVE;
START SLAVE;
CREATE TABLe `t1` (`f1` LONGTEXT) ENGINE=MyISAM;
INSERT INTO `t1`(`f1`) VALUES ('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa2048');
-SHOW STATUS LIKE 'Slave_running';
-Variable_name Value
-Slave_running OFF
+show slave status;
+Slave_IO_State #
+Master_Host 127.0.0.1
+Master_User root
+Master_Port MASTER_MYPORT
+Connect_Retry 1
+Master_Log_File master-bin.000001
+Read_Master_Log_Pos #
+Relay_Log_File #
+Relay_Log_Pos #
+Relay_Master_Log_File master-bin.000001
+Slave_IO_Running No
+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 0
+Last_Error
+Skip_Counter 0
+Exec_Master_Log_Pos #
+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
+Last_IO_Errno 0
+Last_IO_Error
+Last_SQL_Errno 0
+Last_SQL_Error
diff --git a/mysql-test/suite/rpl/t/rpl_packet.test b/mysql-test/suite/rpl/t/rpl_packet.test
index c3987f7ee15..0e17ae3144c 100644
--- a/mysql-test/suite/rpl/t/rpl_packet.test
+++ b/mysql-test/suite/rpl/t/rpl_packet.test
@@ -66,15 +66,11 @@ CREATE TABLe `t1` (`f1` LONGTEXT) ENGINE=MyISAM;
INSERT INTO `t1`(`f1`) VALUES ('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa2048');
# The slave I/O thread must stop after trying to read the above event
-connection slave;
---source include/wait_for_slave_io_to_stop.inc
-SHOW STATUS LIKE 'Slave_running';
-
-# cleanup
-#connection master;
-#drop table t1;
-#connection slave;
-#drop table t1;
-
+connection slave;
+--source include/wait_for_slave_io_to_stop.inc
+--replace_result $MASTER_MYPORT MASTER_MYPORT
+# import is only the 11th column Slave_IO_Running
+--replace_column 1 # 7 # 8 # 9 # 12 # 22 # 23 # 33 #
+query_vertical show slave status;
# End of tests
diff --git a/sql/field.cc b/sql/field.cc
index fa93454c757..052f1cdf6d2 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -6732,6 +6732,7 @@ const uint Field_varstring::MAX_SIZE= UINT_MAX16;
int Field_varstring::do_save_field_metadata(uchar *metadata_ptr)
{
char *ptr= (char *)metadata_ptr;
+ DBUG_ASSERT(field_length <= 65535);
int2store(ptr, field_length);
return 2;
}
diff --git a/sql/log_event.cc b/sql/log_event.cc
index 44898ca8639..f03d4a25c38 100644
--- a/sql/log_event.cc
+++ b/sql/log_event.cc
@@ -6469,6 +6469,16 @@ void Rows_log_event::print_helper(FILE *file,
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.
+ Additionally, values saved for field metadata on the master are saved as a
+ string of bytes (uchar) in the binlog. A field may require 1 or more bytes
+ to store the information. In cases where values require multiple bytes
+ (e.g. values > 255), the endian-safe methods are used to properly encode
+ the values on the master and decode them on the slave. When the field
+ metadata values are captured on the slave, they are stored in an array of
+ type uint16. This allows the least number of casts to prevent casting bugs
+ when the field metadata is used in comparisons of field attributes. When
+ the field metadata is used for calculating addresses in pointer math, the
+ type used is uint32.
*/
/**
diff --git a/sql/rpl_utility.cc b/sql/rpl_utility.cc
index d1ce5bf3b7b..b3ca26d4c2c 100644
--- a/sql/rpl_utility.cc
+++ b/sql/rpl_utility.cc
@@ -31,31 +31,34 @@ uint32 table_def::calc_field_size(uint col, uchar *master_data) const
switch (type(col)) {
case MYSQL_TYPE_NEWDECIMAL:
length= my_decimal_get_binary_size(m_field_metadata[col] >> 8,
- m_field_metadata[col] - ((m_field_metadata[col] >> 8) << 8));
+ m_field_metadata[col] & 0xff);
break;
case MYSQL_TYPE_DECIMAL:
case MYSQL_TYPE_FLOAT:
case MYSQL_TYPE_DOUBLE:
length= m_field_metadata[col];
break;
+ /*
+ The cases for SET and ENUM are include for completeness, however
+ both are mapped to type MYSQL_TYPE_STRING and their real types
+ are encoded in the field metadata.
+ */
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)))
+ uchar type= m_field_metadata[col] >> 8U;
+ if ((type == MYSQL_TYPE_SET) || (type == MYSQL_TYPE_ENUM))
length= m_field_metadata[col] & 0x00ff;
else
{
- length= m_field_metadata[col] & 0x00ff;
- DBUG_ASSERT(length > 0);
- if (length > 255)
- {
- DBUG_ASSERT(uint2korr(master_data) > 0);
- length= uint2korr(master_data) + 2;
- }
- else
- length= (uint) *master_data + 1;
+ /*
+ We are reading the actual size from the master_data record
+ because this field has the actual lengh stored in the first
+ byte.
+ */
+ length= (uint) *master_data + 1;
+ DBUG_ASSERT(length != 0);
}
break;
}
@@ -95,6 +98,13 @@ uint32 table_def::calc_field_size(uint col, uchar *master_data) const
break;
case MYSQL_TYPE_BIT:
{
+ /*
+ Decode the size of the bit field from the master.
+ from_len is the length in bytes from the master
+ from_bit_len is the number of extra bits stored in the master record
+ If from_bit_len is not 0, add 1 to the length to account for accurate
+ number of bytes needed.
+ */
uint from_len= (m_field_metadata[col] >> 8U) & 0x00ff;
uint from_bit_len= m_field_metadata[col] & 0x00ff;
DBUG_ASSERT(from_bit_len <= 7);
@@ -136,7 +146,7 @@ uint32 table_def::calc_field_size(uint col, uchar *master_data) const
length= *master_data;
break;
case 2:
- length= sint2korr(master_data);
+ length= uint2korr(master_data);
break;
case 3:
length= uint3korr(master_data);
diff --git a/sql/rpl_utility.h b/sql/rpl_utility.h
index 26edbdd1405..375715c7858 100644
--- a/sql/rpl_utility.h
+++ b/sql/rpl_utility.h
@@ -99,7 +99,7 @@ public:
/*
These types store a single byte.
*/
- m_field_metadata[i]= (uchar)field_metadata[index];
+ m_field_metadata[i]= field_metadata[index];
index++;
break;
}
@@ -107,14 +107,14 @@ public:
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
+ uint16 x= field_metadata[index++] << 8U; // real_type
+ x+= field_metadata[index++]; // pack or field length
m_field_metadata[i]= x;
break;
}
case MYSQL_TYPE_BIT:
{
- short int x= field_metadata[index++];
+ uint16 x= field_metadata[index++];
x = x + (field_metadata[index++] << 8U);
m_field_metadata[i]= x;
break;
@@ -125,14 +125,14 @@ public:
These types store two bytes.
*/
char *ptr= (char *)&field_metadata[index];
- m_field_metadata[i]= sint2korr(ptr);
+ m_field_metadata[i]= uint2korr(ptr);
index= index + 2;
break;
}
case MYSQL_TYPE_NEWDECIMAL:
{
- short int x= field_metadata[index++] << 8U; // precision
- x = x + field_metadata[index++]; // decimals
+ uint16 x= field_metadata[index++] << 8U; // precision
+ x+= field_metadata[index++]; // decimals
m_field_metadata[i]= x;
break;
}
diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc
index 303918f42a2..d5e88ab8761 100644
--- a/sql/sql_delete.cc
+++ b/sql/sql_delete.cc
@@ -345,7 +345,7 @@ cleanup:
thd->transaction.stmt.modified_non_trans_table= TRUE;
/* See similar binlogging code in sql_update.cc, for comments */
- if ((error < 0) || (deleted && !transactional_table))
+ if ((error < 0) || thd->transaction.stmt.modified_non_trans_table)
{
if (mysql_bin_log.is_open())
{
@@ -862,7 +862,8 @@ bool multi_delete::send_eof()
{
query_cache_invalidate3(thd, delete_tables, 1);
}
- if ((local_error == 0) || (deleted && normal_tables))
+ DBUG_ASSERT(!normal_tables || !deleted || thd->transaction.stmt.modified_non_trans_table);
+ if ((local_error == 0) || thd->transaction.stmt.modified_non_trans_table)
{
if (mysql_bin_log.is_open())
{
@@ -879,7 +880,6 @@ bool multi_delete::send_eof()
if (thd->transaction.stmt.modified_non_trans_table)
thd->transaction.all.modified_non_trans_table= TRUE;
}
- DBUG_ASSERT(!normal_tables || !deleted || thd->transaction.stmt.modified_non_trans_table);
/* Commit or rollback the current SQL statement */
if (transactional_tables)
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index ebbf4cafb19..41e4fe4957e 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -839,59 +839,58 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
}
transactional_table= table->file->has_transactions();
- if ((changed= (info.copied || info.deleted || info.updated)) ||
- was_insert_delayed)
+ if ((changed= (info.copied || info.deleted || info.updated)))
{
/*
Invalidate the table in the query cache if something changed.
For the transactional algorithm to work the invalidation must be
before binlog writing and ha_autocommit_or_rollback
*/
- if (changed)
- query_cache_invalidate3(thd, table_list, 1);
- if (error <= 0 || !transactional_table)
+ query_cache_invalidate3(thd, table_list, 1);
+ }
+ if (changed && error <= 0 || thd->transaction.stmt.modified_non_trans_table
+ || was_insert_delayed)
+ {
+ if (mysql_bin_log.is_open())
{
- if (mysql_bin_log.is_open())
+ if (error <= 0)
{
- if (error <= 0)
- {
- /*
- [Guilhem wrote] Temporary errors may have filled
- thd->net.last_error/errno. For example if there has
- been a disk full error when writing the row, and it was
- MyISAM, then thd->net.last_error/errno will be set to
- "disk full"... and the my_pwrite() will wait until free
- space appears, and so when it finishes then the
- write_row() was entirely successful
- */
- /* todo: consider removing */
- thd->clear_error();
- }
- /* bug#22725:
-
- A query which per-row-loop can not be interrupted with
- KILLED, like INSERT, and that does not invoke stored
- routines can be binlogged with neglecting the KILLED error.
-
- If there was no error (error == zero) until after the end of
- inserting loop the KILLED flag that appeared later can be
- disregarded since previously possible invocation of stored
- routines did not result in any error due to the KILLED. In
- such case the flag is ignored for constructing binlog event.
- */
- DBUG_ASSERT(thd->killed != THD::KILL_BAD_DATA || error > 0);
- if (thd->binlog_query(THD::ROW_QUERY_TYPE,
- thd->query, thd->query_length,
- transactional_table, FALSE,
- (error>0) ? thd->killed : THD::NOT_KILLED) &&
- transactional_table)
- {
- error=1;
- }
- }
- if (thd->transaction.stmt.modified_non_trans_table)
- thd->transaction.all.modified_non_trans_table= TRUE;
+ /*
+ [Guilhem wrote] Temporary errors may have filled
+ thd->net.last_error/errno. For example if there has
+ been a disk full error when writing the row, and it was
+ MyISAM, then thd->net.last_error/errno will be set to
+ "disk full"... and the my_pwrite() will wait until free
+ space appears, and so when it finishes then the
+ write_row() was entirely successful
+ */
+ /* todo: consider removing */
+ thd->clear_error();
+ }
+ /* bug#22725:
+
+ A query which per-row-loop can not be interrupted with
+ KILLED, like INSERT, and that does not invoke stored
+ routines can be binlogged with neglecting the KILLED error.
+
+ If there was no error (error == zero) until after the end of
+ inserting loop the KILLED flag that appeared later can be
+ disregarded since previously possible invocation of stored
+ routines did not result in any error due to the KILLED. In
+ such case the flag is ignored for constructing binlog event.
+ */
+ DBUG_ASSERT(thd->killed != THD::KILL_BAD_DATA || error > 0);
+ if (thd->binlog_query(THD::ROW_QUERY_TYPE,
+ thd->query, thd->query_length,
+ transactional_table, FALSE,
+ (error>0) ? thd->killed : THD::NOT_KILLED) &&
+ transactional_table)
+ {
+ error=1;
+ }
}
+ if (thd->transaction.stmt.modified_non_trans_table)
+ thd->transaction.all.modified_non_trans_table= TRUE;
}
DBUG_ASSERT(transactional_table || !changed ||
thd->transaction.stmt.modified_non_trans_table);
@@ -3164,6 +3163,7 @@ void select_insert::abort() {
*/
if (table)
{
+ bool changed, transactional_table;
/*
If we are not in prelocked mode, we end the bulk insert started
before.
@@ -3185,20 +3185,20 @@ void select_insert::abort() {
If table creation failed, the number of rows modified will also be
zero, so no check for that is made.
*/
- if (info.copied || info.deleted || info.updated)
+ changed= (info.copied || info.deleted || info.updated);
+ transactional_table= table->file->has_transactions();
+ if (thd->transaction.stmt.modified_non_trans_table)
{
- DBUG_ASSERT(table != NULL);
- if (!table->file->has_transactions())
- {
if (mysql_bin_log.is_open())
thd->binlog_query(THD::ROW_QUERY_TYPE, thd->query, thd->query_length,
- table->file->has_transactions(), FALSE);
- if (!thd->current_stmt_binlog_row_based && !table->s->tmp_table &&
- !can_rollback_data())
+ transactional_table, FALSE);
+ if (!thd->current_stmt_binlog_row_based && !can_rollback_data())
thd->transaction.all.modified_non_trans_table= TRUE;
- query_cache_invalidate3(thd, table, 1);
- }
+ if (changed)
+ query_cache_invalidate3(thd, table, 1);
}
+ DBUG_ASSERT(transactional_table || !changed ||
+ thd->transaction.stmt.modified_non_trans_table);
table->file->ha_release_auto_increment();
}
diff --git a/sql/sql_load.cc b/sql/sql_load.cc
index 8bbe1e413b3..23547349a37 100644
--- a/sql/sql_load.cc
+++ b/sql/sql_load.cc
@@ -445,7 +445,7 @@ bool mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
/* If the file was not empty, wrote_create_file is true */
if (lf_info.wrote_create_file)
{
- if ((info.copied || info.deleted) && !transactional_table)
+ if (thd->transaction.stmt.modified_non_trans_table)
write_execute_load_query_log_event(thd, handle_duplicates,
ignore, transactional_table);
else
diff --git a/sql/sql_update.cc b/sql/sql_update.cc
index d4df805d006..2a469220fa7 100644
--- a/sql/sql_update.cc
+++ b/sql/sql_update.cc
@@ -797,7 +797,7 @@ int mysql_update(THD *thd,
Sometimes we want to binlog even if we updated no rows, in case user used
it to be sure master and slave are in same state.
*/
- if ((error < 0) || (updated && !transactional_table))
+ if ((error < 0) || thd->transaction.stmt.modified_non_trans_table)
{
if (mysql_bin_log.is_open())
{