summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
Diffstat (limited to 'sql')
-rw-r--r--sql/field.cc53
-rw-r--r--sql/field.h8
-rw-r--r--sql/log.cc5
-rw-r--r--sql/log_event.cc10
-rw-r--r--sql/log_event.h10
-rw-r--r--sql/rpl_utility.cc2
-rw-r--r--sql/rpl_utility.h11
7 files changed, 53 insertions, 46 deletions
diff --git a/sql/field.cc b/sql/field.cc
index 354c911e1c0..7c7e334dff1 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -1373,12 +1373,14 @@ bool Field::send_binary(Protocol *protocol)
to the size of this field (the slave or destination).
@param field_metadata Encoded size in field metadata
+ @param mflags Flags from the table map event for the table.
@retval 0 if this field's size is < the source field's size
@retval 1 if this field's size is >= the source field's size
*/
int Field::compatible_field_size(uint field_metadata,
- const Relay_log_info *rli_arg __attribute__((unused)))
+ const Relay_log_info *rli_arg __attribute__((unused)),
+ uint16 mflags __attribute__((unused)))
{
uint const source_size= pack_length_from_metadata(field_metadata);
uint const destination_size= row_pack_length();
@@ -2836,7 +2838,8 @@ uint Field_new_decimal::pack_length_from_metadata(uint field_metadata)
@retval 1 if this field's size is >= the source field's size
*/
int Field_new_decimal::compatible_field_size(uint field_metadata,
- const Relay_log_info * __attribute__((unused)))
+ const Relay_log_info * __attribute__((unused)),
+ uint16 mflags __attribute__((unused)))
{
int compatible= 0;
uint const source_precision= (field_metadata >> 8U) & 0x00ff;
@@ -6612,7 +6615,8 @@ check_field_for_37426(const void *param_arg)
#endif
int Field_string::compatible_field_size(uint field_metadata,
- const Relay_log_info *rli_arg)
+ const Relay_log_info *rli_arg,
+ uint16 mflags __attribute__((unused)))
{
#ifdef HAVE_REPLICATION
const Check_field_param check_param = { this };
@@ -6620,7 +6624,7 @@ int Field_string::compatible_field_size(uint field_metadata,
check_field_for_37426, &check_param))
return FALSE; // Not compatible field sizes
#endif
- return Field::compatible_field_size(field_metadata, rli_arg);
+ return Field::compatible_field_size(field_metadata, rli_arg, mflags);
}
@@ -9172,8 +9176,13 @@ uint Field_bit::get_key_image(uchar *buff, uint length, imagetype type_arg)
*/
int Field_bit::do_save_field_metadata(uchar *metadata_ptr)
{
- *metadata_ptr= bit_len;
- *(metadata_ptr + 1)= bytes_in_rec;
+ /*
+ Since this class and Field_bit_as_char have different ideas of
+ what should be stored here, we compute the values of the metadata
+ explicitly using the field_length.
+ */
+ metadata_ptr[0]= field_length % 8;
+ metadata_ptr[1]= field_length / 8;
return 2;
}
@@ -9213,20 +9222,26 @@ uint Field_bit::pack_length_from_metadata(uint field_metadata)
@retval 1 if this field's size is >= the source field's size
*/
int Field_bit::compatible_field_size(uint field_metadata,
- const Relay_log_info * __attribute__((unused)))
+ const Relay_log_info * __attribute__((unused)),
+ uint16 mflags)
{
- int compatible= 0;
- uint const source_size= pack_length_from_metadata(field_metadata);
- uint const destination_size= row_pack_length();
- uint const from_bit_len= field_metadata & 0x00ff;
- uint const from_len= (field_metadata >> 8U) & 0x00ff;
- if ((bit_len == 0) || (from_bit_len == 0))
- compatible= (source_size <= destination_size);
- else if (from_bit_len > bit_len)
- compatible= (from_len < bytes_in_rec);
- else
- compatible= ((from_bit_len <= bit_len) && (from_len <= bytes_in_rec));
- return (compatible);
+ uint from_bit_len= 8 * (field_metadata >> 8) + (field_metadata & 0xff);
+ uint to_bit_len= max_display_length();
+
+ /*
+ If the bit length exact flag is clear, we are dealing with an old
+ master, so we allow some less strict behaviour if replicating by
+ moving both bit lengths to an even multiple of 8.
+
+ We do this by computing the number of bytes to store the field
+ instead, and then compare the result.
+ */
+ if (!(mflags & Table_map_log_event::TM_BIT_LEN_EXACT_F)) {
+ from_bit_len= (from_bit_len + 7) / 8;
+ to_bit_len= (to_bit_len + 7) / 8;
+ }
+
+ return from_bit_len <= to_bit_len;
}
diff --git a/sql/field.h b/sql/field.h
index 784b9133790..0ed5e6d4cac 100644
--- a/sql/field.h
+++ b/sql/field.h
@@ -165,7 +165,7 @@ public:
*/
virtual uint32 pack_length_in_rec() const { return pack_length(); }
virtual int compatible_field_size(uint field_metadata,
- const Relay_log_info *);
+ const Relay_log_info *, uint16 mflags);
virtual uint pack_length_from_metadata(uint field_metadata)
{ return field_metadata; }
/*
@@ -803,7 +803,7 @@ public:
uint pack_length_from_metadata(uint field_metadata);
uint row_pack_length() { return pack_length(); }
int compatible_field_size(uint field_metadata,
- const Relay_log_info *rli);
+ const Relay_log_info *rli, uint16 mflags);
uint is_equal(Create_field *new_field);
virtual const uchar *unpack(uchar* to, const uchar *from,
uint param_data, bool low_byte_first);
@@ -1498,7 +1498,7 @@ public:
return (((field_metadata >> 4) & 0x300) ^ 0x300) + (field_metadata & 0x00ff);
}
int compatible_field_size(uint field_metadata,
- const Relay_log_info *rli);
+ const Relay_log_info *rli, uint16 mflags);
uint row_pack_length() { return (field_length + 1); }
int pack_cmp(const uchar *a,const uchar *b,uint key_length,
my_bool insert_or_update);
@@ -1962,7 +1962,7 @@ public:
uint row_pack_length()
{ return (bytes_in_rec + ((bit_len > 0) ? 1 : 0)); }
int compatible_field_size(uint field_metadata,
- const Relay_log_info *rli);
+ const Relay_log_info *rli, uint16 mflags);
void sql_type(String &str) const;
virtual uchar *pack(uchar *to, const uchar *from,
uint max_length, bool low_byte_first);
diff --git a/sql/log.cc b/sql/log.cc
index 057f5e8cd7d..457be66b87a 100644
--- a/sql/log.cc
+++ b/sql/log.cc
@@ -3847,11 +3847,8 @@ int THD::binlog_write_table_map(TABLE *table, bool is_trans)
DBUG_ASSERT(current_stmt_binlog_row_based && mysql_bin_log.is_open());
DBUG_ASSERT(table->s->table_map_id != ULONG_MAX);
- Table_map_log_event::flag_set const
- flags= Table_map_log_event::TM_NO_FLAGS;
-
Table_map_log_event
- the_event(this, table, table->s->table_map_id, is_trans, flags);
+ the_event(this, table, table->s->table_map_id, is_trans);
if (is_trans && binlog_table_maps == 0)
binlog_start_trans_and_stmt();
diff --git a/sql/log_event.cc b/sql/log_event.cc
index 2cb253c9c56..b686aabd36b 100644
--- a/sql/log_event.cc
+++ b/sql/log_event.cc
@@ -7837,7 +7837,7 @@ int Table_map_log_event::save_field_metadata()
*/
#if !defined(MYSQL_CLIENT)
Table_map_log_event::Table_map_log_event(THD *thd, TABLE *tbl, ulong tid,
- bool is_transactional, uint16 flags)
+ bool is_transactional)
: Log_event(thd, 0, true),
m_table(tbl),
m_dbnam(tbl->s->db.str),
@@ -7847,7 +7847,7 @@ Table_map_log_event::Table_map_log_event(THD *thd, TABLE *tbl, ulong tid,
m_colcnt(tbl->s->fields),
m_memory(NULL),
m_table_id(tid),
- m_flags(flags),
+ m_flags(TM_BIT_LEN_EXACT_F),
m_data_size(0),
m_field_metadata(0),
m_field_metadata_size(0),
@@ -8105,8 +8105,10 @@ int Table_map_log_event::do_apply_event(Relay_log_info const *rli)
inside 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,
- m_field_metadata, m_field_metadata_size, m_null_bits);
+ new (&table_list->m_tabledef)
+ table_def(m_coltype, m_colcnt,
+ m_field_metadata, m_field_metadata_size,
+ m_null_bits, m_flags);
table_list->m_tabledef_valid= TRUE;
/*
diff --git a/sql/log_event.h b/sql/log_event.h
index 31d4a7480c2..673760557ca 100644
--- a/sql/log_event.h
+++ b/sql/log_event.h
@@ -3283,16 +3283,14 @@ public:
/* Special constants representing sets of flags */
enum
{
- TM_NO_FLAGS = 0U
+ TM_NO_FLAGS = 0U,
+ TM_BIT_LEN_EXACT_F = (1U << 0)
};
- void set_flags(flag_set flag) { m_flags |= flag; }
- void clear_flags(flag_set flag) { m_flags &= ~flag; }
flag_set get_flags(flag_set flag) const { return m_flags & flag; }
#ifndef MYSQL_CLIENT
- Table_map_log_event(THD *thd, TABLE *tbl, ulong tid,
- bool is_transactional, uint16 flags);
+ Table_map_log_event(THD *thd, TABLE *tbl, ulong tid, bool is_transactional);
#endif
#ifdef HAVE_REPLICATION
Table_map_log_event(const char *buf, uint event_len,
@@ -3305,7 +3303,7 @@ public:
table_def *create_table_def()
{
return new table_def(m_coltype, m_colcnt, m_field_metadata,
- m_field_metadata_size, m_null_bits);
+ m_field_metadata_size, m_null_bits, m_flags);
}
ulong get_table_id() const { return m_table_id; }
const char *get_table_name() const { return m_tblnam; }
diff --git a/sql/rpl_utility.cc b/sql/rpl_utility.cc
index e34f8561051..6058c473e9f 100644
--- a/sql/rpl_utility.cc
+++ b/sql/rpl_utility.cc
@@ -206,7 +206,7 @@ table_def::compatible_with(Relay_log_info const *rli_arg, TABLE *table)
Check the slave's field size against that of the master.
*/
if (!error &&
- !field->compatible_field_size(field_metadata(col), rli_arg))
+ !field->compatible_field_size(field_metadata(col), rli_arg, m_flags))
{
error= 1;
char buf[256];
diff --git a/sql/rpl_utility.h b/sql/rpl_utility.h
index 1f4ca246ff1..9f4a4c9454b 100644
--- a/sql/rpl_utility.h
+++ b/sql/rpl_utility.h
@@ -32,12 +32,6 @@ class Relay_log_info;
- Extract and decode table definition data from the table map event
- Check if table definition in table map is compatible with table
definition on slave
-
- Currently, the only field type data available is an array of the
- type operators that are present in the table map event.
-
- @todo Add type operands to this structure to allow detection of
- difference between, e.g., BIT(5) and BIT(10).
*/
class table_def
@@ -59,9 +53,9 @@ public:
@param null_bitmap The bitmap of fields that can be null
*/
table_def(field_type *types, ulong size, uchar *field_metadata,
- int metadata_size, uchar *null_bitmap)
+ int metadata_size, uchar *null_bitmap, uint16 flags)
: m_size(size), m_type(0), m_field_metadata_size(metadata_size),
- m_field_metadata(0), m_null_bits(0), m_memory(NULL)
+ m_field_metadata(0), m_null_bits(0), m_flags(flags), m_memory(NULL)
{
m_memory= (uchar *)my_multi_malloc(MYF(MY_WME),
&m_type, size,
@@ -246,6 +240,7 @@ private:
uint m_field_metadata_size;
uint16 *m_field_metadata;
uchar *m_null_bits;
+ uint16 m_flags; // Table flags
uchar *m_memory;
};