List:Commits« Previous MessageNext Message »
From:Andrei Elkin Date:July 19 2007 7:56pm
Subject:bk commit into 5.1 tree (aelkin:1.2539)
View as plain text  
Below is the list of changes that have just been committed into a local
5.1 repository of elkin. When elkin 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-07-19 22:56:08+03:00, aelkin@stripped +22 -0
  wl#3228 master table def different than slave
  
  the background work for wl#3915. The latter testing stopped at bits (again) skipping. NUllable, set, enum work.

  mysql-test/extra/rpl_tests/rpl_extraMaster_Col.test@stripped, 2007-07-19 22:56:04+03:00, aelkin@stripped +404 -0
    New BitKeeper file ``mysql-test/extra/rpl_tests/rpl_extraMaster_Col.test''

  mysql-test/extra/rpl_tests/rpl_extraMaster_Col.test@stripped, 2007-07-19 22:56:04+03:00, aelkin@stripped +0 -0

  mysql-test/r/rpl_row_inexist_tbl.result@stripped, 2007-07-19 22:55:59+03:00, aelkin@stripped +2 -2
    wl3228

  mysql-test/r/rpl_row_log.result@stripped, 2007-07-19 22:55:59+03:00, aelkin@stripped +6 -6
    wl3228

  mysql-test/r/rpl_row_log_innodb.result@stripped, 2007-07-19 22:56:00+03:00, aelkin@stripped +6 -6
    wl3228

  mysql-test/r/rpl_row_max_relay_size.result@stripped, 2007-07-19 22:56:00+03:00, aelkin@stripped +10 -10
    wl3228

  mysql-test/r/rpl_row_until.result@stripped, 2007-07-19 22:56:00+03:00, aelkin@stripped +8 -8
    wl3228

  mysql-test/r/rpl_skip_error.result@stripped, 2007-07-19 22:56:00+03:00, aelkin@stripped +1 -1
    wl3228

  mysql-test/r/rpl_slave_skip.result@stripped, 2007-07-19 22:56:01+03:00, aelkin@stripped +2 -2
    wl3228

  mysql-test/t/binlog_row_mix_innodb_myisam.test@stripped, 2007-07-19 22:56:01+03:00, aelkin@stripped +1 -1
    wl3228

  mysql-test/t/rpl_colSize.test@stripped, 2007-07-19 22:56:04+03:00, aelkin@stripped +87 -0
    wl3228
    

  mysql-test/t/rpl_colSize.test@stripped, 2007-07-19 22:56:04+03:00, aelkin@stripped +0 -0

  mysql-test/t/rpl_extraColmaster_innodb-master.opt@stripped, 2007-07-19 22:56:04+03:00, aelkin@stripped +1 -0
    New BitKeeper file ``mysql-test/t/rpl_extraColmaster_innodb-master.opt''

  mysql-test/t/rpl_extraColmaster_innodb-master.opt@stripped, 2007-07-19 22:56:04+03:00, aelkin@stripped +0 -0

  mysql-test/t/rpl_extraColmaster_innodb-slave.opt@stripped, 2007-07-19 22:56:04+03:00, aelkin@stripped +1 -0
    New BitKeeper file ``mysql-test/t/rpl_extraColmaster_innodb-slave.opt''

  mysql-test/t/rpl_extraColmaster_innodb-slave.opt@stripped, 2007-07-19 22:56:04+03:00, aelkin@stripped +0 -0

  mysql-test/t/rpl_row_create_table.test@stripped, 2007-07-19 22:56:01+03:00, aelkin@stripped +5 -5
    wl3228

  mysql-test/t/rpl_row_flsh_tbls.test@stripped, 2007-07-19 22:56:01+03:00, aelkin@stripped +1 -1
    wl3228

  sql/field.cc@stripped, 2007-07-19 22:56:02+03:00, aelkin@stripped +119 -0
    wl3228

  sql/field.h@stripped, 2007-07-19 22:56:02+03:00, aelkin@stripped +32 -0
    wl3228

  sql/log_event.cc@stripped, 2007-07-19 22:56:02+03:00, aelkin@stripped +210 -8
    wl3228
    ---
    removing asserts and early return from copy_extra_record_fields

  sql/log_event.h@stripped, 2007-07-19 22:56:03+03:00, aelkin@stripped +10 -0
    wl3228

  sql/rpl_record.cc@stripped, 2007-07-19 22:56:03+03:00, aelkin@stripped +12 -3
    wl3228
    ---
    skipping master's extra field utilizing extended table_def class's method by wl#3228

  sql/rpl_rli.h@stripped, 2007-07-19 22:56:03+03:00, aelkin@stripped +10 -0
    wl3228

  sql/rpl_utility.cc@stripped, 2007-07-19 22:56:03+03:00, aelkin@stripped +55 -35
    wl3228
    ---
    correcting case MYSQL_TYPE_VARCHAR of table_def::get_field_size(). 

  sql/rpl_utility.h@stripped, 2007-07-19 22:56:04+03:00, aelkin@stripped +121 -5
    wl3228

