List:Commits« Previous MessageNext Message »
From:Mats Kindahl Date:December 12 2007 7:48pm
Subject:bk commit into 5.1 tree (mats:1.2651) BUG#31502
View as plain text  
Below is the list of changes that have just been committed into a local
5.1 repository of mats. When mats 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-12-12 20:48:06+01:00, mats@stripped +8 -0
  Bug #31502: 5.1.20 -> 5.1.22 Slave crashes if it gets an event
              w/ data for non-exist column
  
  5.1.20 table map event does not contain metadata for fields,
  i.e., there is no information about the parameters for the
  types. When replicating to a 5.1.22 server that expects
  metadata, it turns out to incorrectly be zero in many cases,
  leading to misaligned rows.
  
  This patch does a decent job of providing length of fields
  where the length can be computed without the metadata, and
  throws an error otherwise, stopping the slave.

  mysql-test/suite/bugs/r/rpl_bug31502.result@stripped, 2007-12-12 20:48:00+01:00, mats@stripped +74 -0
    New BitKeeper file ``mysql-test/suite/bugs/r/rpl_bug31502.result''

  mysql-test/suite/bugs/r/rpl_bug31502.result@stripped, 2007-12-12 20:48:00+01:00, mats@stripped +0 -0

  mysql-test/suite/bugs/t/rpl_bug31502.test@stripped, 2007-12-12 20:48:00+01:00, mats@stripped +61 -0
    New BitKeeper file ``mysql-test/suite/bugs/t/rpl_bug31502.test''

  mysql-test/suite/bugs/t/rpl_bug31502.test@stripped, 2007-12-12 20:48:00+01:00, mats@stripped +0 -0

  sql/log_event.cc@stripped, 2007-12-12 20:46:59+01:00, mats@stripped +33 -14
    Adding error code checking and propagation for unpack_current_row()
    so that a failure in that function will propagate the error upwards.

  sql/log_event_old.cc@stripped, 2007-12-12 20:47:00+01:00, mats@stripped +32 -14
    Adding error code checking and propagation for unpack_current_row()
    so that a failure in that function will propagate the error upwards.

  sql/rpl_record.cc@stripped, 2007-12-12 20:47:00+01:00, mats@stripped +20 -4
    Returning error from unpack_row() when row cannot be unpacked due to missing
    parameters (metadata). For some fields, the extra parameter info has to be
    present.

  sql/rpl_utility.cc@stripped, 2007-12-12 20:47:00+01:00, mats@stripped +98 -28
    Setting default values for fields when metadata is missing. If
    field size cannot be computed at all, an error is returned.

  sql/rpl_utility.h@stripped, 2007-12-12 20:47:00+01:00, mats@stripped +10 -3
    Changing signature of calc_field_data() to be able to return error
    and length.

  sql/share/errmsg.txt@stripped, 2007-12-12 20:48:00+01:00, mats@stripped +2 -0
    Adding error message ER_SLAVE_MISSING_PARAMS denoting that
    parameters are missing for some field and the length cannot
    be computed.

