Commit 12443de1 authored by unknown's avatar unknown
Browse files

WL#3259 (RBR with more columns on slave than on master):

Extended replication to allow extra columns added last on slave
as compared with table on master.


mysql-test/extra/rpl_tests/rpl_row_tabledefs.test:
  Testing that replication can handle extra extra columns on slave.
mysql-test/r/rpl_row_tabledefs.result:
  Result file change
sql/Makefile.am:
  Adding new files.
sql/field.cc:
  Implementing missing Field_bit::set_default()
sql/field.h:
  Implementing missing Field_bit::set_default()
sql/log_event.cc:
  Extending unpack_row() and replace_record() to handle the case when there are more columns
  on the slave than on the master. Especially handle BIT columns correctly.
  Using newly introduced table_def class to perform comparison.
sql/log_event.h:
  Adding field to table_map_log_event. Changing prototype for do_prepare_row().
sql/mysql_priv.h:
  Adding include guards
mysql-test/t/rpl_row_tabledefs.test:
  New BitKeeper file ``mysql-test/t/rpl_row_tabledefs.test''
sql/rpl_utility.cc:
  New BitKeeper file ``sql/rpl_utility.cc''
sql/rpl_utility.h:
  New BitKeeper file ``sql/rpl_utility.h''
parent cbdc730a
Loading
Loading
Loading
Loading
+48 −27
Original line number Diff line number Diff line
@@ -3,11 +3,16 @@

# Consider making these part of the basic RBR tests.

-- source include/have_binlog_format_row.inc
-- source include/master-slave.inc
connection slave;
STOP SLAVE;
SET GLOBAL SQL_MODE='STRICT_ALL_TABLES';
START SLAVE;

connection master;
eval CREATE TABLE t1 (a INT PRIMARY KEY, b INT) ENGINE=$engine_type;
eval CREATE TABLE t1_int (a INT PRIMARY KEY, b INT) ENGINE=$engine_type;
eval CREATE TABLE t1_bit (a INT PRIMARY KEY, b INT) ENGINE=$engine_type;
eval CREATE TABLE t1_char (a INT PRIMARY KEY, b INT) ENGINE=$engine_type;
eval CREATE TABLE t1_nodef (a INT PRIMARY KEY, b INT) ENGINE=$engine_type;
eval CREATE TABLE t2 (a INT PRIMARY KEY, b INT) ENGINE=$engine_type;
eval CREATE TABLE t3 (a INT PRIMARY KEY, b INT) ENGINE=$engine_type;
eval CREATE TABLE t4 (a INT) ENGINE=$engine_type;
@@ -15,15 +20,21 @@ eval CREATE TABLE t5 (a INT, b INT, c INT) ENGINE=$engine_type;
eval CREATE TABLE t6 (a INT, b INT, c INT) ENGINE=$engine_type;

# Table used to detect that slave is running
eval CREATE TABLE t9 (a INT PRIMARY KEY) ENGINE=$engine_type;
eval CREATE TABLE t9 (a INT) ENGINE=$engine_type;

sync_slave_with_master;
# On the slave, we add one column last in table 't1',
ALTER TABLE t1 ADD x INT DEFAULT 42;
# ... add one column in the middle of table 't2', and
ALTER TABLE t2 ADD x INT DEFAULT 42 AFTER a;
# ... add one column first in table 't3'.
ALTER TABLE t3 ADD x INT DEFAULT 42 FIRST;

# On the slave, we add one INT column last in table 't1_int',
ALTER TABLE t1_int ADD x INT DEFAULT 42;
# ... and add one BIT column last in table 't1_bit',
ALTER TABLE t1_bit ADD x BIT(3) DEFAULT b'011';
# ... and add one CHAR column last in table 't1_char',
ALTER TABLE t1_char ADD x CHAR(20) DEFAULT 'Just a test';
# ... and add one non-nullable INT column last in table 't1_text'
#     with no default,
ALTER TABLE t1_nodef ADD x INT NOT NULL;
# ... and remove the last column in t2
ALTER TABLE t2 DROP b;
# ... change the type of the single column in table 't4'
ALTER TABLE t4 MODIFY a FLOAT;
# ... change the type of the middle column of table 't5'
@@ -31,28 +42,37 @@ ALTER TABLE t5 MODIFY b FLOAT;
# ... change the type of the last column of table 't6'
ALTER TABLE t6 MODIFY c FLOAT;

# Each of these should generate an error and stop the slave
# Insert some values for tables on slave side. These should not be
# modified when the row from the master is applied.
INSERT INTO t1_int  VALUES (2,4,4711);
INSERT INTO t1_char VALUES (2,4,'Foo is a bar');
INSERT INTO t1_bit  VALUES (2,4,b'101');