diff -Nrup a/mysql-test/extra/rpl_tests/rpl_extraMaster_Col.test b/mysql-test/extra/rpl_tests/rpl_extraMaster_Col.test
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/mysql-test/extra/rpl_tests/rpl_extraMaster_Col.test	2007-07-19 22:56:04 +03:00
@@ -0,0 +1,404 @@
+#############################################################
+# Purpose: To test having extra columns on the master WL#3915
+# engine inspecific sourced part
+#############################################################
+
+# TODO: partition specific
+# -- source include/have_partition.inc
+
+########### Clean up ################
+--disable_warnings
+--disable_query_log
+DROP TABLE IF EXISTS  t1,t2,t3,t4,t31;
+
+--enable_query_log
+--enable_warnings
+
+#
+# Setup differently defined tables on master and slave
+#
+
+# Def on master: t (f_1 type_m_1,... f_s type_m_s, f_s+1, f_m)
+# Def on slave:  t (f_1 type_s_1,... f_s type_s_s)
+# where type_mi,type_si (0 < i-1 <s+1) pairs are compatible types (WL#3228)
+# Arbitrary paramaters of the test are:
+# 1. the tables type
+# 2. the types of the extra master's column f_s+1,..., f_m
+# 3. the numbers of common columns `s' 
+# 4. and  extra columns `m' are par
+#
+# optionally
+#
+# 5. vary the common columns type within compatible ranges.
+
+#
+# constant size column type:
+
+#BIGINT       
+#BLOB         
+#DATE         
+#DATETIME     
+#FLOAT        
+#INT, INTEGER 
+#LONGBLOB      
+#LONGTEXT     
+#MEDIUMBLOB   
+#MEDIUMINT    
+#MEDIUMTEXT   
+#REAL         
+#SMALLINT     
+#TEXT         
+#TIME         
+#TIMESTAMP    
+#TINYBLOB     
+#TINYINT      
+#TINYTEXT     
+#YEAR         
+
+# variable size column types:
+
+#BINARY(M)    
+#BIT(M)        
+#CHAR(M)      
+#DECIMAL(M,D) 
+#DOUBLE[P]    
+#ENUM         
+#FLOAT(p)     
+#NUMERIC(M,D) 
+#SET           
+#VARBINARY(M) 
+#VARCHAR(M)    
+#
+
+
+connection master;
+    eval CREATE TABLE t1 (f1 INT, f2 INT, f3 INT PRIMARY KEY, f4 CHAR(20),
+                      /* extra */
+                       f5 FLOAT DEFAULT '2.00', 
+                       f6 CHAR(4) DEFAULT 'TEST',
+		       f7 INT DEFAULT '0',
+		       f8 TEXT,
+		       f9 LONGBLOB,
+		       /* f10 BIT(63), BITS TODO: uncomment here and in all other places */
+		       f11 VARBINARY(64))
+                      ENGINE=$engine_type;
+
+#connection slave;
+   sync_slave_with_master;
+   alter table t1 drop f5, drop f6, drop f7, drop f8, drop f9, /* BITS TODO: drop f10,*/ drop f11;
+
+connection master;
+
+   INSERT into t1 values (1, 1, 1, 'first',
+                        1.0, 'yksi', 1, 'lounge of happiness', 'very fat blob', /* b'01010101010101', */ 0x123456);
+   INSERT into t1 values (2, 2, 2, 'second',
+                        2.0, 'kaks', 2, 'got stolen from the paradise', 'very fat blob', /* b'01010101010101', */ 0x123456),
+                       (3, 3, 3, 'third',
+                        3.0, 'kolm', 3, 'got stolen from the paradise', 'very fat blob', /* b'01010101010101', */ 0x123456);
+   update t1 set f4= 'next' where f1=1;
+   delete from t1 where f1=1;
+
+   select * from t1;
+
+
+#connection slave;
+   sync_slave_with_master;
+--replace_column 1 # 7 # 8 # 9 # 22 # 23 # 33 #
+--query_vertical show slave status;
+   select * from t1;
+
+
+### Altering table def scenario
+
+connection master;
+
+   eval CREATE TABLE t2 (f1 INT, f2 INT, f3 INT PRIMARY KEY, f4 CHAR(20),
+                      /* extra */
+                       f5 DOUBLE DEFAULT '2.00', 
+                       f6 ENUM('a', 'b', 'c') default 'a',
+		       f7 DECIMAL(17,9) default '1000.00',
+		       f8 MEDIUMBLOB,
+		       f9 NUMERIC(6,4) default '2000.00',
+		       f10 VARCHAR(1024),
+		       f11 BINARY(20) NOT NULL DEFAULT '\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0',
+		       f12 SET('a', 'b', 'c') default 'b')
+                       ENGINE=$engine_type;
+
+   eval CREATE TABLE t3 (f1 INT, f2 INT, f3 INT PRIMARY KEY, f4 CHAR(20),
+                      /* extra */
+                       f5 DOUBLE DEFAULT '2.00', 
+                       f6 ENUM('a', 'b', 'c') default 'a',
+		       f8 MEDIUMBLOB,
+		       f10 VARCHAR(1024),
+		       f11 BINARY(20) NOT NULL DEFAULT '\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0',
+		       f12 SET('a', 'b', 'c') default 'b')
+                       ENGINE=$engine_type;
+
+
+# no ENUM and SET
+    eval CREATE TABLE t4 (f1 INT, f2 INT, f3 INT PRIMARY KEY, f4 CHAR(20),
+                      /* extra */
+                       f5 DOUBLE DEFAULT '2.00', 
+		       f6 DECIMAL(17,9) default '1000.00',
+		       f7 MEDIUMBLOB,
+		       f8 NUMERIC(6,4) default '2000.00',
+		       f9 VARCHAR(1024),
+		       f10 BINARY(20) not null default '\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0',
+		       f11 CHAR(255))
+                       ENGINE=$engine_type;
+
+
+    eval CREATE TABLE t31 (f1 INT, f2 INT, f3 INT PRIMARY KEY, f4 CHAR(20),
+                       
+                       /* extra */
+
+                       f5  BIGINT,
+                       f6  BLOB,
+		       f7  DATE,
+		       f8  DATETIME,
+		       f9  FLOAT,
+		       f10 INT,
+		       f11 LONGBLOB,
+		       f12 LONGTEXT,
+		       f13 MEDIUMBLOB,
+		       f14 MEDIUMINT,
+		       f15 MEDIUMTEXT,
+		       f16 REAL,
+		       f17 SMALLINT,
+		       f18 TEXT,
+		       f19 TIME,
+		       f20 TIMESTAMP,
+		       f21 TINYBLOB,
+		       f22 TINYINT,
+		       f23 TINYTEXT,
+		       f24 YEAR,
+		       f25 BINARY(255),
+		       /* f26 BIT(64), */
+		       f27 CHAR(255),
+		       f28 DECIMAL(30,7),
+		       f29 DOUBLE,
+		       f30 ENUM ('a','b', 'c') default 'a',
+		       f31 FLOAT,
+		       f32 NUMERIC(17,9),
+		       f33 SET ('a', 'b', 'c') default 'b',
+		       f34 VARBINARY(1025),
+		       f35 VARCHAR(257)       
+                       ) ENGINE=$engine_type;
+
+#connection slave;
+    sync_slave_with_master;
+    alter table t2 drop f5, drop f6, drop f7, drop f8, drop f9, drop f10, drop f11, drop f12;
+    alter table t3 drop f5, drop f6, drop f8, drop f10, drop f11, drop f12;
+    alter table t4 drop f5, drop f6, drop f7, drop f8, drop f9, drop f10, drop f11;
+
+    alter table t31 
+       drop f5, drop f6, drop f7, drop f8, drop f9, drop f10, drop f11,
+       drop f12, drop f13, drop f14, drop f15, drop f16, drop f17, drop f18,
+       drop f19, drop f20, drop f21, drop f22, drop f23, drop f24, drop f25,
+       /* BITS TODO: uncomment! drop f26,*/ drop f27, drop f28, drop f29, drop f30, drop f31, drop f32,
+       drop f33, drop f34, drop f35;
+                 
+
+
+connection master;
+   INSERT into t2 set f1=1, f2=1, f3=1, f4='first', f8='f8: medium size blob', f10='f10: some var char';
+   INSERT into t2 values (2, 2, 2, 'second',
+       2.0, 'b', 2000.0002, 'f8: medium size blob', 2000, 'f10: some var char', '01234567', 'c'),
+                       (3, 3, 3, 'third',
+       3.0, 'b', 3000.0003, 'f8: medium size blob', 3000, 'f10: some var char', '01234567', 'c');
+   INSERT into t3 set f1=1, f2=1, f3=1, f4='first', f10='f10: some var char';
+   INSERT into t4 set f1=1, f2=1, f3=1, f4='first', f7='f7: medium size blob', f10='f10: binary data';
+   INSERT into t31 set f1=1, f2=1, f3=1, f4='first';
+   INSERT into t31 set f1=1, f2=1, f3=2, f4='second',
+     f9=2.2,  f10='seven samurai', f28=222.222, f35='222';
+   INSERT into t31 values (1, 1, 3, 'third',
+      /* f5  BIGINT,  */            333333333333333333333333,
+      /* f6  BLOB,  */              '3333333333333333333333',
+      /* f7  DATE,  */              '2007-07-18',
+      /* f8  DATETIME,  */          "2007-07-18",
+      /* f9  FLOAT,  */             3.33333333,
+      /* f10 INT,  */               333333333,
+      /* f11 LONGBLOB,  */          '3333333333333333333',
+      /* f12 LONGTEXT,  */          '3333333333333333333',
+      /* f13 MEDIUMBLOB,  */        '3333333333333333333',
+      /* f14 MEDIUMINT,  */         33,
+      /* f15 MEDIUMTEXT,  */        3.3,
+      /* f16 REAL,  */              3.3,
+      /* f17 SMALLINT,  */          3,
+      /* f18 TEXT,  */              '33',
+      /* f19 TIME,  */              '2:59:58.999',
+      /* f20 TIMESTAMP,  */         20000303000000,
+      /* f21 TINYBLOB,  */          '3333',
+      /* f22 TINYINT,  */           3,
+      /* f23 TINYTEXT,  */          '3',
+      /* f24 YEAR,  */              3000,
+      /* f25 BINARY(255),  */       'three_33333',
+      /* f26 BIT(64),  */           /* b'011', */
+      /* f27 CHAR(255),  */         'three',
+      /* f28 DECIMAL(30,7),  */     3.333,
+      /* f29 DOUBLE,  */            3.333333333333333333333333333,
+      /* f30 ENUM ('a','b','c')*/   'c',
+      /* f31 FLOAT,  */             3.0,
+      /* f32 NUMERIC(17,9),  */     3.3333,
+      /* f33 SET ('a','b','c'),*/   'c',
+      /*f34 VARBINARY(1025),*/      '3333 minus 3',
+      /*f35 VARCHAR(257),*/         'three times three'
+      );
+   
+   INSERT into t31 values (1, 1, 4, 'fourth',
+       /* f5  BIGINT,  */            333333333333333333333333,
+       /* f6  BLOB,  */              '3333333333333333333333',
+       /* f7  DATE,  */              '2007-07-18',
+       /* f8  DATETIME,  */          "2007-07-18",
+       /* f9  FLOAT,  */             3.33333333,
+       /* f10 INT,  */               333333333,
+       /* f11 LONGBLOB,  */          '3333333333333333333',
+       /* f12 LONGTEXT,  */          '3333333333333333333',
+       /* f13 MEDIUMBLOB,  */        '3333333333333333333',
+       /* f14 MEDIUMINT,  */         33,
+       /* f15 MEDIUMTEXT,  */        3.3,
+       /* f16 REAL,  */              3.3,
+       /* f17 SMALLINT,  */          3,
+       /* f18 TEXT,  */              '33',
+       /* f19 TIME,  */              '2:59:58.999',
+       /* f20 TIMESTAMP,  */         20000303000000,
+       /* f21 TINYBLOB,  */          '3333',
+       /* f22 TINYINT,  */           3,
+       /* f23 TINYTEXT,  */          '3',
+       /* f24 YEAR,  */              3000,
+       /* f25 BINARY(255),  */       'three_33333',
+       /* f26 BIT(64),  */           /* b'011', */
+       /* f27 CHAR(255),  */         'three',
+       /* f28 DECIMAL(30,7),  */     3.333,
+       /* f29 DOUBLE,  */            3.333333333333333333333333333,
+       /* f30 ENUM ('a','b','c')*/   'c',
+       /* f31 FLOAT,  */             3.0,
+       /* f32 NUMERIC(17,9),  */     3.3333,
+       /* f33 SET ('a','b','c'),*/   'c',
+       /*f34 VARBINARY(1025),*/      '3333 minus 3',
+       /*f35 VARCHAR(257),*/         'three times three'
+       ),
+   (1, 1, 5, 'fifth',
+       /* f5  BIGINT,  */            333333333333333333333333,
+       /* f6  BLOB,  */              '3333333333333333333333',
+       /* f7  DATE,  */              '2007-07-18',
+       /* f8  DATETIME,  */          "2007-07-18",
+       /* f9  FLOAT,  */             3.33333333,
+       /* f10 INT,  */               333333333,
+       /* f11 LONGBLOB,  */          '3333333333333333333',
+       /* f12 LONGTEXT,  */          '3333333333333333333',
+       /* f13 MEDIUMBLOB,  */        '3333333333333333333',
+       /* f14 MEDIUMINT,  */         33,
+       /* f15 MEDIUMTEXT,  */        3.3,
+       /* f16 REAL,  */              3.3,
+       /* f17 SMALLINT,  */          3,
+       /* f18 TEXT,  */              '33',
+       /* f19 TIME,  */              '2:59:58.999',
+       /* f20 TIMESTAMP,  */         20000303000000,
+       /* f21 TINYBLOB,  */          '3333',
+       /* f22 TINYINT,  */           3,
+       /* f23 TINYTEXT,  */          '3',
+       /* f24 YEAR,  */              3000,
+       /* f25 BINARY(255),  */       'three_33333',
+       /* f26 BIT(64),  */           /* b'011', */
+       /* f27 CHAR(255),  */         'three',
+       /* f28 DECIMAL(30,7),  */     3.333,
+       /* f29 DOUBLE,  */            3.333333333333333333333333333,
+       /* f30 ENUM ('a','b','c')*/   'c',
+       /* f31 FLOAT,  */             3.0,
+       /* f32 NUMERIC(17,9),  */     3.3333,
+       /* f33 SET ('a','b','c'),*/   'c',
+       /*f34 VARBINARY(1025),*/      '3333 minus 3',
+       /*f35 VARCHAR(257),*/         'three times three'
+       ),
+   (1, 1, 6, 'sixth',
+       /* f5  BIGINT,  */            NULL,
+       /* f6  BLOB,  */              '3333333333333333333333',
+       /* f7  DATE,  */              '2007-07-18',
+       /* f8  DATETIME,  */          "2007-07-18",
+       /* f9  FLOAT,  */             3.33333333,
+       /* f10 INT,  */               333333333,
+       /* f11 LONGBLOB,  */          '3333333333333333333',
+       /* f12 LONGTEXT,  */          '3333333333333333333',
+       /* f13 MEDIUMBLOB,  */        '3333333333333333333',
+       /* f14 MEDIUMINT,  */         33,
+       /* f15 MEDIUMTEXT,  */        3.3,
+       /* f16 REAL,  */              3.3,
+       /* f17 SMALLINT,  */          3,
+       /* f18 TEXT,  */              '33',
+       /* f19 TIME,  */              '2:59:58.999',
+       /* f20 TIMESTAMP,  */         20000303000000,
+       /* f21 TINYBLOB,  */          '3333',
+       /* f22 TINYINT,  */           3,
+       /* f23 TINYTEXT,  */          '3',
+       /* f24 YEAR,  */              3000,
+       /* f25 BINARY(255),  */       'three_33333',
+       /* f26 BIT(64),  */           /* b'011',*/
+       /* f27 CHAR(255),  */         'three',
+       /* f28 DECIMAL(30,7),  */     3.333,
+       /* f29 DOUBLE,  */            3.333333333333333333333333333,
+       /* f30 ENUM ('a','b','c')*/   'c',
+       /* f31 FLOAT,  */             3.0,
+       /* f32 NUMERIC(17,9),  */     3.3333,
+       /* f33 SET ('a','b','c'),*/   'c',
+       /*f34 VARBINARY(1025),*/      '3333 minus 3',
+       /*f35 VARCHAR(257),*/         NULL
+       );
+   
+#connection slave;
+   sync_slave_with_master;
+
+   select * from t1;
+   select * from t2;
+   select * from t3;
+   select * from t4;
+   select * from t31;
+   
+connection master;
+
+   update t31 set f5=555555555555555 where f3=6;
+
+#connection slave;
+   sync_slave_with_master;
+connection master;
+   update t31 set f2=2 where f3=2;
+#connection slave;
+   sync_slave_with_master;
+connection master;
+   update t31 set f1=NULL where f3=1;
+#connection slave;
+   sync_slave_with_master;
+connection master;
+   update t31 set f3=NULL, f27=NULL, f35='f35 new value' where f3=3;
+#connection slave;
+   sync_slave_with_master;
+   select * from t31;
+connection master;
+   delete from t1;
+   delete from t2;
+   delete from t3;
+   delete from t4;
+   delete from t31;
+#connection slave;
+   sync_slave_with_master;
+   select * from t31;
+
+--replace_result $MASTER_MYPORT MASTER_PORT
+--replace_column 1 # 7 # 8 # 9 # 22 # 23 # 33 #
+--query_vertical show slave status;
+
+#### Clean Up ####
+
+connection master;
+--disable_warnings
+--disable_query_log
+  DROP TABLE t1,t2,t3,t4,t31;
+
+#connection slave;
+  sync_slave_with_master;
+--enable_query_log
+--enable_warnings
+
+# END of the tests
+
+
diff -Nrup a/mysql-test/r/rpl_row_inexist_tbl.result b/mysql-test/r/rpl_row_inexist_tbl.result
--- a/mysql-test/r/rpl_row_inexist_tbl.result	2007-06-11 23:15:21 +03:00
+++ b/mysql-test/r/rpl_row_inexist_tbl.result	2007-07-19 22:55:59 +03:00
@@ -24,7 +24,7 @@ Master_User	root
 Master_Port	MASTER_PORT
 Connect_Retry	1
 Master_Log_File	master-bin.000001
