List:Commits« Previous MessageNext Message »
From:Mats Kindahl Date:July 27 2007 9:01am
Subject:Re: bk commit into 5.1 tree (cbell:1.2564)
View as plain text  
Hi Chuck!

Code is looking good. I have some comments below, but there is really 
only one issue that we need to address before pushing this. Below, I 
suggest that we use net_store_length() and net_field_length() to store 
the field metadata instead of basing the metadata size on the type.

The advantages are:

    * Changing the number of bytes for the metadata for a field can be
      done while keeping the same code: this makes the format future-proof.
    * The size of the metadata is not dependent on a type, which makes
      it easy to add new types without needing to change any code.
    * The code to read the metadata is significantly shorter and
      entirely independent on the type of the field, while the code to
      write the data is essentially the same.
    * With this change, there is only one place that needs changing if
      we need to alter the metadata for any reason; in the current code
      there are three places: when writing the metadata, when reading
      the metadata, and when calculating the total size of the metadata.

We need to address this issue before pushing the patch since it affects 
the format of the events: all the other comments can be handled at a 
later time (but please read them anyway). If you switch to the suggested 
method, please consider these issues:

    * net_store_length() can store a ulong and net_field_length() can
      return a ulong.
    * allocating memory for the metadata when writing it can be handled
      by over-allocating memory since it is just used during the write.
      You can either use 2 bytes per field (which is the current limit
      on the size of the metadata) or use 4 bytes per field (which will
      then guarantee that there is enough space to store the ulong that
      net_store_length() accepts). In either case, add an assertion to
      make sure you are not writing outsize the allocated memory.
    * You can then set the m_field_metadata_size after you have written
      the metadata by just computing the difference between
      m_field_metadata and the pointer used to write the data
      (metadata_ptr in my sample code below).


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-07-26 20:48:06-04:00, cbell@mysql_cab_desk. +24 -0
>   WL#3228 (NDB) : RBR using different table defs on slave/master
>   
>   This patch adds the ability to store extra field metadata in the table
>   map event. This data can include pack_length() or field_lenght() for
>   fields such as CHAR or VARCHAR enabling developers to add code that
>   can check for compatibilty between master and slave columns. More 
>   importantly, the extra field metadata can be used to store data from the
>   master correctly should a VARCHAR field on the master be <= 255 bytes 
>   while the same field on the slave is > 255 bytes. '
>   
>   The patch also includes the needed changes to unpack to ensure that data
>   which is smaller on the master can be unpacked correctly on the slave.
>
>   mysql-test/r/rpl_colSize.result@stripped, 2007-07-26 20:47:59-04:00,
> cbell@mysql_cab_desk. +179 -0
>     WL#3228 : RBR using different table defs on slave/master
>     
>     This patch contains a result file for the new test designed to test the 
>     feature of having columns on the master that are smaller than what is 
>     on the slave. 
>     
>
>   mysql-test/r/rpl_colSize.result@stripped, 2007-07-26 20:47:59-04:00,
> cbell@mysql_cab_desk. +0 -0
>
>   mysql-test/r/rpl_ndb_log.result@stripped, 2007-07-26 20:47:41-04:00,
> cbell@mysql_cab_desk. +4 -4
>     WL#3228 : RBR using different table defs on slave/master
>     
>     This patch contains a result file for the new test designed to test the 
>     feature of having columns on the master that are smaller than what is 
>     on the slave. 
>
>   mysql-test/r/rpl_rbr_to_sbr.result@stripped, 2007-07-26 20:47:41-04:00,
> cbell@mysql_cab_desk. +2 -2
>     WL#3228 : RBR using different table defs on slave/master
>     
>     This patch contains a result file for the new test designed to test the 
>     feature of having columns on the master that are smaller than what is 
>     on the slave. 
>
>   mysql-test/r/rpl_row_basic_11bugs.result@stripped, 2007-07-26 20:47:42-04:00,
> cbell@mysql_cab_desk. +2 -2
>     WL#3228 : RBR using different table defs on slave/master
>     
>     This patch contains a result file for the new test designed to test the 
>     feature of having columns on the master that are smaller than what is 
>     on the slave. 
>
>   mysql-test/r/rpl_row_create_table.result@stripped, 2007-07-26 20:47:43-04:00,
> cbell@mysql_cab_desk. +42 -42
>     WL#3228 : RBR using different table defs on slave/master
>     
>     This patch contains a result file for the new test designed to test the 
>     feature of having columns on the master that are smaller than what is 
>     on the slave. 
>
>   mysql-test/r/rpl_row_flsh_tbls.result@stripped, 2007-07-26 20:47:44-04:00,
> cbell@mysql_cab_desk. +2 -2
>     WL#3228 : RBR using different table defs on slave/master
>     
>     This patch contains a result file for the new test designed to test the 
>     feature of having columns on the master that are smaller than what is 
>     on the slave. 
>
>   mysql-test/r/rpl_row_inexist_tbl.result@stripped, 2007-07-26 20:47:45-04:00,
> cbell@mysql_cab_desk. +1 -1
>     WL#3228 : RBR using different table defs on slave/master
>     
>     This patch contains a result file for the new test designed to test the 
>     feature of having columns on the master that are smaller than what is 
>     on the slave. 
>
>   mysql-test/r/rpl_row_log.result@stripped, 2007-07-26 20:47:46-04:00,
> cbell@mysql_cab_desk. +5 -5
>     WL#3228 : RBR using different table defs on slave/master
>     
>     This patch contains a result file for the new test designed to test the 
>     feature of having columns on the master that are smaller than what is 
>     on the slave. 
>
>   mysql-test/r/rpl_row_log_innodb.result@stripped, 2007-07-26 20:47:46-04:00,
> cbell@mysql_cab_desk. +5 -5
>     WL#3228 : RBR using different table defs on slave/master
>     
>     This patch contains a result file for the new test designed to test the 
>     feature of having columns on the master that are smaller than what is 
>     on the slave. 
>
>   mysql-test/r/rpl_row_max_relay_size.result@stripped, 2007-07-26 20:47:47-04:00,
> cbell@mysql_cab_desk. +10 -10
>     WL#3228 : RBR using different table defs on slave/master
>     
>     This patch contains a result file for the new test designed to test the 
>     feature of having columns on the master that are smaller than what is 
>     on the slave. 
>
>   mysql-test/r/rpl_row_until.result@stripped, 2007-07-26 20:47:48-04:00,
> cbell@mysql_cab_desk. +4 -4
>     WL#3228 : RBR using different table defs on slave/master
>     
>     This patch contains a result file for the new test designed to test the 
>     feature of having columns on the master that are smaller than what is 
>     on the slave. 
>
>   mysql-test/r/rpl_truncate_7ndb.result@stripped, 2007-07-26 20:47:48-04:00,
> cbell@mysql_cab_desk. +32 -32
>     WL#3228 : RBR using different table defs on slave/master
>     
>     This patch contains a result file for the new test designed to test the 
>     feature of having columns on the master that are smaller than what is 
>     on the slave. 
>
>   mysql-test/t/binlog_row_mix_innodb_myisam.test@stripped, 2007-07-26 20:47:49-04:00,
> cbell@mysql_cab_desk. +1 -1
>     WL#3228 : RBR using different table defs on slave/master
>     
>     This patch changes the test to coincide with changes to binlog
>     size of table map event.
>
>   mysql-test/t/rpl_colSize.test@stripped, 2007-07-26 20:47:59-04:00, cbell@mysql_cab_desk.
> +216 -0
>     WL#3228 : RBR using different table defs on slave/master
>     
>     This patch contains a new test designed to test the feature of having
>     columns on the master that are smaller than what is on the slave. 
>     
>
>   mysql-test/t/rpl_colSize.test@stripped, 2007-07-26 20:47:59-04:00, cbell@mysql_cab_desk.
> +0 -0
>
>   mysql-test/t/rpl_row_create_table.test@stripped, 2007-07-26 20:47:50-04:00,
> cbell@mysql_cab_desk. +5 -5
>     WL#3228 : RBR using different table defs on slave/master
>     
>     This patch changes the test to coincide with changes to binlog
>     size of table map event.
>
>   mysql-test/t/rpl_row_flsh_tbls.test@stripped, 2007-07-26 20:47:51-04:00,
> cbell@mysql_cab_desk. +1 -1
>     WL#3228 : RBR using different table defs on slave/master
>     
>     This patch changes the test to coincide with changes to binlog
>     size of table map event.
>
>   sql/field.cc@stripped, 2007-07-26 20:47:52-04:00, cbell@mysql_cab_desk. +230 -0
>     WL#3228 : RBR using different table defs on slave/master
>     
>     This patch includes updates to the unpack() methods for the variable
>     length fields. A new parameter was added (from_length) that is the
>     value stored in the field_metadata of the table map from the table_def
>     class. If the value is non-zero and less than what the field on the 
>     slave is then use the from_length else use the original value from the
>     field on the slave.
>
>   sql/field.h@stripped, 2007-07-26 20:47:53-04:00, cbell@mysql_cab_desk. +31 -0
>     WL#3228 : RBR using different table defs on slave/master
>     
>     This patch includes updates to the unpack() methods for the variable
>     length fields. A new parameter was added (from_length) that is the
>     value stored in the field_metadata of the table map from the table_def
>     class. 
>
>   sql/log_event.cc@stripped, 2007-07-26 20:47:54-04:00, cbell@mysql_cab_desk. +215 -9
>     WL#3228 : RBR using different table defs on slave/master
>     
>     This patch adds methods to calculate the field metadata size, prepare
>     the field metadata for writing to the binlog, and additions to the
>     Table_map_log_event::write_body method to include the field metadata 
>     in the table map that is written to the binlog.
>
>   sql/log_event.h@stripped, 2007-07-26 20:47:54-04:00, cbell@mysql_cab_desk. +10 -0
>     WL#3228 : RBR using different table defs on slave/master
>     
>     This patch adds method declarations and variables needed to support
>     storing field metadata in the table map that is written to the binlog.
>
>   sql/rpl_record.cc@stripped, 2007-07-26 20:47:55-04:00, cbell@mysql_cab_desk. +14 -4
>     WL#3228 : RBR using different table defs on slave/master
>     
>     This patch modifies the unpack_row() method to unpack fields passing in
>     the value from the table_def class. This value is the extra field
>     metadata stored there from the master.
>
>   sql/rpl_rli.h@stripped, 2007-07-26 20:47:56-04:00, cbell@mysql_cab_desk. +10 -0
>     WL#3228 : RBR using different table defs on slave/master
>     
>     This patch adds a helper function to retrieve the table_def for a given
>     table in the RPL_TABLE_LIST structure.
>
>   sql/rpl_utility.cc@stripped, 2007-07-26 20:47:57-04:00, cbell@mysql_cab_desk. +55 -35
>     WL#3228 : RBR using different table defs on slave/master
>     
>     This patch adds a helper method that retrieves the correct size 
>     parameter for the field. This method is used to compare the size as
>     sent by the master with that on the slave for all types of fields that
>     can vary in size and storage requirements. 
>
>   sql/rpl_utility.h@stripped, 2007-07-26 20:47:58-04:00, cbell@mysql_cab_desk. +120 -7
>     WL#3228 : RBR using different table defs on slave/master
>     
>     This patch changes the table_def class constructor to pass in the raw
>     data read from the table map and extract it into an array of dimension
>     size (number of fields). It also adds a method to return the field 
>     metadata for any field. The method returns the data stored in the table
>     map or 0 if no data was stored for that field. Lastly, a method to return
>     the results of field->maybe_null() is included so that the slave can
>     determine if a field that is not on the slave is null.
>
> # This is a BitKeeper patch.  What follows are the unified diffs for the
> # set of deltas contained in the patch.  The rest of the patch, the part
> # that BitKeeper cares about, is below these diffs.
> # User:	cbell
> # Host:	mysql_cab_desk.
> # Root:	C:/source/c++/mysql-5.1_WL_3228_ndb
>
> --- 1.393/sql/field.cc	2007-07-26 20:48:26 -04:00
> +++ 1.394/sql/field.cc	2007-07-26 20:48:26 -04:00
> @@ -1358,6 +1358,49 @@
>  }
>  
>  
> +/**
> +   Unpack a field from row data.
> +
> +   This method is used to unpack a field from a master whose size 
> +   of the field is less than that of the slave.
> +  
> +   @param   to         Destination of the data
> +   @param   from       Source of the data
> +   @param   param_data Pack length of the field data
> +
> +   @retval  New pointer into memory based on from + length of the data
> +*/
> +const char *Field::unpack(char* to, const char *from, uint param_data)
> +{
> +  uint length=pack_length();
> +  int from_type= 0;
> +  /*
> +    If from length is > 255, it has encoded data in the upper bits. Need
> +    to mask it out.
> +  */
> +  if (param_data > 255)
> +  {
> +    from_type= (param_data & 0xff00) >> 8U;  // real_type.
> +    param_data= param_data & 0x00ff;        // length.
> +  }
> +  uint len= (param_data && (param_data < length)) ?
> +            param_data : length;
> +  /*
> +    If the length is the same, use old unpack method.
> +    If the param_data is 0, use the old unpack method.
> +      This is possible if the table map was generated from a down-level
> +      master or if the data was not available on the master.
> +    If the real_types are not the same, use the old unpack method.
>   

I'm still wondering what makes the old unpack method work when the 
real_types are not the same. Could you given an example?

> +  */
> +  if ((length == param_data) ||
> +      (param_data == 0) ||
> +      (from_type != real_type()))
> +    return(unpack(to, from));
> +  memcpy(to, from, param_data > length ? length : len);
> +  return from+len;
> +}
>   