diff -Nrup a/mysql-test/suite/bugs/r/rpl_bug31502.result b/mysql-test/suite/bugs/r/rpl_bug31502.result
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/mysql-test/suite/bugs/r/rpl_bug31502.result	2007-12-12 20:48:00 +01:00
@@ -0,0 +1,74 @@
+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;
+SET binlog_format = row;
+CREATE TABLE t1 (a CHAR(20), b FLOAT) ENGINE=MyISAM;
+CREATE TABLE t2 (a CHAR(20), b CHAR(64)) ENGINE=MyISAM;
+CREATE TABLE t3 (a CHAR(20), b BLOB) ENGINE=MyISAM;
+ALTER TABLE t1 DROP b;
+ALTER TABLE t2 DROP b;
+ALTER TABLE t3 DROP b;
+INSERT into t1 values ('xxxxxxxxxxx', 1.0);
+SELECT * FROM t1;
+a	b
+xxxxxxxxxxx	1
+SELECT * FROM t1;
+a
+xxxxxxxxxxx
+INSERT into t2 values ('xxxxxxxxxxx', 'blah');
+SELECT * FROM t2;
+a	b
+xxxxxxxxxxx	blah
+SELECT * FROM t2;
+a
+xxxxxxxxxxx
+INSERT into t3 values ('xxxxxxxxxxx', 'This is a blob');
+SELECT * FROM t3;
+a	b
+xxxxxxxxxxx	This is a blob
+SELECT * FROM t3;
+a
+SHOW SLAVE STATUS;
+Slave_IO_State	#
+Master_Host	127.0.0.1
+Master_User	root
+Master_Port	MASTER_PORT
+Connect_Retry	1
+Master_Log_File	master-bin.000001
+Read_Master_Log_Pos	807
+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	1608
+Last_Error	Error in Write_rows event: error during transaction execution on table test.t3. 
+Skip_Counter	0
+Exec_Master_Log_Pos	709
+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	#
+Last_IO_Error	#
+Last_SQL_Errno	1608
+Last_SQL_Error	Error in Write_rows event: error during transaction execution on table test.t3. 
+SET GLOBAL SQL_SLAVE_SKIP_COUNTER = 1;
+START SLAVE;
diff -Nrup a/mysql-test/suite/bugs/t/rpl_bug31502.test b/mysql-test/suite/bugs/t/rpl_bug31502.test
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/mysql-test/suite/bugs/t/rpl_bug31502.test	2007-12-12 20:48:00 +01:00
@@ -0,0 +1,61 @@
+source include/master-slave.inc;
+SET binlog_format = row;
+
+########### Clean up ################
+--disable_warnings
+--disable_query_log
+
+DROP TABLE IF EXISTS t1;
+
+--enable_query_log
+--enable_warnings
+
+connection master;
+CREATE TABLE t1 (a CHAR(20), b FLOAT) ENGINE=MyISAM;
+CREATE TABLE t2 (a CHAR(20), b CHAR(64)) ENGINE=MyISAM;
+CREATE TABLE t3 (a CHAR(20), b BLOB) ENGINE=MyISAM;
+
+sync_slave_with_master;
+ALTER TABLE t1 DROP b;
+ALTER TABLE t2 DROP b;
+ALTER TABLE t3 DROP b;
+
+connection master;
+INSERT into t1 values ('xxxxxxxxxxx', 1.0);
+SELECT * FROM t1;
+sync_slave_with_master;
+SELECT * FROM t1;
+
+connection master;
+INSERT into t2 values ('xxxxxxxxxxx', 'blah');
+SELECT * FROM t2;
+sync_slave_with_master;
+SELECT * FROM t2;
+
+connection master;
+INSERT into t3 values ('xxxxxxxxxxx', 'This is a blob');
+SELECT * FROM t3;
+connection slave;
+source include/wait_for_slave_sql_to_stop.inc;
+SELECT * FROM t3;
+source include/show_slave_status.inc;
+
+SET GLOBAL SQL_SLAVE_SKIP_COUNTER = 1;
+START SLAVE;
+source include/wait_for_slave_to_start.inc;
+
+#### Clean Up ####
+
+connection master;
+--disable_warnings
+--disable_query_log
+DROP TABLE t1;
+
+#connection slave;
+sync_slave_with_master;
+--enable_query_log
+--enable_warnings
+
+# END of the tests
+
+
diff -Nrup a/sql/log_event.cc b/sql/log_event.cc
--- a/sql/log_event.cc	2007-11-28 12:11:13 +01:00
+++ b/sql/log_event.cc	2007-12-12 20:46:59 +01:00
@@ -6446,19 +6446,23 @@ int Rows_log_event::do_apply_event(Relay
       }
 
       /*
-       If m_curr_row_end  was not set during event execution (e.g., because
-       of errors) we can't proceed to the next row. If the error is transient
-       (i.e., error==0 at this point) we must call unpack_current_row() to set 
-       m_curr_row_end.
-      */ 
-   
+       If m_curr_row_end was not set during event execution (e.g.,
+       because of errors) we can't proceed to the next row. If the
+       error is transient (i.e., error==0 at this point) we must call
+       unpack_current_row() to set m_curr_row_end.
+
+       If unpack_current_row() returns an error at this point, we have
+       to abort application of this event with an error.
+      */
+
       DBUG_PRINT("info", ("error: %d", error));
       DBUG_PRINT("info", ("curr_row: 0x%lu; curr_row_end: 0x%lu; rows_end: 0x%lu",
                           (ulong) m_curr_row, (ulong) m_curr_row_end, (ulong) m_rows_end));
 
       if (!m_curr_row_end && !error)