-Read_Master_Log_Pos	597
+Read_Master_Log_Pos	605
 Relay_Log_File	#
 Relay_Log_Pos	#
 Relay_Master_Log_File	master-bin.000001
@@ -39,7 +39,7 @@ Replicate_Wild_Ignore_Table	
 Last_Errno	1146
 Last_Error	Error 'Table 'test.t1' doesn't exist' on opening table `test`.`t1`
 Skip_Counter	0
-Exec_Master_Log_Pos	524
+Exec_Master_Log_Pos	530
 Relay_Log_Space	#
 Until_Condition	None
 Until_Log_File	
diff -Nrup a/mysql-test/r/rpl_row_log.result b/mysql-test/r/rpl_row_log.result
--- a/mysql-test/r/rpl_row_log.result	2007-07-12 10:19:24 +03:00
+++ b/mysql-test/r/rpl_row_log.result	2007-07-19 22:55:59 +03:00
@@ -208,13 +208,13 @@ master-bin.000002	#	Table_map	1	#	table_
 master-bin.000002	#	Write_rows	1	#	table_id: # flags: STMT_END_F
 show binary logs;
 Log_name	File_size
-master-bin.000001	1260
-master-bin.000002	377
+master-bin.000001	1266
+master-bin.000002	379
 start slave;
 show binary logs;
 Log_name	File_size
-slave-bin.000001	1358
-slave-bin.000002	278
+slave-bin.000001	1364
+slave-bin.000002	280
 show binlog events in 'slave-bin.000001' from 4;
 Log_name	Pos	Event_type	Server_id	End_log_pos	Info
 slave-bin.000001	#	Format_desc	2	#	Server ver: VERSION, Binlog ver: 4
@@ -240,7 +240,7 @@ Master_User	root
 Master_Port	MASTER_PORT
 Connect_Retry	1
 Master_Log_File	master-bin.000002
-Read_Master_Log_Pos	377
+Read_Master_Log_Pos	379
 Relay_Log_File	#
 Relay_Log_Pos	#
 Relay_Master_Log_File	master-bin.000002
@@ -255,7 +255,7 @@ Replicate_Wild_Ignore_Table	
 Last_Errno	0
 Last_Error	
 Skip_Counter	0
-Exec_Master_Log_Pos	377
+Exec_Master_Log_Pos	379
 Relay_Log_Space	#
 Until_Condition	None
 Until_Log_File	
diff -Nrup a/mysql-test/r/rpl_row_log_innodb.result b/mysql-test/r/rpl_row_log_innodb.result
--- a/mysql-test/r/rpl_row_log_innodb.result	2007-07-12 10:19:25 +03:00
+++ b/mysql-test/r/rpl_row_log_innodb.result	2007-07-19 22:56:00 +03:00
@@ -213,13 +213,13 @@ master-bin.000002	#	Write_rows	1	#	table
 master-bin.000002	#	Xid	1	#	COMMIT /* XID */
 show binary logs;
 Log_name	File_size
-master-bin.000001	1314
-master-bin.000002	404
+master-bin.000001	1320
+master-bin.000002	406
 start slave;
 show binary logs;
 Log_name	File_size
-slave-bin.000001	1412
-slave-bin.000002	305
+slave-bin.000001	1418
+slave-bin.000002	307
 show binlog events in 'slave-bin.000001' from 4;
 Log_name	Pos	Event_type	Server_id	End_log_pos	Info
 slave-bin.000001	#	Format_desc	2	#	Server ver: VERSION, Binlog ver: 4
@@ -248,7 +248,7 @@ Master_User	root
 Master_Port	MASTER_PORT
 Connect_Retry	1
 Master_Log_File	master-bin.000002
-Read_Master_Log_Pos	404
+Read_Master_Log_Pos	406
 Relay_Log_File	#
 Relay_Log_Pos	#
 Relay_Master_Log_File	master-bin.000002
@@ -263,7 +263,7 @@ Replicate_Wild_Ignore_Table	
 Last_Errno	0
 Last_Error	
 Skip_Counter	0
-Exec_Master_Log_Pos	404
+Exec_Master_Log_Pos	406
 Relay_Log_Space	#
 Until_Condition	None
 Until_Log_File	
diff -Nrup a/mysql-test/r/rpl_row_max_relay_size.result b/mysql-test/r/rpl_row_max_relay_size.result
--- a/mysql-test/r/rpl_row_max_relay_size.result	2007-06-11 23:15:21 +03:00
+++ b/mysql-test/r/rpl_row_max_relay_size.result	2007-07-19 22:56:00 +03:00
@@ -30,7 +30,7 @@ Master_User	root
 Master_Port	MASTER_PORT
 Connect_Retry	1
 Master_Log_File	master-bin.000001
-Read_Master_Log_Pos	58668
+Read_Master_Log_Pos	60268
 Relay_Log_File	#
 Relay_Log_Pos	#
 Relay_Master_Log_File	master-bin.000001
@@ -45,7 +45,7 @@ Replicate_Wild_Ignore_Table	
 Last_Errno	0
 Last_Error	
 Skip_Counter	0
-Exec_Master_Log_Pos	58668
+Exec_Master_Log_Pos	60268
 Relay_Log_Space	#
 Until_Condition	None
 Until_Log_File	
@@ -78,7 +78,7 @@ Master_User	root
 Master_Port	MASTER_PORT
 Connect_Retry	1
 Master_Log_File	master-bin.000001
-Read_Master_Log_Pos	58668
+Read_Master_Log_Pos	60268
 Relay_Log_File	#
 Relay_Log_Pos	#
 Relay_Master_Log_File	master-bin.000001
@@ -93,7 +93,7 @@ Replicate_Wild_Ignore_Table	
 Last_Errno	0
 Last_Error	
 Skip_Counter	0
-Exec_Master_Log_Pos	58668
+Exec_Master_Log_Pos	60268
 Relay_Log_Space	#
 Until_Condition	None
 Until_Log_File	
@@ -126,7 +126,7 @@ Master_User	root
 Master_Port	MASTER_PORT
 Connect_Retry	1
 Master_Log_File	master-bin.000001
-Read_Master_Log_Pos	58668
+Read_Master_Log_Pos	60268
 Relay_Log_File	#
 Relay_Log_Pos	#
 Relay_Master_Log_File	master-bin.000001
@@ -141,7 +141,7 @@ Replicate_Wild_Ignore_Table	
 Last_Errno	0
 Last_Error	
 Skip_Counter	0
-Exec_Master_Log_Pos	58668
+Exec_Master_Log_Pos	60268
 Relay_Log_Space	#
 Until_Condition	None
 Until_Log_File	
@@ -217,7 +217,7 @@ Master_User	root
 Master_Port	MASTER_PORT
 Connect_Retry	1
 Master_Log_File	master-bin.000001
-Read_Master_Log_Pos	58754
+Read_Master_Log_Pos	60354
 Relay_Log_File	#
 Relay_Log_Pos	#
 Relay_Master_Log_File	master-bin.000001
@@ -232,7 +232,7 @@ Replicate_Wild_Ignore_Table	
 Last_Errno	0
 Last_Error	
 Skip_Counter	0
-Exec_Master_Log_Pos	58754
+Exec_Master_Log_Pos	60354
 Relay_Log_Space	#
 Until_Condition	None
 Until_Log_File	
@@ -261,7 +261,7 @@ Master_User	root
 Master_Port	MASTER_PORT
 Connect_Retry	1
 Master_Log_File	master-bin.000001
-Read_Master_Log_Pos	58830
+Read_Master_Log_Pos	60430
 Relay_Log_File	#
 Relay_Log_Pos	#
 Relay_Master_Log_File	master-bin.000001
@@ -276,7 +276,7 @@ Replicate_Wild_Ignore_Table	
 Last_Errno	0
 Last_Error	
 Skip_Counter	0