OK.

> +
> +
>  my_decimal *Field::val_decimal(my_decimal *decimal)
>  {
>    /* This never have to be called */
> @@ -2635,6 +2678,51 @@
>            (new_field->decimals == dec));
>  }
>  
> +/**
> +   Unpack a decimal field from row data.
> +
> +   This method is used to unpack a decimal or numeric field from a master
> +   whose size of the field is less than that of the slave.
> +  
> +   @param   to         Destination of the data
> +   @param   from       Source of the data
> +   @param   param_data Precision (upper) and decimal (lower) values
> +
> +   @retval  New pointer into memory based on from + length of the data
> +*/
> +const char *Field_new_decimal::unpack(char* to, 
> +                                      const char *from, 
> +                                      uint param_data)
> +{
> +  uint from_precision= (param_data & 0xff00) >> 8U;
> +  uint from_decimal= param_data & 0x00ff;
> +  uint length=pack_length();
> +  uint from_pack_len= my_decimal_get_binary_size(from_precision, from_decimal);
> +  uint len= (param_data && (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;
> +    /*
> +      Note: bin2decimal does not change the length of the field. So it is
> +      just the first step the resizing operation. The second step does the
> +      resizing using the precision and decimals from the slave.
> +    */
> +    bin2decimal((char *)from, &dec, from_precision, from_decimal);
> +    decimal2bin(&dec, to, precision, decimals());
> +  }
> +  else
> +    memcpy(to, from, len); // Sizes are the same, just copy the data.
> +  return from+len;
> +}
>   

OK.

>  
>  /****************************************************************************
>  ** tiny int
> @@ -6294,6 +6382,39 @@
>  }
>  
>  
> +/**
> +   Unpack a string field from row data.
> +
> +   This method is used to unpack a string field from a master whose size 
> +   of the field is less than that of the slave. Note that there can be a
> +   variety of field types represented with this class. Certain types like
> +   ENUM or SET are processed differently. Hence, the upper byte of the 
> +   @c param_data argument contains the result of field->real_type() from
> +   the master.
> +
> +   @param   to         Destination of the data
> +   @param   from       Source of the data
> +   @param   param_data Real type (upper) and length (lower) values
> +
> +   @retval  New pointer into memory based on from + length of the data
> +*/
> +const char *Field_string::unpack(char *to,
> +                                 const char *from,
> +                                 uint param_data)
> +{
> +  uint from_len= param_data & 0x00ff;                 // length.
> +  uint length= 0;
> +  uint f_length= (from_len < field_length) ? from_len : field_length;
> +  DBUG_ASSERT(f_length <= 255);
> +  length= (uint) *from++;
> +  bitmap_set_bit(table->write_set,field_index);
> +  store(from, length, system_charset_info);
> +  //memcpy(to, from, (int) length);
> +  //bfill(to+length, field_length - length, ' ');
>   

Remove the commented lines.

> +  return from+length;
> +}
> +
> +
>  const char *Field_string::unpack(char *to, const char *from)
>  {
>    uint length;
> @@ -6782,6 +6903,44 @@
>  }
>  
>  
> +/**
> +   Unpack a varstring field from row data.
> +
> +   This method is used to unpack a varstring field from a master
> +   whose size of the field is less than that of the slave.
> +  
> +   @param   to         Destination of the data
> +   @param   from       Source of the data
> +   @param   param_data Length bytes from the master's field data
> +
> +   @retval  New pointer into memory based on from + length of the data
> +*/
> +const char *Field_varstring::unpack(char *to, 
> +                                    const char *from,
> +                                    uint param_data)
> +{
> +  uint length;
> +  uint l_bytes= (param_data && (param_data < field_length)) ? 
> +                (param_data <= 255) ? 1 : 2 : length_bytes;
> +  if (l_bytes == 1)
> +  {
> +    to[0]= *from++;
> +    length= to[0];
> +    if (length_bytes == 2)
> +      to[1]= 0;
> +  }
> +  else
> +  {
> +    length= uint2korr(from);
> +    to[0]= *from++;
> +    to[1]= *from++;
>   

This part is used both if l_bytes is 2 or if it is length_bytes and 
you're always reading two bytes. Is it possible that length_bytes can be 
1 and you are trying to read two bytes?

> +  }
> +  if (length)
> +    memcpy(to+ length_bytes, from, length);
> +  return from+length;
> +}
> +
> +
>  /*
>    unpack field packed with Field_varstring::pack()
>  */
> @@ -7473,6 +7632,29 @@
>  }
>  
>  
> +/**
> +   Unpack a blob field from row data.
> +
> +   This method is used to unpack a blob field from a master whose size of 
> +   the field is less than that of the slave. Note: This method is included
> +   to satisfy inheritance rules, but is not needed for blob fields. It
> +   simply is used as a pass-through to the original unpack() method for
> +   blob fields.
> +
> +   @param   to         Destination of the data
> +   @param   from       Source of the data
> +   @param   param_data <not used>
> +
> +   @retval  New pointer into memory based on from + length of the data
>   
@return in this case. @retval is when you have value-description pairs. 
No need to fix that with this patch, however.

> +*/
> +const char *Field_blob::unpack(char *to, 
> +                               const char *from,
> +                               uint param_data)
> +{
> +  return unpack(to, from);
> +}
> +
> +
>  const char *Field_blob::unpack(char *to, const char *from)
>  {
>    memcpy(to,from,packlength);
> @@ -8507,6 +8689,54 @@
>    length= min(bytes_in_rec, max_length - (bit_len > 0));
>    memcpy(to, from, length);
>    return to + length;
> +}
> +
> +
> +/**
> +   Unpack a bit field from row data.
> +
> +   This method is used to unpack a bit field from a master whose size 
> +   of the field is less than that of the slave.
> +  
> +   @param   to         Destination of the data
> +   @param   from       Source of the data
> +   @param   param_data Bit length (upper) and length (lower) values
> +
> +   @retval  New pointer into memory based on from + length of the data
> +*/
> +const char *Field_bit::unpack(char *to,
> +                              const char *from,
> +                              uint param_data)
> +{
> +  uint const from_len= (param_data >> 8U) & 0x00ff;
> +  uint const from_bit_len= param_data & 0x00ff;
> +  /*
> +    If the master and slave have the same sizes, then use the old
> +    unpack() method.
> +  */
> +  if ((from_bit_len == bit_len) &&
> +      (from_len == bytes_in_rec)) 
> +    return(unpack(to, from));
> +  /*
> +    We are converting a smaller bit field to a larger one here.
> +    To do that, we first need to construct a raw value for the original
> +    bit value stored in the from buffer. Then that needs to be converted
> +    to the larger field then sent to store() for writing to the field.
> +    Lastly the odd bits need to be masked out if the bytes_in_rec > 0.
> +    Otherwise stray bits can cause spurious values.
> +  */
> +  uint new_len= (field_length + 7) / 8;
> +  char *value= (char *)my_alloca(new_len);
> +  for (uint i= 0; i < new_len; i++)
> +    value[i]= 0;
> +  uint len= from_len + ((from_bit_len > 0) ? 1 : 0);
> +  memcpy(value + (new_len - len), from, len);
> +  if ((from_bit_len > 0) && (from_len > 0))
> +    value[new_len - len]= value[new_len - len] & ((1U << from_bit_len) -
> 1);
>   

If you on the master make sure that the unused bits of this byte are all 
zero, you won't need to do the masking on the slave.

> +  bitmap_set_bit(table->write_set,field_index);
> +  store(value, new_len, system_charset_info);
> +  my_afree(value);
> +  return from + len;
>  }
>  
>  
>
> --- 1.226/sql/field.h	2007-07-26 20:48:26 -04:00
> +++ 1.227/sql/field.h	2007-07-26 20:48:26 -04:00
> @@ -342,6 +342,7 @@
>      memcpy(to,from,length);
>      return to+length;
>    }
> +  virtual const char *unpack(char* to, const char *from, uint param_data);
>    virtual const char *unpack(char* to, const char *from)
>    {
>      uint length=pack_length();
> @@ -613,6 +614,7 @@
>    uint size_of() const { return sizeof(*this); } 
>    uint32 pack_length() const { return (uint32) bin_size; }
>    uint is_equal(create_field *new_field);
> +  virtual const char *unpack(char* to, const char *from, uint param_data);
>  };
>  
>  
> @@ -1154,6 +1156,7 @@
>    void sort_string(char *buff,uint length);
>    void sql_type(String &str) const;
>    char *pack(char *to, const char *from, uint max_length=~(uint) 0);
> +  virtual const char *unpack(char* to, const char *from, uint param_data);
>    const char *unpack(char* to, const char *from);
>    int pack_cmp(const char *a,const char *b,uint key_length,
>                 my_bool insert_or_update);
> @@ -1224,6 +1227,7 @@
>    char *pack(char *to, const char *from, uint max_length=~(uint) 0);
>    char *pack_key(char *to, const char *from, uint max_length);
>    char *pack_key_from_key_image(char* to, const char *from, uint max_length);
> +  virtual const char *unpack(char* to, const char *from, uint param_data);
>    const char *unpack(char* to, const char *from);
>    const char *unpack_key(char* to, const char *from, uint max_length);
>    int pack_cmp(const char *a, const char *b, uint key_length,
> @@ -1279,6 +1283,9 @@
>                    l_char_length <= 16777215 ? 3 : 4;
>      }
>    }
> +  Field_blob(uint32 packlength_arg)
> +    :Field_longstr((char*) 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; }
> @@ -1300,6 +1307,17 @@
>    void sort_string(char *buff,uint length);
>    uint32 pack_length() const
>    { return (uint32) (packlength+table->s->blob_ptr_size); }
> +
> +  /**
> +     Return the packed length without the pointer size added. 
> +
> +     This is used to determine the size of the actual data in the row
> +     buffer.
> +
> +     @retval The length of the raw data itself without the pointer.
> +  */
> +  uint32 pack_length_no_ptr() const
> +  { return (uint32) (packlength); }
>    uint32 sort_length() const;
>    inline uint32 max_data_length() const
>    {
> @@ -1316,6 +1334,17 @@
>      store_length(ptr, packlength, number);
>    }
>  
> +  /**
> +     Return the packed length plus the length of the data. 
> +
> +     This is used to determine the size of the data plus the 
> +     packed length portion in the row data.
> +
> +     @retval The length in the row plus the size of the data.
> +  */
> +  uint32 get_packed_size(const uchar *ptr)
> +    {return packlength + get_length((uint)ptr);}
> +
>    inline uint32 get_length(uint row_offset=0)
>    { return get_length(ptr+row_offset); }
>    uint32 get_length(const char *ptr);
> @@ -1360,6 +1389,7 @@
>    char *pack(char *to, const char *from, uint max_length= ~(uint) 0);
>    char *pack_key(char *to, const char *from, uint max_length);
>    char *pack_key_from_key_image(char* to, const char *from, uint max_length);
> +  virtual const char *unpack(char *to, const char *from, uint param_data);
>    const char *unpack(char *to, const char *from);
>    const char *unpack_key(char* to, const char *from, uint max_length);
>    int pack_cmp(const char *a, const char *b, uint key_length,
> @@ -1534,6 +1564,7 @@
>    uint32 pack_length_in_rec() const { return bytes_in_rec; }
>    void sql_type(String &str) const;
>    char *pack(char *to, const char *from, uint max_length=~(uint) 0);
> +  virtual const char *unpack(char *to, const char *from, uint param_data);
>    const char *unpack(char* to, const char *from);
>    virtual void set_default();
>  
>
> --- 1.279/sql/log_event.cc	2007-07-26 20:48:26 -04:00
> +++ 1.280/sql/log_event.cc	2007-07-26 20:48:26 -04:00
> @@ -5976,11 +5976,8 @@
>  #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)
> @@ -6076,6 +6073,13 @@
>      }
>    }
>  
> +  /*
> +    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 */
>      slave_print_msg(ERROR_LEVEL, rli, thd->net.last_errno,
> @@ -6314,6 +6318,147 @@
>  	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)
> +const int Table_map_log_event::calc_field_metadata_size()
> +{
> +  DBUG_ENTER("Table_map_log_event::calc_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) */
> +
> +/**
> +  @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 
> +  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).
> +  
> +  @retval 0 Ok.
> +*/
>   

I would suggest using net_store_length() to store the data in the array 
instead. That makes the code entirely independent on the types, and will 
also allow adding an "upper" byte to fields that does not have one 
without any need to change the code. It will probably also make the code 
more efficient. The suggested changes below are for this case.

> +#if !defined(MYSQL_CLIENT)
> +int Table_map_log_event::save_field_metadata()
> +{
> +  DBUG_ENTER("Table_map_log_event::save_field_metadata");
> +  int index= 0;
>   
uint16 metadata;
uchar* metadata_ptr= m_field_metadata;
> +  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();
>   
Field_new_decimal *const f= (Field_new_decimal*) m_table->s->field[i];
metadata= f->decimals() & 0xFF;
metadata|= (f->precision & 0xFF) << 8;

> +      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();
>   
metadata= ((Field_blob *)m_table->s->field[i])->pack_length_no_ptr() & 
0xFF;
> +      break;
> +    }
> +    case MYSQL_TYPE_DOUBLE:
> +    case MYSQL_TYPE_FLOAT:
> +    {
> +      m_field_metadata[index++]=
> (uchar)m_table->s->field[i]->pack_length();
>   
metadata= m_table->s->field[i]->pack_length() & 0xFF;

> +      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;
>   

Similar to above.

> +      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);
>   
metadata= m_table->s->field[i]->field_length

> +      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;
>   

Immediate

> +      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();
>   

Immediate

> +      break;
> +    }
> +    default:
> +      break;
> +    }
>   