--echo **** On Master ****
connection master;
INSERT INTO t9 VALUES (1);
INSERT INTO t1_int VALUES (1,2);
INSERT INTO t1_int VALUES (2,5);
INSERT INTO t1_bit VALUES (1,2);
INSERT INTO t1_bit VALUES (2,5);
INSERT INTO t1_char VALUES (1,2);
INSERT INTO t1_char VALUES (2,5);
SELECT * FROM t1_int;
SELECT * FROM t1_bit;
SELECT * FROM t1_char;
--echo **** On Slave ****
sync_slave_with_master;
# Now slave is guaranteed to be running
connection master;
INSERT INTO t1 VALUES (1,2);
connection slave;
wait_for_slave_to_stop;
--replace_result $MASTER_MYPORT MASTER_PORT
--replace_column 1 # 8 # 9 # 23 # 33 #
--vertical_results
SHOW SLAVE STATUS;
SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2;
START SLAVE;
SELECT a,b,x FROM t1_int;
SELECT a,b,HEX(x) FROM t1_bit;
SELECT a,b,x FROM t1_char;

# Each of these should generate an error and stop the slave

connection master;
INSERT INTO t9 VALUES (2);
sync_slave_with_master;
# Now slave is guaranteed to be running
connection master;
INSERT INTO t2 VALUES (2,4);
INSERT INTO t1_nodef VALUES (1,2);
connection slave;
wait_for_slave_to_stop;
--replace_result $MASTER_MYPORT MASTER_PORT
@@ -63,11 +83,11 @@ SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2;
START SLAVE;

connection master;
INSERT INTO t9 VALUES (3);
INSERT INTO t9 VALUES (2);
sync_slave_with_master;
# Now slave is guaranteed to be running
connection master;
INSERT INTO t3 VALUES (3,6);
INSERT INTO t2 VALUES (2,4);
connection slave;
wait_for_slave_to_stop;
--replace_result $MASTER_MYPORT MASTER_PORT
@@ -124,6 +144,7 @@ START SLAVE;