-Exec_Master_Log_Pos	58830
+Exec_Master_Log_Pos	60430
 Relay_Log_Space	#
 Until_Condition	None
 Until_Log_File	
diff -Nrup a/mysql-test/r/rpl_row_until.result b/mysql-test/r/rpl_row_until.result
--- a/mysql-test/r/rpl_row_until.result	2007-06-11 23:15:22 +03:00
+++ b/mysql-test/r/rpl_row_until.result	2007-07-19 22:56:00 +03:00
@@ -26,7 +26,7 @@ Master_User	root
 Master_Port	MASTER_PORT
 Connect_Retry	1
 Master_Log_File	master-bin.000001
-Read_Master_Log_Pos	744
+Read_Master_Log_Pos	750
 Relay_Log_File	#
 Relay_Log_Pos	#
 Relay_Master_Log_File	master-bin.000001
@@ -41,7 +41,7 @@ Replicate_Wild_Ignore_Table	
 Last_Errno	0
 Last_Error	
 Skip_Counter	0
-Exec_Master_Log_Pos	315
+Exec_Master_Log_Pos	317
 Relay_Log_Space	#
 Until_Condition	Master
 Until_Log_File	master-bin.000001
@@ -72,7 +72,7 @@ Master_User	root
 Master_Port	MASTER_PORT
 Connect_Retry	1
 Master_Log_File	master-bin.000001
-Read_Master_Log_Pos	744
+Read_Master_Log_Pos	750
 Relay_Log_File	#
 Relay_Log_Pos	#
 Relay_Master_Log_File	master-bin.000001
@@ -87,7 +87,7 @@ Replicate_Wild_Ignore_Table	
 Last_Errno	0
 Last_Error	
 Skip_Counter	0
-Exec_Master_Log_Pos	315
+Exec_Master_Log_Pos	317
 Relay_Log_Space	#
 Until_Condition	Master
 Until_Log_File	master-no-such-bin.000001
@@ -116,7 +116,7 @@ Master_User	root
 Master_Port	MASTER_PORT
 Connect_Retry	1
 Master_Log_File	master-bin.000001
-Read_Master_Log_Pos	744
+Read_Master_Log_Pos	750
 Relay_Log_File	#
 Relay_Log_Pos	#
 Relay_Master_Log_File	master-bin.000001
@@ -131,7 +131,7 @@ Replicate_Wild_Ignore_Table	
 Last_Errno	0
 Last_Error	
 Skip_Counter	0
-Exec_Master_Log_Pos	590
+Exec_Master_Log_Pos	594
 Relay_Log_Space	#
 Until_Condition	Relay
 Until_Log_File	slave-relay-bin.000004
@@ -158,7 +158,7 @@ Master_User	root
 Master_Port	MASTER_PORT
 Connect_Retry	1
 Master_Log_File	master-bin.000001
-Read_Master_Log_Pos	744
+Read_Master_Log_Pos	750
 Relay_Log_File	#
 Relay_Log_Pos	#
 Relay_Master_Log_File	master-bin.000001
@@ -173,7 +173,7 @@ Replicate_Wild_Ignore_Table	
 Last_Errno	0
 Last_Error	
 Skip_Counter	0
-Exec_Master_Log_Pos	744
+Exec_Master_Log_Pos	750
 Relay_Log_Space	#
 Until_Condition	Master
 Until_Log_File	master-bin.000001
diff -Nrup a/mysql-test/r/rpl_skip_error.result b/mysql-test/r/rpl_skip_error.result
--- a/mysql-test/r/rpl_skip_error.result	2007-06-25 03:35:08 +03:00
+++ b/mysql-test/r/rpl_skip_error.result	2007-07-19 22:56:00 +03:00
@@ -32,5 +32,5 @@ a
 3
 show slave status;
 Slave_IO_State	Master_Host	Master_User	Master_Port	Connect_Retry	Master_Log_File	Read_Master_Log_Pos	Relay_Log_File	Relay_Log_Pos	Relay_Master_Log_File	Slave_IO_Running	Slave_SQL_Running	Replicate_Do_DB	Replicate_Ignore_DB	Replicate_Do_Table	Replicate_Ignore_Table	Replicate_Wild_Do_Table	Replicate_Wild_Ignore_Table	Last_Errno	Last_Error	Skip_Counter	Exec_Master_Log_Pos	Relay_Log_Space	Until_Condition	Until_Log_File	Until_Log_Pos	Master_SSL_Allowed	Master_SSL_CA_File	Master_SSL_CA_Path	Master_SSL_Cert	Master_SSL_Cipher	Master_SSL_Key	Seconds_Behind_Master	Master_SSL_Verify_Server_Cert	Last_IO_Errno	Last_IO_Error	Last_SQL_Errno	Last_SQL_Error
-#	127.0.0.1	root	MASTER_PORT	1	master-bin.000001	776	#	#	master-bin.000001	Yes	Yes							0		0	776	#	None		0	No						#	No	0		0	
+#	127.0.0.1	root	MASTER_PORT	1	master-bin.000001	786	#	#	master-bin.000001	Yes	Yes							0		0	786	#	None		0	No						#	No	0		0	
 drop table t1;
diff -Nrup a/mysql-test/r/rpl_slave_skip.result b/mysql-test/r/rpl_slave_skip.result
--- a/mysql-test/r/rpl_slave_skip.result	2007-06-13 16:16:26 +03:00
+++ b/mysql-test/r/rpl_slave_skip.result	2007-07-19 22:56:01 +03:00
@@ -44,7 +44,7 @@ Master_User	root
 Master_Port	MASTER_PORT
 Connect_Retry	1
 Master_Log_File	master-bin.000001
-Read_Master_Log_Pos	714
+Read_Master_Log_Pos	722
 Relay_Log_File	#
 Relay_Log_Pos	#
 Relay_Master_Log_File	master-bin.000001
@@ -59,7 +59,7 @@ Replicate_Wild_Ignore_Table	
 Last_Errno	0
 Last_Error	
 Skip_Counter	0
-Exec_Master_Log_Pos	484
+Exec_Master_Log_Pos	488
 Relay_Log_Space	#
 Until_Condition	Master
 Until_Log_File	master-bin.000001
diff -Nrup a/mysql-test/t/binlog_row_mix_innodb_myisam.test b/mysql-test/t/binlog_row_mix_innodb_myisam.test
--- a/mysql-test/t/binlog_row_mix_innodb_myisam.test	2007-06-09 08:55:02 +03:00
+++ b/mysql-test/t/binlog_row_mix_innodb_myisam.test	2007-07-19 22:56:01 +03:00
@@ -20,7 +20,7 @@
 # ER_SERVER_SHUTDOWN (i.e. disconnection just rolls back transaction
 # and does not make slave to stop)
 flush logs;
---exec $MYSQL_BINLOG --start-position=520 $MYSQLTEST_VARDIR/log/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/mix_innodb_myisam_binlog.output
+--exec $MYSQL_BINLOG --start-position=522 $MYSQLTEST_VARDIR/log/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/mix_innodb_myisam_binlog.output
 --replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
 eval select
 (@a:=load_file("$MYSQLTEST_VARDIR/tmp/mix_innodb_myisam_binlog.output"))
diff -Nrup a/mysql-test/t/rpl_colSize.test b/mysql-test/t/rpl_colSize.test
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/mysql-test/t/rpl_colSize.test	2007-07-19 22:56:04 +03:00
@@ -0,0 +1,87 @@
+##################################################################
+# 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/have_binlog_format_row.inc
+-- source include/master-slave.inc
+
+--disable_warnings
+DROP TABLE IF EXISTS t1;
+--enable_warnings
+
+--echo **** Testing WL#3228 changes. ****
+--echo *** Create "wider" table on slave ***
+sync_slave_with_master;
+STOP SLAVE;
+RESET SLAVE;
+
+eval CREATE TABLE t1 (
+  a float     (47),
+  b double    (143,9),
+  c decimal   (65,30),
+  d numeric   (4,0),
+  e bit       (32),
+  f char      (21),
+  g varchar   (1300),
+  h binary    (33),
+  j varbinary (200),
+  k enum      ('5','6','7', '8','9','0'),
+  l set       ('1','2','3','4','5','6','7','8','9','0','11','12','13','14','15','16','17','18','19','21','22','23','24','25','26','27','28','29')
+);
+
+--echo *** Create same table on master but with narrow columns ***
+connection master;
+eval CREATE TABLE t1 (
+  a float     (44),
+  b double    (10,3),
+  c decimal   (10,2),
+  d numeric   (3,0),
+  e bit       (20),
+  f char      (10),
+  g varchar   (100),
+  h binary    (20),
+  j varbinary (20),
+  k enum      ('5','6','7'),
+  l set       ('1','2','3','4','5','6','7','8','9','0')
+);
+
+RESET MASTER;
+
+--echo *** Start replication ***
+connection slave;
+START SLAVE;
+
+--echo *** Insert data on master and display it. ***
+connection master;
+
+INSERT INTO t1 () VALUES (
+  17.567, 
+  2.123, 
+  10.20, 
+  125,
+  32,
+  'TEST',
+  'This is a test',
+  'binary data',
+  'more binary data',
+  '6',
+  '7');
+
+SELECT * FROM t1 ORDER BY a;
+
+--echo *** Select data from slave to compare ***
+sync_slave_with_master;
+connection slave;
+
+SELECT * FROM t1 ORDER BY a;
+
+--echo *** Cleanup  ***
+connection master;
+DROP TABLE t1;
+sync_slave_with_master;
+
+# END 5.1 Test Case
diff -Nrup a/mysql-test/t/rpl_extraColmaster_innodb-master.opt b/mysql-test/t/rpl_extraColmaster_innodb-master.opt
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/mysql-test/t/rpl_extraColmaster_innodb-master.opt	2007-07-19 22:56:04 +03:00
@@ -0,0 +1 @@
+--innodb
diff -Nrup a/mysql-test/t/rpl_extraColmaster_innodb-slave.opt b/mysql-test/t/rpl_extraColmaster_innodb-slave.opt
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/mysql-test/t/rpl_extraColmaster_innodb-slave.opt	2007-07-19 22:56:04 +03:00
@@ -0,0 +1 @@
+--innodb
diff -Nrup a/mysql-test/t/rpl_row_create_table.test b/mysql-test/t/rpl_row_create_table.test
--- a/mysql-test/t/rpl_row_create_table.test	2007-06-06 20:48:13 +03:00
+++ b/mysql-test/t/rpl_row_create_table.test	2007-07-19 22:56:01 +03:00
@@ -72,7 +72,7 @@ CREATE TABLE t7 (UNIQUE(b)) SELECT a,b F
 # Shouldn't be written to the binary log
 --replace_column 1 # 4 #
 --replace_regex /\/\* xid=.* \*\//\/* XID *\// /table_id: [0-9]+/table_id: #/