metadata_ptr= net_store_length(metadata_ptr, metadata);

> +  }
> +  DBUG_RETURN(0);
> +}
> +#endif /* !defined(MYSQL_CLIENT) */
> +
>  /*
>    Constructor used to build an event for writing to the binary log.
>    Mats says tbl->s lives longer than this event so it's ok to copy pointers
> @@ -6328,9 +6473,8 @@
>      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_flags(flags)
> +    m_colcnt(tbl->s->fields), m_field_metadata(0),
> +    m_table_id(tid), m_null_bits(0), m_flags(flags)
>  {
>    DBUG_ASSERT(m_table_id != ~0UL);
>    /*
> @@ -6349,6 +6493,16 @@
>    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= calc_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 you use net_store_length() to store the data, you don't know the size 
until you've written the metadata, which means that 
calc_field_metadata_size() *might* require rewriting (but not 
necessarily so). Since you know that there will be no more than 2 byte 
per piece of metadata, you can use 2 * no of fields to allocate memory 
for the field metadata.

>  
>    /* If malloc fails, catched in is_valid() */
>    if ((m_memory= my_malloc(m_colcnt, MYF(MY_WME))))
> @@ -6357,6 +6511,29 @@
>      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.
> +    The bitmap is used to determine when there is a column from the master
> +    that is not on the slave and is null and thus not in the row data during
> +    replication.
> +  */
> +  uint num_null_bytes= (m_table->s->fields + 7) / 8;
> +  m_data_size+= num_null_bytes;
> +  m_meta_memory= my_multi_malloc(MYF(MY_WME),
> +                                 &m_null_bits, num_null_bytes,
> +                                 &m_field_metadata, m_field_metadata_size,
> +                                 NULL);
> +  for (uint i = 0; i < num_null_bytes; i++)
> +    m_null_bits[i]= 0;
>   

Use bzero().

