1 /*
2    Copyright (c) 2006, 2010, Oracle and/or its affiliates.
3 
4    This program is free software; you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation; version 2 of the License.
7 
8    This program is distributed in the hope that it will be useful,
9    but WITHOUT ANY WARRANTY; without even the implied warranty of
10    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11    GNU General Public License for more details.
12 
13    You should have received a copy of the GNU General Public License
14    along with this program; if not, write to the Free Software
15    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1335  USA */
16 
17 #ifndef RPL_UTILITY_H
18 #define RPL_UTILITY_H
19 
20 #ifndef __cplusplus
21 #error "Don't include this C++ header file from a non-C++ file!"
22 #endif
23 
24 #include "sql_priv.h"
25 #include "m_string.h"                           /* bzero, memcpy */
26 #ifdef MYSQL_SERVER
27 #include "table.h"                              /* TABLE_LIST */
28 #endif
29 #include "mysql_com.h"
30 
31 class Relay_log_info;
32 class Log_event;
33 struct rpl_group_info;
34 
35 /**
36   A table definition from the master.
37 
38   The responsibilities of this class is:
39   - Extract and decode table definition data from the table map event
40   - Check if table definition in table map is compatible with table
41     definition on slave
42  */
43 
44 class table_def
45 {
46 public:
47   /**
48     Constructor.
49 
50     @param types Array of types, each stored as a byte
51     @param size  Number of elements in array 'types'
52     @param field_metadata Array of extra information about fields
53     @param metadata_size Size of the field_metadata array
54     @param null_bitmap The bitmap of fields that can be null
55    */
56   table_def(unsigned char *types, ulong size, uchar *field_metadata,
57             int metadata_size, uchar *null_bitmap, uint16 flags);
58 
59   ~table_def();
60 
61   /**
62     Return the number of fields there is type data for.
63 
64     @return The number of fields that there is type data for.
65    */
size()66   ulong size() const { return m_size; }
67 
68 
69   /**
70     Returns internal binlog type code for one field,
71     without translation to real types.
72   */
binlog_type(ulong index)73   enum_field_types binlog_type(ulong index) const
74   {
75     return static_cast<enum_field_types>(m_type[index]);
76   }
77   /*
78     Return a representation of the type data for one field.
79 
80     @param index Field index to return data for
81 
82     @return Will return a representation of the type data for field
83     <code>index</code>. Currently, only the type identifier is
84     returned.
85    */
type(ulong index)86   enum_field_types type(ulong index) const
87   {
88     DBUG_ASSERT(index < m_size);
89     /*
90       If the source type is MYSQL_TYPE_STRING, it can in reality be
91       either MYSQL_TYPE_STRING, MYSQL_TYPE_ENUM, or MYSQL_TYPE_SET, so
92       we might need to modify the type to get the real type.
93     */
94     enum_field_types source_type= binlog_type(index);
95     uint16 source_metadata= m_field_metadata[index];
96     switch (source_type)
97     {
98     case MYSQL_TYPE_STRING:
99     {
100       int real_type= source_metadata >> 8;
101       if (real_type == MYSQL_TYPE_ENUM || real_type == MYSQL_TYPE_SET)
102         source_type= static_cast<enum_field_types>(real_type);
103       break;
104     }
105 
106     /*
107       This type has not been used since before row-based replication,
108       so we can safely assume that it really is MYSQL_TYPE_NEWDATE.
109     */
110     case MYSQL_TYPE_DATE:
111       source_type= MYSQL_TYPE_NEWDATE;
112       break;
113 
114     default:
115       /* Do nothing */
116       break;
117     }
118 
119     return source_type;
120   }
121 
122 
123   /*
124     This function allows callers to get the extra field data from the
125     table map for a given field. If there is no metadata for that field
126     or there is no extra metadata at all, the function returns 0.
127 
128     The function returns the value for the field metadata for column at
129     position indicated by index. As mentioned, if the field was a type
130     that stores field metadata, that value is returned else zero (0) is
131     returned. This method is used in the unpack() methods of the
132     corresponding fields to properly extract the data from the binary log
133     in the event that the master's field is smaller than the slave.
134   */
field_metadata(uint index)135   uint16 field_metadata(uint index) const
136   {
137     DBUG_ASSERT(index < m_size);
138     if (m_field_metadata_size)
139       return m_field_metadata[index];
140     else
141       return 0;
142   }
143 
144   /*
145     This function returns whether the field on the master can be null.
146     This value is derived from field->maybe_null().
147   */
maybe_null(uint index)148   my_bool maybe_null(uint index) const
149   {
150     DBUG_ASSERT(index < m_size);
151     return ((m_null_bits[(index / 8)] &
152             (1 << (index % 8))) == (1 << (index %8)));
153   }
154 
155   /*
156     This function returns the field size in raw bytes based on the type
157     and the encoded field data from the master's raw data. This method can
158     be used for situations where the slave needs to skip a column (e.g.,
159     WL#3915) or needs to advance the pointer for the fields in the raw
160     data from the master to a specific column.
161   */
162   uint32 calc_field_size(uint col, uchar *master_data) const;
163 
164   /**
165     Decide if the table definition is compatible with a table.
166 
167     Compare the definition with a table to see if it is compatible
168     with it.
169 
170     A table definition is compatible with a table if:
171       - The columns types of the table definition is a (not
172         necessarily proper) prefix of the column type of the table.
173 
174       - The other way around.
175 
176       - Each column on the master that also exists on the slave can be
177         converted according to the current settings of @c
178         SLAVE_TYPE_CONVERSIONS.
179 
180     @param thd
181     @param rli   Pointer to relay log info
182     @param table Pointer to table to compare with.
183 
184     @param[out] tmp_table_var Pointer to temporary table for holding
185     conversion table.
186 
187     @retval 1  if the table definition is not compatible with @c table
188     @retval 0  if the table definition is compatible with @c table
189   */
190 #ifndef MYSQL_CLIENT
191   bool compatible_with(THD *thd, rpl_group_info *rgi, TABLE *table,
192                       TABLE **conv_table_var) const;
193 
194   /**
195    Create a virtual in-memory temporary table structure.
196 
197    The table structure has records and field array so that a row can
198    be unpacked into the record for further processing.
199 
200    In the virtual table, each field that requires conversion will
201    have a non-NULL value, while fields that do not require
202    conversion will have a NULL value.
203 
204    Some information that is missing in the events, such as the
205    character set for string types, are taken from the table that the
206    field is going to be pushed into, so the target table that the data
207    eventually need to be pushed into need to be supplied.
208 
209    @param thd Thread to allocate memory from.
210    @param rli Relay log info structure, for error reporting.
211    @param target_table Target table for fields.
212 
213    @return A pointer to a temporary table with memory allocated in the
214    thread's memroot, NULL if the table could not be created
215    */
216   TABLE *create_conversion_table(THD *thd, rpl_group_info *rgi,
217                                  TABLE *target_table) const;
218 #endif
219 
220 
221 private:
222   ulong m_size;           // Number of elements in the types array
223   unsigned char *m_type;  // Array of type descriptors
224   uint m_field_metadata_size;
225   uint16 *m_field_metadata;
226   uchar *m_null_bits;
227   uint16 m_flags;         // Table flags
228   uchar *m_memory;
229 };
230 
231 
232 #ifndef MYSQL_CLIENT
233 /**
234    Extend the normal table list with a few new fields needed by the
235    slave thread, but nowhere else.
236  */
237 struct RPL_TABLE_LIST
238   : public TABLE_LIST
239 {
240   bool m_tabledef_valid;
241   table_def m_tabledef;
242   TABLE *m_conv_table;
243   bool master_had_triggers;
244 };
245 
246 
247 /* Anonymous namespace for template functions/classes */
248 CPP_UNNAMED_NS_START
249 
250   /*
251     Smart pointer that will automatically call my_afree (a macro) when
252     the pointer goes out of scope.  This is used so that I do not have
253     to remember to call my_afree() before each return.  There is no
254     overhead associated with this, since all functions are inline.
255 
256     I (Matz) would prefer to use the free function as a template
257     parameter, but that is not possible when the "function" is a
258     macro.
259   */
260   template <class Obj>
261   class auto_afree_ptr
262   {
263     Obj* m_ptr;
264   public:
auto_afree_ptr(Obj * ptr)265     auto_afree_ptr(Obj* ptr) : m_ptr(ptr) { }
~auto_afree_ptr()266     ~auto_afree_ptr() { if (m_ptr) my_afree(m_ptr); }
assign(Obj * ptr)267     void assign(Obj* ptr) {
268       /* Only to be called if it hasn't been given a value before. */
269       DBUG_ASSERT(m_ptr == NULL);
270       m_ptr= ptr;
271     }
get()272     Obj* get() { return m_ptr; }
273   };
274 
275 CPP_UNNAMED_NS_END
276 
277 class Deferred_log_events
278 {
279 private:
280   DYNAMIC_ARRAY array;
281   Log_event *last_added;
282 
283 public:
284   Deferred_log_events(Relay_log_info *rli);
285   ~Deferred_log_events();
286   /* queue for exection at Query-log-event time prior the Query */
287   int add(Log_event *ev);
288   bool is_empty();
289   bool execute(struct rpl_group_info *rgi);
290   void rewind();
is_last(Log_event * ev)291   bool is_last(Log_event *ev) { return ev == last_added; };
292 };
293 
294 #endif
295 
296 // NB. number of printed bit values is limited to sizeof(buf) - 1
297 #define DBUG_PRINT_BITSET(N,FRM,BS)                \
298   do {                                             \
299     char buf[256];                                 \
300     uint i;                                        \
301     for (i = 0 ; i < MY_MIN(sizeof(buf) - 1, (BS)->n_bits) ; i++) \
302       buf[i] = bitmap_is_set((BS), i) ? '1' : '0'; \
303     buf[i] = '\0';                                 \
304     DBUG_PRINT((N), ((FRM), buf));                 \
305   } while (0)
306 
307 #endif /* RPL_UTILITY_H */
308