-SHOW BINLOG EVENTS FROM 1098;
+SHOW BINLOG EVENTS FROM 1017;
 
 # Test that INSERT-SELECT works the same way as for SBR.
 CREATE TABLE t7 (a INT, b INT UNIQUE);
@@ -82,7 +82,7 @@ SELECT * FROM t7 ORDER BY a,b;
 # Should be written to the binary log
 --replace_column 1 # 4 #
 --replace_regex /\/\* xid=.* \*\//\/* XID *\// /table_id: [0-9]+/table_id: #/
-SHOW BINLOG EVENTS FROM 1098;
+SHOW BINLOG EVENTS FROM 1017;
 sync_slave_with_master;
 SELECT * FROM t7 ORDER BY a,b;
 
@@ -94,7 +94,7 @@ INSERT INTO t7 SELECT a,b FROM tt4;
 ROLLBACK;
 --replace_column 1 # 4 #
 --replace_regex /\/\* xid=.* \*\//\/* XID *\// /table_id: [0-9]+/table_id: #/
-SHOW BINLOG EVENTS FROM 1294;
+SHOW BINLOG EVENTS FROM 1242;
 SELECT * FROM t7 ORDER BY a,b;
 sync_slave_with_master;
 SELECT * FROM t7 ORDER BY a,b;
@@ -110,7 +110,7 @@ CREATE TEMPORARY TABLE tt7 SELECT 1;
 --query_vertical SHOW CREATE TABLE t9
 --replace_column 1 # 4 #
 --replace_regex /\/\* xid=.* \*\//\/* XID *\// /table_id: [0-9]+/table_id: #/
-SHOW BINLOG EVENTS FROM 1390;
+SHOW BINLOG EVENTS FROM 1396;
 sync_slave_with_master;
 --echo **** On Slave ****
 --query_vertical SHOW CREATE TABLE t8
@@ -227,7 +227,7 @@ ROLLBACK;
 SELECT * FROM t2 ORDER BY a;
 --replace_column 1 # 4 #
 --replace_regex /\/\* xid=.* \*\//\/* XID *\// /Server ver: .*, Binlog ver: .*/Server ver: #, Binlog ver: #/ /table_id: [0-9]+/table_id: #/
-SHOW BINLOG EVENTS FROM 631;
+SHOW BINLOG EVENTS FROM 637;
 sync_slave_with_master;
 SELECT * FROM t2 ORDER BY a;
 
diff -Nrup a/mysql-test/t/rpl_row_flsh_tbls.test b/mysql-test/t/rpl_row_flsh_tbls.test
--- a/mysql-test/t/rpl_row_flsh_tbls.test	2007-03-29 22:37:59 +03:00
+++ b/mysql-test/t/rpl_row_flsh_tbls.test	2007-07-19 22:56:01 +03:00
@@ -1,7 +1,7 @@
 # depends on the binlog output
 -- source include/have_binlog_format_row.inc
 
-let $rename_event_pos= 619;
+let $rename_event_pos= 623;
 
 # Bug#18326: Do not lock table for writing during prepare of statement
 # The use of the ps protocol causes extra table maps in the binlog, so
diff -Nrup a/sql/field.cc b/sql/field.cc
--- a/sql/field.cc	2007-06-21 18:12:54 +03:00
+++ b/sql/field.cc	2007-07-19 22:56:02 +03:00
@@ -2642,6 +2642,35 @@ uint Field_new_decimal::is_equal(Create_
           (new_field->decimals == dec));
 }
 