> +  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.
> +  */
> +  save_field_metadata();
>  }
>  #endif /* !defined(MYSQL_CLIENT) */
>  
> @@ -6372,8 +6549,10 @@
>  #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;
> @@ -6444,6 +6623,22 @@
>      strncpy(const_cast<char*>(m_dbnam), (const char*)ptr_dblen  + 1, m_dblen +
> 1);
>      strncpy(const_cast<char*>(m_tblnam), (const char*)ptr_tbllen + 1, m_tbllen
> + 1);
>      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);
> +      uint num_null_bytes= (m_colcnt + 7) / 8;
> +      m_meta_memory= my_multi_malloc(MYF(MY_WME),
> +                                     &m_null_bits, num_null_bytes,
> +                                     &m_field_metadata, m_field_metadata_size,
> +                                     NULL);
> +      memcpy(m_field_metadata, ptr_after_colcnt, m_field_metadata_size);
> +      ptr_after_colcnt= (uchar*)ptr_after_colcnt + m_field_metadata_size;
> +      memcpy(m_null_bits, ptr_after_colcnt, num_null_bytes);
> +    }
>    }
>  
>    DBUG_VOID_RETURN;
> @@ -6452,6 +6647,7 @@
>  
>  Table_map_log_event::~Table_map_log_event()
>  {
> +  my_free(m_meta_memory, MYF(MY_ALLOW_ZERO_PTR));
>    my_free(m_memory, MYF(MY_ALLOW_ZERO_PTR));
>   

Is it possible to combine these two allocations into one?

>  }
>  
> @@ -6585,7 +6781,8 @@
>        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;
>  
>      /*
> @@ -6644,13 +6841,22 @@
>    char *const cbuf_end= net_store_length((char*) cbuf, (uint) m_colcnt);
>    DBUG_ASSERT(static_cast<my_size_t>(cbuf_end - cbuf) <= sizeof(cbuf));
>  
> +  /*
> +    Store the size of the field metadata.
> +  */
> +  char mbuf[sizeof(m_field_metadata_size)];
> +  char *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 byte*)m_dbnam,   m_dblen+1) ||
>            my_b_safe_write(file, tbuf,      sizeof(tbuf)) ||
>            my_b_safe_write(file, (const byte*)m_tblnam,  m_tbllen+1) ||
>            my_b_safe_write(file, reinterpret_cast<byte*>(cbuf),
>                            cbuf_end - (char*) cbuf) ||
> -          my_b_safe_write(file, reinterpret_cast<byte*>(m_coltype),
> m_colcnt));
> +          my_b_safe_write(file, reinterpret_cast<byte*>(m_coltype), m_colcnt)
> ||
> +          my_b_safe_write(file, reinterpret_cast<byte*>(mbuf), (size_t)
> (mbuf_end - mbuf)) ||
> +          my_b_safe_write(file, reinterpret_cast<byte*>(m_field_metadata),
> m_field_metadata_size),
> +          my_b_safe_write(file, reinterpret_cast<byte*>(m_null_bits),
> (m_colcnt + 7) / 8));
>   }
>  #endif
>  
>
> --- 1.149/sql/log_event.h	2007-07-26 20:48:26 -04:00
> +++ 1.150/sql/log_event.h	2007-07-26 20:48:26 -04:00
> @@ -2048,6 +2048,8 @@
>  
>    virtual int get_data_size() { return m_data_size; } 
>  #ifndef MYSQL_CLIENT
> +  virtual const int calc_field_metadata_size();
> +  virtual int save_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; }
> @@ -2083,6 +2085,14 @@
>    flag_set       m_flags;
>  
>    my_size_t      m_data_size;
> +
> +  uchar          *m_field_metadata;        // buffer for field metadata
> +  /*
> +    The size of field metadata buffer set by calling calc_field_metadata_size()
> +  */
> +  ulong         m_field_metadata_size;   
> +  uchar        *m_null_bits;
> +  gptr          m_meta_memory;
>  };
>  
>  
> --- New file ---
> +++ mysql-test/r/rpl_colSize.result	07/07/26 20:47:59
> 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 ***
> STOP SLAVE;
> RESET SLAVE;
> 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'),
> m TINYBLOB,
> n BLOB,
> o MEDIUMBLOB,
> p LONGBLOB,
> q TINYTEXT,
> r TEXT,
> s MEDIUMTEXT,
> t LONGTEXT
> );
> *** Create same table on master but with narrow columns ***
> CREATE TABLE t1 (
> a float     (44),
> b double    (10,3),
> c decimal   (10,2),
> d numeric   (3,0),
> e bit       (16),
> 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'),
> m TINYBLOB,
> n BLOB,
> o MEDIUMBLOB,
> p LONGBLOB,
> q TINYTEXT,
> r TEXT,
> s MEDIUMTEXT,
> t LONGTEXT
> );
> RESET MASTER;
> *** Start replication ***
> START SLAVE;
> *** Insert data on master and display it. ***
> INSERT INTO t1 () VALUES (
> 17.567, 
> 2.123, 
> 10.20, 
> 125,
> hex(64),
> 'TEST',
> 'This is a test',
> 'binary data',
> 'more binary data',
> '6',
> '7',
> "blob 1",
> "blob  2",
> "blob   3",
> "blob    4",
> "text 1",
> "text  2",
> "text   3",
> "text    4");
> SELECT * FROM t1 ORDER BY a;
> a	b	c	d	e	f	g	h	j	k	l	m	n	o	p	q	r	s	t
> 17.567	2.123	10.20	125	#	TEST	This is a test	#	more binary data	6	7	blob 1	blob 
> 2	blob   3	blob    4	text 1	text  2	text   3	text    4
> *** Select data from slave to compare ***
> SELECT * FROM t1 ORDER BY a;
> a	b	c	d	e	f	g	h	j	k	l	m	n	o	p	q	r	s	t
> 17.567	2.123000000	10.200000000000000000000000000000	125	#	TEST	This is a test	#	more
> binary data	6	7	blob 1	blob  2	blob   3	blob    4	text 1	text  2	text   3	text    4
> DROP TABLE t1;
> Create varchar table on master
> CREATE TABLE t1 (
> a VARCHAR(50),
> b VARCHAR(100),
> c VARCHAR(300),
> d CHAR(5)
> );
> Alter varchar table on slave
> ALTER TABLE t1 CHANGE COLUMN a a VARCHAR(100);
> ALTER TABLE t1 CHANGE COLUMN b b VARCHAR(400);
> ALTER TABLE t1 CHANGE COLUMN c c VARCHAR(500);
> ALTER TABLE t1 CHANGE COLUMN d d CHAR(100);
> Insert some values and select them on master
> INSERT INTO t1 VALUES ("This is a test of col a.", 
> "This is another test of col b.",
> "This is a test of the large col c.",
> "Col d");
> SELECT * FROM t1;
> a	b	c	d
> This is a test of col a.	This is another test of col b.	This is a test of the large
> col c.	Col d
> SHOW CREATE TABLE t1;
> Table	Create Table
> t1	CREATE TABLE `t1` (
>   `a` varchar(50) DEFAULT NULL,
>   `b` varchar(100) DEFAULT NULL,
>   `c` varchar(300) DEFAULT NULL,
>   `d` char(5) DEFAULT NULL
> ) ENGINE=MyISAM DEFAULT CHARSET=latin1
> Insert some values and select them on slave
> SELECT * FROM t1;
> a	b	c	d
> This is a test of col a.	This is another test of col b.	This is a test of the large
> col c.	Col d
> SHOW CREATE TABLE t1;
> Table	Create Table
> t1	CREATE TABLE `t1` (
>   `a` varchar(100) DEFAULT NULL,
>   `b` varchar(400) DEFAULT NULL,
>   `c` varchar(500) DEFAULT NULL,
>   `d` char(100) DEFAULT NULL
> ) ENGINE=MyISAM DEFAULT CHARSET=latin1
> DROP TABLE t1;
> Create bit table on master
> CREATE TABLE t1 (
> a BIT(7),
> b BIT(8),
> c BIT(21),
> d BIT(11),
> e BIT(11)
> );
> Create bit table on slave
> DROP TABLE t1;
> CREATE TABLE t1 (
> a BIT(16),
> b BIT(22),
> c BIT(54),
> d BIT(25),
> e BIT(13)
> );
> Insert some values and select them on master
> INSERT INTO t1 VALUES (
> b'1010101',
> b'10101011',
> b'101010110101010101111',
> b'10101010101',
> b'10101011111'
>   );
> SELECT BIN(a), BIN(b), BIN(c), BIN(d), BIN(e) FROM t1;
> BIN(a)	BIN(b)	BIN(c)	BIN(d)	BIN(e)
> 1010101	10101011	101010110101010101111	10101010101	10101011111
> SHOW CREATE TABLE t1;
> Table	Create Table
> t1	CREATE TABLE `t1` (
>   `a` bit(7) DEFAULT NULL,
>   `b` bit(8) DEFAULT NULL,
>   `c` bit(21) DEFAULT NULL,
>   `d` bit(11) DEFAULT NULL,
>   `e` bit(11) DEFAULT NULL
> ) ENGINE=MyISAM DEFAULT CHARSET=latin1
> Insert some values and select them on master
> SELECT BIN(a), BIN(b), BIN(c), BIN(d), BIN(e) FROM t1;
> BIN(a)	BIN(b)	BIN(c)	BIN(d)	BIN(e)
> 1010101	10101011	101010110101010101111	10101010101	10101011111
> SHOW CREATE TABLE t1;
> Table	Create Table
> t1	CREATE TABLE `t1` (
>   `a` bit(16) DEFAULT NULL,
>   `b` bit(22) DEFAULT NULL,
>   `c` bit(54) DEFAULT NULL,
>   `d` bit(25) DEFAULT NULL,
>   `e` bit(13) DEFAULT NULL
> ) ENGINE=MyISAM DEFAULT CHARSET=latin1
> *** Cleanup  ***
> DROP TABLE t1;
>
> --- New file ---
> +++ mysql-test/t/rpl_colSize.test	07/07/26 20:47:59
> ##################################################################
> # 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
>
> --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'),
>   m TINYBLOB,
>   n BLOB,
>   o MEDIUMBLOB,
>   p LONGBLOB,
>   q TINYTEXT,
>   r TEXT,
>   s MEDIUMTEXT,
>   t LONGTEXT
> );
>
> --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       (16),
>   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'),
>   m TINYBLOB,
>   n BLOB,
>   o MEDIUMBLOB,
>   p LONGBLOB,
>   q TINYTEXT,
>   r TEXT,
>   s MEDIUMTEXT,
>   t LONGTEXT
> );
>
> 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,
>   hex(64),
>   'TEST',
>   'This is a test',
>   'binary data',
>   'more binary data',
>   '6',
>   '7',
>   "blob 1",
>   "blob  2",
>   "blob   3",
>   "blob    4",
>   "text 1",
>   "text  2",
>   "text   3",
>   "text    4");
>
> # Replace values in columns that display differently between SBR & RBR
> --replace_column 5 # 8 #
> SELECT * FROM t1 ORDER BY a;
>
> --echo *** Select data from slave to compare ***
> sync_slave_with_master;
> connection slave;
>
> # Replace values in columns that display differently between SBR & RBR
> --replace_column 5 # 8 #
> SELECT * FROM t1 ORDER BY a;
>
> # Test boundary limits of varchar and char fields
> # Master/Slave
> # <256/<256 with m < s, m > s, and m == s <-- col a
> # >255/<256 with m < s, m > s, and m == s <-- error will be caught in
> BUG#22086
> # <256/>255 with m < s, m > s, and m == s <-- col b
> # >255/>255 with m < s, m > s, and m == s <-- col c
> #
> # Test boundary limits of CHAR fields
> # Master/Slave
> # <256/<256 with m < s, m > s, and m == s <-- col d
> # >255/<256 with m < s, m > s, and m == s <-- error char limited to
> 255 chars
> # <256/>255 with m < s, m > s, and m == s <-- error char limited to
> 255 chars
> # >255/>255 with m < s, m > s, and m == s <-- error char limited to
> 255 chars
>
> connection master;
> DROP TABLE t1;
>
> --echo Create varchar table on master
> CREATE TABLE t1 (
>   a VARCHAR(50),
>   b VARCHAR(100),
>   c VARCHAR(300),
>   d CHAR(5)
> );
>
> sync_slave_with_master slave;
>
> --echo Alter varchar table on slave
> ALTER TABLE t1 CHANGE COLUMN a a VARCHAR(100);
> ALTER TABLE t1 CHANGE COLUMN b b VARCHAR(400);
> ALTER TABLE t1 CHANGE COLUMN c c VARCHAR(500);
> ALTER TABLE t1 CHANGE COLUMN d d CHAR(100);
>
> connection master;
>
> --echo Insert some values and select them on master
> INSERT INTO t1 VALUES ("This is a test of col a.", 
>                        "This is another test of col b.",
>                        "This is a test of the large col c.",
>                        "Col d");
> SELECT * FROM t1;
> SHOW CREATE TABLE t1;
>
> sync_slave_with_master slave;
>
> --echo Insert some values and select them on slave
> SELECT * FROM t1;
> SHOW CREATE TABLE t1;
>
>
> # Test boundary limits of bit fields
> # m < s, m % 8 != 0, and s % 8 == 0 col a
> # m < s, m % 8 == 0, and s % 8 != 0 col b
> # m < s, m % 8 != 0, and s % 8 != 0 col c
> # m > s, m % 8 != 0, and s % 8 == 0 <-- error will be caught in BUG#22086
> # m > s, m % 8 == 0, and s % 8 != 0 <-- error will be caught in BUG#22086
> # m > s, m % 8 != 0, and s % 8 != 0 <-- error will be caught in BUG#22086
>
> connection master;
> DROP TABLE t1;
>
> --echo Create bit table on master
> CREATE TABLE t1 (
>   a BIT(7),
>   b BIT(8),
>   c BIT(21),
>   d BIT(11),
>   e BIT(11)
> );
>
> sync_slave_with_master slave;
>
> --echo Create bit table on slave
> DROP TABLE t1;
> CREATE TABLE t1 (
>   a BIT(16),
>   b BIT(22),
>   c BIT(54),
>   d BIT(25),
>   e BIT(13)
> );
>
> connection master;
>
> --echo Insert some values and select them on master
> INSERT INTO t1 VALUES (
>   b'1010101',
>   b'10101011',
>   b'101010110101010101111',
>   b'10101010101',
>   b'10101011111'
>   );
>
> SELECT BIN(a), BIN(b), BIN(c), BIN(d), BIN(e) FROM t1;
> SHOW CREATE TABLE t1;
>
> sync_slave_with_master slave;
>
> --echo Insert some values and select them on master
> SELECT BIN(a), BIN(b), BIN(c), BIN(d), BIN(e) FROM t1;
> SHOW CREATE TABLE t1;
>
> --echo *** Cleanup  ***
> connection master;
> DROP TABLE t1;
> sync_slave_with_master;
>
> # END 5.1 Test Case
>
>
> --- 1.25/mysql-test/r/rpl_ndb_log.result	2007-07-26 20:48:26 -04:00
> +++ 1.26/mysql-test/r/rpl_ndb_log.result	2007-07-26 20:48:26 -04:00
> @@ -88,12 +88,12 @@
>  master-bin.000002	#	Query	1	#	COMMIT
>  show binary logs;
>  Log_name	File_size
> -master-bin.000001	1775
> -master-bin.000002	617
> +master-bin.000001	1789
> +master-bin.000002	623
>  start slave;
>  show binary logs;
>  Log_name	File_size
> -slave-bin.000001	1870
> +slave-bin.000001	1884
>  slave-bin.000002	202
>  show binlog events in 'slave-bin.000001' from 4;
>  Log_name	Pos	Event_type	Server_id	End_log_pos	Info
> @@ -128,7 +128,7 @@
>  slave-bin.000002	#	Query	2	#	COMMIT
>  show slave status;
>   