connection master;
--disable_warnings
DROP TABLE IF EXISTS t1,t2,t3,t4,t5,t6,t9;
DROP TABLE IF EXISTS t1_int,t1_bit,t1_char,t1_nodef;
DROP TABLE IF EXISTS t2,t3,t4,t5,t6,t9;
--enable_warnings
sync_slave_with_master;
+74 −68
Original line number Diff line number Diff line
@@ -4,21 +4,64 @@ reset master;
reset slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
start slave;
CREATE TABLE t1 (a INT PRIMARY KEY, b INT) ENGINE=myisam;
CREATE TABLE t2 (a INT PRIMARY KEY, b INT) ENGINE=myisam;
CREATE TABLE t3 (a INT PRIMARY KEY, b INT) ENGINE=myisam;
CREATE TABLE t4 (a INT) ENGINE=myisam;
CREATE TABLE t5 (a INT, b INT, c INT) ENGINE=myisam;
CREATE TABLE t6 (a INT, b INT, c INT) ENGINE=myisam;
CREATE TABLE t9 (a INT PRIMARY KEY) ENGINE=myisam;
ALTER TABLE t1 ADD x INT DEFAULT 42;
ALTER TABLE t2 ADD x INT DEFAULT 42 AFTER a;
ALTER TABLE t3 ADD x INT DEFAULT 42 FIRST;
STOP SLAVE;
SET GLOBAL SQL_MODE='STRICT_ALL_TABLES';
START SLAVE;
CREATE TABLE t1_int (a INT PRIMARY KEY, b INT) ENGINE='MyISAM';
CREATE TABLE t1_bit (a INT PRIMARY KEY, b INT) ENGINE='MyISAM';
CREATE TABLE t1_char (a INT PRIMARY KEY, b INT) ENGINE='MyISAM';
CREATE TABLE t1_nodef (a INT PRIMARY KEY, b INT) ENGINE='MyISAM';
CREATE TABLE t2 (a INT PRIMARY KEY, b INT) ENGINE='MyISAM';
CREATE TABLE t3 (a INT PRIMARY KEY, b INT) ENGINE='MyISAM';
CREATE TABLE t4 (a INT) ENGINE='MyISAM';
CREATE TABLE t5 (a INT, b INT, c INT) ENGINE='MyISAM';
CREATE TABLE t6 (a INT, b INT, c INT) ENGINE='MyISAM';
CREATE TABLE t9 (a INT) ENGINE='MyISAM';
ALTER TABLE t1_int ADD x INT DEFAULT 42;
ALTER TABLE t1_bit ADD x BIT(3) DEFAULT b'011';
ALTER TABLE t1_char ADD x CHAR(20) DEFAULT 'Just a test';
ALTER TABLE t1_nodef ADD x INT NOT NULL;
ALTER TABLE t2 DROP b;
ALTER TABLE t4 MODIFY a FLOAT;
ALTER TABLE t5 MODIFY b FLOAT;
ALTER TABLE t6 MODIFY c FLOAT;
INSERT INTO t9 VALUES (1);
INSERT INTO t1 VALUES (1,2);
INSERT INTO t1_int  VALUES (2,4,4711);
INSERT INTO t1_char VALUES (2,4,'Foo is a bar');
INSERT INTO t1_bit  VALUES (2,4,b'101');
**** On Master ****
INSERT INTO t1_int VALUES (1,2);
INSERT INTO t1_int VALUES (2,5);
INSERT INTO t1_bit VALUES (1,2);
INSERT INTO t1_bit VALUES (2,5);
INSERT INTO t1_char VALUES (1,2);
INSERT INTO t1_char VALUES (2,5);
SELECT * FROM t1_int;
a	b
1	2
2	5
SELECT * FROM t1_bit;
a	b
1	2
2	5
SELECT * FROM t1_char;
a	b
1	2
2	5
**** On Slave ****
SELECT a,b,x FROM t1_int;
a	b	x
2	5	4711
1	2	42
SELECT a,b,HEX(x) FROM t1_bit;
a	b	HEX(x)
2	5	5
1	2	3
SELECT a,b,x FROM t1_char;
a	b	x
2	5	Foo is a bar
1	2	Just a test
INSERT INTO t9 VALUES (2);
INSERT INTO t1_nodef VALUES (1,2);
SHOW SLAVE STATUS;
Slave_IO_State	#
Master_Host	127.0.0.1
@@ -26,7 +69,7 @@ Master_User root
Master_Port	MASTER_PORT
Connect_Retry	1
Master_Log_File	master-bin.000001
Read_Master_Log_Pos	1042
Read_Master_Log_Pos	1934
Relay_Log_File	#
Relay_Log_Pos	#
Relay_Master_Log_File	master-bin.000001
@@ -38,10 +81,10 @@ Replicate_Do_Table
Replicate_Ignore_Table	
Replicate_Wild_Do_Table	
Replicate_Wild_Ignore_Table	
Last_Errno	1454
Last_Error	Table width mismatch - received 2 columns, test.t1 has 3 columns
Last_Errno	1364
Last_Error	Error in Write_rows event: error during transaction execution on table test.t1_nodef
Skip_Counter	0
Exec_Master_Log_Pos	968
Exec_Master_Log_Pos	1850
Relay_Log_Space	#
Until_Condition	None
Until_Log_File	
@@ -64,45 +107,7 @@ Master_User root
Master_Port	MASTER_PORT
Connect_Retry	1
Master_Log_File	master-bin.000001
Read_Master_Log_Pos	1185
Relay_Log_File	#
Relay_Log_Pos	#
Relay_Master_Log_File	master-bin.000001
Slave_IO_Running	Yes
Slave_SQL_Running	No
Replicate_Do_DB	
Replicate_Ignore_DB	
Replicate_Do_Table	
Replicate_Ignore_Table	
Replicate_Wild_Do_Table	
Replicate_Wild_Ignore_Table	
Last_Errno	1454
Last_Error	Table width mismatch - received 2 columns, test.t2 has 3 columns
Skip_Counter	0
Exec_Master_Log_Pos	1111
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	#
SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2;
START SLAVE;
INSERT INTO t9 VALUES (3);
INSERT INTO t3 VALUES (3,6);
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.000001
Read_Master_Log_Pos	1328
Read_Master_Log_Pos	2085
Relay_Log_File	#
Relay_Log_Pos	#
Relay_Master_Log_File	master-bin.000001
@@ -114,10 +119,10 @@ Replicate_Do_Table
Replicate_Ignore_Table	
Replicate_Wild_Do_Table	
Replicate_Wild_Ignore_Table	
Last_Errno	1454
Last_Error	Table width mismatch - received 2 columns, test.t3 has 3 columns
Last_Errno	1514
Last_Error	Table width mismatch - received 2 columns, test.t2 has 1 columns
Skip_Counter	0
Exec_Master_Log_Pos	1254
Exec_Master_Log_Pos	2007
Relay_Log_Space	#
Until_Condition	None
Until_Log_File	
@@ -140,7 +145,7 @@ Master_User root
Master_Port	MASTER_PORT
Connect_Retry	1
Master_Log_File	master-bin.000001
Read_Master_Log_Pos	1466
Read_Master_Log_Pos	2231
Relay_Log_File	#
Relay_Log_Pos	#
Relay_Master_Log_File	master-bin.000001
@@ -152,10 +157,10 @@ Replicate_Do_Table
Replicate_Ignore_Table	
Replicate_Wild_Do_Table	
Replicate_Wild_Ignore_Table	
Last_Errno	1454
Last_Errno	1514
Last_Error	Column 0 type mismatch - received type 3, test.t4 has type 4
Skip_Counter	0
Exec_Master_Log_Pos	1397
Exec_Master_Log_Pos	2158
Relay_Log_Space	#
Until_Condition	None
Until_Log_File	
@@ -178,7 +183,7 @@ Master_User root
Master_Port	MASTER_PORT
Connect_Retry	1
Master_Log_File	master-bin.000001
Read_Master_Log_Pos	1614
Read_Master_Log_Pos	2387
Relay_Log_File	#
Relay_Log_Pos	#
Relay_Master_Log_File	master-bin.000001
@@ -190,10 +195,10 @@ Replicate_Do_Table
Replicate_Ignore_Table	
Replicate_Wild_Do_Table	
Replicate_Wild_Ignore_Table	
Last_Errno	1454
Last_Errno	1514
Last_Error	Column 1 type mismatch - received type 3, test.t5 has type 4
Skip_Counter	0
Exec_Master_Log_Pos	1535
Exec_Master_Log_Pos	2304
Relay_Log_Space	#
Until_Condition	None
Until_Log_File	
@@ -216,7 +221,7 @@ Master_User root
Master_Port	MASTER_PORT
Connect_Retry	1
Master_Log_File	master-bin.000001
Read_Master_Log_Pos	1762
Read_Master_Log_Pos	2543
Relay_Log_File	#
Relay_Log_Pos	#
Relay_Master_Log_File	master-bin.000001
@@ -228,10 +233,10 @@ Replicate_Do_Table
Replicate_Ignore_Table	
Replicate_Wild_Do_Table	
Replicate_Wild_Ignore_Table	
Last_Errno	1454
Last_Errno	1514
Last_Error	Column 2 type mismatch - received type 3, test.t6 has type 4
Skip_Counter	0
Exec_Master_Log_Pos	1683
Exec_Master_Log_Pos	2460
Relay_Log_Space	#
Until_Condition	None
Until_Log_File	
@@ -245,4 +250,5 @@ Master_SSL_Key
Seconds_Behind_Master	#
SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2;
START SLAVE;
DROP TABLE IF EXISTS t1,t2,t3,t4,t5,t6,t9;
DROP TABLE IF EXISTS t1_int,t1_bit,t1_char,t1_nodef;
DROP TABLE IF EXISTS t2,t3,t4,t5,t6,t9;
+8 −0
Original line number Diff line number Diff line

