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-1301 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
31class Relay_log_info;
32class Log_event;
33struct 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
44class table_def
45{
46public:
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 */
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 */
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 */
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 */
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 */
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
221private:
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 */
237struct 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 */
248CPP_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:
265 auto_afree_ptr(Obj* ptr) : m_ptr(ptr) { }
266 ~auto_afree_ptr() { if (m_ptr) my_afree(m_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 }
272 Obj* get() { return m_ptr; }
273 };
274
275CPP_UNNAMED_NS_END
276
277class Deferred_log_events
278{
279private:
280 DYNAMIC_ARRAY array;
281 Log_event *last_added;
282
283public:
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();
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