Since you're changing this one anyway, make it a vertical display to 
make it easier in the future.

> 
> 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
>
> -#	127.0.0.1	root	MASTER_PORT	1	master-bin.000002	617	#	#	master-bin.000002	Yes	Yes				#			0		0	617	#	None		0	No						#	No
>
> +#	127.0.0.1	root	MASTER_PORT	1	master-bin.000002	623	#	#	master-bin.000002	Yes	Yes				#			0		0	623	#	None		0	No						#	No
>  show binlog events in 'slave-bin.000005' from 4;
>  ERROR HY000: Error when executing command SHOW BINLOG EVENTS: Could not find target
> log
>  DROP TABLE t1;
>
> --- 1.17/mysql-test/r/rpl_row_log_innodb.result	2007-07-26 20:48:26 -04:00
> +++ 1.18/mysql-test/r/rpl_row_log_innodb.result	2007-07-26 20:48:26 -04:00
> @@ -71,13 +71,13 @@
>  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
> @@ -101,7 +101,7 @@
>  slave-bin.000002	#	Xid	1	#	COMMIT /* XID */
>  show slave status;
>   

Same here. You could do the switch from horizontal to vertical display 
in a separate patch and push that with this patch.

> 
> 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
>
> -#	127.0.0.1	root	MASTER_PORT	1	master-bin.000002	404	#	#	master-bin.000002	Yes	Yes				#			0		0	404	#	None		0	No						#	No
>
> +#	127.0.0.1	root	MASTER_PORT	1	master-bin.000002	406	#	#	master-bin.000002	Yes	Yes				#			0		0	406	#	None		0	No						#	No
>  show binlog events in 'slave-bin.000005' from 4;
>  ERROR HY000: Error when executing command SHOW BINLOG EVENTS: Could not find target
> log
>  DROP TABLE t1;
>
> --- 1.12/mysql-test/r/rpl_row_create_table.result	2007-07-26 20:48:26 -04:00
> +++ 1.13/mysql-test/r/rpl_row_create_table.result	2007-07-26 20:48:26 -04:00
> @@ -127,7 +127,7 @@
>  NULL	6	12
>  CREATE TABLE t7 (UNIQUE(b)) SELECT a,b FROM tt3;
>  ERROR 23000: Duplicate entry '2' for key 'b'
> -SHOW BINLOG EVENTS FROM 1098;
> +SHOW BINLOG EVENTS FROM 1100;
>  Log_name	Pos	Event_type	Server_id	End_log_pos	Info
>  CREATE TABLE t7 (a INT, b INT UNIQUE);
>  INSERT INTO t7 SELECT a,b FROM tt3;
> @@ -137,11 +137,11 @@
>  1	2
>  2	4
>  3	6
> -SHOW BINLOG EVENTS FROM 1098;
> +SHOW BINLOG EVENTS FROM 1100;
>  Log_name	Pos	Event_type	Server_id	End_log_pos	Info
> -#	1098	Query	#	1198	use `test`; CREATE TABLE t7 (a INT, b INT UNIQUE)
> -#	1198	Table_map	#	1238	table_id: # (test.t7)
> -#	1238	Write_rows	#	1294	table_id: # flags: STMT_END_F
> +#	1100	Query	#	1200	use `test`; CREATE TABLE t7 (a INT, b INT UNIQUE)
> +#	1200	Table_map	#	1242	table_id: # (test.t7)
> +#	1242	Write_rows	#	1298	table_id: # flags: STMT_END_F
>  SELECT * FROM t7 ORDER BY a,b;
>  a	b
>  1	2
> @@ -154,10 +154,10 @@
>  ROLLBACK;
>  Warnings:
>  Warning	1196	Some non-transactional changed tables couldn't be rolled back
> -SHOW BINLOG EVENTS FROM 1294;
> +SHOW BINLOG EVENTS FROM 1298;
>  Log_name	Pos	Event_type	Server_id	End_log_pos	Info
> -#	1294	Table_map	#	1334	table_id: # (test.t7)
> -#	1334	Write_rows	#	1390	table_id: # flags: STMT_END_F
> +#	1298	Table_map	#	1340	table_id: # (test.t7)
> +#	1340	Write_rows	#	1396	table_id: # flags: STMT_END_F
>  SELECT * FROM t7 ORDER BY a,b;
>  a	b
>  1	2
> @@ -192,10 +192,10 @@
>    `a` int(11) DEFAULT NULL,
>    `b` int(11) DEFAULT NULL
>  ) ENGINE=MyISAM DEFAULT CHARSET=latin1
> -SHOW BINLOG EVENTS FROM 1390;
> +SHOW BINLOG EVENTS FROM 1396;
>  Log_name	Pos	Event_type	Server_id	End_log_pos	Info
> -#	1390	Query	#	1476	use `test`; CREATE TABLE t8 LIKE t4
> -#	1476	Query	#	1615	use `test`; CREATE TABLE `t9` (
> +#	1396	Query	#	1482	use `test`; CREATE TABLE t8 LIKE t4
> +#	1482	Query	#	1621	use `test`; CREATE TABLE `t9` (
>    `a` int(11) DEFAULT NULL,
>    `b` int(11) DEFAULT NULL
>  )
> @@ -276,31 +276,31 @@
>  Log_name	Pos	Event_type	Server_id	End_log_pos	Info
>  #	4	Format_desc	#	106	Server ver: #, Binlog ver: #
>  #	106	Query	#	192	use `test`; CREATE TABLE t1 (a INT)
> -#	192	Table_map	#	231	table_id: # (test.t1)
> -#	231	Write_rows	#	275	table_id: # flags: STMT_END_F
> -#	275	Query	#	343	use `test`; BEGIN
> -#	343	Query	#	125	use `test`; CREATE TABLE `t2` (
> +#	192	Table_map	#	233	table_id: # (test.t1)
> +#	233	Write_rows	#	277	table_id: # flags: STMT_END_F
> +#	277	Query	#	345	use `test`; BEGIN
> +#	345	Query	#	125	use `test`; CREATE TABLE `t2` (
>    `a` int(11) DEFAULT NULL
>  ) ENGINE=InnoDB
> -#	468	Table_map	#	164	table_id: # (test.t2)
> -#	507	Write_rows	#	208	table_id: # flags: STMT_END_F
> -#	551	Xid	#	578	COMMIT /* XID */
> -#	578	Query	#	646	use `test`; BEGIN
> -#	646	Query	#	125	use `test`; CREATE TABLE `t3` (
> +#	470	Table_map	#	166	table_id: # (test.t2)
> +#	511	Write_rows	#	210	table_id: # flags: STMT_END_F
> +#	555	Xid	#	582	COMMIT /* XID */
> +#	582	Query	#	650	use `test`; BEGIN
> +#	650	Query	#	125	use `test`; CREATE TABLE `t3` (
>    `a` int(11) DEFAULT NULL
>  ) ENGINE=InnoDB
> -#	771	Table_map	#	164	table_id: # (test.t3)
> -#	810	Write_rows	#	208	table_id: # flags: STMT_END_F
> -#	854	Xid	#	881	COMMIT /* XID */
> -#	881	Query	#	949	use `test`; BEGIN
> -#	949	Query	#	125	use `test`; CREATE TABLE `t4` (
> +#	775	Table_map	#	166	table_id: # (test.t3)
> +#	816	Write_rows	#	210	table_id: # flags: STMT_END_F
> +#	860	Xid	#	887	COMMIT /* XID */
> +#	887	Query	#	955	use `test`; BEGIN
> +#	955	Query	#	125	use `test`; CREATE TABLE `t4` (
>    `a` int(11) DEFAULT NULL
>  ) ENGINE=InnoDB
> -#	1074	Table_map	#	164	table_id: # (test.t4)
> -#	1113	Write_rows	#	208	table_id: # flags: STMT_END_F
> -#	1157	Xid	#	1184	COMMIT /* XID */
> -#	1184	Table_map	#	1223	table_id: # (test.t1)
> -#	1223	Write_rows	#	1267	table_id: # flags: STMT_END_F
> +#	1080	Table_map	#	166	table_id: # (test.t4)
> +#	1121	Write_rows	#	210	table_id: # flags: STMT_END_F
> +#	1165	Xid	#	1192	COMMIT /* XID */
> +#	1192	Table_map	#	1233	table_id: # (test.t1)
> +#	1233	Write_rows	#	1277	table_id: # flags: STMT_END_F
>  SHOW TABLES;
>  Tables_in_test
>  t1
> @@ -367,15 +367,15 @@
>  Log_name	Pos	Event_type	Server_id	End_log_pos	Info
>  #	4	Format_desc	#	106	Server ver: #, Binlog ver: #
>  #	106	Query	#	192	use `test`; CREATE TABLE t1 (a INT)
> -#	192	Table_map	#	231	table_id: # (test.t1)
> -#	231	Write_rows	#	275	table_id: # flags: STMT_END_F
> -#	275	Query	#	375	use `test`; CREATE TABLE t2 (a INT) ENGINE=INNODB
> -#	375	Query	#	443	use `test`; BEGIN
> -#	443	Table_map	#	39	table_id: # (test.t2)
> -#	482	Write_rows	#	83	table_id: # flags: STMT_END_F
> -#	526	Table_map	#	122	table_id: # (test.t2)
> -#	565	Write_rows	#	161	table_id: # flags: STMT_END_F
> -#	604	Xid	#	631	COMMIT /* XID */
> +#	192	Table_map	#	233	table_id: # (test.t1)
> +#	233	Write_rows	#	277	table_id: # flags: STMT_END_F
> +#	277	Query	#	377	use `test`; CREATE TABLE t2 (a INT) ENGINE=INNODB
> +#	377	Query	#	445	use `test`; BEGIN
> +#	445	Table_map	#	41	table_id: # (test.t2)
> +#	486	Write_rows	#	85	table_id: # flags: STMT_END_F
> +#	530	Table_map	#	126	table_id: # (test.t2)
> +#	571	Write_rows	#	165	table_id: # flags: STMT_END_F
> +#	610	Xid	#	637	COMMIT /* XID */
>  SELECT * FROM t2 ORDER BY a;
>  a
>  1
> @@ -394,10 +394,10 @@
>  ROLLBACK;
>  SELECT * FROM t2 ORDER BY a;
>  a
> -SHOW BINLOG EVENTS FROM 631;
> +SHOW BINLOG EVENTS FROM 637;
>  Log_name	Pos	Event_type	Server_id	End_log_pos	Info
> -#	631	Query	#	80	use `test`; TRUNCATE TABLE t2
> -#	711	Xid	#	738	COMMIT /* XID */
> +#	637	Query	#	80	use `test`; TRUNCATE TABLE t2
> +#	717	Xid	#	744	COMMIT /* XID */
>  SELECT * FROM t2 ORDER BY a;
>  a
>  DROP TABLE t1,t2;
>
> --- 1.5/mysql-test/r/rpl_row_flsh_tbls.result	2007-07-26 20:48:26 -04:00
> +++ 1.6/mysql-test/r/rpl_row_flsh_tbls.result	2007-07-26 20:48:26 -04:00
> @@ -12,13 +12,13 @@
>  insert into t4 select * from t3;
>  rename table t1 to t5, t2 to t1;
>  flush no_write_to_binlog tables;
> -SHOW BINLOG EVENTS FROM 619 ;
> +SHOW BINLOG EVENTS FROM 623 ;
>  Log_name	Pos	Event_type	Server_id	End_log_pos	Info
>  master-bin.000001	#	Query	1	#	use `test`; rename table t1 to t5, t2 to t1
>  select * from t3;
>  a
>  flush tables;
> -SHOW BINLOG EVENTS FROM 619 ;
> +SHOW BINLOG EVENTS FROM 623 ;
>  Log_name	Pos	Event_type	Server_id	End_log_pos	Info
>  master-bin.000001	#	Query	1	#	use `test`; rename table t1 to t5, t2 to t1
>  master-bin.000001	#	Query	1	#	use `test`; flush tables
>
> --- 1.7/mysql-test/r/rpl_row_inexist_tbl.result	2007-07-26 20:48:26 -04:00
> +++ 1.8/mysql-test/r/rpl_row_inexist_tbl.result	2007-07-26 20:48:26 -04:00
> @@ -39,7 +39,7 @@
>  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	
>
> --- 1.17/mysql-test/r/rpl_row_log.result	2007-07-26 20:48:26 -04:00
> +++ 1.18/mysql-test/r/rpl_row_log.result	2007-07-26 20:48:26 -04:00
> @@ -66,13 +66,13 @@
>  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
> @@ -93,7 +93,7 @@
>  slave-bin.000002	#	Write_rows	1	#	table_id: # flags: STMT_END_F
>  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
>
> -#	127.0.0.1	root	MASTER_PORT	1	master-bin.000002	377	#	#	master-bin.000002	Yes	Yes				#			0		0	377	#	None		0	No						#	No
>
> +#	127.0.0.1	root	MASTER_PORT	1	master-bin.000002	379	#	#	master-bin.000002	Yes	Yes				#			0		0	379	#	None		0	No						#	No
>  show binlog events in 'slave-bin.000005' from 4;
>  ERROR HY000: Error when executing command SHOW BINLOG EVENTS: Could not find target
> log
>  DROP TABLE t1;
>
> --- 1.9/mysql-test/r/rpl_row_max_relay_size.result	2007-07-26 20:48:26 -04:00
> +++ 1.10/mysql-test/r/rpl_row_max_relay_size.result	2007-07-26 20:48:26 -04:00
> @@ -30,7 +30,7 @@
>  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 @@
>  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	
> @@ -74,7 +74,7 @@
>  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
> @@ -89,7 +89,7 @@
>  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	
> @@ -118,7 +118,7 @@
>  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
> @@ -133,7 +133,7 @@
>  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	
> @@ -201,7 +201,7 @@
>  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
> @@ -216,7 +216,7 @@
>  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	
> @@ -241,7 +241,7 @@
>  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
> @@ -256,7 +256,7 @@
>  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	
>
> --- 1.5/mysql-test/r/rpl_row_until.result	2007-07-26 20:48:26 -04:00
> +++ 1.6/mysql-test/r/rpl_row_until.result	2007-07-26 20:48:26 -04:00
> @@ -21,7 +21,7 @@
>  4
>  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
>
> -#	127.0.0.1	root	MASTER_MYPORT	1	master-bin.000001	744	slave-relay-bin.000004	#	master-bin.000001	#	No							0		0	315	#	Master	master-bin.000001	311	No						#	No
>
> +#	127.0.0.1	root	MASTER_MYPORT	1	master-bin.000001	750	slave-relay-bin.000004	#	master-bin.000001	#	No							0		0	317	#	Master	master-bin.000001	311	No						#	No
>  start slave until master_log_file='master-no-such-bin.000001', master_log_pos=291;
>  select * from t1;
>  n
> @@ -31,7 +31,7 @@
>  4
>  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
>
> -#	127.0.0.1	root	MASTER_MYPORT	1	master-bin.000001	744	slave-relay-bin.000004	#	master-bin.000001	#	No							0		0	315	#	Master	master-no-such-bin.000001	291	No						#	No
>
> +#	127.0.0.1	root	MASTER_MYPORT	1	master-bin.000001	750	slave-relay-bin.000004	#	master-bin.000001	#	No							0		0	317	#	Master	master-no-such-bin.000001	291	No						#	No
>  start slave until relay_log_file='slave-relay-bin.000004', relay_log_pos=728;
>  select * from t2;
>  n
> @@ -39,13 +39,13 @@
>  2
>  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
>
> -#	127.0.0.1	root	MASTER_MYPORT	1	master-bin.000001	744	slave-relay-bin.000004	#	master-bin.000001	#	No							0		0	590	#	Relay	slave-relay-bin.000004	728	No						#	No
>
> +#	127.0.0.1	root	MASTER_MYPORT	1	master-bin.000001	750	slave-relay-bin.000004	#	master-bin.000001	#	No							0		0	594	#	Relay	slave-relay-bin.000004	728	No						#	No
>  start slave;
>  stop slave;
>  start slave until master_log_file='master-bin.000001', master_log_pos=740;
>  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
>
> -#	127.0.0.1	root	MASTER_MYPORT	1	master-bin.000001	744	slave-relay-bin.000004	#	master-bin.000001	Yes	No							0		0	744	#	Master	master-bin.000001	740	No						#	No
>
> +#	127.0.0.1	root	MASTER_MYPORT	1	master-bin.000001	750	slave-relay-bin.000004	#	master-bin.000001	Yes	No							0		0	750	#	Master	master-bin.000001	740	No						#	No
>  start slave until master_log_file='master-bin', master_log_pos=561;
>  ERROR HY000: Incorrect parameter or combination of parameters for START SLAVE UNTIL
>  start slave until master_log_file='master-bin.000001', master_log_pos=561,
> relay_log_pos=12;
>
> --- 1.9/mysql-test/t/binlog_row_mix_innodb_myisam.test	2007-07-26 20:48:26 -04:00
> +++ 1.10/mysql-test/t/binlog_row_mix_innodb_myisam.test	2007-07-26 20:48:26 -04: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=524 $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"))
>
> --- 1.12/mysql-test/t/rpl_row_create_table.test	2007-07-26 20:48:26 -04:00
> +++ 1.13/mysql-test/t/rpl_row_create_table.test	2007-07-26 20:48:26 -04:00
> @@ -72,7 +72,7 @@
>  # 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 1100;
>  
>  # Test that INSERT-SELECT works the same way as for SBR.
>  CREATE TABLE t7 (a INT, b INT UNIQUE);
> @@ -82,7 +82,7 @@
>  # 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 1100;
>  sync_slave_with_master;
>  SELECT * FROM t7 ORDER BY a,b;
>  
> @@ -94,7 +94,7 @@
>  ROLLBACK;
>  --replace_column 1 # 4 #
>  --replace_regex /\/\* xid=.* \*\//\/* XID *\// /table_id: [0-9]+/table_id: #/
> -SHOW BINLOG EVENTS FROM 1294;
> +SHOW BINLOG EVENTS FROM 1298;
>  SELECT * FROM t7 ORDER BY a,b;
>  sync_slave_with_master;
>  SELECT * FROM t7 ORDER BY a,b;
> @@ -110,7 +110,7 @@
>  --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 @@
>  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;
>  
>
> --- 1.5/mysql-test/t/rpl_row_flsh_tbls.test	2007-07-26 20:48:26 -04:00
> +++ 1.6/mysql-test/t/rpl_row_flsh_tbls.test	2007-07-26 20:48:26 -04: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
>
> --- 1.14/sql/rpl_rli.h	2007-07-26 20:48:26 -04:00
> +++ 1.15/sql/rpl_rli.h	2007-07-26 20:48:26 -04:00
> @@ -19,6 +19,7 @@
>  #define MAX_SLAVE_ERRMSG      1024
>  
>  #include "rpl_tblmap.h"
> +#include "rpl_utility.h"
>  
>  struct RPL_TABLE_LIST;
>  
> @@ -304,6 +305,15 @@
>    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
>
> --- 1.7/mysql-test/r/rpl_rbr_to_sbr.result	2007-07-26 20:48:27 -04:00
> +++ 1.8/mysql-test/r/rpl_rbr_to_sbr.result	2007-07-26 20:48:27 -04:00
> @@ -28,7 +28,7 @@
>  Master_Port	MASTER_PORT
>  Connect_Retry	1
>  Master_Log_File	master-bin.000001
> -Read_Master_Log_Pos	454
> +Read_Master_Log_Pos	457
>  Relay_Log_File	#
>  Relay_Log_Pos	#
>  Relay_Master_Log_File	master-bin.000001
> @@ -43,7 +43,7 @@
>  Last_Errno	0
>  Last_Error	
>  Skip_Counter	0
> -Exec_Master_Log_Pos	454
> +Exec_Master_Log_Pos	457
>  Relay_Log_Space	#
>  Until_Condition	None
>  Until_Log_File	
>
> --- 1.16/mysql-test/r/rpl_row_basic_11bugs.result	2007-07-26 20:48:27 -04:00
> +++ 1.17/mysql-test/r/rpl_row_basic_11bugs.result	2007-07-26 20:48:27 -04:00
> @@ -56,8 +56,8 @@
>  Log_name	Pos	Event_type	Server_id	End_log_pos	Info
>  master-bin.000001	4	Format_desc	1	106	Server ver: SERVER_VERSION, Binlog ver: 4
>  master-bin.000001	106	Query	1	192	use `test`; CREATE TABLE t1 (a INT)
> -master-bin.000001	192	Table_map	1	231	table_id: # (test.t1)
> -master-bin.000001	231	Write_rows	1	270	table_id: # flags: STMT_END_F
> +master-bin.000001	192	Table_map	1	233	table_id: # (test.t1)
> +master-bin.000001	233	Write_rows	1	272	table_id: # flags: STMT_END_F
>  DROP TABLE t1;
>  ================ Test for BUG#17620 ================
>  drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
>
> --- 1.10/mysql-test/r/rpl_truncate_7ndb.result	2007-07-26 20:48:27 -04:00
> +++ 1.11/mysql-test/r/rpl_truncate_7ndb.result	2007-07-26 20:48:27 -04:00
> @@ -32,14 +32,14 @@
>  master-bin.000001	4	Format_desc	1	106	Server ver: SERVER_VERSION, Binlog ver: 4
>  master-bin.000001	106	Query	1	223	use `test`; CREATE TABLE t1 (a INT PRIMARY KEY, b
> LONG) ENGINE=NDB
>  master-bin.000001	223	Query	1	287	BEGIN
> -master-bin.000001	287	Table_map	1	40	table_id: # (test.t1)
> -master-bin.000001	327	Table_map	1	98	table_id: # (mysql.ndb_apply_status)
> -master-bin.000001	385	Write_rows	1	157	table_id: #
> -master-bin.000001	444	Write_rows	1	195	table_id: #
> -master-bin.000001	482	Write_rows	1	233	table_id: # flags: STMT_END_F
> -master-bin.000001	520	Query	1	585	COMMIT
> -master-bin.000001	585	Query	1	665	use `test`; TRUNCATE TABLE t1
> -master-bin.000001	665	Query	1	741	use `test`; DROP TABLE t1
> +master-bin.000001	287	Table_map	1	43	table_id: # (test.t1)
> +master-bin.000001	330	Table_map	1	105	table_id: # (mysql.ndb_apply_status)
> +master-bin.000001	392	Write_rows	1	164	table_id: #
> +master-bin.000001	451	Write_rows	1	202	table_id: #
> +master-bin.000001	489	Write_rows	1	240	table_id: # flags: STMT_END_F
> +master-bin.000001	527	Query	1	592	COMMIT
> +master-bin.000001	592	Query	1	672	use `test`; TRUNCATE TABLE t1
> +master-bin.000001	672	Query	1	748	use `test`; DROP TABLE t1
>  **** On Master ****
>  CREATE TABLE t1 (a INT PRIMARY KEY, b LONG) ENGINE=NDB;
>  INSERT INTO t1 VALUES (1,1), (2,2);
> @@ -69,27 +69,27 @@
>  master-bin.000001	4	Format_desc	1	106	Server ver: SERVER_VERSION, Binlog ver: 4
>  master-bin.000001	106	Query	1	223	use `test`; CREATE TABLE t1 (a INT PRIMARY KEY, b
> LONG) ENGINE=NDB
>  master-bin.000001	223	Query	1	287	BEGIN
> -master-bin.000001	287	Table_map	1	40	table_id: # (test.t1)
> -master-bin.000001	327	Table_map	1	98	table_id: # (mysql.ndb_apply_status)
> -master-bin.000001	385	Write_rows	1	157	table_id: #
> -master-bin.000001	444	Write_rows	1	195	table_id: #
> -master-bin.000001	482	Write_rows	1	233	table_id: # flags: STMT_END_F
> -master-bin.000001	520	Query	1	585	COMMIT
> -master-bin.000001	585	Query	1	665	use `test`; TRUNCATE TABLE t1
> -master-bin.000001	665	Query	1	741	use `test`; DROP TABLE t1
> -master-bin.000001	741	Query	1	858	use `test`; CREATE TABLE t1 (a INT PRIMARY KEY, b
> LONG) ENGINE=NDB
> -master-bin.000001	858	Query	1	922	BEGIN
> -master-bin.000001	922	Table_map	1	40	table_id: # (test.t1)
> -master-bin.000001	962	Table_map	1	98	table_id: # (mysql.ndb_apply_status)
> -master-bin.000001	1020	Write_rows	1	157	table_id: #
> -master-bin.000001	1079	Write_rows	1	195	table_id: #
> -master-bin.000001	1117	Write_rows	1	233	table_id: # flags: STMT_END_F
> -master-bin.000001	1155	Query	1	1220	COMMIT
> -master-bin.000001	1220	Query	1	1284	BEGIN
> -master-bin.000001	1284	Table_map	1	40	table_id: # (test.t1)
> -master-bin.000001	1324	Table_map	1	98	table_id: # (mysql.ndb_apply_status)
> -master-bin.000001	1382	Write_rows	1	157	table_id: #
> -master-bin.000001	1441	Delete_rows	1	191	table_id: #
> -master-bin.000001	1475	Delete_rows	1	225	table_id: # flags: STMT_END_F
> -master-bin.000001	1509	Query	1	1574	COMMIT
> -master-bin.000001	1574	Query	1	1650	use `test`; DROP TABLE t1
> +master-bin.000001	287	Table_map	1	43	table_id: # (test.t1)
> +master-bin.000001	330	Table_map	1	105	table_id: # (mysql.ndb_apply_status)
> +master-bin.000001	392	Write_rows	1	164	table_id: #
> +master-bin.000001	451	Write_rows	1	202	table_id: #
> +master-bin.000001	489	Write_rows	1	240	table_id: # flags: STMT_END_F
> +master-bin.000001	527	Query	1	592	COMMIT
> +master-bin.000001	592	Query	1	672	use `test`; TRUNCATE TABLE t1
> +master-bin.000001	672	Query	1	748	use `test`; DROP TABLE t1
> +master-bin.000001	748	Query	1	865	use `test`; CREATE TABLE t1 (a INT PRIMARY KEY, b
> LONG) ENGINE=NDB
> +master-bin.000001	865	Query	1	929	BEGIN
> +master-bin.000001	929	Table_map	1	43	table_id: # (test.t1)
> +master-bin.000001	972	Table_map	1	105	table_id: # (mysql.ndb_apply_status)
> +master-bin.000001	1034	Write_rows	1	164	table_id: #
> +master-bin.000001	1093	Write_rows	1	202	table_id: #
> +master-bin.000001	1131	Write_rows	1	240	table_id: # flags: STMT_END_F
> +master-bin.000001	1169	Query	1	1234	COMMIT
> +master-bin.000001	1234	Query	1	1298	BEGIN
> +master-bin.000001	1298	Table_map	1	43	table_id: # (test.t1)
> +master-bin.000001	1341	Table_map	1	105	table_id: # (mysql.ndb_apply_status)
> +master-bin.000001	1403	Write_rows	1	164	table_id: #
> +master-bin.000001	1462	Delete_rows	1	198	table_id: #
> +master-bin.000001	1496	Delete_rows	1	232	table_id: # flags: STMT_END_F
> +master-bin.000001	1530	Query	1	1595	COMMIT
> +master-bin.000001	1595	Query	1	1671	use `test`; DROP TABLE t1
>
> --- 1.5/sql/rpl_utility.cc	2007-07-26 20:48:27 -04:00
> +++ 1.6/sql/rpl_utility.cc	2007-07-26 20:48:27 -04:00
> @@ -15,17 +15,46 @@
>  
>  #include "rpl_utility.h"
>  
> -uint32
> -field_length_from_packed(enum_field_types const field_type, 
> -                         byte 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::calc_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] & 0xff00) == (MYSQL_TYPE_SET << 8)) ||
> +        ((m_field_metadata[col] & 0xff00) == (MYSQL_TYPE_ENUM << 8)))
> +      length= m_field_metadata[col] & 0x00ff;
> +    else
> +    {
> +      length= m_field_metadata[col] & 0x00ff;
> +      if (length > 255)
> +        length= uint2korr(master_data) + 2;
> +      else
> +        length= (uint) *master_data + 1;
> +    }
>      break;
> +  }
>    case MYSQL_TYPE_YEAR:
>    case MYSQL_TYPE_TINY:
>      length= 1;
> @@ -44,12 +73,6 @@
>      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;
> @@ -57,8 +80,6 @@
>      length= 3;
>      break;
>    case MYSQL_TYPE_DATE:
> -    length= 4;
> -    break;
>    case MYSQL_TYPE_TIME:
>      length= 3;
>      break;
> @@ -68,41 +89,34 @@
>    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_len= (m_field_metadata[col] >> 8U) & 0x00ff;
> +    uint from_bit_len= m_field_metadata[col] & 0x00ff;
> +    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]);
>   