-        unpack_current_row(rli);
-  
+        if ((error= unpack_current_row(rli)))
+          DBUG_RETURN(error);
+
       // at this moment m_curr_row_end should be set
       DBUG_ASSERT(error || m_curr_row_end != NULL); 
       DBUG_ASSERT(error || m_curr_row < m_curr_row_end);
@@ -7461,9 +7465,15 @@ Rows_log_event::write_row(const Relay_lo
   if ((error= prepare_record(rli, table, m_width,
                              TRUE /* check if columns have def. values */)))
     DBUG_RETURN(error);
-  
-  /* unpack row into table->record[0] */
-  error= unpack_current_row(rli); // TODO: how to handle errors?
+
+  /*
+    Unpack row into table->record[0]
+
+    If unpacking the row failed, we cannot write the row, so we have
+    to abort with an error.
+  */
+  if ((error= unpack_current_row(rli)))
+    DBUG_RETURN(error);
 
 #ifndef DBUG_OFF
   DBUG_DUMP("record[0]", table->record[0], table->s->reclength);
@@ -7567,6 +7577,8 @@ Rows_log_event::write_row(const Relay_lo
     {
       restore_record(table,record[1]);
       error= unpack_current_row(rli);
+      // Since we unpacked the row previously, it should not fail.
+      DBUG_ASSERT(error == 0);
     }
 
 #ifndef DBUG_OFF
@@ -7776,9 +7788,11 @@ int Rows_log_event::find_row(const Relay
 
   /* unpack row - missing fields get default values */
 
-  // TODO: shall we check and report errors here?
   prepare_record(NULL,table,m_width,FALSE /* don't check errors */); 
-  error= unpack_current_row(rli); 
+
+  // If unpacking the row here fails, we cannot proceed.
+  if ((error= unpack_current_row(rli)))
+    DBUG_RETURN(error);
 
 #ifndef DBUG_OFF
   DBUG_PRINT("info",("looking for the following record"));
@@ -8200,9 +8214,14 @@ Update_rows_log_event::do_exec_row(const
     /*
       We need to read the second image in the event of error to be
       able to skip to the next pair of updates
+
+      Don't bother to call unpack_current_row() if the error is
+      ER_SLAVE_MISSING_PARAMS since we will just get the same error
+      back and be in the same position as before the call.
     */
     m_curr_row= m_curr_row_end;
-    unpack_current_row(rli);
+    if (error != ER_SLAVE_MISSING_PARAMS)
+      unpack_current_row(rli);
     return error;
   }
 
diff -Nrup a/sql/log_event_old.cc b/sql/log_event_old.cc
--- a/sql/log_event_old.cc	2007-11-21 16:53:44 +01:00
+++ b/sql/log_event_old.cc	2007-12-12 20:47:00 +01:00
@@ -1781,13 +1781,16 @@ int Old_rows_log_event::do_apply_event(R
                           (ulong) m_curr_row, (ulong) m_curr_row_end, (ulong) m_rows_end));
 
       if (!m_curr_row_end && !error)
-        unpack_current_row(rli);
-  
-      // at this moment m_curr_row_end should be set
+        error= unpack_current_row(rli);
+
+      /*
+        At this moment m_curr_row_end should be set or we should have
+        an error.
+      */
       DBUG_ASSERT(error || m_curr_row_end != NULL); 
       DBUG_ASSERT(error || m_curr_row < m_curr_row_end);
       DBUG_ASSERT(error || m_curr_row_end <= m_rows_end);
-  
+
       m_curr_row= m_curr_row_end;
  
     } // row processing loop
@@ -2122,9 +2125,14 @@ Old_rows_log_event::write_row(const Rela
   if ((error= prepare_record(rli, table, m_width,
                              TRUE /* check if columns have def. values */)))
     DBUG_RETURN(error);
-  
-  /* unpack row into table->record[0] */
-  error= unpack_current_row(rli); // TODO: how to handle errors?
+
+  /*
+    Unpack row into table->record[0]
+
+    If unpacking fails, we cannot proceed, so we return an error.
+  */
+  if ((error= unpack_current_row(rli)))
+    DBUG_RETURN(error);
 
 #ifndef DBUG_OFF
   DBUG_DUMP("record[0]", table->record[0], table->s->reclength);
@@ -2227,7 +2235,8 @@ Old_rows_log_event::write_row(const Rela
     if (!get_flags(COMPLETE_ROWS_F))
     {
       restore_record(table,record[1]);
-      error= unpack_current_row(rli);
+      if ((error= unpack_current_row(rli)))
+        DBUG_RETURN(error);
     }
 
 #ifndef DBUG_OFF
@@ -2309,8 +2318,12 @@ Old_rows_log_event::write_row(const Rela
   can contain extra columns not present in the row. It is also possible that 
   the table has fewer columns than the row being located. 
 
-  @returns Error code on failure, 0 on success. 
-  
+  @retval 0 Success
+
+  @retval ER_SLAVE_MISSING_PARAMS
+  Replication from an old master was attempted, but some columns have
+  types that need the parameters to replicate correctly.
+
   @post In case of success @c m_table->record[0] contains the record found. 
   Also, the internal "cursor" of the table is positioned at the record found.
 
@@ -2329,9 +2342,9 @@ int Old_rows_log_event::find_row(const R
 
   /* unpack row - missing fields get default values */
 
-  // TODO: shall we check and report errors here?
   prepare_record(NULL,table,m_width,FALSE /* don't check errors */); 
-  error= unpack_current_row(rli); 
+  if ((error= unpack_current_row(rli)))
+    DBUG_RETURN(error);
 
 #ifndef DBUG_OFF
   DBUG_PRINT("info",("looking for the following record"));
@@ -2922,10 +2935,15 @@ Update_rows_log_event_old::do_exec_row(c
   {
     /*
       We need to read the second image in the event of error to be
-      able to skip to the next pair of updates
+      able to skip to the next pair of updates.
+
+      Don't bother to call the unpack_current_row() if the previous
+      failure was ER_SLAVE_MISSING_PARAMS since we will just get the
+      same error back from the call.
     */
     m_curr_row= m_curr_row_end;
-    unpack_current_row(rli);
+    if (error != ER_SLAVE_MISSING_PARAMS)
+      unpack_current_row(rli);
     return error;
   }
 
diff -Nrup a/sql/rpl_record.cc b/sql/rpl_record.cc
--- a/sql/rpl_record.cc	2007-10-17 09:29:06 +02:00
+++ b/sql/rpl_record.cc	2007-12-12 20:47:00 +01:00
@@ -174,6 +174,11 @@ pack_row(TABLE *table, MY_BITMAP const* 
    Returned if one of the fields existing on the slave but not on the
    master does not have a default value (and isn't nullable)
 
+   @retval ER_SLAVE_MISSING_PARAMS
+   Returned if one of the missing columns (as compared to the master)
+   does not have a size that can be computed without the metadata for
+   the field.
+
  */
 #if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION)
 int
@@ -210,6 +215,7 @@ unpack_row(Relay_log_info const *rli,
       No need to bother about columns that does not exist: they have
       gotten default values when being emptied above.
      */
+    DBUG_ASSERT(i == (uint) (field_ptr - begin_ptr));
     if (bitmap_is_set(cols, field_ptr -  begin_ptr))
     {
       if ((null_mask & 0xFF) == 0)
@@ -240,9 +246,9 @@ unpack_row(Relay_log_info const *rli,
         uchar const *const old_pack_ptr= pack_ptr;
 #endif
         pack_ptr= f->unpack(f->ptr, pack_ptr, metadata, TRUE);
-	DBUG_PRINT("debug", ("field: %s; metadata: 0x%x;"
+	DBUG_PRINT("debug", ("field: %s; type: %d; metadata: 0x%x;"
                              " pack_ptr: 0x%lx; pack_ptr': 0x%lx; bytes: %d",
-                             f->field_name, metadata,
+                             f->field_name, f->type(), metadata,
                              (ulong) old_pack_ptr, (ulong) pack_ptr,
                              (int) (pack_ptr - old_pack_ptr)));
       }
@@ -255,6 +261,8 @@ unpack_row(Relay_log_info const *rli,
   /*
     throw away master's extra fields
   */
+  DBUG_PRINT("info", ("i: %u; tabledef->size: %lu; cols->n_bits: %u",
+                      i, tabledef->size(), cols->n_bits));
   uint max_cols= min(tabledef->size(), cols->n_bits);
   for (; i < max_cols; i++)
   {
@@ -268,8 +276,16 @@ unpack_row(Relay_log_info const *rli,
       }
       DBUG_ASSERT(null_mask & 0xFF); // One of the 8 LSB should be set
 
-      if (!((null_bits & null_mask) && tabledef->maybe_null(i)))
-        pack_ptr+= tabledef->calc_field_size(i, (uchar *) pack_ptr);
+      if (!((null_bits & null_mask) && tabledef->maybe_null(i))) {
+        uint32 length;
+        if ((error= tabledef->calc_field_size(i, (uchar *) pack_ptr, &length, rli)))
+          DBUG_RETURN(error);
+        DBUG_PRINT("info",
+                   ("type: %d; pack_ptr: 0x%lu; pack_ptr': 0x%lu",
+                    tabledef->type(i),
+                    (ulong) pack_ptr, (ulong) pack_ptr + length));
+        pack_ptr += length;
+      }
       null_mask <<= 1;
     }
   }
diff -Nrup a/sql/rpl_utility.cc b/sql/rpl_utility.cc
--- a/sql/rpl_utility.cc	2007-10-01 11:25:25 +02:00
+++ b/sql/rpl_utility.cc	2007-12-12 20:47:00 +01:00
@@ -20,11 +20,87 @@
  *                   table_def member definitions                    *
  *********************************************************************/
 
-/*
+/**
+   Check and set length of parameter based on metadata length.
+ */
+int
+check_and_set_length(enum_field_types field_type, uint32 length,
+                     Slave_reporting_capability const *log, uint32 *out_length)
+{
+  int error= 0;
+  switch (field_type) {
+  case MYSQL_TYPE_STRING:
+    *out_length = length;
+    break;
+
+  case MYSQL_TYPE_NULL:
+    *out_length = length ? length : 0;
+    break;
+
+  case MYSQL_TYPE_TINY:
+  case MYSQL_TYPE_YEAR:
+    *out_length = length ? length : 1;
+    break;
+
+  case MYSQL_TYPE_SHORT:
+    *out_length = length ? length : 2;
+    break;
+
+  case MYSQL_TYPE_DATE:
+  case MYSQL_TYPE_TIME:
+  case MYSQL_TYPE_NEWDATE:
+  case MYSQL_TYPE_INT24:
+    *out_length = length ? length : 3;
+    break;
+
+  case MYSQL_TYPE_TIMESTAMP:
+  case MYSQL_TYPE_FLOAT:
+  case MYSQL_TYPE_LONG:
+    *out_length = length ? length : 4;
+    break;
+
+  case MYSQL_TYPE_DATETIME:
+  case MYSQL_TYPE_DOUBLE:
+  case MYSQL_TYPE_LONGLONG:
+    *out_length = length ? length : 8;
+    break;
+
+  case MYSQL_TYPE_ENUM:
+  case MYSQL_TYPE_SET:
+  case MYSQL_TYPE_NEWDECIMAL:
+  case MYSQL_TYPE_TINY_BLOB:
+  case MYSQL_TYPE_MEDIUM_BLOB:
+  case MYSQL_TYPE_LONG_BLOB:
+  case MYSQL_TYPE_BLOB:
+  case MYSQL_TYPE_GEOMETRY:
+  case MYSQL_TYPE_VAR_STRING:
+  case MYSQL_TYPE_VARCHAR:
+  case MYSQL_TYPE_BIT:
+  case MYSQL_TYPE_DECIMAL:                      // ???
+    log->report(ERROR_LEVEL, ER_SLAVE_MISSING_PARAMS,
+                ER(ER_SLAVE_MISSING_PARAMS), field_type);
+    error= ER_SLAVE_MISSING_PARAMS;
+    break;
+  }
+  return error;
+}
+
+
+/**
+  Compute the field size based on the type and the metadata.
+
   This function returns the field size in raw bytes based on the type
-  and the encoded field data from the master's raw data.
+  and the encoded field data from the master's raw data. If the
+  metadata is not present (that is, it's zero), then the slave will do
+  a "best effort" to replicate the data, but throw an error if it is
+  not possible to replicate the data.
+
+  @param len_arg Pointer to variable that will hold the length.
+  @return Error code, or zero if there were no error.
 */
-uint32 table_def::calc_field_size(uint col, uchar *master_data) const
+int
+table_def::calc_field_size(uint col, uchar *master_data, uint32 *len_arg,
+                           Slave_reporting_capability const* log) const
 {
   uint32 length;
 
@@ -34,34 +110,23 @@ uint32 table_def::calc_field_size(uint c
                                        m_field_metadata[col] & 0xff);
     break;
   case MYSQL_TYPE_DECIMAL:
+    length= m_field_metadata[col] & 0x00ff;
+    break;
+
   case MYSQL_TYPE_FLOAT:
   case MYSQL_TYPE_DOUBLE:
-    length= m_field_metadata[col];
-    break;
-  /*
-    The cases for SET and ENUM are include for completeness, however
-    both are mapped to type MYSQL_TYPE_STRING and their real types
-    are encoded in the field metadata.
-  */
   case MYSQL_TYPE_SET:
   case MYSQL_TYPE_ENUM:
+    length= m_field_metadata[col] & 0x00ff;
+    break;
   case MYSQL_TYPE_STRING:
-  {
-    uchar type= m_field_metadata[col] >> 8U;
-    if ((type == MYSQL_TYPE_SET) || (type == MYSQL_TYPE_ENUM))
-      length= m_field_metadata[col] & 0x00ff;
-    else
-    {
-      /*
-        We are reading the actual size from the master_data record
-        because this field has the actual lengh stored in the first
-        byte.
-      */
-      length= (uint) *master_data + 1;
-      DBUG_ASSERT(length != 0);
-    }
+    /*
+      We are reading the actual size from the master_data record
+      because this field has the actual lengh stored in the first
+      byte.
+    */
+    length= (uint) *master_data + 1;
     break;
-  }
   case MYSQL_TYPE_YEAR:
   case MYSQL_TYPE_TINY:
     length= 1;
@@ -113,8 +178,11 @@ uint32 table_def::calc_field_size(uint c
   }
   case MYSQL_TYPE_VARCHAR:
   {
-    length= m_field_metadata[col] > 255 ? 2 : 1; // c&p of Field_varstring::data_length()
-    DBUG_ASSERT(uint2korr(master_data) > 0);
+    /*
+      This only works when the metadata is 0 if the VARCHAR is less
+      than 255.
+     */
+    length= m_field_metadata[col] > 255 ? 2 : 1;
     length+= length == 1 ? (uint32) *master_data : uint2korr(master_data);
     break;
   }
@@ -166,7 +234,9 @@ uint32 table_def::calc_field_size(uint c
   default:
     length= -1;
   }
-  return length;
+
+  int const error= check_and_set_length(type(col), length, log, len_arg);
+  return error;
 }
 
 /*
diff -Nrup a/sql/rpl_utility.h b/sql/rpl_utility.h
--- a/sql/rpl_utility.h	2007-10-01 11:25:25 +02:00
+++ b/sql/rpl_utility.h	2007-12-12 20:47:00 +01:00
@@ -171,10 +171,10 @@ public:
     <code>index</code>. Currently, only the type identifier is
     returned.
    */
-  field_type type(ulong index) const
+  enum_field_types type(ulong index) const
   {
     DBUG_ASSERT(index < m_size);
-    return m_type[index];
+    return static_cast<enum_field_types>(m_type[index]);
   }
 
 
@@ -216,8 +216,15 @@ public:
     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.
+
+    @param col         Column number
+    @param master_data Pointer to packed field data from master
+    @param len_arg     Pointer to variable holding length if no error
+    @param log         Error logging object
+    @return error code, or zero if no error
   */
-  uint32 calc_field_size(uint col, uchar *master_data) const;
+  int calc_field_size(uint col, uchar *master_data, uint32 *len_arg,
+                      Slave_reporting_capability const* log) const;
 
   /**
     Decide if the table definition is compatible with a table.
diff -Nrup a/sql/share/errmsg.txt b/sql/share/errmsg.txt
--- a/sql/share/errmsg.txt	2007-11-14 14:28:21 +01:00
+++ b/sql/share/errmsg.txt	2007-12-12 20:48:00 +01:00
@@ -6114,3 +6114,5 @@ ER_TRG_CANT_OPEN_TABLE
 
 ER_CANT_CREATE_SROUTINE
   eng "Cannot create stored routine `%-.64s`. Check warnings"
+ER_SLAVE_MISSING_PARAMS
+        eng "Field of type %d cannot be reconstructed from old master since type parameters are missing.  Use a newer version of the master server."
Thread
bk commit into 5.1 tree (mats:1.2651) BUG#31502Mats Kindahl12 Dec
  • Re: bk commit into 5.1 tree (mats:1.2651) BUG#31502Andrei Elkin13 Dec
    • Re: bk commit into 5.1 tree (mats:1.2651) BUG#31502Mats Kindahl13 Dec