List:Commits« Previous MessageNext Message »
From:Chuck Bell Date:August 10 2007 6:54pm
Subject:RE: bk commit into 5.1 tree (cbell:1.2548) BUG#22086
View as plain text  
Hi Mats,

Thanks again for a very insightful and well done review. Your changes kick
my work up a notch (or two!). Here's the latest patch. Please ignore
previous patches -- mostly false alarms and attempts to fix some weirdness
moving code among my machines.

http://lists.mysql.com/commits/32370

See interdelinia below.

Chuck 

> 1. Avoid casts. Casts are evil. Casts hide errors. Implicit 
> conversions 
> are your friend. Trust implicit conversions. If you *really* 
> have to use 
> a cast, make sure to inscribe the proper runes to avert Loki (i.e., 
> write some comments and/or assertions).

Aye, evil casts banished to oblivion.

> 2. Just using the pack length means that there are cases where 
> replication is accepted even though it should not. For 
> example, the pack 
> length for both DECIMAL(27,9) and DECIMAL(27,18) are 4*3 = 12 
> bytes, but 
> since the fractional parts of the decimal numbers are 
> different, this is 
> not possible. For example, it is not possible to store 
> 12.3456789 into a 
> DECIMAL(9,2) without losing precision.
> 
> What you actually want is a comparison function for each field (say: 
> compare_metadata()), that compares the field with some 
> arbitrary piece 
> of metadata (presumably gotten from the master) and decides on an 
> ordering (or compares two pieces of metadata with each other).

For most fields, it is sufficient to use the pack_length(), but for decimal
and bit fields you are correct. They need additional checks to ensure
compatibility. These classes have overridden the compatible method with
specialized implementations. For others that do not use pack_length(), such
as bit, the implementation of row_pack_length() returns the appropriate
value that matches what is stored in the metadata and are of a single value.

> 3. Instead of issuing two virtual calls, one to save_field_metadata() 
> and one to field_metadata_size(), it is better to just pass *one* 
> pointer to save_field_metadata(), let it write what it wants 
> to write, 
> and then return the number of bytes actually written. There 
> are several 
> reasons for this:
> 
>     * The return value for save_field_metadata() is ignored, so the
>       "error number" that I suppose that you wanted to 
> return, is never
>       used. It's better to use that return value for a purpose.

Agreed. Requires some minor refactoring in log_event.cc to accomplish, but
it's better for it. ;)

>     * You are always returning 0 from save_field_metadata(), 
> so there's
>       no point in returning a value that is never used and 
> never will be
>       anything but 0.

agreed

>     * There is no reason to pass two parameters since I cannot see any
>       conceivable situation where it should be possible to 
> pass anything
>       but ptr and ptr+1 as arguments to the current version of the
>       function. Indeed, even the parameter names suggest this 
> is the case.

Ingenious!

>     * In the case that the second argument is not used, you are making
>       unnecessary computations just to throw it away, and it can be
>       avoided by this simple change.

Agreed. Code changed.

> 4. Introduce two versions of the save_field_metadata function: one 
> virtual but private function (say: do_save_field_metadata()) and one 
> non-virtual public function (say: save_field_metadata()). 
> This separates 
> the public interface directed at class users from the internal 
> inheritance interface directed as subclasses. At this point, 
> the public 
> non-virtual function save_field_metadata() just needs to call the 
> virtual private function, but it makes it possible to, for example, 
> introduce code to handle caching of the metadata that will be 
> independent of the inheritance interface: all without renaming any 
> functions at all.

Rrrrright... Ok, had to think about this one. I see the wisdom now. Done.

> 
> 5. Add tests to test for the cases that I give as potential problems 
> below, i.e., replicating BIT(12) to BIT(11) (which should fail) and 
> replicating DECIMAL(27,18) to DECIMAL(27,9).

Tests added.