+const uchar *Field_new_decimal::unpack(uchar* to, const uchar *from, uint from_length)
+{
+  uint from_precision= from_length >> 8U;
+  uint from_decimal= from_length - (from_precision << 8U);
+  uint length=pack_length();
+  uint from_pack_len= my_decimal_get_binary_size(from_precision, from_decimal);
+  uint len= (from_length && (from_pack_len < length)) ?
+            from_pack_len : length;
+  if (from_pack_len && (from_pack_len < length))
+  {
+    /*
+      If the master's data is smaller than the slave, we need to convert
+      the binary to decimal then resize the decimal converting it back to
+      a decimal and write that to the raw data buffer.
+    */
+    decimal_digit_t dec_buf[DECIMAL_MAX_PRECISION];
+    decimal_t dec;
+    dec.len= from_precision;
+    dec.buf= dec_buf;
+    double dbl;
+    bin2decimal((uchar*) from, &dec, from_precision, from_decimal);
+    decimal2double(&dec, &dbl);
+    double2decimal(dbl, &dec);
+    decimal2bin(&dec, to, precision, decimals());
+  }
+  else
+    memcpy(to, from, len); // Sizes are the same, just copy the data.
+  return from+len;
+}
 
 /****************************************************************************
 ** tiny int
@@ -6291,6 +6320,29 @@ uchar *Field_string::pack(uchar *to, con
 }
 
 
+/*
+  When unpacking data that may be smaller in the "from" than the "to," use
+  the from_length to unpack rather than the to's length.
+*/
+const uchar *Field_string::unpack(uchar *to, const uchar *from, uint from_length)
+{
+  uint from_len= (from_length >> 8U);           // real_type.
+  from_len= from_length - (from_len << 8U);     //length.
+  uint length= 0;
+  uint f_length= (from_length && (from_len < field_length)) ? 
+                from_len : field_length;
+  if (f_length > 255)
+  {
+    length= uint2korr(from);
+    from+= 2;
+  }
+  else
+    length= (uint) *from++;
+  memcpy(to, from, (int) length);
+  bfill(to+length, field_length - length, ' ');
+  return from+length;
+}
+
 const uchar *Field_string::unpack(uchar *to, const uchar *from)
 {
   uint length;
@@ -6783,7 +6835,34 @@ uchar *Field_varstring::pack_key_from_ke
 
 /*
   unpack field packed with Field_varstring::pack()
+
+  When unpacking data that may be smaller in the "from" than the "to," use
+  the from_length to unpack rather than the to's length_bytes.
 */
+const uchar *Field_varstring::unpack(uchar *to, const uchar *from, uint from_length)
+{
+  uint length;
+  uint l_bytes= (from_length && (from_length < field_length)) ? 
+                (from_length <= 255) ? 1 : 2 : length_bytes;
+  if (l_bytes == 1)
+    if (length_bytes == 1)
+      length= (uint) (*to= *from++);
+    else
+    {
+      to[1]= 0;
+      to[0]= *from++;
+      length= to[0];
+    }
+  else
+  {
+    length= uint2korr(from);
+    to[0]= *from++;
+    to[1]= *from++;
+  }
+  if (length)
+    memcpy(to+ length_bytes, from, length);
+  return from+length;
+}
 
 const uchar *Field_varstring::unpack(uchar *to, const uchar *from)
 {
@@ -7476,6 +7555,14 @@ uchar *Field_blob::pack(uchar *to, const
   return to+packlength+length;
 }
 
+/*
+  Note: from_length included to satisfy inheritance rules, but is not needed
+  for blob fields.
+*/
+const uchar *Field_blob::unpack(uchar *to, const uchar *from, uint from_length)
+{
+  return unpack(to, from);
+}
 
 const uchar *Field_blob::unpack(uchar *to, const uchar *from)
 {
@@ -8523,6 +8610,38 @@ uchar *Field_bit::pack(uchar *to, const 
   return to + length;
 }
 
+
+/*
+  When unpacking data that may be smaller in the "from" than the "to," use
+  the from_length to unpack rather than the to's length.
+*/
+const uchar *Field_bit::unpack(uchar *to, const uchar *from, uint from_length)
+{
+  uint from_bit_len= from_length >> 8U;
+  uint from_len= from_length - (from_bit_len << 8U);
+  /*
+    If the master and slave have the same sizes, then use the old
+    unpack() method.
+  */
+  uint master_width= from_len + ((from_bit_len > 0) ? 1 : 0);
+  uint slave_width= bytes_in_rec + ((bit_len > 0) ? 1 : 0);
+  if (master_width == slave_width) 
+    return(unpack(to, from));
+  if (from_bit_len > 0)
+  {
+    /*
+      set_rec_bits is a macro, don't put the post-increment in the
+      argument since that might cause strange side-effects.
+
+      For the choice of the second argument, see the explanation for
+      Field_bit::pack().
+    */
+    set_rec_bits(*from, bit_ptr + (to - ptr), bit_ofs, from_bit_len);
+    from++;
+  }
+  memcpy(to, from, from_len);
+  return from + from_len;
+}
 
 const uchar *Field_bit::unpack(uchar *to, const uchar *from)
 {
diff -Nrup a/sql/field.h b/sql/field.h
--- a/sql/field.h	2007-06-15 20:36:14 +03:00
+++ b/sql/field.h	2007-07-19 22:56:02 +03:00
@@ -343,6 +343,26 @@ public:
     memcpy(to,from,length);
     return to+length;
   }
+  virtual const uchar *unpack(uchar* to, const uchar *from, uint from_length)
+  {
+    uint length=pack_length();
+    /*
+      If from length is > 255, it has encoded data in the upper bits. Need
+      to mask it out.
+    */
+    if (from_length > 255)
+    {
+      uint from_len= (from_length >> 8U);           // real_type.
+      from_length= from_length - (from_len << 8U);  //length.
+    }
+    uint len= (from_length && (from_length < length)) ?
+              from_length : length;
+    if (from_length > length)
+      memcpy(to,from,length);
+    else
+      memcpy(to,from,len);
+    return from+len;
+  }
   virtual const uchar *unpack(uchar* to, const uchar *from)
   {
     uint length=pack_length();
@@ -626,6 +646,7 @@ public:
   uint size_of() const { return sizeof(*this); } 
   uint32 pack_length() const { return (uint32) bin_size; }
   uint is_equal(Create_field *new_field);
+  const uchar *unpack(uchar* to, const uchar *from, uint from_length);
 };
 
 
@@ -1162,6 +1183,7 @@ public:
   void sort_string(uchar *buff,uint length);
   void sql_type(String &str) const;
   uchar *pack(uchar *to, const uchar *from, uint max_length=~(uint) 0);
+  const uchar *unpack(uchar* to, const uchar *from, uint from_length);
   const uchar *unpack(uchar* to, const uchar *from);
   int pack_cmp(const uchar *a,const uchar *b,uint key_length,
                my_bool insert_or_update);
@@ -1238,6 +1260,7 @@ public:
   uchar *pack_key(uchar *to, const uchar *from, uint max_length);
   uchar *pack_key_from_key_image(uchar* to, const uchar *from,
                                  uint max_length);
+  const uchar *unpack(uchar* to, const uchar *from, uint from_length);
   const uchar *unpack(uchar* to, const uchar *from);
   const uchar *unpack_key(uchar* to, const uchar *from, uint max_length);
   int pack_cmp(const uchar *a, const uchar *b, uint key_length,
@@ -1293,6 +1316,9 @@ public:
                   l_char_length <= 16777215 ? 3 : 4;
     }
   }
+  Field_blob(uint32 packlength_arg)
+    :Field_longstr((uchar*) 0, 0, (uchar*) "", 0, NONE, "temp", system_charset_info),
+    packlength(packlength_arg) {}
   enum_field_types type() const { return MYSQL_TYPE_BLOB;}
   enum ha_base_keytype key_type() const
     { return binary() ? HA_KEYTYPE_VARBINARY2 : HA_KEYTYPE_VARTEXT2; }
@@ -1314,6 +1340,8 @@ public:
   void sort_string(uchar *buff,uint length);
   uint32 pack_length() const
   { return (uint32) (packlength+table->s->blob_ptr_size); }
+  uint32 pack_length_no_ptr() const
+  { return (uint32) (packlength); }
   uint32 sort_length() const;
   inline uint32 max_data_length() const
   {
@@ -1329,6 +1357,8 @@ public:
   {
     store_length(ptr, packlength, number);
   }
+  uint32 get_packed_size(const uchar *ptr)
+    {return packlength + get_length(ptr);}
  
   inline uint32 get_length(uint row_offset=0)
   { return get_length(ptr+row_offset); }
@@ -1377,6 +1407,7 @@ public:
   uchar *pack_key(uchar *to, const uchar *from, uint max_length);
   uchar *pack_key_from_key_image(uchar* to, const uchar *from,
                                  uint max_length);
+  const uchar *unpack(uchar *to, const uchar *from, uint from_length);
   const uchar *unpack(uchar *to, const uchar *from);
   const uchar *unpack_key(uchar* to, const uchar *from, uint max_length);
   int pack_cmp(const uchar *a, const uchar *b, uint key_length,
@@ -1552,6 +1583,7 @@ public:
   uint32 pack_length_in_rec() const { return bytes_in_rec; }
   void sql_type(String &str) const;
   uchar *pack(uchar *to, const uchar *from, uint max_length=~(uint) 0);
+  const uchar *unpack(uchar* to, const uchar *from, uint from_length);
   const uchar *unpack(uchar* to, const uchar *from);
   virtual void set_default();
 
diff -Nrup a/sql/log_event.cc b/sql/log_event.cc
--- a/sql/log_event.cc	2007-07-12 10:19:25 +03:00
+++ b/sql/log_event.cc	2007-07-19 22:56:02 +03:00
@@ -6028,11 +6028,8 @@ int Rows_log_event::do_apply_event(RELAY
 #ifdef HAVE_QUERY_CACHE
     query_cache.invalidate_locked_for_write(rli->tables_to_lock);
 #endif
-    const_cast<RELAY_LOG_INFO*>(rli)->clear_tables_to_lock();
   }
 
-  DBUG_ASSERT(rli->tables_to_lock == NULL && rli->tables_to_lock_count == 0);
-
   TABLE* table= const_cast<RELAY_LOG_INFO*>(rli)->m_table_map.get_table(m_table_id);
 
   if (table)
@@ -6127,6 +6124,13 @@ int Rows_log_event::do_apply_event(RELAY
     }
   }
 
+  /*
+    We need to delay this clear until the table def is no longer needed.
+    The table def is needed in unpack_row().
+  */
+  if (rli->tables_to_lock && get_flags(STMT_END_F))
+    const_cast<RELAY_LOG_INFO*>(rli)->clear_tables_to_lock();
+
   if (error)
   {                     /* error has occured during the transaction */
     rli->report(ERROR_LEVEL, thd->net.last_errno,
@@ -6375,6 +6379,146 @@ void Rows_log_event::print_helper(FILE *
 /**************************************************************************
 	Table_map_log_event member functions and support functions
 **************************************************************************/
+/**
+  * Calculate field metadata size based on the real_type of the field.
+  *
+  * @returns int Size of field metadata.
+  */
+#if !defined(MYSQL_CLIENT)
+int Table_map_log_event::get_field_metadata_size()
+{
+  DBUG_ENTER("Table_map_log_event::get_field_metadata_size");
+  int size= 0;
+  for (unsigned int i= 0 ; i < m_table->s->fields ; i++)
+  {
+    switch (m_table->s->field[i]->real_type()) {
+    case MYSQL_TYPE_TINY_BLOB:
+    case MYSQL_TYPE_BLOB:
+    case MYSQL_TYPE_MEDIUM_BLOB:
+    case MYSQL_TYPE_LONG_BLOB:
+    case MYSQL_TYPE_DOUBLE:
+    case MYSQL_TYPE_FLOAT:
+    {
+      size++;                         // Store one byte here.
+      break; 
+    }
+    case MYSQL_TYPE_BIT:
+    case MYSQL_TYPE_NEWDECIMAL:
+    case MYSQL_TYPE_ENUM:
+    case MYSQL_TYPE_STRING:
+    case MYSQL_TYPE_VARCHAR:
+    case MYSQL_TYPE_SET:
+    {
+      size= size + sizeof(short int); // Store short int here.
+      break;
+    }
+    default:
+      break;
+    }
+  }
+  m_field_metadata_size= size;
+  DBUG_PRINT("info", ("Table_map_log_event: %d bytes in field metadata.",
+                       (int)m_field_metadata_size));
+  DBUG_RETURN(m_field_metadata_size);
+}
+#endif /* !defined(MYSQL_CLIENT) */
+
+/**
+  * How replication of field metadata works.
+  * 
+  * When a table map is created, the master first calls 
+  * Table_map_log_event::get_field_metadata_size() which calculates how many 
+  * values will be in the field metadata. Only those fields that require the 
+  * extra data are added (see table above). The master then loops through all
+  * of the fields in the table calling the method 
+  * Table_map_log_event::get_field_metadata() which returns the values for the 
+  * field that will be saved in the metadata and replicated to the slave. Once 
+  * all fields have been processed, the table map is written to the binlog 
+  * adding the size of the field metadata and the field metadata to the end of 
+  * the body of the table map.
+  * 
+  * When a table map is read on the slave, the field metadata is read from the 
+  * table map and passed to the table_def class constructor which saves the 
+  * field metadata from the table map into an array based on the type of the 
+  * field. Field metadata values not present (those fields that do not use extra 
+  * data) in the table map are initialized as zero (0). The array size is the 
+  * same as the columns for the table on the slave.
+*/
+
+/**
+  * Save the field metadata based on the real_type of the field.
+  * The metadata saved depends on the type of the field. Some fields
+  * store a single byte for pack_length() while others store two bytes
+  * for field_length (max length).
+  *
+  * @returns int 0 = Ok.
+  */
+#if !defined(MYSQL_CLIENT)
+int Table_map_log_event::get_field_metadata()
+{
+  DBUG_ENTER("Table_map_log_event::get_field_metadata");
+  int index= 0;
+  for (unsigned int i= 0 ; i < m_table->s->fields ; i++)
+  {
+    switch (m_table->s->field[i]->real_type()) {
+    case MYSQL_TYPE_NEWDECIMAL:
+    {
+      m_field_metadata[index++]= 
+        (uchar)((Field_new_decimal *)m_table->s->field[i])->precision;
+      m_field_metadata[index++]= 
+        (uchar)((Field_new_decimal *)m_table->s->field[i])->decimals();
+      break;
+    }
+    case MYSQL_TYPE_TINY_BLOB:
+    case MYSQL_TYPE_BLOB:
+    case MYSQL_TYPE_MEDIUM_BLOB:
+    case MYSQL_TYPE_LONG_BLOB:
+    {
+      m_field_metadata[index++]= 
+       (uchar)((Field_blob *)m_table->s->field[i])->pack_length_no_ptr();
+      break;
+    }
+    case MYSQL_TYPE_DOUBLE:
+    case MYSQL_TYPE_FLOAT:
+    {
+      m_field_metadata[index++]= (uchar)m_table->s->field[i]->pack_length();
+      break;
+    }
+    case MYSQL_TYPE_BIT:
+    { 
+      m_field_metadata[index++]= 
+        (uchar)((Field_bit *)m_table->s->field[i])->bit_len;
+      m_field_metadata[index++]= 
+        (uchar)((Field_bit *)m_table->s->field[i])->bytes_in_rec;
+      break;
+    }
+    case MYSQL_TYPE_VARCHAR:
+    {
+      short int *x= (short int *)&m_field_metadata[index];
+      int2store(x, m_table->s->field[i]->field_length);
+      index= index + sizeof(short int);
+      break;
+    }
+    case MYSQL_TYPE_STRING:
+    {
+      m_field_metadata[index++]= (uchar)m_table->s->field[i]->real_type();
+      m_field_metadata[index++]= m_table->s->field[i]->field_length;
+      break;
+    }
+    case MYSQL_TYPE_ENUM:
+    case MYSQL_TYPE_SET:
+    {
+      m_field_metadata[index++]= (uchar)m_table->s->field[i]->real_type();
+      m_field_metadata[index++]= m_table->s->field[i]->pack_length();
+      break;
+    }
+    default:
+      break;
+    }
+  }
+  DBUG_RETURN(0);
+}
+#endif /* !defined(MYSQL_CLIENT) */
 
 /*
   Constructor used to build an event for writing to the binary log.
@@ -6390,8 +6534,8 @@ Table_map_log_event::Table_map_log_event
     m_dblen(m_dbnam ? tbl->s->db.length : 0),
     m_tblnam(tbl->s->table_name.str),
     m_tbllen(tbl->s->table_name.length),
-    m_colcnt(tbl->s->fields), m_coltype(0),
-    m_table_id(tid),
+    m_colcnt(tbl->s->fields), m_field_metadata(0),
+    m_table_id(tid), m_null_bits(0), m_num_null_bytes(0),
     m_flags(flags)
 {
   DBUG_ASSERT(m_table_id != ~0UL);
@@ -6411,6 +6555,16 @@ Table_map_log_event::Table_map_log_event
   m_data_size+= m_dblen + 2;	// Include length and terminating \0
   m_data_size+= m_tbllen + 2;	// Include length and terminating \0
   m_data_size+= 1 + m_colcnt;	// COLCNT and column types
+  m_field_metadata_size= get_field_metadata_size();
+
+  /*
+    Now set the size of the data to the size of the field metadata array
+    plus one or two bytes for number of elements in the field metadata array.
+  */
+  if (m_field_metadata_size > 255)
+    m_data_size+= m_field_metadata_size + 2; 
+  else
+    m_data_size+= m_field_metadata_size + 1; 
 
   /* If malloc fails, catched in is_valid() */
   if ((m_memory= (uchar*) my_malloc(m_colcnt, MYF(MY_WME))))
@@ -6419,6 +6573,26 @@ Table_map_log_event::Table_map_log_event
     for (unsigned int i= 0 ; i < m_table->s->fields ; ++i)
       m_coltype[i]= m_table->field[i]->type();
   }
+
+  /*
+    Calculate a bitmap for the results of maybe_null() for all columns.
+    This will be writtento the table for use in skipping columns on the master
+    that do not exist on the slave.
+  */
+  m_num_null_bytes= m_table->s->fields / 8 + 1;
+  m_data_size+= m_num_null_bytes;
+  m_null_bits= new uchar[m_num_null_bytes];
+  for (uint i = 0; i < m_num_null_bytes; i++)
+    m_null_bits[i]= 0;
+  for (unsigned int i= 0 ; i < m_table->s->fields ; ++i)
+    if (m_table->field[i]->maybe_null())
+      m_null_bits[(i / 8)]+= 1 << (i % 8);
+
+  /*
+    Create an array for the field metadata and store it.
+  */
+  m_field_metadata= new uchar[m_field_metadata_size];
+  get_field_metadata();
 }
 #endif /* !defined(MYSQL_CLIENT) */
 
@@ -6434,8 +6608,10 @@ Table_map_log_event::Table_map_log_event
 #ifndef MYSQL_CLIENT
   m_table(NULL),
 #endif
-  m_memory(NULL)
+  m_memory(NULL),
+  m_field_metadata(0), m_field_metadata_size(0)
 {
+  unsigned int bytes_read= 0;
   DBUG_ENTER("Table_map_log_event::Table_map_log_event(const char*,uint,...)");
 
   uint8 common_header_len= description_event->common_header_len;
@@ -6508,12 +6684,27 @@ Table_map_log_event::Table_map_log_event
     memcpy(m_coltype, ptr_after_colcnt, m_colcnt);
   }
 
+  ptr_after_colcnt= ptr_after_colcnt + m_colcnt;
+  bytes_read= ptr_after_colcnt - (uchar *)buf;
+  DBUG_PRINT("info", ("Bytes read: %d.\n", bytes_read));
+  if (bytes_read < event_len)
+  {
+    m_field_metadata_size= net_field_length(&ptr_after_colcnt);
+    m_field_metadata= new uchar[m_field_metadata_size];
+    memcpy(m_field_metadata, ptr_after_colcnt, m_field_metadata_size);
+    ptr_after_colcnt= (uchar*)ptr_after_colcnt + m_field_metadata_size;
+    m_null_bits= new uchar[m_colcnt /8 + 1];
+    memcpy(m_null_bits, ptr_after_colcnt, m_colcnt / 8 + 1);
+  }
+
   DBUG_VOID_RETURN;
 }
 #endif
 
 Table_map_log_event::~Table_map_log_event()
 {
+  delete[] m_field_metadata;
+  delete[] m_null_bits;
   my_free(m_memory, MYF(MY_ALLOW_ZERO_PTR));
 }
 
@@ -6644,7 +6835,9 @@ int Table_map_log_event::do_apply_event(
       inside st_relay_log_info::clear_tables_to_lock() by calling the
       table_def destructor explicitly.
     */
-    new (&table_list->m_tabledef) table_def(m_coltype, m_colcnt);
+    new (&table_list->m_tabledef) table_def(m_coltype, m_colcnt, 
+         m_field_metadata, m_field_metadata_size, m_null_bits);
+
     table_list->m_tabledef_valid= TRUE;
 
     /*
@@ -6716,12 +6909,21 @@ bool Table_map_log_event::write_data_bod
   uchar *const cbuf_end= net_store_length(cbuf, (size_t) m_colcnt);
   DBUG_ASSERT(static_cast<size_t>(cbuf_end - cbuf) <= sizeof(cbuf));
 
+  /*
+    Store the size of the field metadata.
+  */
+  uchar mbuf[sizeof(m_field_metadata_size)];
+  uchar *const mbuf_end= net_store_length(mbuf, (size_t) m_field_metadata_size);
+
   return (my_b_safe_write(file, dbuf,      sizeof(dbuf)) ||
           my_b_safe_write(file, (const uchar*)m_dbnam,   m_dblen+1) ||
           my_b_safe_write(file, tbuf,      sizeof(tbuf)) ||
           my_b_safe_write(file, (const uchar*)m_tblnam,  m_tbllen+1) ||
           my_b_safe_write(file, cbuf, (size_t) (cbuf_end - cbuf)) ||
-          my_b_safe_write(file, m_coltype, m_colcnt));
+          my_b_safe_write(file, m_coltype, m_colcnt) ||
+          my_b_safe_write(file, mbuf, (size_t) (mbuf_end - mbuf)) ||
+          my_b_safe_write(file, m_field_metadata, m_field_metadata_size),
+          my_b_safe_write(file, m_null_bits, m_num_null_bytes));
  }
 #endif
 
diff -Nrup a/sql/log_event.h b/sql/log_event.h
--- a/sql/log_event.h	2007-06-05 02:15:00 +03:00
+++ b/sql/log_event.h	2007-07-19 22:56:03 +03:00
@@ -2049,6 +2049,8 @@ public:
 
   virtual int get_data_size() { return m_data_size; } 
 #ifndef MYSQL_CLIENT
+  virtual int get_field_metadata_size();
+  virtual int get_field_metadata();
   virtual bool write_data_header(IO_CACHE *file);
   virtual bool write_data_body(IO_CACHE *file);
   virtual const char *get_db() { return m_dbnam; }
@@ -2085,6 +2087,14 @@ private:
   flag_set       m_flags;
 
   size_t         m_data_size;
+
+  uchar          *m_field_metadata;        // buffer for field metadata
+  /*
+    The size of field metadata buffer set by calling get_field_metadata_size()
+  */
+  ulong         m_field_metadata_size;   
+  uchar        *m_null_bits;
+  uint          m_num_null_bytes;
 };
 
 
diff -Nrup a/sql/rpl_record.cc b/sql/rpl_record.cc
--- a/sql/rpl_record.cc	2007-06-11 23:15:28 +03:00
+++ b/sql/rpl_record.cc	2007-07-19 22:56:03 +03:00
@@ -17,6 +17,7 @@
 #include "rpl_rli.h"
 #include "rpl_record.h"
 #include "slave.h"                  // Need to pull in slave_print_msg
+#include "rpl_utility.h"
 
 /**
    Pack a record of data for a table into a format suitable for
@@ -191,7 +192,9 @@ unpack_row(RELAY_LOG_INFO const *rli,
   unsigned int null_mask= 1U;
   // The "current" null bits
   unsigned int null_bits= *null_ptr++;
-  for (field_ptr= begin_ptr ; field_ptr < end_ptr ; ++field_ptr)
+  uint i= 0;
+  table_def *tabledef= const_cast<RELAY_LOG_INFO*>(rli)->get_tabledef(table);
+  for (field_ptr= begin_ptr ; field_ptr < end_ptr && *field_ptr ; ++field_ptr)
   {
     Field *const f= *field_ptr;
 
@@ -220,13 +223,19 @@ unpack_row(RELAY_LOG_INFO const *rli,
         f->set_notnull();
 
         /*
-          We only unpack the field if it was non-null
+          We only unpack the field if it was non-null.
+          Use the master's size information if available else call
+          normal unpack operation.
         */
-        pack_ptr= f->unpack(f->ptr, pack_ptr);
+        if (tabledef && tabledef->field_metadata(i))
+          pack_ptr= f->unpack(f->ptr, pack_ptr, tabledef->field_metadata(i));
+        else
+          pack_ptr= f->unpack(f->ptr, pack_ptr);
       }
 
       bitmap_set_bit(rw_set, f->field_index);
       null_mask <<= 1;
