summaryrefslogtreecommitdiffstats
path: root/sql/rpl_utility.h
diff options
context:
space:
mode:
Diffstat (limited to 'sql/rpl_utility.h')
-rw-r--r--sql/rpl_utility.h309
1 files changed, 309 insertions, 0 deletions
diff --git a/sql/rpl_utility.h b/sql/rpl_utility.h
new file mode 100644
index 00000000..c28e8aa1
--- /dev/null
+++ b/sql/rpl_utility.h
@@ -0,0 +1,309 @@
+/*
+ Copyright (c) 2006, 2010, Oracle and/or its affiliates.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */
+
+#ifndef RPL_UTILITY_H
+#define RPL_UTILITY_H
+
+#ifndef __cplusplus
+#error "Don't include this C++ header file from a non-C++ file!"
+#endif
+
+#include "sql_priv.h"
+#include "m_string.h" /* bzero, memcpy */
+#ifdef MYSQL_SERVER
+#include "table.h" /* TABLE_LIST */
+#endif
+#include "mysql_com.h"
+
+class Relay_log_info;
+class Log_event;
+struct rpl_group_info;
+
+/**
+ A table definition from the master.
+
+ The responsibilities of this class is:
+ - 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
+ */
+
+class table_def
+{
+public:
+ /**
+ Constructor.
+
+ @param types Array of types, each stored as a byte
+ @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(unsigned char *types, ulong size, uchar *field_metadata,
+ int metadata_size, uchar *null_bitmap, uint16 flags);
+
+ ~table_def();
+
+ /**
+ Return the number of fields there is type data for.
+
+ @return The number of fields that there is type data for.
+ */
+ ulong size() const { return m_size; }
+
+
+ /**
+ Returns internal binlog type code for one field,
+ without translation to real types.
+ */
+ enum_field_types binlog_type(ulong index) const
+ {
+ return static_cast<enum_field_types>(m_type[index]);
+ }
+ /*
+ Return a representation of the type data for one field.
+
+ @param index Field index to return data for
+
+ @return Will return a representation of the type data for field
+ <code>index</code>. Currently, only the type identifier is
+ returned.
+ */
+ enum_field_types type(ulong index) const
+ {
+ DBUG_ASSERT(index < m_size);
+ /*
+ If the source type is MYSQL_TYPE_STRING, it can in reality be
+ either MYSQL_TYPE_STRING, MYSQL_TYPE_ENUM, or MYSQL_TYPE_SET, so
+ we might need to modify the type to get the real type.
+ */
+ enum_field_types source_type= binlog_type(index);
+ uint16 source_metadata= m_field_metadata[index];
+ switch (source_type)
+ {
+ case MYSQL_TYPE_STRING:
+ {
+ int real_type= source_metadata >> 8;
+ if (real_type == MYSQL_TYPE_ENUM || real_type == MYSQL_TYPE_SET)
+ source_type= static_cast<enum_field_types>(real_type);
+ break;
+ }
+
+ /*
+ This type has not been used since before row-based replication,
+ so we can safely assume that it really is MYSQL_TYPE_NEWDATE.
+ */
+ case MYSQL_TYPE_DATE:
+ source_type= MYSQL_TYPE_NEWDATE;
+ break;
+
+ default:
+ /* Do nothing */
+ break;
+ }
+
+ return source_type;
+ }
+#ifdef MYSQL_SERVER
+ const Type_handler *field_type_handler(uint index) const;
+#endif
+
+ /*
+ 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_size)
+ 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) const;
+
+ /**
+ Decide if the table definition is compatible with a table.
+
+ Compare the definition with a table to see if it is compatible
+ with it.
+
+ A table definition is compatible with a table if:
+ - The columns types of the table definition is a (not
+ necessarily proper) prefix of the column type of the table.
+
+ - The other way around.
+
+ - Each column on the master that also exists on the slave can be
+ converted according to the current settings of @c
+ SLAVE_TYPE_CONVERSIONS.
+
+ @param thd
+ @param rli Pointer to relay log info
+ @param table Pointer to table to compare with.
+
+ @param[out] tmp_table_var Pointer to temporary table for holding
+ conversion table.
+
+ @retval 1 if the table definition is not compatible with @c table
+ @retval 0 if the table definition is compatible with @c table
+ */
+#ifndef MYSQL_CLIENT
+ bool compatible_with(THD *thd, rpl_group_info *rgi, TABLE *table,
+ TABLE **conv_table_var) const;
+
+ /**
+ Create a virtual in-memory temporary table structure.
+
+ The table structure has records and field array so that a row can
+ be unpacked into the record for further processing.
+
+ In the virtual table, each field that requires conversion will
+ have a non-NULL value, while fields that do not require
+ conversion will have a NULL value.
+
+ Some information that is missing in the events, such as the
+ character set for string types, are taken from the table that the
+ field is going to be pushed into, so the target table that the data
+ eventually need to be pushed into need to be supplied.
+
+ @param thd Thread to allocate memory from.
+ @param rli Relay log info structure, for error reporting.
+ @param target_table Target table for fields.
+
+ @return A pointer to a temporary table with memory allocated in the
+ thread's memroot, NULL if the table could not be created
+ */
+ TABLE *create_conversion_table(THD *thd, rpl_group_info *rgi,
+ TABLE *target_table) const;
+#endif
+
+
+private:
+ ulong m_size; // Number of elements in the types array
+ unsigned char *m_type; // Array of type descriptors
+ uint m_field_metadata_size;
+ uint16 *m_field_metadata;
+ uchar *m_null_bits;
+ uint16 m_flags; // Table flags
+ uchar *m_memory;
+};
+
+
+#ifndef MYSQL_CLIENT
+/**
+ Extend the normal table list with a few new fields needed by the
+ slave thread, but nowhere else.
+ */
+struct RPL_TABLE_LIST
+ : public TABLE_LIST
+{
+ bool m_tabledef_valid;
+ table_def m_tabledef;
+ TABLE *m_conv_table;
+ bool master_had_triggers;
+};
+
+
+/* Anonymous namespace for template functions/classes */
+CPP_UNNAMED_NS_START
+
+ /*
+ Smart pointer that will automatically call my_afree (a macro) when
+ the pointer goes out of scope. This is used so that I do not have
+ to remember to call my_afree() before each return. There is no
+ overhead associated with this, since all functions are inline.
+
+ I (Matz) would prefer to use the free function as a template
+ parameter, but that is not possible when the "function" is a
+ macro.
+ */
+ template <class Obj>
+ class auto_afree_ptr
+ {
+ Obj* m_ptr;
+ public:
+ auto_afree_ptr(Obj* ptr) : m_ptr(ptr) { }
+ ~auto_afree_ptr() { if (m_ptr) my_afree(m_ptr); }
+ void assign(Obj* ptr) {
+ /* Only to be called if it hasn't been given a value before. */
+ DBUG_ASSERT(m_ptr == NULL);
+ m_ptr= ptr;
+ }
+ Obj* get() { return m_ptr; }
+ };
+
+CPP_UNNAMED_NS_END
+
+class Deferred_log_events
+{
+private:
+ DYNAMIC_ARRAY array;
+ Log_event *last_added;
+
+public:
+ Deferred_log_events(Relay_log_info *rli);
+ ~Deferred_log_events();
+ /* queue for exection at Query-log-event time prior the Query */
+ int add(Log_event *ev);
+ bool is_empty();
+ bool execute(struct rpl_group_info *rgi);
+ void rewind();
+ bool is_last(Log_event *ev) { return ev == last_added; };
+};
+
+#endif
+
+// NB. number of printed bit values is limited to sizeof(buf) - 1
+#define DBUG_PRINT_BITSET(N,FRM,BS) \
+ do { \
+ char buf[256]; \
+ uint i; \
+ for (i = 0 ; i < MY_MIN(sizeof(buf) - 1, (BS)->n_bits) ; i++) \
+ buf[i] = bitmap_is_set((BS), i) ? '1' : '0'; \
+ buf[i] = '\0'; \
+ DBUG_PRINT((N), ((FRM), buf)); \
+ } while (0)
+
+#endif /* RPL_UTILITY_H */