Is it not possible to at least allocate the Field_blob instance on the 
stack by removing the "new"?

> +    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?
>  
> @@ -135,8 +149,14 @@
>                      tsh->fields);
>    }
>  
> +  /*
> +    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);
>
> --- 1.5/sql/rpl_utility.h	2007-07-26 20:48:27 -04:00
> +++ 1.6/sql/rpl_utility.h	2007-07-26 20:48:27 -04: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, byte const *data);
> -
>  /**
>    A table definition from the master.
>  
> @@ -57,19 +55,90 @@
>  
>      @param types Array of types
>      @param size  Number of elements in array 'types'
> +    @param field_metadata Array of extra information about fields
> +    @param metadata_size Size of the field_metadata array
> +    @param null_bitmap The bitmap of fields that can be null
>     */
> -  table_def(field_type *types, my_size_t 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(0),
> +      m_field_metadata(0), m_null_bits(0), m_memory(NULL)
>    {
> +    m_memory= my_multi_malloc(MYF(MY_WME),
> +                              &m_type, size,
> +                              &m_field_metadata, size * sizeof(short),
> +                              &m_null_bits, (m_size + 7) / 8,
> +                              NULL);
>      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 an older version server since 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)
> +    { 
> +      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_SET:
> +        case MYSQL_TYPE_ENUM:
> +        case MYSQL_TYPE_STRING:
> +        {
> +          short int x= field_metadata[index++] << 8U; // real_type
> +          x = x + field_metadata[index++];            // pack or field length
> +          m_field_metadata[i]= x;
> +          break;
> +        }
> +        case MYSQL_TYPE_BIT:
> +        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
> +          x = x + field_metadata[index++];            // decimals
> +          m_field_metadata[i]= x;
> +          break;
> +        }
> +        default:
> +          m_field_metadata[i]= 0;
> +          break;
> +        }
> +      }
> +    }
>   