+      i++;
     }
   }
 
diff -Nrup a/sql/rpl_rli.h b/sql/rpl_rli.h
--- a/sql/rpl_rli.h	2007-06-11 23:15:29 +03:00
+++ b/sql/rpl_rli.h	2007-07-19 22:56:03 +03:00
@@ -18,6 +18,7 @@
 
 #include "rpl_tblmap.h"
 #include "rpl_reporting.h"
+#include "rpl_utility.h"
 
 struct RPL_TABLE_LIST;
 
@@ -300,6 +301,15 @@ typedef struct st_relay_log_info : publi
   RPL_TABLE_LIST *tables_to_lock;           /* RBR: Tables to lock  */
   uint tables_to_lock_count;        /* RBR: Count of tables to lock */
   table_mapping m_table_map;      /* RBR: Mapping table-id to table */
+
+  inline table_def *get_tabledef(TABLE *tbl)
+  {
+    table_def *td= 0;
+    for (TABLE_LIST *ptr= tables_to_lock; ptr && !td; ptr= ptr->next_global)
+      if (ptr->table == tbl)
+        td= &((RPL_TABLE_LIST *)ptr)->m_tabledef;
+    return (td);
+  }
 
   /*
     Last charset (6 bytes) seen by slave SQL thread is cached here; it helps
diff -Nrup a/sql/rpl_utility.cc b/sql/rpl_utility.cc
--- a/sql/rpl_utility.cc	2007-06-11 23:15:29 +03:00
+++ b/sql/rpl_utility.cc	2007-07-19 22:56:03 +03:00
@@ -16,17 +16,46 @@
 #include "rpl_utility.h"
 #include "rpl_rli.h"
 
-uint32
-field_length_from_packed(enum_field_types const field_type, 
-                         uchar const *const data)
+/*********************************************************************
+ *                   table_def member definitions                    *
+ *********************************************************************/
+
+/*
+  This function returns the field size in raw bytes based on the type
+  and the encoded field data from the master's raw data.
+*/
+uint32 table_def::get_field_size(uint col, uchar *master_data)
 {
   uint32 length;
 
-  switch (field_type) {
-  case MYSQL_TYPE_DECIMAL:
+  switch (type(col)) {
   case MYSQL_TYPE_NEWDECIMAL:
-    length= ~(uint32) 0;
+    length= my_decimal_get_binary_size(m_field_metadata[col] >> 8, 
+             m_field_metadata[col] - ((m_field_metadata[col] >> 8) << 8));
+    break;
+  case MYSQL_TYPE_DECIMAL:
+  case MYSQL_TYPE_FLOAT:
+  case MYSQL_TYPE_DOUBLE:
+    length= m_field_metadata[col];
     break;
+  case MYSQL_TYPE_SET:
+  case MYSQL_TYPE_ENUM:
+  case MYSQL_TYPE_STRING:
+  {
+    if ((((m_field_metadata[col] >> 8U) & 0x00ff) == MYSQL_TYPE_SET) ||
+        (((m_field_metadata[col] >> 8U) & 0x00ff) == MYSQL_TYPE_ENUM))
+      length= m_field_metadata[col] - ((m_field_metadata[col] >> 8U) << 8U);
+    else
+    {
+      length= m_field_metadata[col] - ((m_field_metadata[col] >> 8U) << 8U);
+      if (length > 255)
+        length= uint2korr(master_data);
+      else
+        length= (uint) *master_data;
+      length = length + 1;
+    }
+    break;
+  }
   case MYSQL_TYPE_YEAR:
   case MYSQL_TYPE_TINY:
     length= 1;
@@ -45,12 +74,6 @@ field_length_from_packed(enum_field_type
     length= 8;
     break;
 #endif
-  case MYSQL_TYPE_FLOAT:
-    length= sizeof(float);
-    break;
-  case MYSQL_TYPE_DOUBLE:
-    length= sizeof(double);
-    break;
   case MYSQL_TYPE_NULL:
     length= 0;
     break;
@@ -58,8 +81,6 @@ field_length_from_packed(enum_field_type
     length= 3;
     break;
   case MYSQL_TYPE_DATE:
-    length= 4;
-    break;
   case MYSQL_TYPE_TIME:
     length= 3;
     break;
@@ -69,41 +90,34 @@ field_length_from_packed(enum_field_type
   case MYSQL_TYPE_DATETIME:
     length= 8;
     break;
-    break;
   case MYSQL_TYPE_BIT:
-    length= ~(uint32) 0;
-    break;
-  default:
-    /* This case should never be chosen */
-    DBUG_ASSERT(0);
-    /* If something goes awfully wrong, it's better to get a string than die */
-  case MYSQL_TYPE_STRING:
-    length= uint2korr(data);
+  {
+    uint from_bit_len= m_field_metadata[col] >> 8U;
+    uint from_len= m_field_metadata[col] - (from_bit_len << 8U);
+    length= from_len + ((from_bit_len > 0) ? 1 : 0);
     break;
-
-  case MYSQL_TYPE_ENUM:
-  case MYSQL_TYPE_SET:
-  case MYSQL_TYPE_VAR_STRING:
+  }
   case MYSQL_TYPE_VARCHAR:
-    length= ~(uint32) 0;                               // NYI
+    length= m_field_metadata[col] > 255 ? 2 : 1; // c&p of Field_varstring::data_length()
+    length+= length == 1 ? (uint32) *master_data : uint2korr(master_data);
     break;
-
   case MYSQL_TYPE_TINY_BLOB:
   case MYSQL_TYPE_MEDIUM_BLOB:
   case MYSQL_TYPE_LONG_BLOB:
   case MYSQL_TYPE_BLOB:
   case MYSQL_TYPE_GEOMETRY:
-    length= ~(uint32) 0;                               // NYI
+  {
+    Field_blob *fb= new Field_blob(m_field_metadata[col]);
+    length= fb->get_packed_size(master_data);
+    delete fb;
     break;
   }
-
+  default:
+    length= -1;
+  }
   return length;
 }
 
-/*********************************************************************
- *                   table_def member definitions                    *
- *********************************************************************/
-
 /*
   Is the definition compatible with a table?
 
@@ -138,8 +152,14 @@ table_def::compatible_with(RELAY_LOG_INF
                 ER(ER_BINLOG_ROW_WRONG_TABLE_DEF), buf);
   }
 
+  /*
+    We now check for column type and size compatibility.
+  */
   for (uint col= 0 ; col < cols_to_check ; ++col)
   {
+    /*
+      Checking types.
+    */
     if (table->field[col]->type() != type(col))
     {
       DBUG_ASSERT(col < size() && col < tsh->fields);
diff -Nrup a/sql/rpl_utility.h b/sql/rpl_utility.h
--- a/sql/rpl_utility.h	2007-05-24 01:39:21 +03:00
+++ b/sql/rpl_utility.h	2007-07-19 22:56:04 +03:00
@@ -21,13 +21,11 @@
 #endif
 
 #include "mysql_priv.h"
+#include "my_bitmap.h"
 
 struct st_relay_log_info;
 typedef st_relay_log_info RELAY_LOG_INFO;
 
-uint32
-field_length_from_packed(enum_field_types field_type, uchar const *data);
-
 /**
   A table definition from the master.
 
@@ -58,18 +56,94 @@ public:
     @param types Array of types
     @param size  Number of elements in array 'types'
    */
-  table_def(field_type *types, ulong size)
-    : m_size(size), m_type(new unsigned char [size])
+  table_def(field_type *types, ulong size, uchar *field_metadata, 
+      int metadata_size, uchar *null_bitmap)
+    : m_size(size), m_type(new unsigned char [size]),
+      m_field_metadata(0), m_null_bits(0)
   {
     if (m_type)
       memcpy(m_type, types, size);
     else
       m_size= 0;
+    /*
+      Extract the data from the table map into the field metadata array
+      iff there is field metadata. The variable metadata_size will be
+      0 if we are replicating from a down-level server hence no field
+      metadata was written to the table map. This can also happen if 
+      there were no fields in the master that needed extra metadata.
+    */
+    if (m_size && metadata_size)
+    { 
+      m_field_metadata= new short int[m_size];
+      int index= 0;
+      for (unsigned int i= 0; i < m_size; i++)
+      {
+        switch (m_type[i]) {
+        case MYSQL_TYPE_TINY_BLOB:
+        case MYSQL_TYPE_BLOB:
+        case MYSQL_TYPE_MEDIUM_BLOB:
+        case MYSQL_TYPE_LONG_BLOB:
+        case MYSQL_TYPE_DOUBLE:
+        case MYSQL_TYPE_FLOAT:
+        {
+          /*
+            These types store a single byte.
+          */
+          m_field_metadata[i]= (uchar)field_metadata[index];
+          index++;
+          break;
+        }
+        case MYSQL_TYPE_BIT:
+        case MYSQL_TYPE_SET:
+        case MYSQL_TYPE_ENUM:
+        case MYSQL_TYPE_STRING:
+        {
+          short int x= field_metadata[index] << 8U; // real_type
+          index++;
+          x = x + field_metadata[index];            // pack or field length
+          m_field_metadata[i]= x;
+          index++;
+          break;
+        }
+        case MYSQL_TYPE_VARCHAR:
+        {
+          /*
+            These types store two bytes.
+          */
+          short int *x= (short int *)&field_metadata[index];
+          m_field_metadata[i]= sint2korr(x);
+          index= index + sizeof(short int);
+          break;
+        }
+        case MYSQL_TYPE_NEWDECIMAL:
+        {
+          short int x= field_metadata[index] << 8U; // precision
+          index++;
+          x = x + field_metadata[index];            // decimals
+          m_field_metadata[i]= x;
+          index++;
+          break;
+        }
+        default:
+          m_field_metadata[i]= 0;
+          break;
+        }
+      }
+    }
+    if (m_size && null_bitmap)
+    {
+       m_null_bits= new uchar[m_size / 8 + 1];
+       memcpy(m_null_bits, null_bitmap, m_size / 8 + 1);
+    }
   }
 
   ~table_def() {
     if (m_type)
       delete [] m_type;
+    if (m_field_metadata)
+      delete [] m_field_metadata;
+    if (m_null_bits)
+      delete [] m_null_bits;
 #ifndef DBUG_OFF
     m_type= 0;
     m_size= 0;
@@ -99,6 +173,46 @@ public:
     return m_type[index];
   }
 
+  /*
+    This function allows callers to get the extra field data from the
+    table map for a given field. If there is no metadata for that field
+    or there is no extra metadata at all, the function returns 0.
+
+    The function returns the value for the field metadata for column at 
+    position indicated by index. As mentioned, if the field was a type 
+    that stores field metadata, that value is returned else zero (0) is 
+    returned. This method is used in the unpack() methods of the 
+    corresponding fields to properly extract the data from the binary log 
+    in the event that the master's field is smaller than the slave.
+  */
+  uint field_metadata(uint index) const
+  {
+    DBUG_ASSERT(index < m_size);
+    if (m_field_metadata)
+      return m_field_metadata[index];
+    else
+      return 0;
+  }
+
+  /*
+    This function returns whether the field on the master can be null.
+    This value is derived from field->maybe_null().
+  */
+  my_bool maybe_null(ulong index) const
+  {
+    DBUG_ASSERT(index < m_size);
+    return ((m_null_bits[(index / 8)] & (1 << (index % 8))) == (1 << (index %8)));
+  }
+
+  /*
+    This function returns the field size in raw bytes based on the type
+    and the encoded field data from the master's raw data. This method can 
+    be used for situations where the slave needs to skip a column (e.g., 
+    WL#3915) or needs to advance the pointer for the fields in the raw 
+    data from the master to a specific column.
+  */
+  uint32 get_field_size(uint col, uchar *master_data);
+
   /**
     Decide if the table definition is compatible with a table.
 
@@ -121,6 +235,8 @@ public:
 private:
   ulong m_size;           // Number of elements in the types array
   field_type *m_type;                     // Array of type descriptors
+  short int *m_field_metadata;
+  uchar *m_null_bits;
 };
 
 /**
Thread
bk commit into 5.1 tree (aelkin:1.2539)Andrei Elkin19 Jul