> 
> Just my few cents,
> Mats Kindahl
> 
> cbell@stripped wrote:
> > Below is the list of changes that have just been committed 
> into a local
> > 5.1 repository of cbell. When cbell does a push these changes will
> > be propagated to the main repository and, within 24 hours after the
> > push, to the public repository.
> > For information on how to access the public repository
> > see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html
> >
> > ChangeSet@stripped, 2007-08-09 22:08:16-04:00, 
> cbell@mysql_cab_desk. +11 -0
> >   BUG#22086 : Extra Slave Col: Char(5) on slave and 
> Char(10) on master cause mysqld crash 
> >   
> >   This patch adds functionality to row-based replication to 
> ensure the
> >   slave's column sizes are >= to that of the master.
> >   
> >   It also includes some refactoring for the code from WL#3228.
> >
> >   mysql-test/extra/rpl_tests/rpl_extraSlave_Col.test@stripped, 
> 2007-08-09 22:08:05-04:00, cbell@mysql_cab_desk. +41 -32
> >     BUG#22086 : Extra Slave Col: Char(5) on slave and 
> Char(10) on master cause mysqld crash 
> >     
> >     Removed commented out portion of test referenced in bug 
> report. This
> >     test supports the original request of the bug report.
> >
> >   mysql-test/include/test_fieldsize.inc@stripped, 2007-08-09 
> 22:08:10-04:00, cbell@mysql_cab_desk. +40 -0
> >     BUG#22086 : Extra Slave Col: Char(5) on slave and 
> Char(10) on master cause mysqld crash 
> >     
> >     Sub unit file to test each variable type that relies on field
> >     metadata from the master.
> >
> >   mysql-test/include/test_fieldsize.inc@stripped, 2007-08-09 
> 22:08:10-04:00, cbell@mysql_cab_desk. +0 -0
> >
> >   mysql-test/suite/rpl/r/rpl_extraCol_innodb.result@stripped, 
> 2007-08-09 22:08:06-04:00, cbell@mysql_cab_desk. +67 -0
> >     BUG#22086 : Extra Slave Col: Char(5) on slave and 
> Char(10) on master cause mysqld crash 
> >     
> >     New result file for additional test.
> >
> >   mysql-test/suite/rpl/r/rpl_extraCol_myisam.result@stripped, 
> 2007-08-09 22:08:06-04:00, cbell@mysql_cab_desk. +67 -0
> >     BUG#22086 : Extra Slave Col: Char(5) on slave and 
> Char(10) on master cause mysqld crash 
> >     
> >     New result file for additional test.
> >
> >   mysql-test/suite/rpl/r/rpl_row_colSize.result@stripped, 
> 2007-08-09 22:08:09-04:00, cbell@mysql_cab_desk. +646 -0
> >     BUG#22086 : Extra Slave Col: Char(5) on slave and 
> Char(10) on master cause mysqld crash 
> >     
> >     New result file for additional test.
> >
> >   mysql-test/suite/rpl/r/rpl_row_colSize.result@stripped, 
> 2007-08-09 22:08:09-04:00, cbell@mysql_cab_desk. +0 -0
> >
> >   mysql-test/suite/rpl/t/rpl_row_colSize.test@stripped, 
> 2007-08-09 22:08:10-04:00, cbell@mysql_cab_desk. +158 -0
> >     BUG#22086 : Extra Slave Col: Char(5) on slave and 
> Char(10) on master cause mysqld crash 
> >     
> >     Added a test file to test each variable type that 
> relies on field
> >     metadata from the master.
> >
> >   mysql-test/suite/rpl/t/rpl_row_colSize.test@stripped, 
> 2007-08-09 22:08:10-04:00, cbell@mysql_cab_desk. +0 -0
> >
> >   mysql-test/suite/rpl_ndb/r/rpl_ndb_extraCol.result@stripped, 
> 2007-08-09 22:08:07-04:00, cbell@mysql_cab_desk. +67 -0
> >     BUG#22086 : Extra Slave Col: Char(5) on slave and 
> Char(10) on master cause mysqld crash 
> >     
> >     New result file for additional test.
> >
> >   sql/field.cc@stripped, 2007-08-09 22:08:07-04:00, 
> cbell@mysql_cab_desk. +220 -0
> >     BUG#22086 : Extra Slave Col: Char(5) on slave and 
> Char(10) on master cause mysqld crash 
> >     
> >     This patch refactors the additions made by this bug 
> patch and those
> >     made by WL#3228. The effort consolidates the large 
> switches on type()
> >     into functions within the field classes. 
> >
> >   sql/field.h@stripped, 2007-08-09 22:08:08-04:00, 
> cbell@mysql_cab_desk. +39 -0
> >     BUG#22086 : Extra Slave Col: Char(5) on slave and 
> Char(10) on master cause mysqld crash 
> >     
> >     This patch refactors the additions made by this bug 
> patch and those
> >     made by WL#3228. The effort consolidates the large 
> switches on type()
> >     into functions within the field classes. 
> >
> >   sql/log_event.cc@stripped, 2007-08-09 22:08:08-04:00, 
> cbell@mysql_cab_desk. +12 -91
> >     BUG#22086 : Extra Slave Col: Char(5) on slave and 
> Char(10) on master cause mysqld crash 
> >     
> >     This patch refactors the calc_field_size() method to use the new
> >     methods implemented in the field classes. It also 
> corrects comments 
> >     concerning how replication of field metadata works. 
> >
> >   sql/rpl_utility.cc@stripped, 2007-08-09 22:08:09-04:00, 
> cbell@mysql_cab_desk. +19 -0
> >     BUG#22086 : Extra Slave Col: Char(5) on slave and 
> Char(10) on master cause mysqld crash 
> >     
> >     This patch adds a method to check the size of the field 
> on the master
> >     using the field metadata from WL#3228. Each column is 
> checked to ensure
> >     the slave's column is >= to the master's column in size.
> >
> > diff -Nrup 
> a/mysql-test/extra/rpl_tests/rpl_extraSlave_Col.test 
> b/mysql-test/extra/rpl_tests/rpl_extraSlave_Col.test
> > --- a/mysql-test/extra/rpl_tests/rpl_extraSlave_Col.test	
> 2007-06-12 23:50:32 -04:00
> > +++ b/mysql-test/extra/rpl_tests/rpl_extraSlave_Col.test	
> 2007-08-09 22:08:05 -04:00
> > @@ -71,38 +71,47 @@ sync_slave_with_master;
> >  ############################################
> >  
> >  ## BUG22086
> > -#--echo *** Create t2 on slave  ***
> > -#STOP SLAVE;
> > -#RESET SLAVE;
> > -#eval CREATE TABLE t2 (a INT, b INT PRIMARY KEY, c CHAR(5),
> > -#                      d FLOAT DEFAULT '2.00',
> > -#                      e CHAR(5) DEFAULT 'TEST2')
> > -#                      ENGINE=$engine_type;
> > -#
> > -#--echo *** Create t2 on Master ***
> > -#connection master;
> > -#eval CREATE TABLE t2 (a INT PRIMARY KEY, b INT, c CHAR(10)
> > -#                       ) ENGINE=$engine_type;
> > -#RESET MASTER;
> > -#
> > -#--echo *** Start Slave ***
> > -#connection slave;
> > -#START SLAVE;
> > -#
> > -#--echo *** Master Data Insert ***
> > -#connection master;
> > -#
> > -#INSERT INTO t2 () VALUES(1,2,'Kyle, TEX'),(2,1,'JOE 
> AUSTIN'),(3,4,'QA TESTING');
> > -#SELECT * FROM t2 ORDER BY a;
> > -
> > -#--echo *** Select from slave ***
> > -#sync_slave_with_master;
> > -#SELECT * FROM t2 ORDER BY a;
> > -
> > -#--echo *** Drop t2  ***
> > -#connection master;
> > -#DROP TABLE t2;
> > -#sync_slave_with_master;
> > +--echo *** Create t2 on slave  ***
> > +STOP SLAVE;
> > +RESET SLAVE;
> > +eval CREATE TABLE t2 (a INT, b INT PRIMARY KEY, c CHAR(5),
> > +                      d FLOAT DEFAULT '2.00',
> > +                      e CHAR(5) DEFAULT 'TEST2')
> > +                      ENGINE=$engine_type;
> > +
> > +--echo *** Create t2 on Master ***
> > +connection master;
> > +eval CREATE TABLE t2 (a INT PRIMARY KEY, b INT, c CHAR(10)
> > +                       ) ENGINE=$engine_type;
> > +RESET MASTER;
> > +
> > +--echo *** Master Data Insert ***
> > +connection master;
> > +
> > +INSERT INTO t2 () VALUES(1,2,'Kyle, TEX'),(2,1,'JOE 
> AUSTIN'),(3,4,'QA TESTING');
> > +SELECT * FROM t2 ORDER BY a;
> > +
> > +--echo *** Start Slave ***
> > +connection slave;
> > +START SLAVE;
> > +wait_for_slave_to_stop;
> > +--replace_result $MASTER_MYPORT MASTER_PORT
> > +--replace_column 1 # 4 # 7 # 8 # 9 # 22 # 23 # 33 #
> > +--query_vertical SHOW SLAVE STATUS
> > +STOP SLAVE;
> > +RESET SLAVE;
> > +SELECT * FROM t2 ORDER BY a;
> > +
> > +connection master;
> > +RESET MASTER;
> > +
> > +connection slave;
> > +START SLAVE;
> > +
> > +--echo *** Drop t2  ***
> > +connection master;
> > +DROP TABLE t2;
> > +sync_slave_with_master;
> >  
> >  ####################################
> >  ### Try to replicate BLOB to INT ###
> > diff -Nrup a/mysql-test/include/test_fieldsize.inc 
> b/mysql-test/include/test_fieldsize.inc
> > --- /dev/null	Wed Dec 31 16:00:00 196900
> > +++ b/mysql-test/include/test_fieldsize.inc	2007-08-09 
> 22:08:10 -04:00
> > @@ -0,0 +1,40 @@
> > +#
> > +# include/test_fieldsize.inc 
> > +# 
> > +# This include file is designed to create a table with one column
> > +# whose size on the master is greater than that on the slave. The
> > +# test should fail with an error on the slave.
> > +#
> > +
> > +connection master;
> > +DROP TABLE IF EXISTS t1;
> > +
> > +sync_slave_with_master;
> > +STOP SLAVE;
> > +RESET SLAVE;
> > +eval $test_table_slave;
> > +
> > +connection master;
> > +eval $test_table_master;
> > +RESET MASTER;
> > +
> > +eval $test_insert;
> > +
> > +connection slave;
> > +START SLAVE;
> > +wait_for_slave_to_stop;
> > +--replace_result $MASTER_MYPORT MASTER_PORT
> > +--replace_column 1 # 4 # 7 # 8 # 9 # 22 # 23 # 33 #
> > +--query_vertical SHOW SLAVE STATUS
> > +
> > +# The following should be 0
> > +SELECT COUNT(*) FROM t1;
> > +STOP SLAVE;
> > +RESET SLAVE;
> > +
> > +connection master;
> > +RESET MASTER;
> > +
> > +connection slave;
> > +START SLAVE;
> > +
> > diff -Nrup 
> a/mysql-test/suite/rpl/r/rpl_extraCol_innodb.result 
> b/mysql-test/suite/rpl/r/rpl_extraCol_innodb.result
> > --- a/mysql-test/suite/rpl/r/rpl_extraCol_innodb.result	
> 2007-07-09 04:54:16 -04:00
> > +++ b/mysql-test/suite/rpl/r/rpl_extraCol_innodb.result	
> 2007-08-09 22:08:06 -04:00
> > @@ -33,6 +33,73 @@ a	b	c	d	e
> >  3	4	QA	2	TEST
> >  *** Drop t1  ***
> >  DROP TABLE t1;
> > +*** Create t2 on slave  ***
> > +STOP SLAVE;
> > +RESET SLAVE;
> > +CREATE TABLE t2 (a INT, b INT PRIMARY KEY, c CHAR(5),
> > +d FLOAT DEFAULT '2.00',
> > +e CHAR(5) DEFAULT 'TEST2')
> > +ENGINE='InnoDB';
> > +*** Create t2 on Master ***
> > +CREATE TABLE t2 (a INT PRIMARY KEY, b INT, c CHAR(10)
> > +) ENGINE='InnoDB';
> > +RESET MASTER;
> > +*** Master Data Insert ***
> > +INSERT INTO t2 () VALUES(1,2,'Kyle, TEX'),(2,1,'JOE 
> AUSTIN'),(3,4,'QA TESTING');
> > +SELECT * FROM t2 ORDER BY a;
> > +a	b	c
> > +1	2	Kyle, TEX
> > +2	1	JOE AUSTIN
> > +3	4	QA TESTING
> > +*** Start Slave ***
> > +START SLAVE;
> > +SHOW SLAVE STATUS;
> > +Slave_IO_State	#
> > +Master_Host	127.0.0.1
> > +Master_User	root
> > +Master_Port	#
> > +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	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	1532
> > +Last_Error	Table definition on master and slave does not 
> match: Column 2 size mismatch - master has size 10, test.t2 
> on slave has size 6. Master's column size should be <= the 
> slave's column size.
> > +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
> 
> It is probably a good idea to blank out these columns, since an I/O 
> error is not an indication of a failure of the test (in 
> addition, there 
> are other checks for catching that kind of failure). I 
> believe there is 
> a show_slave_status.inc file that can be used for "standard" 
> show slave 
> status checks.

Done. Ditto for others below.

> 
> > 	
> > +Last_SQL_Errno	1532
> > +Last_SQL_Error	Table definition on master and slave 
> does not match: Column 2 size mismatch - master has size 10, 
> test.t2 on slave has size 6. Master's column size should be 
> <= the slave's column size.
> > +STOP SLAVE;
> > +RESET SLAVE;
> > +SELECT * FROM t2 ORDER BY a;
> > +a	b	c	d	e
> > +RESET MASTER;
> > +START SLAVE;
> > +*** Drop t2  ***
> > +DROP TABLE t2;
> >  *** Create t3 on slave  ***
> >  STOP SLAVE;
> >  RESET SLAVE;
> > diff -Nrup 
> a/mysql-test/suite/rpl/r/rpl_extraCol_myisam.result 
> b/mysql-test/suite/rpl/r/rpl_extraCol_myisam.result
> > --- a/mysql-test/suite/rpl/r/rpl_extraCol_myisam.result	
> 2007-07-09 04:54:16 -04:00
> > +++ b/mysql-test/suite/rpl/r/rpl_extraCol_myisam.result	
> 2007-08-09 22:08:06 -04:00
> > @@ -33,6 +33,73 @@ a	b	c	d	e
> >  3	4	QA	2	TEST
> >  *** Drop t1  ***
> >  DROP TABLE t1;
> > +*** Create t2 on slave  ***
> > +STOP SLAVE;
> > +RESET SLAVE;
> > +CREATE TABLE t2 (a INT, b INT PRIMARY KEY, c CHAR(5),
> > +d FLOAT DEFAULT '2.00',
> > +e CHAR(5) DEFAULT 'TEST2')
> > +ENGINE='MyISAM';
> > +*** Create t2 on Master ***
> > +CREATE TABLE t2 (a INT PRIMARY KEY, b INT, c CHAR(10)
> > +) ENGINE='MyISAM';
> > +RESET MASTER;
> > +*** Master Data Insert ***
> > +INSERT INTO t2 () VALUES(1,2,'Kyle, TEX'),(2,1,'JOE 
> AUSTIN'),(3,4,'QA TESTING');
> > +SELECT * FROM t2 ORDER BY a;
> > +a	b	c
> > +1	2	Kyle, TEX
> > +2	1	JOE AUSTIN
> > +3	4	QA TESTING
> > +*** Start Slave ***
> > +START SLAVE;
> > +SHOW SLAVE STATUS;
> > +Slave_IO_State	#
> > +Master_Host	127.0.0.1
> > +Master_User	root
> > +Master_Port	#
> > +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	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	1532
> > +Last_Error	Table definition on master and slave does not 
> match: Column 2 size mismatch - master has size 10, test.t2 
> on slave has size 6. Master's column size should be <= the 
> slave's column size.
> > +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	
> >   
> 
> See above.
> 
> > +Last_SQL_Errno	1532
> > +Last_SQL_Error	Table definition on master and slave 
> does not match: Column 2 size mismatch - master has size 10, 
> test.t2 on slave has size 6. Master's column size should be 
> <= the slave's column size.
> > +STOP SLAVE;
> > +RESET SLAVE;
> > +SELECT * FROM t2 ORDER BY a;
> > +a	b	c	d	e
> > +RESET MASTER;
> > +START SLAVE;
> > +*** Drop t2  ***
> > +DROP TABLE t2;
> >  *** Create t3 on slave  ***
> >  STOP SLAVE;
> >  RESET SLAVE;
> > diff -Nrup a/mysql-test/suite/rpl/r/rpl_row_colSize.result 
> b/mysql-test/suite/rpl/r/rpl_row_colSize.result
> > --- /dev/null	Wed Dec 31 16:00:00 196900
> > +++ b/mysql-test/suite/rpl/r/rpl_row_colSize.result	
> 2007-08-09 22:08:09 -04:00
> > @@ -0,0 +1,646 @@
> > +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 ***
> > +Checking MYSQL_TYPE_NEWDECIMAL fields
> > +DROP TABLE IF EXISTS t1;
> > +Warnings:
> > +Note	1051	Unknown table 't1'
> > +STOP SLAVE;
> > +RESET SLAVE;
> > +CREATE TABLE t1 (a DECIMAL(5,2));
> > +CREATE TABLE t1 (a DECIMAL(20, 10));
> > +RESET MASTER;
> > +INSERT INTO t1 VALUES (901251.90125);
> > +START SLAVE;
> > +SHOW SLAVE STATUS;
> > +Slave_IO_State	#
> > +Master_Host	127.0.0.1
> > +Master_User	root
> > +Master_Port	#
> > +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	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	1532
> > +Last_Error	Table definition on master and slave does not 
> match: Column 0 size mismatch - master has size 10, test.t1 
> on slave has size 3. Master's column size should be <= the 
> slave's column size.
> > +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	
> >   
> 
> See above.
> 
> > +Last_SQL_Errno	1532
> > +Last_SQL_Error	Table definition on master and slave 
> does not match: Column 0 size mismatch - master has size 10, 
> test.t1 on slave has size 3. Master's column size should be 
> <= the slave's column size.
> > +SELECT COUNT(*) FROM t1;
> > +COUNT(*)
> > +0
> > +STOP SLAVE;
> > +RESET SLAVE;
> > +RESET MASTER;
> > +START SLAVE;
> > +DROP TABLE IF EXISTS t1;
> > +STOP SLAVE;
> > +RESET SLAVE;
> > +CREATE TABLE t1 (a NUMERIC(5,2));
> > +CREATE TABLE t1 (a NUMERIC(20, 10));
> > +RESET MASTER;
> > +INSERT INTO t1 VALUES (901251.90125);
> > +START SLAVE;
> > +SHOW SLAVE STATUS;
> > +Slave_IO_State	#
> > +Master_Host	127.0.0.1
> > +Master_User	root
> > +Master_Port	#
> > +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	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	1532
> > +Last_Error	Table definition on master and slave does not 
> match: Column 0 size mismatch - master has size 10, test.t1 
> on slave has size 3. Master's column size should be <= the 
> slave's column size.
> > +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	1532
> > +Last_SQL_Error	Table definition on master and slave 
> does not match: Column 0 size mismatch - master has size 10, 
> test.t1 on slave has size 3. Master's column size should be 
> <= the slave's column size.
> > +SELECT COUNT(*) FROM t1;
> > +COUNT(*)
> > +0
> > +STOP SLAVE;
> > +RESET SLAVE;
> > +RESET MASTER;
> > +START SLAVE;
> > +Checking MYSQL_TYPE_FLOAT fields
> > +DROP TABLE IF EXISTS t1;
> > +STOP SLAVE;
> > +RESET SLAVE;
> > +CREATE TABLE t1 (a FLOAT(20));
> > +CREATE TABLE t1 (a FLOAT(47));
> > +RESET MASTER;
> > +INSERT INTO t1 VALUES (901251.90125);
> > +START SLAVE;
> > +SHOW SLAVE STATUS;
> > +Slave_IO_State	#
> > +Master_Host	127.0.0.1
> > +Master_User	root
> > +Master_Port	#
> > +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	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	1532
> > +Last_Error	Table definition on master and slave does not 
> match: Column 0 type mismatch - received type 5, test.t1 has type 4
> > +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	1532
> > +Last_SQL_Error	Table definition on master and slave 
> does not match: Column 0 type mismatch - received type 5, 
> test.t1 has type 4
> > +SELECT COUNT(*) FROM t1;
> > +COUNT(*)
> > +0
> > +STOP SLAVE;
> > +RESET SLAVE;
> > +RESET MASTER;
> > +START SLAVE;
> > +Checking MYSQL_TYPE_BIT fields
> > +DROP TABLE IF EXISTS t1;
> > +STOP SLAVE;
> > +RESET SLAVE;
> > +CREATE TABLE t1 (a BIT(5));
> > +CREATE TABLE t1 (a BIT(64));
> > +RESET MASTER;
> > +INSERT INTO t1 VALUES (B'10101');
> > +START SLAVE;
> > +SHOW SLAVE STATUS;
> > +Slave_IO_State	#
> > +Master_Host	127.0.0.1
> > +Master_User	root
> > +Master_Port	#
> > +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	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	1532
> > +Last_Error	Table definition on master and slave does not 
> match: Column 0 size mismatch - master has size 8, test.t1 on 
> slave has size 1. Master's column size should be <= the 
> slave's column size.
> > +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	1532
> > +Last_SQL_Error	Table definition on master and slave 
> does not match: Column 0 size mismatch - master has size 8, 
> test.t1 on slave has size 1. Master's column size should be 
> <= the slave's column size.
> > +SELECT COUNT(*) FROM t1;
> > +COUNT(*)
> > +0
> > +STOP SLAVE;
> > +RESET SLAVE;
> > +RESET MASTER;
> > +START SLAVE;
> > +Checking MYSQL_TYPE_SET fields
> > +DROP TABLE IF EXISTS t1;
> > +STOP SLAVE;
> > +RESET SLAVE;
> > +CREATE TABLE t1 (a SET('4'));
> > +CREATE TABLE t1 (a SET('1','2','3','4','5','6','7','8','9'));
> > +RESET MASTER;
> > +INSERT INTO t1 VALUES ('4');
> > +START SLAVE;
> > +SHOW SLAVE STATUS;
> > +Slave_IO_State	#
> > +Master_Host	127.0.0.1
> > +Master_User	root
> > +Master_Port	#
> > +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	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	1532
> > +Last_Error	Table definition on master and slave does not 
> match: Column 0 size mismatch - master has size 2, test.t1 on 
> slave has size 1. Master's column size should be <= the 
> slave's column size.
> > +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	1532
> > +Last_SQL_Error	Table definition on master and slave 
> does not match: Column 0 size mismatch - master has size 2, 
> test.t1 on slave has size 1. Master's column size should be 
> <= the slave's column size.
> > +SELECT COUNT(*) FROM t1;
> > +COUNT(*)
> > +0
> > +STOP SLAVE;
> > +RESET SLAVE;
> > +RESET MASTER;
> > +START SLAVE;
> > +Checking MYSQL_TYPE_STRING fields
> > +DROP TABLE IF EXISTS t1;
> > +STOP SLAVE;
> > +RESET SLAVE;
> > +CREATE TABLE t1 (a CHAR(10));
> > +CREATE TABLE t1 (a CHAR(20));
> > +RESET MASTER;
> > +INSERT INTO t1 VALUES ('This is a test.');
> > +START SLAVE;
> > +SHOW SLAVE STATUS;
> > +Slave_IO_State	#
> > +Master_Host	127.0.0.1
> > +Master_User	root
> > +Master_Port	#
> > +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	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	1532
> > +Last_Error	Table definition on master and slave does not 
> match: Column 0 size mismatch - master has size 20, test.t1 
> on slave has size 11. Master's column size should be <= the 
> slave's column size.
> > +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	1532
> > +Last_SQL_Error	Table definition on master and slave 
> does not match: Column 0 size mismatch - master has size 20, 
> test.t1 on slave has size 11. Master's column size should be 
> <= the slave's column size.
> > +SELECT COUNT(*) FROM t1;
> > +COUNT(*)
> > +0
> > +STOP SLAVE;
> > +RESET SLAVE;
> > +RESET MASTER;
> > +START SLAVE;
> > +Checking MYSQL_TYPE_ENUM fields
> > +DROP TABLE IF EXISTS t1;
> > +STOP SLAVE;
> > +RESET SLAVE;
> > +CREATE TABLE t1 (a ENUM('44','54'));
> > +CREATE TABLE t1 (a ENUM(
> > +'01','02','03','04','05','06','07','08','09',
> > +'11','12','13','14','15','16','17','18','19',
> > +'21','22','23','24','25','26','27','28','29',
> > +'31','32','33','34','35','36','37','38','39',
> > +'41','42','43','44','45','46','47','48','49',
> > +'51','52','53','54','55','56','57','58','59',
> > +'61','62','63','64','65','66','67','68','69',
> > +'71','72','73','74','75','76','77','78','79',
> > +'81','82','83','84','85','86','87','88','89',
> > +'91','92','93','94','95','96','97','98','99',
> > +'101','102','103','104','105','106','107','108','109',
> > +'111','112','113','114','115','116','117','118','119',
> > +'121','122','123','124','125','126','127','128','129',
> > +'131','132','133','134','135','136','137','138','139',
> > +'141','142','143','144','145','146','147','148','149',
> > +'151','152','153','154','155','156','157','158','159',
> > +'161','162','163','164','165','166','167','168','169',
> > +'171','172','173','174','175','176','177','178','179',
> > +'181','182','183','184','185','186','187','188','189',
> > +'191','192','193','194','195','196','197','198','199',
> > +'201','202','203','204','205','206','207','208','209',
> > +'211','212','213','214','215','216','217','218','219',
> > +'221','222','223','224','225','226','227','228','229',
> > +'231','232','233','234','235','236','237','238','239',
> > +'241','242','243','244','245','246','247','248','249',
> > +'251','252','253','254','255','256','257','258','259',
> > +'261','262','263','264','265','266','267','268','269',
> > +'271','272','273','274','275','276','277','278','279',
> > +'281','282','283','284','285','286','287','288','289',
> > +'291','292','293','294','295','296','297','298','299'
> > +            ));
> > +RESET MASTER;
> > +INSERT INTO t1 VALUES ('44');
> > +START SLAVE;
> > +SHOW SLAVE STATUS;
> > +Slave_IO_State	#
> > +Master_Host	127.0.0.1
> > +Master_User	root
> > +Master_Port	#
> > +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	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	1532
> > +Last_Error	Table definition on master and slave does not 
> match: Column 0 size mismatch - master has size 2, test.t1 on 
> slave has size 1. Master's column size should be <= the 
> slave's column size.
> > +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	1532
> > +Last_SQL_Error	Table definition on master and slave 
> does not match: Column 0 size mismatch - master has size 2, 
> test.t1 on slave has size 1. Master's column size should be 
> <= the slave's column size.
> > +SELECT COUNT(*) FROM t1;
> > +COUNT(*)
> > +0
> > +STOP SLAVE;
> > +RESET SLAVE;
> > +RESET MASTER;
> > +START SLAVE;
> > +Checking MYSQL_TYPE_VARCHAR fields
> > +DROP TABLE IF EXISTS t1;
> > +STOP SLAVE;
> > +RESET SLAVE;
> > +CREATE TABLE t1 (a VARCHAR(100));
> > +CREATE TABLE t1 (a VARCHAR(2000));
> > +RESET MASTER;
> > +INSERT INTO t1 VALUES ('This is a test.');
> > +START SLAVE;
> > +SHOW SLAVE STATUS;
> > +Slave_IO_State	#
> > +Master_Host	127.0.0.1
> > +Master_User	root
> > +Master_Port	#
> > +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	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	1532
> > +Last_Error	Table definition on master and slave does not 
> match: Column 0 size mismatch - master has size 2000, test.t1 
> on slave has size 100. Master's column size should be <= the 
> slave's column size.
> > +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	1532
> > +Last_SQL_Error	Table definition on master and slave 
> does not match: Column 0 size mismatch - master has size 
> 2000, test.t1 on slave has size 100. Master's column size 
> should be <= the slave's column size.
> > +SELECT COUNT(*) FROM t1;
> > +COUNT(*)
> > +0
> > +STOP SLAVE;
> > +RESET SLAVE;
> > +RESET MASTER;
> > +START SLAVE;
> > +DROP TABLE IF EXISTS t1;
> > +STOP SLAVE;
> > +RESET SLAVE;
> > +CREATE TABLE t1 (a VARCHAR(10));
> > +CREATE TABLE t1 (a VARCHAR(200));
> > +RESET MASTER;
> > +INSERT INTO t1 VALUES ('This is a test.');
> > +START SLAVE;
> > +SHOW SLAVE STATUS;
> > +Slave_IO_State	#
> > +Master_Host	127.0.0.1
> > +Master_User	root
> > +Master_Port	#
> > +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	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	1532
> > +Last_Error	Table definition on master and slave does not 
> match: Column 0 size mismatch - master has size 200, test.t1 
> on slave has size 10. Master's column size should be <= the 
> slave's column size.
> > +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	1532
> > +Last_SQL_Error	Table definition on master and slave 
> does not match: Column 0 size mismatch - master has size 200, 
> test.t1 on slave has size 10. Master's column size should be 
> <= the slave's column size.
> > +SELECT COUNT(*) FROM t1;
> > +COUNT(*)
> > +0
> > +STOP SLAVE;
> > +RESET SLAVE;
> > +RESET MASTER;
> > +START SLAVE;
> > +DROP TABLE IF EXISTS t1;
> > +STOP SLAVE;
> > +RESET SLAVE;
> > +CREATE TABLE t1 (a VARCHAR(1000));
> > +CREATE TABLE t1 (a VARCHAR(2000));
> > +RESET MASTER;
> > +INSERT INTO t1 VALUES ('This is a test.');
> > +START SLAVE;
> > +SHOW SLAVE STATUS;
> > +Slave_IO_State	#
> > +Master_Host	127.0.0.1
> > +Master_User	root
> > +Master_Port	#
> > +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	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	1532
> > +Last_Error	Table definition on master and slave does not 
> match: Column 0 size mismatch - master has size 2000, test.t1 
> on slave has size 1000. Master's column size should be <= the 
> slave's column size.
> > +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	1532
> > +Last_SQL_Error	Table definition on master and slave 
> does not match: Column 0 size mismatch - master has size 
> 2000, test.t1 on slave has size 1000. Master's column size 
> should be <= the slave's column size.
> > +SELECT COUNT(*) FROM t1;
> > +COUNT(*)
> > +0
> > +STOP SLAVE;
> > +RESET SLAVE;
> > +RESET MASTER;
> > +START SLAVE;
> > +Checking MYSQL_TYPE_BLOB fields
> > +DROP TABLE IF EXISTS t1;
> > +STOP SLAVE;
> > +RESET SLAVE;
> > +CREATE TABLE t1 (a TINYBLOB);
> > +CREATE TABLE t1 (a LONGBLOB);
> > +RESET MASTER;
> > +INSERT INTO t1 VALUES ('This is a test.');
> > +START SLAVE;
> > +SHOW SLAVE STATUS;
> > +Slave_IO_State	#
> > +Master_Host	127.0.0.1
> > +Master_User	root
> > +Master_Port	#
> > +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	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	1532
> > +Last_Error	Table definition on master and slave does not 
> match: Column 0 size mismatch - master has size 4, test.t1 on 
> slave has size 1. Master's column size should be <= the 
> slave's column size.
> > +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	1532
> > +Last_SQL_Error	Table definition on master and slave 
> does not match: Column 0 size mismatch - master has size 4, 
> test.t1 on slave has size 1. Master's column size should be 
> <= the slave's column size.
> > +SELECT COUNT(*) FROM t1;
> > +COUNT(*)
> > +0
> > +STOP SLAVE;
> > +RESET SLAVE;
> > +RESET MASTER;
> > +START SLAVE;
> > +*** Cleanup  ***
> > +DROP TABLE IF EXISTS t1;
> > diff -Nrup a/mysql-test/suite/rpl/t/rpl_row_colSize.test 
> b/mysql-test/suite/rpl/t/rpl_row_colSize.test
> > --- /dev/null	Wed Dec 31 16:00:00 196900
> > +++ b/mysql-test/suite/rpl/t/rpl_row_colSize.test	
> 2007-08-09 22:08:10 -04:00
> > @@ -0,0 +1,158 @@
> > +##################################################################
> > +# 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
> > +-- source include/have_binlog_format_row.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;
> > +
> > +#
> > +# Check each column type to verify error 1532 fires (BUG#22086)
> > +# This check covers only those fields that require additional
> > +# metadata from the master to be replicated to the slave. These
> > +# field types are:
> > +#   MYSQL_TYPE_NEWDECIMAL:
> > +#   MYSQL_TYPE_FLOAT:
> > +#   MYSQL_TYPE_BIT:
> > +#   MYSQL_TYPE_SET:
> > +#   MYSQL_TYPE_STRING:
> > +#   MYSQL_TYPE_ENUM:
> > +#   MYSQL_TYPE_VARCHAR:
> > +#   MYSQL_TYPE_BLOB:
> > +
> > +#
> > +# Test: Checking MYSQL_TYPE_NEWDECIMAL fields
> > +#
> > +--echo Checking MYSQL_TYPE_NEWDECIMAL fields
> > +let $test_table_master = CREATE TABLE t1 (a DECIMAL(20, 10));
> > +let $test_table_slave = CREATE TABLE t1 (a DECIMAL(5,2));
> > +let $test_insert = INSERT INTO t1 VALUES (901251.90125);
> > +source include/test_fieldsize.inc;
> > +
> > +let $test_table_master = CREATE TABLE t1 (a NUMERIC(20, 10));
> > +let $test_table_slave = CREATE TABLE t1 (a NUMERIC(5,2));
> > +let $test_insert = INSERT INTO t1 VALUES (901251.90125);
> > +source include/test_fieldsize.inc;
> > +
> > +#
> > +# Test: Checking MYSQL_TYPE_FLOAT fields
> > +#
> > +--echo Checking MYSQL_TYPE_FLOAT fields
> > +let $test_table_master = CREATE TABLE t1 (a FLOAT(47));
> > +let $test_table_slave = CREATE TABLE t1 (a FLOAT(20));
> > +let $test_insert = INSERT INTO t1 VALUES (901251.90125);
> > +source include/test_fieldsize.inc;
> > +
> > +#
> > +# Test: Checking MYSQL_TYPE_BIT fields
> > +#
> > +--echo Checking MYSQL_TYPE_BIT fields
> > +let $test_table_master = CREATE TABLE t1 (a BIT(64));
> > +let $test_table_slave = CREATE TABLE t1 (a BIT(5));
> > +let $test_insert = INSERT INTO t1 VALUES (B'10101');
> > +source include/test_fieldsize.inc;
> > +
> > +#
> > +# Test: Checking MYSQL_TYPE_SET fields
> > +#
> > +--echo Checking MYSQL_TYPE_SET fields
> > +let $test_table_master = CREATE TABLE t1 (a 
> SET('1','2','3','4','5','6','7','8','9'));
> > +let $test_table_slave = CREATE TABLE t1 (a SET('4'));
> > +let $test_insert = INSERT INTO t1 VALUES ('4');
> > +source include/test_fieldsize.inc;
> > +
> > +#
> > +# Test: Checking MYSQL_TYPE_STRING fields
> > +#
> > +--echo Checking MYSQL_TYPE_STRING fields
> > +let $test_table_master = CREATE TABLE t1 (a CHAR(20));
> > +let $test_table_slave = CREATE TABLE t1 (a CHAR(10));
> > +let $test_insert = INSERT INTO t1 VALUES ('This is a test.');
> > +source include/test_fieldsize.inc;
> > +
> > +#
> > +# Test: Checking MYSQL_TYPE_ENUM fields
> > +#
> > +--echo Checking MYSQL_TYPE_ENUM fields
> > +let $test_table_master = CREATE TABLE t1 (a ENUM(
> > +            '01','02','03','04','05','06','07','08','09',
> > +            '11','12','13','14','15','16','17','18','19',
> > +            '21','22','23','24','25','26','27','28','29',
> > +            '31','32','33','34','35','36','37','38','39',
> > +            '41','42','43','44','45','46','47','48','49',
> > +            '51','52','53','54','55','56','57','58','59',
> > +            '61','62','63','64','65','66','67','68','69',
> > +            '71','72','73','74','75','76','77','78','79',
> > +            '81','82','83','84','85','86','87','88','89',
> > +            '91','92','93','94','95','96','97','98','99',
> > +            '101','102','103','104','105','106','107','108','109',
> > +            '111','112','113','114','115','116','117','118','119',
> > +            '121','122','123','124','125','126','127','128','129',
> > +            '131','132','133','134','135','136','137','138','139',
> > +            '141','142','143','144','145','146','147','148','149',
> > +            '151','152','153','154','155','156','157','158','159',
> > +            '161','162','163','164','165','166','167','168','169',
> > +            '171','172','173','174','175','176','177','178','179',
> > +            '181','182','183','184','185','186','187','188','189',
> > +            '191','192','193','194','195','196','197','198','199',
> > +            '201','202','203','204','205','206','207','208','209',
> > +            '211','212','213','214','215','216','217','218','219',
> > +            '221','222','223','224','225','226','227','228','229',
> > +            '231','232','233','234','235','236','237','238','239',
> > +            '241','242','243','244','245','246','247','248','249',
> > +            '251','252','253','254','255','256','257','258','259',
> > +            '261','262','263','264','265','266','267','268','269',
> > +            '271','272','273','274','275','276','277','278','279',
> > +            '281','282','283','284','285','286','287','288','289',
> > +            '291','292','293','294','295','296','297','298','299'
> > +            ));
> > +let $test_table_slave = CREATE TABLE t1 (a ENUM('44','54'));
> > +let $test_insert = INSERT INTO t1 VALUES ('44');
> > +source include/test_fieldsize.inc;
> > +
> > +#
> > +# Test: Checking MYSQL_TYPE_VARCHAR fields
> > +#
> > +--echo Checking MYSQL_TYPE_VARCHAR fields
> > +let $test_table_master = CREATE TABLE t1 (a VARCHAR(2000));
> > +let $test_table_slave = CREATE TABLE t1 (a VARCHAR(100));
> > +let $test_insert = INSERT INTO t1 VALUES ('This is a test.');
> > +source include/test_fieldsize.inc;
> > +
> > +let $test_table_master = CREATE TABLE t1 (a VARCHAR(200));
> > +let $test_table_slave = CREATE TABLE t1 (a VARCHAR(10));
> > +let $test_insert = INSERT INTO t1 VALUES ('This is a test.');
> > +source include/test_fieldsize.inc;
> > +
> > +let $test_table_master = CREATE TABLE t1 (a VARCHAR(2000));
> > +let $test_table_slave = CREATE TABLE t1 (a VARCHAR(1000));
> > +let $test_insert = INSERT INTO t1 VALUES ('This is a test.');
> > +source include/test_fieldsize.inc;
> > +
> > +#
> > +# Test: Checking MYSQL_TYPE_BLOB fields
> > +#
> > +--echo Checking MYSQL_TYPE_BLOB fields
> > +let $test_table_master = CREATE TABLE t1 (a LONGBLOB);
> > +let $test_table_slave = CREATE TABLE t1 (a TINYBLOB);
> > +let $test_insert = INSERT INTO t1 VALUES ('This is a test.');
> > +source include/test_fieldsize.inc;
> > +
> > +--echo *** Cleanup  ***
> > +connection master;
> > +DROP TABLE IF EXISTS t1;
> > +sync_slave_with_master;
> > +# END 5.1 Test Case
> > +
> > diff -Nrup 
> a/mysql-test/suite/rpl_ndb/r/rpl_ndb_extraCol.result 
> b/mysql-test/suite/rpl_ndb/r/rpl_ndb_extraCol.result
> > --- a/mysql-test/suite/rpl_ndb/r/rpl_ndb_extraCol.result	
> 2007-07-09 04:54:16 -04:00
> > +++ b/mysql-test/suite/rpl_ndb/r/rpl_ndb_extraCol.result	
> 2007-08-09 22:08:07 -04:00
> > @@ -33,6 +33,73 @@ a	b	c	d	e
> >  3	4	QA	NULL	NULL
> >  *** Drop t1  ***
> >  DROP TABLE t1;
> > +*** Create t2 on slave  ***
> > +STOP SLAVE;
> > +RESET SLAVE;
> > +CREATE TABLE t2 (a INT, b INT PRIMARY KEY, c CHAR(5),
> > +d FLOAT DEFAULT '2.00',
> > +e CHAR(5) DEFAULT 'TEST2')
> > +ENGINE='NDB';
> > +*** Create t2 on Master ***
> > +CREATE TABLE t2 (a INT PRIMARY KEY, b INT, c CHAR(10)
> > +) ENGINE='NDB';
> > +RESET MASTER;
> > +*** Master Data Insert ***
> > +INSERT INTO t2 () VALUES(1,2,'Kyle, TEX'),(2,1,'JOE 
> AUSTIN'),(3,4,'QA TESTING');
> > +SELECT * FROM t2 ORDER BY a;
> > +a	b	c
> > +1	2	Kyle, TEX
> > +2	1	JOE AUSTIN
> > +3	4	QA TESTING
> > +*** Start Slave ***
> > +START SLAVE;
> > +SHOW SLAVE STATUS;
> > +Slave_IO_State	#
> > +Master_Host	127.0.0.1
> > +Master_User	root
> > +Master_Port	#
> > +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	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	1532
> > +Last_Error	Table definition on master and slave does not 
> match: Column 2 size mismatch - master has size 10, test.t2 
> on slave has size 6. Master's column size should be <= the 
> slave's column size.
> > +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	1532
> > +Last_SQL_Error	Table definition on master and slave 
> does not match: Column 2 size mismatch - master has size 10, 
> test.t2 on slave has size 6. Master's column size should be 
> <= the slave's column size.
> > +STOP SLAVE;
> > +RESET SLAVE;
> > +SELECT * FROM t2 ORDER BY a;
> > +a	b	c	d	e
> > +RESET MASTER;
> > +START SLAVE;
> > +*** Drop t2  ***
> > +DROP TABLE t2;
> >  *** Create t3 on slave  ***
> >  STOP SLAVE;
> >  RESET SLAVE;
> > diff -Nrup a/sql/field.cc b/sql/field.cc
> > --- a/sql/field.cc	2007-07-29 18:10:23 -04:00
> > +++ b/sql/field.cc	2007-08-09 22:08:07 -04:00
> > @@ -1360,6 +1360,27 @@ bool Field::send_binary(Protocol *protoc
> >  }
> >  
> >  
> > +/**
> > +   Check to see if field size is compatible with destination.
> > +
> > +   This method is used in row-based replication to verify 
> that the slave's
> > +   field size is less than or equal to the master's field 
> size. The 
> > +   encoded field metadata (from the master or source) is 
> decoded and compared
> > +   to the size of this field (the slave or destination). 
> > +
> > +   @param   field_metadata   Encoded size in field metadata
> > +
> > +   @returns 0 if this field's size is < the source field's size
> > +   @returns 1 if this field's size is >= the source field's size
> >   
> 
> Use @retval when there is a list of possible return values (as above) 
> and @return when the return value is best described using a text.

Done.

> 
> > +*/
> > +int Field::compatible_field_size(uint field_metadata)
> > +{
> > +  uint const source_size= 
> pack_length_from_metadata(field_metadata);
> > +  uint const destination_size= row_pack_length();
> >   
> 
> Pack length is the same as the size of the data in the 
> record, but how 
> does row_pack_length() differ from pack_length()? Why do you need it 
> separate? If there is a reason, please add a comment explaining the 
> differences, and maybe give an example of a case where it differs.

Yes, it can. The classes Field_string, Field_varstring, and Field_blob
return field_length + 1, field_length, and pack_length_no_ptr()
respectfully.

> 
> > +  return (source_size <= destination_size);
> > +}
> > +
> > +
> >  int Field::store(const char *to, uint length, CHARSET_INFO *cs,
> >                   enum_check_fields check_level)
> >  {
> > @@ -2690,6 +2711,47 @@ void Field_new_decimal::sql_type(String 
> >  }
> >  
> >  
> > +/**
> > +   Retrieve the field metadata for new decimal fields.
> > +
> > +   Saves the precision in the first byte and decimals() in 
> the second.
> >   
> 
> There seems to be a contradiction between the first and second 
> paragraph. Shouldn't the first paragraph contain "Saves" instead of 
> "Retrieves"?
> 

Changed to save.

> > +
> > +   @param   first_byte   First byte of field metadata
> > +   @param   second_byte  Second byte of field metadata
> > +
> > +   @returns 0 success
> > +*/
> > +int Field_new_decimal::save_field_metadata(uchar *first_byte, 
> > +                                           uchar *second_byte)
> > +{
> > +  *first_byte= (uchar)precision;
> > +  *second_byte= (uchar)decimals();
> >   
> 
> Are the casts necessary?
> 
> > +  return 0;
> > +}
> > +
> > +
> > +/**
> > +   Returns the number of bytes field uses in row-based replication 
> > +   row packed size.
> > +
> > +   This method is used in row-based replication to 
> determine the number
> > +   of bytes that the field consumes in the row record 
> format. This is
> > +   used to skip fields in the master that do not exist on 
> the slave.
> > +
> > +   @param   field_metadata   Encoded size in field metadata
> > +
> > +   @retval The size of the field based on the field metadata.
> > +*/
> > +uint Field_new_decimal::pack_length_from_metadata(uint 
> field_metadata)
> > +{
> > +  uint const source_precision= (field_metadata >> 8U) & 0x00ff;
> > +  uint const source_decimal= field_metadata & 0x00ff; 
> > +  uint const source_size= 
> my_decimal_get_binary_size(source_precision, 
> > +                                                     
> source_decimal);
> >   
> 
> See! No casts!
> 
> > +  return (source_size);
> >   
> 
> So, this would mean that it is perfectly legal to replicate a 
> DECIMAL(27,9) to a DECIMAL(27, 18)? Is this the intention? It 
> would mean 
> losing precision in the replication.

Corrected.

>  
> > +}
> > +
> > +
> >  uint Field_new_decimal::is_equal(Create_field *new_field)
> >  {
> >    return ((new_field->sql_type == real_type()) &&
> > @@ -4087,6 +4149,25 @@ bool Field_float::send_binary(Protocol *
> >  }
> >  
> >  
> > +/**
> > +   Retrieve the field metadata for float fields.
> > +
> > +   Saves the pack length in the first byte.
> > +   The second byte is not used.
> > +
> > +   @param   first_byte   First byte of field metadata
> > +   @param   second_byte  Second byte of field metadata
> > +
> > +   @returns 0 success
> > +*/
> > +int Field_float::save_field_metadata(uchar *first_byte, 
> > +                                     uchar *second_byte)
> > +{
> > +  *first_byte= (uchar)pack_length();
> >   
> 
> Is the cast necessary?
> 
> > +  return 0;
> > +}
> > +
> > +
> >  void Field_float::sql_type(String &res) const
> >  {
> >    if (dec == NOT_FIXED_DEC)
> > @@ -4404,6 +4485,25 @@ void Field_double::sort_string(uchar *to
> >  }
> >  
> >  
> > +/*p*
> >   
> 
> Remove the "p"
> 
> > +   Retrieve the field metadata for double fields.
> >   
> 
> Saves, not retrieves?
> 
> > +
> > +   Saves the pack length in the first byte.
> > +   The second byte is not used.
> > +
> > +   @param   first_byte   First byte of field metadata
> > +   @param   second_byte  Second byte of field metadata
> > +
> > +   @returns 0 success
> > +*/
> > +int Field_double::save_field_metadata(uchar *first_byte, 
> > +                                      uchar *second_byte)
> > +{
> > +  *first_byte= (uchar)pack_length();
> > +  return 0;
> > +}
> > +
> > +
> >  void Field_double::sql_type(String &res) const
> >  {
> >    CHARSET_INFO *cs=res.charset();
> > @@ -6445,6 +6545,26 @@ const uchar *Field_string::unpack(uchar 
> >  }
> >  
> >  
> > +/**
> > +   Retrieve the field metadata for string fields.
> >   
> 
> Saves, not retrieves?
> 
> > +
> > +   Saves the real type in the first byte and the field 
> length in the 
> > +   second byte.
> > +
> > +   @param   first_byte   First byte of field metadata
> > +   @param   second_byte  Second byte of field metadata
> > +
> > +   @returns 0 success
> > +*/
> > +int Field_string::save_field_metadata(uchar *first_byte, 
> > +                                      uchar *second_byte)
> > +{
> > +  *first_byte= (uchar)real_type();
> > +  *second_byte= (uchar)field_length;
> >   
> 
> Are the casts necessary?
> 
> > +  return 0;
> > +}
> > +
> > +
> >  /*
> >    Compare two packed keys
> >  
> > @@ -6597,6 +6717,26 @@ Field *Field_string::new_field(MEM_ROOT 
> >  
> >  const uint Field_varstring::MAX_SIZE= UINT_MAX16;
> >  
> > +/**
> > +   Retrieve the field metadata for varstring fields.
> > +
> > +   Saves the field length in the first byte. Note: may consume
> > +   2 bytes. Caller must ensure second byte is contiguous with
> > +   first byte (e.g. array index 0,1).
> > +
> > +   @param   first_byte   First byte of field metadata
> > +   @param   second_byte  Second byte of field metadata
> > +
> > +   @returns 0 success
> > +*/
> > +int Field_varstring::save_field_metadata(uchar *first_byte, 
> > +                                         uchar *second_byte)
> > +{
> > +  char *ptr= (char *)first_byte;
> > +  int2store(ptr, field_length);
> > +  return 0;
> > +}
> >   
> 
> Here you are obviously not using the second byte (because it is not 
> needed) so it seems like you're needlessly passing the second 
> parameter 
> (just yet another reason to not use the second parameter).
> 
> And yes, I know the cast is necessary here (hopefully, Monty's patch 
> will eliminate this).

Corrected.

> 
> > +
> >  int Field_varstring::store(const char *from,uint 
> length,CHARSET_INFO *cs)
> >  {
> >    ASSERT_COLUMN_MARKED_FOR_WRITE;
> > @@ -7560,6 +7700,25 @@ int Field_blob::key_cmp(const uchar *a,c
> >  }
> >  
> >  
> > +/**
> > +   Retrieve the field metadata for blob fields.
> > +
> > +   Saves the pack length without the pointer in the first byte.
> > +   The second byte is not used.
> > +
> > +   @param   first_byte   First byte of field metadata
> > +   @param   second_byte  Second byte of field metadata
> > +
> > +   @returns 0 success
> > +*/
> > +int Field_blob::save_field_metadata(uchar *first_byte, 
> > +                                    uchar *second_byte)
> > +{
> > +  *first_byte= (uchar)pack_length_no_ptr();
> >   
> 
> Is the cast necessary? If you just want to get the lower byte of the 
> integral, using & 0xFF is a safer option. Please add an assertion to 
> ensure that the upper bytes of the returned value really is 
> zero, which 
> they should be.
> 
> > +  return 0;
> > +}
> > +
> > +
> >  uint32 Field_blob::sort_length() const
> >  {
> >    return (uint32) (current_thd->variables.max_sort_length + 
> > @@ -8145,6 +8304,26 @@ longlong Field_enum::val_int(void)
> >  }
> >  
> >  
> > +/**
> > +   Retrieve the field metadata for enum fields.
> > +
> > +   Saves the real type in the first byte and the pack 
> length in the 
> > +   second byte.
> > +
> > +   @param   first_byte   First byte of field metadata
> > +   @param   second_byte  Second byte of field metadata
> > +
> > +   @returns 0 success
> > +*/
> > +int Field_enum::save_field_metadata(uchar *first_byte, 
> > +                                    uchar *second_byte)
> > +{
> > +  *first_byte= (uchar)real_type();
> > +  *second_byte= (uchar)pack_length();
> >   
> 
> Are the casts necessary?
> 
> > +  return 0;
> > +}
> > +
> > +
> >  String *Field_enum::val_str(String *val_buffer 
> __attribute__((unused)),
> >  			    String *val_ptr)
> >  {
> > @@ -8678,6 +8857,47 @@ uint Field_bit::get_key_image(uchar *buf
> >    uint data_length = min(length, bytes_in_rec);
> >    memcpy(buff, ptr, data_length);
> >    return data_length + 1;
> > +}
> > +
> > +
> > +/**
> > +   Retrieve the field metadata for bit fields.
> > +
> > +   Saves the bit length in the first byte and the bytes in 
> rec in the 
> > +   second byte.
> > +
> > +   @param   first_byte   First byte of field metadata
> > +   @param   second_byte  Second byte of field metadata
> > +
> > +   @returns 0 success
> > +*/
> > +int Field_bit::save_field_metadata(uchar *first_byte, 
> > +                                   uchar *second_byte)
> > +{
> > +  *first_byte= (uchar)bit_len;
> > +  *second_byte= (uchar)bytes_in_rec;
> >   
> 
> Are the casts necessary? (In this case, I think they actually are.)
> 
> > +  return 0;
> > +}
> > +
> > +
> > +/**
> > +   Returns the number of bytes field uses in row-based replication 
> > +   row packed size.
> > +
> > +   This method is used in row-based replication to 
> determine the number
> > +   of bytes that the field consumes in the row record 
> format. This is
> > +   used to skip fields in the master that do not exist on 
> the slave.
> > +
> > +   @param   field_metadata   Encoded size in field metadata
> > +
> > +   @retval The size of the field based on the field metadata.
> > +*/
> > +uint Field_bit::pack_length_from_metadata(uint field_metadata)
> > +{
> > +  uint const from_len= (field_metadata >> 8U) & 0x00ff;
> > +  uint const from_bit_len= field_metadata & 0x00ff;
> > +  uint const source_size= from_len + ((from_bit_len > 0) ? 1 : 0);
> > +  return (source_size);
> >   
> 
> This means that it is possible to replicate a BIT(12) field 
> to a BIT(11) 
> field? Is this the intention?
> 
> >  }
> >  
> >  
> > diff -Nrup a/sql/field.h b/sql/field.h
> > --- a/sql/field.h	2007-07-29 18:10:24 -04:00
> > +++ b/sql/field.h	2007-08-09 22:08:08 -04:00
> > @@ -151,6 +151,13 @@ public:
> >      table, which is located on disk).
> >    */
> >    virtual uint32 pack_length_in_rec() const { return 
> pack_length(); }
> > +  virtual int field_metadata_size() const { return 0; }
> > +  virtual int save_field_metadata(uchar *first_byte, uchar 
> *second_byte)
> > +  { return 0; }
> > +  virtual int compatible_field_size(uint field_metadata);
> > +  virtual uint pack_length_from_metadata(uint field_metadata)
> > +  { return field_metadata; }
> >   
> 
> You returning the field_metadata when the function should return the 
> pack length? If this is just an arbitrary default you picked and the 
> function is not actually expected to be used, it is better to 
> make the 
> function a pure virtual functions.

See comments above and in code. 

> 
> > +  virtual uint row_pack_length() { return 0; }
> >   
> 
> Is it reasonable that the row pack length is 0? If it's not, and this 
> function always should be defined in a subclass, you should make it a 
> pure virtual function.
> 
> >  
> >    /*
> >      data_length() return the "real size" of the data in memory.
> > @@ -628,6 +635,10 @@ public:
> >    uint32 max_display_length() { return field_length; }
> >    uint size_of() const { return sizeof(*this); } 
> >    uint32 pack_length() const { return (uint32) bin_size; }
> > +  int field_metadata_size() const { return 2; }
> > +  int save_field_metadata(uchar *first_byte, uchar *second_byte);
> > +  uint pack_length_from_metadata(uint field_metadata);
> > +  uint row_pack_length() { return pack_length(); }
> >    uint is_equal(Create_field *new_field);
> >    virtual const uchar *unpack(uchar* to, const uchar 
> *from, uint param_data);
> >  };
> > @@ -834,6 +845,9 @@ public:
> >    int cmp(const uchar *,const uchar *);
> >    void sort_string(uchar *buff,uint length);
> >    uint32 pack_length() const { return sizeof(float); }
> > +  int field_metadata_size() const { return 1; }
> > +  int save_field_metadata(uchar *first_byte, uchar *second_byte);
> > +  uint row_pack_length() { return pack_length(); }
> >    void sql_type(String &str) const;
> >  };
> >  
> > @@ -871,6 +885,9 @@ public:
> >    int cmp(const uchar *,const uchar *);
> >    void sort_string(uchar *buff,uint length);
> >    uint32 pack_length() const { return sizeof(double); }
> > +  int field_metadata_size() const { return 1; }
> > +  int save_field_metadata(uchar *first_byte, uchar *second_byte);
> > +  uint row_pack_length() { return pack_length(); }
> >    void sql_type(String &str) const;
> >  };
> >  
> > @@ -1168,6 +1185,11 @@ public:
> >    uchar *pack(uchar *to, const uchar *from, uint 
> max_length=~(uint) 0);
> >    virtual const uchar *unpack(uchar* to, const uchar 
> *from, uint param_data);
> >    const uchar *unpack(uchar* to, const uchar *from);
> > +  int field_metadata_size() const { return 2; }
> > +  int save_field_metadata(uchar *first_byte, uchar *second_byte);
> > +  uint pack_length_from_metadata(uint field_metadata)
> > +  { return (field_metadata & 0x00ff); }
> > +  uint row_pack_length() { return (field_length + 1); }
> >    int pack_cmp(const uchar *a,const uchar *b,uint key_length,
> >                 my_bool insert_or_update);
> >    int pack_cmp(const uchar *b,uint key_length,my_bool 
> insert_or_update);
> > @@ -1214,6 +1236,9 @@ public:
> >  
> >    enum_field_types type() const { return MYSQL_TYPE_VARCHAR; }
> >    enum ha_base_keytype key_type() const;
> > +  int field_metadata_size() const { return 2; }
> > +  int save_field_metadata(uchar *first_byte, uchar *second_byte);
> > +  uint row_pack_length() { return field_length; }
> >    bool zero_pack() const { return 0; }
> >    int  reset(void) { bzero(ptr,field_length+length_bytes); 
> return 0; }
> >    uint32 pack_length() const { return (uint32) 
> field_length+length_bytes; }
> > @@ -1334,6 +1359,9 @@ public:
> >    */
> >    uint32 pack_length_no_ptr() const
> >    { return (uint32) (packlength); }
> > +  int field_metadata_size() const { return 1; }
> > +  int save_field_metadata(uchar *first_byte, uchar *second_byte);
> > +  uint row_pack_length() { return pack_length_no_ptr(); }
> >    uint32 sort_length() const;
> >    inline uint32 max_data_length() const
> >    {
> > @@ -1493,6 +1521,11 @@ public:
> >    void sql_type(String &str) const;
> >    uint size_of() const { return sizeof(*this); }
> >    enum_field_types real_type() const { return MYSQL_TYPE_ENUM; }
> > +  int field_metadata_size() const { return 2; }
> > +  int save_field_metadata(uchar *first_byte, uchar *second_byte);
> > +  uint pack_length_from_metadata(uint field_metadata)
> > +  { return (field_metadata & 0x00ff); }
> > +  uint row_pack_length() { return pack_length(); }
> >    virtual bool zero_pack() const { return 0; }
> >    bool optimize_range(uint idx, uint part) { return 0; }
> >    bool eq_def(Field *field);
> > @@ -1519,6 +1552,7 @@ public:
> >    int  store(const char *to,uint length,CHARSET_INFO *charset);
> >    int  store(double nr) { return 
> Field_set::store((longlong) nr, FALSE); }
> >    int  store(longlong nr, bool unsigned_val);
> > +
> >    virtual bool zero_pack() const { return 1; }
> >    String *val_str(String*,String *);
> >    void sql_type(String &str) const;
> > @@ -1582,6 +1616,11 @@ public:
> >    { get_key_image(buff, length, itRAW); }
> >    uint32 pack_length() const { return (uint32) 
> (field_length + 7) / 8; }
> >    uint32 pack_length_in_rec() const { return bytes_in_rec; }
> > +  int field_metadata_size() const { return 2; }
> > +  int save_field_metadata(uchar *first_byte, uchar *second_byte);
> > +  uint pack_length_from_metadata(uint field_metadata);
> > +  uint row_pack_length()
> > +  { return (bytes_in_rec + ((bit_len > 0) ? 1 : 0)); }
> >    void sql_type(String &str) const;
> >    uchar *pack(uchar *to, const uchar *from, uint 
> max_length=~(uint) 0);
> >    virtual const uchar *unpack(uchar *to, const uchar 
> *from, uint param_data);
> > diff -Nrup a/sql/log_event.cc b/sql/log_event.cc
> > --- a/sql/log_event.cc	2007-07-30 17:39:48 -04:00
> > +++ b/sql/log_event.cc	2007-08-09 22:08:08 -04:00
> > @@ -6391,35 +6391,9 @@ void Rows_log_event::print_helper(FILE *
> >  const int Table_map_log_event::calc_field_metadata_size()
> >  {
> >    DBUG_ENTER("Table_map_log_event::calc_field_metadata_size");
> > -  int size= 0;
> > +  m_field_metadata_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 + 2; // Store short int here.
> > -      break;
> > -    }
> > -    default:
> > -      break;
> > -    }
> > -  }
> > -  m_field_metadata_size= size;
> > +    m_field_metadata_size+= 
> m_table->s->field[i]->field_metadata_size();
> >    DBUG_PRINT("info", ("Table_map_log_event: %d bytes in 
> field metadata.",
> >                         (int)m_field_metadata_size));
> >    DBUG_RETURN(m_field_metadata_size);
> > @@ -6430,15 +6404,14 @@ const int Table_map_log_event::calc_fiel
> >    @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 
> > +  Table_map_log_event::calc_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.
> > +  extra data are added. The master then loops through all 
> of the fields in 
> > +  the table calling the method 
> Table_map_log_event::save_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 
> > @@ -6479,61 +6452,9 @@ int Table_map_log_event::save_field_meta
> >    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:
> > -    {
> > -      char *ptr= (char *)&m_field_metadata[index];
> > -      int2store(ptr, m_table->s->field[i]->field_length);
> > -      index= index + 2;
> > -      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;
> > -    }
> > +    
> m_table->s->field[i]->save_field_metadata(&m_field_metadata[index], 
> > +                                              
> &m_field_metadata[index+1]);
> > +    index+= m_table->s->field[i]->field_metadata_size();
> >   
> 
> If you do the changes I suggest above, these lines become:
> 
>   index+= 
> m_table->s->field[i]->save_field_metadata(&m_field_metadata[index]);
> 
> which means cutting the number of virtual calls into half and 
> simplifying the code significantly. Remember this piece of code is 
> called for each field in a table and for each statement, so this 
> improvement pays off pretty fast.
> 

Done.

> >    }
> >    DBUG_RETURN(0);
> >  }
> > diff -Nrup a/sql/rpl_utility.cc b/sql/rpl_utility.cc
> > --- a/sql/rpl_utility.cc	2007-07-30 17:39:49 -04:00
> > +++ b/sql/rpl_utility.cc	2007-08-09 22:08:09 -04:00
> > @@ -156,6 +156,25 @@ table_def::compatible_with(RELAY_LOG_INF
> >        rli->report(ERROR_LEVEL, ER_BINLOG_ROW_WRONG_TABLE_DEF,
> >                    ER(ER_BINLOG_ROW_WRONG_TABLE_DEF), buf);
> >      }
> > +    /*
> > +      Check the slave's field size against that of the master.
> > +    */
> > +    if (!error && 
> > +        
> !table->field[col]->compatible_field_size(m_field_metadata[col]))
> > +    {
> > +      error= 1;
> > +      char buf[256];
> > +      my_snprintf(buf, sizeof(buf), "Column %d size mismatch - "
> > +                  "master has size %d, %s.%s on slave has size %d."
> > +                  " Master's column size should be <= the slave's "
> > +                  "column size.", col,
> > +                  table->field[col]->pack_length_from_metadata(
> > +                                       m_field_metadata[col]),
> > +                  tsh->db.str, tsh->table_name.str, 
> > +                  table->field[col]->row_pack_length());
> > +      rli->report(ERROR_LEVEL, ER_BINLOG_ROW_WRONG_TABLE_DEF,
> > +                  ER(ER_BINLOG_ROW_WRONG_TABLE_DEF), buf);
> > +    }
> >    }
> >  
> >    return error;
> >
> >
> >   
> 
> 
> -- 
> Mats Kindahl
> Lead Software Developer
> Replication Team
> MySQL AB, www.mysql.com
> 
> 

Thread
bk commit into 5.1 tree (cbell:1.2548) BUG#22086cbell10 Aug
  • Re: bk commit into 5.1 tree (cbell:1.2548) BUG#22086Mats Kindahl10 Aug
    • RE: bk commit into 5.1 tree (cbell:1.2548) BUG#22086Chuck Bell10 Aug