summaryrefslogtreecommitdiff
path: root/sql/rpl_utility.h
diff options
context:
space:
mode:
authorcbell/Chuck@mysql_cab_desk. <>2007-07-29 18:10:42 -0400
committercbell/Chuck@mysql_cab_desk. <>2007-07-29 18:10:42 -0400
commit537c23e833204511bb1bfa37fb3a97e5ca4c012d (patch)
tree26c861dcc289b76dcb70a1d8206d6ec0405e5b20 /sql/rpl_utility.h
parent8f01f9d02c93f3c90b2e5557eb405b085a903033 (diff)
downloadmariadb-git-537c23e833204511bb1bfa37fb3a97e5ca4c012d.tar.gz
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. WL#3915 : (NDB) master's cols > slave Slave starts accepting and handling rows of master's tables which have more columns. The most important part of implementation is how to caclulate the amount of bytes to skip for unknown by slave column.
Diffstat (limited to 'sql/rpl_utility.h')
-rw-r--r--sql/rpl_utility.h132
1 files changed, 126 insertions, 6 deletions
diff --git a/sql/rpl_utility.h b/sql/rpl_utility.h
index 79e69aecaeb..c91113c9e2a 100644
--- a/sql/rpl_utility.h
+++ b/sql/rpl_utility.h
@@ -25,8 +25,6 @@
struct st_relay_log_info;
typedef st_relay_log_info RELAY_LOG_INFO;
-uint32
-field_length_from_packed(enum_field_types field_type, uchar const *data);
/**
A table definition from the master.
@@ -57,19 +55,96 @@ public:
@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, ulong size)
- : m_size(size), m_type(new unsigned char [size])
+ table_def(field_type *types, ulong size, uchar *field_metadata,
+ int metadata_size, uchar *null_bitmap)
+ : m_size(size), m_type(0),
+ m_field_metadata(0), m_null_bits(0), m_memory(NULL)
{
+ m_memory= (uchar *)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:
+ {
+ short int x= field_metadata[index++];
+ x = x + (field_metadata[index++] << 8U);
+ m_field_metadata[i]= x;
+ break;
+ }
+ case MYSQL_TYPE_VARCHAR:
+ {
+ /*
+ These types store two bytes.
+ */
+ char *ptr= (char *)&field_metadata[index];
+ m_field_metadata[i]= sint2korr(ptr);
+ 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 (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;
@@ -99,6 +174,48 @@ public:
return m_type[index];
}
+
+ /*
+ This function allows callers to get the extra field data from the
+ table map for a given field. If there is no metadata for that field
+ or there is no extra metadata at all, the function returns 0.
+
+ The function returns the value for the field metadata for column at
+ position indicated by index. As mentioned, if the field was a type
+ that stores field metadata, that value is returned else zero (0) is
+ returned. This method is used in the unpack() methods of the
+ corresponding fields to properly extract the data from the binary log
+ in the event that the master's field is smaller than the slave.
+ */
+ 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.
@@ -121,6 +238,9 @@ public:
private:
ulong m_size; // Number of elements in the types array
field_type *m_type; // Array of type descriptors
+ short int *m_field_metadata;
+ uchar *m_null_bits;
+ uchar *m_memory;
};
/**