If you do as I suggested above (using net_store_length()), the above 
code (the for-loop with the switch inside) can be replaced with:

      for (unsigned int i= 0; i < m_size; i++)
        m_field_metadata[i]= net_field_length(&field_metadata);


> +    if (m_size && null_bitmap)
> +       memcpy(m_null_bits, null_bitmap, (m_size + 7) / 8);
>    }
>  
>    ~table_def() {
> -    if (m_type)
> -      delete [] m_type;
> +    my_free(m_memory, MYF(0));
>  #ifndef DBUG_OFF
>      m_type= 0;
>      m_size= 0;
> @@ -100,6 +169,47 @@
>      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.
> +  */
> +  uint16 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(uint 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 calc_field_size(uint col, uchar *master_data);
> +
>    /**
>      Decide if the table definition is compatible with a table.
>  
> @@ -122,6 +232,9 @@
>  private:
>    my_size_t 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;
> +  gptr m_memory;
>  };
>  
>  /**
>
> --- 1.2/sql/rpl_record.cc	2007-07-26 20:48:27 -04:00
> +++ 1.3/sql/rpl_record.cc	2007-07-26 20:48:27 -04:00
> @@ -16,6 +16,8 @@
>  #include "mysql_priv.h"
>  #include "rpl_record.h"
>  #include "slave.h"                  // Need to pull in slave_print_msg
> +#include "rpl_utility.h"
> +#include "rpl_rli.h"
>  
>  /**
>     Pack a record of data for a table into a format suitable for
> @@ -190,7 +192,9 @@
>    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);
>   

Why do you need to cast away const-ness? Conceptually, I would say that 
get_tabledef() does not require a non-const RELAY_LOG_INFO instance: if 
it changes things internally, I would suggest placing a cast there 
instead of forcing the interface to adapt to implementation issues.

> +  for (field_ptr= begin_ptr ; field_ptr < end_ptr && *field_ptr ;
> ++field_ptr)
>    {
>      Field *const f= *field_ptr;
>  
> @@ -219,14 +223,20 @@
>          f->set_notnull();
>  
>          /*
> -          We only unpack the field if it was non-null
> -        */
> -        pack_ptr= f->unpack(f->ptr, pack_ptr);
> +          We only unpack the field if it was non-null.
> +          Use the master's size information if available else call
> +          normal unpack operation.
> +         */
> +        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++;
>   
>    }
>  
>    /*
>
>
>   


-- 
Mats Kindahl
Lead Software Developer
Replication Team
MySQL AB, www.mysql.com


Thread
bk commit into 5.1 tree (cbell:1.2564)cbell27 Jul
  • Re: bk commit into 5.1 tree (cbell:1.2564)Mats Kindahl27 Jul
    • RE: bk commit into 5.1 tree (cbell:1.2564)Chuck Bell27 Jul