-- source include/have_binlog_format_row.inc
-- source include/master-slave.inc

let $engine_type = 'MyISAM';
-- source extra/rpl_tests/rpl_row_tabledefs.test

+2 −2
Original line number Diff line number Diff line
@@ -53,7 +53,7 @@ noinst_HEADERS = item.h item_func.h item_sum.h item_cmpfunc.h \
			sql_manager.h sql_map.h sql_string.h unireg.h \
			sql_error.h field.h handler.h mysqld_suffix.h \
			ha_heap.h ha_myisam.h ha_myisammrg.h ha_partition.h \
			opt_range.h protocol.h rpl_tblmap.h \
			opt_range.h protocol.h rpl_tblmap.h rpl_utility.h \
			log.h sql_show.h rpl_rli.h \
			sql_select.h structs.h table.h sql_udf.h hash_filo.h\
			lex.h lex_symbol.h sql_acl.h sql_crypt.h  \
@@ -91,7 +91,7 @@ mysqld_SOURCES = sql_lex.cc sql_handler.cc sql_partition.cc \
			sql_load.cc mf_iocache.cc field_conv.cc sql_show.cc \
			sql_udf.cc sql_analyse.cc sql_analyse.h sql_cache.cc \
			slave.cc sql_repl.cc rpl_filter.cc rpl_tblmap.cc \
			rpl_injector.cc \
			rpl_utility.cc rpl_injector.cc \
                        sql_union.cc sql_derived.cc \
			client.c sql_client.cc mini_client_errors.c pack.c\
			stacktrace.c repl_failsafe.h repl_failsafe.cc \
+8 −0
Original line number Diff line number Diff line
@@ -8259,6 +8259,14 @@ const char *Field_bit::unpack(char *to, const char *from)
}


void Field_bit::set_default()
{
  my_ptrdiff_t const offset= table->s->default_values - table->record[0];
  uchar bits= get_rec_bits(bit_ptr + offset, bit_ofs, bit_len);
  set_rec_bits(bits, bit_ptr, bit_ofs, bit_len);
  Field::set_default();
}

/*
  Bit field support for non-MyISAM tables.
*/
Loading