diff options
author | unknown <cbell/Chuck@mysql_cab_desk.> | 2007-08-10 12:48:01 -0400 |
---|---|---|
committer | unknown <cbell/Chuck@mysql_cab_desk.> | 2007-08-10 12:48:01 -0400 |
commit | 9ad300d50d531d930c649002ee34123b452ec526 (patch) | |
tree | d3ef511f255d489f7a8ebaf7ce57c0512a4a2607 /sql/log_event.cc | |
parent | 21c55af5a103bcd3133c28073a7cd6e09d0521e3 (diff) | |
download | mariadb-git-9ad300d50d531d930c649002ee34123b452ec526.tar.gz |
BUG#22086 : Extra Slave Col: Char(5) on slave and Char(10) on master cause mysqld crash
This patch adds functionality to row-based replication to ensure the
slave's column sizes are >= to that of the master.
It also includes some refactoring for the code from WL#3228.
mysql-test/extra/rpl_tests/rpl_extraSlave_Col.test:
BUG#22086 : Extra Slave Col: Char(5) on slave and Char(10) on master cause mysqld crash
Removed commented out portion of test referenced in bug report. This
test supports the original request of the bug report.
mysql-test/suite/rpl/r/rpl_extraCol_innodb.result:
BUG#22086 : Extra Slave Col: Char(5) on slave and Char(10) on master cause mysqld crash
New result file for additional test.
mysql-test/suite/rpl/r/rpl_extraCol_myisam.result:
BUG#22086 : Extra Slave Col: Char(5) on slave and Char(10) on master cause mysqld crash
New result file for additional test.
mysql-test/suite/rpl_ndb/r/rpl_ndb_extraCol.result:
BUG#22086 : Extra Slave Col: Char(5) on slave and Char(10) on master cause mysqld crash
New result file for additional test.
sql/field.cc:
BUG#22086 : Extra Slave Col: Char(5) on slave and Char(10) on master cause mysqld crash
This patch refactors the additions made by this bug patch and those
made by WL#3228. The effort consolidates the large switches on type()
into functions within the field classes.
sql/field.h:
BUG#22086 : Extra Slave Col: Char(5) on slave and Char(10) on master cause mysqld crash
This patch refactors the additions made by this bug patch and those
made by WL#3228. The effort consolidates the large switches on type()
into functions within the field classes.
sql/log_event.cc:
BUG#22086 : Extra Slave Col: Char(5) on slave and Char(10) on master cause mysqld crash
This patch refactors the calc_field_size() method to use the new
methods implemented in the field classes. It also corrects comments
concerning how replication of field metadata works.
sql/log_event.h:
BUG#22086 : Extra Slave Col: Char(5) on slave and Char(10) on master cause mysqld crash
This patch refactors out the calc_field_size() method into the method
save_field_metadata().
sql/rpl_utility.cc:
BUG#22086 : Extra Slave Col: Char(5) on slave and Char(10) on master cause mysqld crash
This patch adds a method to check the size of the field on the master
using the field metadata from WL#3228. Each column is checked to ensure
the slave's column is >= to the master's column in size.
sql/rpl_utility.h:
BUG#22086 : Extra Slave Col: Char(5) on slave and Char(10) on master cause mysqld crash
This patch changes the table_def class so that it records the size of
the metadata. This is a result of refactoring out the calc_field_size()
method into the method save_field_metadata(). Prevents access via
field_metadata(col) to unitialized memory when there is no metadata
transmitted from the master.
mysql-test/suite/rpl/r/rpl_row_colSize.result:
BUG#22086 : Extra Slave Col: Char(5) on slave and Char(10) on master cause mysqld crash
New result file for additional test.
mysql-test/suite/rpl/t/rpl_row_colSize.test:
BUG#22086 : Extra Slave Col: Char(5) on slave and Char(10) on master cause mysqld crash
Added a test file to test each variable type that relies on field
metadata from the master.
mysql-test/include/test_fieldsize.inc:
BUG#22086 : Extra Slave Col: Char(5) on slave and Char(10) on master cause mysqld crash
Sub unit file to test each variable type that relies on field
metadata from the master.
Diffstat (limited to 'sql/log_event.cc')
-rw-r--r-- | sql/log_event.cc | 155 |
1 files changed, 29 insertions, 126 deletions
diff --git a/sql/log_event.cc b/sql/log_event.cc index 6f63d8bf718..aa474335d89 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -6383,63 +6383,18 @@ void Rows_log_event::print_helper(FILE *file, **************************************************************************/ /** - * 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 + 2; // 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 + Table_map_log_event::save_field_metadata() which calculates how many values will be in the field metadata. Only those fields that require the - extra data are added (see table above). The master then loops through all - of the fields in the table calling the method - Table_map_log_event::get_field_metadata() which returns the values for the - field that will be saved in the metadata and replicated to the slave. Once - all fields have been processed, the table map is written to the binlog - adding the size of the field metadata and the field metadata to the end of - the body of the table map. - + extra data are added. The method also loops through all of the fields in + the table calling the method Field::save_field_metadata() which returns the + values for the field that will be saved in the metadata and replicated to + the slave. Once all fields have been processed, the table map is written to + the binlog adding the size of the field metadata and the field metadata to + the end of the body of the table map. + When a table map is read on the slave, the field metadata is read from the table map and passed to the table_def class constructor which saves the field metadata from the table map into an array based on the type of the @@ -6478,64 +6433,8 @@ int Table_map_log_event::save_field_metadata() DBUG_ENTER("Table_map_log_event::save_field_metadata"); int index= 0; for (unsigned int i= 0 ; i < m_table->s->fields ; i++) - { - switch (m_table->s->field[i]->real_type()) { - case MYSQL_TYPE_NEWDECIMAL: - { - m_field_metadata[index++]= - (uchar)((Field_new_decimal *)m_table->s->field[i])->precision; - m_field_metadata[index++]= - (uchar)((Field_new_decimal *)m_table->s->field[i])->decimals(); - break; - } - case MYSQL_TYPE_TINY_BLOB: - case MYSQL_TYPE_BLOB: - case MYSQL_TYPE_MEDIUM_BLOB: - case MYSQL_TYPE_LONG_BLOB: - { - m_field_metadata[index++]= - (uchar)((Field_blob *)m_table->s->field[i])->pack_length_no_ptr(); - break; - } - case MYSQL_TYPE_DOUBLE: - case MYSQL_TYPE_FLOAT: - { - m_field_metadata[index++]= (uchar)m_table->s->field[i]->pack_length(); - break; - } - case MYSQL_TYPE_BIT: - { - m_field_metadata[index++]= - (uchar)((Field_bit *)m_table->s->field[i])->bit_len; - m_field_metadata[index++]= - (uchar)((Field_bit *)m_table->s->field[i])->bytes_in_rec; - break; - } - case MYSQL_TYPE_VARCHAR: - { - char *ptr= (char *)&m_field_metadata[index]; - int2store(ptr, m_table->s->field[i]->field_length); - index= index + 2; - break; - } - case MYSQL_TYPE_STRING: - { - m_field_metadata[index++]= (uchar)m_table->s->field[i]->real_type(); - m_field_metadata[index++]= m_table->s->field[i]->field_length; - break; - } - case MYSQL_TYPE_ENUM: - case MYSQL_TYPE_SET: - { - m_field_metadata[index++]= (uchar)m_table->s->field[i]->real_type(); - m_field_metadata[index++]= m_table->s->field[i]->pack_length(); - break; - } - default: - break; - } - } - DBUG_RETURN(0); + index+= m_table->s->field[i]->save_field_metadata(&m_field_metadata[index]); + DBUG_RETURN(index); } #endif /* !defined(MYSQL_CLIENT) */ @@ -6573,16 +6472,6 @@ Table_map_log_event::Table_map_log_event(THD *thd, TABLE *tbl, ulong tid, 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 malloc fails, catched in is_valid() */ if ((m_memory= (uchar*) my_malloc(m_colcnt, MYF(MY_WME)))) @@ -6602,17 +6491,31 @@ Table_map_log_event::Table_map_log_event(THD *thd, TABLE *tbl, ulong tid, m_data_size+= num_null_bytes; m_meta_memory= (uchar *)my_multi_malloc(MYF(MY_WME), &m_null_bits, num_null_bytes, - &m_field_metadata, m_field_metadata_size, + &m_field_metadata, (m_colcnt * 2), NULL); + + bzero(m_field_metadata, (m_colcnt * 2)); + + /* + Create an array for the field metadata and store it. + */ + m_field_metadata_size= save_field_metadata(); + DBUG_ASSERT(m_field_metadata_size <= (m_colcnt * 2)); + + /* + 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; + bzero(m_null_bits, num_null_bytes); 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) */ |