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